Skip to content

Commit 8642b4e

Browse files
authored
Merge pull request #2101 from topolarity/mss-diff
Change `show` format for `MatchedSystemStructure` and add DeepDiffs.jl support
2 parents 288e803 + b88327e commit 8642b4e

File tree

5 files changed

+276
-39
lines changed

5 files changed

+276
-39
lines changed

Project.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
4646
UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
4747
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
4848

49+
[weakdeps]
50+
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"
51+
52+
[extensions]
53+
MTKDeepDiffsExt = "DeepDiffs"
54+
4955
[compat]
5056
AbstractTrees = "0.3, 0.4"
5157
ArrayInterface = "6, 7"
@@ -88,6 +94,7 @@ julia = "1.6"
8894
AmplNLWriter = "7c4d4715-977e-5154-bfe0-e096adeac482"
8995
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
9096
ControlSystemsMTK = "687d7614-c7e5-45fc-bfc3-9ee385575c88"
97+
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"
9198
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
9299
Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9"
93100
Ipopt_jll = "9cc047cb-c261-5740-88fc-0cf96f7bdcc7"

ext/MTKDeepDiffsExt.jl

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
module MTKDeepDiffsExt
2+
3+
using DeepDiffs, ModelingToolkit
4+
using ModelingToolkit.BipartiteGraphs: Label, BipartiteAdjacencyList, unassigned,
5+
HighlightInt
6+
using ModelingToolkit.SystemStructures: SystemStructure, MatchedSystemStructure,
7+
SystemStructurePrintMatrix
8+
9+
"""
10+
A utility struct for displaying the difference between two HighlightInts.
11+
12+
# Example
13+
```julia
14+
using ModelingToolkit, DeepDiffs
15+
16+
old_i = HighlightInt(1, :default, true)
17+
new_i = HighlightInt(2, :default, false)
18+
diff = HighlightIntDiff(new_i, old_i)
19+
20+
show(diff)
21+
```
22+
"""
23+
struct HighlightIntDiff
24+
new::HighlightInt
25+
old::HighlightInt
26+
end
27+
28+
function Base.show(io::IO, d::HighlightIntDiff)
29+
p_color = d.new.highlight
30+
(d.new.match && !d.old.match) && (p_color = :light_green)
31+
(!d.new.match && d.old.match) && (p_color = :light_red)
32+
33+
(d.new.match || d.old.match) && printstyled(io, "(", color = p_color)
34+
if d.new.i != d.old.i
35+
Base.show(io, HighlightInt(d.old.i, :light_red, d.old.match))
36+
print(io, " ")
37+
Base.show(io, HighlightInt(d.new.i, :light_green, d.new.match))
38+
else
39+
Base.show(io, HighlightInt(d.new.i, d.new.highlight, false))
40+
end
41+
(d.new.match || d.old.match) && printstyled(io, ")", color = p_color)
42+
end
43+
44+
"""
45+
A utility struct for displaying the difference between two
46+
BipartiteAdjacencyList's.
47+
48+
# Example
49+
```julia
50+
using ModelingToolkit, DeepDiffs
51+
52+
old = BipartiteAdjacencyList(...)
53+
new = BipartiteAdjacencyList(...)
54+
diff = BipartiteAdjacencyListDiff(new, old)
55+
56+
show(diff)
57+
```
58+
"""
59+
struct BipartiteAdjacencyListDiff
60+
new::BipartiteAdjacencyList
61+
old::BipartiteAdjacencyList
62+
end
63+
64+
function Base.show(io::IO, l::BipartiteAdjacencyListDiff)
65+
print(io,
66+
LabelDiff(Label(l.new.match === true ? "" : ""),
67+
Label(l.old.match === true ? "" : "")))
68+
(l.new.match !== true && l.old.match !== true) && print(io, " ")
69+
70+
new_nonempty = isnothing(l.new.u) ? nothing : !isempty(l.new.u)
71+
old_nonempty = isnothing(l.old.u) ? nothing : !isempty(l.old.u)
72+
if new_nonempty === true && old_nonempty === true
73+
if (!isempty(setdiff(l.new.highligh_u, l.new.u)) ||
74+
!isempty(setdiff(l.old.highligh_u, l.old.u)))
75+
throw(ArgumentError("The provided `highligh_u` must be a sub-graph of `u`."))
76+
end
77+
78+
new_items = Dict(i => HighlightInt(i, :nothing, i === l.new.match) for i in l.new.u)
79+
old_items = Dict(i => HighlightInt(i, :nothing, i === l.old.match) for i in l.old.u)
80+
81+
highlighted = union(map(intersect(l.new.u, l.old.u)) do i
82+
HighlightIntDiff(new_items[i], old_items[i])
83+
end,
84+
map(setdiff(l.new.u, l.old.u)) do i
85+
HighlightInt(new_items[i].i, :light_green,
86+
new_items[i].match)
87+
end,
88+
map(setdiff(l.old.u, l.new.u)) do i
89+
HighlightInt(old_items[i].i, :light_red,
90+
old_items[i].match)
91+
end)
92+
print(IOContext(io, :typeinfo => typeof(highlighted)), highlighted)
93+
elseif new_nonempty === true
94+
printstyled(io, map(l.new.u) do i
95+
HighlightInt(i, :nothing, i === l.new.match)
96+
end, color = :light_green)
97+
elseif old_nonempty === true
98+
printstyled(io, map(l.old.u) do i
99+
HighlightInt(i, :nothing, i === l.old.match)
100+
end, color = :light_red)
101+
elseif old_nonempty !== nothing || new_nonempty !== nothing
102+
print(io,
103+
LabelDiff(Label(new_nonempty === false ? "" : "", :light_black),
104+
Label(old_nonempty === false ? "" : "", :light_black)))
105+
else
106+
printstyled(io, '', color = :light_black)
107+
end
108+
end
109+
110+
"""
111+
A utility struct for displaying the difference between two Labels
112+
in git-style red/green highlighting.
113+
114+
# Example
115+
```julia
116+
using ModelingToolkit, DeepDiffs
117+
118+
old = Label("before")
119+
new = Label("after")
120+
diff = LabelDiff(new, old)
121+
122+
show(diff)
123+
```
124+
"""
125+
struct LabelDiff
126+
new::Label
127+
old::Label
128+
end
129+
function Base.show(io::IO, l::LabelDiff)
130+
if l.new != l.old
131+
printstyled(io, l.old.s, color = :light_red)
132+
length(l.new.s) != 0 && length(l.old.s) != 0 && print(io, " ")
133+
printstyled(io, l.new.s, color = :light_green)
134+
else
135+
print(io, l.new)
136+
end
137+
end
138+
139+
"""
140+
A utility struct for displaying the difference between two
141+
(Matched)SystemStructure's in git-style red/green highlighting.
142+
143+
# Example
144+
```julia
145+
using ModelingToolkit, DeepDiffs
146+
147+
old = SystemStructurePrintMatrix(...)
148+
new = SystemStructurePrintMatrix(...)
149+
diff = SystemStructureDiffPrintMatrix(new, old)
150+
151+
show(diff)
152+
```
153+
"""
154+
struct SystemStructureDiffPrintMatrix <:
155+
AbstractMatrix{Union{LabelDiff, BipartiteAdjacencyListDiff}}
156+
new::SystemStructurePrintMatrix
157+
old::SystemStructurePrintMatrix
158+
end
159+
160+
function Base.size(ssdpm::SystemStructureDiffPrintMatrix)
161+
max.(Base.size(ssdpm.new), Base.size(ssdpm.old))
162+
end
163+
164+
function Base.getindex(ssdpm::SystemStructureDiffPrintMatrix, i::Integer, j::Integer)
165+
checkbounds(ssdpm, i, j)
166+
if i > 1 && (j == 4 || j == 9)
167+
old = new = BipartiteAdjacencyList(nothing, nothing, unassigned)
168+
(i <= size(ssdpm.new, 1)) && (new = ssdpm.new[i, j])
169+
(i <= size(ssdpm.old, 1)) && (old = ssdpm.old[i, j])
170+
BipartiteAdjacencyListDiff(new, old)
171+
else
172+
old = new = Label("")
173+
(i <= size(ssdpm.new, 1)) && (new = ssdpm.new[i, j])
174+
(i <= size(ssdpm.old, 1)) && (old = ssdpm.old[i, j])
175+
LabelDiff(new, old)
176+
end
177+
end
178+
179+
function DeepDiffs.deepdiff(old::Union{MatchedSystemStructure, SystemStructure},
180+
new::Union{MatchedSystemStructure, SystemStructure})
181+
new_sspm = SystemStructurePrintMatrix(new)
182+
old_sspm = SystemStructurePrintMatrix(old)
183+
Base.print_matrix(stdout, SystemStructureDiffPrintMatrix(new_sspm, old_sspm))
184+
end
185+
186+
end # module

