Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit 24c3047

Browse files
sjoelundOpenModelica-Hudson
authored andcommitted
Perform incomplete matching for over/underdet syst
This performs an incomplete matching after producing the message unbalanced equation system, and instead of just a number differing OMC will try to perform a sanity check to figure out if for example a variable is never referenced in any equation or if two variables must be matched by the same equation.
1 parent 1355755 commit 24c3047

File tree

6 files changed

+195
-20
lines changed

6 files changed

+195
-20
lines changed

Compiler/BackEnd/BackendDAECreate.mo

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ protected
115115
list<BackendDAE.TimeEvent> timeEvents;
116116
String neqStr, nvarStr;
117117
Integer varSize, eqnSize, numCheckpoints;
118+
BackendDAE.EqSystem syst;
118119
algorithm
119120
numCheckpoints:=ErrorExt.getNumCheckpoints();
120121
try
@@ -148,7 +149,8 @@ algorithm
148149
ieqnarr := BackendEquation.listEquation(ieqns);
149150
einfo := BackendDAE.EVENT_INFO(timeEvents, ZeroCrossings.new(), DoubleEndedList.fromList({}), ZeroCrossings.new(), 0);
150151
symjacs := {(NONE(), ({}, {}, ({}, {}), -1), {}), (NONE(), ({}, {}, ({}, {}), -1), {}), (NONE(), ({}, {}, ({}, {}), -1), {}), (NONE(), ({}, {}, ({}, {}), -1), {})};
151-
outBackendDAE := BackendDAE.DAE(BackendDAEUtil.createEqSystem(vars_1, eqnarr, {}, BackendDAE.UNKNOWN_PARTITION(), reqnarr)::{},
152+
syst := BackendDAEUtil.createEqSystem(vars_1, eqnarr, {}, BackendDAE.UNKNOWN_PARTITION(), reqnarr);
153+
outBackendDAE := BackendDAE.DAE(syst::{},
152154
BackendDAE.SHARED(globalKnownVars,
153155
localKnownVars,
154156
extVars,
@@ -167,17 +169,11 @@ algorithm
167169
BackendDAEUtil.emptyPartitionsInfo()
168170
));
169171
BackendDAEUtil.checkBackendDAEWithErrorMsg(outBackendDAE);
170-
varSize := BackendVariable.varsSize(vars_1);
171-
eqnSize := BackendEquation.equationArraySize(eqnarr);
172-
neqStr := intString(eqnSize);
173-
nvarStr := intString(varSize);
174-
175-
if varSize <> eqnSize then
176-
Error.addMessage(if varSize > eqnSize then Error.UNDERDET_EQN_SYSTEM else Error.OVERDET_EQN_SYSTEM, {neqStr, nvarStr});
177-
fail();
178-
end if;
172+
BackendDAEUtil.checkIncidenceMatrixSolvability(syst, functionTree);
179173

180-
Error.assertionOrAddSourceMessage(not Flags.isSet(Flags.DUMP_BACKENDDAE_INFO),Error.BACKENDDAEINFO_LOWER,{neqStr,nvarStr},Absyn.dummyInfo);
174+
if Flags.isSet(Flags.DUMP_BACKENDDAE_INFO) then
175+
Error.addSourceMessage(Error.BACKENDDAEINFO_LOWER,{String(BackendEquation.equationArraySize(syst.orderedEqs)), String(BackendVariable.varsSize(syst.orderedVars))},Absyn.dummyInfo);
176+
end if;
181177
execStat("Generate backend data structure");
182178
return;
183179
else

Compiler/BackEnd/BackendDAEOptimize.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ algorithm
16621662
b = i > 1;
16631663
// bcall2(b,BackendDump.dumpBackendDAE,BackendDAE.DAE({syst},shared), "partitionIndependentBlocksHelper");
16641664
// printPartition(b,ixs);
1665-
systs = if b then SynchronousFeatures.partitionIndependentBlocksSplitBlocks(i, syst, eqPartMap, rixs, mT, rmT, throwNoError) else {syst};
1665+
systs = if b then SynchronousFeatures.partitionIndependentBlocksSplitBlocks(i, syst, eqPartMap, rixs, mT, rmT, throwNoError, funcs) else {syst};
16661666
// print("Number of partitioned systems: " + intString(listLength(systs)) + "\n");
16671667
// List.map1_0(systs, BackendDump.dumpEqSystem, "System");
16681668
GC.free(eqPartMap);

Compiler/BackEnd/BackendDAEUtil.mo

Lines changed: 177 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,10 @@ algorithm
156156
Boolean samesize;
157157
BackendDAE.Variables vars;
158158
BackendDAE.EquationArray orderedEqs;
159+
BackendDAE.EqSystem syst;
160+
DAE.FunctionTree functionTree;
159161

160-
case (BackendDAE.DAE(eqs=BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=orderedEqs)::{})) equation
162+
case BackendDAE.DAE(eqs=(syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=orderedEqs))::{}, shared=BackendDAE.SHARED(functionTree=functionTree)) equation
161163
//true = Flags.isSet(Flags.CHECK_BACKEND_DAE);
162164
//Check for correct size
163165
nVars = BackendVariable.varsSize(vars);
@@ -271,7 +273,7 @@ algorithm
271273
equation
272274
allvars = BackendVariable.mergeVariables(syst.orderedVars, shared.globalKnownVars);
273275
((_, expcrefs)) = traverseBackendDAEExpsVars(syst.orderedVars, checkBackendDAEExp, (allvars, {}));
274-
((_, expcrefs)) = traverseBackendDAEExpsEqns(shared.removedEqs, checkBackendDAEExp, (allvars, expcrefs));
276+
((_, expcrefs)) = traverseBackendDAEExpsEqns(shared.removedEqs, checkBackendDAEExp, (allvars, expcrefs));
275277
((_, expcrefs)) = traverseBackendDAEExpsVars(shared.globalKnownVars, checkBackendDAEExp, (allvars, expcrefs));
276278
((_, expcrefs)) = traverseBackendDAEExpsEqns(syst.orderedEqs, checkBackendDAEExp, (allvars, expcrefs));
277279
((_, expcrefs)) = traverseBackendDAEExpsEqns(syst.removedEqs, checkBackendDAEExp, (allvars, expcrefs));
@@ -9060,5 +9062,178 @@ algorithm
90609062
end for;
90619063
end getNoDerivativeInputPosition;
90629064

