Skip to content

Commit 3f2cc90

Browse files
authored
Merge branch 'master' into func-affect
2 parents 8e7ef41 + 942a24d commit 3f2cc90

22 files changed

+444
-473
lines changed

Project.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
3030
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
3131
RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd"
3232
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
33-
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
3433
RuntimeGeneratedFunctions = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47"
3534
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
3635
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
@@ -66,7 +65,6 @@ NaNMath = "0.3, 1"
6665
NonlinearSolve = "0.3.8"
6766
RecursiveArrayTools = "2.3"
6867
Reexport = "0.2, 1"
69-
Requires = "1.0"
7068
RuntimeGeneratedFunctions = "0.4.3, 0.5"
7169
SciMLBase = "1.26.2"
7270
Setfield = "0.7, 0.8, 1"
@@ -79,9 +77,13 @@ Unitful = "1.1"
7977
julia = "1.6"
8078

8179
[extras]
80+
AmplNLWriter = "7c4d4715-977e-5154-bfe0-e096adeac482"
8281
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
8382
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
83+
Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9"
84+
Ipopt_jll = "9cc047cb-c261-5740-88fc-0cf96f7bdcc7"
8485
Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba"
86+
OptimizationMOI = "fd9f6733-72f4-499f-8506-86b2bdd0dea1"
8587
OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e"
8688
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
8789
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
@@ -93,4 +95,4 @@ Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4"
9395
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
9496

