Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 86.8% 46 / 0 / 53
Functions: -% 0 / 1 / 1
Branches: 73.9% 34 / 0 / 46

OMCompiler/Compiler/Util/SBSet.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 uniontype SBSet
37 import SBAtomicSet;
38 import UnorderedSet;
39
40 protected
41 import Array;
42 import List;
43 import Vector;
44
45 public
46 record SET
47 UnorderedSet<SBAtomicSet> asets;
48 Integer ndim;
49 end SET;
50
51 function new
52 input UnorderedSet<SBAtomicSet> ss;
53 output SBSet set;
54 protected
55 Integer dim;
56
57 function is_equal_dim
58 input SBAtomicSet set1;
59 input Integer dim;
60 output Boolean equal = SBAtomicSet.ndim(set1) == dim;
61 end is_equal_dim;
62 algorithm
63
2/2
✓ Branch 1 taken 1773 times.
✓ Branch 2 taken 4148 times.
5921 if not UnorderedSet.isEmpty(ss) then
64 1773 dim := SBAtomicSet.ndim(UnorderedSet.first(ss));
65
66
2/4
✓ Branch 1 taken 1773 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1773 times.
✗ Branch 6 not taken.
1773 if dim <> 0 and UnorderedSet.all(ss, function is_equal_dim(dim = dim)) then
67 // TODO: Since MetaModelica doesn't have copy semantics this doesn't
68 // copy the elements in the set, only the set itself. That might
69 // cause some issues if they're changed in the input set.
70 1773 set := SET(UnorderedSet.copy(ss), dim);
71 else
72 // Error: Using atomic sets of different sizes.
73 ✗ set := newEmpty();
74 end if;
75 else
76 4148 set := SET(UnorderedSet.copy(ss), 0);
77 end if;
78 end new;
79
80 function newEmpty
81 output SBSet set;
82 algorithm
83 29234 set := SET(UnorderedSet.new(SBAtomicSet.hash, SBAtomicSet.isEqual), 0);
84 end newEmpty;
85
86 function copy
87 input output SBSet set;
88 algorithm
89 58 set.asets := UnorderedSet.copy(set.asets);
90 end copy;
91
92 function ndim
93 input SBSet set;
94 output Integer ndim = set.ndim;
95 end ndim;
96
97 function isEmpty
98 input SBSet set;
99 output Boolean empty = UnorderedSet.isEmpty(set.asets);
100 end isEmpty;
101
102 function isDim
103 input SBSet set;
104 input Integer dim;
105 output Boolean res = set.ndim == dim;
106 end isDim;
107
108 function asets
109 input SBSet set;
110 output UnorderedSet<SBAtomicSet> asets = set.asets;
111 end asets;
112
113 function contains
114 input array<Integer> vals;
115 input SBSet set;
116 output Boolean res;
117 algorithm
118 ✗ res := UnorderedSet.all(set.asets, function SBAtomicSet.contains(vals = vals));
119 end contains;
120
121 function addAtomicSet
122 // TODO: SBSet is semi-mutable, should we make ndim mutable to make it
123 // completely mutable or make a copy of the set here?
124 input SBAtomicSet aset;
125 input output SBSet set;
126 algorithm
127
2/2
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 5505 times.
5798 if SBAtomicSet.isEmpty(aset) then
128 293 return;
129 end if;
130
131
2/2
✓ Branch 1 taken 5183 times.
✓ Branch 2 taken 322 times.
5505 if UnorderedSet.isEmpty(set.asets) then
132 5183 UnorderedSet.add(aset, set.asets);
133 5183 set.ndim := SBAtomicSet.ndim(aset);
134 elseif SBAtomicSet.ndim(aset) == set.ndim then
135 322 UnorderedSet.add(aset, set.asets);
136 // else
137 // Error: Atomic sets should have the same dimension.
138 end if;
139 end addAtomicSet;
140
141 function addAtomicSets
142 input UnorderedSet<SBAtomicSet> asets;
143 input output SBSet set;
144 algorithm
145 9974 set := UnorderedSet.fold(asets, addAtomicSet, set);
146 end addAtomicSets;
147
148 function intersection
149 input SBSet set1;
150 input SBSet set2;
151 output SBSet outSet;
152 protected
153 SBAtomicSet int_set;
154 UnorderedSet<SBAtomicSet> res;
155 algorithm
156
4/4
✓ Branch 1 taken 7327 times.
✓ Branch 2 taken 6350 times.
✓ Branch 4 taken 1407 times.
✓ Branch 5 taken 5920 times.
13677 if UnorderedSet.isEmpty(set1.asets) or UnorderedSet.isEmpty(set2.asets) then
157 7757 outSet := newEmpty();
158 7757 return;
159 end if;
160
161 5920 res := UnorderedSet.new(SBAtomicSet.hash, SBAtomicSet.isEqual);
162
163
2/2
✓ Branch 2 taken 6220 times.
✓ Branch 3 taken 5920 times.
18060 for as1 in UnorderedSet.toArray(set1.asets) loop
164
2/2
✓ Branch 2 taken 6747 times.
✓ Branch 3 taken 6220 times.
19187 for as2 in UnorderedSet.toArray(set2.asets) loop
165 6747 int_set := SBAtomicSet.intersection(as1, as2);
166
167
2/2
✓ Branch 1 taken 1788 times.
✓ Branch 2 taken 4959 times.
6747 if not SBAtomicSet.isEmpty(int_set) then
168 1788 UnorderedSet.add(int_set, res);
169 end if;
170 end for;
171 end for;
172
173 5920 outSet := new(res);
174 end intersection;
175
176 function complement
177 input SBSet set1;
178 input SBSet set2;
179 output SBSet outSet;
180 protected
181 UnorderedSet<SBAtomicSet> int_res, aux, comp_res;
182 SBSet new_sets;
183 algorithm
184 7920 outSet := newEmpty();
185
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7920 times.
7920 SET(asets = int_res) := intersection(set1, set2);
186
187
2/2
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 7715 times.
7920 if not UnorderedSet.isEmpty(int_res) then
188
2/2
✓ Branch 2 taken 256 times.
✓ Branch 3 taken 205 times.
666 for as1 in UnorderedSet.toArray(set1.asets) loop
189 256 aux := UnorderedSet.new(SBAtomicSet.hash, SBAtomicSet.isEqual);
190 256 UnorderedSet.add(as1, aux);
191
192
2/2
✓ Branch 2 taken 305 times.
✓ Branch 3 taken 256 times.
817 for as2 in UnorderedSet.toArray(int_res) loop
193 305 new_sets := newEmpty();
194
195
2/2
✓ Branch 2 taken 293 times.
✓ Branch 3 taken 305 times.
903 for as3 in UnorderedSet.toArray(aux) loop
196 293 comp_res := SBAtomicSet.complement(as3, as2);
197 293 new_sets := addAtomicSets(comp_res, new_sets);
198 end for;
199
200 305 aux := new_sets.asets;
201 end for;
202
203 256 outSet := addAtomicSets(aux, outSet);
204 end for;
205 else
206 7715 outSet := addAtomicSets(set1.asets, outSet);
207 end if;
208 end complement;
209
210 function union
211 input SBSet set1;
212 input SBSet set2;
213 output SBSet outSet;
214 protected
215 SBSet aux;
216 algorithm
217 7508 outSet := SET(UnorderedSet.copy(set1.asets), set1.ndim);
218 7508 aux := complement(set2, outSet);
219
220
2/2
✓ Branch 1 taken 5821 times.
✓ Branch 2 taken 1687 times.
7508 if not isEmpty(aux) then
221 1687 outSet := addAtomicSets(aux.asets, outSet);
222 end if;
223 end union;
224
225 function card
226 "the name cardinality seems to be reserved and cannot be used inside of the same scope
227 ToDo: rename the others?"
228 input SBSet set;
229 output Integer cardinality = UnorderedSet.fold(set.asets, SBAtomicSet.cardinality, 0);
230 end card;
231
232 function maxCardinality
233 "ToDo kabdelhak: this can be optimized by storing all the cardinalities and update them if a set is changed"
234 input Vector<SBSet> sets;
235 output SBSet maxSet;
236 output Integer index;
237 function maxCardinality_traverse
238 input SBSet set;
239 output Boolean res = false;
240 input output Integer maxCard;
241 protected
242 Integer cardinality = card(set);
243 algorithm
244 ✗ if cardinality > maxCard then
245 res := true;
246 maxCard := cardinality;
247 end if;
248 end maxCardinality_traverse;
249 algorithm
250 try
251 ✗ (SOME(maxSet), index, _) := Vector.findFold(sets, maxCardinality_traverse, 0);
252 else
253 ✗ fail();
254 end try;
255 end maxCardinality;
256
257 function minElem
258 input SBSet set;
259 output array<Integer> res;
260 protected
261 function lessFn
262 input array<Integer> set1;
263 input array<Integer> set2;
264 output Boolean res;
265 algorithm
266 3 res := Array.isLess(set1, set2, intLt);
267 end lessFn;
268
269 list<array<Integer>> min_elems;
270 algorithm
271
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
67 if isEmpty(set) then
272 ✗ res := listArray({});
273 else
274
4/4
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 67 times.
✓ Branch 4 taken 70 times.
✓ Branch 5 taken 67 times.
274 min_elems := list(SBAtomicSet.minElem(e) for e in UnorderedSet.toArray(set.asets));
275 67 res := List.minElement(min_elems, lessFn);
276 end if;
277 end minElem;
278
279 function isEqual
280 input SBSet set1;
281 input SBSet set2;
282 output Boolean equal = UnorderedSet.isEqual(set1.asets, set2.asets);
283 end isEqual;
284
285 function hash
286 input SBSet set;
287 output Integer hash = UnorderedSet.size(set.asets);
288 end hash;
289
290 function toString
291 input SBSet set;
292 output String str;
293 algorithm
294 ✗ str := "{" + UnorderedSet.toString(set.asets, SBAtomicSet.toString, "U") + "}";
295 end toString;
296
297 annotation(__OpenModelica_Interface="util");
298 end SBSet;
299