9065+
public function checkIncidenceMatrixSolvability "Performs a limited matching algorithm to sometimes figure out which equations are superflours or which variables are never solved for."
9066+
input BackendDAE.EqSystem syst;
9067+
input DAE.FunctionTree functionTree;
9068+
protected
9069+
Integer varSize, eqnSize, v, eq, count;
9070+
BackendDAE.IncidenceMatrix m, mT, mOrig, mTOrig;
9071+
list<Integer> vars, eqs, varsInOrig, eqsInOrig;
9072+
array<Integer> solvedVars;
9073+
array<list<tuple<DAE.ComponentRef,Integer>>> solvedEqs;
9074+
list<SourceInfo> infos;
9075+
list<tuple<DAE.ComponentRef,Integer>> names;
9076+
Integer errors = 0, numSolved = 0, eqSize, lenInfos, lenVars;
9077+
Boolean cont = true;
9078+
BackendDAE.Variables varsArray;
9079+
BackendDAE.Var var;
9080+
BackendDAE.EquationArray eqsArray;
9081+
BackendDAE.Equation _equation;
9082+
constant Boolean debug=false;
9083+
constant Boolean alwaysCheck=false;
9084+
SourceInfo info;
9085+
algorithm
9086+
varsArray := syst.orderedVars;
9087+
eqsArray := syst.orderedEqs;
9088+
varSize := BackendVariable.varsSize(varsArray);
9089+
eqnSize := BackendEquation.equationArraySize(eqsArray);
9090+
if varSize <> eqnSize then
9091+
Error.addMessage(if varSize > eqnSize then Error.UNDERDET_EQN_SYSTEM else Error.OVERDET_EQN_SYSTEM, {String(eqnSize), String(varSize)});
9092+
elseif not alwaysCheck then
9093+
return;
9094+
end if;
9095+
(_, mOrig, mTOrig) := BackendDAEUtil.getIncidenceMatrixfromOption(syst, BackendDAE.ABSOLUTE(), SOME(functionTree));
9096+
9097+
m := arrayCopy(mOrig);
9098+
mT := arrayCopy(mTOrig);
9099+
9100+
solvedVars := arrayCreate(arrayLength(mT), 0);
9101+
solvedEqs := arrayCreate(arrayLength(m), {});
9102+
9103+
if debug then
9104+
print("Got adjacency matrix "+String(varSize)+" "+String(arrayLength(m))+" "+String(eqnSize)+" "+String(arrayLength(mT))+"...\n");
9105+
end if;
9106+
count := 0;
9107+
while cont and count < 1000 loop
9108+
cont := false;
9109+
count := count+1;
9110+
for i in 1:arrayLength(m) /* Not eqnSize; that is the size including arrays */ loop
9111+
if not listEmpty(arrayGet(solvedEqs, i)) then
9112+
continue;
9113+
end if;
9114+
_equation := BackendEquation.get(eqsArray, i);
9115+
info := BackendEquation.equationInfo(_equation);
9116+
eqSize := BackendEquation.equationSize(_equation);
9117+
vars := arrayGet(m, i);
9118+
lenVars := listLength(vars);
9119+
if eqSize == 0 then
9120+
arrayUpdate(solvedEqs, i, {(DAE.emptyCref,0)});
9121+
continue;
9122+
end if;
9123+
if lenVars <= eqSize then
9124+
if lenVars < eqSize then
9125+
variableDoesNotFitInEquation(i, vars, mOrig, eqsArray, varsArray, solvedVars);
9126+
errors := errors+1;
9127+
if lenVars == 0 then
9128+
arrayUpdate(solvedEqs, i, (DAE.emptyCref,0)::arrayGet(solvedEqs,i));
9129+
end if;
9130+
end if;
9131+
for v in vars loop
9132+
var := BackendVariable.getVarAt(varsArray, v);
9133+
arrayUpdate(solvedEqs, i, (var.varName,v)::arrayGet(solvedEqs,i));
9134+
arrayUpdate(solvedVars, v, i);
9135+
eqs := arrayGet(mT, v);
9136+
for eq in eqs loop
9137+
// Remove references to the variable in other equations since we can't solve it there
9138+
arrayUpdate(m, eq, List.setDifference(arrayGet(m, eq), vars));
9139+
end for;
9140+
numSolved := numSolved+1;
9141+
end for;
9142+
cont := true;
9143+
end if;
9144+
end for;
9145+
9146+
if debug then
9147+
print("Number of equations solved: " + String(numSolved-errors) + "\n");
9148+
print("Number of errors: " + String(errors) + "\n");
9149+
end if;
9150+
9151+
for i in 1:arrayLength(mT) /* = varSize */ loop
9152+
if 0 <> arrayGet(solvedVars, i) then
9153+
continue;
9154+
end if;
9155+
eqs := arrayGet(mT, i);
9156+
var := BackendVariable.getVarAt(varsArray, i);
9157+
info := var.source.info;
9158+
if listLength(eqs) == 0 then
9159+
Error.addSourceMessage(Error.VAR_NO_REMAINING_EQN, {
9160+
ComponentReference.printComponentRefStr(var.varName),
9161+
stringAppendList(list("\n Equation " + String(eq) + ": " + BackendDump.equationString(BackendEquation.get(eqsArray, eq)) + ", which needs to solve for " + stringDelimitList(list(ComponentReference.printComponentRefStr(Util.tuple21(tpl)) for tpl in arrayGet(solvedEqs, eq)), ", ") for eq in arrayGet(mTOrig, i)))
9162+
}, info);
9163+
arrayUpdate(solvedVars, i, -1);
9164+
elseif listLength(eqs) == 1 then
9165+
{eq} := eqs;
9166+
eqSize := BackendEquation.equationSize(BackendEquation.get(eqsArray, eq));
9167+
names := arrayGet(solvedEqs, eq);
9168+
lenInfos := listLength(names);
9169+
arrayUpdate(solvedVars, i, eq);
9170+
arrayUpdate(solvedEqs, eq, (var.varName,i)::names);
9171+
if lenInfos >= eqSize then
9172+
variableDoesNotFitInEquation(eq, {i}, mOrig, eqsArray, varsArray, solvedVars);
9173+
errors := errors+1;
9174+
end if;
9175+
vars := arrayGet(m, eq);
9176+
if lenInfos+1 >= eqSize then // TODO: FIXME
9177+
for v in vars loop
9178+
// Remove references to the equation in other variables since we can't solve it there
9179+
arrayUpdate(mT, v, List.setDifference(arrayGet(mT, v), eqs));
9180+
end for;
9181+
end if;
9182+
numSolved := numSolved+1;
9183+
cont := true;
9184+
end if;
9185+
end for;
9186+
9187+
if debug then
9188+
print("Number of equations solved: " + String(numSolved-errors) + "\n");
9189+
print("Number of errors: " + String(errors) + "\n");
9190+
end if;
9191+
end while;
9192+
true := 0 == errors;
9193+
if alwaysCheck and varSize == eqnSize then
9194+
return;
9195+
end if;
9196+
fail();
9197+
end checkIncidenceMatrixSolvability;
9198+
9199+
protected function variableDoesNotFitInEquation
9200+
input Integer eq;
9201+
input list<Integer> vars;
9202+
input BackendDAE.IncidenceMatrix m;
9203+
input BackendDAE.EquationArray eqsArray;
9204+
input BackendDAE.Variables varsArray;
9205+
input array<Integer> solvedVars;
9206+
protected
9207+
BackendDAE.Equation _equation;
9208+
list<Integer> varsInOrig, eqsInOrig;
9209+
String eqsString;
9210+
SourceInfo info;
9211+
Integer eqSize;
9212+
algorithm
9213+
_equation := BackendEquation.get(eqsArray, eq);
9214+
info := BackendEquation.equationInfo(_equation);
9215+
eqSize := BackendEquation.equationSize(_equation);
9216+
9217+
varsInOrig := List.setDifference(arrayGet(m, eq), vars);
9218+
eqsInOrig := List.sortedUnique(List.sort(list(arrayGet(solvedVars,myVar) for myVar guard arrayGet(solvedVars,myVar)>0 in varsInOrig), intGt), intEq);
9219+
eqsString := stringAppendList(list("\n Equation " + String(eqNum) + " (size: "+String(BackendEquation.equationSize(BackendEquation.get(eqsArray, eqNum)))+"): " + BackendDump.equationString(BackendEquation.get(eqsArray, eqNum)) for eqNum in eqsInOrig));
9220+
Error.addSourceMessage(Error.EQN_NO_SPACE_TO_SOLVE, {
9221+
String(eq),
9222+
String(eqSize),
9223+
BackendDump.equationString(_equation),
9224+
getVariableNamesForErrorMessage(varsArray, vars),
9225+
getVariableNamesForErrorMessage(varsArray, varsInOrig),
9226+
eqsString
9227+
}, info);
9228+
end variableDoesNotFitInEquation;
9229+
9230+
protected function getVariableNamesForErrorMessage
9231+
input BackendDAE.Variables varsArray;
9232+
input list<Integer> vars;
9233+
output String names;
9234+
algorithm
9235+
names := stringDelimitList(list(ComponentReference.printComponentRefStr(BackendVariable.varCref(BackendVariable.getVarAt(varsArray, v))) for v in vars), ", ");
9236+
end getVariableNamesForErrorMessage;
9237+
90639238
annotation(__OpenModelica_Interface="backend");
90649239
end BackendDAEUtil;

