OMCompiler/Compiler/BackEnd/AdjacencyMatrix.mo
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of OpenModelica. | ||
| 3 | * | ||
| 4 | * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), | ||
| 5 | * c/o Linköpings universitet, Department of Computer and Information Science, | ||
| 6 | * SE-58183 Linköping, Sweden. | ||
| 7 | * | ||
| 8 | * All rights reserved. | ||
| 9 | * | ||
| 10 | * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR | ||
| 11 | * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. | ||
| 12 | * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES | ||
| 13 | * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL | ||
| 14 | * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. | ||
| 15 | * | ||
| 16 | * The OpenModelica software and the OSMC (Open Source Modelica Consortium) | ||
| 17 | * Public License (OSMC-PL) are obtained from OSMC, either from the above | ||
| 18 | * address, from the URLs: | ||
| 19 | * http://www.openmodelica.org or | ||
| 20 | * https://github.com/OpenModelica/ or | ||
| 21 | * http://www.ida.liu.se/projects/OpenModelica, | ||
| 22 | * and in the OpenModelica distribution. | ||
| 23 | * | ||
| 24 | * GNU AGPL version 3 is obtained from: | ||
| 25 | * https://www.gnu.org/licenses/licenses.html#GPL | ||
| 26 | * | ||
| 27 | * This program is distributed WITHOUT ANY WARRANTY; without | ||
| 28 | * even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 29 | * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH | ||
| 30 | * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. | ||
| 31 | * | ||
| 32 | * See the full OSMC Public License conditions for more details. | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | encapsulated package AdjacencyMatrix | ||
| 37 | |||
| 38 | import BackendDAE; | ||
| 39 | |||
| 40 | protected | ||
| 41 | import Array; | ||
| 42 | import Debug; | ||
| 43 | import Flags; | ||
| 44 | import List; | ||
| 45 | import MetaModelica.Dangerous; | ||
| 46 | |||
| 47 | public function copyAdjacencyMatrix | ||
| 48 | input Option<BackendDAE.AdjacencyMatrix> inAdjacencyMatrix; | ||
| 49 | output Option<BackendDAE.AdjacencyMatrix> outAdjacencyMatrix; | ||
| 50 | algorithm | ||
| 51 | outAdjacencyMatrix := match inAdjacencyMatrix | ||
| 52 | local | ||
| 53 | BackendDAE.AdjacencyMatrix m; | ||
| 54 | |||
| 55 | case SOME(m) algorithm | ||
| 56 | 40200 | m := arrayCopy(m); | |
| 57 | then SOME(m); | ||
| 58 | |||
| 59 | else NONE(); | ||
| 60 | end match; | ||
| 61 | end copyAdjacencyMatrix; | ||
| 62 | |||
| 63 | public function copyAdjacencyMatrixT = copyAdjacencyMatrix; | ||
| 64 | |||
| 65 | public function traverseAdjacencyMatrix<T> | ||
| 66 | input BackendDAE.AdjacencyMatrix inM; | ||
| 67 | input FuncType func; | ||
| 68 | input T inTypeA; | ||
| 69 | output BackendDAE.AdjacencyMatrix outM; | ||
| 70 | output T outTypeA; | ||
| 71 | partial function FuncType | ||
| 72 | input BackendDAE.AdjacencyMatrixElement elem; | ||
| 73 | input Integer pos; | ||
| 74 | input T inTpl; | ||
| 75 | output list<Integer> outList; | ||
| 76 | output T outTpl; | ||
| 77 | end FuncType; | ||
| 78 | algorithm | ||
| 79 | ✗ | (outM, outTypeA) := traverseAdjacencyMatrix1(inM, func, 1, arrayLength(inM), inTypeA); | |
| 80 | end traverseAdjacencyMatrix; | ||
| 81 | |||
| 82 | protected function traverseAdjacencyMatrix1<T> | ||
| 83 | input BackendDAE.AdjacencyMatrix inM; | ||
| 84 | input FuncType func; | ||
| 85 | input Integer pos "iterated 1..len"; | ||
| 86 | input Integer len "length of array"; | ||
| 87 | input T inTypeA; | ||
| 88 | output BackendDAE.AdjacencyMatrix outM; | ||
| 89 | output T outTypeA; | ||
| 90 | partial function FuncType | ||
| 91 | input BackendDAE.AdjacencyMatrixElement elem; | ||
| 92 | input Integer pos; | ||
| 93 | input T inTpl; | ||
| 94 | output list<Integer> outList; | ||
| 95 | output T outTpl; | ||
| 96 | end FuncType; | ||
| 97 | algorithm | ||
| 98 | ✗ | (outM, outTypeA) := traverseAdjacencyMatrix2(inM, func, pos, len, intGt(pos, len), inTypeA); | |
| 99 | annotation(__OpenModelica_EarlyInline = true); | ||
| 100 | end traverseAdjacencyMatrix1; | ||
| 101 | |||
| 102 | protected function traverseAdjacencyMatrix2<T> | ||
| 103 | input BackendDAE.AdjacencyMatrix inM; | ||
| 104 | input FuncType func; | ||
| 105 | input Integer pos "iterated 1..len"; | ||
| 106 | input Integer len "length of array"; | ||
| 107 | input Boolean stop; | ||
| 108 | input T inTypeA; | ||
| 109 | output BackendDAE.AdjacencyMatrix outM; | ||
| 110 | output T outTypeA; | ||
| 111 | partial function FuncType | ||
| 112 | input BackendDAE.AdjacencyMatrixElement elem; | ||
| 113 | input Integer pos; | ||
| 114 | input T inTpl; | ||
| 115 | output list<Integer> outList; | ||
| 116 | output T outTpl; | ||
| 117 | end FuncType; | ||
| 118 | algorithm | ||
| 119 | (outM, outTypeA) := match stop | ||
| 120 | local | ||
| 121 | BackendDAE.AdjacencyMatrix m1, m2; | ||
| 122 | T extArg, extArg1, extArg2; | ||
| 123 | list<Integer> eqns, eqns1; | ||
| 124 | |||
| 125 | case true | ||
| 126 | then (inM, inTypeA); | ||
| 127 | |||
| 128 | case false algorithm | ||
| 129 | ✗ | (eqns, extArg) := func(inM[pos], pos, inTypeA); | |
| 130 | ✗ | eqns1 := List.removeOnTrue(pos, intLt, eqns); | |
| 131 | ✗ | (m1, extArg1) := traverseAdjacencyMatrixList(eqns1, inM, func, arrayLength(inM), pos, extArg); | |
| 132 | ✗ | (m2, extArg2) := traverseAdjacencyMatrix2(m1, func, pos+1, len, intGt(pos+1, len), extArg1); | |
| 133 | then (m2, extArg2); | ||
| 134 | end match; | ||
| 135 | end traverseAdjacencyMatrix2; | ||
| 136 | |||
| 137 | protected function traverseAdjacencyMatrixList<T> | ||
| 138 | input list<Integer> inLst "elements to traverse"; | ||
| 139 | input BackendDAE.AdjacencyMatrix inM; | ||
| 140 | input FuncType func; | ||
| 141 | input Integer len "length of array"; | ||
| 142 | input Integer maxpos "do not go further than this position"; | ||
| 143 | input T inTypeA; | ||
| 144 | output BackendDAE.AdjacencyMatrix outM; | ||
| 145 | output T outTypeA; | ||
| 146 | partial function FuncType | ||
| 147 | input BackendDAE.AdjacencyMatrixElement elem; | ||
| 148 | input Integer pos; | ||
| 149 | input T inTpl; | ||
| 150 | output list<Integer> outList; | ||
| 151 | output T outTpl; | ||
| 152 | end FuncType; | ||
| 153 | algorithm | ||
| 154 | (outM, outTypeA) := matchcontinue inLst | ||
| 155 | local | ||
| 156 | BackendDAE.AdjacencyMatrix m; | ||
| 157 | T extArg, extArg1; | ||
| 158 | list<Integer> rest, eqns, eqns1, alleqns; | ||
| 159 | Integer pos; | ||
| 160 | |||
| 161 | case {} | ||
| 162 | ✗ | then (inM, inTypeA); | |
| 163 | |||
| 164 | case pos::rest algorithm | ||
| 165 | // do not leave the list | ||
| 166 | ✗ | true := intLt(pos, len+1); | |
| 167 | // do not more than necesary | ||
| 168 | ✗ | true := intLt(pos, maxpos); | |
| 169 | ✗ | (eqns, extArg) := func(inM[pos], pos, inTypeA); | |
| 170 | ✗ | eqns1 := List.removeOnTrue(maxpos, intLt, eqns); | |
| 171 | ✗ | alleqns := List.unionOnTrueList({rest, eqns1}, intEq); | |
| 172 | ✗ | (m, extArg1) := traverseAdjacencyMatrixList(alleqns, inM, func, len, maxpos, extArg); | |
| 173 | then (m, extArg1); | ||
| 174 | |||
| 175 | case pos::rest algorithm | ||
| 176 | // do not leave the list | ||
| 177 | ✗ | true := intLt(pos, len+1); | |
| 178 | ✗ | (m, extArg) := traverseAdjacencyMatrixList(rest, inM, func, len, maxpos, inTypeA); | |
| 179 | then (m, extArg); | ||
| 180 | |||
| 181 | else algorithm | ||
| 182 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 183 | ✗ | Debug.trace("- BackendDAEOptimize.traverseAdjacencyMatrixList failed\n"); | |
| 184 | ✗ | then fail(); | |
| 185 | end matchcontinue; | ||
| 186 | end traverseAdjacencyMatrixList; | ||
| 187 | |||
| 188 | public function getOtherEqSysAdjacencyMatrix | ||
| 189 | "This function removes tvar and res from adjacency matrix." | ||
| 190 | input BackendDAE.AdjacencyMatrix m; | ||
| 191 | input Integer size; | ||
| 192 | input Integer index; | ||
| 193 | input array<Integer> skip; | ||
| 194 | input array<Integer> rowskip; | ||
| 195 | input BackendDAE.AdjacencyMatrix mnew; | ||
| 196 | output BackendDAE.AdjacencyMatrix outMNew; | ||
| 197 | algorithm | ||
| 198 | outMNew := match m | ||
| 199 | local | ||
| 200 | list<Integer> row; | ||
| 201 | |||
| 202 | case _ guard intGt(index, size) | ||
| 203 | then mnew; | ||
| 204 | |||
| 205 | case _ guard intGt(skip[index], 0) | ||
| 206 | algorithm | ||
| 207 |
8/8✓ Branch 1 taken 1016 times.
✓ Branch 2 taken 6 times.
✓ Branch 4 taken 218 times.
✓ Branch 5 taken 798 times.
✓ Branch 6 taken 1022 times.
✓ Branch 7 taken 414 times.
✓ Branch 8 taken 798 times.
✓ Branch 9 taken 414 times.
|
1436 | row := list(r for r guard intGt(r,0) and intGt(rowskip[r], 0) in m[index]); |
| 208 | 414 | arrayUpdate(mnew, index, row); | |
| 209 | 414 | then getOtherEqSysAdjacencyMatrix(m, size, index+1, skip, rowskip, mnew); | |
| 210 | |||
| 211 | case _ algorithm | ||
| 212 | 128 | arrayUpdate(mnew,index,{}); | |
| 213 | 128 | then getOtherEqSysAdjacencyMatrix(m, size, index+1, skip, rowskip, mnew); | |
| 214 | end match; | ||
| 215 | end getOtherEqSysAdjacencyMatrix; | ||
| 216 | |||
| 217 | protected function isAssigned | ||
| 218 | input array<Integer> ass; | ||
| 219 | input Integer i; | ||
| 220 | output Boolean b; | ||
| 221 | algorithm | ||
| 222 | ✗ | b := intGt(ass[i], 0); | |
| 223 | end isAssigned; | ||
| 224 | |||
| 225 | public function transposeAdjacencyMatrix | ||
| 226 | "Calculates the transpose of the adjacency matrix, | ||
| 227 | i.e. which equations each variable is present in." | ||
| 228 | input BackendDAE.AdjacencyMatrix m; | ||
| 229 | input Integer nRowsMt; | ||
| 230 | output BackendDAE.AdjacencyMatrixT mt; | ||
| 231 | protected | ||
| 232 | Integer i = 1; | ||
| 233 | algorithm | ||
| 234 | 2577 | mt := arrayCreate(nRowsMt, {}); | |
| 235 |
2/2✓ Branch 1 taken 1579814 times.
✓ Branch 2 taken 2577 times.
|
1582391 | for e in m loop |
| 236 | 1579814 | (mt, i) := transposeRow(e, mt, i); | |
| 237 | end for; | ||
| 238 | end transposeAdjacencyMatrix; | ||
| 239 | |||
| 240 | protected function transposeRow "author: PA | ||
| 241 | Helper function to transposeMatrix2. | ||
| 242 | Input: BackendDAE.AdjacencyMatrix (eqn => var) | ||
| 243 | Input: row number (variable) | ||
| 244 | Input: iterator (start with one) | ||
| 245 | inputs: (int list list, int /* row */,int /* iter */) | ||
| 246 | outputs: int list" | ||
| 247 | input list<Integer> row; | ||
| 248 | input output BackendDAE.AdjacencyMatrixT mt; | ||
| 249 | input output Integer indx; | ||
| 250 | algorithm | ||
| 251 | (mt, indx) := match row | ||
| 252 | local | ||
| 253 | Integer i, indx1, iabs; | ||
| 254 | list<Integer> res, col; | ||
| 255 | |||
| 256 | case {} | ||
| 257 |
1/2✓ Branch 0 taken 1579814 times.
✗ Branch 1 not taken.
|
1579814 | then (mt, indx+1); |
| 258 | |||
| 259 | case i::res algorithm | ||
| 260 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2627826 times.
|
2627826 | iabs := intAbs(i); |
| 261 | 2627826 | mt := Array.expand(iabs - arrayLength(mt), mt, {}); | |
| 262 | 2627826 | col := mt[iabs]; | |
| 263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2627826 times.
|
2627826 | indx1 := if intLt(i, 0) then -indx else indx; |
| 264 | 2627826 | arrayUpdate(mt, iabs, indx1::col); | |
| 265 | 2627826 | then transposeRow(res, mt, indx); | |
| 266 | end match; | ||
| 267 | end transposeRow; | ||
| 268 | |||
| 269 | public function absAdjacencyMatrix "author: PA | ||
| 270 | Applies absolute value to all entries in the adjacency matrix. | ||
| 271 | This can be used when e.g. der(x) and x are considered the same variable." | ||
| 272 | input BackendDAE.AdjacencyMatrix m; | ||
| 273 | output BackendDAE.AdjacencyMatrix res; | ||
| 274 | protected | ||
| 275 | Integer i = 1; | ||
| 276 | Integer minn; | ||
| 277 | algorithm | ||
| 278 | 123176 | res := Dangerous.arrayCreateNoInit(arrayLength(m),{}); | |
| 279 |
2/2✓ Branch 1 taken 925676 times.
✓ Branch 2 taken 123176 times.
|
1048852 | for v in m loop |
| 280 | 925676 | minn := List.fold(v,intMin,0); | |
| 281 |
2/2✓ Branch 0 taken 87479 times.
✓ Branch 1 taken 838197 times.
|
925676 | if minn < 0 then |
| 282 | 87479 | Dangerous.arrayUpdateNoBoundsChecking(res, i, List.map(v,intAbs)); | |
| 283 | else | ||
| 284 | Dangerous.arrayUpdateNoBoundsChecking(res, i, v); | ||
| 285 | end if; | ||
| 286 | 925676 | i := i+1; | |
| 287 | end for; | ||
| 288 | end absAdjacencyMatrix; | ||
| 289 | |||
| 290 | public function isEmpty | ||
| 291 | input BackendDAE.AdjacencyMatrix m; | ||
| 292 | output Boolean b = true; | ||
| 293 | algorithm | ||
| 294 |
2/2✓ Branch 1 taken 52 times.
✓ Branch 2 taken 1 time.
|
53 | for element in m loop |
| 295 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
|
52 | if not listEmpty(element) then |
| 296 | b := false; | ||
| 297 | ✗ | return; | |
| 298 | end if; | ||
| 299 | end for; | ||
| 300 | end isEmpty; | ||
| 301 | |||
| 302 | annotation(__OpenModelica_Interface="backend"); | ||
| 303 | end AdjacencyMatrix; | ||
| 304 |