OMCompiler/Compiler/BackEnd/Coloring.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 Coloring | ||
| 37 | " file: Coloring.mo | ||
| 38 | package: Coloring | ||
| 39 | description: Distance-2 graph coloring of sparsity patterns, used to compress | ||
| 40 | the columns of analytic Jacobians. Operates purely on integer | ||
| 41 | adjacency structures (no backend datatypes), so it is shared by | ||
| 42 | both the old backend (SymbolicJacobian) and the new backend | ||
| 43 | (NBJacobian) without either depending on the other. | ||
| 44 | " | ||
| 45 | |||
| 46 | protected | ||
| 47 | import Array; | ||
| 48 | import ExecStat.execStat; | ||
| 49 | import Error; | ||
| 50 | import Flags; | ||
| 51 | import GCExt; | ||
| 52 | import Graph; | ||
| 53 | import List; | ||
| 54 | |||
| 55 | public function createColoring | ||
| 56 | input array<list<Integer>> sparseArray; | ||
| 57 | input array<list<Integer>> sparseArrayT; | ||
| 58 | input Integer sizeVars; | ||
| 59 | input Integer sizeVarswithDep; | ||
| 60 | output array<list<Integer>> coloredArray; | ||
| 61 | protected | ||
| 62 | constant Boolean debug = false; | ||
| 63 | array<Integer> colored; | ||
| 64 | list<tuple<Integer, list<Integer>>> sparseGraphT; | ||
| 65 | Integer maxColor; | ||
| 66 | algorithm | ||
| 67 | try | ||
| 68 | // build up a bi-partied graph of pattern | ||
| 69 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3058 times.
|
3058 | if Flags.isSet(Flags.DUMP_SPARSE_VERBOSE) then |
| 70 | ✗ | print("analytical Jacobians[SPARSE] -> build sparse graph.\n"); | |
| 71 | end if; | ||
| 72 | 3058 | sparseGraphT := Graph.buildGraph(List.intRange2(1,sizeVars),createBipartiteGraph,sparseArrayT); | |
| 73 | |||
| 74 | // debug dump | ||
| 75 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3058 times.
|
3058 | if Flags.isSet(Flags.DUMP_SPARSE_VERBOSE) then |
| 76 | ✗ | print("sparse graph: \n"); | |
| 77 | ✗ | Graph.printGraphInt(Graph.buildGraph(List.intRange2(1,sizeVarswithDep),createBipartiteGraph,sparseArray)); | |
| 78 | ✗ | print("transposed sparse graph: \n"); | |
| 79 | ✗ | Graph.printGraphInt(sparseGraphT); | |
| 80 | ✗ | print("analytical Jacobians[SPARSE] -> builded graph for coloring.\n"); | |
| 81 | end if; | ||
| 82 | |||
| 83 | // color sparse bipartite graph | ||
| 84 | 3058 | colored := arrayCreate(sizeVars,0); | |
| 85 | if debug then execStat("generateSparsePattern -> coloring start "); end if; | ||
| 86 |
2/2✓ Branch 0 taken 3040 times.
✓ Branch 1 taken 18 times.
|
3058 | if (sizeVars>0) then |
| 87 | 3040 | Graph.partialDistance2colorInt(sparseGraphT, sizeVarswithDep, colored); | |
| 88 | end if; | ||
| 89 | if debug then execStat("generateSparsePattern -> coloring end "); end if; | ||
| 90 | // get max color used | ||
| 91 | 3058 | maxColor := Array.fold(colored, intMax, 0); | |
| 92 | |||
| 93 | // map index of that array into colors | ||
| 94 | 3058 | coloredArray := arrayCreate(maxColor, {}); | |
| 95 | 3058 | mapIndexColors(colored, sizeVars, coloredArray); | |
| 96 | 3058 | GCExt.free(colored); | |
| 97 | |||
| 98 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3058 times.
|
3058 | if Flags.isSet(Flags.DUMP_SPARSE_VERBOSE) then |
| 99 | ✗ | print("Print Coloring Cols: \n"); | |
| 100 | ✗ | dumpColoring(arrayList(coloredArray)); | |
| 101 | end if; | ||
| 102 | else | ||
| 103 | ✗ | Error.addInternalError("function createColoring failed", sourceInfo()); | |
| 104 | ✗ | fail(); | |
| 105 | end try; | ||
| 106 | end createColoring; | ||
| 107 | |||
| 108 | protected function createBipartiteGraph | ||
| 109 | input Integer inNode; | ||
| 110 | input array<list<Integer>> inSparsePattern; | ||
| 111 | output list<Integer> outEdges = {}; | ||
| 112 | algorithm | ||
| 113 |
4/4✓ Branch 0 taken 16239 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 16221 times.
✓ Branch 3 taken 18 times.
|
32496 | if inNode >= 1 and inNode <= arrayLength(inSparsePattern) then |
| 114 | 16221 | outEdges := arrayGet(inSparsePattern,inNode); | |
| 115 | else | ||
| 116 | outEdges := {}; | ||
| 117 | end if; | ||
| 118 | end createBipartiteGraph; | ||
| 119 | |||
| 120 | protected function mapIndexColors | ||
| 121 | input array<Integer> inColors; | ||
| 122 | input Integer inMaxIndex; | ||
| 123 | input array<list<Integer>> inArray; | ||
| 124 | protected | ||
| 125 | Integer index; | ||
| 126 | algorithm | ||
| 127 | try | ||
| 128 |
2/2✓ Branch 0 taken 3040 times.
✓ Branch 1 taken 18 times.
|
19279 | for i in 1:inMaxIndex loop |
| 129 | 16221 | index := arrayGet(inColors, i); | |
| 130 | 32442 | arrayUpdate(inArray, index, i::arrayGet(inArray, index)); | |
| 131 | end for; | ||
| 132 | else | ||
| 133 | ✗ | Error.addInternalError("function mapIndexColors failed", sourceInfo()); | |
| 134 | ✗ | fail(); | |
| 135 | end try; | ||
| 136 | end mapIndexColors; | ||
| 137 | |||
| 138 | protected function dumpColoring | ||
| 139 | "Local equivalent of BackendDump.dumpSparsePattern for the verbose coloring | ||
| 140 | dump. Kept here so this shared package does not depend on the old backend's | ||
| 141 | BackendDump." | ||
| 142 | input list<list<Integer>> pattern; | ||
| 143 | algorithm | ||
| 144 | ✗ | print("Print sparse pattern: " + intString(listLength(pattern)) + "\n"); | |
| 145 | ✗ | for row in pattern loop | |
| 146 | ✗ | print("{" + stringDelimitList(List.map(row, intString), ", ") + "}\n"); | |
| 147 | end for; | ||
| 148 | ✗ | print("\n"); | |
| 149 | end dumpColoring; | ||
| 150 | |||
| 151 | annotation(__OpenModelica_Interface="backend_util"); | ||
| 152 | end Coloring; | ||
| 153 |