Skip to content

Commit 21edfca

Browse files
KenoYingboMa
authored andcommitted
Topologically sort sccs before attempting codegen
1 parent 89dcbdd commit 21edfca

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

src/bipartite_graph.jl

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module BipartiteGraphs
22

33
export BipartiteEdge, BipartiteGraph, DiCMOBiGraph, Unassigned, unassigned,
44
Matching, ResidualCMOGraph, InducedCondensationGraph, maximal_matching,
5-
construct_augmenting_path!
5+
construct_augmenting_path!, MatchedCondensationGraph
66

77
export 𝑠vertices, 𝑑vertices, has_𝑠vertex, has_𝑑vertex, 𝑠neighbors, 𝑑neighbors,
88
𝑠edges, 𝑑edges, nsrcs, ndsts, SRC, DST, set_neighbors!, invview,
@@ -516,4 +516,80 @@ end
516516
Graphs.has_edge(g::DiCMOBiGraph{true}, a, b) = a in inneighbors(g, b)
517517
Graphs.has_edge(g::DiCMOBiGraph{false}, a, b) = b in outneighbors(g, a)
518518

519+
# Condensation Graphs
520+
abstract type AbstractCondensationGraph <: AbstractGraph{Int}; end
521+
function (T::Type{<:AbstractCondensationGraph})(g, sccs::Vector{Union{Int, Vector{Int}}})
522+
scc_assignment = Vector{Int}(undef, isa(g, BipartiteGraph) ? ndsts(g) : nv(g))
523+
for (i, c) in enumerate(sccs)
524+
for v in c
525+
scc_assignment[v] = i
526+
end
527+
end
528+
T(g, sccs, scc_assignment)
529+
end
530+
(T::Type{<:AbstractCondensationGraph})(g, sccs::Vector{Vector{Int}}) =
531+
T(g, Vector{Union{Int, Vector{Int}}}(sccs))
532+
533+
Graphs.is_directed(::Type{<:AbstractCondensationGraph}) = true
534+
Graphs.nv(icg::AbstractCondensationGraph) = length(icg.sccs)
535+
Graphs.vertices(icg::AbstractCondensationGraph) = Base.OneTo(nv(icg))
536+
537+
"""
538+
struct MatchedCondensationGraph
539+
540+
For some bipartite-graph and an orientation induced on its destination contraction,
541+
records the condensation DAG of the digraph formed by the orientation. I.e. this
542+
is a DAG of connected components formed by the destination vertices of some
543+
underlying bipartite graph.
544+
N.B.: This graph does not store explicit neighbor relations of the sccs.
545+
Therefor, the edge multiplicity is derived from the underlying bipartite graph,
546+
i.e. this graph is not strict.
547+
"""
548+
struct MatchedCondensationGraph{G <: DiCMOBiGraph} <: AbstractCondensationGraph
549+
graph::G
550+
# Records the members of a strongly connected component. For efficiency,
551+
# trivial sccs (with one vertex member) are stored inline. Note: the sccs
552+
# here need not be stored in topological order.
553+
sccs::Vector{Union{Int, Vector{Int}}}
554+
# Maps the vertices back to the scc of which they are a part
555+
scc_assignment::Vector{Int}
556+
end
557+
558+
559+
Graphs.outneighbors(mcg::MatchedCondensationGraph, cc::Integer) =
560+
Iterators.flatten((mcg.scc_assignment[v′] for v′ in outneighbors(mcg.graph, v)) for v in mcg.sccs[cc])
561+
562+
Graphs.inneighbors(mcg::MatchedCondensationGraph, cc::Integer) =
563+
Iterators.flatten((mcg.scc_assignment[v′] for v′ in inneighbors(mcg.graph, v)) for v in mcg.sccs[cc])
564+
565+
"""
566+
struct InducedCondensationGraph
567+
568+
For some bipartite-graph and a topologicall sorted list of connected components,
569+
represents the condensation DAG of the digraph formed by the orientation. I.e. this
570+
is a DAG of connected components formed by the destination vertices of some
571+
underlying bipartite graph.
572+
N.B.: This graph does not store explicit neighbor relations of the sccs.
573+
Therefor, the edge multiplicity is derived from the underlying bipartite graph,
574+
i.e. this graph is not strict.
575+
"""
576+
struct InducedCondensationGraph{G <: BipartiteGraph} <: AbstractCondensationGraph
577+
graph::G
578+
# Records the members of a strongly connected component. For efficiency,
579+
# trivial sccs (with one vertex member) are stored inline. Note: the sccs
580+
# here are stored in topological order.
581+
sccs::Vector{Union{Int, Vector{Int}}}
582+
# Maps the vertices back to the scc of which they are a part
583+
scc_assignment::Vector{Int}
584+
end
585+
586+
_neighbors(icg::InducedCondensationGraph, cc::Integer) =
587+
Iterators.flatten(Iterators.flatten(icg.graph.fadjlist[vsrc] for vsrc in icg.graph.badjlist[v]) for v in icg.sccs[cc])
588+
589+
Graphs.outneighbors(icg::InducedCondensationGraph, v::Integer) =
590+
(icg.scc_assignment[n] for n in _neighbors(icg, v) if icg.scc_assignment[n] > v)
591+
592+
Graphs.inneighbors(icg::InducedCondensationGraph, v::Integer) =
593+
(icg.scc_assignment[n] for n in _neighbors(icg, v) if icg.scc_assignment[n] < v)
594+
519595
end # module

src/compat/incremental_cycles.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Base.Iterators: repeated
2+
import Graphs.Experimental.Traversals: topological_sort
23

34
# Abstract Interface
45

src/structural_transformation/codegen.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ function build_torn_function(
175175
s = structure(sys)
176176
@unpack fullvars = s
177177
var_eq_matching, var_sccs = algebraic_variables_scc(sys)
178+
condensed_graph = MatchedCondensationGraph(
179+
DiCMOBiGraph{true}(complete(s.graph), complete(var_eq_matching)), var_sccs)
180+
toporder = topological_sort_by_dfs(condensed_graph)
181+
var_sccs = var_sccs[toporder]
178182

179183
states = map(i->s.fullvars[i], diffvars_range(s))
180184
mass_matrix_diag = ones(length(states))

0 commit comments

Comments
 (0)