Skip to content

Commit 37653ba

Browse files
Improved alias elimination (especially to handle medium propagation)
1 parent c378ea0 commit 37653ba

File tree

5 files changed

+155
-22
lines changed

5 files changed

+155
-22
lines changed

src/Modia.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Modia main module.
33
44
* Developers: Hilding Elmqvist, Mogram AB, Toivo Henningsson, Lund and Martin Otter, DLR
5-
* Copyright (c) 2016-2018: Hilding Elmqvist, Toivo Henningsson, Martin Otter
5+
* Copyright (c) 2016-2019: Hilding Elmqvist, Toivo Henningsson, Martin Otter
66
* License: MIT (expat)
77
=#
88

@@ -45,8 +45,8 @@ For more information, see (https://github.com/ModiaSim/Modia.jl/blob/master/READ
4545
"""
4646
module Modia
4747

48-
const Version = "0.2.3-beta.5"
49-
const Date = "2019-01-09"
48+
const Version = "0.2.3-beta.7"
49+
const Date = "2019-01-23"
5050

5151
#println(" \n\nWelcome to Modia - Dynamic MODeling and Simulation in julIA")
5252
print(" \n\nWelcome to ")

src/language/Instantiation.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Modia module for instantiation and flattening of models.
33
44
* Original developer: Toivo Henningsson, Lund
55
* Developer: Hilding Elmqvist, Mogram AB
6-
* Copyright (c) 2016-2018: Hilding Elmqvist, Toivo Henningsson, Martin Otter
6+
* Copyright (c) 2016-2019: Hilding Elmqvist, Toivo Henningsson, Martin Otter
77
* License: MIT (expat)
88
99
"""
@@ -178,6 +178,12 @@ function Base.show(io::IO, v::Variable)
178178
print(io, "Variable(")
179179
first = true
180180

181+
if v.value != nothing
182+
if !first; print(io, ", ") end
183+
print(io, "value = ", v.value)
184+
first = false
185+
end
186+
181187
if v.variability != continuous
182188
if !first; print(io, ", ") end
183189
print(io, "variability = ", v.variability)
@@ -380,6 +386,21 @@ function recode(ex::Expr)
380386
head, args = ex.head, ex.args
381387
if head == :block
382388
args = collect(filter(ex -> (!is_linenumber(ex)), args))
389+
#=
390+
println("recode:")
391+
dump(args)
392+
393+
rex = Expr(:block)
394+
for a in args
395+
ra = recode(a)
396+
println("ra:")
397+
dump(ra)
398+
push!(rex.args, ra)
399+
end
400+
println("rex:")
401+
dump(rex)
402+
return rex
403+
=#
383404
if length(args) == 1; return recode(args[1]); end
384405
elseif head == :.
385406
return :( $(quot(model_getfield))($(recode(args[1])), $(args[2])) )

src/symbolic/DAEquations/BasicStructuralTransform.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,8 @@ function analyzeStructurally(equations, params, unknowns_indices, deriv, unknown
666666
else
667667
emptySet = Set(Any[])
668668
end
669+
# @show coeff keys(coeff) keys(params)
670+
# @show intersect(keys(coeff), keys(params))
669671
if !nonLinear && (intersect(keys(coeff), keys(params)) == emptySet) && !(1 in keys(coeff))
670672
push!(coefficients, copy(coeff))
671673
push!(orgEquIndex, neq)

src/symbolic/StructuralTransform.jl

Lines changed: 127 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Module for structural transformation of models including alias handling and size
33
44
* Developer: Hilding Elmqvist, Mogram AB
55
* First version: July-August 2016
6-
* Copyright (c) 2016-2018: Hilding Elmqvist, Toivo Henningsson, Martin Otter
6+
* Copyright (c) 2016-2019: Hilding Elmqvist, Toivo Henningsson, Martin Otter
77
* License: MIT (expat)
88
"""
99
module StructuralTransform
@@ -13,7 +13,7 @@ using ..BLTandPantelidesUtilities
1313
using ..Utilities
1414
using ..BasicStructuralTransform
1515
using ..Instantiation
16-
import ..Instantiation: GetField, This, Der, Symbolic, time_global, get_dims
16+
import ..Instantiation: GetField, This, Der, Symbolic, time_global, get_dims, parameter
1717
import ..Execution: get_value, Subs, subs, Variable, split_variables, vars_of, GetField
1818
using Base.Meta: quot, isexpr
1919
using DataStructures
@@ -108,11 +108,76 @@ v1 := v2
108108
v3 = v2 ->
109109
=#
110110

111-
function findAliases!(nonAliasEquations, aliases, eq::Expr, unknowns)
111+
function equivalence(pairs)
112+
equ = []
113+
for p in pairs
114+
for e in equ
115+
if intersect(p, e) != []
116+
if p[1] in e && p[2] in e
117+
println("Redundant equation: $(p[1]) = $(p[2])")
118+
end
119+
union!(p, e)
120+
setdiff!(e, e)
121+
end
122+
end
123+
push!(equ, p)
124+
end
125+
equivalenceClasses = []
126+
for e in equ
127+
if e != []
128+
push!(equivalenceClasses, e)
129+
end
130+
end
131+
equivalenceClasses
132+
end
133+
134+
function findAliases2!(nonAliasEquations, aliases, equations, variables, defined)
135+
equivalencePairs = []
136+
for eq in equations
137+
if !isexpr(eq, :quote)
138+
if eq.head in [:(=), :(:=)]
139+
e1 = eq.args[1]
140+
e2 = eq.args[2]
141+
if typeof(e1) == GetField && typeof(e2) == GetField
142+
push!(equivalencePairs, [e1.name, e2.name])
143+
else
144+
push!(nonAliasEquations, eq)
145+
end
146+
end
147+
end
148+
end
149+
equivalenceClasses = equivalence(equivalencePairs)
150+
for equiv in equivalenceClasses
151+
nonalias = nothing
152+
for v in equiv
153+
if typeof(variables[v]) != Variable || variables[v].variability <= parameter
154+
nonalias = GetField(This(), v)
155+
break
156+
end
157+
end
158+
if nonalias == nothing
159+
nonalias = GetField(This(), equiv[1]) # No non-Variable or parameter to define as nonalias, pick first
160+
end
161+
for v in equiv
162+
if v != nonalias.name
163+
aliases[GetField(This(), v)] = nonalias
164+
if typeof(variables[v]) != Variable || variables[v].variability <= parameter
165+
if "$(variables[v])" != "$(variables[nonalias.name])"
166+
println("Non consistent constraint: $v = $(nonalias.name): $(variables[v]) != $(variables[nonalias.name])")
167+
end
168+
end
169+
end
170+
end
171+
end
172+
end
173+
174+
175+
function findAliases!(nonAliasEquations, aliases, eq::Expr, unknowns, defined)
112176
if !isexpr(eq, :quote)
113177
if eq.head in [:(=), :(:=)]
114178
e1 = eq.args[1]
115179
e2 = eq.args[2]
180+
@show e1 e2
116181
if typeof(e1) == GetField && typeof(e2) == GetField && haskey(unknowns, e1.name) && haskey(unknowns, e2.name) # && unknowns[e1.name].state && unknowns[e2.name].state
117182
# nonAliases = collect(values(aliases))
118183
# if ! haskey(aliases, e1) && ! (e1 in nonAliases) && ! haskey(aliases, e2) && ! (e2 in nonAliases)
@@ -121,15 +186,46 @@ function findAliases!(nonAliasEquations, aliases, eq::Expr, unknowns)
121186
aliases[e1] = e2
122187
unknowns[e2.name].state = unknowns[e1.name].state
123188
# @show e2.name, unknowns[e2.name].state
189+
println()
124190
elseif !haskey(aliases, e2) && getNonAliasVariable(aliases, e1, unknowns)[1] != e2 && if haskey(unknowns, e1.name); unknowns[e1.name].state else false end
125191
aliases[e2] = e1
126192
unknowns[e1.name].state = unknowns[e2.name].state
127-
# @show e1.name, unknowns[e1.name].state
128-
else
193+
@show e1.name, unknowns[e1.name].state
194+
else
129195
println("Circular aliases between: $e1 and $e2")
130-
error("Aborting")
196+
# error("Aborting")
131197
end
198+
elseif typeof(e1) == GetField && typeof(e2) == GetField && (haskey(unknowns, e1.name) || haskey(unknowns, e2.name))
199+
println("One is unknown:")
200+
println(eq)
201+
if haskey(unknowns, e1.name)
202+
var = e1.name
203+
val = e2.name
204+
else
205+
var = e2.name
206+
val = e1.name
207+
end
208+
@show var
209+
@show aliases
210+
if haskey(aliases, var)
211+
var = aliases[var]
212+
@show aliases[var]
213+
end
214+
@show defined
215+
if ! haskey(defined, var)
216+
defined[var] = val
217+
@show defined
218+
println("Adding: ", eq)
219+
push!(nonAliasEquations, eq)
220+
elseif defined[var] != val
221+
println("Non consistent overdetermined variable:")
222+
println("$var = $val")
223+
println("$var = $defined[var]")
224+
else
225+
println("Not added: ", eq)
226+
end
132227
else
228+
println(eq)
133229
push!(nonAliasEquations, eq)
134230
end
135231
end
@@ -182,11 +278,16 @@ function performAliasElimination!(flat_model, unknowns, params, equations)
182278
loglnModia("\nALIAS ELIMINATION")
183279
aliases = AliasSubs()
184280
nonAliasEquations = []
281+
defined = Dict()
185282

283+
nonAliasEquations = []
284+
findAliases2!(nonAliasEquations, aliases, equations, merge(unknowns, params), defined)
285+
286+
#=
186287
for eq in equations
187-
findAliases!(nonAliasEquations, aliases, eq, unknowns)
288+
findAliases!(nonAliasEquations, aliases, eq, unknowns, defined)
188289
end
189-
290+
=#
190291
loglnModia("\nAlias equations")
191292
for a in aliases
192293
loglnModia(prettyfy(a[1]), " = ", prettyfy(a[2]))
@@ -195,7 +296,7 @@ function performAliasElimination!(flat_model, unknowns, params, equations)
195296
loglnModia("\nAlias definitions")
196297
for a in aliases
197298
(nonAlias, state) = getNonAliasVariable(aliases, a[2], unknowns)
198-
unknowns[nonAlias.name].state = state
299+
# unknowns[nonAlias.name].state = state # Temporarily
199300
loglnModia(prettyfy(a[1]), " := ", prettyfy(nonAlias))
200301
end
201302

@@ -248,7 +349,7 @@ Types and sizes can be inferred from the start values provided. An outline of su
248349
- If only one remaining unknown, solve for it.
249350
- Check if the equation only has +/- operators and at least one variable has known size and type. If so, copy size and type to the other variables.
250351
251-
Note: This function should be rewritten to ensure conssistency, etc.
352+
Note: This function should be rewritten to ensure consistency, etc.
252353
"""
253354
function deduceVariableAndEquationSizes(flat_model, unknowns, params, equations)
254355
loglnModia("\nSIZE AND TYPE DEDUCTION")
@@ -350,10 +451,10 @@ function deduceVariableAndEquationSizes(flat_model, unknowns, params, equations)
350451
try
351452
E = eval(e)
352453
catch err
353-
if isa(err, ErrorException) && contains(err.msg, "Unit mismatch")
454+
if isa(err, ErrorException) && occursin("Unit mismatch", err.msg)
354455
loglnModia("Warning: ", err.msg,
355-
"\n in expression: ", prettyPrint(e),
356-
"\n in equation: ", prettyPrint(eq))
456+
"\n in expression: ", prettyPrint(e),
457+
"\n in equation: ", prettyPrint(eq))
357458
end
358459
E
359460
end
@@ -463,6 +564,7 @@ function deduceVariableAndEquationSizes(flat_model, unknowns, params, equations)
463564
RHS = tryEval(rhs, eq)
464565
if RHS != nothing && typeof(RHS) != GetField && typeof(RHS) != Der
465566
if typeof(RHS) == String || fieldnames(typeof(RHS)) != emptyFieldNames || typeof(RHS) == Tuple{Array{Float64,2},Array{Float64,2}} # Special case for calling qr function
567+
# Using isstructtype(typeof(RHS)) did not work as expected so fieldnames(typeof(RHS)) != emptyFieldNames is used instead
466568
size_RHS = ()
467569
else
468570
size_RHS = size(RHS)
@@ -499,20 +601,27 @@ function deduceVariableAndEquationSizes(flat_model, unknowns, params, equations)
499601
else
500602
size_RHS = size(RHS)
501603
end
502-
503-
if size(LHS) != size_RHS
604+
#=
605+
if typeof(LHS) == String || typeof(LHS) != AbstractArray || fieldnames(typeof(LHS)) != emptyFieldNames
606+
size_LHS = ()
607+
else
608+
size_LHS = size(LHS)
609+
end
610+
=#
611+
size_LHS = size(LHS)
612+
if size_LHS != size_RHS
504613
loglnModia("Warning: Not equal size of left and right hand side in equation $(prettyPrint(eq)): $LHS = $RHS")
505614
end
506615

507616
e = promote(LHS, RHS)
508617
t = typeof(e[1])
509618
# loglnModia("ASSERT: ", typeof(LHS), " == ", typeof(RHS))
510-
loglnModia("SIZE = ", size(LHS), " \tTYPE = ", t, " \t", prettyPrint(eq))
511-
equSizes[i] = size(LHS)
619+
loglnModia("SIZE = ", size_LHS, " \tTYPE = ", t, " \t", prettyPrint(eq))
620+
equSizes[i] = size_LHS
512621
equTypes[i] = t
513622
equationSubs[i] = eqsubs
514623
#= Fix for call back function
515-
elseif LHS != nothing && typeof(LHS) != Der
624+
elseif LHS != nothing && typeof(LHS) != Der
516625
t = typeof(LHS)
517626
loglnModia("SIZE = ", size(LHS), " \tTYPE = ", t, " \t", prettyPrint(eq))
518627
equSizes[i] = size(LHS)

src/symbolic/Utilities.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ function checkSizes(VSizes, ESizes)
234234
end
235235

236236
loglnModia()
237+
# Should check that arrays are not empty
237238
scalarV = sum(length(zeros(v)) for v in VSizes)
238239
scalarE = sum(length(zeros(e)) for e in ESizes)
239240

0 commit comments

Comments
 (0)