'if-condition on array of booleans in Modelica
I'm sorry if this is a 'read the manual' question (I did but can't find an answer).
I have an array of Booleans and I want to test if any of them is true.
model TestArray
(...)
Boolean[:] booleanArray;
Real y;
equation
y = if [if any element in booleanArray is true] then ... else ...;
end TestArray;
How can I do this? Thanks, Roel
Solution 1:[1]
There are functions like the ones you are requesting in Modelica.Math.BooleanVectors.
Here you'll find allTrue(Boolean b[:]), anyTrue(Boolean b[:]) and oneTrue(Boolean b[:]).
Solution 2:[2]
This is an interesting question. Frankly, I'm not aware of any built-in capabilities for doing this (although the need for such capabilities is certainly valid).
What we've frequently done in the past is to write utility functions called "any" and "all", that look like this (untested, but you get the idea):
function any
input Boolean vals[:];
output Boolean result;
algorithm
result := max({if i==true then 1 else 0 for i in vals})==1;
end any;
function all
input Boolean vals[:];
output Boolean result;
algorithm
result := min({if i==true then 1 else 0 for i in vals})==1;
end all;
This is similar to what you did but using array comprehensions and then encapsulating that in functions. This allows you to write code like:
if any(conditions) then ... else ...;
Ideally, these functions could be added to the built-in set of "reduction operators" (like min and max), but the language group tends to be somewhat conservative about introducing such operators because they pollute the namespace and create potential collisions with existing code.
Note that things get a bit tricky when using when clauses. With when clauses, there is a vector construction, e.g.
when {cond1, cond2, cond3} then
...
end when;
Which has very useful semantics, but is not 100% analogous to either "any" or "all" as written above. So if you intend to use a vector of conditions in a when clause, then read up on how this is handled (in the specification) or ask a follow-up question on that and I can elaborate more (it is somewhat beyond the scope of this question).
Solution 3:[3]
Section 10.3.4 of Modelica Specification Version 4.3 allows Boolean arrays v as arguments of min(v) and max(v).
If all components of v are true then min(v) gives true, false otherwise.
If all components of v are false then max(v) gives false, true otherwise.
Example model:
model Test
Boolean anyFalseGivesFalse = min( { true, false } );
Boolean allTrueGivesTrue = min( { true, true } );
Boolean allFalseGivesFalse = max( { false, false } );
Boolean anyTrueGivesTrue = max( { false, true } );
end Test;
Solution 4:[4]
Now I found a workaround, but it must be possible to do it much nicer:
model TestArray
(...)
Boolean[:] booleanArray;
Real y;
Real[:] test;
equation
for i in 1:size(booleanArray):
test[i] = if booleanArray[i] then 1 else 0;
end for;
y = if sum(test) > 0 then ... else ...;
end TestArray;
Solution 5:[5]
You could use Modelica.Blocks.Math.BooleanToInteger to convert your Boolean-array to an Integer-array with which you can calculate ...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Peter Sundström |
| Solution 2 | Michael Tiller |
| Solution 3 | Tobias |
| Solution 4 | saroele |
| Solution 5 | ruben baetens |
