Skip to content

Commit

Permalink
[NB] correctly determine record and tuple equations (OpenModelica#12553)
Browse files Browse the repository at this point in the history
* [NB] correctly determine record and tuple equations

 - check if when and if equations return multiple values
 - small update index reduction interface

* [testsuite] update for changes

 - changed initial balancing behaviour
  • Loading branch information
kabdelhak committed Jun 11, 2024
1 parent 9e58230 commit 597ea33
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 20 deletions.
53 changes: 53 additions & 0 deletions OMCompiler/Compiler/NBackEnd/Classes/NBEquation.mo
Original file line number Diff line number Diff line change
Expand Up @@ -1683,8 +1683,16 @@ public
output Boolean b;
algorithm
b := match Pointer.access(eqn)
local
WhenEquationBody when_body;
IfEquationBody if_body;

case RECORD_EQUATION() then true;
case ARRAY_EQUATION(recordSize = SOME(_)) then true;
case WHEN_EQUATION(body = when_body)
then WhenEquationBody.isRecordOrTupleEquation(when_body);
case IF_EQUATION(body = if_body)
then IfEquationBody.isRecordOrTupleEquation(if_body);
else false;
end match;
end isRecordOrTupleEquation;
Expand Down Expand Up @@ -2430,6 +2438,22 @@ public
end for;
end split;

function isRecordOrTupleEquation
"only checks first layer body if it returns multiple variables"
input IfEquationBody body;
output Boolean b;
algorithm
b := match body.then_eqns
local
Pointer<Equation> eqn_ptr;
// just a tuple itself
case {eqn_ptr} guard(Equation.isRecordOrTupleEquation(eqn_ptr)) then true;
// multiple body equations -> tuple return
case _ :: _ then true;
else false;
end match;
end isRecordOrTupleEquation;

protected
function sortForSplit
"sorts the body equations by discrete and continuous to correctly split them
Expand Down Expand Up @@ -2763,6 +2787,25 @@ public
end for;
end getAllAssigned;

function isRecordOrTupleEquation
"only checks first layer body if it returns multiple variables"
input WhenEquationBody body;
output Boolean b;
algorithm
b := match body.when_stmts
local
ComponentRef cref;
// just a record or tuple itself
case {WhenStatement.ASSIGN(lhs = Expression.TUPLE())} then true;
case {WhenStatement.ASSIGN(lhs = Expression.RECORD())} then true;
case {WhenStatement.ASSIGN(lhs = Expression.CREF(cref = cref))}
then BVariable.checkCref(cref, BVariable.isRecord);
// multiple body equations -> tuple return
case _ guard(List.count(body.when_stmts, WhenStatement.isAssign) > 1) then true;
else false;
end match;
end isRecordOrTupleEquation;

protected
type CrefSet = UnorderedSet<ComponentRef>;
function collectForSplit
Expand Down Expand Up @@ -2990,6 +3033,16 @@ public
end match;
end size;

function isAssign
input WhenStatement stmt;
output Boolean b;
algorithm
b := match stmt
case ASSIGN() then true;
else false;
end match;
end isAssign;

function isAssignOrReinit
input WhenStatement stmt;
output Boolean b;
Expand Down
4 changes: 2 additions & 2 deletions OMCompiler/Compiler/NBackEnd/Modules/1_Main/NBCausalize.mo
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ protected
vn := UnorderedMap.subMap(system.unknowns.map, list(BVariable.getVarName(var) for var in fixable));
en := UnorderedMap.new<Integer>(ComponentRef.hash, ComponentRef.isEqual);
(adj_matching, full) := Adjacency.Matrix.expand(adj_matching, full, vo, vn, eo, en, system.unknowns, system.equations);
(matching, adj_matching, full, variables, equations, funcTree, varData, eqData) := Matching.singular(matching, adj_matching, full, system.unknowns, system.equations, funcTree, varData, eqData, system.systemType, false, true, false);
(matching, adj_matching, full, variables, equations, funcTree, varData, eqData) := Matching.singular(matching, adj_matching, full, system.unknowns, system.equations, funcTree, varData, eqData, system.systemType, false, false);

// create all occurence adjacency matrix for sorting, upgrading the matching matrix
adj_sorting := Adjacency.Matrix.upgrade(adj_matching, full, variables.map, equations.map, equations, NBAdjacency.MatrixStrictness.SORTING);
Expand All @@ -296,7 +296,7 @@ protected

// create solvable adjacency matrix for matching
adj_matching := Adjacency.Matrix.fromFull(full, variables.map, equations.map, equations, NBAdjacency.MatrixStrictness.MATCHING);
(matching, adj_matching, full, variables, equations, funcTree, varData, eqData) := Matching.singular(NBMatching.EMPTY_MATCHING, adj_matching, full, variables, equations, funcTree, varData, eqData, system.systemType, false, true);
(matching, adj_matching, full, variables, equations, funcTree, varData, eqData) := Matching.singular(NBMatching.EMPTY_MATCHING, adj_matching, full, variables, equations, funcTree, varData, eqData, system.systemType, false);

// create all occurence adjacency matrix for sorting, upgrading the matching matrix
adj_sorting := Adjacency.Matrix.upgrade(adj_matching, full, variables.map, equations.map, equations, NBAdjacency.MatrixStrictness.SORTING);
Expand Down
27 changes: 14 additions & 13 deletions OMCompiler/Compiler/NBackEnd/Modules/1_Main/NBMatching.mo
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ public
input output EqData eqData;
input System.SystemType systemType;
input Boolean transposed = false "transpose matching if true";
input Boolean partially = false "do not resolve singular systems and return partial matching if true";
input Boolean clear = true "start from scratch if true";
protected
list<list<Integer>> marked_eqns;
Expand All @@ -142,24 +141,26 @@ public
end try;

// 2. Resolve singular systems if necessary
changed := match systemType
case NBSystem.SystemType.INI algorithm
// ####### BALANCE INITIALIZATION #######
(adj, full, vars, eqns, varData, eqData, funcTree, changed) := ResolveSingularities.balanceInitialization(adj, full, vars, eqns, varData, eqData, funcTree, matching, mapping);
then changed;

else algorithm
// ####### INDEX REDUCTION ######
(adj, full, vars, eqns, varData, eqData, funcTree, changed) := ResolveSingularities.noIndexReduction(adj, full, vars, eqns, varData, eqData, funcTree, matching, mapping);
then changed;
end match;
if systemType == NBSystem.SystemType.INI then
// ####### BALANCE INITIALIZATION #######
(adj, full, vars, eqns, varData, eqData, funcTree, changed) := ResolveSingularities.balanceInitialization(adj, full, vars, eqns, varData, eqData, funcTree, matching, mapping);
else
// ####### INDEX REDUCTION #######
(adj, full, vars, eqns, varData, eqData, funcTree, changed) := ResolveSingularities.noIndexReduction(adj, full, vars, eqns, varData, eqData, funcTree, matching, mapping);
end if;

// 3. Recompute adjacency and restart matching if something changed in step 2.
if changed then
// ToDo: keep more of old information by only updating changed stuff
adj := Adjacency.Matrix.createFull(vars, eqns);
adj := Adjacency.Matrix.fromFull(adj, vars.map, eqns.map, eqns, matrixStrictness);
(matching, adj, full, vars, eqns, funcTree, varData, eqData) := singular(EMPTY_MATCHING, adj, full, vars, eqns, funcTree, varData, eqData, systemType, false, true);
if systemType == NBSystem.SystemType.INI then
// ####### DO NOT REDO BALANCING INITIALIZATION #######
matching := regular(EMPTY_MATCHING, adj);
else
// ####### REDO INDEX REDUCTION IF NECESSARY #######
(matching, adj, full, vars, eqns, funcTree, varData, eqData) := singular(EMPTY_MATCHING, adj, full, vars, eqns, funcTree, varData, eqData, systemType, transposed);
end if;
end if;
end singular;

Expand Down
4 changes: 3 additions & 1 deletion OMCompiler/Compiler/NBackEnd/Modules/1_Main/NBSorting.mo
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,9 @@ public
if Flags.isSet(Flags.DUMP_SORTING) then
print(StringUtil.headline_1("Sorting"));
end if;
buckets := PseudoBucket.create(matching.eqn_to_var, eqns, adj.mapping, adj.modes);

// phase 1 tarjan
buckets := PseudoBucket.create(matching.eqn_to_var, eqns, adj.mapping, adj.modes);
comps_indices := tarjanScalar(adj.m, matching.var_to_eqn, matching.eqn_to_var);

// phase 2 tarjan
Expand All @@ -260,6 +261,7 @@ public
// it is just safer if something is changed in the future
() := match phase2_adj
case Adjacency.Matrix.FINAL() algorithm
// phase 3 tarjan
phase2_indices := tarjanScalar(phase2_adj.m, phase2_matching.var_to_eqn, phase2_matching.eqn_to_var);
comps := list(SuperNode.collapse(comp, super_nodes, adj.m, adj.mapping, matching.var_to_eqn, matching.eqn_to_var, vars, eqns) for comp in phase2_indices);
then ();
Expand Down
19 changes: 19 additions & 0 deletions OMCompiler/Compiler/Util/List.mo
Original file line number Diff line number Diff line change
Expand Up @@ -7405,6 +7405,25 @@ algorithm
outResult := false;
end any;

public function count<T>
"Counts the number of elements the function returns true for"
input list<T> inList;
input PredFunc inFunc;
output Integer outResult = 0;

partial function PredFunc
input T inElement;
output Boolean outMatch;
end PredFunc;
algorithm
for e in inList loop
if inFunc(e) then
outResult := outResult + 1;
return;
end if;
end for;
end count;

public function separateOnTrue<T>
"Takes a list of values and a filter function over the values and returns 2
sub lists of values for which the matching function returns true and false."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ simulate(underdetermined_init); getErrorString();
// ***************************************************************
// [SCAL] (1) y = $START.y ($RES_SIM_6)
//
// Not underdetermined.
// **********************
// Not overdetermined.
// *********************
// record SimulationResult
// resultFile = "underdetermined_init_res.mat",
// simulationOptions = "startTime = 0.0, stopTime = 1.0, numberOfIntervals = 500, tolerance = 1e-6, method = 'dassl', fileNamePrefix = 'underdetermined_init', options = '', outputFormat = 'mat', variableFilter = '.*', cflags = '', simflags = ''",
Expand Down

0 comments on commit 597ea33

Please sign in to comment.