Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 28.8% 422 / 0 / 1466
Functions: -% 0 / 1 / 1
Branches: 28.0% 235 / 0 / 840

OMCompiler/Compiler/BackEnd/Matching.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 Matching
37 " file: Matching.mo
38 package: Matching
39 description: Matching contains functions for matching algorithms"
40
41
42
43 import BackendDAE;
44 import BackendDAEFunc;
45 import DAE;
46
47 protected
48
49 import Absyn;
50 import Array;
51 import BackendDAEEXT;
52 import BackendDAEUtil;
53 import BackendDump;
54 import BackendEquation;
55 import BackendVariable;
56 import ClockIndexes;
57 import Config;
58 import Debug;
59 import Differentiate;
60 import DumpGraphML;
61 import ElementSource;
62 import Error;
63 import Ceval;
64 import Expression;
65 import Flags;
66 import IndexReduction;
67 import Inline;
68 import List;
69 import MetaModelica.Dangerous;
70 import UnorderedMap;
71 import UnorderedSet;
72 import Util;
73 import Sorting;
74 import System;
75 protected import ComponentReferenceBasics;
76
77 // =============================================================================
78 // just a matching algorithm
79 // - PerfectMatching
80 // - RegularMatching
81 //
82 // =============================================================================
83
84 public function PerfectMatching "
85 This function fails if there is no perfect matching for the given system."
86 input BackendDAE.AdjacencyMatrix m;
87 output array<Integer> ass1 "eqn := ass1[var]";
88 output array<Integer> ass2 "var := ass2[eqn]";
89 protected
90 Integer N = arrayLength(m);
91 algorithm
92 2018 ass1 := arrayCreate(N, -1);
93 2018 ass2 := arrayCreate(N, -1);
94
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2018 times.
✓ Branch 4 taken 2018 times.
✗ Branch 5 not taken.
2018 (ass1, ass2, true, _, _) := ContinueMatching(m, N, N, ass1, ass2, true);
95 end PerfectMatching;
96
97 public function RegularMatching "
98 This function returns at least a partial matching for singular systems, starting from scratch.
99 Unmatched nodes are represented by -1. The eMark and vMark vectors are only relevant if
100 perfectMatching = false."
101 input BackendDAE.AdjacencyMatrix m;
102 input Integer nVars;
103 input Integer nEqns;
104 output array<Integer> ass1 "eqn := ass1[var]";
105 output array<Integer> ass2 "var := ass2[eqn]";
106 output Boolean perfectMatching;
107 output array<Boolean> eMark "equations contained in the minimal structurally singular subset";
108 output array<Boolean> vMark "variables contained in the minimal structurally singular subset";
109 algorithm
110 48069 ass1 := arrayCreate(nVars, -1);
111 48069 ass2 := arrayCreate(nEqns, -1);
112 48069 (ass1, ass2, perfectMatching, eMark, vMark) := ContinueMatching(m, nVars, nEqns, ass1, ass2, false);
113 end RegularMatching;
114
115 public function ContinueMatching "
116 This function returns at least a partial matching for singular systems.
117 Unmatched nodes are represented by -1."
118 input BackendDAE.AdjacencyMatrix m;
119 input Integer nVars;
120 input Integer nEqns;
121 input output array<Integer> ass1 "eqn := ass1[var]";
122 input output array<Integer> ass2 "var := ass2[eqn]";
123 input Boolean stopAtSingularity = false;
124 output Boolean perfectMatching = true;
125 output array<Boolean> eMark;
126 output array<Boolean> vMark;
127 protected
128 Integer i, j;
129 array<Integer> eMarkIx, vMarkIx;
130 Integer eMarkN=0, vMarkN=0, eDead=0, vDead=0;
131 Boolean success;
132 algorithm
133 97627 vMark := arrayCreate(nVars, false);
134 97627 eMark := arrayCreate(nEqns, false);
135 97627 vMarkIx := arrayCreate(nVars, 0);
136 97627 eMarkIx := arrayCreate(nEqns, 0);
137
138 i := 1;
139
2/2
✓ Branch 0 taken 655996 times.
✓ Branch 1 taken 97627 times.
753623 while i <= nEqns loop
140 655996 j := ass2[i];
141
3/4
✓ Branch 0 taken 73080 times.
✓ Branch 1 taken 582916 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73080 times.
655996 if not (j>0 and ass1[j] == i) then
142 // What a failed search visited is closed under alternating paths, so it
143 // stays marked and later searches skip it.
144 582916 (success, eMarkN, vMarkN) := BBPathFound(i, m, eMark, vMark, ass1, ass2, eMarkIx, vMarkIx, eDead, vDead);
145
2/2
✓ Branch 0 taken 522322 times.
✓ Branch 1 taken 60594 times.
582916 if success then
146 522322 clearMarks(eMark, eMarkIx, eDead, eMarkN);
147 522322 clearMarks(vMark, vMarkIx, vDead, vMarkN);
148 else
149 perfectMatching := false;
150 60594 eDead := eMarkN;
151 60594 vDead := vMarkN;
152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60594 times.
60594 if stopAtSingularity then
153 ✗ return;
154 end if;
155 end if;
156 end if;
157 655996 i := i+1;
158 end while;
159 end ContinueMatching;
160
161 protected function clearMarks "Sets arr[arrIx[from+1:to]] to false"
162 input array<Boolean> arr;
163 input array<Integer> arrIx;
164 input Integer from, to;
165 algorithm
166
2/2
✓ Branch 0 taken 489923 times.
✓ Branch 1 taken 554721 times.
2603476 for i in from+1:to loop
167 1558832 arrayUpdate(arr, arrIx[i], false);
168 end for;
169 end clearMarks;
170
171 public function BBMatching
172 input BackendDAE.EqSystem inSys;
173 input BackendDAE.Shared inShared;
174 input Boolean clearMatching;
175 input BackendDAE.MatchingOptions inMatchingOptions;
176 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
177 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
178 output BackendDAE.EqSystem outSys = inSys;
179 output BackendDAE.Shared outShared = inShared;
180 output BackendDAE.StructurallySingularSystemHandlerArg outArg = inArg;
181 protected
182 Integer i;
183 Boolean success = true;
184 BackendDAE.AdjacencyMatrix m;
185 Integer nVars, nEqns, j;
186 array<Integer> ass1, ass2;
187 array<Boolean> eMark, vMark;
188 array<Integer> eMarkIx, vMarkIx;
189 Integer eMarkN=0, vMarkN=0;
190 list<Integer> mEqns;
191 algorithm
192 //BackendDAE.EQSYSTEM(m=SOME(m), matching=BackendDAE.MATCHING(ass1=ass1, ass2=ass2)) := outSys;
193 ✗ SOME(m) := outSys.m;
194 ✗ nEqns := BackendDAEUtil.systemSize(outSys);
195 ✗ nVars := BackendVariable.daenumVariables(outSys);
196 // Be carefull, since matching may have been generated with not distinguishing between
197 // state and their derivative, which leads to wrong traversing of bibartite graph!!!!
198 //(ass1, ass2) := getAssignment(clearMatching, nVars, nEqns, inSys);
199 //if clearMatching then
200 ✗ ass2 := arrayCreate(nEqns, -1);
201 ✗ ass1 := arrayCreate(nVars, -1);
202 //BBCheapMatching(nEqns, m, ass1, ass2);
203 //end if;
204 ✗ vMark := arrayCreate(nVars, false);
205 ✗ eMark := arrayCreate(nEqns, false);
206 ✗ vMarkIx := arrayCreate(nVars, 0);
207 ✗ eMarkIx := arrayCreate(nEqns, 0);
208 i := 1;
209 ✗ while i <= nEqns and success loop
210 ✗ j := ass2[i];
211 ✗ if ((j>0) and ass1[j] == i) then
212 success :=true;
213 else
214 ✗ clearArrayWithKnownSetIndexes(eMark, eMarkIx, eMarkN);
215 ✗ clearArrayWithKnownSetIndexes(vMark, vMarkIx, vMarkN);
216 ✗ (success,eMarkN,vMarkN) := BBPathFound(i, m, eMark, vMark, ass1, ass2, eMarkIx, vMarkIx, 0, 0);
217 ✗ if not success then
218 mEqns := {};
219 ✗ for j in 1:nEqns loop
220 ✗ if eMark[j] then
221 mEqns:=j::mEqns;
222 end if;
223 end for;
224 ✗ (_, i, outSys, outShared, ass1, ass2, outArg) := sssHandler({mEqns}, i, outSys, outShared, ass1, ass2, outArg);
225 ✗ SOME(m) := outSys.m;
226 //nEqns := BackendDAEUtil.systemSize(outSys);
227 //nVars := BackendVariable.daenumVariables(outSys);
228 //ass1 := assignmentsArrayExpand(ass1, nVars, arrayLength(ass1), -1);
229 //ass2 := assignmentsArrayExpand(ass2, nEqns, arrayLength(ass2), -1);
230 //vMark := assignmentsArrayBooleanExpand(vMark, nVars, arrayLength(vMark), false);
231 //eMark := assignmentsArrayBooleanExpand(eMark, nEqns, arrayLength(eMark), false);
232 success := true;
233 ✗ i := i-1;
234 end if;
235 end if;
236 ✗ i := i+1;
237 end while;
238 if success then
239 ✗ outSys := BackendDAEUtil.setEqSystMatching(outSys, BackendDAE.MATCHING(ass1, ass2, {}));
240 else
241 print("\nSingular System!!!\n");
242 end if;
243 end BBMatching;
244
245 protected function BBPathFound
246 "Searches an augmenting path starting at equation i."
247 input Integer i;
248 input BackendDAE.AdjacencyMatrix m;
249 input array<Boolean> eMark;
250 input array<Boolean> vMark;
251 input array<Integer> ass1 "eqn := ass1[var]";
252 input array<Integer> ass2 "var := ass2[eqn]";
253 input array<Integer> eMarkIx;
254 input array<Integer> vMarkIx;
255 output Boolean success=false;
256 input output Integer eMarkN, vMarkN;
257 protected
258 list<tuple<Integer, Integer, list<Integer>>> stack = {} "(eqn, var descended through, vars left to try)";
259 list<Integer> vars = {};
260 Integer eqn = i, var, parent;
261 Boolean enter = true, descended;
262 algorithm
263 while true loop
264
2/2
✓ Branch 0 taken 1167537 times.
✓ Branch 1 taken 412601 times.
1580138 if enter then
265 enter := false;
266 vars := {};
267
1/2
✓ Branch 1 taken 1167537 times.
✗ Branch 2 not taken.
1167537 if not arrayGet(eMark, eqn) then
268 1167537 arrayUpdate(eMark, eqn, true);
269 1167537 eMarkN := eMarkN+1;
270 1167537 arrayUpdate(eMarkIx, eMarkN, eqn);
271
272
2/2
✓ Branch 1 taken 3013677 times.
✓ Branch 2 taken 645215 times.
3658892 for j in m[eqn] loop
273 // negative entries in adjacence matrix belong to states!!!
274
3/4
✓ Branch 0 taken 3013677 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 522322 times.
✓ Branch 4 taken 2491355 times.
3013677 if (j>0 and ass1[j] <= 0) then
275 success := true;
276 522322 arrayUpdate(ass1, j, eqn);
277 522322 arrayUpdate(ass2, eqn, j);
278 break;
279 end if;
280 end for;
281
282 if success then
283
2/2
✓ Branch 0 taken 172020 times.
✓ Branch 1 taken 522322 times.
694342 for frame in stack loop
284 172020 (parent, var, _) := frame;
285 172020 arrayUpdate(ass1, var, parent);
286 172020 arrayUpdate(ass2, parent, var);
287 end for;
288 522322 return;
289 end if;
290 vars := m[eqn];
291 end if;
292 end if;
293
294 descended := false;
295
2/2
✓ Branch 0 taken 1905515 times.
✓ Branch 1 taken 473195 times.
2378710 while not listEmpty(vars) loop
296 1905515 var::vars := vars;
297 // negative entries in adjacence matrix belong to states!!!
298
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1905515 times.
✓ Branch 3 taken 1320894 times.
✓ Branch 4 taken 584621 times.
1905515 if (var>0 and not vMark[var]) then
299 584621 arrayUpdate(vMark, var, true);
300 584621 vMarkN := vMarkN+1;
301 584621 arrayUpdate(vMarkIx, vMarkN, var);
302 584621 stack := (eqn, var, vars)::stack;
303 584621 eqn := ass1[var];
304 enter := true;
305 descended := true;
306 584621 break;
307 end if;
308 end while;
309
310
2/2
✓ Branch 0 taken 584621 times.
✓ Branch 1 taken 473195 times.
1057816 if not descended then
311
2/2
✓ Branch 0 taken 60594 times.
✓ Branch 1 taken 412601 times.
473195 if listEmpty(stack) then
312 60594 return;
313 end if;
314 412601 (eqn, _, vars)::stack := stack;
315 end if;
316 end while;
317 end BBPathFound;
318
319 protected function BBCheapMatching
320 input Integer nEqns;
321 input BackendDAE.AdjacencyMatrix m;
322 input array<Integer> ass1 "eqn := ass1[var]";
323 input array<Integer> ass2 "var := ass2[eqn]";
324 protected
325 Integer i, j;
326 Boolean success=false;
327 list<Integer> vars;
328 algorithm
329 ✗ for i in 1:nEqns loop
330 ✗ vars := m[i];
331 ✗ while not success and not listEmpty(vars) loop
332 ✗ j::vars := vars;
333 // negative entries in adjacence matrix belong to states!!!
334 ✗ if (j>0 and ass1[j] <= 0) then
335 success := true;
336 ✗ arrayUpdate(ass1, j, i);
337 ✗ arrayUpdate(ass2, i, j);
338 end if;
339 end while;
340 end for;
341 end BBCheapMatching;
342
343 public function invertMatching "author: lochel
344 ass1 <-> ass2"
345 input array<Integer> inAss;
346 output array<Integer> outAss;
347 protected
348 Integer N = arrayLength(inAss);
349 Integer j;
350 algorithm
351 ✗ outAss := arrayCreate(N, -1);
352 ✗ for i in 1:N loop
353 ✗ j := inAss[i];
354 ✗ if j > 0 then
355 ✗ outAss[inAss[i]] := i;
356 end if;
357 end for;
358 end invertMatching;
359
360 // =============================================================================
361 // Matching Algorithms
362 //
363 // =============================================================================
364
365 public function DFSLH
366 "depth first search with look ahead feature. basically the same like MC21A."
367 input BackendDAE.EqSystem isyst;
368 input BackendDAE.Shared ishared;
369 input Boolean clearMatching;
370 input BackendDAE.MatchingOptions inMatchingOptions;
371 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
372 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
373 output BackendDAE.EqSystem osyst;
374 output BackendDAE.Shared oshared;
375 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
376 algorithm
377 (osyst,oshared,outArg) :=
378 matchcontinue isyst
379 local
380 Integer nvars,neqns;
381 array<Integer> vec1,vec2,emark,vmark;
382 BackendDAE.StructurallySingularSystemHandlerArg arg;
383 BackendDAE.EqSystem syst;
384 BackendDAE.Shared shared;
385 BackendDAE.AdjacencyMatrix m;
386 BackendDAE.AdjacencyMatrixT mt;
387
388 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
389 algorithm
390 ✗ neqns := BackendDAEUtil.systemSize(isyst);
391 ✗ nvars := BackendVariable.daenumVariables(isyst);
392 ✗ true := intGt(nvars,0);
393 ✗ true := intGt(neqns,0);
394 ✗ vmark := arrayCreate(nvars,-1);
395 ✗ emark := arrayCreate(neqns,-1);
396 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
397 ✗ cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,false);
398 ✗ (vec1,vec2,syst,shared,arg) := DFSLH2(isyst,ishared,nvars,neqns,1,emark,vmark,vec1,vec2,inMatchingOptions,sssHandler,inArg);
399 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec1,vec2,{}));
400 ✗ then
401 (syst,shared,arg);
402 // fail case if system is empty
403 case _
404 algorithm
405 ✗ neqns := BackendDAEUtil.systemSize(isyst);
406 ✗ nvars := BackendVariable.daenumVariables(isyst);
407 ✗ false := intGt(nvars,0);
408 ✗ false := intGt(neqns,0);
409 ✗ vec1 := listArray({});
410 ✗ vec2 := listArray({});
411 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
412 then
413 (syst,ishared,inArg);
414 else
415 algorithm
416 ✗ if Flags.isSet(Flags.FAILTRACE) then
417 ✗ Debug.trace("- Matching.DFSLH failed\n");
418 end if;
419 ✗ then
420 fail();
421 end matchcontinue;
422 end DFSLH;
423
424 protected function DFSLH2
425 "author: PA
426 This is the outer loop of the matching algorithm
427 The find_path algorithm is called for each equation/variable.
428 inputs: (BackendDAE,AdjacencyMatrix, AdjacencyMatrixT
429 ,int /* number of vars */
430 ,int /* number of eqns */
431 ,int /* current var */
432 ,Assignments /* assignments, array of eqn indices */
433 ,Assignments /* assignments, array of var indices */
434 ,MatchingOptions) /* options for matching alg. */
435 outputs: (Assignments, /* assignments, array of equation indices */
436 Assignments, /* assignments, list of variable indices */
437 BackendDAE, BackendDAE.AdjacencyMatrix, AdjacencyMatrixT)"
438 input BackendDAE.EqSystem isyst;
439 input BackendDAE.Shared ishared;
440 input Integer nv;
441 input Integer nf;
442 input Integer i;
443 input array<Integer> emark;
444 input array<Integer> vmark;
445 input array<Integer> ass1 "eqn := ass1[var]";
446 input array<Integer> ass2 "var := ass2[eqn]";
447 input BackendDAE.MatchingOptions match_opts;
448 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
449 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
450 output array<Integer> outAssignments1;
451 output array<Integer> outAssignments2;
452 output BackendDAE.EqSystem osyst;
453 output BackendDAE.Shared oshared;
454 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
455 algorithm
456 (outAssignments1,outAssignments2,osyst,oshared,outArg):=
457 matchcontinue (isyst, match_opts)
458 local
459 array<Integer> ass1_1,ass2_1,ass1_2,ass2_2,ass1_3,ass2_3,emark1,vmark1;
460 BackendDAE.AdjacencyMatrix m;
461 BackendDAE.AdjacencyMatrixT mt;
462 Integer i_1,nv_1,nf_1;
463 BackendDAE.EquationArray eqns;
464 list<Integer> eqn_lst,meqns;
465 BackendDAE.StructurallySingularSystemHandlerArg arg,arg1;
466 BackendDAE.EqSystem syst;
467 BackendDAE.Shared shared;
468 case (syst as BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)), _)
469 algorithm
470 ✗ true := intGe(i,nv);
471 ✗ (ass1_1,ass2_1) := pathFound(m, mt, i, i,emark, vmark, ass1, ass2) "eMark(i)=vMark(i)=false; eMark(i)=vMark(i)=false exit loop";
472 ✗ then
473 (ass1_1,ass2_1,syst,ishared,inArg);
474
475 case (syst as BackendDAE.EQSYSTEM(m=SOME(_),mT=SOME(_)), _)
476 algorithm
477 ✗ i_1 := i + 1;
478 ✗ true := intGt(ass2[i],0);
479 ✗ (ass1_2,ass2_2,syst,shared,arg) := DFSLH2(syst, ishared, nv, nf, i_1, emark, vmark, ass1, ass2, match_opts, sssHandler, inArg);
480 then
481 (ass1_2,ass2_2,syst,shared,arg);
482
483 case (syst as BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)), _)
484 algorithm
485 ✗ i_1 := i + 1;
486 ✗ (ass1_1,ass2_1) := pathFound(m, mt, i, i,emark, vmark, ass1, ass2) "eMark(i)=vMark(i)=false";
487 ✗ (ass1_2,ass2_2,syst,shared,arg) := DFSLH2(syst, ishared, nv, nf, i_1, emark, vmark, ass1_1, ass2_1, match_opts, sssHandler, inArg);
488 then
489 (ass1_2,ass2_2,syst,shared,arg);
490
491 case (_, (BackendDAE.INDEX_REDUCTION(),_))
492 algorithm
493 ✗ meqns := getMarked(nf,i,emark,{});
494 ✗ (_,i_1,syst,shared,ass1_1,ass2_1,arg) := sssHandler({meqns},i,isyst,ishared,ass1,ass2,inArg)
495 "path_found failed, Try index reduction using dummy derivatives.
496 When a constraint exist between states and index reduction is needed
497 the dummy derivative will select one of the states as a dummy state
498 (and the derivative of that state as a dummy derivative).
499 For instance, u1=u2 is a constraint between states. Choose u1 as dummy state
500 and der(u1) as dummy derivative, named der_u1. The differentiated function
501 then becomes: der_u1 = der(u2).
502 In the dummy derivative method this equation is added and the original equation
503 u1=u2 is kept. This is not the case for the original pantilides algorithm, where
504 the original equation is removed from the system.";
505 ✗ eqns := BackendEquation.getEqnsFromEqSystem(syst);
506 ✗ nf_1 := BackendEquation.equationArraySize(eqns) "and try again, restarting. This could be optimized later. It should not
507 be necessary to restart the matching, according to Bernard Bachmann. Instead one
508 could continue the matching as usual. This was tested (2004-11-22) and it does not
509 work to continue without restarting.
510 For instance the Influenca model \"../testsuite/mofiles/Influenca.mo\" does not work if
511 not restarting.
512 2004-12-29 PA. This was a bug, assignment lists needed to be expanded with the size
513 of the system in order to work. SO: Matching is not needed to be restarted from
514 scratch.";
515 ✗ nv_1 := BackendVariable.varsSize(BackendVariable.daeVars(syst));
516 ✗ ass1_2 := assignmentsArrayExpand(ass1_1, nv_1,arrayLength(ass1_1),-1);
517 ✗ ass2_2 := assignmentsArrayExpand(ass2_1, nf_1,arrayLength(ass2_1),-1);
518 ✗ vmark1 := assignmentsArrayExpand(vmark, nv_1,arrayLength(vmark),-1);
519 ✗ emark1 := assignmentsArrayExpand(emark, nf_1,arrayLength(emark),-1);
520 ✗ (ass1_3,ass2_3,syst,shared,arg1) := DFSLH2(syst,shared,nv_1,nf_1,i_1,emark1, vmark1,ass1_2,ass2_2,match_opts,sssHandler,arg);
521 then
522 (ass1_3,ass2_3,syst,shared,arg1);
523
524 case (_, _)
525 algorithm
526 ✗ eqn_lst := getMarked(nf,i,emark,{});
527 ✗ singularSystemError({eqn_lst},i,isyst,ishared,ass1,ass2,inArg);
528 ✗ then
529 fail();
530 end matchcontinue;
531 end DFSLH2;
532
533 protected function pathFound "author: PA
534 This function is part of the matching algorithm.
535 It tries to find a matching for the equation index given as
536 third argument, i.
537 inputs: (AdjacencyMatrix, BackendDAE.AdjacencyMatrixT, int /* equation */,
538 Assignments, Assignments)
539 outputs: (Assignments, Assignments)"
540 input BackendDAE.AdjacencyMatrix m;
541 input BackendDAE.AdjacencyMatrixT mt;
542 input Integer i;
543 input Integer imark;
544 input array<Integer> emark;
545 input array<Integer> vmark;
546 input array<Integer> ass1 "eqn := ass1[var]";
547 input array<Integer> ass2 "var := ass2[eqn]";
548 output array<Integer> outAssignments1;
549 output array<Integer> outAssignments2;
550 algorithm
551 (outAssignments1,outAssignments2):=
552 matchcontinue ass2
553 local
554 array<Integer> ass1_1,ass2_1;
555 case _
556 algorithm
557 ✗ arrayUpdate(emark,i,imark) "Side effect";
558 ✗ (ass1_1,ass2_1) := assignOneInEqn(m, mt, i, ass1, ass2);
559 then
560 (ass1_1,ass2_1);
561 case _
562 algorithm
563 ✗ (ass1_1,ass2_1) := forallUnmarkedVarsInEqn(m, mt, i, imark, emark, vmark, ass1, ass2);
564 then
565 (ass1_1,ass2_1);
566 end matchcontinue;
567 end pathFound;
568
569 protected function assignOneInEqn "author: PA
570 Helper function to pathFound."
571 input BackendDAE.AdjacencyMatrix m;
572 input BackendDAE.AdjacencyMatrixT mt;
573 input Integer i;
574 input array<Integer> ass1 "eqn := ass1[var]";
575 input array<Integer> ass2 "var := ass2[eqn]";
576 output array<Integer> outAssignments1;
577 output array<Integer> outAssignments2;
578 protected
579 list<Integer> vars;
580 algorithm
581 ✗ vars := BackendDAEUtil.varsInEqn(m, i);
582 ✗ (outAssignments1,outAssignments2):= assignFirstUnassigned(i, vars, ass1, ass2);
583 end assignOneInEqn;
584
585 protected function assignFirstUnassigned
586 "author: PA
587 This function assigns the first unassign variable to the equation
588 given as first argument. It is part of the matching algorithm.
589 inputs: (int /* equation */,
590 int list /* variables */,
591 BackendDAE.Assignments /* ass1 */,
592 BackendDAE.Assignments /* ass2 */)
593 outputs: (Assignments, /* ass1 */
594 Assignments) /* ass2 */"
595 input Integer i;
596 input list<Integer> inIntegerLst2;
597 input array<Integer> ass1 "eqn := ass1[var]";
598 input array<Integer> ass2 "var := ass2[eqn]";
599 output array<Integer> outAssignments1;
600 output array<Integer> outAssignments2;
601 algorithm
602 (outAssignments1,outAssignments2):=
603 matchcontinue inIntegerLst2
604 local
605 array<Integer> ass1_1,ass2_1;
606 Integer v;
607 list<Integer> vs;
608 case v :: _
609 algorithm
610 ✗ false := intGt(ass1[v],0);
611 ✗ ass1_1 := arrayUpdate(ass1,v,i);
612 ✗ ass2_1 := arrayUpdate(ass2,i,v);
613 ✗ then
614 (ass1_1,ass2_1);
615 case _ :: vs
616 algorithm
617 ✗ (ass1_1,ass2_1) := assignFirstUnassigned(i, vs, ass1, ass2);
618 then
619 (ass1_1,ass2_1);
620 end matchcontinue;
621 end assignFirstUnassigned;
622
623 protected function forallUnmarkedVarsInEqn
624 "author: PA
625 This function is part of the matching algorithm.
626 It loops over all umarked variables in an equation.
627 inputs: (AdjacencyMatrix,
628 AdjacencyMatrixT,
629 int,
630 BackendDAE.Assignments /* ass1 */,
631 BackendDAE.Assignments /* ass2 */)
632 outputs: (Assignments, Assignments)"
633 input BackendDAE.AdjacencyMatrix m;
634 input BackendDAE.AdjacencyMatrixT mt;
635 input Integer i;
636 input Integer imark;
637 input array<Integer> emark;
638 input array<Integer> vmark;
639 input array<Integer> ass1 "eqn := ass1[var]";
640 input array<Integer> ass2 "var := ass2[eqn]";
641 output array<Integer> outAssignments1;
642 output array<Integer> outAssignments2;
643 protected
644 list<Integer> vars,vars_1;
645 algorithm
646 ✗ vars := BackendDAEUtil.varsInEqn(m, i);
647 ✗ vars_1 := List.filter1OnTrue(vars, isNotVMarked, (imark, vmark));
648 ✗ (outAssignments1,outAssignments2) := forallUnmarkedVarsInEqnBody(m, mt, i, imark, emark, vmark, vars_1, ass1, ass2);
649 end forallUnmarkedVarsInEqn;
650
651 protected function isNotVMarked
652 "author: PA
653 This function succeds for variables that are not marked."
654 input Integer i;
655 input tuple<Integer,array<Integer>> inTpl;
656 output Boolean outB;
657 protected
658 Integer imark;
659 array<Integer> vmark;
660 algorithm
661 ✗ (imark,vmark) := inTpl;
662 ✗ outB := not intEq(imark,vmark[i]);
663 end isNotVMarked;
664
665 protected function forallUnmarkedVarsInEqnBody
666 "author: PA
667 This function is part of the matching algorithm.
668 It is the body of the loop over all unmarked variables.
669 inputs: (AdjacencyMatrix, BackendDAE.AdjacencyMatrixT,
670 int,
671 int list /* var list */
672 Assignments
673 Assignments)
674 outputs: (Assignments, Assignments)"
675 input BackendDAE.AdjacencyMatrix m;
676 input BackendDAE.AdjacencyMatrixT mt;
677 input Integer i;
678 input Integer imark;
679 input array<Integer> emark;
680 input array<Integer> vmark;
681 input list<Integer> inIntegerLst4;
682 input array<Integer> ass1 "eqn := ass1[var]";
683 input array<Integer> ass2 "var := ass2[eqn]";
684 output array<Integer> outAssignments1;
685 output array<Integer> outAssignments2;
686 algorithm
687 (outAssignments1,outAssignments2):=
688 matchcontinue inIntegerLst4
689 local
690 Integer assarg,v;
691 array<Integer> ass1_1,ass2_1,ass1_2,ass2_2;
692 list<Integer> vs;
693 case v :: _
694 algorithm
695 ✗ arrayUpdate(vmark,v,imark);
696 ✗ assarg := ass1[v];
697 ✗ (ass1_1,ass2_1) := pathFound(m, mt, assarg, imark, emark, vmark, ass1, ass2);
698 ✗ ass1_2 := arrayUpdate(ass1_1,v,i);
699 ✗ ass2_2 := arrayUpdate(ass2_1,i,v);
700 ✗ then
701 (ass1_2,ass2_2);
702 case _ :: vs
703 algorithm
704 ✗ (ass1_1,ass2_1) := forallUnmarkedVarsInEqnBody(m, mt, i, imark, emark, vmark, vs, ass1, ass2);
705 then
706 (ass1_1,ass2_1);
707 end matchcontinue;
708 end forallUnmarkedVarsInEqnBody;
709
710
711 public function BFSB
712 " complexity O(n*tau)
713 author: Frenkel TUD 2012-03"
714 input BackendDAE.EqSystem isyst;
715 input BackendDAE.Shared ishared;
716 input Boolean clearMatching;
717 input BackendDAE.MatchingOptions inMatchingOptions;
718 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
719 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
720 output BackendDAE.EqSystem osyst;
721 output BackendDAE.Shared oshared;
722 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
723 algorithm
724 (osyst,oshared,outArg) :=
725 matchcontinue isyst
726 local
727 Integer nvars,neqns;
728 array<Integer> vec1,vec2;
729 BackendDAE.StructurallySingularSystemHandlerArg arg;
730 BackendDAE.EqSystem syst;
731 BackendDAE.Shared shared;
732 array<Integer> rowmarks,parentcolum;
733 BackendDAE.AdjacencyMatrix m;
734 BackendDAE.AdjacencyMatrixT mt;
735
736 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
737 algorithm
738 ✗ neqns := BackendDAEUtil.systemSize(isyst);
739 ✗ nvars := BackendVariable.daenumVariables(isyst);
740 ✗ true := intGt(nvars,0);
741 ✗ true := intGt(neqns,0);
742 ✗ rowmarks := arrayCreate(nvars,-1);
743 ✗ parentcolum := arrayCreate(nvars,-1);
744 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
745 ✗ cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,false);
746 ✗ (vec1,vec2,syst,shared,arg) := BFSB1(1,1,nvars,neqns,m,mt,rowmarks,parentcolum,vec1,vec2,isyst,ishared,inMatchingOptions, sssHandler, inArg);
747 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
748 ✗ then
749 (syst,shared,arg);
750
751 // fail case if system is empty
752 case _
753 algorithm
754 ✗ neqns := BackendDAEUtil.systemSize(isyst);
755 ✗ nvars := BackendVariable.daenumVariables(isyst);
756 ✗ false := intGt(nvars,0);
757 ✗ false := intGt(neqns,0);
758 ✗ vec1 := listArray({});
759 ✗ vec2 := listArray({});
760 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
761 then
762 (syst,ishared,inArg);
763
764 else
765 algorithm
766 ✗ if Flags.isSet(Flags.FAILTRACE) then
767 ✗ Debug.trace("- Matching.BFSB failed\n");
768 end if;
769 ✗ then
770 fail();
771 end matchcontinue;
772 end BFSB;
773
774 protected function BFSB1
775 "function helper for BFSB, traverses all colums and perform a BFSB phase on each
776 author: Frenkel TUD 2012-03"
777 input Integer i;
778 input Integer rowmark;
779 input Integer nv;
780 input Integer ne;
781 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
782 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
783 input array<Integer> rowmarks;
784 input array<Integer> parentcolum;
785 input array<Integer> ass1 "ass[eqnindx]=varindx";
786 input array<Integer> ass2 "ass[varindx]=eqnindx";
787 input BackendDAE.EqSystem isyst;
788 input BackendDAE.Shared ishared;
789 input BackendDAE.MatchingOptions inMatchingOptions;
790 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
791 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
792 output array<Integer> outAss1;
793 output array<Integer> outAss2;
794 output BackendDAE.EqSystem osyst;
795 output BackendDAE.Shared oshared;
796 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
797 algorithm
798 (outAss1,outAss2,osyst,oshared,outArg):=
799 matchcontinue inArg
800 local
801 list<Integer> visitedcolums;
802 BackendDAE.AdjacencyMatrix m1,mt1;
803 Integer nv_1,ne_1,i_1;
804 BackendDAE.StructurallySingularSystemHandlerArg arg;
805 BackendDAE.EqSystem syst;
806 BackendDAE.Shared shared;
807 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,rowmarks1,parentcolum1;
808
809 case _
810 algorithm
811 ✗ true:=intGt(i,ne);
812 ✗ then
813 (ass1,ass2,isyst,ishared,inArg);
814
815 case _
816 algorithm
817 // not assigned
818 ✗ false := intGt(ass1[i],0);
819 // search augmenting paths
820 ✗ visitedcolums := BFSBphase({i},rowmark,i,nv,ne,m,mT,rowmarks,parentcolum,ass1,ass2,{},{});
821 // if visitedcolums is not zero matching fails -> try index reduction and matching aggain
822 ✗ (_,i_1,syst as BackendDAE.EQSYSTEM(m=SOME(m1),mT=SOME(mt1)),shared,nv_1,ne_1,ass1_1,ass2_1,arg) := reduceIndexifNecessary(visitedcolums,i,isyst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
823 ✗ rowmarks1 := assignmentsArrayExpand(rowmarks,nv_1,arrayLength(rowmarks),-1);
824 ✗ parentcolum1 := assignmentsArrayExpand(parentcolum,nv_1,arrayLength(parentcolum),-1);
825 ✗ (ass1_2,ass2_2,syst,shared,arg) := BFSB1(i_1,rowmark+1,nv_1,ne_1,m1,mt1,rowmarks1,parentcolum1,ass1_1,ass2_1,syst,shared,inMatchingOptions,sssHandler,arg);
826 then
827 (ass1_2,ass2_2,syst,shared,arg);
828
829 case _
830 algorithm
831 ✗ true := intGt(ass1[i],0);
832 ✗ (ass1_1,ass2_1,syst,shared,arg) := BFSB1(i+1,rowmark,nv,ne,m,mT,rowmarks,parentcolum,ass1,ass2,isyst,ishared,inMatchingOptions,sssHandler,inArg);
833 then
834 (ass1_1,ass2_1,syst,shared,arg);
835
836 else
837 algorithm
838 ✗ Error.addInternalError("function BFSB1 failed in equation " + intString(i), sourceInfo());
839 ✗ then
840 fail();
841
842 end matchcontinue;
843 end BFSB1;
844
845 protected function BFSBphase
846 "function helper for BFSB, traverses all colums and perform a BFSB phase on each
847 author: Frenkel TUD 2012-03"
848 input list<Integer> queue;
849 input Integer rowmark;
850 input Integer i;
851 input Integer nv;
852 input Integer ne;
853 input BackendDAE.AdjacencyMatrix m;
854 input BackendDAE.AdjacencyMatrixT mT;
855 input array<Integer> rowmarks;
856 input array<Integer> parentcolum;
857 input array<Integer> ass1 "eqn := ass1[var]";
858 input array<Integer> ass2 "var := ass2[eqn]";
859 input list<Integer> nextQueue;
860 input list<Integer> inVisitedColums;
861 output list<Integer> outVisitedColums "This list stores all visited collums, if no augmenting path is found
862 it could be used to prune the nodes, if a path is found the list is empty";
863 algorithm
864 outVisitedColums :=
865 match (queue, nextQueue)
866 local
867 list<Integer> rest,queue1,rows;
868 Integer c;
869 Boolean b;
870 case ({}, {}) then inVisitedColums;
871 case ({}, _)
872 ✗ then
873 BFSBphase(nextQueue,rowmark,i,nv,ne,m,mT,rowmarks,parentcolum,ass1,ass2,{},inVisitedColums);
874 case (c::rest, _)
875 algorithm
876 // traverse all adiacent rows
877 ✗ rows := List.select(m[c], Util.intPositive);
878 ✗ (queue1,b) := BFSBtraverseRows(rows,nextQueue,rowmark,i,c,nv,ne,m,mT,rowmarks,parentcolum,ass1,ass2);
879 ✗ then
880 BFSBphase1(b,rest,rowmark,i,nv,ne,m,mT,rowmarks,parentcolum,ass1,ass2,queue1,c::inVisitedColums);
881 else
882 algorithm
883 ✗ Error.addInternalError("function BFSBphase failed in equation " + intString(i), sourceInfo());
884 ✗ then
885 fail();
886
887 end match;
888 end BFSBphase;
889
890 protected function BFSBphase1
891 "function helper for BFSB, traverses all colums and perform a BFSB phase on each
892 author: Frenkel TUD 2012-03"
893 input Boolean inPathFound;
894 input list<Integer> queue;
895 input Integer rowmark;
896 input Integer i;
897 input Integer nv;
898 input Integer ne;
899 input BackendDAE.AdjacencyMatrix m;
900 input BackendDAE.AdjacencyMatrixT mT;
901 input array<Integer> rowmarks;
902 input array<Integer> parentcolum;
903 input array<Integer> ass1 "eqn := ass1[var]";
904 input array<Integer> ass2 "var := ass2[eqn]";
905 input list<Integer> nextQueue;
906 input list<Integer> inVisitedColums;
907 output list<Integer> outVisitedColums;
908 algorithm
909 outVisitedColums :=
910 match inPathFound
911 case true then {};
912 case false
913 ✗ then
914 BFSBphase(queue,rowmark,i,nv,ne,m,mT,rowmarks,parentcolum,ass1,ass2,nextQueue,inVisitedColums);
915 else
916 algorithm
917 ✗ Error.addInternalError("function BFSBphase1 failed", sourceInfo());
918 ✗ then
919 fail();
920 end match;
921 end BFSBphase1;
922
923 protected function BFSBtraverseRows
924 "function helper for BFSB, traverses all vars of a equations and search a augmenting path
925 author: Frenkel TUD 2012-03"
926 input list<Integer> rows;
927 input list<Integer> queue;
928 input Integer rowmark;
929 input Integer i;
930 input Integer c;
931 input Integer nv;
932 input Integer ne;
933 input BackendDAE.AdjacencyMatrix m;
934 input BackendDAE.AdjacencyMatrixT mT;
935 input array<Integer> rowmarks;
936 input array<Integer> parentcolum;
937 input array<Integer> ass1 "eqn := ass1[var]";
938 input array<Integer> ass2 "var := ass2[eqn]";
939 output list<Integer> outEqnqueue;
940 output Boolean pathFound;
941 algorithm
942 (outEqnqueue,pathFound):=
943 matchcontinue rows
944 local
945 list<Integer> rest,queue1,queue2;
946 Integer rc,r;
947 Boolean b;
948 ✗ case {} then (listReverse(queue),false);
949 case r::_
950 algorithm
951 // row is unmatched -> augmenting path found
952 ✗ true := intLt(ass2[r],0);
953 ✗ BFSBreasign(i,c,parentcolum,r,ass1,ass2);
954 ✗ then
955 ({},true);
956 case r::rest
957 algorithm
958 // row is matched
959 ✗ rc := ass2[r];
960 ✗ false := intLt(rc,0);
961 ✗ queue1 := BFSBenque(queue,rowmark,c,rc,r,intLt(rowmarks[r],rowmark),rowmarks,parentcolum);
962 ✗ (queue2,b) := BFSBtraverseRows(rest,queue1,rowmark,i,c,nv,ne,m,mT,rowmarks,parentcolum,ass1,ass2);
963 then
964 (queue2,b);
965 else
966 algorithm
967 ✗ Error.addInternalError("function BFSBtraverseRows failed in equation " + intString(i), sourceInfo());
968 ✗ then
969 fail();
970
971 end matchcontinue;
972 end BFSBtraverseRows;
973
974 protected function BFSBreasign
975 "function helper for BFSB, reasignment(rematching) allong the augmenting path
976 remove all edges from the assignments that are in the path
977 add all other edges to the assignment
978 author: Frenkel TUD 2012-03"
979 input Integer i;
980 input Integer c;
981 input array<Integer> parentcolum;
982 input Integer l;
983 input array<Integer> ass1 "eqn := ass1[var]";
984 input array<Integer> ass2 "var := ass2[eqn]";
985 algorithm
986 () := matchcontinue ass2
987 local
988 Integer r;
989 case _
990 algorithm
991 ✗ true := intEq(i,c);
992 ✗ arrayUpdate(ass1,c,l);
993 ✗ arrayUpdate(ass2,l,c);
994 then ();
995 case _
996 algorithm
997 ✗ r := ass1[c];
998 ✗ arrayUpdate(ass1,c,l);
999 ✗ arrayUpdate(ass2,l,c);
1000 ✗ BFSBreasign(i,parentcolum[r],parentcolum,r,ass1,ass2);
1001 then
1002 ();
1003 else
1004 algorithm
1005 ✗ Error.addInternalError("function BFSBreasign failed", sourceInfo());
1006 ✗ then
1007 fail();
1008 end matchcontinue;
1009 end BFSBreasign;
1010
1011 protected function BFSBenque
1012 "function helper for BFSB, enque a collum if the row is not visited
1013 author: Frenkel TUD 2012-03"
1014 input list<Integer> queue;
1015 input Integer rowmark;
1016 input Integer c;
1017 input Integer rc;
1018 input Integer r;
1019 input Boolean visited;
1020 input array<Integer> rowmarks;
1021 input array<Integer> parentcolum;
1022 output list<Integer> outEqnqueue;
1023 algorithm
1024 outEqnqueue:=
1025 match visited
1026 case false then queue;
1027 case true
1028 algorithm
1029 // mark row
1030 ✗ arrayUpdate(rowmarks,r,rowmark);
1031 // store parent colum
1032 ✗ arrayUpdate(parentcolum,r,c);
1033 then
1034 (rc::queue);
1035 else
1036 algorithm
1037 ✗ Error.addInternalError("function BFSBenque failed", sourceInfo());
1038 ✗ then
1039 fail();
1040
1041 end match;
1042 end BFSBenque;
1043
1044
1045 public function DFSB
1046 " complexity O(n*tau)
1047 author: Frenkel TUD 2012-03"
1048 input BackendDAE.EqSystem isyst;
1049 input BackendDAE.Shared ishared;
1050 input Boolean clearMatching;
1051 input BackendDAE.MatchingOptions inMatchingOptions;
1052 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
1053 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
1054 output BackendDAE.EqSystem osyst;
1055 output BackendDAE.Shared oshared;
1056 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
1057 algorithm
1058 (osyst,oshared,outArg) :=
1059 matchcontinue isyst
1060 local
1061 Integer nvars,neqns;
1062 BackendDAE.AdjacencyMatrix m;
1063 BackendDAE.AdjacencyMatrixT mt;
1064 array<Integer> vec1,vec2;
1065 BackendDAE.StructurallySingularSystemHandlerArg arg;
1066 BackendDAE.EqSystem syst;
1067 BackendDAE.Shared shared;
1068 array<Integer> rowmarks;
1069
1070 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
1071 algorithm
1072 ✗ neqns := BackendDAEUtil.systemSize(isyst);
1073 ✗ nvars := BackendVariable.daenumVariables(isyst);
1074 ✗ true := intGt(nvars,0);
1075 ✗ true := intGt(neqns,0);
1076 ✗ rowmarks := arrayCreate(nvars,-1);
1077 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
1078 ✗ cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,false);
1079 ✗ (vec1,vec2,syst,shared,arg) := DFSB1(1,1,nvars,neqns,m,mt,rowmarks,vec1,vec2,isyst,ishared,inMatchingOptions,sssHandler,inArg);
1080 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
1081 ✗ then
1082 (syst,shared,arg);
1083
1084 // fail case if system is empty
1085 case _
1086 algorithm
1087 ✗ neqns := BackendDAEUtil.systemSize(isyst);
1088 ✗ nvars := BackendVariable.daenumVariables(isyst);
1089 ✗ false := intGt(nvars,0);
1090 ✗ false := intGt(neqns,0);
1091 ✗ vec1 := listArray({});
1092 ✗ vec2 := listArray({});
1093 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
1094 then
1095 (syst,ishared,inArg);
1096
1097 else
1098 algorithm
1099 ✗ if Flags.isSet(Flags.FAILTRACE) then
1100 ✗ Debug.trace("- Matching.BFSB failed\n");
1101 end if;
1102 ✗ then
1103 fail();
1104 end matchcontinue;
1105 end DFSB;
1106
1107 protected function DFSB1
1108 "function helper for DFSB, traverses all colums and perform a DFSB phase on each
1109 author: Frenkel TUD 2012-03"
1110 input Integer i;
1111 input Integer rowmark;
1112 input Integer nv;
1113 input Integer ne;
1114 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
1115 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
1116 input array<Integer> rowmarks;
1117 input array<Integer> ass1 "ass[eqnindx]=varindx";
1118 input array<Integer> ass2 "ass[varindx]=eqnindx";
1119 input BackendDAE.EqSystem isyst;
1120 input BackendDAE.Shared ishared;
1121 input BackendDAE.MatchingOptions inMatchingOptions;
1122 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
1123 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
1124 output array<Integer> outAss1;
1125 output array<Integer> outAss2;
1126 output BackendDAE.EqSystem osyst;
1127 output BackendDAE.Shared oshared;
1128 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
1129 algorithm
1130 (outAss1,outAss2,osyst,oshared,outArg):=
1131 matchcontinue inArg
1132 local
1133 list<Integer> visitedcolums;
1134 BackendDAE.AdjacencyMatrix m1,mt1;
1135 Integer nv_1,ne_1,i_1;
1136 BackendDAE.StructurallySingularSystemHandlerArg arg;
1137 BackendDAE.EqSystem syst;
1138 BackendDAE.Shared shared;
1139 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,rowmarks1;
1140 case _
1141 algorithm
1142 ✗ true:=intGt(i,ne);
1143 ✗ then
1144 (ass1,ass2,isyst,ishared,inArg);
1145 case _
1146 algorithm
1147 // not assigned
1148 ✗ false := intGt(ass1[i],0);
1149 // search augmenting paths
1150 ✗ visitedcolums := DFSBphase({i},rowmark,i,nv,ne,m,mT,rowmarks,ass1,ass2,{i});
1151 // if visitedcolums is not zero matching fails -> try index reduction and matching aggain
1152 // if visitedcolums is not zero matching fails -> try index reduction and matching aggain
1153 ✗ (_,i_1,syst as BackendDAE.EQSYSTEM(m=SOME(m1),mT=SOME(mt1)),shared,nv_1,ne_1,ass1_1,ass2_1,arg) := reduceIndexifNecessary(visitedcolums,i,isyst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
1154 ✗ rowmarks1 := assignmentsArrayExpand(rowmarks,nv_1,arrayLength(rowmarks),-1);
1155 ✗ (ass1_2,ass2_2,syst,shared,arg) := DFSB1(i_1,rowmark+1,nv_1,ne_1,m1,mt1,rowmarks1,ass1_1,ass2_1,syst,shared,inMatchingOptions,sssHandler,arg);
1156 then
1157 (ass1_2,ass2_2,syst,shared,arg);
1158
1159 case _
1160 algorithm
1161 ✗ true := intGt(ass1[i],0);
1162 ✗ (ass1_1,ass2_1,syst,shared,arg) := DFSB1(i+1,rowmark,nv,ne,m,mT,rowmarks,ass1,ass2,isyst,ishared,inMatchingOptions,sssHandler,inArg);
1163 then
1164 (ass1_1,ass2_1,syst,shared,arg);
1165
1166 else
1167 algorithm
1168 ✗ Error.addInternalError("function DFSB1 failed in equation " + intString(i), sourceInfo());
1169 ✗ then
1170 fail();
1171
1172 end matchcontinue;
1173 end DFSB1;
1174
1175 protected function DFSBphase
1176 "function helper for DFSB, traverses all colums and perform a DFSB phase on each
1177 author: Frenkel TUD 2012-03"
1178 input list<Integer> stack;
1179 input Integer i;
1180 input Integer c;
1181 input Integer nv;
1182 input Integer ne;
1183 input BackendDAE.AdjacencyMatrix m;
1184 input BackendDAE.AdjacencyMatrixT mT;
1185 input array<Integer> rowmarks;
1186 input array<Integer> ass1 "eqn := ass1[var]";
1187 input array<Integer> ass2 "var := ass2[eqn]";
1188 input list<Integer> inVisitedColums;
1189 output list<Integer> outVisitedColums "This list stores all visited collums, if no augmenting path is found
1190 it could be used to prune the nodes, if a path is found the list is empty";
1191 algorithm
1192 outVisitedColums :=
1193 match stack
1194 local
1195 list<Integer> rows;
1196 case {} then inVisitedColums;
1197 case _
1198 algorithm
1199 // traverse all adiacent rows
1200 ✗ rows := List.select(m[c], Util.intPositive);
1201 ✗ then
1202 DFSBtraverseRows(rows,stack,i,nv,ne,m,mT,rowmarks,ass1,ass2,inVisitedColums);
1203 else
1204 algorithm
1205 ✗ Error.addInternalError("function DFSBphase failed in equation " + intString(c), sourceInfo());
1206 ✗ then
1207 fail();
1208
1209 end match;
1210 end DFSBphase;
1211
1212 protected function DFSBtraverseRows
1213 "function helper for DFSB, traverses all vars of a equations and search a augmenting path
1214 author: Frenkel TUD 2012-03"
1215 input list<Integer> rows;
1216 input list<Integer> stack;
1217 input Integer i;
1218 input Integer nv;
1219 input Integer ne;
1220 input BackendDAE.AdjacencyMatrix m;
1221 input BackendDAE.AdjacencyMatrixT mT;
1222 input array<Integer> rowmarks;
1223 input array<Integer> ass1 "eqn := ass1[var]";
1224 input array<Integer> ass2 "var := ass2[eqn]";
1225 input list<Integer> inVisitedColums;
1226 output list<Integer> outVisitedColums;
1227 algorithm
1228 outVisitedColums:=
1229 matchcontinue rows
1230 local
1231 list<Integer> rest,visitedColums;
1232 Integer rc,r;
1233 case {} then inVisitedColums;
1234 case r::_
1235 algorithm
1236 // row is unmatched -> augmenting path found
1237 ✗ true := intLt(ass2[r],0);
1238 ✗ DFSBreasign(stack,r,ass1,ass2);
1239 then
1240 {};
1241 case r::rest
1242 algorithm
1243 // row is matched
1244 ✗ rc := ass2[r];
1245 ✗ false := intLt(rc,0);
1246 ✗ true := intLt(rowmarks[r],i);
1247 ✗ arrayUpdate(rowmarks,r,i);
1248 ✗ visitedColums := DFSBphase(rc::stack,i,rc,nv,ne,m,mT,rowmarks,ass1,ass2,rc::inVisitedColums);
1249 ✗ then
1250 DFSBtraverseRows1(rest,stack,i,nv,ne,m,mT,rowmarks,ass1,ass2,visitedColums);
1251 case _::rest
1252 ✗ then
1253 DFSBtraverseRows(rest,stack,i,nv,ne,m,mT,rowmarks,ass1,ass2,inVisitedColums);
1254 else
1255 algorithm
1256 ✗ Error.addInternalError("function DFSBtraverseRows failed", sourceInfo());
1257 ✗ then
1258 fail();
1259
1260 end matchcontinue;
1261 end DFSBtraverseRows;
1262
1263 protected function DFSBtraverseRows1
1264 "function helper for DFSBtraverseRows
1265 author: Frenkel TUD 2012-03"
1266 input list<Integer> rows;
1267 input list<Integer> stack;
1268 input Integer i;
1269 input Integer nv;
1270 input Integer ne;
1271 input BackendDAE.AdjacencyMatrix m;
1272 input BackendDAE.AdjacencyMatrixT mT;
1273 input array<Integer> rowmarks;
1274 input array<Integer> ass1 "eqn := ass1[var]";
1275 input array<Integer> ass2 "var := ass2[eqn]";
1276 input list<Integer> inVisitedColums;
1277 output list<Integer> outVisitedColums;
1278 algorithm
1279 outVisitedColums:=
1280 match inVisitedColums
1281 case {} then inVisitedColums;
1282 ✗ else DFSBtraverseRows(rows,stack,i,nv,ne,m,mT,rowmarks,ass1,ass2,inVisitedColums);
1283 end match;
1284 end DFSBtraverseRows1;
1285
1286 protected function DFSBreasign
1287 "function helper for DFSB, reasignment(rematching) allong the augmenting path
1288 remove all edges from the assignments that are in the path
1289 add all other edges to the assignment
1290 author: Frenkel TUD 2012-03"
1291 input list<Integer> stack;
1292 input Integer r;
1293 input array<Integer> ass1 "eqn := ass1[var]";
1294 input array<Integer> ass2 "var := ass2[eqn]";
1295 algorithm
1296 () := match stack
1297 local
1298 Integer c,rc;
1299 list<Integer> rest;
1300 case {} then ();
1301 case c::rest
1302 algorithm
1303 251 rc := ass1[c];
1304 251 arrayUpdate(ass1,c,r);
1305 251 arrayUpdate(ass2,r,c);
1306 251 DFSBreasign(rest,rc,ass1,ass2);
1307 then ();
1308 end match;
1309 end DFSBreasign;
1310
1311 public function MC21A
1312 " complexity O(n*tau)
1313 author: Frenkel TUD 2012-03"
1314 input BackendDAE.EqSystem isyst;
1315 input BackendDAE.Shared ishared;
1316 input Boolean clearMatching;
1317 input BackendDAE.MatchingOptions inMatchingOptions;
1318 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
1319 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
1320 output BackendDAE.EqSystem osyst;
1321 output BackendDAE.Shared oshared;
1322 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
1323 algorithm
1324 (osyst,oshared,outArg) :=
1325 matchcontinue isyst
1326 local
1327 Integer nvars,neqns;
1328 BackendDAE.AdjacencyMatrix m;
1329 BackendDAE.AdjacencyMatrixT mt;
1330 array<Integer> vec1,vec2;
1331 BackendDAE.StructurallySingularSystemHandlerArg arg;
1332 BackendDAE.EqSystem syst;
1333 BackendDAE.Shared shared;
1334 array<Integer> rowmarks,lookahead;
1335
1336 case syst as BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
1337 algorithm
1338 ✗ neqns := BackendDAEUtil.systemSize(isyst);
1339 ✗ nvars := BackendVariable.daenumVariables(isyst);
1340 ✗ true := intGt(nvars,0);
1341 ✗ true := intGt(neqns,0);
1342 ✗ rowmarks := arrayCreate(nvars,-1);
1343 ✗ lookahead := arrayCreate(neqns,0);
1344 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
1345 ✗ cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,false);
1346 ✗ (vec1,vec2,syst,shared,arg) := MC21A1(1,1,nvars,neqns,m,mt,rowmarks,lookahead,vec1,vec2,isyst,ishared,inMatchingOptions,sssHandler,inArg);
1347 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
1348 ✗ then
1349 (syst,shared,arg);
1350 // fail case if system is empty
1351 case _
1352 algorithm
1353 ✗ neqns := BackendDAEUtil.systemSize(isyst);
1354 ✗ nvars := BackendVariable.daenumVariables(isyst);
1355 ✗ false := intGt(nvars,0);
1356 ✗ false := intGt(neqns,0);
1357 ✗ vec1 := listArray({});
1358 ✗ vec2 := listArray({});
1359 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
1360 then
1361 (syst,ishared,inArg);
1362 else
1363 algorithm
1364 ✗ if Flags.isSet(Flags.FAILTRACE) then
1365 ✗ Debug.trace("- Matching.MC21A failed\n");
1366 end if;
1367 ✗ then
1368 fail();
1369 end matchcontinue;
1370 end MC21A;
1371
1372 protected function MC21A1
1373 "function helper for MC21A, traverses all colums and perform a MC21A phase on each
1374 author: Frenkel TUD 2012-03"
1375 input Integer i;
1376 input Integer rowmark;
1377 input Integer nv;
1378 input Integer ne;
1379 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
1380 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
1381 input array<Integer> rowmarks;
1382 input array<Integer> lookahead;
1383 input array<Integer> ass1 "ass[eqnindx]=varindx";
1384 input array<Integer> ass2 "ass[varindx]=eqnindx";
1385 input BackendDAE.EqSystem isyst;
1386 input BackendDAE.Shared ishared;
1387 input BackendDAE.MatchingOptions inMatchingOptions;
1388 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
1389 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
1390 output array<Integer> outAss1;
1391 output array<Integer> outAss2;
1392 output BackendDAE.EqSystem osyst;
1393 output BackendDAE.Shared oshared;
1394 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
1395 algorithm
1396 (outAss1,outAss2,osyst,oshared,outArg):=
1397 matchcontinue inArg
1398 local
1399 list<Integer> visitedcolums,changedEqns;
1400 BackendDAE.AdjacencyMatrix m1,mt1;
1401 Integer nv_1,ne_1,i_1;
1402 BackendDAE.StructurallySingularSystemHandlerArg arg;
1403 BackendDAE.EqSystem syst;
1404 BackendDAE.Shared shared;
1405 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,rowmarks1,lookahead1;
1406
1407 case _
1408 algorithm
1409 ✗ true:=intGt(i,ne);
1410 ✗ then
1411 (ass1,ass2,isyst,ishared,inArg);
1412 case _
1413 algorithm
1414 // not assigned
1415 ✗ false := intGt(ass1[i],0);
1416 // search augmenting paths
1417 ✗ visitedcolums := MC21Aphase({i},rowmark,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,{i});
1418 // if visitedcolums is not zero matching fails -> try index reduction and matching aggain
1419 ✗ (changedEqns,i_1,syst as BackendDAE.EQSYSTEM(m=SOME(m1),mT=SOME(mt1)),shared,nv_1,ne_1,ass1_1,ass2_1,arg) := reduceIndexifNecessary(visitedcolums,i,isyst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
1420 ✗ (rowmarks1,lookahead1) := MC21A1fixArrays(visitedcolums,nv_1,ne_1,rowmarks,lookahead,changedEqns);
1421 ✗ (ass1_2,ass2_2,syst,shared,arg) := MC21A1(i_1,rowmark+1,nv_1,ne_1,m1,mt1,rowmarks1,lookahead1,ass1_1,ass2_1,syst,shared,inMatchingOptions,sssHandler,arg);
1422 then
1423 (ass1_2,ass2_2,syst,shared,arg);
1424 case _
1425 algorithm
1426 ✗ true := intGt(ass1[i],0);
1427 ✗ (ass1_1,ass2_1,syst,shared,arg) := MC21A1(i+1,rowmark,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,isyst,ishared,inMatchingOptions,sssHandler,inArg);
1428 then
1429 (ass1_1,ass2_1,syst,shared,arg);
1430 else
1431 algorithm
1432 ✗ Error.addInternalError("function MC21A1 failed in equation " + intString(i), sourceInfo());
1433 ✗ then
1434 fail();
1435 end matchcontinue;
1436 end MC21A1;
1437
1438 protected function MC21A1fixArrays
1439 "function: MC21A1fixArrays, fixes lookahead and rowmarks after system has been index reduced
1440 author: Frenkel TUD 2012-04"
1441 input list<Integer> meqns "Marked Equations for Index Reduction";
1442 input Integer nv;
1443 input Integer ne;
1444 input array<Integer> rowmarks;
1445 input array<Integer> lookahead;
1446 input list<Integer> changedEqns;
1447 output array<Integer> outrowmarks;
1448 output array<Integer> outlookahead;
1449 algorithm
1450 (outrowmarks,outlookahead):=
1451 match meqns
1452 local
1453 Integer memsize;
1454 array<Integer> rowmarks1,lookahead1;
1455 case {} then (rowmarks,lookahead);
1456 case _::_
1457 algorithm
1458 memsize := arrayLength(rowmarks);
1459 ✗ rowmarks1 := assignmentsArrayExpand(rowmarks,nv,memsize,-1);
1460 ✗ lookahead1 := assignmentsArrayExpand(lookahead,ne,memsize,0);
1461 ✗ MC21A1fixArray(changedEqns,lookahead1);
1462 then
1463 (rowmarks1,lookahead1);
1464 else
1465 algorithm
1466 ✗ Error.addInternalError("function MC21A1fixArrays failed", sourceInfo());
1467 ✗ then
1468 fail();
1469 end match;
1470 end MC21A1fixArrays;
1471
1472 protected function MC21A1fixArray
1473 "author: Frenkel TUD 2012-04"
1474 input list<Integer> meqns "Marked Equations for Index Reduction";
1475 input array<Integer> arr;
1476 algorithm
1477 () :=
1478 match meqns
1479 local
1480 Integer e;
1481 list<Integer> rest;
1482 case {} then ();
1483 case e::rest
1484 algorithm
1485 54 arrayUpdate(arr,e,0);
1486 54 MC21A1fixArray(rest,arr);
1487 then
1488 ();
1489 else
1490 algorithm
1491 ✗ Error.addInternalError("function MC21A1fixArray failed", sourceInfo());
1492 ✗ then
1493 fail();
1494 end match;
1495 end MC21A1fixArray;
1496
1497 protected function MC21Aphase
1498 "function helper for MC21A, traverses all colums and perform a MC21A phase on each
1499 author: Frenkel TUD 2012-03"
1500 input list<Integer> stack;
1501 input Integer i;
1502 input Integer c;
1503 input Integer nv;
1504 input Integer ne;
1505 input BackendDAE.AdjacencyMatrix m;
1506 input BackendDAE.AdjacencyMatrixT mT;
1507 input array<Integer> rowmarks;
1508 input array<Integer> lookahead;
1509 input array<Integer> ass1 "eqn := ass1[var]";
1510 input array<Integer> ass2 "var := ass2[eqn]";
1511 input list<Integer> inVisitedColums;
1512 output list<Integer> outVisitedColums "This list stores all visited collums, if no augmenting path is found
1513 it could be used to prune the nodes, if a path is found the list is empty";
1514 algorithm
1515 outVisitedColums :=
1516 match stack
1517 local
1518 list<Integer> rows;
1519 Boolean b;
1520 case {} then inVisitedColums;
1521 case _
1522 algorithm
1523 // traverse all adiacent rows
1524 ✗ rows := List.select(m[c], Util.intPositive);
1525 ✗ b := intLt(lookahead[c],listLength(rows));
1526 ✗ then
1527 MC21Achecklookahead(b,rows,stack,i,c,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,inVisitedColums);
1528 else
1529 algorithm
1530 ✗ Error.addInternalError("function MC21Aphase failed in equation " + intString(c), sourceInfo());
1531 ✗ then
1532 fail();
1533 end match;
1534 end MC21Aphase;
1535
1536 protected function MC21Achecklookahead
1537 "function helper for MC21A, traverses all vars of a equations and search a augmenting path
1538 author: Frenkel TUD 2012-03"
1539 input Boolean dolookahaed;
1540 input list<Integer> rows;
1541 input list<Integer> stack;
1542 input Integer i;
1543 input Integer c;
1544 input Integer nv;
1545 input Integer ne;
1546 input BackendDAE.AdjacencyMatrix m;
1547 input BackendDAE.AdjacencyMatrixT mT;
1548 input array<Integer> rowmarks;
1549 input array<Integer> lookahead;
1550 input array<Integer> ass1 "eqn := ass1[var]";
1551 input array<Integer> ass2 "var := ass2[eqn]";
1552 input list<Integer> inVisitedColums;
1553 output list<Integer> outVisitedColums;
1554 algorithm
1555 ✗ outVisitedColums:=
1556 match dolookahaed
1557 case true
1558 then
1559 MC21AtraverseRowsUnmatched(rows,rows,stack,i,c,listLength(rows),nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,inVisitedColums);
1560 else
1561 MC21AtraverseRows(rows,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,inVisitedColums);
1562 end match;
1563 end MC21Achecklookahead;
1564
1565 protected function MC21AtraverseRowsUnmatched
1566 "function helper for MC21A, traverses all vars of a equations and search a augmenting path
1567 author: Frenkel TUD 2012-03"
1568 input list<Integer> rows;
1569 input list<Integer> rows1;
1570 input list<Integer> stack;
1571 input Integer i;
1572 input Integer c;
1573 input Integer l;
1574 input Integer nv;
1575 input Integer ne;
1576 input BackendDAE.AdjacencyMatrix m;
1577 input BackendDAE.AdjacencyMatrixT mT;
1578 input array<Integer> rowmarks;
1579 input array<Integer> lookahead;
1580 input array<Integer> ass1 "eqn := ass1[var]";
1581 input array<Integer> ass2 "var := ass2[eqn]";
1582 input list<Integer> inVisitedColums;
1583 output list<Integer> outVisitedColums;
1584 algorithm
1585 outVisitedColums:=
1586 matchcontinue rows
1587 local
1588 list<Integer> rest;
1589 Integer r;
1590 case {}
1591 algorithm
1592 ✗ arrayUpdate(lookahead,c,l);
1593 ✗ then
1594 MC21AtraverseRows(rows1,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,inVisitedColums);
1595 case r::_
1596 algorithm
1597 // row is unmatched -> augmenting path found
1598 ✗ true := intLt(ass2[r],0);
1599 ✗ DFSBreasign(stack,r,ass1,ass2);
1600 then
1601 {};
1602 case _::rest
1603 ✗ then
1604 MC21AtraverseRowsUnmatched(rest,rows1,stack,i,c,l,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,inVisitedColums);
1605 end matchcontinue;
1606 end MC21AtraverseRowsUnmatched;
1607
1608 protected function MC21AtraverseRows
1609 "function helper for MC21A, traverses all vars of a equations and search a augmenting path
1610 author: Frenkel TUD 2012-03"
1611 input list<Integer> rows;
1612 input list<Integer> stack;
1613 input Integer i;
1614 input Integer nv;
1615 input Integer ne;
1616 input BackendDAE.AdjacencyMatrix m;
1617 input BackendDAE.AdjacencyMatrixT mT;
1618 input array<Integer> rowmarks;
1619 input array<Integer> lookahead;
1620 input array<Integer> ass1 "eqn := ass1[var]";
1621 input array<Integer> ass2 "var := ass2[eqn]";
1622 input list<Integer> inVisitedColums;
1623 output list<Integer> outVisitedColums;
1624 algorithm
1625 outVisitedColums:=
1626 matchcontinue rows
1627 local
1628 list<Integer> rest,visitedColums;
1629 Integer rc,r;
1630 case {} then inVisitedColums;
1631 case r::rest
1632 algorithm
1633 // row is matched
1634 ✗ rc := ass2[r];
1635 ✗ false := intLt(rc,0);
1636 ✗ true := intLt(rowmarks[r],i);
1637 ✗ arrayUpdate(rowmarks,r,i);
1638 ✗ visitedColums := MC21Aphase(rc::stack,i,rc,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,rc::inVisitedColums);
1639 ✗ then
1640 MC21AtraverseRows1(rest,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,visitedColums);
1641 case _::rest
1642 ✗ then
1643 MC21AtraverseRows(rest,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,inVisitedColums);
1644 else
1645 algorithm
1646 ✗ Error.addInternalError("function MC21AtraverseRows failed", sourceInfo());
1647 ✗ then
1648 fail();
1649 end matchcontinue;
1650 end MC21AtraverseRows;
1651
1652 protected function MC21AtraverseRows1
1653 "function helper for MC21AtraverseRows
1654 author: Frenkel TUD 2012-03"
1655 input list<Integer> rows;
1656 input list<Integer> stack;
1657 input Integer i;
1658 input Integer nv;
1659 input Integer ne;
1660 input BackendDAE.AdjacencyMatrix m;
1661 input BackendDAE.AdjacencyMatrixT mT;
1662 input array<Integer> rowmarks;
1663 input array<Integer> lookahead;
1664 input array<Integer> ass1 "eqn := ass1[var]";
1665 input array<Integer> ass2 "var := ass2[eqn]";
1666 input list<Integer> inVisitedColums;
1667 output list<Integer> outVisitedColums;
1668 algorithm
1669 outVisitedColums:=
1670 match inVisitedColums
1671 case {} then inVisitedColums;
1672 ✗ else MC21AtraverseRows(rows,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,inVisitedColums);
1673 end match;
1674 end MC21AtraverseRows1;
1675
1676
1677 public function PF
1678 " complexity O(n*tau)
1679 author: Frenkel TUD 2012-03"
1680 input BackendDAE.EqSystem isyst;
1681 input BackendDAE.Shared ishared;
1682 input Boolean clearMatching;
1683 input BackendDAE.MatchingOptions inMatchingOptions;
1684 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
1685 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
1686 output BackendDAE.EqSystem osyst;
1687 output BackendDAE.Shared oshared;
1688 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
1689 algorithm
1690 (osyst,oshared,outArg) :=
1691 matchcontinue isyst
1692 local
1693 Integer nvars,neqns;
1694 BackendDAE.AdjacencyMatrix m;
1695 BackendDAE.AdjacencyMatrixT mt;
1696 array<Integer> vec1,vec2;
1697 BackendDAE.StructurallySingularSystemHandlerArg arg;
1698 BackendDAE.EqSystem syst;
1699 BackendDAE.Shared shared;
1700 array<Integer> rowmarks,lookahead;
1701 list<Integer> unmatched;
1702 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
1703 algorithm
1704 ✗ neqns := BackendDAEUtil.systemSize(isyst);
1705 ✗ nvars := BackendVariable.daenumVariables(isyst);
1706 ✗ true := intGt(nvars,0);
1707 ✗ true := intGt(neqns,0);
1708 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
1709 ✗ rowmarks := arrayCreate(nvars,-1);
1710 ✗ lookahead := arrayCreate(neqns,0);
1711 ✗ unmatched := cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,true);
1712 ✗ (vec1,vec2,syst,shared,arg) := PF1(0,unmatched,rowmarks,lookahead,isyst,ishared,nvars,neqns,vec1,vec2,inMatchingOptions,sssHandler,inArg);
1713 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
1714 ✗ then
1715 (syst,shared,arg);
1716 // fail case if system is empty
1717 case _
1718 algorithm
1719 ✗ neqns := BackendDAEUtil.systemSize(isyst);
1720 ✗ nvars := BackendVariable.daenumVariables(isyst);
1721 ✗ false := intGt(nvars,0);
1722 ✗ false := intGt(neqns,0);
1723 ✗ vec1 := listArray({});
1724 ✗ vec2 := listArray({});
1725 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
1726 then
1727 (syst,ishared,inArg);
1728 else
1729 algorithm
1730 ✗ if Flags.isSet(Flags.FAILTRACE) then
1731 ✗ Debug.trace("- Matching.PF failed\n");
1732 end if;
1733 ✗ then
1734 fail();
1735 end matchcontinue;
1736 end PF;
1737
1738 protected function PF1
1739 "function: PF1, helper for PF
1740 author: Frenkel TUD 2012-03"
1741 input Integer i;
1742 input list<Integer> unmatched;
1743 input array<Integer> rowmarks;
1744 input array<Integer> lookahead;
1745 input BackendDAE.EqSystem isyst;
1746 input BackendDAE.Shared ishared;
1747 input Integer nv;
1748 input Integer ne;
1749 input array<Integer> ass1 "eqn := ass1[var]";
1750 input array<Integer> ass2 "var := ass2[eqn]";
1751 input BackendDAE.MatchingOptions inMatchingOptions;
1752 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
1753 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
1754 output array<Integer> outAss1;
1755 output array<Integer> outAss2;
1756 output BackendDAE.EqSystem osyst;
1757 output BackendDAE.Shared oshared;
1758 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
1759 algorithm
1760 (outAss1,outAss2,osyst,oshared,outArg):=
1761 match (unmatched, isyst)
1762 local
1763 BackendDAE.AdjacencyMatrix m,mt;
1764 Integer nv_1,ne_1,i_1;
1765 list<Integer> unmatched1;
1766 list<list<Integer>> meqns;
1767 BackendDAE.StructurallySingularSystemHandlerArg arg,arg1;
1768 BackendDAE.EqSystem syst;
1769 BackendDAE.Shared shared;
1770 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,rowmarks1,lookahead1;
1771 case ({}, _)
1772 then
1773 (ass1,ass2,isyst,ishared,inArg);
1774 case (_, BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)))
1775 algorithm
1776 ✗ (i_1,unmatched1) := PFaugmentmatching(i,unmatched,nv,ne,m,mt,rowmarks,lookahead,ass1,ass2,listLength(unmatched),{});
1777 ✗ meqns := getEqnsforIndexReduction(unmatched1,ne,m,mt,ass1,ass2,inArg);
1778 ✗ (unmatched1,rowmarks1,lookahead1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg) := PF2(meqns,unmatched1,{},rowmarks,lookahead,isyst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
1779 ✗ (ass1_2,ass2_2,syst,shared,arg1) := PF1(i_1+1,unmatched1,rowmarks1,lookahead1,syst,shared,nv_1,ne_1,ass1_1,ass2_1,inMatchingOptions,sssHandler,arg);
1780 then
1781 (ass1_2,ass2_2,syst,shared,arg1);
1782 end match;
1783 end PF1;
1784
1785 protected function PF2
1786 "function: PF2, helper for PF
1787 author: Frenkel TUD 2012-03"
1788 input list<list<Integer>> meqns "Marked Equations for Index Reduction";
1789 input list<Integer> unmatched;
1790 input list<Integer> changedEqns;
1791 input array<Integer> rowmarks;
1792 input array<Integer> lookahead;
1793 input BackendDAE.EqSystem isyst;
1794 input BackendDAE.Shared ishared;
1795 input Integer nv;
1796 input Integer ne;
1797 input array<Integer> ass1 "eqn := ass1[var]";
1798 input array<Integer> ass2 "var := ass2[eqn]";
1799 input BackendDAE.MatchingOptions inMatchingOptions;
1800 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
1801 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
1802 output list<Integer> outunmatched;
1803 output array<Integer> outrowmarks;
1804 output array<Integer> outlookahead;
1805 output Integer nvars;
1806 output Integer neqns;
1807 output array<Integer> outAss1;
1808 output array<Integer> outAss2;
1809 output BackendDAE.EqSystem osyst;
1810 output BackendDAE.Shared oshared;
1811 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
1812 algorithm
1813 (outunmatched,outrowmarks,outlookahead,nvars,neqns,outAss1,outAss2,osyst,oshared,outArg):=
1814 match (meqns, inMatchingOptions)
1815 local
1816 Integer nv_1,ne_1;
1817 list<Integer> unmatched1;
1818 BackendDAE.StructurallySingularSystemHandlerArg arg;
1819 BackendDAE.EqSystem syst;
1820 BackendDAE.Shared shared;
1821 array<Integer> ass1_1,ass2_1,rowmarks1,lookahead1;
1822
1823 case ({}, _)
1824 then
1825 (unmatched,rowmarks,lookahead,nv,ne,ass1,ass2,isyst,ishared,inArg);
1826 case (_, (BackendDAE.INDEX_REDUCTION(),_))
1827 algorithm
1828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 (unmatched1,_,syst,shared,ass2_1,ass1_1,arg) := sssHandler(meqns,0,isyst,ishared,ass2,ass1,inArg);
1829 2 ne_1 := BackendDAEUtil.systemSize(syst);
1830 2 nv_1 := BackendVariable.daenumVariables(syst);
1831 2 ass1_1 := assignmentsArrayExpand(ass1_1,ne_1,ne,-1);
1832 2 ass2_1 := assignmentsArrayExpand(ass2_1,nv_1,nv,-1);
1833 2 rowmarks1 := assignmentsArrayExpand(rowmarks,nv_1,nv,-1);
1834 2 lookahead1 := assignmentsArrayExpand(lookahead,ne_1,ne,0);
1835 2 MC21A1fixArray(unmatched1,lookahead1);
1836 2 then
1837 (unmatched1,rowmarks1,lookahead1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg);
1838 case (_, _)
1839 algorithm
1840 ✗ singularSystemError(meqns,0,isyst,ishared,ass1,ass2,inArg);
1841 ✗ then
1842 fail();
1843 end match;
1844 end PF2;
1845
1846 protected function PFaugmentmatching
1847 "function helper for PFaugmentmatching, traverses all unmatched
1848 colums and perform one pass of the augmenting proceure
1849 author: Frenkel TUD 2012-03"
1850 input Integer i;
1851 input list<Integer> U;
1852 input Integer nv;
1853 input Integer ne;
1854 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
1855 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
1856 input array<Integer> rowmarks;
1857 input array<Integer> lookahead;
1858 input array<Integer> ass1 "ass[eqnindx]=varindx";
1859 input array<Integer> ass2 "ass[varindx]=eqnindx";
1860 input Integer previousUnmatched;
1861 input list<Integer> unMatched;
1862 output Integer outI;
1863 output list<Integer> outUnmatched;
1864 algorithm
1865 (outI,outUnmatched):=
1866 matchcontinue U
1867 local
1868 list<Integer> rest,unmatched;
1869 Integer c,i_1;
1870 Boolean b;
1871 case {}
1872 algorithm
1873 // no augmenting path is found in pass
1874 ✗ true:=intEq(previousUnmatched,listLength(unMatched));
1875 ✗ then
1876 (i,unMatched);
1877 case {}
1878 algorithm
1879 // augmenting path is found in pass, next round
1880 ✗ (i_1,unmatched) := PFaugmentmatching(i+1,unMatched,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,listLength(unMatched),{});
1881 then
1882 (i_1,unmatched);
1883 case c::rest
1884 algorithm
1885 ✗ true := intGt(ass1[c],-1);
1886 ✗ (i_1,unmatched) := PFaugmentmatching(i,rest,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,previousUnmatched,unMatched);
1887 then
1888 (i_1,unmatched);
1889 case c::rest
1890 algorithm
1891 ✗ b := PFphase({c},i,c,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
1892 ✗ unmatched := List.consOnTrue(not b, c, unMatched);
1893 ✗ (i_1,unmatched) := PFaugmentmatching(i,rest,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,previousUnmatched,unmatched);
1894 then
1895 (i_1,unmatched);
1896 else
1897 algorithm
1898 ✗ Error.addInternalError("function PFaugmentmatching failed", sourceInfo());
1899 ✗ then
1900 fail();
1901 end matchcontinue;
1902 end PFaugmentmatching;
1903
1904 protected function PFphase
1905 "function helper for PF, traverses all colums and perform a PF phase on each
1906 author: Frenkel TUD 2012-03"
1907 input list<Integer> stack;
1908 input Integer i;
1909 input Integer c;
1910 input Integer nv;
1911 input Integer ne;
1912 input BackendDAE.AdjacencyMatrix m;
1913 input BackendDAE.AdjacencyMatrixT mT;
1914 input array<Integer> rowmarks;
1915 input array<Integer> lookahead;
1916 input array<Integer> ass1 "eqn := ass1[var]";
1917 input array<Integer> ass2 "var := ass2[eqn]";
1918 output Boolean matched;
1919 algorithm
1920 matched :=
1921 match stack
1922 local
1923 list<Integer> rows;
1924 Boolean b;
1925 case {} then false;
1926 case _
1927 algorithm
1928 // traverse all adiacent rows
1929 ✗ rows := List.select(m[c], Util.intPositive);
1930 ✗ b := intLt(lookahead[c],listLength(rows));
1931 ✗ then
1932 PFchecklookahead(b,rows,stack,i,c,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
1933 else
1934 algorithm
1935 ✗ Error.addInternalError("function PFphase failed in equation " + intString(c), sourceInfo());
1936 ✗ then
1937 fail();
1938
1939 end match;
1940 end PFphase;
1941
1942 protected function PFchecklookahead
1943 "function helper for PF, traverses all vars of a equations and search a augmenting path
1944 author: Frenkel TUD 2012-03"
1945 input Boolean dolookahaed;
1946 input list<Integer> rows;
1947 input list<Integer> stack;
1948 input Integer i;
1949 input Integer c;
1950 input Integer nv;
1951 input Integer ne;
1952 input BackendDAE.AdjacencyMatrix m;
1953 input BackendDAE.AdjacencyMatrixT mT;
1954 input array<Integer> rowmarks;
1955 input array<Integer> lookahead;
1956 input array<Integer> ass1 "eqn := ass1[var]";
1957 input array<Integer> ass2 "var := ass2[eqn]";
1958 output Boolean matched;
1959 algorithm
1960 ✗ matched:=
1961 match dolookahaed
1962 case true
1963 then
1964 PFtraverseRowsUnmatched(rows,rows,stack,i,c,listLength(rows),nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
1965 else
1966 PFtraverseRows(rows,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
1967 end match;
1968 end PFchecklookahead;
1969
1970 protected function PFtraverseRowsUnmatched
1971 "function helper for PF, traverses all vars of a equations and search a augmenting path
1972 author: Frenkel TUD 2012-03"
1973 input list<Integer> rows;
1974 input list<Integer> rows1;
1975 input list<Integer> stack;
1976 input Integer i;
1977 input Integer c;
1978 input Integer l;
1979 input Integer nv;
1980 input Integer ne;
1981 input BackendDAE.AdjacencyMatrix m;
1982 input BackendDAE.AdjacencyMatrixT mT;
1983 input array<Integer> rowmarks;
1984 input array<Integer> lookahead;
1985 input array<Integer> ass1 "eqn := ass1[var]";
1986 input array<Integer> ass2 "var := ass2[eqn]";
1987 output Boolean matched;
1988 algorithm
1989 matched:=
1990 matchcontinue rows
1991 local
1992 list<Integer> rest;
1993 Integer r;
1994 case {}
1995 algorithm
1996 ✗ arrayUpdate(lookahead,c,l);
1997 ✗ then
1998 PFtraverseRows(rows1,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
1999 case r::_
2000 algorithm
2001 // row is unmatched -> augmenting path found
2002 ✗ true := intLt(ass2[r],0);
2003 ✗ DFSBreasign(stack,r,ass1,ass2);
2004 then
2005 true;
2006 case _::rest
2007 ✗ then
2008 PFtraverseRowsUnmatched(rest,rows1,stack,i,c,l,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
2009 end matchcontinue;
2010 end PFtraverseRowsUnmatched;
2011
2012 protected function PFtraverseRows
2013 "function helper for PF, traverses all vars of a equations and search a augmenting path
2014 author: Frenkel TUD 2012-03"
2015 input list<Integer> rows;
2016 input list<Integer> stack;
2017 input Integer i;
2018 input Integer nv;
2019 input Integer ne;
2020 input BackendDAE.AdjacencyMatrix m;
2021 input BackendDAE.AdjacencyMatrixT mT;
2022 input array<Integer> rowmarks;
2023 input array<Integer> lookahead;
2024 input array<Integer> ass1 "eqn := ass1[var]";
2025 input array<Integer> ass2 "var := ass2[eqn]";
2026 output Boolean matched;
2027 algorithm
2028 matched:=
2029 matchcontinue rows
2030 local
2031 list<Integer> rest;
2032 Integer rc,r;
2033 Boolean b;
2034 case {} then false;
2035 case r::rest
2036 algorithm
2037 // row is matched
2038 ✗ rc := ass2[r];
2039 ✗ false := intLt(rc,0);
2040 ✗ false := intEq(rowmarks[r],i);
2041 ✗ arrayUpdate(rowmarks,r,i);
2042 ✗ b := PFphase(rc::stack,i,rc,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
2043 ✗ then
2044 PFtraverseRows1(rest,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,b);
2045 case _::rest
2046 ✗ then
2047 PFtraverseRows(rest,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
2048 else
2049 algorithm
2050 ✗ Error.addInternalError("function PFtraverseRows failed", sourceInfo());
2051 ✗ then
2052 fail();
2053 end matchcontinue;
2054 end PFtraverseRows;
2055
2056 protected function PFtraverseRows1
2057 "function helper for PFtraverseRows
2058 author: Frenkel TUD 2012-03"
2059 input list<Integer> rows;
2060 input list<Integer> stack;
2061 input Integer i;
2062 input Integer nv;
2063 input Integer ne;
2064 input BackendDAE.AdjacencyMatrix m;
2065 input BackendDAE.AdjacencyMatrixT mT;
2066 input array<Integer> rowmarks;
2067 input array<Integer> lookahead;
2068 input array<Integer> ass1 "eqn := ass1[var]";
2069 input array<Integer> ass2 "var := ass2[eqn]";
2070 input Boolean inMatched;
2071 output Boolean matched;
2072 algorithm
2073 ✗ matched:=
2074 match inMatched
2075 case true then inMatched;
2076 else PFtraverseRows(rows,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2);
2077 end match;
2078 end PFtraverseRows1;
2079
2080 public function PFPlus
2081 " complexity O(n*tau)
2082 author: Frenkel TUD 2012-03"
2083 input BackendDAE.EqSystem isyst;
2084 input BackendDAE.Shared ishared;
2085 input Boolean clearMatching;
2086 input BackendDAE.MatchingOptions inMatchingOptions;
2087 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
2088 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
2089 output BackendDAE.EqSystem osyst;
2090 output BackendDAE.Shared oshared;
2091 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
2092 algorithm
2093 (osyst,oshared,outArg) :=
2094 matchcontinue isyst
2095 local
2096 Integer nvars,neqns;
2097 BackendDAE.AdjacencyMatrix m;
2098 BackendDAE.AdjacencyMatrixT mt;
2099 array<Integer> vec1,vec2;
2100 BackendDAE.StructurallySingularSystemHandlerArg arg;
2101 BackendDAE.EqSystem syst;
2102 BackendDAE.Shared shared;
2103 array<Integer> rowmarks,lookahead;
2104 list<Integer> unmatched;
2105 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
2106 algorithm
2107 646 neqns := BackendDAEUtil.systemSize(isyst);
2108 646 nvars := BackendVariable.daenumVariables(isyst);
2109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 646 times.
646 true := intGt(nvars,0);
2110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 646 times.
646 true := intGt(neqns,0);
2111 646 (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
2112 646 rowmarks := arrayCreate(nvars,-1);
2113 646 lookahead := arrayCreate(neqns,0);
2114 646 unmatched := cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,true);
2115 646 (_,vec1,vec2,syst,shared,arg) := PFPlus1(0,unmatched,rowmarks,lookahead,isyst,ishared,nvars,neqns,vec1,vec2,inMatchingOptions,sssHandler,inArg);
2116 646 syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
2117 646 then
2118 (syst,shared,arg);
2119 // fail case if system is empty
2120 case _
2121 algorithm
2122 ✗ neqns := BackendDAEUtil.systemSize(isyst);
2123 ✗ nvars := BackendVariable.daenumVariables(isyst);
2124 ✗ false := intGt(nvars,0);
2125 ✗ false := intGt(neqns,0);
2126 ✗ vec1 := listArray({});
2127 ✗ vec2 := listArray({});
2128 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
2129 then
2130 (syst,ishared,inArg);
2131 else
2132 algorithm
2133 ✗ if Flags.isSet(Flags.FAILTRACE) then
2134 ✗ Debug.trace("- Matching.PFPlus failed\n");
2135 end if;
2136 ✗ then
2137 fail();
2138 end matchcontinue;
2139 end PFPlus;
2140
2141 protected function PFPlus1
2142 "function: PFPlus1, helper for PFPlus
2143 author: Frenkel TUD 2012-03"
2144 input Integer i;
2145 input list<Integer> unmatched;
2146 input array<Integer> rowmarks;
2147 input array<Integer> lookahead;
2148 input BackendDAE.EqSystem isyst;
2149 input BackendDAE.Shared ishared;
2150 input Integer nv;
2151 input Integer ne;
2152 input array<Integer> ass1 "eqn := ass1[var]";
2153 input array<Integer> ass2 "var := ass2[eqn]";
2154 input BackendDAE.MatchingOptions inMatchingOptions;
2155 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
2156 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
2157 output Integer outI;
2158 output array<Integer> outAss1;
2159 output array<Integer> outAss2;
2160 output BackendDAE.EqSystem osyst;
2161 output BackendDAE.Shared oshared;
2162 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
2163 algorithm
2164 (outI,outAss1,outAss2,osyst,oshared,outArg):=
2165 match (unmatched, isyst)
2166 local
2167 BackendDAE.AdjacencyMatrix m,mt;
2168 Integer nv_1,ne_1,i_1;
2169 list<Integer> unmatched1;
2170 list<list<Integer>> meqns;
2171 BackendDAE.StructurallySingularSystemHandlerArg arg,arg1;
2172 BackendDAE.EqSystem syst;
2173 BackendDAE.Shared shared;
2174 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,rowmarks1,lookahead1;
2175 case ({}, _)
2176 then
2177 (i,ass1,ass2,isyst,ishared,inArg);
2178 case (_, syst as BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)))
2179 algorithm
2180 11 (i_1,unmatched1) := PFPlusaugmentmatching(i,unmatched,nv,ne,m,mt,rowmarks,lookahead,ass1,ass2,listLength(unmatched),{},false);
2181 11 meqns := getEqnsforIndexReduction(unmatched1,ne,m,mt,ass1,ass2,inArg);
2182 11 (unmatched1,rowmarks1,lookahead1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg) := PF2(meqns,unmatched1,{},rowmarks,lookahead,syst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
2183 11 (i_1,ass1_2,ass2_2,syst,shared,arg1) := PFPlus1(i_1+1,unmatched1,rowmarks1,lookahead1,syst,shared,nv_1,ne_1,ass1_1,ass2_1,inMatchingOptions,sssHandler,arg);
2184 then
2185 (i_1,ass1_2,ass2_2,syst,shared,arg1);
2186 end match;
2187 end PFPlus1;
2188
2189 protected function PFPlusaugmentmatching
2190 "function helper for PFPlusaugmentmatching, traverses all unmatched
2191 colums and perform one pass of the augmenting proceure
2192 author: Frenkel TUD 2012-03"
2193 input Integer i;
2194 input list<Integer> U;
2195 input Integer nv;
2196 input Integer ne;
2197 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
2198 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
2199 input array<Integer> rowmarks;
2200 input array<Integer> lookahead;
2201 input array<Integer> ass1 "ass[eqnindx]=varindx";
2202 input array<Integer> ass2 "ass[varindx]=eqnindx";
2203 input Integer previousUnmatched;
2204 input list<Integer> unMatched;
2205 input Boolean reverseRows;
2206 output Integer outI;
2207 output list<Integer> outUnMatched;
2208 algorithm
2209 (outI,outUnMatched) :=
2210 matchcontinue U
2211 local
2212 list<Integer> rest,unmatched;
2213 Integer c,i_1;
2214 Boolean b;
2215 case {}
2216 algorithm
2217 // no augmenting path is found in pass
2218
2/2
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 11 times.
24 true:=intEq(previousUnmatched,listLength(unMatched));
2219 11 then
2220 (i,unMatched);
2221 case {}
2222 algorithm
2223 // augmenting path is found in pass, next round
2224 13 (i_1,unmatched) := PFPlusaugmentmatching(i+1,unMatched,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,listLength(unMatched),{},reverseRows);
2225 then
2226 (i_1,unmatched);
2227 case c::rest
2228 algorithm
2229
1/2
✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
89 true := intGt(ass1[c],-1);
2230 ✗ (i_1,unmatched) := PFPlusaugmentmatching(i,rest,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,previousUnmatched,unMatched,reverseRows);
2231 then
2232 (i_1,unmatched);
2233 case c::rest
2234 algorithm
2235 89 b := PFPlusphase({c},i,c,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2236 89 unmatched := List.consOnTrue(not b, c, unMatched);
2237 89 (i_1,unmatched) := PFPlusaugmentmatching(i,rest,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,previousUnmatched,unmatched,not reverseRows);
2238 then
2239 (i_1,unmatched);
2240 else
2241 algorithm
2242 ✗ Error.addInternalError("function PFPlusaugmentmatching failed", sourceInfo());
2243 ✗ then
2244 fail();
2245 end matchcontinue;
2246 end PFPlusaugmentmatching;
2247
2248 protected function PFPlusphase
2249 "function helper for PFPlus, traverses all colums and perform a PFPlus phase on each
2250 author: Frenkel TUD 2012-03"
2251 input list<Integer> stack;
2252 input Integer i;
2253 input Integer c;
2254 input Integer nv;
2255 input Integer ne;
2256 input BackendDAE.AdjacencyMatrix m;
2257 input BackendDAE.AdjacencyMatrixT mT;
2258 input array<Integer> rowmarks;
2259 input array<Integer> lookahead;
2260 input array<Integer> ass1 "eqn := ass1[var]";
2261 input array<Integer> ass2 "var := ass2[eqn]";
2262 input Boolean reverseRows;
2263 output Boolean matched;
2264 algorithm
2265 matched :=
2266 match (stack, reverseRows)
2267 local
2268 list<Integer> rows;
2269 Boolean b;
2270 case ({}, _) then false;
2271 case (_, false)
2272 algorithm
2273 // traverse all adiacent rows
2274 500 rows := List.select(m[c], Util.intPositive);
2275 500 b := intLt(lookahead[c],listLength(rows));
2276 500 then
2277 PFPluschecklookahead(b,rows,stack,i,c,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2278 case (_, true)
2279 algorithm
2280 // traverse all adiacent rows
2281 117 rows := List.select(m[c], Util.intPositive);
2282 117 b := intLt(lookahead[c],listLength(rows));
2283 117 then
2284 PFPluschecklookahead(b,listReverse(rows),stack,i,c,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2285 else
2286 algorithm
2287 ✗ Error.addInternalError("function PFPlusphase failed in equation " + intString(c), sourceInfo());
2288 ✗ then
2289 fail();
2290
2291 end match;
2292 end PFPlusphase;
2293
2294 protected function PFPluschecklookahead
2295 "function helper for PFPlus, traverses all vars of a equations and search a augmenting path
2296 author: Frenkel TUD 2012-03"
2297 input Boolean dolookahaed;
2298 input list<Integer> rows;
2299 input list<Integer> stack;
2300 input Integer i;
2301 input Integer c;
2302 input Integer nv;
2303 input Integer ne;
2304 input BackendDAE.AdjacencyMatrix m;
2305 input BackendDAE.AdjacencyMatrixT mT;
2306 input array<Integer> rowmarks;
2307 input array<Integer> lookahead;
2308 input array<Integer> ass1 "eqn := ass1[var]";
2309 input array<Integer> ass2 "var := ass2[eqn]";
2310 input Boolean reverseRows;
2311 output Boolean matched;
2312 algorithm
2313
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 137 times.
617 matched:=
2314 match dolookahaed
2315 case true
2316 then
2317 PFPlustraverseRowsUnmatched(rows,rows,stack,i,c,listLength(rows),nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2318 else
2319 PFPlustraverseRows(rows,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2320 end match;
2321 end PFPluschecklookahead;
2322
2323 protected function PFPlustraverseRowsUnmatched
2324 "function helper for PFPlus, traverses all vars of a equations and search a augmenting path
2325 author: Frenkel TUD 2012-03"
2326 input list<Integer> rows;
2327 input list<Integer> rows1;
2328 input list<Integer> stack;
2329 input Integer i;
2330 input Integer c;
2331 input Integer l;
2332 input Integer nv;
2333 input Integer ne;
2334 input BackendDAE.AdjacencyMatrix m;
2335 input BackendDAE.AdjacencyMatrixT mT;
2336 input array<Integer> rowmarks;
2337 input array<Integer> lookahead;
2338 input array<Integer> ass1 "eqn := ass1[var]";
2339 input array<Integer> ass2 "var := ass2[eqn]";
2340 input Boolean reverseRows;
2341 output Boolean matched;
2342 algorithm
2343 matched:=
2344 matchcontinue rows
2345 local
2346 list<Integer> rest;
2347 Integer r;
2348 case {}
2349 algorithm
2350 415 arrayUpdate(lookahead,c,l);
2351 415 then
2352 PFPlustraverseRows(rows1,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2353 case r::_
2354 algorithm
2355 // row is unmatched -> augmenting path found
2356
2/2
✓ Branch 1 taken 1148 times.
✓ Branch 2 taken 65 times.
1213 true := intLt(ass2[r],0);
2357 65 DFSBreasign(stack,r,ass1,ass2);
2358 then
2359 true;
2360 case _::rest
2361 1148 then
2362 PFPlustraverseRowsUnmatched(rest,rows1,stack,i,c,l,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2363 end matchcontinue;
2364 end PFPlustraverseRowsUnmatched;
2365
2366 protected function PFPlustraverseRows
2367 "function helper for PFPlus, traverses all vars of a equations and search a augmenting path
2368 author: Frenkel TUD 2012-03"
2369 input list<Integer> rows;
2370 input list<Integer> stack;
2371 input Integer i;
2372 input Integer nv;
2373 input Integer ne;
2374 input BackendDAE.AdjacencyMatrix m;
2375 input BackendDAE.AdjacencyMatrixT mT;
2376 input array<Integer> rowmarks;
2377 input array<Integer> lookahead;
2378 input array<Integer> ass1 "eqn := ass1[var]";
2379 input array<Integer> ass2 "var := ass2[eqn]";
2380 input Boolean reverseRows;
2381 output Boolean matched;
2382 algorithm
2383 matched:=
2384 matchcontinue rows
2385 local
2386 list<Integer> rest;
2387 Integer rc,r;
2388 Boolean b;
2389 case {} then false;
2390 case r::rest
2391 algorithm
2392 // row is matched
2393 1213 rc := ass2[r];
2394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1213 times.
1213 false := intLt(rc,0);
2395
2/2
✓ Branch 1 taken 685 times.
✓ Branch 2 taken 528 times.
1213 false := intEq(rowmarks[r],i);
2396 528 arrayUpdate(rowmarks,r,i);
2397 528 b := PFPlusphase(rc::stack,i,rc,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2398 528 then
2399 PFPlustraverseRows1(rest,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,b,reverseRows);
2400 case _::rest
2401 685 then
2402 PFPlustraverseRows(rest,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2403 else
2404 algorithm
2405 ✗ Error.addInternalError("function PFPlustraverseRows failed", sourceInfo());
2406 ✗ then
2407 fail();
2408 end matchcontinue;
2409 end PFPlustraverseRows;
2410
2411 protected function PFPlustraverseRows1
2412 "function helper for PFPlustraverseRows
2413 author: Frenkel TUD 2012-03"
2414 input list<Integer> rows;
2415 input list<Integer> stack;
2416 input Integer i;
2417 input Integer nv;
2418 input Integer ne;
2419 input BackendDAE.AdjacencyMatrix m;
2420 input BackendDAE.AdjacencyMatrixT mT;
2421 input array<Integer> rowmarks;
2422 input array<Integer> lookahead;
2423 input array<Integer> ass1 "eqn := ass1[var]";
2424 input array<Integer> ass2 "var := ass2[eqn]";
2425 input Boolean inMatched;
2426 input Boolean reverseRows;
2427 output Boolean matched;
2428 algorithm
2429
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 186 times.
528 matched:=
2430 match inMatched
2431 case true then inMatched;
2432 else PFPlustraverseRows(rows,stack,i,nv,ne,m,mT,rowmarks,lookahead,ass1,ass2,reverseRows);
2433 end match;
2434 end PFPlustraverseRows1;
2435
2436 public function HK
2437 " complexity O(sqrt(n)*tau)
2438 author: Frenkel TUD 2012-03"
2439 input BackendDAE.EqSystem isyst;
2440 input BackendDAE.Shared ishared;
2441 input Boolean clearMatching;
2442 input BackendDAE.MatchingOptions inMatchingOptions;
2443 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
2444 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
2445 output BackendDAE.EqSystem osyst;
2446 output BackendDAE.Shared oshared;
2447 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
2448 algorithm
2449 (osyst,oshared,outArg) :=
2450 matchcontinue isyst
2451 local
2452 Integer nvars,neqns;
2453 BackendDAE.AdjacencyMatrix m;
2454 BackendDAE.AdjacencyMatrixT mt;
2455 array<Integer> vec1,vec2;
2456 BackendDAE.StructurallySingularSystemHandlerArg arg;
2457 BackendDAE.EqSystem syst;
2458 BackendDAE.Shared shared;
2459 array<Integer> rowmarks,level,collummarks;
2460 list<Integer> unmatched;
2461 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
2462 algorithm
2463 ✗ neqns := BackendDAEUtil.systemSize(isyst);
2464 ✗ nvars := BackendVariable.daenumVariables(isyst);
2465 ✗ true := intGt(nvars,0);
2466 ✗ true := intGt(neqns,0);
2467 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
2468 ✗ rowmarks := arrayCreate(nvars,-1);
2469 ✗ collummarks := arrayCreate(neqns,-1);
2470 ✗ level := arrayCreate(neqns,-1);
2471 ✗ unmatched := cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,true);
2472 ✗ (vec1,vec2,syst,shared,arg) := HK1(0,unmatched,rowmarks,collummarks,level,isyst,ishared,nvars,neqns,vec1,vec2,inMatchingOptions,sssHandler,inArg);
2473 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
2474 ✗ then
2475 (syst,shared,arg);
2476 // fail case if system is empty
2477 case _
2478 algorithm
2479 ✗ neqns := BackendDAEUtil.systemSize(isyst);
2480 ✗ nvars := BackendVariable.daenumVariables(isyst);
2481 ✗ false := intGt(nvars,0);
2482 ✗ false := intGt(neqns,0);
2483 ✗ vec1 := listArray({});
2484 ✗ vec2 := listArray({});
2485 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
2486 then
2487 (syst,ishared,inArg);
2488 else
2489 algorithm
2490 ✗ if Flags.isSet(Flags.FAILTRACE) then
2491 ✗ Debug.trace("- Matching.HK failed\n");
2492 end if;
2493 ✗ then
2494 fail();
2495 end matchcontinue;
2496 end HK;
2497
2498 protected function HK1
2499 "function: HK1, helper for HK
2500 author: Frenkel TUD 2012-03"
2501 input Integer i;
2502 input list<Integer> unmatched;
2503 input array<Integer> rowmarks;
2504 input array<Integer> collummarks;
2505 input array<Integer> level;
2506 input BackendDAE.EqSystem isyst;
2507 input BackendDAE.Shared ishared;
2508 input Integer nv;
2509 input Integer ne;
2510 input array<Integer> ass1 "eqn := ass1[var]";
2511 input array<Integer> ass2 "var := ass2[eqn]";
2512 input BackendDAE.MatchingOptions inMatchingOptions;
2513 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
2514 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
2515 output array<Integer> outAss1;
2516 output array<Integer> outAss2;
2517 output BackendDAE.EqSystem osyst;
2518 output BackendDAE.Shared oshared;
2519 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
2520 algorithm
2521 (outAss1,outAss2,osyst,oshared,outArg):=
2522 match (unmatched, isyst)
2523 local
2524 BackendDAE.AdjacencyMatrix m,mt;
2525 Integer nv_1,ne_1,i_1;
2526 list<Integer> unmatched1;
2527 list<list<Integer>> meqns;
2528 BackendDAE.StructurallySingularSystemHandlerArg arg,arg1;
2529 BackendDAE.EqSystem syst;
2530 BackendDAE.Shared shared;
2531 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,rowmarks1,collummarks1,level1;
2532 case ({}, _)
2533 then
2534 (ass1,ass2,isyst,ishared,inArg);
2535 case (_, syst as BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)))
2536 algorithm
2537 ✗ (i_1,unmatched1) := HKphase(i,unmatched,nv,ne,m,mt,rowmarks,collummarks,level,ass1,ass2,listLength(unmatched),{});
2538 ✗ meqns := getEqnsforIndexReduction(unmatched1,ne,m,mt,ass1,ass2,inArg);
2539 ✗ (unmatched1,rowmarks1,collummarks1,level1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg) := HK2(meqns,unmatched1,{},rowmarks,collummarks,level,syst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
2540 ✗ (ass1_2,ass2_2,syst,shared,arg1) := HK1(i_1+1,unmatched1,rowmarks1,collummarks1,level1,syst,shared,nv_1,ne_1,ass1_1,ass2_1,inMatchingOptions,sssHandler,arg);
2541 then
2542 (ass1_2,ass2_2,syst,shared,arg1);
2543 end match;
2544 end HK1;
2545
2546 protected function HK2
2547 "function: HK2, helper for HK
2548 author: Frenkel TUD 2012-03"
2549 input list<list<Integer>> meqns "Marked Equations for Index Reduction";
2550 input list<Integer> unmatched;
2551 input list<Integer> changedEqns;
2552 input array<Integer> rowmarks;
2553 input array<Integer> collummarks;
2554 input array<Integer> level;
2555 input BackendDAE.EqSystem isyst;
2556 input BackendDAE.Shared ishared;
2557 input Integer nv;
2558 input Integer ne;
2559 input array<Integer> ass1 "eqn := ass1[var]";
2560 input array<Integer> ass2 "var := ass2[eqn]";
2561 input BackendDAE.MatchingOptions inMatchingOptions;
2562 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
2563 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
2564 output list<Integer> outunmatched;
2565 output array<Integer> outrowmarks;
2566 output array<Integer> outcollummarks;
2567 output array<Integer> outlevel;
2568 output Integer nvars;
2569 output Integer neqns;
2570 output array<Integer> outAss1;
2571 output array<Integer> outAss2;
2572 output BackendDAE.EqSystem osyst;
2573 output BackendDAE.Shared oshared;
2574 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
2575 algorithm
2576 (outunmatched,outrowmarks,outcollummarks,outlevel,nvars,neqns,outAss1,outAss2,osyst,oshared,outArg):=
2577 match (meqns, inMatchingOptions)
2578 local
2579 Integer nv_1,ne_1;
2580 list<Integer> unmatched1;
2581 BackendDAE.StructurallySingularSystemHandlerArg arg;
2582 BackendDAE.EqSystem syst;
2583 BackendDAE.Shared shared;
2584 array<Integer> ass1_1,ass2_1,rowmarks1,collummarks1,level1;
2585
2586 case ({}, _)
2587 then
2588 (unmatched,rowmarks,collummarks,level,nv,ne,ass1,ass2,isyst,ishared,inArg);
2589 case (_, (BackendDAE.INDEX_REDUCTION(),_))
2590 algorithm
2591 ✗ (unmatched1,_,syst,shared,ass2_1,ass1_1,arg) := sssHandler(meqns,0,isyst,ishared,ass2,ass1,inArg);
2592 ✗ ne_1 := BackendDAEUtil.systemSize(syst);
2593 ✗ nv_1 := BackendVariable.daenumVariables(syst);
2594 ✗ ass1_1 := assignmentsArrayExpand(ass1_1,ne_1,arrayLength(ass1),-1);
2595 ✗ ass2_1 := assignmentsArrayExpand(ass2_1,nv_1,arrayLength(ass2),-1);
2596 ✗ rowmarks1 := assignmentsArrayExpand(rowmarks,nv_1,arrayLength(rowmarks),-1);
2597 ✗ collummarks1 := assignmentsArrayExpand(collummarks,ne_1,arrayLength(collummarks),-1);
2598 ✗ level1 := assignmentsArrayExpand(level,ne_1,arrayLength(level),-1);
2599 ✗ then
2600 (unmatched1,rowmarks1,collummarks1,level1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg);
2601 case (_, _)
2602 algorithm
2603 ✗ singularSystemError(meqns,0,isyst,ishared,ass1,ass2,inArg);
2604 ✗ then
2605 fail();
2606 end match;
2607 end HK2;
2608
2609 protected function HKphase
2610 "function helper for HK, traverses all unmatched
2611 colums and run a BFS and DFS
2612 author: Frenkel TUD 2012-03"
2613 input Integer i;
2614 input list<Integer> U;
2615 input Integer nv;
2616 input Integer ne;
2617 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
2618 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
2619 input array<Integer> rowmarks;
2620 input array<Integer> collummarks;
2621 input array<Integer> level;
2622 input array<Integer> ass1 "ass[eqnindx]=varindx";
2623 input array<Integer> ass2 "ass[varindx]=eqnindx";
2624 input Integer previousUnmatched;
2625 input list<Integer> unMatched;
2626 output Integer outI;
2627 output list<Integer> outunMatched;
2628 algorithm
2629 (outI,outunMatched):=
2630 matchcontinue U
2631 local
2632 list<Integer> unmatched;
2633 list<tuple<Integer,Integer>> rows;
2634 Integer i_1;
2635 case {}
2636 algorithm
2637 // no augmenting path is found in phase
2638 ✗ true:=intEq(previousUnmatched,listLength(unMatched));
2639 ✗ then
2640 (i,unMatched);
2641 case {}
2642 algorithm
2643 // augmenting path is found in phase, next round
2644 ✗ (i_1,unmatched) := HKphase(i+1,unMatched,nv,ne,m,mT,rowmarks,collummarks,level,ass1,ass2,listLength(unMatched),{});
2645 then
2646 (i_1,unmatched);
2647 case _
2648 algorithm
2649 // BFS phase to get the level information
2650 ✗ rows := HKBFS(U,nv,ne,m,mT,rowmarks,i,level,NONE(),ass1,ass2,{});
2651 // DFS to match
2652 ✗ HKDFS(rows,i,nv,ne,m,mT,collummarks,level,ass1,ass2,{});
2653 // remove matched collums from U
2654 ✗ unmatched := HKgetUnmatched(U,ass1,{});
2655 ✗ (i_1,unmatched) := HKphase(i,{},nv,ne,m,mT,rowmarks,collummarks,level,ass1,ass2,previousUnmatched,unmatched);
2656 then
2657 (i_1,unmatched);
2658 else
2659 algorithm
2660 ✗ Error.addInternalError("function HKphase failed", sourceInfo());
2661 ✗ then
2662 fail();
2663 end matchcontinue;
2664 end HKphase;
2665
2666 protected function HKgetUnmatched
2667 input list<Integer> U;
2668 input array<Integer> ass1 "eqn := ass1[var]";
2669 input list<Integer> inUnmatched;
2670 output list<Integer> outUnmatched;
2671 algorithm
2672 outUnmatched:=
2673 matchcontinue U
2674 local
2675 list<Integer> rest;
2676 Integer c;
2677 case {} then inUnmatched;
2678 case c::rest
2679 algorithm
2680 ✗ true := intGt(ass1[c],0);
2681 ✗ then
2682 HKgetUnmatched(rest,ass1,inUnmatched);
2683 case c::rest
2684 ✗ then
2685 HKgetUnmatched(rest,ass1,c::inUnmatched);
2686 end matchcontinue;
2687 end HKgetUnmatched;
2688
2689 protected function HKBFS
2690 "function helper for HK, traverses all colums and perform a BFSB phase on each to get the level information
2691 the BFS stops at a colum with unmatched rows
2692 author: Frenkel TUD 2012-03"
2693 input list<Integer> colums;
2694 input Integer nv;
2695 input Integer ne;
2696 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
2697 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
2698 input array<Integer> rowmarks;
2699 input Integer i;
2700 input array<Integer> level;
2701 input Option<Integer> lowestL "lowest level find unmatched rows";
2702 input array<Integer> ass1 "ass[eqnindx]=varindx";
2703 input array<Integer> ass2 "ass[varindx]=eqnindx";
2704 input list<tuple<Integer,Integer>> inRows "(row,level)";
2705 output list<tuple<Integer,Integer>> outRows "unmatched rows found by BFS";
2706 algorithm
2707 outRows:=
2708 match colums
2709 local
2710 list<Integer> rest;
2711 list<tuple<Integer,Integer>> rows;
2712 Integer c;
2713 Option<Integer> ll;
2714 case {} then inRows;
2715 case c::rest
2716 algorithm
2717 ✗ (rows,ll) := HKBFSBphase({c},i,0,lowestL,nv,ne,m,mT,rowmarks,level,ass1,ass2,inRows,{});
2718 ✗ then
2719 HKBFS(rest,nv,ne,m,mT,rowmarks,i,level,ll,ass1,ass2,rows);
2720 else
2721 algorithm
2722 ✗ Error.addInternalError("function HKBFS failed in phase " + intString(i), sourceInfo());
2723 ✗ then
2724 fail();
2725 end match;
2726 end HKBFS;
2727
2728 protected function HKBFSBphase
2729 "function helper for HKBFS, traverses all colums and perform a BFSB phase on each
2730 author: Frenkel TUD 2012-03"
2731 input list<Integer> queue;
2732 input Integer i;
2733 input Integer l "current level";
2734 input Option<Integer> lowestL "lowest level find unmatched rows";
2735 input Integer nv;
2736 input Integer ne;
2737 input BackendDAE.AdjacencyMatrix m;
2738 input BackendDAE.AdjacencyMatrixT mT;
2739 input array<Integer> rowmarks;
2740 input array<Integer> level;
2741 input array<Integer> ass1 "eqn := ass1[var]";
2742 input array<Integer> ass2 "var := ass2[eqn]";
2743 input list<tuple<Integer,Integer>> inRows;
2744 input list<Integer> queue1;
2745 output list<tuple<Integer,Integer>> outRows;
2746 output Option<Integer> outlowestL;
2747 algorithm
2748 (outRows,outlowestL) :=
2749 match (queue, lowestL, queue1)
2750 local
2751 list<Integer> rest,queue2,cr;
2752 list<tuple<Integer,Integer>> rows;
2753 Integer c,lowl,l_1;
2754 Boolean b;
2755 Option<Integer> ll;
2756 ✗ case ({}, _, {}) then (inRows,lowestL);
2757 case ({}, SOME(lowl), _)
2758 algorithm
2759 ✗ l_1 := l+1;
2760 ✗ b := intGt(l_1,lowl);
2761 ✗ (rows,ll) := HKBFSBphase1(b,queue1,i,l_1,lowestL,nv,ne,m,mT,rowmarks,level,ass1,ass2,inRows,{});
2762 then
2763 (rows,ll);
2764 case ({}, NONE(), _)
2765 algorithm
2766 ✗ (rows,ll) := HKBFSBphase(queue1,i,l+1,lowestL,nv,ne,m,mT,rowmarks,level,ass1,ass2,inRows,{});
2767 then
2768 (rows,ll);
2769 case (c::rest, _, _)
2770 algorithm
2771 // traverse all adiacent rows
2772 ✗ cr := List.select(m[c], Util.intPositive);
2773 ✗ arrayUpdate(level,c,l);
2774 ✗ (queue2,rows,b) := HKBFStraverseRows(cr,{},i,l,m,mT,rowmarks,level,ass1,ass2,inRows,false);
2775 ✗ queue2 := listAppend(queue1,queue2);
2776 ✗ ll := if b then SOME(l) else lowestL;
2777 ✗ (rows,ll) := HKBFSBphase(rest,i,l,ll,nv,ne,m,mT,rowmarks,level,ass1,ass2,rows,queue2);
2778 then
2779 (rows,ll);
2780 else
2781 algorithm
2782 ✗ Error.addInternalError("function HKBFSBphase failed in phase " + intString(i), sourceInfo());
2783 ✗ then
2784 fail();
2785
2786 end match;
2787 end HKBFSBphase;
2788
2789 protected function HKBFSBphase1
2790 "function helper for HKBFSB
2791 author: Frenkel TUD 2012-03"
2792 input Boolean inUnMaRowFound;
2793 input list<Integer> queue;
2794 input Integer i;
2795 input Integer l;
2796 input Option<Integer> lowestL;
2797 input Integer nv;
2798 input Integer ne;
2799 input BackendDAE.AdjacencyMatrix m;
2800 input BackendDAE.AdjacencyMatrixT mT;
2801 input array<Integer> rowmarks;
2802 input array<Integer> level;
2803 input array<Integer> ass1 "eqn := ass1[var]";
2804 input array<Integer> ass2 "var := ass2[eqn]";
2805 input list<tuple<Integer,Integer>> inRows;
2806 input list<Integer> queue1;
2807 output list<tuple<Integer,Integer>> outRows;
2808 output Option<Integer> outlowestL;
2809 algorithm
2810 (outRows,outlowestL) :=
2811 match inUnMaRowFound
2812 local
2813 Option<Integer> ll;
2814 list<tuple<Integer,Integer>> rows;
2815 ✗ case true then (inRows,SOME(l));
2816 case false
2817 algorithm
2818 ✗ (rows,ll) := HKBFSBphase(queue,i,l,lowestL,nv,ne,m,mT,rowmarks,level,ass1,ass2,inRows,queue1);
2819 then
2820 (rows,ll);
2821 else
2822 algorithm
2823 ✗ Error.addInternalError("function HKBFSBphase1 failed", sourceInfo());
2824 ✗ then
2825 fail();
2826 end match;
2827 end HKBFSBphase1;
2828
2829 protected function HKBFStraverseRows
2830 "function helper for BFSB, traverses all rows of a collum and set level
2831 author: Frenkel TUD 2012-03"
2832 input list<Integer> rows;
2833 input list<Integer> queue;
2834 input Integer i;
2835 input Integer l;
2836 input BackendDAE.AdjacencyMatrix m;
2837 input BackendDAE.AdjacencyMatrixT mT;
2838 input array<Integer> rowmarks;
2839 input array<Integer> level;
2840 input array<Integer> ass1 "eqn := ass1[var]";
2841 input array<Integer> ass2 "var := ass2[eqn]";
2842 input list<tuple<Integer,Integer>> inRows;
2843 input Boolean inunmarowFound;
2844 output list<Integer> outEqnqueue;
2845 output list<tuple<Integer,Integer>> outRows;
2846 output Boolean unmarowFound;
2847 algorithm
2848 (outEqnqueue,outRows,unmarowFound):=
2849 matchcontinue rows
2850 local
2851 list<Integer> rest,queue1;
2852 list<tuple<Integer,Integer>> rowstpl;
2853 Integer rc,r;
2854 Boolean b;
2855 ✗ case {} then (listReverse(queue),inRows,inunmarowFound);
2856 case r::rest
2857 algorithm
2858 // row is visited
2859 ✗ false := intLt(rowmarks[r],i);
2860 ✗ (queue1,rowstpl,b) := HKBFStraverseRows(rest,queue,i,l,m,mT,rowmarks,level,ass1,ass2,inRows,inunmarowFound);
2861 then
2862 (queue1,rowstpl,b);
2863 case r::rest
2864 algorithm
2865 // row is unmatched
2866 ✗ true := intLt(ass2[r],0);
2867 ✗ arrayUpdate(rowmarks,r,i);
2868 ✗ (queue1,rowstpl,b) := HKBFStraverseRows(rest,queue,i,l,m,mT,rowmarks,level,ass1,ass2,(r,l)::inRows,true);
2869 then
2870 (queue1,rowstpl,b);
2871 case r::rest
2872 algorithm
2873 // row is matched
2874 ✗ rc := ass2[r];
2875 ✗ false := intLt(rc,0);
2876 ✗ arrayUpdate(rowmarks,r,i);
2877 ✗ (queue1,rowstpl,b) := HKBFStraverseRows(rest,rc::queue,i,l,m,mT,rowmarks,level,ass1,ass2,inRows,inunmarowFound);
2878 then
2879 (queue1,rowstpl,b);
2880 else
2881 algorithm
2882 ✗ Error.addInternalError("function HKBFStraverseRows failed in phase " + intString(i), sourceInfo());
2883 ✗ then
2884 fail();
2885
2886 end matchcontinue;
2887 end HKBFStraverseRows;
2888
2889 protected function HKDFS
2890 "function helper for HKDFSB, traverses all colums and perform a DFSB phase on each
2891 author: Frenkel TUD 2012-03"
2892 input list<tuple<Integer,Integer>> unmatchedRows;
2893 input Integer i;
2894 input Integer nv;
2895 input Integer ne;
2896 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
2897 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
2898 input array<Integer> collummarks;
2899 input array<Integer> level;
2900 input array<Integer> ass1 "ass[eqnindx]=varindx";
2901 input array<Integer> ass2 "ass[varindx]=eqnindx";
2902 input list<Integer> inUnmatchedRows;
2903 output list<Integer> outUnmatchedRows;
2904 algorithm
2905 outUnmatchedRows:=
2906 match unmatchedRows
2907 local
2908 list<tuple<Integer,Integer>> rest;
2909 list<Integer> ur;
2910 Integer r,l;
2911 Boolean b;
2912 case {} then inUnmatchedRows;
2913 case (r,l)::rest
2914 algorithm
2915 // search augmenting paths
2916 ✗ b := HKDFSphase({r},i,r,l,nv,ne,m,mT,collummarks,level,ass1,ass2,false);
2917 ✗ ur := List.consOnTrue(not b,r,inUnmatchedRows);
2918 ✗ then
2919 HKDFS(rest,i,nv,ne,m,mT,collummarks,level,ass1,ass2,ur);
2920 else
2921 algorithm
2922 ✗ Error.addInternalError("function HKDFS failed in phase " + intString(i), sourceInfo());
2923 ✗ then
2924 fail();
2925
2926 end match;
2927 end HKDFS;
2928
2929 protected function HKDFSphase
2930 "function helper for HKDFSBphase, traverses all colums and perform a DFSB phase on each
2931 author: Frenkel TUD 2012-03"
2932 input list<Integer> stack;
2933 input Integer i;
2934 input Integer r;
2935 input Integer l;
2936 input Integer nv;
2937 input Integer ne;
2938 input BackendDAE.AdjacencyMatrix m;
2939 input BackendDAE.AdjacencyMatrixT mT;
2940 input array<Integer> collummarks;
2941 input array<Integer> level;
2942 input array<Integer> ass1 "eqn := ass1[var]";
2943 input array<Integer> ass2 "var := ass2[eqn]";
2944 input Boolean inMatched;
2945 output Boolean matched;
2946 algorithm
2947 matched :=
2948 match stack
2949 local
2950 list<Integer> collums;
2951 case {} then inMatched;
2952 case _
2953 algorithm
2954 // traverse all adiacent rows
2955 ✗ collums := List.select(mT[r], Util.intPositive);
2956 ✗ then
2957 HKDFStraverseCollums(collums,stack,i,l,nv,ne,m,mT,collummarks,level,ass1,ass2,inMatched);
2958 else
2959 algorithm
2960 ✗ Error.addInternalError("function HKDFSphase failed in phase " + intString(i), sourceInfo());
2961 ✗ then
2962 fail();
2963 end match;
2964 end HKDFSphase;
2965
2966 protected function HKDFStraverseCollums
2967 "function helper for HKDFSB, traverses all collums of a row and search a augmenting path
2968 author: Frenkel TUD 2012-03"
2969 input list<Integer> collums;
2970 input list<Integer> stack;
2971 input Integer i;
2972 input Integer l;
2973 input Integer nv;
2974 input Integer ne;
2975 input BackendDAE.AdjacencyMatrix m;
2976 input BackendDAE.AdjacencyMatrixT mT;
2977 input array<Integer> collummarks;
2978 input array<Integer> level;
2979 input array<Integer> ass1 "eqn := ass1[var]";
2980 input array<Integer> ass2 "var := ass2[eqn]";
2981 input Boolean inMatched;
2982 output Boolean matched;
2983 algorithm
2984 matched:=
2985 matchcontinue collums
2986 local
2987 list<Integer> rest;
2988 Integer r,c;
2989 Boolean b;
2990 case {} then inMatched;
2991 case c::rest
2992 algorithm
2993 // collum is not in graph
2994 ✗ false := intEq(level[c],l);
2995 ✗ then
2996 HKDFStraverseCollums(rest,stack,i,l,nv,ne,m,mT,collummarks,level,ass1,ass2,inMatched);
2997 case c::_
2998 algorithm
2999 // collum is in graph
3000 ✗ true := intEq(level[c],l);
3001 // collum is unvisited
3002 ✗ true := intLt(collummarks[c],i);
3003 // collum is unmatched
3004 ✗ true := intLt(ass1[c],0);
3005 ✗ HKDFSreasign(stack,c,ass1,ass2);
3006 then
3007 true;
3008 case c::rest
3009 algorithm
3010 // collum is in graph
3011 ✗ true := intEq(level[c],l);
3012 // collum is unvisited
3013 ✗ true := intLt(collummarks[c],i);
3014 // collum is matched
3015 ✗ r := ass1[c];
3016 ✗ false := intLt(r,0);
3017 ✗ arrayUpdate(collummarks,c,i);
3018 ✗ b := HKDFSphase(r::stack,i,r,l-1,nv,ne,m,mT,collummarks,level,ass1,ass2,inMatched);
3019 ✗ then
3020 HKDFStraverseCollums1(b,rest,stack,i,l,nv,ne,m,mT,collummarks,level,ass1,ass2);
3021 case c::rest
3022 algorithm
3023 // collum is in graph
3024 ✗ true := intEq(level[c],l);
3025 // collum is visited
3026 ✗ false := intLt(collummarks[c],i);
3027 ✗ then
3028 HKDFStraverseCollums(rest,stack,i,l,nv,ne,m,mT,collummarks,level,ass1,ass2,inMatched);
3029 else
3030 algorithm
3031 ✗ Error.addInternalError("function HKDFStraverseCollums failed", sourceInfo());
3032 ✗ then
3033 fail();
3034 end matchcontinue;
3035 end HKDFStraverseCollums;
3036
3037 protected function HKDFStraverseCollums1
3038 "function helper for HKDFSBtraverseCollums
3039 author: Frenkel TUD 2012-03"
3040 input Boolean inMatched;
3041 input list<Integer> rows;
3042 input list<Integer> stack;
3043 input Integer i;
3044 input Integer l;
3045 input Integer nv;
3046 input Integer ne;
3047 input BackendDAE.AdjacencyMatrix m;
3048 input BackendDAE.AdjacencyMatrixT mT;
3049 input array<Integer> collummarks;
3050 input array<Integer> level;
3051 input array<Integer> ass1 "eqn := ass1[var]";
3052 input array<Integer> ass2 "var := ass2[eqn]";
3053 output Boolean matched;
3054 algorithm
3055 ✗ matched:=
3056 match inMatched
3057 case true then inMatched;
3058 else HKDFStraverseCollums(rows,stack,i,l,nv,ne,m,mT,collummarks,level,ass1,ass2,inMatched);
3059 end match;
3060 end HKDFStraverseCollums1;
3061
3062 protected function HKDFSreasign
3063 "function helper for HKDFS, reasignment(rematching) allong the augmenting path
3064 remove all edges from the assignments that are in the path
3065 add all other edges to the assignment
3066 author: Frenkel TUD 2012-03"
3067 input list<Integer> stack;
3068 input Integer c;
3069 input array<Integer> ass1 "eqn := ass1[var]";
3070 input array<Integer> ass2 "var := ass2[eqn]";
3071 algorithm
3072 () := match stack
3073 local
3074 Integer r,cr;
3075 list<Integer> rest;
3076 case {} then ();
3077 case r::rest
3078 algorithm
3079 ✗ cr := ass2[r];
3080 ✗ arrayUpdate(ass1,c,r);
3081 ✗ arrayUpdate(ass2,r,c);
3082 ✗ HKDFSreasign(rest,cr,ass1,ass2);
3083 then ();
3084 end match;
3085 end HKDFSreasign;
3086
3087
3088 public function HKDW
3089 " complexity O(sqrt(n)*tau)
3090 author: Frenkel TUD 2012-03"
3091 input BackendDAE.EqSystem isyst;
3092 input BackendDAE.Shared ishared;
3093 input Boolean clearMatching;
3094 input BackendDAE.MatchingOptions inMatchingOptions;
3095 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
3096 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
3097 output BackendDAE.EqSystem osyst;
3098 output BackendDAE.Shared oshared;
3099 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
3100 algorithm
3101 (osyst,oshared,outArg) :=
3102 matchcontinue isyst
3103 local
3104 Integer nvars,neqns;
3105 BackendDAE.AdjacencyMatrix m;
3106 BackendDAE.AdjacencyMatrixT mt;
3107 array<Integer> vec1,vec2;
3108 BackendDAE.StructurallySingularSystemHandlerArg arg;
3109 BackendDAE.EqSystem syst;
3110 BackendDAE.Shared shared;
3111 array<Integer> rowmarks,level,collummarks;
3112 list<Integer> unmatched;
3113 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
3114 algorithm
3115 ✗ neqns := BackendDAEUtil.systemSize(isyst);
3116 ✗ nvars := BackendVariable.daenumVariables(isyst);
3117 ✗ true := intGt(nvars,0);
3118 ✗ true := intGt(neqns,0);
3119 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
3120 ✗ rowmarks := arrayCreate(nvars,-1);
3121 ✗ collummarks := arrayCreate(neqns,-1);
3122 ✗ level := arrayCreate(neqns,-1);
3123 ✗ unmatched := cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,true);
3124 ✗ (vec1,vec2,syst,shared,arg) := HKDW1(0,unmatched,rowmarks,collummarks,level,isyst,ishared,nvars,neqns,vec1,vec2,inMatchingOptions,sssHandler,inArg);
3125 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
3126 ✗ then
3127 (syst,shared,arg);
3128 // fail case if system is empty
3129 case _
3130 algorithm
3131 ✗ neqns := BackendDAEUtil.systemSize(isyst);
3132 ✗ nvars := BackendVariable.daenumVariables(isyst);
3133 ✗ false := intGt(nvars,0);
3134 ✗ false := intGt(neqns,0);
3135 ✗ vec1 := listArray({});
3136 ✗ vec2 := listArray({});
3137 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
3138 then
3139 (syst,ishared,inArg);
3140 else
3141 algorithm
3142 ✗ if Flags.isSet(Flags.FAILTRACE) then
3143 ✗ Debug.trace("- Matching.HKDW failed\n");
3144 end if;
3145 ✗ then
3146 fail();
3147 end matchcontinue;
3148 end HKDW;
3149
3150 protected function HKDW1
3151 "function: HKDW1, helper for HKDW
3152 author: Frenkel TUD 2012-03"
3153 input Integer i;
3154 input list<Integer> unmatched;
3155 input array<Integer> rowmarks;
3156 input array<Integer> collummarks;
3157 input array<Integer> level;
3158 input BackendDAE.EqSystem isyst;
3159 input BackendDAE.Shared ishared;
3160 input Integer nv;
3161 input Integer ne;
3162 input array<Integer> ass1 "eqn := ass1[var]";
3163 input array<Integer> ass2 "var := ass2[eqn]";
3164 input BackendDAE.MatchingOptions inMatchingOptions;
3165 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
3166 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
3167 output array<Integer> outAss1;
3168 output array<Integer> outAss2;
3169 output BackendDAE.EqSystem osyst;
3170 output BackendDAE.Shared oshared;
3171 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
3172 algorithm
3173 (outAss1,outAss2,osyst,oshared,outArg):=
3174 match (unmatched, isyst)
3175 local
3176 BackendDAE.AdjacencyMatrix m,mt;
3177 Integer nv_1,ne_1,i_1;
3178 list<Integer> unmatched1;
3179 list<list<Integer>> meqns;
3180 BackendDAE.StructurallySingularSystemHandlerArg arg,arg1;
3181 BackendDAE.EqSystem syst;
3182 BackendDAE.Shared shared;
3183 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,rowmarks1,collummarks1,level1;
3184 case ({}, _)
3185 then
3186 (ass1,ass2,isyst,ishared,inArg);
3187 case (_, syst as BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)))
3188 algorithm
3189 ✗ (i_1,unmatched1) := HKDWphase(i,unmatched,nv,ne,m,mt,rowmarks,collummarks,level,ass1,ass2,listLength(unmatched),{});
3190 ✗ meqns := getEqnsforIndexReduction(unmatched1,ne,m,mt,ass1,ass2,inArg);
3191 ✗ (unmatched1,rowmarks1,collummarks1,level1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg) := HK2(meqns,unmatched1,{},rowmarks,collummarks,level,syst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
3192 ✗ (ass1_2,ass2_2,syst,shared,arg1) := HKDW1(i_1+1,unmatched1,rowmarks1,collummarks1,level1,syst,shared,nv_1,ne_1,ass1_1,ass2_1,inMatchingOptions,sssHandler,arg);
3193 then
3194 (ass1_2,ass2_2,syst,shared,arg1);
3195 end match;
3196 end HKDW1;
3197
3198 protected function HKDWphase
3199 "function helper for HKDW, traverses all unmatched
3200 colums and run a BFS and DFS
3201 author: Frenkel TUD 2012-03"
3202 input Integer i;
3203 input list<Integer> U;
3204 input Integer nv;
3205 input Integer ne;
3206 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
3207 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
3208 input array<Integer> rowmarks;
3209 input array<Integer> collummarks;
3210 input array<Integer> level;
3211 input array<Integer> ass1 "ass[eqnindx]=varindx";
3212 input array<Integer> ass2 "ass[varindx]=eqnindx";
3213 input Integer previousUnmatched;
3214 input list<Integer> unMatched;
3215 output Integer outI;
3216 output list<Integer> outunMatched;
3217 algorithm
3218 (outI,outunMatched):=
3219 matchcontinue U
3220 local
3221 list<Integer> unmatched;
3222 list<tuple<Integer,Integer>> rows;
3223 list<Integer> ur;
3224 Integer i_1;
3225 case {}
3226 algorithm
3227 // no augmenting path is found in phase
3228 ✗ true:=intEq(previousUnmatched,listLength(unMatched));
3229 ✗ then
3230 (i,unMatched);
3231 case {}
3232 algorithm
3233 // augmenting path is found in phase, next round
3234 ✗ (i_1,unmatched) := HKphase(i+1,unMatched,nv,ne,m,mT,rowmarks,collummarks,level,ass1,ass2,listLength(unMatched),{});
3235 then
3236 (i_1,unmatched);
3237 case _
3238 algorithm
3239 // BFS phase to get the level information
3240 ✗ rows := HKBFS(U,nv,ne,m,mT,rowmarks,i,level,NONE(),ass1,ass2,{});
3241 // DFS to match
3242 ✗ ur := HKDFS(rows,i,nv,ne,m,mT,collummarks,level,ass1,ass2,{});
3243 // second DFS in full graph
3244 ✗ HKDWDFS(ur,i,nv,ne,m,mT,collummarks,ass1,ass2);
3245 // remove matched collums from U
3246 ✗ unmatched := HKgetUnmatched(U,ass1,{});
3247 ✗ (i_1,unmatched) := HKphase(i,{},nv,ne,m,mT,rowmarks,collummarks,level,ass1,ass2,previousUnmatched,unmatched);
3248 then
3249 (i_1,unmatched);
3250 else
3251 algorithm
3252 ✗ Error.addInternalError("function HKDWphase failed", sourceInfo());
3253 ✗ then
3254 fail();
3255 end matchcontinue;
3256 end HKDWphase;
3257
3258 protected function HKDWDFS
3259 "function helper for HKDWDFSB, traverses all colums and perform a DFSB phase on each
3260 author: Frenkel TUD 2012-03"
3261 input list<Integer> unmatchedRows;
3262 input Integer i;
3263 input Integer nv;
3264 input Integer ne;
3265 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
3266 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
3267 input array<Integer> collummarks;
3268 input array<Integer> ass1 "ass[eqnindx]=varindx";
3269 input array<Integer> ass2 "ass[varindx]=eqnindx";
3270 algorithm
3271 ():=
3272 match unmatchedRows
3273 local
3274 list<Integer> rest;
3275 Integer r;
3276 case {} then ();
3277 case r::rest
3278 algorithm
3279 // search augmenting paths
3280 ✗ HKDWDFSphase({r},i,r,nv,ne,m,mT,collummarks,ass1,ass2,false);
3281 ✗ HKDWDFS(rest,i,nv,ne,m,mT,collummarks,ass1,ass2);
3282 then
3283 ();
3284 else
3285 algorithm
3286 ✗ Error.addInternalError("function HKDWDFS failed in phase " + intString(i), sourceInfo());
3287 ✗ then
3288 fail();
3289
3290 end match;
3291 end HKDWDFS;
3292
3293 protected function HKDWDFSphase
3294 "function helper for HKDWDFSBphase, traverses all colums and perform a DFSB phase on each
3295 author: Frenkel TUD 2012-03"
3296 input list<Integer> stack;
3297 input Integer i;
3298 input Integer r;
3299 input Integer nv;
3300 input Integer ne;
3301 input BackendDAE.AdjacencyMatrix m;
3302 input BackendDAE.AdjacencyMatrixT mT;
3303 input array<Integer> collummarks;
3304 input array<Integer> ass1 "eqn := ass1[var]";
3305 input array<Integer> ass2 "var := ass2[eqn]";
3306 input Boolean inMatched;
3307 output Boolean matched;
3308 algorithm
3309 matched :=
3310 match stack
3311 local
3312 list<Integer> collums;
3313 case {} then inMatched;
3314 case _
3315 algorithm
3316 // traverse all adiacent rows
3317 ✗ collums := List.select(mT[r], Util.intPositive);
3318 ✗ then
3319 HKDWDFStraverseCollums(collums,stack,i,nv,ne,m,mT,collummarks,ass1,ass2,inMatched);
3320 else
3321 algorithm
3322 ✗ Error.addInternalError("function HKDWDFSphase failed in phase " + intString(i), sourceInfo());
3323 ✗ then
3324 fail();
3325 end match;
3326 end HKDWDFSphase;
3327
3328 protected function HKDWDFStraverseCollums
3329 "function helper for HKDWDFSB, traverses all collums of a row and search a augmenting path
3330 author: Frenkel TUD 2012-03"
3331 input list<Integer> collums;
3332 input list<Integer> stack;
3333 input Integer i;
3334 input Integer nv;
3335 input Integer ne;
3336 input BackendDAE.AdjacencyMatrix m;
3337 input BackendDAE.AdjacencyMatrixT mT;
3338 input array<Integer> collummarks;
3339 input array<Integer> ass1 "eqn := ass1[var]";
3340 input array<Integer> ass2 "var := ass2[eqn]";
3341 input Boolean inMatched;
3342 output Boolean matched;
3343 algorithm
3344 matched:=
3345 matchcontinue collums
3346 local
3347 list<Integer> rest;
3348 Integer r,c;
3349 Boolean b;
3350 case {} then inMatched;
3351 case c::_
3352 algorithm
3353 // collum is unvisited
3354 ✗ true := intLt(collummarks[c],i);
3355 // collum is unmatched
3356 ✗ true := intLt(ass1[c],0);
3357 ✗ HKDFSreasign(stack,c,ass1,ass2);
3358 then
3359 true;
3360 case c::rest
3361 algorithm
3362 // collum is unvisited
3363 ✗ true := intLt(collummarks[c],i);
3364 // collum is matched
3365 ✗ r := ass1[c];
3366 ✗ false := intLt(r,0);
3367 ✗ arrayUpdate(collummarks,c,i);
3368 ✗ b := HKDWDFSphase(r::stack,i,r,nv,ne,m,mT,collummarks,ass1,ass2,inMatched);
3369 ✗ then
3370 HKDWDFStraverseCollums1(b,rest,stack,i,nv,ne,m,mT,collummarks,ass1,ass2);
3371 case c::rest
3372 algorithm
3373 // collum is visited
3374 ✗ false := intLt(collummarks[c],i);
3375 ✗ then
3376 HKDWDFStraverseCollums(rest,stack,i,nv,ne,m,mT,collummarks,ass1,ass2,inMatched);
3377 else
3378 algorithm
3379 ✗ Error.addInternalError("function HKDWDFStraverseCollums failed", sourceInfo());
3380 ✗ then
3381 fail();
3382 end matchcontinue;
3383 end HKDWDFStraverseCollums;
3384
3385 protected function HKDWDFStraverseCollums1
3386 "function helper for HKDWDFSBtraverseCollums
3387 author: Frenkel TUD 2012-03"
3388 input Boolean inMatched;
3389 input list<Integer> rows;
3390 input list<Integer> stack;
3391 input Integer i;
3392 input Integer nv;
3393 input Integer ne;
3394 input BackendDAE.AdjacencyMatrix m;
3395 input BackendDAE.AdjacencyMatrixT mT;
3396 input array<Integer> collummarks;
3397 input array<Integer> ass1 "eqn := ass1[var]";
3398 input array<Integer> ass2 "var := ass2[eqn]";
3399 output Boolean matched;
3400 algorithm
3401 ✗ matched:=
3402 match inMatched
3403 case true then inMatched;
3404 else HKDWDFStraverseCollums(rows,stack,i,nv,ne,m,mT,collummarks,ass1,ass2,inMatched);
3405 end match;
3406 end HKDWDFStraverseCollums1;
3407
3408
3409 public function ABMP
3410 " complexity O(sqrt(n)*tau)
3411 author: Frenkel TUD 2012-03"
3412 input BackendDAE.EqSystem isyst;
3413 input BackendDAE.Shared ishared;
3414 input Boolean clearMatching;
3415 input BackendDAE.MatchingOptions inMatchingOptions;
3416 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
3417 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
3418 output BackendDAE.EqSystem osyst;
3419 output BackendDAE.Shared oshared;
3420 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
3421 algorithm
3422 (osyst,oshared,outArg) :=
3423 matchcontinue isyst
3424 local
3425 Integer nvars,neqns;
3426 BackendDAE.AdjacencyMatrix m;
3427 BackendDAE.AdjacencyMatrixT mt;
3428 array<Integer> vec1,vec2;
3429 BackendDAE.StructurallySingularSystemHandlerArg arg;
3430 BackendDAE.EqSystem syst;
3431 BackendDAE.Shared shared;
3432 array<Integer> rowmarks,level,collummarks,rlevel,colptrs;
3433 list<Integer> unmatched;
3434 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
3435 algorithm
3436 ✗ neqns := BackendDAEUtil.systemSize(isyst);
3437 ✗ nvars := BackendVariable.daenumVariables(isyst);
3438 ✗ true := intGt(nvars,0);
3439 ✗ true := intGt(neqns,0);
3440 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
3441 ✗ rowmarks := arrayCreate(nvars,-1);
3442 ✗ collummarks := arrayCreate(neqns,-1);
3443 ✗ level := arrayCreate(neqns,-1);
3444 ✗ rlevel := arrayCreate(nvars,nvars);
3445 ✗ colptrs := arrayCreate(neqns,-1);
3446 ✗ unmatched := cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,true);
3447 ✗ (vec1,vec2,syst,shared,arg) := ABMP1(1,unmatched,rowmarks,collummarks,level,rlevel,colptrs,isyst,ishared,nvars,neqns,vec1,vec2,inMatchingOptions,sssHandler,inArg);
3448 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
3449 ✗ then
3450 (syst,shared,arg);
3451 // fail case if system is empty
3452 case _
3453 algorithm
3454 ✗ neqns := BackendDAEUtil.systemSize(isyst);
3455 ✗ nvars := BackendVariable.daenumVariables(isyst);
3456 ✗ false := intGt(nvars,0);
3457 ✗ false := intGt(neqns,0);
3458 ✗ vec1 := listArray({});
3459 ✗ vec2 := listArray({});
3460 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
3461 then
3462 (syst,ishared,inArg);
3463 else
3464 algorithm
3465 ✗ if Flags.isSet(Flags.FAILTRACE) then
3466 ✗ Debug.trace("- Matching.ABMP failed\n");
3467 end if;
3468 ✗ then
3469 fail();
3470 end matchcontinue;
3471 end ABMP;
3472
3473 protected function ABMP1
3474 "function: ABMP1, helper for HKABMP
3475 author: Frenkel TUD 2012-03"
3476 input Integer i;
3477 input list<Integer> unmatched;
3478 input array<Integer> rowmarks;
3479 input array<Integer> collummarks;
3480 input array<Integer> level;
3481 input array<Integer> rlevel;
3482 input array<Integer> colptrs;
3483 input BackendDAE.EqSystem isyst;
3484 input BackendDAE.Shared ishared;
3485 input Integer nv;
3486 input Integer ne;
3487 input array<Integer> ass1 "eqn := ass1[var]";
3488 input array<Integer> ass2 "var := ass2[eqn]";
3489 input BackendDAE.MatchingOptions inMatchingOptions;
3490 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
3491 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
3492 output array<Integer> outAss1;
3493 output array<Integer> outAss2;
3494 output BackendDAE.EqSystem osyst;
3495 output BackendDAE.Shared oshared;
3496 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
3497 algorithm
3498 (outAss1,outAss2,osyst,oshared,outArg):=
3499 match (unmatched, isyst)
3500 local
3501 BackendDAE.AdjacencyMatrix m,mt;
3502 Integer nv_1,ne_1,i_1,lim;
3503 list<Integer> unmatched1;
3504 list<list<Integer>> meqns;
3505 BackendDAE.StructurallySingularSystemHandlerArg arg,arg1;
3506 BackendDAE.EqSystem syst;
3507 BackendDAE.Shared shared;
3508 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,rowmarks1,collummarks1,level1,rlevel1;
3509 case ({}, _)
3510 then
3511 (ass1,ass2,isyst,ishared,inArg);
3512 case (_, BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)))
3513 algorithm
3514 ✗ lim := integer(0.1 * sqrt(arrayLength(ass1)));
3515 ✗ unmatched1 := ABMPphase(unmatched,i,nv,ne,m,mt,rowmarks,rlevel,colptrs,lim,ass1,ass2);
3516 ✗ (i_1,unmatched1) := HKphase(i+1,unmatched,nv,ne,m,mt,rowmarks,collummarks,level,ass1,ass2,listLength(unmatched),{});
3517 ✗ meqns := getEqnsforIndexReduction(unmatched1,ne,m,mt,ass1,ass2,inArg);
3518 ✗ (unmatched1,rowmarks1,collummarks1,level1,rlevel1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg) := ABMP2(meqns,unmatched1,{},rowmarks,collummarks,level,rlevel,isyst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
3519 ✗ (ass1_2,ass2_2,syst,shared,arg1) := ABMP1(i_1+1,unmatched1,rowmarks1,collummarks1,level1,rlevel1,colptrs,syst,shared,nv_1,ne_1,ass1_1,ass2_1,inMatchingOptions,sssHandler,arg);
3520 then
3521 (ass1_2,ass2_2,syst,shared,arg1);
3522 end match;
3523 end ABMP1;
3524
3525 protected function ABMP2
3526 "function: ABMP2, helper for ABMP
3527 author: Frenkel TUD 2012-03"
3528 input list<list<Integer>> meqns "Marked Equations for Index Reduction";
3529 input list<Integer> unmatched;
3530 input list<Integer> changedEqns;
3531 input array<Integer> rowmarks;
3532 input array<Integer> collummarks;
3533 input array<Integer> level;
3534 input array<Integer> rlevel;
3535 input BackendDAE.EqSystem isyst;
3536 input BackendDAE.Shared ishared;
3537 input Integer nv;
3538 input Integer ne;
3539 input array<Integer> ass1 "eqn := ass1[var]";
3540 input array<Integer> ass2 "var := ass2[eqn]";
3541 input BackendDAE.MatchingOptions inMatchingOptions;
3542 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
3543 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
3544 output list<Integer> outunmatched;
3545 output array<Integer> outrowmarks;
3546 output array<Integer> outcollummarks;
3547 output array<Integer> outlevel;
3548 output array<Integer> outrlevel;
3549 output Integer nvars;
3550 output Integer neqns;
3551 output array<Integer> outAss1;
3552 output array<Integer> outAss2;
3553 output BackendDAE.EqSystem osyst;
3554 output BackendDAE.Shared oshared;
3555 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
3556 algorithm
3557 (outunmatched,outrowmarks,outcollummarks,outlevel,outrlevel,nvars,neqns,outAss1,outAss2,osyst,oshared,outArg):=
3558 match (meqns, inMatchingOptions)
3559 local
3560 Integer nv_1,ne_1;
3561 list<Integer> unmatched1;
3562 BackendDAE.StructurallySingularSystemHandlerArg arg;
3563 BackendDAE.EqSystem syst;
3564 BackendDAE.Shared shared;
3565 array<Integer> ass1_1,ass2_1,rowmarks1,collummarks1,level1,rlevel1;
3566
3567 case ({}, _)
3568 then
3569 (unmatched,rowmarks,collummarks,level,rlevel,nv,ne,ass1,ass2,isyst,ishared,inArg);
3570 case (_, (BackendDAE.INDEX_REDUCTION(),_))
3571 algorithm
3572 ✗ (unmatched1,_,syst,shared,ass2_1,ass1_1,arg) := sssHandler(meqns,0,isyst,ishared,ass2,ass1,inArg);
3573 ✗ ne_1 := BackendDAEUtil.systemSize(syst);
3574 ✗ nv_1 := BackendVariable.daenumVariables(syst);
3575 ✗ ass1_1 := assignmentsArrayExpand(ass1_1,ne_1,arrayLength(ass1_1),-1);
3576 ✗ ass2_1 := assignmentsArrayExpand(ass2_1,nv_1,arrayLength(ass2_1),-1);
3577 ✗ rowmarks1 := assignmentsArrayExpand(rowmarks,nv_1,arrayLength(rowmarks),-1);
3578 ✗ collummarks1 := assignmentsArrayExpand(collummarks,ne_1,arrayLength(collummarks),-1);
3579 ✗ rlevel1 := arrayCreate(arrayLength(ass2_1),arrayLength(ass2_1));
3580 ✗ level1 := assignmentsArrayExpand(level,ne_1,arrayLength(level),-1);
3581 ✗ then
3582 (unmatched1,rowmarks1,collummarks1,level1,rlevel1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg);
3583 case (_, _)
3584 algorithm
3585 ✗ singularSystemError(meqns,0,isyst,ishared,ass2,ass1,inArg);
3586 ✗ then
3587 fail();
3588 end match;
3589 end ABMP2;
3590
3591 protected function ABMPphase
3592 "function helper for ABMP, traverses all unmatched
3593 colums and run a BFS and DFS to assign level information
3594 and increase matching.
3595 author: Frenkel TUD 2012-03"
3596 input list<Integer> U;
3597 input Integer i;
3598 input Integer nv;
3599 input Integer ne;
3600 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
3601 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
3602 input array<Integer> rowmarks;
3603 input array<Integer> level;
3604 input array<Integer> colptrs;
3605 input Integer lim;
3606 input array<Integer> ass1 "ass[eqnindx]=varindx";
3607 input array<Integer> ass2 "ass[varindx]=eqnindx";
3608 output list<Integer> unMatched;
3609 algorithm
3610 unMatched:=
3611 match U
3612 local
3613 list<Integer> ur;
3614 case {} then {};
3615 case _
3616 algorithm
3617 // BFS to assign levels
3618 ✗ ur := ABMPBFSphase(U,i,0,lim,listLength(U),nv,ne,m,mT,rowmarks,level,ass1,ass2,{},{});
3619 ✗ then
3620 ABMPphase1(U,ur,i,nv,ne,m,mT,rowmarks,level,colptrs,lim,ass1,ass2);
3621 else
3622 algorithm
3623 ✗ Error.addInternalError("function ABMPphase failed", sourceInfo());
3624 ✗ then
3625 fail();
3626 end match;
3627 end ABMPphase;
3628
3629 protected function ABMPphase1
3630 "function helper for ABMP, traverses all unmatched
3631 colums and run a BFS and DFS to assign level information
3632 and increase matching.
3633 author: Frenkel TUD 2012-03"
3634 input list<Integer> U;
3635 input list<Integer> unmatchedRows;
3636 input Integer i;
3637 input Integer nv;
3638 input Integer ne;
3639 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
3640 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
3641 input array<Integer> rowmarks;
3642 input array<Integer> level;
3643 input array<Integer> colptrs;
3644 input Integer lim;
3645 input array<Integer> ass1 "ass[eqnindx]=varindx";
3646 input array<Integer> ass2 "ass[varindx]=eqnindx";
3647 output list<Integer> unMatched;
3648 algorithm
3649 unMatched:=
3650 match unmatchedRows
3651 local
3652 list<Integer> unmatched;
3653 Integer L,r;
3654 case {} then U;
3655 case r::_
3656 algorithm
3657 ✗ L := level[r];
3658 ✗ ABMPDFS(unmatchedRows,0,L,nv,ne,m,mT,level,colptrs,ass1,ass2,{});
3659 // remove unmatched collums from U
3660 ✗ unmatched := HKgetUnmatched(U,ass1,{});
3661 ✗ then
3662 ABMPphase2(unmatched,i,L,nv,ne,m,mT,rowmarks,level,colptrs,lim,ass1,ass2);
3663 else
3664 algorithm
3665 ✗ Error.addInternalError("function ABMPphase1 failed", sourceInfo());
3666 ✗ then
3667 fail();
3668 end match;
3669 end ABMPphase1;
3670
3671 protected function ABMPphase2
3672 "function helper for ABMP, traverses all unmatched
3673 colums and run a BFS and DFS to assign level information
3674 and increase matching.
3675 author: Frenkel TUD 2012-03"
3676 input list<Integer> U;
3677 input Integer i;
3678 input Integer L;
3679 input Integer nv;
3680 input Integer ne;
3681 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
3682 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
3683 input array<Integer> rowmarks;
3684 input array<Integer> level;
3685 input array<Integer> colptrs;
3686 input Integer lim;
3687 input array<Integer> ass1 "ass[eqnindx]=varindx";
3688 input array<Integer> ass2 "ass[varindx]=eqnindx";
3689 output list<Integer> unMatched;
3690 algorithm
3691 unMatched:=
3692 matchcontinue U
3693 case {} then U;
3694 case _
3695 algorithm
3696 ✗ true := intGt(50*L,listLength(U));
3697 then
3698 U;
3699 case _
3700 // next round width updated level
3701 ✗ then
3702 ABMPphase(U,i,nv,ne,m,mT,rowmarks,level,colptrs,lim,ass1,ass2);
3703 else
3704 algorithm
3705 ✗ Error.addInternalError("function ABMPphase2 failed", sourceInfo());
3706 ✗ then
3707 fail();
3708 end matchcontinue;
3709 end ABMPphase2;
3710
3711 protected function ABMPBFSphase
3712 "function helper for ABMP, traverses all colums and set level information
3713 author: Frenkel TUD 2012-03"
3714 input list<Integer> queue;
3715 input Integer i;
3716 input Integer L;
3717 input Integer lim;
3718 input Integer lim1;
3719 input Integer nv;
3720 input Integer ne;
3721 input BackendDAE.AdjacencyMatrix m;
3722 input BackendDAE.AdjacencyMatrixT mT;
3723 input array<Integer> rowmarks;
3724 input array<Integer> level;
3725 input array<Integer> ass1 "eqn := ass1[var]";
3726 input array<Integer> ass2 "var := ass2[eqn]";
3727 input list<Integer> nextqueue;
3728 input list<Integer> unMatched;
3729 output list<Integer> outunMatched;
3730 algorithm
3731 outunMatched :=
3732 match (queue, nextqueue)
3733 local
3734 list<Integer> rest,rows,queue1,unmatched;
3735 Integer c,l;
3736 Boolean b;
3737 case ({}, {}) then unMatched;
3738 case ({}, _)
3739 algorithm
3740 ✗ l := L+2;
3741 ✗ b := intGt(l,lim) or intGt(50*l,lim1);
3742 ✗ then
3743 ABMPBFSphase1(b,nextqueue,i,l,lim,lim1,nv,ne,m,mT,rowmarks,level,ass1,ass2,{},unMatched);
3744 case (c::rest, _)
3745 algorithm
3746 // traverse all adiacent rows
3747 ✗ rows := List.select(m[c], Util.intPositive);
3748 ✗ (queue1,unmatched) := ABMPBFStraverseRows(rows,i,L,nv,ne,m,mT,rowmarks,level,ass1,ass2,nextqueue,unMatched);
3749 ✗ then
3750 ABMPBFSphase(rest,i,L,lim,lim1,nv,ne,m,mT,rowmarks,level,ass1,ass2,queue1,unmatched);
3751 else
3752 algorithm
3753 ✗ Error.addInternalError("function ABMPBFSphase failed", sourceInfo());
3754 ✗ then
3755 fail();
3756 end match;
3757 end ABMPBFSphase;
3758
3759 protected function ABMPBFSphase1
3760 "function helper for ABMPBFSphase
3761 author: Frenkel TUD 2012-03"
3762 input Boolean inStop;
3763 input list<Integer> queue;
3764 input Integer i;
3765 input Integer L;
3766 input Integer lim;
3767 input Integer lim1;
3768 input Integer nv;
3769 input Integer ne;
3770 input BackendDAE.AdjacencyMatrix m;
3771 input BackendDAE.AdjacencyMatrixT mT;
3772 input array<Integer> rowmarks;
3773 input array<Integer> level;
3774 input array<Integer> ass1 "eqn := ass1[var]";
3775 input array<Integer> ass2 "var := ass2[eqn]";
3776 input list<Integer> nextqueue;
3777 input list<Integer> unMatched;
3778 output list<Integer> outunMatched;
3779 algorithm
3780 outunMatched :=
3781 match inStop
3782 case true then unMatched;
3783 case false
3784 ✗ then
3785 ABMPBFSphase(queue,i,L,lim,lim1,nv,ne,m,mT,rowmarks,level,ass1,ass2,nextqueue,unMatched);
3786 else
3787 algorithm
3788 ✗ Error.addInternalError("function ABMPBFSphase1 failed", sourceInfo());
3789 ✗ then
3790 fail();
3791 end match;
3792 end ABMPBFSphase1;
3793
3794 protected function ABMPBFStraverseRows
3795 "function helper for ABMPBFS, traverses all rows and assign level informaiton
3796 author: Frenkel TUD 2012-03"
3797 input list<Integer> rows;
3798 input Integer i;
3799 input Integer L;
3800 input Integer nv;
3801 input Integer ne;
3802 input BackendDAE.AdjacencyMatrix m;
3803 input BackendDAE.AdjacencyMatrixT mT;
3804 input array<Integer> rowmarks;
3805 input array<Integer> level;
3806 input array<Integer> ass1 "eqn := ass1[var]";
3807 input array<Integer> ass2 "var := ass2[eqn]";
3808 input list<Integer> queue;
3809 input list<Integer> unMatched;
3810 output list<Integer> outEqnqueue;
3811 output list<Integer> outUnmatched;
3812 algorithm
3813 (outEqnqueue,outUnmatched):=
3814 matchcontinue rows
3815 local
3816 list<Integer> rest,queue1,unmatched;
3817 Integer rc,r;
3818 ✗ case {} then (listReverse(queue),unMatched);
3819 case r::rest
3820 algorithm
3821 // row is unvisited
3822 ✗ false := intEq(rowmarks[r],i);
3823 // row is unmatched
3824 ✗ true := intLt(ass2[r],0);
3825 ✗ arrayUpdate(level,r,L);
3826 ✗ arrayUpdate(rowmarks,r,i);
3827 ✗ (queue1,unmatched) := ABMPBFStraverseRows(rest,i,L,nv,ne,m,mT,rowmarks,level,ass1,ass2,queue,r::unMatched);
3828 then
3829 (queue1,unmatched);
3830 case r::rest
3831 algorithm
3832 // row is unvisited
3833 ✗ false := intEq(rowmarks[r],i);
3834 // row is matched
3835 ✗ rc := ass2[r];
3836 ✗ false := intLt(rc,0);
3837 ✗ arrayUpdate(rowmarks,r,i);
3838 ✗ (queue1,unmatched) := ABMPBFStraverseRows(rest,i,L,nv,ne,m,mT,rowmarks,level,ass1,ass2,rc::queue,unMatched);
3839 then
3840 (queue1,unmatched);
3841 case r::rest
3842 algorithm
3843 // row is visited
3844 ✗ true := intEq(rowmarks[r],i);
3845 ✗ (queue1,unmatched) := ABMPBFStraverseRows(rest,i,L,nv,ne,m,mT,rowmarks,level,ass1,ass2,queue,unMatched);
3846 then
3847 (queue1,unmatched);
3848 else
3849 algorithm
3850 ✗ Error.addInternalError("function ABMPBFStraverseRows failed", sourceInfo());
3851 ✗ then
3852 fail();
3853 end matchcontinue;
3854 end ABMPBFStraverseRows;
3855
3856 protected function ABMPDFS
3857 "function helper for ABMPDFS, traverses all rows and perform a DFSB phase on each
3858 author: Frenkel TUD 2012-03"
3859 input list<Integer> unmatchedRows;
3860 input Integer i;
3861 input Integer L;
3862 input Integer nv;
3863 input Integer ne;
3864 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
3865 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
3866 input array<Integer> level;
3867 input array<Integer> colptrs;
3868 input array<Integer> ass1 "ass[eqnindx]=varindx";
3869 input array<Integer> ass2 "ass[varindx]=eqnindx";
3870 input list<Integer> unMatched;
3871 algorithm
3872 ():=
3873 matchcontinue unmatchedRows
3874 local
3875 list<Integer> rest,unmatched;
3876 Integer r,i_1;
3877 Boolean b;
3878 case {} then ();
3879 case _
3880 algorithm
3881 ✗ false := intLt(i,ne);
3882 then ();
3883 case r::rest
3884 algorithm
3885 // search augmenting paths
3886 ✗ arrayUpdate(colptrs,r,0);
3887 ✗ (i_1,b) := ABMPDFSphase({r},i,r,nv,ne,m,mT,level,colptrs,ass1,ass2);
3888 ✗ unmatched := List.consOnTrue(not b, r, unMatched);
3889 ✗ ABMPDFS1(b,r,rest,unmatched,i_1,L,nv,ne,m,mT,level,colptrs,ass1,ass2);
3890 then
3891 ();
3892 else
3893 algorithm
3894 ✗ Error.addInternalError("function ABMPBFS failed", sourceInfo());
3895 ✗ then
3896 fail();
3897 end matchcontinue;
3898 end ABMPDFS;
3899
3900 protected function ABMPDFS1
3901 "function helper for ABMPDFS, traverses all rows and perform a DFSB phase on each
3902 author: Frenkel TUD 2012-03"
3903 input Boolean inMatched;
3904 input Integer r;
3905 input list<Integer> unmatchedRows;
3906 input list<Integer> unMatched;
3907 input Integer i;
3908 input Integer L;
3909 input Integer nv;
3910 input Integer ne;
3911 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
3912 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
3913 input array<Integer> level;
3914 input array<Integer> colptrs;
3915 input array<Integer> ass1 "ass[eqnindx]=varindx";
3916 input array<Integer> ass2 "ass[varindx]=eqnindx";
3917 algorithm
3918 ():=
3919 matchcontinue (inMatched, unmatchedRows, unMatched)
3920 local
3921 list<Integer> unmatched;
3922 Integer r1,r2,l;
3923 case (_, {}, _) then ();
3924 case (true, _, _)
3925 algorithm
3926 ✗ true := intGt(50*L,listLength(unmatchedRows)+listLength(unMatched));
3927 then ();
3928 case (true, _, {})
3929 algorithm
3930 ✗ false := intGt(50*L,listLength(unmatchedRows)+listLength(unMatched));
3931 ✗ ABMPDFS(unmatchedRows,i,L,nv,ne,m,mT,level,colptrs,ass1,ass2,{});
3932 then ();
3933 case (true, r1::_, r2::{})
3934 algorithm
3935 ✗ false := intGt(50*L,listLength(unmatchedRows)+listLength(unMatched));
3936 ✗ false := intEq(L,level[r1]);
3937 ✗ l := level[r2];
3938 ✗ ABMPDFS(r2::unmatchedRows,i,l,nv,ne,m,mT,level,colptrs,ass1,ass2,{});
3939 then ();
3940 case (true, r1::_, _)
3941 algorithm
3942 ✗ false := intGt(50*L,listLength(unmatchedRows)+listLength(unMatched));
3943 ✗ false := intEq(L,level[r1]);
3944 ✗ r2::unmatched := listReverse(unMatched);
3945 ✗ l := level[r2];
3946 ✗ unmatched := listAppend(unmatched,r2::unmatchedRows) annotation(__OpenModelica_DisableListAppendWarning=true);
3947 ✗ ABMPDFS(unmatchedRows,i,l,nv,ne,m,mT,level,colptrs,ass1,ass2,{});
3948 then ();
3949 case (_, r1::_, {})
3950 algorithm
3951 ✗ false := intEq(L,level[r1]);
3952 ✗ l := level[r];
3953 ✗ ABMPDFS(unmatchedRows,i,l,nv,ne,m,mT,level,colptrs,ass1,ass2,{});
3954 then ();
3955 case (_, r1::_, _)
3956 algorithm
3957 ✗ false := intEq(L,level[r1]);
3958 ✗ r2::unmatched := listReverse(unMatched);
3959 ✗ l := level[r2];
3960 ✗ unmatched := listAppend(r2::unmatched,unmatchedRows);
3961 ✗ ABMPDFS(unmatched,i,l,nv,ne,m,mT,level,colptrs,ass1,ass2,{});
3962 then ();
3963 case (_, r1::_, _)
3964 algorithm
3965 ✗ true := intEq(L,level[r1]);
3966 ✗ ABMPDFS(unmatchedRows,i,L,nv,ne,m,mT,level,colptrs,ass1,ass2,unMatched);
3967 then ();
3968 else
3969 algorithm
3970 ✗ Error.addInternalError("function ABMPBFS1 failed", sourceInfo());
3971 ✗ then
3972 fail();
3973 end matchcontinue;
3974 end ABMPDFS1;
3975
3976 protected function ABMPDFSphase
3977 "function helper for ABMPDFSBphase, traverses all colums and perform a DFSB phase on each
3978 author: Frenkel TUD 2012-03"
3979 input list<Integer> stack;
3980 input Integer i;
3981 input Integer r;
3982 input Integer nv;
3983 input Integer ne;
3984 input BackendDAE.AdjacencyMatrix m;
3985 input BackendDAE.AdjacencyMatrixT mT;
3986 input array<Integer> level;
3987 input array<Integer> colptrs;
3988 input array<Integer> ass1 "eqn := ass1[var]";
3989 input array<Integer> ass2 "var := ass2[eqn]";
3990 output Integer outI;
3991 output Boolean matched;
3992 algorithm
3993 (outI,matched) :=
3994 match stack
3995 local
3996 list<Integer> collums;
3997 Integer desL,i_1;
3998 Boolean b;
3999 case {} then (i,false);
4000 case _
4001 algorithm
4002 // traverse all adiacent rows
4003 ✗ collums := List.select(mT[r], Util.intPositive);
4004 ✗ collums := List.stripN(collums,colptrs[r]);
4005 ✗ desL := level[r]-2;
4006 ✗ (i_1,b) := ABMPDFStraverseCollums(collums,1,stack,r,i,desL,nv,ne,m,mT,level,colptrs,ass1,ass2);
4007 then
4008 (i_1,b);
4009 else
4010 algorithm
4011 ✗ Error.addInternalError("function ABMPDFSphase failed in phase " + intString(i), sourceInfo());
4012 ✗ then
4013 fail();
4014 end match;
4015 end ABMPDFSphase;
4016
4017 protected function ABMPDFStraverseCollums
4018 "function helper for ABMPDFSB, traverses all collums of a row and search a augmenting path
4019 author: Frenkel TUD 2012-03"
4020 input list<Integer> collums;
4021 input Integer counter;
4022 input list<Integer> stack;
4023 input Integer r;
4024 input Integer i;
4025 input Integer desL;
4026 input Integer nv;
4027 input Integer ne;
4028 input BackendDAE.AdjacencyMatrix m;
4029 input BackendDAE.AdjacencyMatrixT mT;
4030 input array<Integer> level;
4031 input array<Integer> colptrs;
4032 input array<Integer> ass1 "eqn := ass1[var]";
4033 input array<Integer> ass2 "var := ass2[eqn]";
4034 output Integer outI;
4035 output Boolean matched;
4036 algorithm
4037 (outI,matched):=
4038 matchcontinue collums
4039 local
4040 list<Integer> rest;
4041 Integer rc,c,i_1;
4042 Boolean b;
4043 case {}
4044 algorithm
4045 ✗ arrayUpdate(level,r,level[r]+2);
4046 ✗ arrayUpdate(colptrs,r,0);
4047 ✗ then
4048 (i+1,false);
4049 case c::_
4050 algorithm
4051 // collum is unmatched
4052 ✗ true := intLt(ass1[c],0);
4053 ✗ arrayUpdate(colptrs,r,counter);
4054 ✗ HKDFSreasign(stack,c,ass1,ass2);
4055 ✗ then
4056 (i,true);
4057 case c::rest
4058 algorithm
4059 // collum is unvisited
4060 ✗ true := intEq(level[c],desL);
4061 // collum is matched
4062 ✗ rc := ass1[c];
4063 ✗ true := intGt(rc,0);
4064 ✗ arrayUpdate(colptrs,r,counter);
4065 ✗ (i_1,b) := ABMPDFSphase(rc::stack,i,rc,nv,ne,m,mT,level,colptrs,ass1,ass2);
4066 ✗ (i_1,b) := ABMPDFStraverseCollums1(b,counter+1,rest,stack,r,i_1,desL,nv,ne,m,mT,level,colptrs,ass1,ass2);
4067 then
4068 (i_1,b);
4069 case _::rest
4070 algorithm
4071 ✗ (i_1,b) := ABMPDFStraverseCollums(rest,counter+1,stack,r,i,desL,nv,ne,m,mT,level,colptrs,ass1,ass2);
4072 then
4073 (i_1,b);
4074 else
4075 algorithm
4076 ✗ Error.addInternalError("function ABMPDFSBtraverseCollums failed", sourceInfo());
4077 ✗ then
4078 fail();
4079 end matchcontinue;
4080 end ABMPDFStraverseCollums;
4081
4082 protected function ABMPDFStraverseCollums1
4083 "function helper for ABMPDFSBtraverseCollums
4084 author: Frenkel TUD 2012-03"
4085 input Boolean inMatched;
4086 input Integer counter;
4087 input list<Integer> rows;
4088 input list<Integer> stack;
4089 input Integer r;
4090 input Integer i;
4091 input Integer desL;
4092 input Integer nv;
4093 input Integer ne;
4094 input BackendDAE.AdjacencyMatrix m;
4095 input BackendDAE.AdjacencyMatrixT mT;
4096 input array<Integer> level;
4097 input array<Integer> colptrs;
4098 input array<Integer> ass1 "eqn := ass1[var]";
4099 input array<Integer> ass2 "var := ass2[eqn]";
4100 output Integer outI;
4101 output Boolean matched;
4102 algorithm
4103 (outI,matched):=
4104 match (inMatched, i)
4105 local
4106 Integer i_1;
4107 Boolean b;
4108 case (true, i_1)
4109 ✗ then (i_1,true);
4110 else
4111 algorithm
4112 ✗ (i_1,b) := ABMPDFStraverseCollums(rows,counter,stack,r,i,desL,nv,ne,m,mT,level,colptrs,ass1,ass2);
4113 then
4114 (i_1,b);
4115 end match;
4116 end ABMPDFStraverseCollums1;
4117
4118
4119 public function PR_FIFO_FAIR
4120 " complexity O(n*tau)
4121 author: Frenkel TUD 2012-04"
4122 input BackendDAE.EqSystem isyst;
4123 input BackendDAE.Shared ishared;
4124 input Boolean clearMatching;
4125 input BackendDAE.MatchingOptions inMatchingOptions;
4126 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
4127 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
4128 output BackendDAE.EqSystem osyst;
4129 output BackendDAE.Shared oshared;
4130 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
4131 algorithm
4132 (osyst,oshared,outArg) :=
4133 matchcontinue isyst
4134 local
4135 Integer nvars,neqns;
4136 BackendDAE.AdjacencyMatrix m;
4137 BackendDAE.AdjacencyMatrixT mt;
4138 array<Integer> vec1,vec2;
4139 BackendDAE.StructurallySingularSystemHandlerArg arg;
4140 BackendDAE.EqSystem syst;
4141 BackendDAE.Shared shared;
4142 array<Integer> l_label,r_label;
4143 list<Integer> unmatched;
4144
4145 case BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt))
4146 algorithm
4147 ✗ neqns := BackendDAEUtil.systemSize(isyst);
4148 ✗ nvars := BackendVariable.daenumVariables(isyst);
4149 ✗ true := intGt(nvars,0);
4150 ✗ true := intGt(neqns,0);
4151 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
4152 ✗ l_label := arrayCreate(neqns,-1);
4153 ✗ r_label := arrayCreate(nvars,-1);
4154 ✗ unmatched := cheapmatchingalgorithm(nvars,neqns,m,mt,vec1,vec2,true);
4155 ✗ (vec1,vec2,syst,shared,arg) := PR_FIFO_FAIR1(unmatched,l_label,r_label,isyst,ishared,nvars,neqns,vec1,vec2,inMatchingOptions,sssHandler,inArg);
4156 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
4157 ✗ then
4158 (syst,shared,arg);
4159 // fail case if system is empty
4160 case _
4161 algorithm
4162 ✗ neqns := BackendDAEUtil.systemSize(isyst);
4163 ✗ nvars := BackendVariable.daenumVariables(isyst);
4164 ✗ false := intGt(nvars,0);
4165 ✗ false := intGt(neqns,0);
4166 ✗ vec1 := listArray({});
4167 ✗ vec2 := listArray({});
4168 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
4169 then
4170 (syst,ishared,inArg);
4171 else
4172 algorithm
4173 ✗ if Flags.isSet(Flags.FAILTRACE) then
4174 ✗ Debug.trace("- Matching.PR_FIFO_FAIR failed\n");
4175 end if;
4176 ✗ then
4177 fail();
4178 end matchcontinue;
4179 end PR_FIFO_FAIR;
4180
4181 protected function PR_FIFO_FAIR1
4182 "function: PR_FIFO_FAIR1, helper for PR_FIFO_FAIR
4183 author: Frenkel TUD 2012-03"
4184 input list<Integer> unmatched;
4185 input array<Integer> l_label;
4186 input array<Integer> r_label;
4187 input BackendDAE.EqSystem isyst;
4188 input BackendDAE.Shared ishared;
4189 input Integer nv;
4190 input Integer ne;
4191 input array<Integer> ass1 "eqn := ass1[var]";
4192 input array<Integer> ass2 "var := ass2[eqn]";
4193 input BackendDAE.MatchingOptions inMatchingOptions;
4194 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
4195 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
4196 output array<Integer> outAss1;
4197 output array<Integer> outAss2;
4198 output BackendDAE.EqSystem osyst;
4199 output BackendDAE.Shared oshared;
4200 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
4201 algorithm
4202 (outAss1,outAss2,osyst,oshared,outArg):=
4203 matchcontinue (unmatched, isyst, inArg)
4204 local
4205 BackendDAE.AdjacencyMatrix m,mt;
4206 Integer nv_1,ne_1;
4207 list<Integer> unmatched1;
4208 list<list<Integer>> meqns;
4209 String eqn_str,var_str;
4210 BackendDAE.StructurallySingularSystemHandlerArg arg,arg1;
4211 DAE.ElementSource source;
4212 SourceInfo info;
4213 BackendDAE.EqSystem syst;
4214 BackendDAE.Shared shared;
4215 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2,l_label1,r_label1;
4216 array<Integer> mapIncRowEqn;
4217 case ({}, _, _)
4218 ✗ then
4219 (ass1,ass2,isyst,ishared,inArg);
4220 case (_, syst as BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)), _)
4221 algorithm
4222 ✗ PR_Global_Relabel(l_label,r_label,nv,ne,m,mt,ass1,ass2);
4223 ✗ PR_FIFO_FAIRphase(0,unmatched,nv+ne,-1,nv,ne,m,mt,l_label,r_label,ass1,ass2,{});
4224 ✗ unmatched1 := getUnassigned(ne, ass1, {});
4225 ✗ meqns := getEqnsforIndexReduction(unmatched1,ne,m,mt,ass1,ass2,inArg);
4226 ✗ (unmatched1,l_label1,r_label1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg) := PR_FIFO_FAIR2(meqns,unmatched1,{},l_label,r_label,syst,ishared,nv,ne,ass1,ass2,inMatchingOptions,sssHandler,inArg);
4227 ✗ (ass1_2,ass2_2,syst,shared,arg1) := PR_FIFO_FAIR1(unmatched1,l_label1,r_label1,syst,shared,nv_1,ne_1,ass1_1,ass2_1,inMatchingOptions,sssHandler,arg);
4228 then
4229 (ass1_2,ass2_2,syst,shared,arg1);
4230 case (_, _, (_,_,_,mapIncRowEqn,_))
4231 algorithm
4232 // get from scalar eqns indexes the indexes in the equation array
4233 ✗ unmatched1 := List.map1r(unmatched,arrayGet,mapIncRowEqn);
4234 ✗ unmatched1 := List.uniqueIntN(unmatched1,arrayLength(mapIncRowEqn));
4235 ✗ eqn_str := BackendDump.dumpMarkedEqns(isyst, unmatched1);
4236 ✗ unmatched1 := getUnassigned(nv, ass2, {});
4237 ✗ var_str := BackendDump.dumpMarkedVars(isyst, unmatched1);
4238 ✗ source := BackendEquation.markedEquationSource(isyst, listHead(unmatched1));
4239 ✗ info := ElementSource.getElementSourceFileInfo(source);
4240 ✗ Error.addSourceMessage(Error.STRUCT_SINGULAR_SYSTEM, {eqn_str,var_str}, info);
4241 ✗ then
4242 fail();
4243 end matchcontinue;
4244 end PR_FIFO_FAIR1;
4245
4246 protected function PR_FIFO_FAIR2
4247 "function: PR_FIFO_FAIR2, helper for PR_FIFO_FAIR
4248 author: Frenkel TUD 2012-03"
4249 input list<list<Integer>> meqns "Marked Equations for Index Reduction";
4250 input list<Integer> unmatched;
4251 input list<Integer> changedEqns;
4252 input array<Integer> l_label;
4253 input array<Integer> r_label;
4254 input BackendDAE.EqSystem isyst;
4255 input BackendDAE.Shared ishared;
4256 input Integer nv;
4257 input Integer ne;
4258 input array<Integer> ass1 "eqn := ass1[var]";
4259 input array<Integer> ass2 "var := ass2[eqn]";
4260 input BackendDAE.MatchingOptions inMatchingOptions;
4261 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
4262 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
4263 output list<Integer> outunmatched;
4264 output array<Integer> outl_label;
4265 output array<Integer> outr_label;
4266 output Integer nvars;
4267 output Integer neqns;
4268 output array<Integer> outAss1;
4269 output array<Integer> outAss2;
4270 output BackendDAE.EqSystem osyst;
4271 output BackendDAE.Shared oshared;
4272 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
4273 algorithm
4274 (outunmatched,outl_label,outr_label,nvars,neqns,outAss1,outAss2,osyst,oshared,outArg):=
4275 match (meqns, inMatchingOptions)
4276 local
4277 Integer nv_1,ne_1;
4278 list<Integer> unmatched1;
4279 BackendDAE.StructurallySingularSystemHandlerArg arg;
4280 BackendDAE.EqSystem syst;
4281 BackendDAE.Shared shared;
4282 array<Integer> ass1_1,ass2_1,l_label1,r_label1;
4283
4284 case ({}, _)
4285 then
4286 (unmatched,l_label,r_label,nv,ne,ass1,ass2,isyst,ishared,inArg);
4287 case (_, (BackendDAE.INDEX_REDUCTION(),_))
4288 algorithm
4289 ✗ (unmatched1,_,syst,shared,ass2_1,ass1_1,arg) := sssHandler(meqns,0,isyst,ishared,ass2,ass1,inArg);
4290 ✗ ne_1 := BackendDAEUtil.systemSize(syst);
4291 ✗ nv_1 := BackendVariable.daenumVariables(syst);
4292 ✗ ass1_1 := assignmentsArrayExpand(ass1_1,ne_1,arrayLength(ass1_1),-1);
4293 ✗ ass2_1 := assignmentsArrayExpand(ass2_1,nv_1,arrayLength(ass2_1),-1);
4294 ✗ l_label1 := assignmentsArrayExpand(l_label,ne_1,arrayLength(l_label),-1);
4295 ✗ r_label1 := assignmentsArrayExpand(r_label,nv_1,arrayLength(r_label),-1);
4296 ✗ then
4297 (unmatched1,l_label1,r_label1,nv_1,ne_1,ass1_1,ass2_1,syst,shared,arg);
4298 case (_, _)
4299 algorithm
4300 ✗ singularSystemError(meqns,0,isyst,ishared,ass1,ass2,inArg);
4301 ✗ then
4302 fail();
4303 end match;
4304 end PR_FIFO_FAIR2;
4305
4306 protected function PR_Global_Relabel
4307 "function PR_Global_Relabel, helper for PR_FIFO_FAIR,
4308 update the labels of eatch vertex
4309 author: Frenkel TUD 2012-04"
4310 input array<Integer> l_label;
4311 input array<Integer> r_label;
4312 input Integer nv;
4313 input Integer ne;
4314 input BackendDAE.AdjacencyMatrix m;
4315 input BackendDAE.AdjacencyMatrixT mT;
4316 input array<Integer> ass1 "eqn := ass1[var]";
4317 input array<Integer> ass2 "var := ass2[eqn]";
4318 protected
4319 list<Integer> queue;
4320 Integer max;
4321 algorithm
4322 ✗ max := nv+ne;
4323 ✗ PR_Global_Relabel_init_l_label(1,ne,max,l_label);
4324 ✗ queue := PR_Global_Relabel_init_r_label(1,nv,max,r_label,ass2,{});
4325 ✗ PR_Global_Relabel1(queue,l_label,r_label,max,nv,ne,m,mT,ass1,ass2,{});
4326 end PR_Global_Relabel;
4327
4328 protected function PR_Global_Relabel_init_l_label
4329 "function PR_Global_Relabel_init_l_label, helper for PR_Global_Relabel
4330 author: Frenkel TUD 2012-04"
4331 input Integer i;
4332 input Integer ne;
4333 input Integer max;
4334 input array<Integer> l_label;
4335 algorithm
4336 ✗ if not intGt(i,ne) then
4337 ✗ arrayUpdate(l_label,i,max);
4338 ✗ PR_Global_Relabel_init_l_label(i+1,ne,max,l_label);
4339 end if;
4340 end PR_Global_Relabel_init_l_label;
4341
4342 protected function PR_Global_Relabel_init_r_label
4343 "function PR_Global_Relabel_init_r_label, helper for PR_Global_Relabel
4344 author: Frenkel TUD 2012-04"
4345 input Integer i;
4346 input Integer nv;
4347 input Integer max;
4348 input array<Integer> r_label;
4349 input array<Integer> ass2 "var := ass2[eqn]";
4350 input list<Integer> inQueue;
4351 output list<Integer> outQueue;
4352 algorithm
4353 outQueue := matchcontinue inQueue
4354 case _
4355 algorithm
4356 ✗ true := intGt(i,nv);
4357 ✗ then
4358 listReverse(inQueue);
4359 case _
4360 algorithm
4361 ✗ false := intGt(i,nv);
4362 ✗ false := intGt(ass2[i],0);
4363 ✗ arrayUpdate(r_label,i,0);
4364 ✗ then
4365 PR_Global_Relabel_init_r_label(i+1,nv,max,r_label,ass2,i::inQueue);
4366 else
4367 algorithm
4368 ✗ arrayUpdate(r_label,i,max);
4369 ✗ then
4370 PR_Global_Relabel_init_r_label(i+1,nv,max,r_label,ass2,inQueue);
4371 end matchcontinue;
4372 end PR_Global_Relabel_init_r_label;
4373
4374 protected function PR_Global_Relabel1
4375 "function PR_Global_Relabel, helper for PR_FIFO_FAIR,
4376 update the labels of eatch vertex
4377 author: Frenkel TUD 2012-04"
4378 input list<Integer> queue;
4379 input array<Integer> l_label;
4380 input array<Integer> r_label;
4381 input Integer max;
4382 input Integer nv;
4383 input Integer ne;
4384 input BackendDAE.AdjacencyMatrix m;
4385 input BackendDAE.AdjacencyMatrixT mT;
4386 input array<Integer> ass1 "eqn := ass1[var]";
4387 input array<Integer> ass2 "var := ass2[eqn]";
4388 input list<Integer> nextqueue;
4389 algorithm
4390 () := matchcontinue(queue, nextqueue)
4391 local
4392 list<Integer> rest,collums,queue1;
4393 Integer r;
4394 case({}, {}) then ();
4395 case({}, _)
4396 algorithm
4397 ✗ PR_Global_Relabel1(listReverse(nextqueue),l_label,r_label,max,nv,ne,m,mT,ass1,ass2,{});
4398 then
4399 ();
4400 case(r::rest, _)
4401 algorithm
4402 ✗ collums := List.select(mT[r], Util.intPositive);
4403 ✗ queue1 := PR_Global_Relabel_traverseCollums(collums,max,r,l_label,r_label,nv,ne,m,mT,ass1,ass2,nextqueue);
4404 ✗ PR_Global_Relabel1(rest,l_label,r_label,max,nv,ne,m,mT,ass1,ass2,queue1);
4405 then
4406 ();
4407 end matchcontinue;
4408 end PR_Global_Relabel1;
4409
4410 protected function PR_Global_Relabel_traverseCollums
4411 "function helper for PR_Global_Relabel1, traverses all collums of a row and asing label indexes
4412 author: Frenkel TUD 2012-04"
4413 input list<Integer> collums;
4414 input Integer max;
4415 input Integer r;
4416 input array<Integer> l_label;
4417 input array<Integer> r_label;
4418 input Integer nv;
4419 input Integer ne;
4420 input BackendDAE.AdjacencyMatrix m;
4421 input BackendDAE.AdjacencyMatrixT mT;
4422 input array<Integer> ass1 "eqn := ass1[var]";
4423 input array<Integer> ass2 "var := ass2[eqn]";
4424 input list<Integer> nextqueue;
4425 output list<Integer> outQueue;
4426 algorithm
4427 outQueue:=
4428 matchcontinue collums
4429 local
4430 list<Integer> rest;
4431 Integer rc,c;
4432 case {} then nextqueue;
4433 case c::rest
4434 algorithm
4435 ✗ true := intEq(l_label[c],max);
4436 ✗ arrayUpdate(l_label,c,r_label[r]+1);
4437 ✗ rc := ass1[c];
4438 ✗ true := intGt(rc,-1);
4439 ✗ true := intEq(r_label[rc] ,max);
4440 ✗ arrayUpdate(r_label,rc,l_label[c]+1);
4441 ✗ then
4442 PR_Global_Relabel_traverseCollums(rest,max,r,l_label,r_label,nv,ne,m,mT,ass1,ass2,rc::nextqueue);
4443 case _::rest
4444 ✗ then
4445 PR_Global_Relabel_traverseCollums(rest,max,r,l_label,r_label,nv,ne,m,mT,ass1,ass2,nextqueue);
4446 else
4447 algorithm
4448 ✗ Error.addInternalError("function PR_Global_Relabel_traverseCollums failed", sourceInfo());
4449 ✗ then
4450 fail();
4451 end matchcontinue;
4452 end PR_Global_Relabel_traverseCollums;
4453
4454
4455 protected function PR_FIFO_FAIRphase
4456 "function PR_FIFO_FAIRphase, match rows and collums with push relabel tecnic
4457 author: Frenkel TUD 2012-04"
4458 input Integer relabels;
4459 input list<Integer> U;
4460 input Integer max;
4461 input Integer min_vertex;
4462 input Integer nv;
4463 input Integer ne;
4464 input BackendDAE.AdjacencyMatrix m;
4465 input BackendDAE.AdjacencyMatrixT mT;
4466 input array<Integer> l_label;
4467 input array<Integer> r_label;
4468 input array<Integer> ass1 "eqn := ass1[var]";
4469 input array<Integer> ass2 "var := ass2[eqn]";
4470 input list<Integer> nextqueue;
4471 algorithm
4472 () := matchcontinue(U, nextqueue)
4473 local
4474 list<Integer> rest,queue;
4475 Integer c,min_label,rlcount,minvertex;
4476 case({}, {}) then ();
4477 case({}, _)
4478 algorithm
4479 ✗ PR_FIFO_FAIRphase(relabels,nextqueue,max,min_vertex,nv,ne,m,mT,l_label,r_label,ass1,ass2,{});
4480 then ();
4481 case(_, _)
4482 algorithm
4483 ✗ true := intEq(relabels,max);
4484 ✗ PR_Global_Relabel(l_label,r_label,nv,ne,m,mT,ass1,ass2);
4485 ✗ PR_FIFO_FAIRphase(0,U,max,min_vertex,nv,ne,m,mT,l_label,r_label,ass1,ass2,nextqueue);
4486 then ();
4487 case(c::rest, _)
4488 algorithm
4489 ✗ (rlcount,min_label,minvertex) := PR_FIFO_FAIRphase1(intLt(l_label[c],max),relabels+1,c,min_vertex,max,max,nv,ne,m,mT,l_label,r_label,ass1,ass2);
4490 ✗ queue := PR_FIFO_FAIRrelabel(c,minvertex,min_label,max,nv,ne,m,mT,l_label,r_label,ass1,ass2,nextqueue);
4491 ✗ PR_FIFO_FAIRphase(rlcount,rest,max,minvertex,nv,ne,m,mT,l_label,r_label,ass1,ass2,queue);
4492 then ();
4493 end matchcontinue;
4494 end PR_FIFO_FAIRphase;
4495
4496 protected function PR_FIFO_FAIRphase1
4497 "function helper for PR_FIFO_FAIRphase
4498 author: Frenkel TUD 2012-04"
4499 input Boolean b;
4500 input Integer relabels;
4501 input Integer max_vertex;
4502 input Integer min_vertec;
4503 input Integer min_label;
4504 input Integer max;
4505 input Integer nv;
4506 input Integer ne;
4507 input BackendDAE.AdjacencyMatrix m;
4508 input BackendDAE.AdjacencyMatrixT mT;
4509 input array<Integer> l_label;
4510 input array<Integer> r_label;
4511 input array<Integer> ass1 "eqn := ass1[var]";
4512 input array<Integer> ass2 "var := ass2[eqn]";
4513 output Integer outRelabels;
4514 output Integer outMinLabels;
4515 output Integer outMinVertex;
4516 algorithm
4517 (outRelabels,outMinLabels,outMinVertex) :=
4518 match b
4519 local
4520 Integer rel,minlab,minvert,tmp;
4521 case true
4522 algorithm
4523 ✗ tmp := intMod(l_label[max_vertex],4);
4524 ✗ (rel,minlab,minvert) := PR_FIFO_FAIRphase2(intEq(tmp,1),relabels,max_vertex,min_vertec,min_label,max,nv,ne,m,mT,l_label,r_label,ass1,ass2);
4525 then
4526 (rel,minlab,minvert);
4527 else
4528 ✗ then
4529 (relabels,min_label,min_vertec);
4530 end match;
4531 end PR_FIFO_FAIRphase1;
4532
4533 protected function PR_FIFO_FAIRphase2
4534 "function helper for PR_FIFO_FAIRphase
4535 author: Frenkel TUD 2012-04"
4536 input Boolean b;
4537 input Integer relabels;
4538 input Integer max_vertex;
4539 input Integer min_vertec;
4540 input Integer min_label;
4541 input Integer max;
4542 input Integer nv;
4543 input Integer ne;
4544 input BackendDAE.AdjacencyMatrix m;
4545 input BackendDAE.AdjacencyMatrixT mT;
4546 input array<Integer> l_label;
4547 input array<Integer> r_label;
4548 input array<Integer> ass1 "eqn := ass1[var]";
4549 input array<Integer> ass2 "var := ass2[eqn]";
4550 output Integer outRelabels;
4551 output Integer outMinLabels;
4552 output Integer outMinVertex;
4553 algorithm
4554 (outRelabels,outMinLabels,outMinVertex) :=
4555 match b
4556 local
4557 list<Integer> rows;
4558 Integer rel,minlab,minvert;
4559 case true
4560 algorithm
4561 ✗ rows := List.select(m[max_vertex], Util.intPositive);
4562 ✗ (rel,minlab,minvert) := PR_FIFO_FAIRphase_traverseRows(rows,relabels,max_vertex,min_vertec,min_label,max,nv,ne,m,mT,l_label,r_label,ass1,ass2);
4563 then
4564 (rel,minlab,minvert);
4565 else
4566 algorithm
4567 ✗ rows := List.select(m[max_vertex], Util.intPositive);
4568 ✗ rows := listReverse(rows);
4569 ✗ (rel,minlab,minvert) := PR_FIFO_FAIRphase_traverseRows(rows,relabels,max_vertex,min_vertec,min_label,max,nv,ne,m,mT,l_label,r_label,ass1,ass2);
4570 then
4571 (rel,minlab,minvert);
4572 end match;
4573 end PR_FIFO_FAIRphase2;
4574
4575 protected function PR_FIFO_FAIRphase_traverseRows
4576 "function helper for PR_FIFO_FAIRphase2
4577 author: Frenkel TUD 2012-04"
4578 input list<Integer> rows;
4579 input Integer relabels;
4580 input Integer max_vertex;
4581 input Integer min_vertex;
4582 input Integer min_label;
4583 input Integer max;
4584 input Integer nv;
4585 input Integer ne;
4586 input BackendDAE.AdjacencyMatrix m;
4587 input BackendDAE.AdjacencyMatrixT mT;
4588 input array<Integer> l_label;
4589 input array<Integer> r_label;
4590 input array<Integer> ass1 "eqn := ass1[var]";
4591 input array<Integer> ass2 "var := ass2[eqn]";
4592 output Integer outRelabels;
4593 output Integer outMinLabels;
4594 output Integer outMinVertex;
4595 algorithm
4596 (outRelabels,outMinLabels,outMinVertex) :=
4597 matchcontinue rows
4598 local
4599 list<Integer> rest;
4600 Integer r,minlabel,minvertex,rel;
4601 ✗ case {} then (relabels,min_label,min_vertex);
4602 case r::_
4603 algorithm
4604 ✗ true := intLt(r_label[r],min_label);
4605 minlabel := r_label[r];
4606 minvertex := r;
4607 ✗ true := intEq(r_label[minvertex],l_label[max_vertex]-1);
4608 ✗ then
4609 (relabels-1,minlabel,minvertex);
4610 case r::rest
4611 algorithm
4612 ✗ true := intLt(r_label[r],min_label);
4613 minlabel := r_label[r];
4614 minvertex := r;
4615 ✗ false := intEq(r_label[minvertex],l_label[max_vertex]-1);
4616 ✗ (rel,minlabel,minvertex) := PR_FIFO_FAIRphase_traverseRows(rest,relabels,max_vertex,minvertex,minlabel,max,nv,ne,m,mT,l_label,r_label,ass1,ass2);
4617 then
4618 (rel,minlabel,minvertex);
4619 case _::rest
4620 algorithm
4621 ✗ (rel,minlabel,minvertex) := PR_FIFO_FAIRphase_traverseRows(rest,relabels,max_vertex,min_vertex,min_label,max,nv,ne,m,mT,l_label,r_label,ass1,ass2);
4622 then
4623 (rel,minlabel,minvertex);
4624 else
4625 algorithm
4626 ✗ Error.addInternalError("function PR_FIFO_FAIRphase_traverseRows failed", sourceInfo());
4627 ✗ then
4628 fail();
4629 end matchcontinue;
4630 end PR_FIFO_FAIRphase_traverseRows;
4631
4632 protected function PR_FIFO_FAIRrelabel
4633 "function helper for PR_FIFO_FAIRphase
4634 author: Frenkel TUD 2012-04"
4635 input Integer max_vertex;
4636 input Integer min_vertex;
4637 input Integer min_label;
4638 input Integer max;
4639 input Integer nv;
4640 input Integer ne;
4641 input BackendDAE.AdjacencyMatrix m;
4642 input BackendDAE.AdjacencyMatrixT mT;
4643 input array<Integer> l_label;
4644 input array<Integer> r_label;
4645 input array<Integer> ass1 "eqn := ass1[var]";
4646 input array<Integer> ass2 "var := ass2[eqn]";
4647 input list<Integer> inQueue;
4648 output list<Integer> outQueue;
4649 algorithm
4650 outQueue := matchcontinue inQueue
4651 local
4652 Integer next_vertex;
4653 case _
4654 algorithm
4655 ✗ true := intLt(min_label,max);
4656 ✗ true := intLt(ass2[min_vertex],0);
4657 ✗ arrayUpdate(ass2,min_vertex,max_vertex);
4658 ✗ arrayUpdate(ass1,max_vertex,min_vertex);
4659 ✗ arrayUpdate(r_label,min_vertex,min_label+2);
4660 then
4661 inQueue;
4662 case _
4663 algorithm
4664 ✗ true := intLt(min_label,max);
4665 ✗ false := intLt(ass2[min_vertex],0);
4666 next_vertex := ass2[min_vertex];
4667 ✗ arrayUpdate(ass2,min_vertex,max_vertex);
4668 ✗ arrayUpdate(ass1,max_vertex,min_vertex);
4669 ✗ arrayUpdate(ass1,next_vertex,-1);
4670 ✗ arrayUpdate(l_label,max_vertex,min_label+1);
4671 ✗ arrayUpdate(r_label,min_vertex,min_label+2);
4672 then
4673 next_vertex::inQueue;
4674 else
4675 then
4676 inQueue;
4677 end matchcontinue;
4678 end PR_FIFO_FAIRrelabel;
4679
4680
4681 // =============================================================================
4682 // cheap matching implementations
4683 //
4684 // =============================================================================
4685
4686 protected function cheapmatchingalgorithm
4687 "function cheapmatchingalgorithm, traverses all colums and look for a cheap matching, a unmatch row
4688 author: Frenkel TUD 2012-07"
4689 input Integer nv;
4690 input Integer ne;
4691 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
4692 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
4693 input array<Integer> ass1 "ass[eqnindx]=varindx";
4694 input array<Integer> ass2 "ass[varindx]=eqnindx";
4695 input Boolean intRangeUsed;
4696 output list<Integer> outUnMatched;
4697 algorithm
4698 646 outUnMatched := cheapmatchingalgorithm1(Config.getCheapMatchingAlgorithm(),nv,ne,m,mT,ass1,ass2,intRangeUsed);
4699 end cheapmatchingalgorithm;
4700
4701 protected function cheapmatchingalgorithm1
4702 " author: Frenkel TUD 2012-07"
4703 input Integer algorithmid;
4704 input Integer nv;
4705 input Integer ne;
4706 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
4707 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
4708 input array<Integer> ass1 "ass[eqnindx]=varindx";
4709 input array<Integer> ass2 "ass[varindx]=eqnindx";
4710 input Boolean intRangeUsed;
4711 output list<Integer> outUnMatched;
4712 algorithm
4713 outUnMatched := match(algorithmid, intRangeUsed)
4714 ✗ case(1, _) then cheapmatching(1,nv,ne,m,mT,ass1,ass2,{});
4715 646 case(3, _) then ks_rand_cheapmatching(nv,ne,m,mT,ass1,ass2);
4716 ✗ case(_, true) then getUnassigned(ne, ass1, {});
4717 else {};
4718 end match;
4719 end cheapmatchingalgorithm1;
4720
4721 protected function cheapmatching
4722 "function cheapmatching, traverses all colums and look for a cheap matching, a unmatch row
4723 author: Frenkel TUD 2012-03"
4724 input Integer i;
4725 input Integer nv;
4726 input Integer ne;
4727 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
4728 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
4729 input array<Integer> ass1 "ass[eqnindx]=varindx";
4730 input array<Integer> ass2 "ass[varindx]=eqnindx";
4731 input list<Integer> inUnMatched;
4732 output list<Integer> outUnMatched;
4733 algorithm
4734 outUnMatched:=
4735 matchcontinue inUnMatched
4736 local
4737 list<Integer> rows;
4738 case _
4739 algorithm
4740 ✗ true:=intGt(i,ne);
4741 then
4742 inUnMatched;
4743 case _
4744 algorithm
4745 // search cheap matching
4746 ✗ rows := List.select(m[i], Util.intPositive);
4747 ✗ cheapmatching1(rows,i,ass1,ass2);
4748 ✗ then
4749 cheapmatching(i+1,nv,ne,m,mT,ass1,ass2,inUnMatched);
4750 case _
4751 // unmatched add to list
4752 ✗ then
4753 cheapmatching(i+1,nv,ne,m,mT,ass1,ass2,i::inUnMatched);
4754 else
4755 algorithm
4756 ✗ Error.addInternalError("function cheapmatching failed in equation " + intString(i), sourceInfo());
4757 ✗ then
4758 fail();
4759 end matchcontinue;
4760 end cheapmatching;
4761
4762 protected function cheapmatching1
4763 "function helper for cheapmatching, traverses all rows, fails if no unmatched is found
4764 author: Frenkel TUD 2012-03"
4765 input list<Integer> rows;
4766 input Integer c;
4767 input array<Integer> ass1 "eqn := ass1[var]";
4768 input array<Integer> ass2 "var := ass2[eqn]";
4769 algorithm
4770 ():=
4771 matchcontinue rows
4772 local
4773 list<Integer> rest;
4774 Integer r;
4775 case r::_
4776 algorithm
4777 // row is unmatched -> return
4778 ✗ true := intLt(ass2[r],0);
4779 ✗ arrayUpdate(ass1,c,r);
4780 ✗ arrayUpdate(ass2,r,c);
4781 then
4782 ();
4783 case _::rest
4784 algorithm
4785 ✗ cheapmatching1(rest,c,ass1,ass2);
4786 then
4787 ();
4788 end matchcontinue;
4789 end cheapmatching1;
4790
4791 protected function ks_rand_cheapmatching
4792 "function ks_rand_cheapmatching, Random Karp-Sipser
4793 author: Frenkel TUD 2012-04"
4794 input Integer nv;
4795 input Integer ne;
4796 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
4797 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
4798 input array<Integer> ass1 "ass[eqnindx]=varindx";
4799 input array<Integer> ass2 "ass[varindx]=eqnindx";
4800 output list<Integer> outUnMatched;
4801 protected
4802 list<Integer> onecolums, onerows;
4803 array<Integer> col_degrees, row_degrees,randarr;
4804 algorithm
4805 646 col_degrees := arrayCreate(ne,0);
4806 646 row_degrees := arrayCreate(ne,0);
4807 646 onerows := getOneRows(ne,mT,row_degrees,{});
4808 646 onecolums := getOneRows(nv,m,col_degrees,{});
4809 646 randarr := Array.createIntRange(ne);
4810 646 setrandArray(ne,randarr);
4811 646 ks_rand_cheapmatching1(1,ne,onecolums,onerows,col_degrees,row_degrees,randarr,m,mT,ass1,ass2);
4812 646 outUnMatched := getUnassigned(ne,ass1,{});
4813 end ks_rand_cheapmatching;
4814
4815 protected function ks_rand_cheapmatching1
4816 "function ks_rand_cheapmatching1, helper for ks_rand_cheapmatching.
4817 author: Frenkel TUD 2012-04"
4818 input Integer i;
4819 input Integer ne;
4820 input list<Integer> onecolums;
4821 input list<Integer> onerows;
4822 input array<Integer> col_degrees;
4823 input array<Integer> row_degrees;
4824 input array<Integer> randarr;
4825 input BackendDAE.AdjacencyMatrix m;
4826 input BackendDAE.AdjacencyMatrixT mT;
4827 input array<Integer> ass1 "eqn := ass1[var]";
4828 input array<Integer> ass2 "var := ass2[eqn]";
4829 protected
4830 list<Integer> onecolums1,onerows1;
4831 Integer c;
4832 Boolean b;
4833 algorithm
4834
2/2
✓ Branch 0 taken 2970 times.
✓ Branch 1 taken 646 times.
3616 if intLe(i,ne) then
4835 2970 ks_rand_match(onerows,onecolums,row_degrees,col_degrees,mT,m,ass2,ass1);
4836 2970 c := randarr[i];
4837
4/4
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 2890 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 74 times.
2970 b := intLt(ass1[c],0) and intGt(col_degrees[c],0);
4838 2970 (onecolums1,onerows1) := ks_rand_cheapmatching2(b,c,col_degrees,row_degrees,randarr,m,mT,ass1,ass2);
4839 2970 ks_rand_cheapmatching1(i+1,ne,onecolums1,onerows1,col_degrees,row_degrees,randarr,m,mT,ass1,ass2);
4840 end if;
4841 end ks_rand_cheapmatching1;
4842
4843 protected function ks_rand_cheapmatching2
4844 "function ks_rand_cheapmatching2, helper for ks_rand_cheapmatching.
4845 author: Frenkel TUD 2012-04"
4846 input Boolean b;
4847 input Integer c;
4848 input array<Integer> col_degrees;
4849 input array<Integer> row_degrees;
4850 input array<Integer> randarr;
4851 input BackendDAE.AdjacencyMatrix m;
4852 input BackendDAE.AdjacencyMatrixT mT;
4853 input array<Integer> ass1 "eqn := ass1[var]";
4854 input array<Integer> ass2 "var := ass2[eqn]";
4855 output list<Integer> onecolums;
4856 output list<Integer> onerows;
4857 algorithm
4858 (onecolums,onerows) := match b
4859 local
4860 list<Integer> clst,rlst,lst;
4861 Integer e_id,r;
4862 case true
4863 algorithm
4864 74 e_id := realInt(realMod(System.realRand(),intReal(col_degrees[c])));
4865 74 lst := List.select(m[c], Util.intPositive);
4866 74 (rlst,r) := ks_rand_cheapmatching3(e_id,lst,row_degrees,c,ass1,ass2,{},0);
4867 74 lst := List.select(mT[r], Util.intPositive);
4868 74 clst := ks_rand_cheapmatching4(lst,row_degrees[r],col_degrees,ass1,{});
4869 then
4870 (clst,rlst);
4871 else
4872 ({},{});
4873 end match;
4874 end ks_rand_cheapmatching2;
4875
4876 protected function ks_rand_cheapmatching3
4877 "function ks_rand_cheapmatching3, helper for ks_rand_match.
4878 author: Frenkel TUD 2012-04"
4879 input Integer e_id;
4880 input list<Integer> rows;
4881 input array<Integer> row_degrees;
4882 input Integer c;
4883 input array<Integer> ass1 "eqn := ass1[var]";
4884 input array<Integer> ass2 "var := ass2[eqn]";
4885 input list<Integer> onerows;
4886 input Integer inR;
4887 output list<Integer> outonerows;
4888 output Integer outR;
4889 algorithm
4890 (outonerows,outR) := matchcontinue rows
4891 local
4892 list<Integer> rest,stack,statck1;
4893 Integer r,r_1;
4894 27 case {} then (onerows,inR);
4895 case r::rest
4896 algorithm
4897
2/2
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 84 times.
128 true := intLt(ass2[r],0);
4898
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 47 times.
84 true := intEq(e_id,0);
4899 47 arrayUpdate(ass1,c,r);
4900 47 arrayUpdate(ass2,r,c);
4901 47 stack := ks_rand_match_degree(rest,row_degrees,ass2,onerows);
4902 47 then
4903 (stack,r);
4904 case r::rest
4905 algorithm
4906
2/2
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 37 times.
81 true := intLt(ass2[r],0);
4907 37 arrayUpdate(row_degrees,r,row_degrees[r]-1);
4908 37 stack := List.consOnTrue(intEq(row_degrees[r],1),r,onerows);
4909 37 (statck1,r_1) := ks_rand_cheapmatching3(e_id-1,rest,row_degrees,c,ass1,ass2,stack,r);
4910 then
4911 (statck1,r_1);
4912 case r::rest
4913 algorithm
4914 44 (statck1,r_1) := ks_rand_cheapmatching3(e_id-1,rest,row_degrees,c,ass1,ass2,onerows,r);
4915 then
4916 (statck1,r_1);
4917 end matchcontinue;
4918 end ks_rand_cheapmatching3;
4919
4920 protected function ks_rand_cheapmatching4
4921 "function ks_rand_cheapmatching4, helper for ks_rand_cheapmatching.
4922 author: Frenkel TUD 2012-04"
4923 input list<Integer> cols;
4924 input Integer count;
4925 input array<Integer> col_degrees;
4926 input array<Integer> ass1 "eqn := ass1[var]";
4927 input list<Integer> inStack;
4928 output list<Integer> outStack;
4929 algorithm
4930 outStack := matchcontinue cols
4931 local
4932 list<Integer> rest,stack;
4933 Integer c;
4934 case {} then inStack;
4935 case _
4936 algorithm
4937
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 15 times.
285 false := intGt(count,0);
4938 then
4939 inStack;
4940 case c::rest
4941 algorithm
4942
2/2
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 139 times.
270 true := intLt(ass1[c],0);
4943 139 arrayUpdate(col_degrees,c,col_degrees[c]-1);
4944 139 stack := List.consOnTrue(intEq(col_degrees[c],1),c,inStack);
4945 139 then
4946 ks_rand_cheapmatching4(rest,count-1,col_degrees,ass1,stack);
4947 case _::rest
4948 131 then
4949 ks_rand_cheapmatching4(rest,count,col_degrees,ass1,inStack);
4950 end matchcontinue;
4951 end ks_rand_cheapmatching4;
4952
4953 protected function getOneRows
4954 "function getOneRows, helper for ks_rand_cheapmatching.
4955 return all rows with length == 1
4956 author: Frenkel TUD 2012-04"
4957 input Integer n;
4958 input BackendDAE.AdjacencyMatrix m;
4959 input array<Integer> degrees;
4960 input list<Integer> inOneRows;
4961 output list<Integer> outOneRows;
4962 algorithm
4963 outOneRows := match n
4964 local
4965 list<Integer> lst,onerows;
4966 Integer l;
4967 1292 case 0 then listReverse(inOneRows);
4968 else
4969 algorithm
4970 5940 lst := List.select(m[n], Util.intPositive);
4971 5940 l := listLength(lst);
4972 5940 arrayUpdate(degrees,n,l);
4973 5940 onerows := List.consOnTrue(intEq(l,1),n,inOneRows);
4974 5940 then
4975 getOneRows(n-1,m,degrees,onerows);
4976 end match;
4977 end getOneRows;
4978
4979 protected function setrandArray
4980 "function setrandArray, helper for ks_rand_cheapmatching.
4981 return all rows with length == 1
4982 author: Frenkel TUD 2012-04"
4983 input Integer n;
4984 input array<Integer> randarr;
4985 algorithm
4986 () := match n
4987 local
4988 Integer z,tmp;
4989 case 0 then ();
4990 else
4991 algorithm
4992 2970 z := realInt(realMod(System.realRand(),intReal(n)))+1;
4993 2970 tmp := randarr[n];
4994 2970 arrayUpdate(randarr,n,randarr[z]);
4995 2970 arrayUpdate(randarr,z,tmp);
4996 2970 setrandArray(n-1,randarr);
4997 then
4998 ();
4999 end match;
5000 end setrandArray;
5001
5002 protected function ks_rand_match
5003 "function ks_rand_match, helper for ks_rand_cheapmatching.
5004 author: Frenkel TUD 2012-04"
5005 input list<Integer> stack1;
5006 input list<Integer> stack2;
5007 input array<Integer> degrees1;
5008 input array<Integer> degrees2;
5009 input BackendDAE.AdjacencyMatrix m1;
5010 input BackendDAE.AdjacencyMatrix m2;
5011 input array<Integer> ass1 "eqn := ass1[var]";
5012 input array<Integer> ass2 "var := ass2[eqn]";
5013 algorithm
5014 () := matchcontinue (stack1, stack2)
5015 local
5016 Integer e;
5017 list<Integer> rest,lst,stack;
5018 case ({}, {}) then ();
5019 case (e::rest, {})
5020 algorithm
5021
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 1257 times.
1266 true := intEq(degrees1[e],1);
5022
2/2
✓ Branch 1 taken 899 times.
✓ Branch 2 taken 358 times.
1257 true := intLt(ass1[e],0);
5023 358 lst := List.select(m1[e], Util.intPositive);
5024 358 stack := ks_rand_match1(e,lst,rest,degrees1,degrees2,m2,ass1,ass2);
5025 358 ks_rand_match(stack,{},degrees1,degrees2,m1,m2,ass1,ass2);
5026 then
5027 ();
5028 case (_::rest, {})
5029 algorithm
5030 908 ks_rand_match(rest,{},degrees1,degrees2,m1,m2,ass1,ass2);
5031 then
5032 ();
5033 case ({}, e::rest)
5034 algorithm
5035
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 true := intEq(degrees2[e],1);
5036
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 true := intLt(ass2[e],0);
5037 17 lst := List.select(m2[e], Util.intPositive);
5038 17 stack := ks_rand_match1(e,lst,rest,degrees2,degrees1,m1,ass2,ass1);
5039 17 ks_rand_match(stack,{},degrees2,degrees1,m2,m1,ass2,ass1);
5040 then
5041 ();
5042 case ({}, _::rest)
5043 algorithm
5044 ✗ ks_rand_match(rest,{},degrees2,degrees1,m2,m1,ass2,ass1);
5045 then
5046 ();
5047 case (e::rest, _)
5048 algorithm
5049
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1554 times.
1554 true := intEq(degrees1[e],1);
5050
2/2
✓ Branch 1 taken 459 times.
✓ Branch 2 taken 1095 times.
1554 true := intLt(ass1[e],0);
5051 1095 lst := List.select(m1[e], Util.intPositive);
5052 1095 stack := ks_rand_match1(e,lst,rest,degrees1,degrees2,m2,ass1,ass2);
5053 1095 ks_rand_match(stack2,stack,degrees2,degrees1,m2,m1,ass2,ass1);
5054 then
5055 ();
5056 case (_::rest, _)
5057 algorithm
5058 459 ks_rand_match(stack2,rest,degrees2,degrees1,m2,m1,ass2,ass1);
5059 then
5060 ();
5061 end matchcontinue;
5062 end ks_rand_match;
5063
5064 protected function ks_rand_match1
5065 "function ks_rand_match1, helper for ks_rand_match.
5066 author: Frenkel TUD 2012-04"
5067 input Integer i;
5068 input list<Integer> entries;
5069 input list<Integer> stack;
5070 input array<Integer> degrees1;
5071 input array<Integer> degrees2;
5072 input BackendDAE.AdjacencyMatrix adjacency;
5073 input array<Integer> ass1 "eqn := ass1[var]";
5074 input array<Integer> ass2 "var := ass2[eqn]";
5075 output list<Integer> outStack;
5076 algorithm
5077 outStack := matchcontinue entries
5078 local
5079 list<Integer> rest,lst;
5080 Integer e;
5081 case {} then stack;
5082 case e::_
5083 algorithm
5084
2/2
✓ Branch 1 taken 680 times.
✓ Branch 2 taken 1443 times.
2123 true := intLt(ass2[e],0);
5085 1443 lst := List.select(adjacency[e], Util.intPositive);
5086 1443 arrayUpdate(ass1,i,e);
5087 1443 arrayUpdate(ass2,e,i);
5088 1443 then
5089 ks_rand_match_degree(lst,degrees1,ass1,stack);
5090 case _::rest
5091 680 then
5092 ks_rand_match1(i,rest,stack,degrees1,degrees2,adjacency,ass1,ass2);
5093 end matchcontinue;
5094 end ks_rand_match1;
5095
5096 protected function ks_rand_match_degree
5097 "function ks_rand_match_degree, helper for ks_rand_match.
5098 author: Frenkel TUD 2012-04"
5099 input list<Integer> entries;
5100 input array<Integer> degrees;
5101 input array<Integer> ass;
5102 input list<Integer> inStack;
5103 output list<Integer> outStack;
5104 algorithm
5105 outStack := matchcontinue entries
5106 local
5107 list<Integer> rest,stack;
5108 Integer e;
5109 case {} then inStack;
5110 case e::rest
5111 algorithm
5112
2/2
✓ Branch 1 taken 1923 times.
✓ Branch 2 taken 1560 times.
3483 true := intLt(ass[e],0);
5113 1560 arrayUpdate(degrees,e,degrees[e]-1);
5114 1560 stack := List.consOnTrue(intEq(degrees[e],1),e,inStack);
5115 1560 then
5116 ks_rand_match_degree(rest,degrees,ass,stack);
5117 case _::rest
5118 1923 then
5119 ks_rand_match_degree(rest,degrees,ass,inStack);
5120 end matchcontinue;
5121 end ks_rand_match_degree;
5122
5123 // =============================================================================
5124 // C-Implementation Stuff from
5125 // Kamer Kaya, Johannes Langguth and Bora Ucar
5126 // see: http://bmi.osu.edu/~kamer/index.html
5127 // =============================================================================
5128
5129 public function DFSBExternal
5130 "function: DFSBExternal"
5131 input BackendDAE.EqSystem isyst;
5132 input BackendDAE.Shared ishared;
5133 input Boolean clearMatching;
5134 input BackendDAE.MatchingOptions inMatchingOptions;
5135 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5136 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5137 output BackendDAE.EqSystem osyst;
5138 output BackendDAE.Shared oshared;
5139 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5140 algorithm
5141 (osyst,oshared,outArg) :=
5142 matchcontinue inArg
5143 local
5144 Integer nvars,neqns;
5145 array<Integer> vec1,vec2;
5146 BackendDAE.StructurallySingularSystemHandlerArg arg;
5147 BackendDAE.EqSystem syst;
5148 BackendDAE.Shared shared;
5149 case _
5150 algorithm
5151 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5152 ✗ nvars := BackendVariable.daenumVariables(isyst);
5153 ✗ true := intGt(nvars,0);
5154 ✗ true := intGt(neqns,0);
5155 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5156 ✗ true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5157 ✗ (vec1,vec2,syst,shared,arg) := matchingExternal({},false,1,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5158 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5159 ✗ then
5160 (syst,shared,arg);
5161 // fail case if system is empty
5162 case _
5163 algorithm
5164 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5165 ✗ nvars := BackendVariable.daenumVariables(isyst);
5166 ✗ false := intGt(nvars,0);
5167 ✗ false := intGt(neqns,0);
5168 ✗ vec1 := listArray({});
5169 ✗ vec2 := listArray({});
5170 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5171 then
5172 (syst,ishared,inArg);
5173 else
5174 algorithm
5175 ✗ if Flags.isSet(Flags.FAILTRACE) then
5176 ✗ Debug.trace("- Matching.DFSBExternal failed\n");
5177 end if;
5178 ✗ then
5179 fail();
5180 end matchcontinue;
5181 end DFSBExternal;
5182
5183 public function BFSBExternal
5184 "function: BFSBExternal"
5185 input BackendDAE.EqSystem isyst;
5186 input BackendDAE.Shared ishared;
5187 input Boolean clearMatching;
5188 input BackendDAE.MatchingOptions inMatchingOptions;
5189 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5190 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5191 output BackendDAE.EqSystem osyst;
5192 output BackendDAE.Shared oshared;
5193 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5194 algorithm
5195 (osyst,oshared,outArg) :=
5196 matchcontinue inArg
5197 local
5198 Integer nvars,neqns;
5199 array<Integer> vec1,vec2;
5200 BackendDAE.StructurallySingularSystemHandlerArg arg;
5201 BackendDAE.EqSystem syst;
5202 BackendDAE.Shared shared;
5203 case _
5204 algorithm
5205 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5206 ✗ nvars := BackendVariable.daenumVariables(isyst);
5207 ✗ true := intGt(nvars,0);
5208 ✗ true := intGt(neqns,0);
5209 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5210 ✗ true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5211 ✗ (vec1,vec2,syst,shared,arg) := matchingExternal({},false,2,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5212 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5213 ✗ then
5214 (syst,shared,arg);
5215 // fail case if system is empty
5216 case _
5217 algorithm
5218 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5219 ✗ nvars := BackendVariable.daenumVariables(isyst);
5220 ✗ false := intGt(nvars,0);
5221 ✗ false := intGt(neqns,0);
5222 ✗ vec1 := listArray({});
5223 ✗ vec2 := listArray({});
5224 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5225 then
5226 (syst,ishared,inArg);
5227 else
5228 algorithm
5229 ✗ if Flags.isSet(Flags.FAILTRACE) then
5230 ✗ Debug.trace("- Matching.BFSBExternal failed\n");
5231 end if;
5232 ✗ then
5233 fail();
5234 end matchcontinue;
5235 end BFSBExternal;
5236
5237 public function MC21AExternal
5238 "function: MC21AExternal"
5239 input BackendDAE.EqSystem isyst;
5240 input BackendDAE.Shared ishared;
5241 input Boolean clearMatching;
5242 input BackendDAE.MatchingOptions inMatchingOptions;
5243 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5244 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5245 output BackendDAE.EqSystem osyst;
5246 output BackendDAE.Shared oshared;
5247 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5248 algorithm
5249 (osyst,oshared,outArg) :=
5250 matchcontinue inArg
5251 local
5252 Integer nvars,neqns;
5253 array<Integer> vec1,vec2;
5254 BackendDAE.StructurallySingularSystemHandlerArg arg;
5255 BackendDAE.EqSystem syst;
5256 BackendDAE.Shared shared;
5257 case _
5258 algorithm
5259 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5260 ✗ nvars := BackendVariable.daenumVariables(isyst);
5261 ✗ true := intGt(nvars,0);
5262 ✗ true := intGt(neqns,0);
5263 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5264 ✗ true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5265 ✗ (vec1,vec2,syst,shared,arg) := matchingExternal({},false,3,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5266 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5267 ✗ then
5268 (syst,shared,arg);
5269 // fail case if system is empty
5270 case _
5271 algorithm
5272 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5273 ✗ nvars := BackendVariable.daenumVariables(isyst);
5274 ✗ false := intGt(nvars,0);
5275 ✗ false := intGt(neqns,0);
5276 ✗ vec1 := listArray({});
5277 ✗ vec2 := listArray({});
5278 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5279 then
5280 (syst,ishared,inArg);
5281 else
5282 algorithm
5283 ✗ if Flags.isSet(Flags.FAILTRACE) then
5284 ✗ Debug.trace("- Matching.MC21AExternal failed\n");
5285 end if;
5286 ✗ then
5287 fail();
5288 end matchcontinue;
5289 end MC21AExternal;
5290
5291 public function PFExternal
5292 "function: PFExternal"
5293 input BackendDAE.EqSystem isyst;
5294 input BackendDAE.Shared ishared;
5295 input Boolean clearMatching;
5296 input BackendDAE.MatchingOptions inMatchingOptions;
5297 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5298 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5299 output BackendDAE.EqSystem osyst;
5300 output BackendDAE.Shared oshared;
5301 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5302 algorithm
5303 (osyst,oshared,outArg) :=
5304 matchcontinue inArg
5305 local
5306 Integer nvars,neqns;
5307 array<Integer> vec1,vec2;
5308 BackendDAE.StructurallySingularSystemHandlerArg arg;
5309 BackendDAE.EqSystem syst;
5310 BackendDAE.Shared shared;
5311 case _
5312 algorithm
5313 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5314 ✗ nvars := BackendVariable.daenumVariables(isyst);
5315 ✗ true := intGt(nvars,0);
5316 ✗ true := intGt(neqns,0);
5317 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5318 ✗ true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5319 ✗ (vec1,vec2,syst,shared,arg) := matchingExternal({},false,4,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5320 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5321 ✗ then
5322 (syst,shared,arg);
5323 // fail case if system is empty
5324 case _
5325 algorithm
5326 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5327 ✗ nvars := BackendVariable.daenumVariables(isyst);
5328 ✗ false := intGt(nvars,0);
5329 ✗ false := intGt(neqns,0);
5330 ✗ vec1 := listArray({});
5331 ✗ vec2 := listArray({});
5332 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5333 then
5334 (syst,ishared,inArg);
5335 else
5336 algorithm
5337 ✗ if Flags.isSet(Flags.FAILTRACE) then
5338 ✗ Debug.trace("- Matching.PFExternal failed\n");
5339 end if;
5340 ✗ then
5341 fail();
5342 end matchcontinue;
5343 end PFExternal;
5344
5345 public function PFPlusExternal
5346 "function: PFExternal"
5347 input BackendDAE.EqSystem isyst;
5348 input BackendDAE.Shared ishared;
5349 input Boolean clearMatching;
5350 input BackendDAE.MatchingOptions inMatchingOptions;
5351 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5352 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5353 output BackendDAE.EqSystem osyst;
5354 output BackendDAE.Shared oshared;
5355 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5356 protected
5357 Integer nvars,neqns;
5358 algorithm
5359 122529 neqns := BackendDAEUtil.systemSize(isyst);
5360 122529 nvars := BackendVariable.daenumVariables(isyst);
5361 (osyst,oshared,outArg) :=
5362 matchcontinue inArg
5363 local
5364 array<Integer> vec1,vec2;
5365 BackendDAE.StructurallySingularSystemHandlerArg arg;
5366 BackendDAE.EqSystem syst;
5367 BackendDAE.Shared shared;
5368 case _ guard intGt(nvars,0) and intGt(neqns,0)
5369 algorithm
5370 118741 (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5371
3/4
✓ Branch 0 taken 59370 times.
✓ Branch 1 taken 59371 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59370 times.
118741 true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5372
2/2
✓ Branch 0 taken 59370 times.
✓ Branch 1 taken 59371 times.
178111 (vec1,vec2,syst,shared,arg) := matchingExternal({},false,5,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5373 118740 syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5374 118740 then
5375 (syst,shared,arg);
5376 // fail case if system is empty
5377 case _ guard not intGt(nvars,0) and not intGt(neqns,0)
5378 algorithm
5379 3788 vec1 := listArray({});
5380 3788 vec2 := listArray({});
5381 3788 syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5382 then
5383 (syst,ishared,inArg);
5384 else
5385 algorithm
5386
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if Flags.isSet(Flags.FAILTRACE) then
5387 ✗ Debug.trace("- Matching.PFPlusExternal failed\n");
5388 end if;
5389 1 then
5390 fail();
5391 end matchcontinue;
5392 end PFPlusExternal;
5393
5394 public function HKExternal
5395 "function: HKExternal"
5396 input BackendDAE.EqSystem isyst;
5397 input BackendDAE.Shared ishared;
5398 input Boolean clearMatching;
5399 input BackendDAE.MatchingOptions inMatchingOptions;
5400 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5401 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5402 output BackendDAE.EqSystem osyst;
5403 output BackendDAE.Shared oshared;
5404 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5405 algorithm
5406 (osyst,oshared,outArg) :=
5407 matchcontinue inArg
5408 local
5409 Integer nvars,neqns;
5410 array<Integer> vec1,vec2;
5411 BackendDAE.StructurallySingularSystemHandlerArg arg;
5412 BackendDAE.EqSystem syst;
5413 BackendDAE.Shared shared;
5414 case _
5415 algorithm
5416 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5417 ✗ nvars := BackendVariable.daenumVariables(isyst);
5418 ✗ true := intGt(nvars,0);
5419 ✗ true := intGt(neqns,0);
5420 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5421 ✗ true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5422 ✗ (vec1,vec2,syst,shared,arg) := matchingExternal({},false,6,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5423 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5424 ✗ then
5425 (syst,shared,arg);
5426 // fail case if system is empty
5427 case _
5428 algorithm
5429 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5430 ✗ nvars := BackendVariable.daenumVariables(isyst);
5431 ✗ false := intGt(nvars,0);
5432 ✗ false := intGt(neqns,0);
5433 ✗ vec1 := listArray({});
5434 ✗ vec2 := listArray({});
5435 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5436 then
5437 (syst,ishared,inArg);
5438 else
5439 algorithm
5440 ✗ if Flags.isSet(Flags.FAILTRACE) then
5441 ✗ Debug.trace("- Matching.HKExternal failed\n");
5442 end if;
5443 ✗ then
5444 fail();
5445 end matchcontinue;
5446 end HKExternal;
5447
5448 public function HKDWExternal
5449 "function: HKDWExternal"
5450 input BackendDAE.EqSystem isyst;
5451 input BackendDAE.Shared ishared;
5452 input Boolean clearMatching;
5453 input BackendDAE.MatchingOptions inMatchingOptions;
5454 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5455 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5456 output BackendDAE.EqSystem osyst;
5457 output BackendDAE.Shared oshared;
5458 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5459 algorithm
5460 (osyst,oshared,outArg) :=
5461 matchcontinue inArg
5462 local
5463 Integer nvars,neqns;
5464 array<Integer> vec1,vec2;
5465 BackendDAE.StructurallySingularSystemHandlerArg arg;
5466 BackendDAE.EqSystem syst;
5467 BackendDAE.Shared shared;
5468 case _
5469 algorithm
5470 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5471 ✗ nvars := BackendVariable.daenumVariables(isyst);
5472 ✗ true := intGt(nvars,0);
5473 ✗ true := intGt(neqns,0);
5474 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5475 ✗ true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5476 ✗ (vec1,vec2,syst,shared,arg) := matchingExternal({},false,7,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5477 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5478 ✗ then
5479 (syst,shared,arg);
5480 // fail case if system is empty
5481 case _
5482 algorithm
5483 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5484 ✗ nvars := BackendVariable.daenumVariables(isyst);
5485 ✗ false := intGt(nvars,0);
5486 ✗ false := intGt(neqns,0);
5487 ✗ vec1 := listArray({});
5488 ✗ vec2 := listArray({});
5489 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5490 then
5491 (syst,ishared,inArg);
5492 else
5493 algorithm
5494 ✗ if Flags.isSet(Flags.FAILTRACE) then
5495 ✗ Debug.trace("- Matching.HKDWExternal failed\n");
5496 end if;
5497 ✗ then
5498 fail();
5499 end matchcontinue;
5500 end HKDWExternal;
5501
5502 public function ABMPExternal
5503 "function: ABMPExternal"
5504 input BackendDAE.EqSystem isyst;
5505 input BackendDAE.Shared ishared;
5506 input Boolean clearMatching;
5507 input BackendDAE.MatchingOptions inMatchingOptions;
5508 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5509 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5510 output BackendDAE.EqSystem osyst;
5511 output BackendDAE.Shared oshared;
5512 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5513 algorithm
5514 (osyst,oshared,outArg) :=
5515 matchcontinue inArg
5516 local
5517 Integer nvars,neqns;
5518 array<Integer> vec1,vec2;
5519 BackendDAE.StructurallySingularSystemHandlerArg arg;
5520 BackendDAE.EqSystem syst;
5521 BackendDAE.Shared shared;
5522 case _
5523 algorithm
5524 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5525 ✗ nvars := BackendVariable.daenumVariables(isyst);
5526 ✗ true := intGt(nvars,0);
5527 ✗ true := intGt(neqns,0);
5528 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5529 ✗ true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5530 ✗ (vec1,vec2,syst,shared,arg) := matchingExternal({},false,8,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5531 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5532 ✗ then
5533 (syst,shared,arg);
5534 // fail case if system is empty
5535 case _
5536 algorithm
5537 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5538 ✗ nvars := BackendVariable.daenumVariables(isyst);
5539 ✗ false := intGt(nvars,0);
5540 ✗ false := intGt(neqns,0);
5541 ✗ vec1 := listArray({});
5542 ✗ vec2 := listArray({});
5543 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5544 then
5545 (syst,ishared,inArg);
5546 else
5547 algorithm
5548 ✗ if Flags.isSet(Flags.FAILTRACE) then
5549 ✗ Debug.trace("- Matching.ABMPExternal failed\n");
5550 end if;
5551 ✗ then
5552 fail();
5553 end matchcontinue;
5554 end ABMPExternal;
5555
5556 public function PR_FIFO_FAIRExternal
5557 "function: PR_FIFO_FAIRExternal"
5558 input BackendDAE.EqSystem isyst;
5559 input BackendDAE.Shared ishared;
5560 input Boolean clearMatching;
5561 input BackendDAE.MatchingOptions inMatchingOptions;
5562 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5563 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5564 output BackendDAE.EqSystem osyst;
5565 output BackendDAE.Shared oshared;
5566 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5567 algorithm
5568 (osyst,oshared,outArg) :=
5569 matchcontinue inArg
5570 local
5571 Integer nvars,neqns;
5572 array<Integer> vec1,vec2;
5573 BackendDAE.StructurallySingularSystemHandlerArg arg;
5574 BackendDAE.EqSystem syst;
5575 BackendDAE.Shared shared;
5576 case _
5577 algorithm
5578 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5579 ✗ nvars := BackendVariable.daenumVariables(isyst);
5580 ✗ true := intGt(nvars,0);
5581 ✗ true := intGt(neqns,0);
5582 ✗ (vec1,vec2) := getAssignment(clearMatching,nvars,neqns,isyst);
5583 ✗ true := if not clearMatching then BackendDAEEXT.setAssignment(neqns, nvars, vec1, vec2) else true;
5584 ✗ (vec1,vec2,syst,shared,arg) := matchingExternal({},false,10,Config.getCheapMatchingAlgorithm(),if clearMatching then 1 else 0,isyst,ishared,nvars, neqns, vec1, vec2, inMatchingOptions, sssHandler, inArg);
5585 ✗ syst := BackendDAEUtil.setEqSystMatching(syst,BackendDAE.MATCHING(vec2,vec1,{}));
5586 ✗ then
5587 (syst,shared,arg);
5588 // fail case if system is empty
5589 case _
5590 algorithm
5591 ✗ neqns := BackendDAEUtil.systemSize(isyst);
5592 ✗ nvars := BackendVariable.daenumVariables(isyst);
5593 ✗ false := intGt(nvars,0);
5594 ✗ false := intGt(neqns,0);
5595 ✗ vec1 := listArray({});
5596 ✗ vec2 := listArray({});
5597 ✗ syst := BackendDAEUtil.setEqSystMatching(isyst,BackendDAE.MATCHING(vec2,vec1,{}));
5598 then
5599 (syst,ishared,inArg);
5600 else
5601 algorithm
5602 ✗ if Flags.isSet(Flags.FAILTRACE) then
5603 ✗ Debug.trace("- Matching.PR_FIFO_FAIRExternal failed\n");
5604 end if;
5605 ✗ then
5606 fail();
5607 end matchcontinue;
5608 end PR_FIFO_FAIRExternal;
5609
5610 protected function matchingExternal
5611 "function: matchingExternal, helper for external matching algorithms
5612 author: Frenkel TUD"
5613 input list<list<Integer>> meqns "Marked Equations for Index Reduction";
5614 input Boolean internalCall "true if function is called from it self";
5615 input Integer algIndx "Index of the algorithm, see BackendDAEEXT.matching";
5616 input Integer cheapMatching "Method for cheap Matching";
5617 input Integer clearMatching;
5618 input BackendDAE.EqSystem isyst;
5619 input BackendDAE.Shared ishared;
5620 input Integer nv;
5621 input Integer ne;
5622 input array<Integer> ass1 "eqn := ass1[var]";
5623 input array<Integer> ass2 "var := ass2[eqn]";
5624 input BackendDAE.MatchingOptions inMatchingOptions;
5625 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
5626 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
5627 output array<Integer> outAss1;
5628 output array<Integer> outAss2;
5629 output BackendDAE.EqSystem osyst;
5630 output BackendDAE.Shared oshared;
5631 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
5632 algorithm
5633 238029 Error.checkCancel();
5634 (outAss1,outAss2,osyst,oshared,outArg):=
5635 match (meqns,internalCall,isyst,inMatchingOptions)
5636 local
5637 BackendDAE.AdjacencyMatrix m,mt, m1,m1t;
5638 Integer nv_1,ne_1,memsize;
5639 list<Integer> unmatched_eqs;
5640 list<list<Integer>> meqns1, comps;
5641 BackendDAE.StructurallySingularSystemHandlerArg arg,arg1;
5642 BackendDAE.EqSystem syst;
5643 BackendDAE.Shared shared;
5644 array<Integer> ass1_1,ass1_2,ass1_3,ass2_1,ass2_2,ass2_3;
5645 Boolean changed = false;
5646 case ({},true,_,_)
5647 then
5648 (ass1,ass2,isyst,ishared,inArg);
5649 case ({},false,BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)),_)
5650 algorithm
5651 119015 matchingExternalsetAdjacencyMatrix(nv,ne,m);
5652 119015 BackendDAEEXT.matching(nv,ne,algIndx,cheapMatching,1.0,clearMatching);
5653 119015 BackendDAEEXT.getAssignment(ass1,ass2);
5654
5655 /*
5656 -----------------------------------------
5657 Try to transform analytical to structural
5658 singularities and destroy algebraic loops
5659 -----------------------------------------
5660 */
5661
5662 // flat-copy everything
5663 119015 (ass1_1, ass2_1) := (ass1, ass2);
5664 119015 syst := isyst;
5665
5666 /* check if index type is solvable and is unprocessed and if index reduction is activated */
5667
5/6
✓ Branch 1 taken 119015 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 59375 times.
✓ Branch 5 taken 59640 times.
✓ Branch 7 taken 1510 times.
✓ Branch 8 taken 57865 times.
119015 if (not Flags.getConfigBool(Flags.NO_ASSC)) and BackendDAEUtil.hasIndexTypeSolvableAndUnprocessedScalar(syst) and BackendDAEUtil.doIndexReduction(inMatchingOptions) then
5668 /* set the system to processed so that it gets analyzed only once */
5669 1510 syst := BackendDAEUtil.setAnalyticalToStructuralProcessed(syst, true);
5670
5671 /* create NORMAL() adjacency matrix for sorting first */
5672 1510 (_, m1, _, _, _) := BackendDAEUtil.getAdjacencyMatrixScalar(isyst, BackendDAE.NORMAL(), NONE(), BackendDAEUtil.isInitializationDAE(ishared));
5673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1510 times.
3020 comps := Sorting.Tarjan(m1, ass2_1);
5674
5675
2/2
✓ Branch 0 taken 37761 times.
✓ Branch 1 taken 1510 times.
39271 for comp in comps loop
5676 37761 (ass1_1, ass2_1, syst, changed) := BackendDAEUtil.analyticalToStructuralSingularity(comp, ass1_1, ass2_1, syst, changed);
5677 end for;
5678
5679 /* only do matching again if anything has changed */
5680
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 1402 times.
1510 if changed then
5681 108 BackendDAEEXT.setAssignment(nv,ne,ass1_1,ass2_1);
5682
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 108 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 108 times.
108 BackendDAE.EQSYSTEM(m=SOME(m),mT=SOME(mt)) := syst;
5683 108 matchingExternalsetAdjacencyMatrix(nv,ne,m);
5684 /* Call with clearMatching = 0 to reuse old information */
5685 108 BackendDAEEXT.matching(nv,ne,algIndx,cheapMatching,1.0,0);
5686 108 BackendDAEEXT.getAssignment(ass1_1,ass2_1);
5687 end if;
5688
5689 end if;
5690
5691
5692 /* get unmatched equations for index reduction */
5693 119015 unmatched_eqs := getUnassigned(ne, ass1_1, {});
5694
5695
3/4
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 119004 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
119015 if Flags.isSet(Flags.BLT_DUMP) and Flags.isSet(Flags.GRAPHML) then BackendDump.dumpBipartiteGraphEqSystem(isyst, ishared, "BeforMatching_"+intString(arrayLength(m))+"_unmatched "+intString(listLength(unmatched_eqs))); end if;
5696
4/4
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 119004 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 10 times.
119015 if Flags.isSet(Flags.BLT_DUMP) and not listEmpty(unmatched_eqs) then print("unmatched equations: "+stringDelimitList(List.map(unmatched_eqs,intString),", ")+"\n\n"); end if;
5697
5698 /*
5699 -------------------------------------
5700 Check if Index Reduction is necessary
5701 -------------------------------------
5702 */
5703
2/2
✓ Branch 0 taken 118739 times.
✓ Branch 1 taken 276 times.
119015 if listEmpty(unmatched_eqs) then
5704 118739 meqns1 := {};
5705 else
5706 // remove some edges which do not have to be traversed when finding the MSSS
5707 276 m1 := arrayCopy(m);
5708 276 m1t := arrayCopy(mt);
5709 276 (m1,m1t) := removeEdgesForNoDerivativeFunctionInputs(m1,m1t,syst,ishared);
5710 276 (m1,m1t) := removeEdgesToDiscreteEquations(m1,m1t,syst,ishared);
5711
5712 276 meqns1 := getEqnsforIndexReduction(unmatched_eqs,ne,m1,m1t,ass1_1,ass2_1,inArg);
5713 end if;
5714 /*
5715 -----------------------------------------
5716 remove artificial states which cause
5717 problems for differentiation
5718 -----------------------------------------
5719 */
5720
2/2
✓ Branch 0 taken 276 times.
✓ Branch 1 taken 118739 times.
119015 if not listEmpty(meqns1) then
5721 276 (syst, meqns1, ass1_1, ass2_1) := sanityCheckArtificialStates(syst, ishared, nv, ne, meqns1, ass1_1, ass2_1, algIndx, cheapMatching, clearMatching, inArg);
5722 else
5723 118739 (syst, meqns1, ass1_1, ass2_1) := (syst, meqns1, ass1_1, ass2_1);
5724 end if;
5725
4/4
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 119003 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 10 times.
119014 if Flags.isSet(Flags.BLT_DUMP) and not listEmpty(meqns1)
5726 1 then print("Index Reduction neccessary!\n"
5727 + "MSS subsets:\n " + stringDelimitList(List.map(meqns1,Util.intLstString),"\n ")+"\n\n");
5728 end if;
5729
5730 //Debug information
5731 //if listLength(List.flatten(meqns1)) >= 5 then meqs_short = List.firstN(List.flatten(meqns1),5); else meqs_short = List.flatten(meqns1); end if;
5732 //BackendDump.dumpBipartiteGraphEqSystem(isyst,ishared,"MSSS_"+stringDelimitList(List.map(meqs_short,intString),"_"));
5733 119288 (ass1_1,ass2_1,syst,shared,arg) := matchingExternal(meqns1,true,algIndx,-1,0,syst,ishared,nv,ne,ass1_1,ass2_1,inMatchingOptions,sssHandler,inArg);
5734 then
5735 (ass1_1,ass2_1,syst,shared,arg);
5736 case (_::_,_,_,(BackendDAE.INDEX_REDUCTION(),_))
5737 algorithm
5738 memsize := arrayLength(ass1);
5739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 274 times.
274 (_,_,syst,shared,ass2_1,ass1_1,arg) := sssHandler(meqns,0,isyst,ishared,ass2,ass1,inArg);
5740 274 ne_1 := BackendDAEUtil.systemSize(syst);
5741 274 nv_1 := BackendVariable.daenumVariables(syst);
5742 274 ass1_2 := assignmentsArrayExpand(ass1_1,ne_1,memsize,-1);
5743 274 ass2_2 := assignmentsArrayExpand(ass2_1,nv_1,memsize,-1);
5744
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 274 times.
274 true := BackendDAEEXT.setAssignment(ne_1,nv_1,ass1_2,ass2_2);
5745 274 (ass1_3,ass2_3,syst,shared,arg1) := matchingExternal({},false,algIndx,cheapMatching,clearMatching,syst,shared,nv_1,ne_1,ass1_2,ass2_2,inMatchingOptions,sssHandler,arg);
5746 then
5747 (ass1_3,ass2_3,syst,shared,arg1);
5748
5749 else
5750 algorithm
5751 ✗ singularSystemError(meqns,0,isyst,ishared,ass1,ass2,inArg);
5752 ✗ then
5753 fail();
5754
5755 end match;
5756 end matchingExternal;
5757
5758 protected function sanityCheckArtificialStates
5759 "author: kabdelhak 2019-09 FHB
5760 Checks if all equations that have to be differentiated for index reduction can
5761 be differentiated by all artificial states. Reverts all those for which we
5762 cannot derive to be algebraic variables.
5763 Ticket: 5459
5764 ----------------------------- INFO -----------------------------
5765 Artificial states are those which do not naturally appear
5766 differentiated in the system of DAEs, but have been forced
5767 to be states with 'StateSelect.always' or 'StateSelect.prefer'.
5768 ----------------------------------------------------------------"
5769 input output BackendDAE.EqSystem syst;
5770 input BackendDAE.Shared shared;
5771 input Integer nv;
5772 input Integer ne;
5773 input output list<list<Integer>> eqns;
5774 input output array<Integer> ass1;
5775 input output array<Integer> ass2;
5776 input Integer algIndx "Index of the algorithm, see BackendDAEEXT.matching";
5777 input Integer cheapMatching "Method for cheap Matching";
5778 input Integer clearMatching;
5779 input BackendDAE.StructurallySingularSystemHandlerArg arg;
5780 protected
5781 list<list<Integer>> eqns_1, unassignedStates, unassignedEqns;
5782 list<Integer> flat_unassignedStates, flat_eqns, unmatched1, unassigned, preferStates;
5783 UnorderedSet<Integer> excessStates = UnorderedSet.new(Util.id, intEq);
5784 list<BackendDAE.Var> reverted = {};
5785 Option<UnorderedSet<DAE.ComponentRef>> derCrefs = NONE();
5786 UnorderedSet<DAE.ComponentRef> dcrs;
5787 BackendDAE.ConstraintEquations constraintEqns;
5788 Integer otherStates;
5789 array<Integer> scalarToArrayMap;
5790 list<BackendDAE.Var> artificialStates = {}, undiffable_artificial = {};
5791 list<BackendDAE.Equation> equations = {};
5792 list<tuple<BackendDAE.Equation, Option<list<DAE.Exp>>>> eqn_forms = {};
5793 list<DAE.Exp> residual_exps;
5794 Option<list<DAE.Exp>> opt_exps;
5795 array<BackendDAE.Var> state_array;
5796 array<list<BackendDAE.Equation>> failed_eqns;
5797 UnorderedMap<DAE.ComponentRef, Integer> state_map;
5798 UnorderedSet<Integer> eqn_states;
5799 UnorderedSet<Integer> visited_states = UnorderedSet.new(Util.id, intEq);
5800 UnorderedSet<Integer> visited_eqns = UnorderedSet.new(Util.id, intEq);
5801 Integer arrayIdx, n_states;
5802 BackendDAE.Var var;
5803 BackendDAE.Equation form_eqn;
5804 DAE.ComponentRef cr;
5805 DAE.Exp residualExp, diffExp;
5806 BackendDAE.AdjacencyMatrix m, mt, m1, m1t;
5807 String msg;
5808 algorithm
5809 try
5810 // Get the information about MSSS from index reduction
5811 276 (eqns_1, unassignedStates, unassignedEqns, _) := IndexReduction.minimalStructurallySingularSystem(eqns, syst, shared, ass2, ass1, arg);
5812 else
5813
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if Flags.isSet(Flags.BLT_DUMP) then
5814 ✗ singularSystemError(eqns, 0, syst, shared, ass1, ass2, arg);
5815 end if;
5816 1 fail();
5817 end try;
5818 // A subset with more unassigned equations than states other than the
5819 // artificial prefer states turns some of those into dummy states anyway.
5820 // Before anything is differentiated, leave them algebraic instead.
5821 275 (_, constraintEqns, _, _, _) := arg;
5822
4/4
✓ Branch 1 taken 179 times.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 1423 times.
✓ Branch 4 taken 275 times.
1973 for states in if Array.all(constraintEqns, listEmpty) then unassignedStates else {} loop
5823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1423 times.
1423 unassigned :: unassignedEqns := unassignedEqns;
5824 otherStates := 0;
5825 preferStates := {};
5826
2/2
✓ Branch 0 taken 4398 times.
✓ Branch 1 taken 1423 times.
5821 for state in states loop
5827 4398 var := BackendVariable.getVarAt(syst.orderedVars, state);
5828
4/4
✓ Branch 1 taken 229 times.
✓ Branch 2 taken 4169 times.
✓ Branch 4 taken 208 times.
✓ Branch 5 taken 21 times.
4398 if BackendVariable.isArtificialState(var) and BackendVariable.varStateSelectPrefer(var) then
5829
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 169 times.
208 if isNone(derCrefs) then
5830 39 derCrefs := SOME(derivedCrefs(syst, shared));
5831 end if;
5832
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 208 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 208 times.
208 SOME(dcrs) := derCrefs;
5833
2/2
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 173 times.
208 if UnorderedSet.contains(var.varName, dcrs) then
5834 35 otherStates := otherStates + 1;
5835 else
5836 preferStates := state :: preferStates;
5837 end if;
5838 else
5839 4190 otherStates := otherStates + 1;
5840 end if;
5841 end for;
5842
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1419 times.
1423 if listLength(unassigned) > otherStates then
5843
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4 times.
19 for state in preferStates loop
5844
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 if UnorderedSet.add(state, excessStates) then
5845 15 var := BackendVariable.getVarAt(syst.orderedVars, state);
5846 15 reverted := BackendVariable.setVarKind(var, BackendDAE.VARIABLE()) :: reverted;
5847 end if;
5848 end for;
5849 end if;
5850 end for;
5851
3/4
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 274 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
275 if Flags.isSet(Flags.BLT_DUMP) and not listEmpty(reverted) then
5852 ✗ print(BackendDump.varListStringShort(reverted, "Artificial states that cannot all be states, treated as algebraic"));
5853 end if;
5854 275 flat_unassignedStates := List.flatten(unassignedStates);
5855 // Collect artificial states
5856
2/2
✓ Branch 0 taken 7620 times.
✓ Branch 1 taken 275 times.
7895 for state in flat_unassignedStates loop
5857
4/4
✓ Branch 1 taken 7600 times.
✓ Branch 2 taken 20 times.
✓ Branch 4 taken 5279 times.
✓ Branch 5 taken 2321 times.
7620 if not UnorderedSet.contains(state, excessStates) and UnorderedSet.add(state, visited_states) then
5858 5279 var := BackendVariable.getVarAt(syst.orderedVars, state);
5859
2/2
✓ Branch 1 taken 957 times.
✓ Branch 2 taken 4322 times.
5279 if BackendVariable.isArtificialState(var) then
5860 artificialStates := var :: artificialStates;
5861 end if;
5862 end if;
5863 end for;
5864
4/4
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 101 times.
✓ Branch 2 taken 172 times.
✓ Branch 3 taken 2 times.
275 if listEmpty(artificialStates) and listEmpty(reverted) then
5865 172 return;
5866 end if;
5867 103 flat_eqns := List.flatten(eqns_1); // use eqns_1 (without discrete)
5868
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 103 times.
103 SOME((_, scalarToArrayMap, _, _, _)) := syst.mapping;
5869
2/2
✓ Branch 0 taken 2472 times.
✓ Branch 1 taken 103 times.
2575 for scalar_eqn in flat_eqns loop
5870 try
5871 2472 arrayIdx := scalarToArrayMap[scalar_eqn];
5872
1/2
✓ Branch 1 taken 2472 times.
✗ Branch 2 not taken.
2472 if UnorderedSet.add(arrayIdx, visited_eqns) then
5873 2472 equations := BackendEquation.get(syst.orderedEqs, arrayIdx) :: equations;
5874 end if;
5875 else
5876 // equation can't be found -- scalar index to array index failed?
5877 end try;
5878 end for;
5879
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 103 times.
103 state_array := listArray(artificialStates);
5880 103 n_states := arrayLength(state_array);
5881 103 failed_eqns := arrayCreate(n_states, {});
5882 103 state_map := UnorderedMap.new<Integer>(ComponentReferenceBasics.hashComponentRef,
5883 ComponentReferenceBasics.crefEqual, Util.nextPrime(n_states));
5884
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 2 times.
1060 for i in 1:n_states loop
5885 957 UnorderedMap.add(BackendVariable.varCref(state_array[i]), i, state_map);
5886 end for;
5887 // The residual form is state independent; an equation without one stays
5888 // undiffable for every artificial state.
5889
2/2
✓ Branch 0 taken 2472 times.
✓ Branch 1 taken 103 times.
2575 for eqn in equations loop
5890 2472 Error.checkCancel();
5891 try
5892 2472 residual_exps := {};
5893
2/2
✓ Branch 1 taken 2472 times.
✓ Branch 2 taken 2472 times.
4944 for res in BackendEquation.equationToScalarResidualForm(eqn, shared.functionTree) loop
5894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2472 times.
2472 BackendDAE.RESIDUAL_EQUATION(exp = residualExp) := res;
5895 residual_exps := residualExp :: residual_exps;
5896 end for;
5897 4944 eqn_forms := (eqn, SOME(listReverse(residual_exps))) :: eqn_forms;
5898 else
5899 ✗ eqn_forms := (eqn, NONE()) :: eqn_forms;
5900 end try;
5901 end for;
5902 // Look up the states an equation mentions instead of scanning all equations
5903 // for every state.
5904
2/2
✓ Branch 1 taken 2472 times.
✓ Branch 2 taken 103 times.
2575 for form in listReverse(eqn_forms) loop
5905 2472 (form_eqn, opt_exps) := form;
5906
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2472 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2472 times.
2472 if isNone(opt_exps) then
5907 ✗ for i in 1:n_states loop
5908 ✗ failed_eqns[i] := form_eqn :: failed_eqns[i];
5909 end for;
5910 else
5911 2472 SOME(residual_exps) := opt_exps;
5912 2472 eqn_states := UnorderedSet.new(Util.id, intEq);
5913
2/2
✓ Branch 0 taken 2472 times.
✓ Branch 1 taken 2472 times.
4944 for res_exp in residual_exps loop
5914 2472 Expression.traverseExpTopDown(res_exp, function collectArtificialStates(stateMap = state_map, states = eqn_states), false);
5915 end for;
5916
2/2
✓ Branch 1 taken 2715 times.
✓ Branch 2 taken 2472 times.
5187 for i in UnorderedSet.toList(eqn_states) loop
5917 2715 Error.checkCancel();
5918 2715 cr := BackendVariable.varCref(state_array[i]);
5919 try
5920
2/2
✓ Branch 0 taken 2715 times.
✓ Branch 1 taken 2698 times.
5413 for res_exp in residual_exps loop
5921 // Only check if the equation actually contains the cref
5922
1/2
✓ Branch 1 taken 2715 times.
✗ Branch 2 not taken.
2715 if Expression.expHasCref(res_exp, cr) then
5923 // Check if the equation can be differentiated by the artificial state
5924 2715 (diffExp,_,_) := Inline.forceInlineExp(res_exp,(SOME(shared.functionTree),{DAE.NORM_INLINE(),DAE.DEFAULT_INLINE()}),DAE.emptyElementSource,Ceval.cevalSimpleWithFunctionTreeReturnExp);
5925 2715 diffExp := Expression.replaceDerOpInExp(diffExp);
5926 2715 Differentiate.differentiateExpSolve(diffExp, cr, SOME(shared.functionTree));
5927 // Check if the equation contains smooth(0, cr)
5928
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2698 times.
2698 false := Expression.expHasCrefInSmoothZero(diffExp, cr);
5929 end if;
5930 end for;
5931 else
5932 34 failed_eqns[i] := form_eqn :: failed_eqns[i];
5933 end try;
5934 end for;
5935 end if;
5936 end for;
5937
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 2 times.
1060 for i in 1:n_states loop
5938
2/2
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 940 times.
957 if not listEmpty(failed_eqns[i]) then
5939 17 var := state_array[i];
5940
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if Flags.isSet(Flags.BLT_DUMP) then
5941 ✗ for eqn in listReverse(failed_eqns[i]) loop
5942 ✗ print("### The Equation ### \n" + BackendDump.equationString(eqn) +
5943 "\n\n--- could not be differentiated for artificial variable ---\n " +
5944 ComponentReferenceBasics.printComponentRefStr(var.varName) + ".\n\n");
5945 end for;
5946 end if;
5947 // revert the varKind from STATE to VARIABLE
5948 17 undiffable_artificial := BackendVariable.setVarKind(var, BackendDAE.VARIABLE()) :: undiffable_artificial;
5949 end if;
5950 end for;
5951
5952
4/4
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 97 times.
✓ Branch 3 taken 3 times.
103 if not (listEmpty(undiffable_artificial) and listEmpty(reverted)) then
5953 6 syst.orderedVars := BackendVariable.addVars(listAppend(reverted, undiffable_artificial), syst.orderedVars);
5954 6 (syst, _, _, _, _) := BackendDAEUtil.getAdjacencyMatrixScalar(syst, BackendDAE.SOLVABLE(), SOME(shared.functionTree), BackendDAEUtil.isInitializationDAE(shared));
5955
5956
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
6 if isSome(syst.m) and isSome(syst.mT) then
5957 6 SOME(m) := syst.m;
5958 6 SOME(mt) := syst.mT;
5959 // It would be great to replace full matching by continue matching,
5960 // to reuse old information, but somehow it does something different.
5961 // (ass1, ass2) := ContinueMatching(m, nv, ne, ass1, ass2);
5962 6 matchingExternalsetAdjacencyMatrix(nv, ne, m);
5963 6 BackendDAEEXT.matching(nv, ne, algIndx, cheapMatching, 1.0, clearMatching);
5964 6 BackendDAEEXT.getAssignment(ass1, ass2);
5965 6 unmatched1 := getUnassigned(ne, ass1, {});
5966 6 m1 := arrayCopy(m);
5967 6 m1t := arrayCopy(mt);
5968 6 (m1,m1t) := removeEdgesForNoDerivativeFunctionInputs(m1, m1t, syst, shared);
5969 6 (m1,m1t) := removeEdgesToDiscreteEquations(m1, m1t, syst, shared);
5970 6 eqns := getEqnsforIndexReduction(unmatched1, ne, m1, m1t, ass1, ass2, arg);
5971 end if;
5972
5973
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 if Flags.isSet(Flags.BLT_DUMP) and not listEmpty(undiffable_artificial) then
5974 ✗ print("----------------------------- INFO -----------------------------\n" +
5975 " Artificial states are those which do not naturally appear\n" +
5976 " differentiated in the system of DAEs, but have been forced\n" +
5977 " to be states with 'StateSelect.always' or 'StateSelect.prefer'.\n" +
5978 " The ones mentioned above will be treated as if they had \n" +
5979 "'StateSelect.default'.\n" +
5980 "----------------------------------------------------------------\n\n");
5981 end if;
5982
5983
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if not listEmpty(undiffable_artificial) then
5984 3 msg := BackendDump.varListStringShort(undiffable_artificial,"They will be treated as if they had stateSelect=StateSelect.default") +
5985 "Please use -d=bltdump for more information.\n";
5986 3 Error.addMessage(Error.STATE_STATESELECT_PREFER_REVERT, {msg});
5987 end if;
5988 end if;
5989 end sanityCheckArtificialStates;
5990
5991 protected function derivedCrefs
5992 "Returns the crefs that occur differentiated in the equations or the initial
5993 equations, and the crefs that are the derivative of a state."
5994 input BackendDAE.EqSystem syst;
5995 input BackendDAE.Shared shared;
5996 output UnorderedSet<DAE.ComponentRef> crefs = UnorderedSet.new(ComponentReferenceBasics.hashComponentRef, ComponentReferenceBasics.crefEqual);
5997 algorithm
5998 39 BackendDAEUtil.traverseBackendDAEExpsEqns(syst.orderedEqs, Expression.traverseSubexpressionsHelper, (collectDerCref, crefs));
5999 39 BackendDAEUtil.traverseBackendDAEExpsEqns(BackendEquation.getInitialEqnsFromShared(shared), Expression.traverseSubexpressionsHelper, (collectDerCref, crefs));
6000
2/2
✓ Branch 1 taken 4066 times.
✓ Branch 2 taken 39 times.
4105 for var in BackendVariable.varList(syst.orderedVars) loop
6001 () := match var.varKind
6002 local
6003 DAE.ComponentRef cr;
6004 case BackendDAE.STATE(derName = SOME(cr))
6005 algorithm
6006 171 UnorderedSet.add(cr, crefs);
6007 then ();
6008 else ();
6009 end match;
6010 end for;
6011 end derivedCrefs;
6012
6013 protected function collectDerCref
6014 input output DAE.Exp exp;
6015 input output UnorderedSet<DAE.ComponentRef> crefs;
6016 algorithm
6017 () := match exp
6018 local
6019 DAE.ComponentRef cr;
6020 case DAE.CALL(path = Absyn.IDENT("der"), expLst = {DAE.CREF(componentRef = cr)})
6021 algorithm
6022 407 UnorderedSet.add(cr, crefs);
6023 then ();
6024 else ();
6025 end match;
6026 end collectDerCref;
6027
6028 protected function collectArtificialStates
6029 "Collects the indices of the artificial states occurring in the expression.
6030 Mirrors Expression.expHasCref, which does not look inside pre()."
6031 input DAE.Exp exp;
6032 input Boolean arg;
6033 input UnorderedMap<DAE.ComponentRef, Integer> stateMap;
6034 input UnorderedSet<Integer> states;
6035 output DAE.Exp outExp = exp;
6036 output Boolean cont;
6037 output Boolean outArg = arg;
6038 protected
6039 Integer index;
6040 algorithm
6041 cont := match exp
6042 case DAE.CALL(path = Absyn.IDENT("pre")) then false;
6043 case DAE.CREF()
6044 algorithm
6045 () := match UnorderedMap.get(exp.componentRef, stateMap)
6046 3776 case SOME(index) algorithm UnorderedSet.add(index, states); then ();
6047 else ();
6048 end match;
6049 then true;
6050 else true;
6051 end match;
6052 end collectArtificialStates;
6053
6054 protected function removeEdgesToDiscreteEquations""
6055 input BackendDAE.AdjacencyMatrix m;
6056 input BackendDAE.AdjacencyMatrixT mt;
6057 input BackendDAE.EqSystem sys;
6058 input BackendDAE.Shared shared;
6059 output BackendDAE.AdjacencyMatrix mOut;
6060 output BackendDAE.AdjacencyMatrixT mtOut;
6061 protected
6062 Boolean isDiscrete;
6063 Integer idx, idx2, size, varIdx;
6064 list<Integer> varIdxs, eqIdxs;
6065 BackendDAE.EquationArray eqs;
6066 BackendDAE.Variables vars;
6067 list<BackendDAE.Var> varLst;
6068 array<list<Integer>> eqIdxArray;
6069 UnorderedSet<Integer> idxSet;
6070 algorithm
6071 282 vars := sys.orderedVars;
6072 282 eqs := sys.orderedEqs;
6073 idx := 1;
6074 idx2 := 0;
6075 282 eqIdxArray := arrayCreate(BackendEquation.getNumberOfEquations(eqs), {});
6076 //algorithms with size>n occur as n single nodes in the adjacency matrix, delete the rows for each of them
6077
2/2
✓ Branch 1 taken 53096 times.
✓ Branch 2 taken 282 times.
53378 for eq in BackendEquation.equationList(eqs) loop
6078 53096 size := BackendEquation.equationSize(BackendEquation.get(eqs, idx));
6079 53096 eqIdxs := List.map1(List.intRange(size),intAdd,idx2);
6080 53096 arrayUpdate(eqIdxArray, idx, eqIdxs);
6081 53096 idx := idx+1;
6082 53096 idx2 := size+idx2;
6083 end for;
6084 idx := 1;
6085
2/2
✓ Branch 1 taken 53096 times.
✓ Branch 2 taken 282 times.
53378 for eq in BackendEquation.equationList(eqs) loop
6086 53096 Error.checkCancel();
6087 //print("Check equation "+BackendDump.equationString(eq)+"\n");
6088 53096 isDiscrete := BackendEquation.isWhenEquationOrDiscreteAlgorithm(eq,vars);
6089
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 53030 times.
53096 if isDiscrete then
6090 66 varLst := BackendEquation.equationVars(eq,vars);
6091
6092 66 varIdxs := BackendVariable.getVarIndexFromVars(varLst,vars);
6093 66 eqIdxs := eqIdxArray[idx];
6094 //print("remove edges between eqs: "+stringDelimitList(List.map(eqIdxs,intString),", ")+" and vars "+stringDelimitList(List.map(varIdxs,intString),", ")+"\n");
6095 //update m
6096 66 idxSet := UnorderedSet.fromList(varIdxs, Util.id, intEq);
6097
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 66 times.
157 for e in eqIdxs loop
6098 91 arrayUpdate(m, e, UnorderedSet.difference_list_set(m[e], varIdxs, idxSet));
6099 end for;
6100 //update mt
6101 66 idxSet := UnorderedSet.fromList(eqIdxs, Util.id, intEq);
6102
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 66 times.
253 for varIdx in varIdxs loop
6103 187 arrayUpdate(mt, varIdx, UnorderedSet.difference_list_set(mt[varIdx], eqIdxs, idxSet));
6104 end for;
6105 end if;
6106 53096 idx := idx+1;
6107 end for;
6108 mOut := m;
6109 mtOut := mt;
6110 end removeEdgesToDiscreteEquations;
6111
6112 protected function removeEdgesForNoDerivativeFunctionInputs"when gathering the minimal structurally singular subsets from the unmatches equations,
6113 some edges dont have to be considered e.g. edges between a function call and an input variable if the input variable will not be derived when deriving the function
6114 author: Waurich TUD 10-2015"
6115 input BackendDAE.AdjacencyMatrix m;
6116 input BackendDAE.AdjacencyMatrixT mt;
6117 input BackendDAE.EqSystem sys;
6118 input BackendDAE.Shared shared;
6119 output BackendDAE.AdjacencyMatrix mOut;
6120 output BackendDAE.AdjacencyMatrixT mtOut;
6121 protected
6122 Boolean hasNoDerAnno;
6123 Integer idx, varIdx;
6124 list<Integer> varIdxs, row;
6125 BackendDAE.EquationArray eqs;
6126 BackendDAE.Variables vars;
6127 AvlTreePathFunction.Tree functionTree;
6128 list<DAE.ComponentRef> noDerInputs;
6129 algorithm
6130 282 vars := sys.orderedVars;
6131 282 eqs := sys.orderedEqs;
6132 282 functionTree := shared.functionTree;
6133 idx := 1;
6134
2/2
✓ Branch 1 taken 53096 times.
✓ Branch 2 taken 282 times.
53378 for eq in BackendEquation.equationList(eqs) loop
6135 53096 Error.checkCancel();
6136 53096 (hasNoDerAnno,noDerInputs) := BackendDAEUtil.isFuncCallWithNoDerAnnotation(eq,functionTree);
6137
2/2
✓ Branch 0 taken 8471 times.
✓ Branch 1 taken 44625 times.
53096 if hasNoDerAnno then
6138 8471 (_,varIdxs) := BackendVariable.getVarLst(noDerInputs,vars);
6139 //print("remove edges between eq: "+intString(idx)+" and vars "+stringDelimitList(List.map(varIdxs,intString),", ")+"\n");
6140 //update m
6141 8471 row := m[idx];
6142 8471 row := UnorderedSet.difference_list(row,varIdxs,Util.id,intEq);
6143 8471 arrayUpdate(m,idx,row);
6144 //update mt
6145
2/2
✓ Branch 0 taken 61093 times.
✓ Branch 1 taken 8471 times.
69564 for varIdx in varIdxs loop
6146 61093 row := arrayGet(mt,varIdx);
6147 61093 row := List.deleteMemberOnTrue(idx,row,intEq);
6148 61093 arrayUpdate(mt,varIdx,row);
6149 end for;
6150 end if;
6151 53096 idx := idx+1;
6152 end for;
6153 mOut := m;
6154 mtOut := mt;
6155 end removeEdgesForNoDerivativeFunctionInputs;
6156
6157 protected function countadjacencyMatrixEntries
6158 input Integer n;
6159 input BackendDAE.AdjacencyMatrix m;
6160 output Integer outCount = 0;
6161 algorithm
6162
2/2
✓ Branch 0 taken 1028 times.
✓ Branch 1 taken 119945 times.
1223124 for i in 1:n loop
6163
2/2
✓ Branch 1 taken 5328435 times.
✓ Branch 2 taken 1102151 times.
6430586 for e in m[i] loop
6164
2/2
✓ Branch 0 taken 5125299 times.
✓ Branch 1 taken 203136 times.
5328435 if intGt(e,0) then
6165 5125299 outCount := outCount + 1;
6166 end if;
6167 end for;
6168 end for;
6169 end countadjacencyMatrixEntries;
6170
6171 public function matchingExternalsetAdjacencyMatrix
6172 "author: Frenkel TUD 2012-04
6173 "
6174 input Integer nv;
6175 input Integer ne;
6176 input array<list<Integer>> m;
6177 protected
6178 Integer nz;
6179 algorithm
6180 120973 nz := countadjacencyMatrixEntries(ne,m);
6181 120973 BackendDAEEXT.setAdjacencyMatrix(nv,ne,nz,m);
6182 end matchingExternalsetAdjacencyMatrix;
6183
6184 // =============================================================================
6185 // Util Functions
6186 //
6187 // =============================================================================
6188
6189 public function reachableEquations "author: lochel
6190 Returns a list of reachable nodes (equations), corresponding
6191 to those equations that uses the solved variable of this equation.
6192 The edges of the graph that identifies strong components/blocks are
6193 dependencies between blocks. A directed edge e = (n1, n2) means
6194 that n1 solves for a variable (e.g. \'a\') that is used in the equation
6195 of n2, i.e. the equation of n1 must be solved before the equation of n2."
6196 input Integer eqn;
6197 input BackendDAE.AdjacencyMatrixT mT;
6198 input array<Integer> ass2 "var := ass2[eqn]";
6199 output list<Integer> outEqNodes;
6200 protected
6201 Integer var;
6202 algorithm
6203 ✗ var := ass2[eqn] "get the variable that is solved in given equation";
6204 ✗ outEqNodes := if var > 0 then list(e for e guard(e > 0 and e <> eqn) in mT[var]) else {} "get the equations that depend on that variable";
6205 end reachableEquations;
6206
6207 public function incomingEquations "author: lochel
6208 Returns a list of incoming nodes (equations), corresponding
6209 to those variables that occur in this equation."
6210 input Integer eqn;
6211 input BackendDAE.AdjacencyMatrix m;
6212 input array<Integer> ass1 "eqn := ass1[var]";
6213 output list<Integer> outEqNodes;
6214 algorithm
6215
10/10
✓ Branch 1 taken 819280 times.
✓ Branch 2 taken 31261 times.
✓ Branch 4 taken 393887 times.
✓ Branch 5 taken 425393 times.
✓ Branch 6 taken 1418 times.
✓ Branch 7 taken 392469 times.
✓ Branch 8 taken 850541 times.
✓ Branch 9 taken 425393 times.
✓ Branch 10 taken 392469 times.
✓ Branch 11 taken 425393 times.
1275934 outEqNodes := list(ass1[var] for var guard(var > 0 and ass1[var] <> eqn and ass1[var] > 0) in m[eqn]);
6216 end incomingEquations;
6217
6218 public function isAssigned
6219 "author: Frenkel TUD 2012-05"
6220 input array<Integer> ass;
6221 input Integer i;
6222 output Boolean b;
6223 algorithm
6224 188 b := intGt(ass[intAbs(i)],0);
6225 end isAssigned;
6226
6227 public function isUnAssigned
6228 "author: Frenkel TUD 2012-05"
6229 input array<Integer> ass;
6230 input Integer i;
6231 output Boolean b;
6232 algorithm
6233 45195 b := intLt(ass[intAbs(i)],1);
6234 end isUnAssigned;
6235
6236 public function getMarked
6237 "author: Frenkel TUD 2012-05"
6238 input Integer ne;
6239 input Integer mark;
6240 input array<Integer> markArr;
6241 input list<Integer> iMarked;
6242 output list<Integer> oMarked;
6243 algorithm
6244 oMarked := match ne
6245 local
6246 list<Integer> marked;
6247 case 0
6248 then
6249 iMarked;
6250 case _
6251 algorithm
6252 ✗ marked := List.consOnTrue(intEq(markArr[ne],mark), ne, iMarked);
6253 ✗ then
6254 getMarked(ne-1,mark,markArr,marked);
6255 end match;
6256 end getMarked;
6257
6258 public function getUnassigned "author: Frenkel TUD 2012-05
6259 return all Indices with ass[indx]<1, traverses the
6260 array from the ne element to the first."
6261 input Integer ne;
6262 input array<Integer> ass;
6263 input list<Integer> inUnassigned;
6264 output list<Integer> outUnassigned;
6265 algorithm
6266 outUnassigned := match ne
6267 local
6268 list<Integer> unassigned;
6269 case 0
6270 then
6271 inUnassigned;
6272 case _
6273 algorithm
6274 988351 unassigned := List.consOnTrue(intLt(ass[ne],1), ne, inUnassigned);
6275 988351 then
6276 getUnassigned(ne-1,ass,unassigned);
6277 end match;
6278 end getUnassigned;
6279
6280 public function anyUnassigned
6281 "author: kabdelhak FHB 2019-08
6282 returns true if any assignment is -1."
6283 input Integer ne;
6284 input array<Integer> ass;
6285 output Boolean b;
6286 algorithm
6287 b := match ne
6288 local
6289 case 0
6290 then false;
6291 case _ guard(intLt(ass[ne],1))
6292 then true;
6293 112 else anyUnassigned(ne-1,ass);
6294 end match;
6295 end anyUnassigned;
6296
6297 public function getAssignedArray "author: lochel"
6298 input array<Integer> ass;
6299 output array<Boolean> outIsAssigned;
6300 protected
6301 Integer N = arrayLength(ass);
6302 algorithm
6303 ✗ outIsAssigned := arrayCreate(N, false);
6304 ✗ for i in 1:N loop
6305 ✗ if ass[i] > 0 then
6306 ✗ arrayUpdate(outIsAssigned, i, true);
6307 end if;
6308 end for;
6309 end getAssignedArray;
6310
6311 public function getAssigned
6312 "author: Frenkel TUD 2012-05
6313 return all Indixes with ass[indx]>0, traverses the
6314 array from the ne element to the first."
6315 input Integer ne;
6316 input array<Integer> ass;
6317 input list<Integer> inAssigned;
6318 output list<Integer> outAssigned;
6319 algorithm
6320 outAssigned := match ne
6321 local
6322 list<Integer> assigned;
6323 case 0
6324 then
6325 inAssigned;
6326 case _
6327 algorithm
6328 6622 assigned := List.consOnTrue(intGt(ass[ne],0), ne, inAssigned);
6329 6622 then
6330 getAssigned(ne-1,ass,assigned);
6331 end match;
6332 end getAssigned;
6333
6334 public function getEqnsforIndexReduction
6335 "function getEqnsforIndexReduction, collect all equations for the index reduction from a given set of
6336 unmatched equations
6337 author: Frenkel TUD 2012-04"
6338 input list<Integer> U;
6339 input Integer neqns;
6340 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
6341 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
6342 input array<Integer> ass1 "ass[eqnindx]=varindx";
6343 input array<Integer> ass2 "ass[varindx]=eqnindx";
6344 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
6345 output list<list<Integer>> eqns;
6346 algorithm
6347 eqns := match(U, inArg)
6348 local
6349 Integer lengthU;
6350 array<Integer> colummarks;
6351 array<list<Integer>> mapEqnIncRow,subsets;
6352 array<Integer> mapIncRowEqn;
6353 case({}, _) then {};
6354 case(_, (_,_,mapEqnIncRow,mapIncRowEqn,_))
6355 algorithm
6356 283 colummarks := arrayCreate(neqns,-1);
6357 283 lengthU := listLength(U);
6358 283 subsets := arrayCreate(lengthU,{}) "maximal number of subsets is each unassigned eqn has its own";
6359 283 subsets := getEqnsforIndexReduction1(U,m,mT,1,colummarks,ass1,ass2,mapEqnIncRow,mapIncRowEqn,subsets);
6360 // remove empty subsets
6361 283 then
6362 removeEmptySubsets(1,lengthU,subsets,{});
6363 end match;
6364 end getEqnsforIndexReduction;
6365
6366 protected function removeEmptySubsets
6367 input Integer index;
6368 input Integer length;
6369 input array<list<Integer>> subsets;
6370 input list<list<Integer>> iAcc;
6371 output list<list<Integer>> oAcc;
6372 algorithm
6373 oAcc := match iAcc
6374 local
6375 list<Integer> eqns;
6376 list<list<Integer>> acc;
6377 case _
6378 guard intLe(index,length)
6379 algorithm
6380 2905 eqns := subsets[index];
6381 2905 acc := appendNonEmpty(eqns,iAcc);
6382 2905 then
6383 removeEmptySubsets(index+1,length,subsets,acc);
6384 else iAcc;
6385 end match;
6386 end removeEmptySubsets;
6387
6388 protected function appendNonEmpty
6389 input list<Integer> eqns;
6390 input list<list<Integer>> iAcc;
6391 output list<list<Integer>> oAcc;
6392 algorithm
6393 oAcc := match eqns
6394 case {} then iAcc;
6395 else eqns::iAcc;
6396 end match;
6397 end appendNonEmpty;
6398
6399 protected function getEqnsforIndexReduction1
6400 "function getEqnsforIndexReduction1, helper for getEqnsforIndexReduction
6401 author: Frenkel TUD 2012-04"
6402 input list<Integer> U;
6403 input BackendDAE.AdjacencyMatrix m "m[eqnindx] = list(varindx)";
6404 input BackendDAE.AdjacencyMatrixT mT "mT[varindx] = list(eqnindx)";
6405 input Integer mark;
6406 input array<Integer> colummarks;
6407 input array<Integer> ass1 "ass[eqnindx]=varindx";
6408 input array<Integer> ass2 "ass[varindx]=eqnindx";
6409 input array<list<Integer>> mapEqnIncRow "eqn indx -> skalar Eqn indexes";
6410 input array<Integer> mapIncRowEqn "scalar eqn index -> eqn indx";
6411 input array<list<Integer>> inSubsets;
6412 output array<list<Integer>> outSubsets;
6413 algorithm
6414 outSubsets:= match U
6415 local
6416 list<Integer> rest,eqns;
6417 Integer e,e1;
6418 case {} then inSubsets;
6419 case e::rest
6420 guard not intGt(colummarks[e],0)
6421 algorithm
6422 2905 Error.checkCancel();
6423 // row is not visited
6424 // if it is a multi dim equation take all scalare equations
6425 2905 e1 := mapIncRowEqn[e];
6426 2905 eqns := mapEqnIncRow[e1];
6427 2905 List.fold1r(eqns,arrayUpdate,mark,colummarks);
6428 // print("Seach for unassigned Eqns " + stringDelimitList(List.map(eqns,intString),", ") + "\n");
6429 2905 eqns := getEqnsforIndexReductionphase(eqns,m,mT,mark,colummarks,ass1,ass2,mapEqnIncRow,mapIncRowEqn,inSubsets,eqns);
6430 // print("Found Eqns " + stringDelimitList(List.map(eqns,intString),", ") + "\n");
6431 2905 Array.appendToElement(mark,eqns,inSubsets);
6432 2905 then
6433 getEqnsforIndexReduction1(rest,m,mT,mark+1,colummarks,ass1,ass2,mapEqnIncRow,mapIncRowEqn,inSubsets);
6434 case _::rest
6435 ✗ then
6436 getEqnsforIndexReduction1(rest,m,mT,mark,colummarks,ass1,ass2,mapEqnIncRow,mapIncRowEqn,inSubsets);
6437 end match;
6438 end getEqnsforIndexReduction1;
6439
6440 protected function getEqnsforIndexReductionphase
6441 "author: Frenkel TUD 2012-04"
6442 input list<Integer> elst;
6443 input BackendDAE.AdjacencyMatrix m;
6444 input BackendDAE.AdjacencyMatrixT mT;
6445 input Integer mark;
6446 input array<Integer> colummarks;
6447 input array<Integer> ass1 "eqn := ass1[var]";
6448 input array<Integer> ass2 "var := ass2[eqn]";
6449 input array<list<Integer>> mapEqnIncRow "eqn indx -> skalar Eqn indexes";
6450 input array<Integer> mapIncRowEqn "scalar eqn index -> eqn indx";
6451 input array<list<Integer>> inSubsets;
6452 input list<Integer> inEqns;
6453 output list<Integer> outEqns;
6454 algorithm
6455 outEqns :=
6456 match elst
6457 local
6458 Integer e;
6459 list<Integer> rows,rest,eqns;
6460 case {} then inEqns;
6461 case e::rest
6462 algorithm
6463 // traverse all adiacent rows
6464 7728 rows := List.select(m[e], Util.intPositive);
6465 //print("search in Vars " + stringDelimitList(List.map(rows,intString),", ") + " from equation " + intString(e) + "\n");
6466 7728 eqns := getEqnsforIndexReductiontraverseRows(rows,{},m,mT,mark,colummarks,ass1,ass2,mapEqnIncRow,mapIncRowEqn,inSubsets,inEqns);
6467 7728 then
6468 getEqnsforIndexReductionphase(rest,m,mT,mark,colummarks,ass1,ass2,mapEqnIncRow,mapIncRowEqn,inSubsets,eqns);
6469 else
6470 then
6471 fail();
6472 end match;
6473 end getEqnsforIndexReductionphase;
6474
6475 protected function getEqnsforIndexReductiontraverseRows
6476 "author: Frenkel TUD 2012-04"
6477 input list<Integer> rows;
6478 input list<Integer> nextColums;
6479 input BackendDAE.AdjacencyMatrix m;
6480 input BackendDAE.AdjacencyMatrixT mT;
6481 input Integer mark;
6482 input array<Integer> colummarks;
6483 input array<Integer> ass1 "eqn := ass1[var]";
6484 input array<Integer> ass2 "var := ass2[eqn]";
6485 input array<list<Integer>> mapEqnIncRow "eqn indx -> skalar Eqn indexes";
6486 input array<Integer> mapIncRowEqn "scalar eqn index -> eqn indx";
6487 input array<list<Integer>> inSubsets;
6488 input list<Integer> inEqns;
6489 output list<Integer> outEqns;
6490 algorithm
6491 outEqns:=
6492 match (rows, nextColums)
6493 local
6494 list<Integer> rest,queue,nextqueue,eqns;
6495 Integer rc,r,e;
6496 case ({}, {}) then inEqns;
6497 case ({}, _)
6498 2866 then
6499 getEqnsforIndexReductionphase(nextColums,m,mT,mark,colummarks,ass1,ass2,mapEqnIncRow,mapIncRowEqn,inSubsets,inEqns);
6500 case (r::rest, _)
6501 algorithm
6502 // row is matched
6503 // print("check Row " + intString(r) + "\n");
6504 13785 rc := ass2[r];
6505 // print("check Colum " + intString(rc) + "\n");
6506
5/6
✓ Branch 2 taken 13666 times.
✓ Branch 3 taken 119 times.
✓ Branch 4 taken 13666 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5519 times.
✓ Branch 8 taken 8147 times.
13785 if List.exist1(mT[r],intEq,rc) and intGt(rc,0) and not intEq(colummarks[rc],mark) then
6507
2/2
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 4823 times.
5519 if intGt(colummarks[rc],0) then
6508 696 mergeSubsets(mark,colummarks[rc],inSubsets,colummarks);
6509 nextqueue := nextColums;
6510 queue := inEqns;
6511 else
6512 // if it is a multi dim equation take all scalare equations
6513 4823 e := mapIncRowEqn[rc];
6514 4823 eqns := mapEqnIncRow[e];
6515 4823 List.fold1r(eqns,arrayUpdate,mark,colummarks);
6516 // print("add to nextQueue and Queue " + stringDelimitList(List.map(eqns,intString),", ") + "\n");
6517 4823 nextqueue := listAppend(nextColums,eqns);
6518 4823 queue := listAppend(inEqns,eqns);
6519 //(nextqueue,queue) = getEqnsforIndexReductiontraverseColums(mT[r],colummarks,ass1,rc::nextColums,rc::inEqns);
6520 end if;
6521 else
6522 nextqueue := nextColums;
6523 queue := inEqns;
6524 end if;
6525 13785 then
6526 getEqnsforIndexReductiontraverseRows(rest,nextqueue,m,mT,mark,colummarks,ass1,ass2,mapEqnIncRow,mapIncRowEqn,inSubsets,queue);
6527 end match;
6528 end getEqnsforIndexReductiontraverseRows;
6529
6530 protected function mergeSubsets
6531 input Integer mark;
6532 input Integer markColum;
6533 input array<list<Integer>> inSubsets;
6534 input array<Integer> colummarks;
6535 protected
6536 list<Integer> eqns;
6537 algorithm
6538 696 eqns := inSubsets[markColum];
6539 696 Array.appendToElement(mark,eqns,inSubsets);
6540 696 arrayUpdate(inSubsets,markColum,{});
6541 696 List.fold1r(eqns,arrayUpdate,mark,colummarks);
6542 end mergeSubsets;
6543
6544 protected function reduceIndexifNecessary
6545 "function: reduceIndexifNecessary, calls sssHandler if system need index reduction
6546 author: Frenkel TUD 2012-04"
6547 input list<Integer> meqns "Marked Equations for Index Reduction";
6548 input Integer actualEqn;
6549 input BackendDAE.EqSystem isyst;
6550 input BackendDAE.Shared ishared;
6551 input Integer nv;
6552 input Integer ne;
6553 input array<Integer> ass1 "eqn := ass1[var]";
6554 input array<Integer> ass2 "var := ass2[eqn]";
6555 input BackendDAE.MatchingOptions inMatchingOptions;
6556 input BackendDAEFunc.StructurallySingularSystemHandlerFunc sssHandler;
6557 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
6558 output list<Integer> outchangedEqns;
6559 output Integer continueEqn;
6560 output BackendDAE.EqSystem osyst;
6561 output BackendDAE.Shared oshared;
6562 output Integer nvars;
6563 output Integer neqns;
6564 output array<Integer> outAss1;
6565 output array<Integer> outAss2;
6566 output BackendDAE.StructurallySingularSystemHandlerArg outArg;
6567 algorithm
6568 (outchangedEqns,continueEqn,osyst,oshared,nvars,neqns,outAss1,outAss2,outArg):=
6569 match (meqns, inMatchingOptions)
6570 local
6571 Integer nv_1,ne_1,i_1;
6572 BackendDAE.StructurallySingularSystemHandlerArg arg;
6573 BackendDAE.EqSystem syst;
6574 BackendDAE.Shared shared;
6575 array<Integer> ass1_1,ass1_2,ass2_1,ass2_2;
6576 list<Integer> changedEqns;
6577
6578 case ({}, _)
6579 ✗ then
6580 ({},actualEqn+1,isyst,ishared,nv,ne,ass1,ass2,inArg);
6581 case (_::_, (BackendDAE.INDEX_REDUCTION(),_))
6582 algorithm
6583 ✗ (changedEqns,i_1,syst,shared,ass2_1,ass1_1,arg) := sssHandler({meqns},actualEqn,isyst,ishared,ass2,ass1,inArg);
6584 ✗ ne_1 := BackendDAEUtil.systemSize(syst);
6585 ✗ nv_1 := BackendVariable.daenumVariables(syst);
6586 ✗ ass1_2 := assignmentsArrayExpand(ass1_1,ne_1,arrayLength(ass1_1),-1);
6587 ✗ ass2_2 := assignmentsArrayExpand(ass2_1,nv_1,arrayLength(ass2_1),-1);
6588 then
6589 (changedEqns,i_1,syst,shared,nv_1,ne_1,ass1_2,ass2_2,arg);
6590 case (_, _)
6591 algorithm
6592 ✗ singularSystemError({meqns},actualEqn,isyst,ishared,ass1,ass2,inArg);
6593 ✗ then
6594 fail();
6595 end match;
6596 end reduceIndexifNecessary;
6597
6598 protected function assignmentsArrayExpand
6599 "function helper for assignmentsArrayExpand
6600 author: Frenkel TUD 2012-04"
6601 input array<Integer> ass;
6602 input Integer needed;
6603 input Integer memsize;
6604 input Integer default;
6605 output array<Integer> outAss;
6606 algorithm
6607 outAss := matchcontinue default
6608 case _
6609 algorithm
6610
1/2
✓ Branch 0 taken 556 times.
✗ Branch 1 not taken.
556 true := intGt(memsize,needed);
6611 then
6612 ass;
6613 case _
6614 algorithm
6615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556 times.
556 false := intGt(memsize,needed);
6616 556 then
6617 Array.expand(needed-memsize, ass, default);
6618 else
6619 algorithm
6620 ✗ Error.addInternalError("function assignmentsArrayExpand failed", sourceInfo());
6621 ✗ then
6622 fail();
6623 end matchcontinue;
6624 end assignmentsArrayExpand;
6625
6626 protected function assignmentsArrayBooleanExpand
6627 "function helper for assignmentsArrayExpand
6628 author: Frenkel TUD 2012-04"
6629 input array<Boolean> ass;
6630 input Integer needed;
6631 input Integer memsize;
6632 input Boolean default;
6633 output array<Boolean> outAss;
6634 algorithm
6635 outAss := matchcontinue default
6636 case _
6637 algorithm
6638 ✗ true := intGt(memsize,needed);
6639 then
6640 ass;
6641 case _
6642 algorithm
6643 ✗ false := intGt(memsize,needed);
6644 ✗ then
6645 Array.expand(needed-memsize, ass, default);
6646 else
6647 algorithm
6648 ✗ Error.addInternalError("function assignmentsArrayExpand failed", sourceInfo());
6649 ✗ then
6650 fail();
6651 end matchcontinue;
6652 end assignmentsArrayBooleanExpand;
6653
6654 protected function checkAssignment
6655 "author: Frenkel TUD 2012-06
6656 Check if the assignment is complet/maximum,
6657 returns all unmatched equations"
6658 input Integer indx;
6659 input Integer ne;
6660 input array<Integer> ass1 "eqn := ass1[var]";
6661 input array<Integer> ass2 "var := ass2[eqn]";
6662 input list<Integer> inUnassigned;
6663 output list<Integer> outUnassigned;
6664 protected
6665 list<Integer> unassigned;
6666 algorithm
6667 ✗ if intGt(indx,ne) then
6668 outUnassigned := inUnassigned;
6669 else
6670 ✗ unassigned := List.consOnTrue(intLt(ass1[indx],0), indx, inUnassigned);
6671 ✗ outUnassigned := checkAssignment(indx+1,ne,ass1,ass2,unassigned);
6672 end if;
6673 end checkAssignment;
6674
6675 protected function getAssignment
6676 input Boolean clearMatching;
6677 input Integer nVars;
6678 input Integer nEqns;
6679 input BackendDAE.EqSystem iSyst;
6680 output array<Integer> ass1 "ass[eqnindx]=varindx";
6681 output array<Integer> ass2 "ass[varindx]=eqnindx";
6682 algorithm
6683 (ass1,ass2) := match(clearMatching, iSyst)
6684 case(false, BackendDAE.EQSYSTEM(matching=BackendDAE.MATCHING(ass1=ass1,ass2=ass2))) guard intGe(nVars,arrayLength(ass1)) and intGe(nEqns,arrayLength(ass2))
6685 then
6686 (ass2,ass1);
6687 else
6688 algorithm
6689 59694 ass2 := arrayCreate(nEqns,-1);
6690 59694 ass1 := arrayCreate(nVars,-1);
6691 then
6692 (ass2,ass1);
6693 end match;
6694 end getAssignment;
6695
6696 // =============================================================================
6697 // tests
6698 //
6699 // =============================================================================
6700
6701 public function testMatchingAlgorithms
6702 "function testMatchingAlgorithms, test all matching algorithms
6703 author: Frenkel TUD 2012-03"
6704 input BackendDAE.EqSystem isyst;
6705 input BackendDAE.Shared ishared;
6706 input BackendDAE.MatchingOptions inMatchingOptions;
6707 protected
6708 Real t;
6709 Integer nv,ne,cheapID;
6710 array<list<Integer>> m;
6711 array<Integer> vec1,vec2;
6712 list<tuple<String,BackendDAEFunc.matchingAlgorithmFunc>> matchingAlgorithms;
6713 list<tuple<String,Integer>> extmatchingAlgorithms;
6714 BackendDAE.EqSystem syst;
6715 algorithm
6716 ✗ ne := BackendDAEUtil.systemSize(isyst);
6717 ✗ nv := BackendVariable.daenumVariables(isyst);
6718 ✗ print("Systemsize: " + intString(ne) + "\n");
6719 ✗ matchingAlgorithms := {("OMCNew: ",DFSLH),
6720 ("BFSB: ",BFSB),
6721 ("DFSB: ",DFSB),
6722 ("MC21A: ",MC21A),
6723 ("PF: ",PF),
6724 ("PFPlus: ",PFPlus),
6725 ("HK: ",HK),
6726 ("HKDW: ",HKDW),
6727 ("ABMP: ",ABMP),
6728 ("PR: ",PR_FIFO_FAIR)};
6729 ✗ syst := randSortSystem(isyst,ishared);
6730 ✗ testMatchingAlgorithms1(matchingAlgorithms,syst,ishared,inMatchingOptions);
6731
6732 ✗ System.realtimeTick(ClockIndexes.RT_PROFILER0);
6733 ✗ (_,m,_) := BackendDAEUtil.getAdjacencyMatrixfromOption(syst,BackendDAE.NORMAL(),NONE(),BackendDAEUtil.isInitializationDAE(ishared));
6734 ✗ matchingExternalsetAdjacencyMatrix(nv,ne,m);
6735 cheapID := 3;
6736 ✗ t := System.realtimeTock(ClockIndexes.RT_PROFILER0);
6737 ✗ print("SetMEXT: " + realString(t) + "\n");
6738 extmatchingAlgorithms := {("DFSEXT: ",1),
6739 ("BFSEXT: ",2),
6740 ("MC21AEXT: ",3),
6741 ("PFEXT: ",4),
6742 ("PFPlusEXT:",5),
6743 ("HKEXT: ",6),
6744 ("HKDWEXT ",7),
6745 ("ABMPEXT ",8),
6746 ("PREXT: ",10)};
6747 ✗ testExternMatchingAlgorithms1(extmatchingAlgorithms,cheapID,nv,ne);
6748 ✗ System.realtimeTick(ClockIndexes.RT_PROFILER0);
6749 ✗ vec1 := arrayCreate(ne,-1);
6750 ✗ vec2 := arrayCreate(nv,-1);
6751 ✗ BackendDAEEXT.getAssignment(vec1,vec2);
6752 ✗ print("GetAssEXT: " + realString(t) + "\n");
6753 ✗ System.realtimeTick(ClockIndexes.RT_PROFILER0);
6754 //unassigned := checkAssignment(1,ne,vec1,vec2,{});
6755 //print("Unnasigned: " + intString(listLength(unassigned)) + "\n");
6756 //print("Unassigned:\n");
6757 //BackendDump.debuglst((unassigned,intString,"\n","\n"));
6758 //BackendDump.dumpMatching(vec1);
6759 end testMatchingAlgorithms;
6760
6761 public function testMatchingAlgorithms1
6762 "function testMatchingAlgorithms1, helper for testMatchingAlgorithms
6763 author: Frenkel TUD 2012-04"
6764 input list<tuple<String,BackendDAEFunc.matchingAlgorithmFunc>> matchingAlgorithms;
6765 input BackendDAE.EqSystem isyst;
6766 input BackendDAE.Shared ishared;
6767 input BackendDAE.MatchingOptions inMatchingOptions;
6768 algorithm
6769 () :=
6770 matchcontinue matchingAlgorithms
6771 local
6772 list<tuple<String,BackendDAEFunc.matchingAlgorithmFunc>> rest;
6773 String str;
6774 BackendDAEFunc.matchingAlgorithmFunc matchingAlgorithm;
6775 Real t;
6776 case {}
6777 then ();
6778 case (str,matchingAlgorithm)::rest
6779 algorithm
6780 ✗ System.realtimeTick(ClockIndexes.RT_PROFILER0);
6781 ✗ testMatchingAlgorithm(10,matchingAlgorithm,isyst,ishared,inMatchingOptions);
6782 ✗ t := System.realtimeTock(ClockIndexes.RT_PROFILER0);
6783 ✗ print(str + realString(realDiv(t,10.0)) + "\n");
6784 ✗ testMatchingAlgorithms1(rest,isyst,ishared,inMatchingOptions);
6785 then
6786 ();
6787 case (str,_)::rest
6788 algorithm
6789 ✗ print(str + "failed!\n");
6790 ✗ testMatchingAlgorithms1(rest,isyst,ishared,inMatchingOptions);
6791 then
6792 ();
6793 end matchcontinue;
6794 end testMatchingAlgorithms1;
6795
6796 protected function testMatchingAlgorithm
6797 "function testMatchingAlgorithm, tests a specific matching algorithm
6798 author: Frenkel TUD 2012-04"
6799 input Integer index;
6800 input BackendDAEFunc.matchingAlgorithmFunc matchingAlgorithm;
6801 input BackendDAE.EqSystem isyst;
6802 input BackendDAE.Shared ishared;
6803 input BackendDAE.MatchingOptions inMatchingOptions;
6804 algorithm
6805 () :=
6806 match index
6807 local
6808 BackendDAE.StructurallySingularSystemHandlerArg arg;
6809 case 0
6810 then ();
6811 else
6812 algorithm
6813 ✗ arg := IndexReduction.getStructurallySingularSystemHandlerArg(isyst,ishared,listArray({}),listArray({}));
6814 ✗ matchingAlgorithm(isyst,ishared,true,inMatchingOptions,IndexReduction.pantelidesIndexReduction,arg);
6815 ✗ testMatchingAlgorithm(index-1,matchingAlgorithm,isyst,ishared,inMatchingOptions);
6816 then
6817 ();
6818 end match;
6819 end testMatchingAlgorithm;
6820
6821 public function testExternMatchingAlgorithms1
6822 "function testExternMatchingAlgorithms1, helper for testMatchingAlgorithms
6823 author: Frenkel TUD 2012-04"
6824 input list<tuple<String,Integer>> matchingAlgorithms;
6825 input Integer cheapId;
6826 input Integer nv;
6827 input Integer ne;
6828 protected
6829 String str;
6830 Integer matchingAlgorithm;
6831 Real t;
6832 algorithm
6833 ✗ for alg in matchingAlgorithms loop
6834 ✗ (str,matchingAlgorithm) := alg;
6835 try
6836 ✗ System.realtimeTick(ClockIndexes.RT_PROFILER0);
6837 ✗ testExternMatchingAlgorithm(10,matchingAlgorithm,cheapId,nv,ne);
6838 ✗ t := System.realtimeTock(ClockIndexes.RT_PROFILER0);
6839 ✗ print(str + realString(realDiv(t,10.0)) + "\n");
6840 else
6841 ✗ print(str + "failed!\n");
6842 end try;
6843 end for;
6844 end testExternMatchingAlgorithms1;
6845
6846 public function testExternMatchingAlgorithm
6847 "function testMatchingAlgorithm, tests a specific matching algorithm
6848 author: Frenkel TUD 2012-04"
6849 input Integer index;
6850 input Integer matchingAlgorithm;
6851 input Integer cheapId;
6852 input Integer nv;
6853 input Integer ne;
6854 algorithm
6855 () :=
6856 match index
6857 case 0
6858 then ();
6859 else
6860 algorithm
6861 ✗ BackendDAEEXT.matching(nv,ne,matchingAlgorithm,cheapId,1.0,1);
6862 ✗ testExternMatchingAlgorithm(index-1,matchingAlgorithm,cheapId,nv,ne);
6863 then
6864 ();
6865 end match;
6866 end testExternMatchingAlgorithm;
6867
6868 protected function randSortSystem
6869 "function randSortSystem, resort all equations and variables in random order
6870 author: Frenkel TUD 2012-043"
6871 input BackendDAE.EqSystem isyst;
6872 input BackendDAE.Shared ishared;
6873 output BackendDAE.EqSystem osyst;
6874 algorithm
6875 osyst := match isyst
6876 local
6877 Integer ne, nv;
6878 array<Integer> randarr, randarr1;
6879 BackendDAE.Variables vars;
6880 BackendDAE.EquationArray eqns;
6881 BackendDAE.EqSystem syst;
6882
6883 case syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqns)
6884 algorithm
6885 ✗ ne := BackendDAEUtil.systemSize(isyst);
6886 ✗ nv := BackendVariable.daenumVariables(isyst);
6887 ✗ randarr := Array.createIntRange(ne);
6888 ✗ setrandArray(ne, randarr);
6889 ✗ randarr1 := Array.createIntRange(nv);
6890 ✗ setrandArray(nv, randarr1);
6891 ✗ syst.orderedEqs := randSortSystem1( ne, 0, randarr, eqns, BackendEquation.listEquation({}),
6892 BackendEquation.get, BackendEquation.add );
6893 ✗ syst.orderedVars := randSortSystem1( nv, 0, randarr1, vars, BackendVariable.emptyVars(),
6894 BackendVariable.getVarAt, BackendVariable.addVar );
6895 ✗ (syst, _, _) := BackendDAEUtil.getAdjacencyMatrix( BackendDAEUtil.clearEqSyst(syst), BackendDAE.NORMAL(), NONE(), BackendDAEUtil.isInitializationDAE(ishared));
6896 then
6897 syst;
6898 end match;
6899 end randSortSystem;
6900
6901 protected function randSortSystem1
6902 input Integer index;
6903 input Integer offset "obsolete";
6904 input array<Integer> randarr;
6905 input Type_a oldTypeA;
6906 input Type_a newTypeA;
6907 input getFunc get;
6908 input setFunc set;
6909 output Type_a outTypeA;
6910 replaceable type Type_a subtypeof Any;
6911 replaceable type Type_b subtypeof Any;
6912 partial function getFunc
6913 input Type_a inTypeA;
6914 input Integer inInteger;
6915 output Type_b outTypeB;
6916 end getFunc;
6917 partial function setFunc
6918 input Type_b inTypeB;
6919 input Type_a inTypeA;
6920 output Type_a outTypeA;
6921 end setFunc;
6922 algorithm
6923 outTypeA := match index
6924 local
6925 Type_b tb;
6926 Type_a ta;
6927 case 0
6928 then newTypeA;
6929 else
6930 algorithm
6931 ✗ tb := get(oldTypeA,randarr[index]+offset);
6932 ✗ ta := set(tb,newTypeA);
6933 ✗ then
6934 randSortSystem1(index-1,offset,randarr,oldTypeA,ta,get,set);
6935 end match;
6936 end randSortSystem1;
6937
6938
6939 protected function singularSystemError
6940 input list<list<Integer>> eqns;
6941 input Integer actualEqn;
6942 input BackendDAE.EqSystem isyst;
6943 input BackendDAE.Shared ishared;
6944 input array<Integer> inAssignments1;
6945 input array<Integer> inAssignments2;
6946 input BackendDAE.StructurallySingularSystemHandlerArg inArg;
6947 protected
6948 Integer n;
6949 list<Integer> unmatched,unmatched1,vars;
6950 String eqn_str,var_str;
6951 DAE.ElementSource source;
6952 SourceInfo info;
6953 array<Integer> mapIncRowEqn;
6954 algorithm
6955 ✗ (_,_,_,mapIncRowEqn,_) := inArg;
6956 ✗ n := BackendDAEUtil.systemSize(isyst);
6957 // for debugging
6958 /* BackendDump.printEqSystem(isyst);
6959 BackendDump.dumpMatching(inAssignments1);
6960 BackendDump.dumpMatching(inAssignments2);
6961 syst := BackendDAEUtil.setEqSystMatching(isyst, BackendDAE.MATCHING(inAssignments1,inAssignments2,{}));
6962 DumpGraphML.dumpSystem(syst,ishared,NONE(),"SingularSystem" + intString(n) + ".graphml",false);
6963 */
6964 // get from scalar eqns indexes the indexes in the equation array
6965 ✗ unmatched := List.flatten(eqns);
6966 ✗ unmatched1 := List.map1r(unmatched,arrayGet,mapIncRowEqn);
6967 ✗ unmatched1 := List.uniqueIntN(unmatched1,arrayLength(mapIncRowEqn));
6968 ✗ eqn_str := BackendDump.dumpMarkedEqns(isyst, unmatched1);
6969 ✗ vars := getUnassigned(n, inAssignments2, {});
6970 ✗ vars := List.fold1(unmatched,getAssignedVars,inAssignments1,vars);
6971 ✗ var_str := BackendDump.dumpMarkedVars(isyst, vars);
6972 ✗ source := BackendEquation.markedEquationSource(isyst, listHead(unmatched1));
6973 ✗ info := ElementSource.getElementSourceFileInfo(source);
6974 ✗ Error.addSourceMessage(Error.STRUCT_SINGULAR_SYSTEM, {eqn_str,var_str}, info);
6975 end singularSystemError;
6976
6977 protected function getAssignedVars
6978 input Integer e;
6979 input array<Integer> ass;
6980 input list<Integer> iAcc;
6981 output list<Integer> oAcc;
6982 protected
6983 Integer i;
6984 Boolean b;
6985 algorithm
6986 ✗ i := ass[e];
6987 ✗ b := intGt(i,0);
6988 ✗ oAcc := List.consOnTrue(b,i,iAcc);
6989 end getAssignedVars;
6990
6991 protected function clearArrayWithKnownSetIndexes "Sets elements of arr in arrIx[1:n] to false; if n>0.3*size(arr), clear all of them"
6992 input array<Boolean> arr;
6993 input array<Integer> arrIx;
6994 input Integer n;
6995 protected
6996 constant Boolean debug = false;
6997 algorithm
6998 ✗ if n>0.3*arrayLength(arr) then
6999 ✗ for i in 1:arrayLength(arr) loop
7000 Dangerous.arrayUpdateNoBoundsChecking(arr, i, false);
7001 end for;
7002 else
7003 ✗ true := n <= arrayLength(arrIx);
7004 ✗ for i in 1:n loop
7005 ✗ arrayUpdate(arr, Dangerous.arrayGetNoBoundsChecking(arrIx, i), false);
7006 end for;
7007 end if;
7008 if debug then
7009 for e in 1:arrayLength(arr) loop
7010 Error.assertion(not arrayGet(arr,e), "clearArrayWithKnownSetIndexes failed: " + String(e) + " n=" + String(n)+" ixs="+stringDelimitList(list(String(arrayGet(arrIx,i)) for i in 1:n),","), sourceInfo());
7011 end for;
7012 end if;
7013 end clearArrayWithKnownSetIndexes;
7014
7015 annotation(__OpenModelica_Interface="backend");
7016 end Matching;
7017