Skip to content

Commit

Permalink
[BE] update ASSC algorithm (#7331)
Browse files Browse the repository at this point in the history
* [BE] update ASSC algorithm

 - add support for real valued coefficients
 - switch from list to hash map structures for more efficient value searches

* [BE] update ASSC algorithm

 - devide pivot row by pivot element to avoid bad scaling

* [BE] fix ASSC zero check

 - allow a bigger margin for zero check (1e-12)
 - if pivot is 1.0 wo do not need to devide by it
 - update dumping

* [BE] do not have index reduction for jacobians

 - when matching jacobians do not allow index reduction
 - also prevents ASSC

* [testsuite] update assc testcase

* [testsuite] small updates for ASSC

* [testsuite] update fixes TSP_FourFlows3 model

* [BE] cleanup ASSC

 - remove legacy linear integer jacobian code
 - restructure and rename new linear jacobian to fit more neatly

* [testsuite] update data recon test properly
  • Loading branch information
kabdelhak committed Mar 30, 2021
1 parent 27f9326 commit 05d9e01
Show file tree
Hide file tree
Showing 11 changed files with 3,360 additions and 2,329 deletions.
15 changes: 0 additions & 15 deletions OMCompiler/Compiler/BackEnd/BackendDAE.mo
Expand Up @@ -34,7 +34,6 @@ encapsulated package BackendDAE
package: BackendDAE
description: BackendDAE contains the data-types used by the back end.
"

import Absyn;
import AvlSetPath;
import DAE;
Expand Down Expand Up @@ -808,20 +807,6 @@ constant SparsePattern emptySparsePattern = ({},{},({},{}),0);
public
type SparseColoring = list<list< .DAE.ComponentRef>>; // colouring

/*
Type only for transformation from analytical to structural singularity.
*/
type LinearIntegerJacobianRow = list<tuple<Integer, Integer>>; // Actual jacobian entries sparse, <column, value>
type LinearIntegerJacobianRhs = array<.DAE.Exp>; // RHS-Exp for full pivot algorithm. Replacement for eliminated equation.
type LinearIntegerJacobianIndices = array<tuple<Integer, Integer>>; // Index tuple <array, scalar> for equations

/*
The full linear integer matrix
- additional boolean array to track which rows have been changed
- additional boolean array to track which variables are matched to the equations
*/
type LinearIntegerJacobian = tuple<array<LinearIntegerJacobianRow>, LinearIntegerJacobianRhs, LinearIntegerJacobianIndices, array<Boolean>, array<Boolean>>;

public
uniontype DifferentiateInputData
record DIFFINPUTDATA
Expand Down
20 changes: 10 additions & 10 deletions OMCompiler/Compiler/BackEnd/BackendDAEUtil.mo
Expand Up @@ -8015,7 +8015,7 @@ algorithm
dae := preOptimizeDAE(inDAE, preOptModules);

// transformation phase (matching and sorting using a index reduction method
dae := causalizeDAE(dae, NONE(), matchingAlgorithm, daeHandler, true);
dae := causalizeDAE(dae, SOME((BackendDAE.NO_INDEX_REDUCTION(), BackendDAE.EXACT())), matchingAlgorithm, daeHandler, true);
execStat("causalizeDAE (first run)");
//fcall(Flags.DUMP_DAE_LOW, BackendDump.bltdump, ("bltdump", dae));

Expand Down Expand Up @@ -8124,7 +8124,7 @@ protected
list<tuple<BackendDAE.Equation, tuple<Integer, Integer>>> loopEqs = {}; /* scalar index needs to be list -- replace lookup with eqnIndexArray*/
list<tuple<BackendDAE.Var, Integer>> loopVars = {};
BackendDAE.Equation tmp_eq;
BackendDAE.LinearIntegerJacobian linIntJac;
SymbolicJacobian.LinearJacobian linJac;
algorithm
if listLength(comp) > 1 then
/* collect eqs and vars from strong component */
Expand All @@ -8143,27 +8143,27 @@ algorithm
loopVars := (BackendVariable.getVarAt(syst.orderedVars, ass1[eqnIndex]), ass1[eqnIndex]) :: loopVars;
end for;

if listLength(loopEqs) <= Flags.getConfigInt(Flags.MAX_SIZE_ASSC) then
if not listEmpty(loopEqs) and (listLength(loopEqs) <= Flags.getConfigInt(Flags.MAX_SIZE_ASSC)) then
try
/* generate linear integer sub jacobian from system */
linIntJac := SymbolicJacobian.generateLinearIntegerJacobian(loopEqs, loopVars, ass1);
linJac := SymbolicJacobian.LinearJacobian.generate(loopEqs, loopVars, ass1);

if not SymbolicJacobian.emptyOrSingleLinearIntegerJacobian(linIntJac) then
if not SymbolicJacobian.LinearJacobian.emptyOrSingle(linJac) then
if Flags.isSet(Flags.DUMP_ASSC) then
BackendDump.dumpLinearIntegerJacobianSparse(linIntJac, "Original");
print(SymbolicJacobian.LinearJacobian.toString(linJac, "Original"));
end if;

/* solve jacobian with gaussian elimination */
linIntJac := SymbolicJacobian.solveLinearIntegerJacobian(linIntJac);
linJac := SymbolicJacobian.LinearJacobian.solve(linJac);
if Flags.isSet(Flags.DUMP_ASSC) then
BackendDump.dumpLinearIntegerJacobianSparse(linIntJac, "Solved");
print(SymbolicJacobian.LinearJacobian.toString(linJac, "Solved"));
end if;

/* set changed to true if it was true before, or any row changed in the jacobian */
changed := changed or SymbolicJacobian.anyRowChanged(linIntJac);
changed := changed or SymbolicJacobian.LinearJacobian.anyChanges(linJac);

/* resolve zero rows to new equations and update assignments / adjacency matrix */
(ass1, ass2, syst) := SymbolicJacobian.resolveAnalyticalSingularities(linIntJac, ass1, ass2, syst);
(ass1, ass2, syst) := SymbolicJacobian.LinearJacobian.resolveASSC(linJac, ass1, ass2, syst);
end if;
else
/* possibly fails if jacobian is empty --- nothing to do */
Expand Down
41 changes: 0 additions & 41 deletions OMCompiler/Compiler/BackEnd/BackendDump.mo
Expand Up @@ -2460,47 +2460,6 @@ algorithm
end match;
end symJacString;

public function dumpLinearIntegerJacobianSparse
input BackendDAE.LinearIntegerJacobian linIntJac;
input String heading = "";
protected
array<BackendDAE.LinearIntegerJacobianRow> rowArr;
BackendDAE.LinearIntegerJacobianRhs rhsArr;
BackendDAE.LinearIntegerJacobianIndices idxArr;
array<Boolean> boolArr, matchedVarsArr;
algorithm
(rowArr, rhsArr, idxArr, boolArr, matchedVarsArr) := linIntJac;
print("######################################################\n" +
" LinearIntegerJacobian sparsity pattern: " + heading + "\n" +
"######################################################\n" +
"(scal_idx|arr_idx|changed) [var_index, value] || RHS_EXPRESSION\n");
for idx in 1:arrayLength(rowArr) loop
dumpLinearIntegerJacobianSparseRow(rowArr[idx], rhsArr[idx], idxArr[idx], boolArr[idx]);
end for;
print("\n");
end dumpLinearIntegerJacobianSparse;

protected function dumpLinearIntegerJacobianSparseRow
input BackendDAE.LinearIntegerJacobianRow linIntJacRow;
input DAE.Exp rhs;
input tuple<Integer, Integer> indices;
input Boolean changed;
protected
Integer i_arr, i_scal, index, value;
algorithm
(i_arr, i_scal) := indices;
print("(" + intString(i_arr) + "|" + intString(i_scal) + "|" + boolString(changed) +"): ");
if listLength(linIntJacRow) < 1 then
print("EMPTY ROW ");
else
for element in linIntJacRow loop
(index, value) := element;
print("[" + intString(index) + "|" + intString(value) + "] ");
end for;
end if;
print(" || RHS: " + ExpressionDump.printExpStr(rhs) + "\n");
end dumpLinearIntegerJacobianSparseRow;

public function dumpEqnsStr
"Helper function to dump."
input list<BackendDAE.Equation> eqns;
Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/BackEnd/Matching.mo
Expand Up @@ -5637,7 +5637,7 @@ algorithm
syst := isyst;

/* check if index type is solvable and is unprocessed and if index reduction is activated */
if not Flags.getConfigBool(Flags.NO_ASSC) and BackendDAEUtil.hasIndexTypeSolvableAndUnprocessedScalar(syst) and BackendDAEUtil.doIndexReduction(inMatchingOptions) then
if (not Flags.getConfigBool(Flags.NO_ASSC)) and BackendDAEUtil.hasIndexTypeSolvableAndUnprocessedScalar(syst) and BackendDAEUtil.doIndexReduction(inMatchingOptions) then
/* set the system to processed so that it gets analyzed only once */
syst := BackendDAEUtil.setAnalyticalToStructuralProcessed(syst, true);

Expand Down

0 comments on commit 05d9e01

Please sign in to comment.