Skip to content

Commit 70f3d0c

Browse files
authored
Merge pull request #809 from SciML/myb/alias
WIP: Alias elimination with singularity removal
2 parents 4606369 + 9cdfdd9 commit 70f3d0c

File tree

8 files changed

+699
-355
lines changed

8 files changed

+699
-355
lines changed

src/ModelingToolkit.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ include("systems/dependency_graphs.jl")
248248
include("systems/systemstructure.jl")
249249
using .SystemStructures
250250

251-
include("systems/reduction.jl")
251+
include("systems/alias_elimination.jl")
252252

253253
include("latexify_recipes.jl")
254254
include("build_function.jl")
@@ -266,6 +266,7 @@ export SteadyStateProblem, SteadyStateProblemExpr
266266
export JumpProblem, DiscreteProblem
267267
export NonlinearSystem, OptimizationSystem
268268
export ControlSystem
269+
export alias_elimination, flatten
269270
export ode_order_lowering, liouville_transform
270271
export runge_kutta_discretize
271272
export PDESystem

src/bipartite_graph.jl

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,13 @@ badjlist = [[1,2,5,6],[3,4,6]]
6666
bg = BipartiteGraph(7, fadjlist, badjlist)
6767
```
6868
"""
69-
mutable struct BipartiteGraph{I<:Integer} <: LightGraphs.AbstractGraph{I}
69+
mutable struct BipartiteGraph{I<:Integer,M} <: LightGraphs.AbstractGraph{I}
7070
ne::Int
7171
fadjlist::Vector{Vector{I}} # `fadjlist[src] => dsts`
7272
badjlist::Vector{Vector{I}} # `badjlist[dst] => srcs`
73+
metadata::M
7374
end
75+
BipartiteGraph(ne::Integer, fadj::AbstractVector, badj::AbstractVector) = BipartiteGraph(ne, fadj, badj, nothing)
7476

7577
"""
7678
```julia
@@ -91,10 +93,22 @@ $(SIGNATURES)
9193
9294
Build an empty `BipartiteGraph` with `nsrcs` sources and `ndsts` destinations.
9395
"""
94-
BipartiteGraph(nsrcs::T, ndsts::T) where T = BipartiteGraph(0, map(_->T[], 1:nsrcs), map(_->T[], 1:ndsts))
96+
function BipartiteGraph(nsrcs::T, ndsts::T; metadata=nothing) where T
97+
fadjlist = map(_->T[], 1:nsrcs)
98+
badjlist = map(_->T[], 1:ndsts)
99+
BipartiteGraph(0, fadjlist, badjlist, metadata)
100+
end
95101

96-
Base.eltype(::Type{BipartiteGraph{I}}) where I = I
97-
Base.empty!(g::BipartiteGraph) = (foreach(empty!, g.fadjlist); foreach(empty!, g.badjlist); g.ne = 0; g)
102+
Base.eltype(::Type{<:BipartiteGraph{I}}) where I = I
103+
function Base.empty!(g::BipartiteGraph)
104+
foreach(empty!, g.fadjlist)
105+
foreach(empty!, g.badjlist)
106+
g.ne = 0
107+
if g.metadata !== nothing
108+
foreach(empty!, g.metadata)
109+
end
110+
g
111+
end
98112
Base.length(::BipartiteGraph) = error("length is not well defined! Use `ne` or `nv`.")
99113

100114
if isdefined(LightGraphs, :has_contiguous_vertices)
@@ -106,8 +120,8 @@ LightGraphs.vertices(g::BipartiteGraph) = (𝑠vertices(g), 𝑑vertices(g))
106120
𝑑vertices(g::BipartiteGraph) = axes(g.badjlist, 1)
107121
has_𝑠vertex(g::BipartiteGraph, v::Integer) = v in 𝑠vertices(g)
108122
has_𝑑vertex(g::BipartiteGraph, v::Integer) = v in 𝑑vertices(g)
109-
𝑠neighbors(g::BipartiteGraph, i::Integer) = g.fadjlist[i]
110-
𝑑neighbors(g::BipartiteGraph, i::Integer) = g.badjlist[i]
123+
𝑠neighbors(g::BipartiteGraph, i::Integer, with_metadata::Val{M}=Val(false)) where M = M ? zip(g.fadjlist[i], g.metadata[i]) : g.fadjlist[i]
124+
𝑑neighbors(g::BipartiteGraph, j::Integer, with_metadata::Val{M}=Val(false)) where M = M ? zip(g.badjlist[j], (g.metadata[i][j] for i in g.badjlist[j])) : g.badjlist[j]
111125
LightGraphs.ne(g::BipartiteGraph) = g.ne
112126
LightGraphs.nv(g::BipartiteGraph) = sum(length, vertices(g))
113127
LightGraphs.edgetype(g::BipartiteGraph{I}) where I = BipartiteEdge{I}
@@ -124,8 +138,12 @@ end
124138
###
125139
### Populate
126140
###
127-
LightGraphs.add_edge!(g::BipartiteGraph, i::Integer, j::Integer) = add_edge!(g, BipartiteEdge(i, j))
128-
function LightGraphs.add_edge!(g::BipartiteGraph, edge::BipartiteEdge)
141+
struct NoMetadata
142+
end
143+
const NO_METADATA = NoMetadata()
144+
145+
LightGraphs.add_edge!(g::BipartiteGraph, i::Integer, j::Integer, md=NO_METADATA) = add_edge!(g, BipartiteEdge(i, j), md)
146+
function LightGraphs.add_edge!(g::BipartiteGraph, edge::BipartiteEdge, md=NO_METADATA)
129147
@unpack fadjlist, badjlist = g
130148
verts = vertices(g)
131149
s, d = src(edge), dst(edge)
@@ -134,6 +152,9 @@ function LightGraphs.add_edge!(g::BipartiteGraph, edge::BipartiteEdge)
134152
index = searchsortedfirst(list, d)
135153
@inbounds (index <= length(list) && list[index] == d) && return false # edge already in graph
136154
insert!(list, index, d)
155+
if md !== NO_METADATA
156+
insert!(g.metadata[s], index, md)
157+
end
137158

138159
g.ne += 1
139160
@inbounds list = badjlist[d]
@@ -170,7 +191,7 @@ Base.length(it::BipartiteEdgeIter{ALL}) = 2ne(it.g)
170191

171192
Base.eltype(it::BipartiteEdgeIter) = edgetype(it.g)
172193

173-
function Base.iterate(it::BipartiteEdgeIter{SRC,BipartiteGraph{T}}, state=(1, 1, SRC)) where T
194+
function Base.iterate(it::BipartiteEdgeIter{SRC,<:BipartiteGraph{T}}, state=(1, 1, SRC)) where T
174195
@unpack g = it
175196
neqs = nsrcs(g)
176197
neqs == 0 && return nothing
@@ -191,7 +212,7 @@ function Base.iterate(it::BipartiteEdgeIter{SRC,BipartiteGraph{T}}, state=(1, 1,
191212
return nothing
192213
end
193214

194-
function Base.iterate(it::BipartiteEdgeIter{DST,BipartiteGraph{T}}, state=(1, 1, DST)) where T
215+
function Base.iterate(it::BipartiteEdgeIter{DST,<:BipartiteGraph{T}}, state=(1, 1, DST)) where T
195216
@unpack g = it
196217
nvars = ndsts(g)
197218
nvars == 0 && return nothing

0 commit comments

Comments
 (0)