Compiler/BackEnd/Causalize.mo

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ algorithm
100100
esize_str = intString(neqns);
101101
vsize_str = intString(nvars);
102102
Error.addMessage(Error.UNDERDET_EQN_SYSTEM, {esize_str,vsize_str});
103+
BackendDAEUtil.checkIncidenceMatrixSolvability(isyst, ishared.functionTree);
103104
then
104105
fail();
105106

@@ -109,6 +110,7 @@ algorithm
109110
esize_str = intString(neqns) ;
110111
vsize_str = intString(nvars);
111112
Error.addMessage(Error.OVERDET_EQN_SYSTEM, {esize_str,vsize_str});
113+
BackendDAEUtil.checkIncidenceMatrixSolvability(isyst, ishared.functionTree);
112114
then
113115
fail();
114116

Compiler/BackEnd/SynchronousFeatures.mo

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2600,7 +2600,7 @@ algorithm
26002600
partitionCnt := partitionIndependentBlocks0(m, mT, rm, rmT, eqPartMap, varPartMap, reqsPartition, varsPartition, rvarsPartition);
26012601

26022602
if partitionCnt > 1 then
2603-
(systs, outUnpartRemEqs) := partitionIndependentBlocksSplitBlocks(partitionCnt, syst, eqPartMap, reqsPartition, mT, rmT, false);
2603+
(systs, outUnpartRemEqs) := partitionIndependentBlocksSplitBlocks(partitionCnt, syst, eqPartMap, reqsPartition, mT, rmT, false, funcs);
26042604
else
26052605
(systs, outUnpartRemEqs) := ({syst}, {});
26062606
end if;
@@ -3049,14 +3049,14 @@ public function partitionIndependentBlocksSplitBlocks
30493049
input BackendDAE.IncidenceMatrix mT;
30503050
input BackendDAE.IncidenceMatrix rmT;
30513051
input Boolean throwNoError;
3052+
input DAE.FunctionTree funcs;
30523053
output list<BackendDAE.EqSystem> systs = {};
30533054
output list<BackendDAE.Equation> unpartRemovedEqs;
30543055
output array<Integer> varPartMap;
30553056
protected
30563057
array<list<BackendDAE.Equation>> ea, rea;
30573058
array<list<BackendDAE.Var>> va;
30583059
Integer i1, i2;
3059-
String s1, s2;
30603060
Boolean b, b1 = true;
30613061
BackendDAE.EqSystem syst;
30623062
array<Integer> varsPartition;
@@ -3070,10 +3070,8 @@ algorithm
30703070
i2 := BackendVariable.varsSize(inSyst.orderedVars);
30713071