9597
[targets]
96-
test = ["BenchmarkTools", "ForwardDiff", "Optimization", "OptimizationOptimJL", "OrdinaryDiffEq", "Random", "ReferenceTests", "SafeTestsets", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials"]
98+
test = ["AmplNLWriter", "BenchmarkTools", "ForwardDiff", "Ipopt", "Ipopt_jll", "Optimization", "OptimizationOptimJL", "OptimizationMOI", "OrdinaryDiffEq", "Random", "ReferenceTests", "SafeTestsets", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials"]

docs/pages.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ pages = [
88
"tutorials/nonlinear.md",
99
"tutorials/optimization.md",
1010
"tutorials/stochastic_diffeq.md",
11-
"tutorials/nonlinear_optimal_control.md",
1211
"tutorials/parameter_identifiability.md"],
1312
"ModelingToolkitize Tutorials" => Any["mtkitize_tutorials/modelingtoolkitize.md",
1413
"mtkitize_tutorials/modelingtoolkitize_index_reduction.md",
@@ -25,7 +24,6 @@ pages = [
2524
"systems/JumpSystem.md",
2625
"systems/NonlinearSystem.md",
2726
"systems/OptimizationSystem.md",
28-
"systems/ControlSystem.md",
2927
"systems/PDESystem.md"],
3028
"comparison.md",
3129
"internals.md",

docs/src/systems/ControlSystem.md

Lines changed: 0 additions & 23 deletions
This file was deleted.

docs/src/tutorials/nonlinear_optimal_control.md

Lines changed: 0 additions & 95 deletions
This file was deleted.

src/ModelingToolkit.jl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ import DiffEqBase: @add_kwonly
6060

6161
import Graphs: SimpleDiGraph, add_edge!, incidence_matrix
6262

63-
using Requires
64-
6563
for fun in [:toexpr]
6664
@eval begin
6765
function $fun(eq::Equation; kw...)
@@ -137,8 +135,6 @@ include("systems/nonlinear/modelingtoolkitize.jl")
137135

138136
include("systems/optimization/optimizationsystem.jl")
139137

140-
include("systems/control/controlsystem.jl")
141-
142138
include("systems/pde/pdesystem.jl")
143139

144140
include("systems/sparsematrixclil.jl")
@@ -173,13 +169,11 @@ export AutoModelingToolkit
173169
export SteadyStateProblem, SteadyStateProblemExpr
174170
export JumpProblem, DiscreteProblem
175171
export NonlinearSystem, OptimizationSystem
176-
export ControlSystem
177172
export alias_elimination, flatten
178173
export connect, @connector, Connection, Flow, Stream, instream
179174
export isinput, isoutput, getbounds, hasbounds, isdisturbance, istunable, getdist, hasdist,
180175
tunable_parameters, isirreducible
181176
export ode_order_lowering, dae_order_lowering, liouville_transform
182-
export runge_kutta_discretize
183177
export PDESystem
184178
export Differential, expand_derivatives, @derivatives
185179
export Equation, ConstrainedEquation

src/bipartite_graph.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,53 @@ function complete(g::BipartiteGraph{I}) where {I}
184184
BipartiteGraph(g.ne, g.fadjlist, badjlist)
185185
end
186186

187+
# Matrix whose only purpose is to pretty-print the bipartite graph
188+
struct BipartiteAdjacencyList
189+
u::Union{Vector{Int}, Nothing}
190+
end
191+
function Base.show(io::IO, l::BipartiteAdjacencyList)
192+
if l.u === nothing
193+
printstyled(io, '', color = :light_black)
194+
elseif isempty(l.u)
195+
printstyled(io, '', color = :light_black)
196+
else
197+
print(io, l.u)
198+
end
199+
end
200+
201+
struct Label
202+
s::String
203+
end
204+
Base.show(io::IO, l::Label) = print(io, l.s)
205+
206+
struct BipartiteGraphPrintMatrix <:
207+
AbstractMatrix{Union{Label, Int, BipartiteAdjacencyList}}
208+
bpg::BipartiteGraph
209+
end
210+
Base.size(bgpm::BipartiteGraphPrintMatrix) = (max(nsrcs(bgpm.bpg), ndsts(bgpm.bpg)) + 1, 3)
211+
function Base.getindex(bgpm::BipartiteGraphPrintMatrix, i::Integer, j::Integer)
212+
checkbounds(bgpm, i, j)
213+
if i == 1
214+
return (Label.(("#", "src", "dst")))[j]
215+
elseif j == 1
216+
return i - 1
217+
elseif j == 2
218+
return BipartiteAdjacencyList(i - 1 <= nsrcs(bgpm.bpg) ?
219+
𝑠neighbors(bgpm.bpg, i - 1) : nothing)
220+
elseif j == 3
221+
return BipartiteAdjacencyList(i - 1 <= ndsts(bgpm.bpg) ?
222+
𝑑neighbors(bgpm.bpg, i - 1) : nothing)
223+
else
224+
@assert false
225+
end
226+
end
227+
228+
function Base.show(io::IO, b::BipartiteGraph)
229+
print(io, "BipartiteGraph with (", length(b.fadjlist), ", ",
230+
isa(b.badjlist, Int) ? b.badjlist : length(b.badjlist), ") (𝑠,𝑑)-vertices\n")
231+
Base.print_matrix(io, BipartiteGraphPrintMatrix(b))
232+
end
233+
187234
"""
188235
```julia
189236
Base.isequal(bg1::BipartiteGraph{T}, bg2::BipartiteGraph{T}) where {T<:Integer}

src/structural_transformation/bipartite_tearing/modia_tearing.jl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,57 @@ end
3737

3838
function tear_graph_modia(structure::SystemStructure; varfilter = v -> true,
3939
eqfilter = eq -> true)
40+
# It would be possible here to simply iterate over all variables and attempt to
41+
# use tearEquations! to produce a matching that greedily selects the minimal
42+
# number of torn variables. However, we can do this process faster if we first
43+
# compute the strongly connected components. In the absence of cycles and
44+
# non-solvability, a maximal matching on the original graph will give us an
45+
# optimal assignment. However, even with cycles, we can use the maximal matching
46+
# to give us a good starting point for a good matching and then proceed to
47+
# reverse edges in each scc to improve the solution. Note that it is possible
48+
# to have optimal solutions that cannot be found by this process. We will not
49+
# find them here [TODO: It would be good to have an explicit example of this.]
50+
4051
@unpack graph, solvable_graph = structure
4152
var_eq_matching = complete(maximal_matching(graph, eqfilter, varfilter))
4253
var_sccs::Vector{Union{Vector{Int}, Int}} = find_var_sccs(graph, var_eq_matching)
4354

55+
# Here, we're using a maximal matching on the post-pantelides system to find
56+
# the strongly connected components of the system (of variables that depend
57+
# on each other). The strongly connected components are unique, however, the
58+
# maximal matching itself is not. Every maximal matching gives rise to the
59+
# same set of strongly connected components, but the associated equations need
60+
# not be the same. In the absence of solvability constraints, this may be a
61+
# small issue, but here it is possible that an equation got assigned to an
62+
# scc that cannot actually use it for solving a variable, but still precludes
63+
# another scc from using it. To avoid this, we delete any assignments that
64+
# are not in the solvable graph and extend the set of considered eqauations
65+
# below.
66+
for var in ndsts(solvable_graph)
67+
var_eq_matching[var] === unassigned && continue
68+
if !(BipartiteEdge(var, var_eq_matching[var]) in solvable_graph)
69+
var_eq_matching[var] = unassigned
70+
end
71+
end
72+
4473
for vars in var_sccs
4574
filtered_vars = filter(varfilter, vars)
4675
ieqs = Int[var_eq_matching[v]
4776
for v in filtered_vars if var_eq_matching[v] !== unassigned]
4877
for var in vars
4978
var_eq_matching[var] = unassigned
5079
end
80+
for var in filtered_vars
81+
# Add any equations that we may not have been able to use earlier to see
82+
# if a different matching may have been possible.
83+
for eq′ in 𝑑neighbors(solvable_graph, var)
84+
eqfilter(eq′) || continue
85+
eq′ in ieqs && continue
86+
if invview(var_eq_matching)[eq′] === unassigned
87+
push!(ieqs, eq′)
88+
end
89+
end
90+
end
5191
tear_graph_block_modia!(var_eq_matching, graph, solvable_graph, ieqs, filtered_vars)
5292
end
5393

0 commit comments

Comments
 (0)