src/ModelingToolkit.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ export @variables, @parameters, @constants, @brownian
221221
export @named, @nonamespace, @namespace, extend, compose, complete
222222
export debug_system
223223

224+
export show_with_compare
225+
224226
#export Continuous, Discrete, sampletime, input_timedomain, output_timedomain
225227
#export has_discrete_domain, has_continuous_domain
226228
#export is_discrete_domain, is_continuous_domain, is_hybrid_domain

src/bipartite_graph.jl

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -212,21 +212,25 @@ end
212212

213213
struct HighlightInt
214214
i::Int
215-
highlight::Union{Symbol, Nothing}
215+
highlight::Symbol
216+
match::Bool
216217
end
217218
Base.typeinfo_implicit(::Type{HighlightInt}) = true
218-
219219
function Base.show(io::IO, hi::HighlightInt)
220-
if hi.highlight !== nothing
220+
if hi.match
221+
printstyled(io, "(", color = hi.highlight)
221222
printstyled(io, hi.i, color = hi.highlight)
223+
printstyled(io, ")", color = hi.highlight)
222224
else
223-
print(io, hi.i)
225+
printstyled(io, hi.i, color = hi.highlight)
224226
end
225227
end
226228

227229
function Base.show(io::IO, l::BipartiteAdjacencyList)
228230
if l.match === true
229-
printstyled(io, "", color = :light_blue, bold = true)
231+
printstyled(io, "")
232+
else
233+
printstyled(io, " ")
230234
end
231235
if l.u === nothing
232236
printstyled(io, '', color = :light_black)
@@ -238,26 +242,30 @@ function Base.show(io::IO, l::BipartiteAdjacencyList)
238242
match = l.match
239243
isa(match, Bool) && (match = unassigned)
240244
function choose_color(i)
241-
i in l.highligh_u ? (i == match ? :light_yellow : :green) :
242-
(i == match ? :yellow : nothing)
245+
i in l.highligh_u ? :default : :light_black
243246
end
244247
if !isempty(setdiff(l.highligh_u, l.u))
245248
# Only for debugging, shouldn't happen in practice
246-
print(io, map(union(l.u, l.highligh_u)) do i
247-
HighlightInt(i, !(i in l.u) ? :light_red : choose_color(i))
249+
print(io,
250+
map(union(l.u, l.highligh_u)) do i
251+
HighlightInt(i, !(i in l.u) ? :light_red : choose_color(i),
252+
i == match)
248253
end)
249254
else
250255
print(io, map(l.u) do i
251-
HighlightInt(i, choose_color(i))
256+
HighlightInt(i, choose_color(i), i == match)
252257
end)
253258
end
254259
end
255260
end
256261

257262
struct Label
258263
s::String
264+
c::Symbol
259265
end
260-
Base.show(io::IO, l::Label) = print(io, l.s)
266+
Label(s::AbstractString) = Label(s, :nothing)
267+
Label(x::Integer) = Label(string(x))
268+
Base.show(io::IO, l::Label) = printstyled(io, l.s, color = l.c)
261269

262270
struct BipartiteGraphPrintMatrix <:
263271
AbstractMatrix{Union{Label, Int, BipartiteAdjacencyList}}

0 commit comments

Comments
 (0)