Skip to content

Commit 99acf1e

Browse files
committed
Topologically sort sccs before attempting codegen
1 parent 8ed38eb commit 99acf1e

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-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,
@@ -535,4 +535,80 @@ end
535535
Graphs.has_edge(g::DiCMOBiGraph{true}, a, b) = a in inneighbors(g, b)
536536
Graphs.has_edge(g::DiCMOBiGraph{false}, a, b) = b in outneighbors(g, a)
537537

538+
# Condensation Graphs
539+
abstract type AbstractCondensationGraph <: AbstractGraph{Int}; end
540+
function (T::Type{<:AbstractCondensationGraph})(g, sccs::Vector{Union{Int, Vector{Int}}})
541+
scc_assignment = Vector{Int}(undef, isa(g, BipartiteGraph) ? ndsts(g) : nv(g))
542+
for (i, c) in enumerate(sccs)
543+
for v in c
544+
scc_assignment[v] = i
545+
end
546+
end
547+
T(g, sccs, scc_assignment)
548+
end
549+
(T::Type{<:AbstractCondensationGraph})(g, sccs::Vector{Vector{Int}}) =
550+
T(g, Vector{Union{Int, Vector{Int}}}(sccs))
551+
552+
Graphs.is_directed(::Type{<:AbstractCondensationGraph}) = true
553+
Graphs.nv(icg::AbstractCondensationGraph) = length(icg.sccs)
554+
Graphs.vertices(icg::AbstractCondensationGraph) = Base.OneTo(nv(icg))
555+
556+
"""
557+
struct MatchedCondensationGraph
558+
559+
For some bipartite-graph and an orientation induced on its destination contraction,
560+
records the condensation DAG of the digraph formed by the orientation. I.e. this
561+
is a DAG of connected components formed by the destination vertices of some
562+
underlying bipartite graph.
563+
N.B.: This graph does not store explicit neighbor relations of the sccs.
564+
Therefor, the edge multiplicity is derived from the underlying bipartite graph,
565+
i.e. this graph is not strict.
566+
"""
567+
struct MatchedCondensationGraph{G <: DiCMOBiGraph} <: AbstractCondensationGraph
568+
graph::G
569+
# Records the members of a strongly connected component. For efficiency,
570+
# trivial sccs (with one vertex member) are stored inline. Note: the sccs
571+
# here need not be stored in topological order.
572+
sccs::Vector{Union{Int, Vector{Int}}}
573+
# Maps the vertices back to the scc of which they are a part
574+
scc_assignment::Vector{Int}
575+
end
576+
577+
578+
Graphs.outneighbors(mcg::MatchedCondensationGraph, cc::Integer) =
579+
Iterators.flatten((mcg.scc_assignment[v′] for v′ in outneighbors(mcg.graph, v)) for v in mcg.sccs[cc])
580+
581+
Graphs.inneighbors(mcg::MatchedCondensationGraph, cc::Integer) =
582+
Iterators.flatten((mcg.scc_assignment[v′] for v′ in inneighbors(mcg.graph, v)) for v in mcg.sccs[cc])
583+
584+
"""
585+
struct InducedCondensationGraph
586+
587+
For some bipartite-graph and a topologicall sorted list of connected components,
588+
represents the condensation DAG of the digraph formed by the orientation. I.e. this
589+
is a DAG of connected components formed by the destination vertices of some
590+
underlying bipartite graph.
591+
N.B.: This graph does not store explicit neighbor relations of the sccs.
592+
Therefor, the edge multiplicity is derived from the underlying bipartite graph,
593+
i.e. this graph is not strict.
594+
"""
595+
struct InducedCondensationGraph{G <: BipartiteGraph} <: AbstractCondensationGraph
596+
graph::G
597+
# Records the members of a strongly connected component. For efficiency,
598+
# trivial sccs (with one vertex member) are stored inline. Note: the sccs
599+
# here are stored in topological order.
600+
sccs::Vector{Union{Int, Vector{Int}}}
601+
# Maps the vertices back to the scc of which they are a part
602+
scc_assignment::Vector{Int}
603+
end
604+
605+
_neighbors(icg::InducedCondensationGraph, cc::Integer) =
606+
Iterators.flatten(Iterators.flatten(icg.graph.fadjlist[vsrc] for vsrc in icg.graph.badjlist[v]) for v in icg.sccs[cc])
607+
608+
Graphs.outneighbors(icg::InducedCondensationGraph, v::Integer) =
609+
(icg.scc_assignment[n] for n in _neighbors(icg, v) if icg.scc_assignment[n] > v)
610+
611+
Graphs.inneighbors(icg::InducedCondensationGraph, v::Integer) =
612+
(icg.scc_assignment[n] for n in _neighbors(icg, v) if icg.scc_assignment[n] < v)
613+
538614
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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ function build_torn_function(
174174
state = TearingState(sys)
175175
fullvars = state.fullvars
176176
var_eq_matching, var_sccs = algebraic_variables_scc(state)
177+
toporder = reverse(topological_sort_by_dfs(MatchedCondensationGraph(
178+
DiCMOBiGraph{true}(complete(state.structure.graph), complete(var_eq_matching)), var_sccs)))
179+
var_sccs = var_sccs[toporder]
177180

178181
states = map(i->fullvars[i], diffvars_range(state.structure))
179182
mass_matrix_diag = ones(length(states))

0 commit comments

Comments
 (0)