30723072
if i1 <> i2 and not throwNoError then
3073-
s1 := intString(i1);
3074-
s2 := intString(i2);
3075-
Error.addSourceMessage(if i1 > i2 then Error.OVERDET_EQN_SYSTEM else Error.UNDERDET_EQN_SYSTEM,
3076-
{s1, s2}, Absyn.dummyInfo);
3073+
Error.addSourceMessage(if i1 > i2 then Error.OVERDET_EQN_SYSTEM else Error.UNDERDET_EQN_SYSTEM, {String(i1), String(i2)}, Absyn.dummyInfo);
3074+
BackendDAEUtil.checkIncidenceMatrixSolvability(inSyst, funcs);
30773075
fail();
30783076
end if;
30793077

Compiler/Util/Error.mo

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,10 @@ public constant Message CLASS_EXTENDS_TARGET_NOT_FOUND = MESSAGE(579, TRANSLATIO
879879
Util.gettext("Base class targeted by class extends %s not found in the inherited classes."));
880880
public constant Message ASSIGN_PARAM_FIXED_ERROR = MESSAGE(580, TRANSLATION(), ERROR(),
881881
Util.gettext("Trying to assign to parameter component %s(fixed=true) in %s := %s"));
882+
public constant Message EQN_NO_SPACE_TO_SOLVE = MESSAGE(581, SYMBOLIC(), WARNING(),
883+
Util.gettext("Equation %s (size: %s) %s is not big enough to solve for enough variables.\n Remaining unsolved variables are: %s\n Already solved: %s\n Equations used to solve those variables:%s"));
884+
public constant Message VAR_NO_REMAINING_EQN = MESSAGE(582, SYMBOLIC(), WARNING(),
885+
Util.gettext("Variable %s does not have any remaining equation to be solved in.\n The original equations were:%s"));
882886

883887
public constant Message MATCH_SHADOWING = MESSAGE(5001, TRANSLATION(), ERROR(),
884888
Util.gettext("Local variable '%s' shadows another variable."));

0 commit comments

Comments
 (0)