Skip to content

Commit 384d869

Browse files
committed
Fix bipartite update
1 parent 875c6bb commit 384d869

File tree

2 files changed

+4
-127
lines changed

2 files changed

+4
-127
lines changed

src/bipartite_graph.jl

Lines changed: 0 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -516,117 +516,4 @@ 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-
"""
520-
struct ResidualCMOGraph
521-
522-
For a bipartite graph and matching on the graph's destination vertices, this
523-
wrapper exposes the induced graph on the destination vertices formed by those
524-
destination and source vertices that are left unmatched. In particular, two
525-
(destination) vertices a and b are neighbors if they are both unassigned and
526-
there is some unassigned source vertex `s` such that `s` is a neighbor (in the
527-
bipartite graph) of both `a` and `b`.
528-
529-
# Hypergraph interpreation
530-
531-
Refer to the hypergraph interpretation of the DiCMOBiGraph. Now consider the
532-
hypergraph left over after removing all edges that are oriented by the mapping.
533-
This graph is the undirected graph obtained by replacing all hyper edges by the
534-
maximal undirected graph on the vertices that are members of the original hyper
535-
edge.
536-
537-
# Nota Bene
538-
539-
1. For technical reasons, the `vertices` function includes even those vertices
540-
vertices that are assigned in the original hypergraph, even though they
541-
are conceptually not part of the graph.
542-
2. This graph is not strict. In particular, multi edges between vertices are
543-
allowed and common.
544-
"""
545-
struct ResidualCMOGraph{I, G<:BipartiteGraph{I}, M <: Matching} <: Graphs.AbstractGraph{I}
546-
graph::G
547-
matching::M
548-
function ResidualCMOGraph{I, G, M}(g::G, m::M) where {I, G<:BipartiteGraph{I}, M}
549-
require_complete(g)
550-
require_complete(m)
551-
new{I, G, M}(g, m)
552-
end
553-
end
554-
ResidualCMOGraph(g::G, m::M) where {I, G<:BipartiteGraph{I}, M} = ResidualCMOGraph{I, G, M}(g, m)
555-
556-
invview(rcg::ResidualCMOGraph) = ResidualCMOGraph(invview(rcg.graph), invview(rcg.matching))
557-
558-
Graphs.is_directed(::Type{<:ResidualCMOGraph}) = false
559-
Graphs.nv(rcg::ResidualCMOGraph) = ndsts(rcg.graph)
560-
Graphs.vertices(rcg::ResidualCMOGraph) = 𝑑vertices(rcg.graph)
561-
function Graphs.neighbors(rcg::ResidualCMOGraph, v::Integer)
562-
rcg.matching[v] !== unassigned && return ()
563-
Iterators.filter(
564-
vdst->rcg.matching[vdst] === unassigned,
565-
Iterators.flatten(rcg.graph.fadjlist[vsrc] for
566-
vsrc in rcg.graph.badjlist[v] if
567-
invview(rcg.matching)[vsrc] === unassigned))
568-
end
569-
570-
# TODO: Fix the function in Graphs to do this instead
571-
function Graphs.neighborhood(rcg::ResidualCMOGraph, v::Integer)
572-
worklist = Int[v]
573-
ns = BitSet()
574-
while !isempty(worklist)
575-
v′ = popfirst!(worklist)
576-
for n in neighbors(rcg, v′)
577-
if !(n in ns)
578-
push!(ns, n)
579-
push!(worklist, n)
580-
end
581-
end
582-
end
583-
return ns
584-
end
585-
586-
"""
587-
struct InducedCondensationGraph
588-
589-
For some bipartite-graph and an orientation induced on its destination contraction,
590-
records the condensation DAG of the digraph formed by the orientation. I.e. this
591-
is a DAG of connected components formed by the destination vertices of some
592-
underlying bipartite graph.
593-
594-
N.B.: This graph does not store explicit neighbor relations of the sccs.
595-
Therefor, the edge multiplicity is derived from the underlying bipartite graph,
596-
i.e. this graph is not strict.
597-
"""
598-
struct InducedCondensationGraph{G <: BipartiteGraph} <: AbstractGraph{Vector{Union{Int, Vector{Int}}}}
599-
graph::G
600-
# Records the members of a strongly connected component. For efficiency,
601-
# trivial sccs (with one vertex member) are stored inline. Note: the sccs
602-
# here are stored in topological order.
603-
sccs::Vector{Union{Int, Vector{Int}}}
604-
# Maps the vertices back to the scc of which they are a part
605-
scc_assignment::Vector{Int}
606-
end
607-
608-
function InducedCondensationGraph(g::BipartiteGraph, sccs::Vector{Union{Int, Vector{Int}}})
609-
scc_assignment = Vector{Int}(undef, ndsts(g))
610-
for (i, c) in enumerate(sccs)
611-
for v in c
612-
scc_assignment[v] = i
613-
end
614-
end
615-
InducedCondensationGraph(g, sccs, scc_assignment)
616-
end
617-
618-
Graphs.is_directed(::Type{<:InducedCondensationGraph}) = true
619-
Graphs.nv(icg::InducedCondensationGraph) = length(icg.sccs)
620-
Graphs.vertices(icg::InducedCondensationGraph) = icg.sccs
621-
622-
_neighbors(icg::InducedCondensationGraph, cc::Integer) =
623-
Iterators.flatten(Iterators.flatten(rcg.graph.fadjlist[vsrc] for vsrc in rcg.graph.badjlist[v]) for v in icg.sccs[cc])
624-
625-
Graphs.outneighbors(rcg::InducedCondensationGraph, v::Integer) =
626-
(scc_assignment[n] for n in _neighbors(rcg, v) if scc_assignment[n] > v)
627-
628-
Graphs.inneighbors(rcg::InducedCondensationGraph, v::Integer) =
629-
(scc_assignment[n] for n in _neighbors(rcg, v) if scc_assignment[n] < v)
630-
631-
632519
end # module

src/structural_transformation/tearing.jl

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,11 @@ function contract_variables(graph::BipartiteGraph, var_eq_matching::Matching, el
3131
masked_cumsum!(var_rename)
3232
masked_cumsum!(eq_rename)
3333

34-
rg = ResidualCMOGraph(graph, var_eq_matching)
34+
dig = DiCMOBiGraph{true}(graph, var_eq_matching)
3535

3636
# Update bipartite graph
37-
var_deps = Union{Vector{Int}, Nothing}[nothing for v in eliminated_variables]
38-
var_idxs = Dict(v => i for (i,v) in enumerate(eliminated_variables))
39-
for (i, v) in enumerate(eliminated_variables)
40-
isa(var_deps[i], Vector{Int}) && continue
41-
var_deps[i] = deps = Vector{Int}()
42-
for v′ in neighborhood(rg, v)
43-
if var_rename[v′] != 0
44-
push!(deps, var_rename[v′])
45-
else
46-
var_deps[var_idxs[v′]] = deps
47-
end
48-
end
37+
var_deps = map(1:ndsts(graph)) do v
38+
[var_rename[v′] for v′ in neighborhood(dig, v, Inf; dir=:in) if var_rename[v′] != 0]
4939
end
5040

5141
new_fadjlist = Vector{Int}[
@@ -54,7 +44,7 @@ function contract_variables(graph::BipartiteGraph, var_eq_matching::Matching, el
5444
if var_rename[v] != 0
5545
push!(new_list, var_rename[v])
5646
else
57-
append!(new_list, var_deps[var_idxs[v]])
47+
append!(new_list, var_deps[v])
5848
end
5949
end
6050
new_list

0 commit comments

Comments
 (0)