What are the performance differences between the alternatives? Clearly, the operator “|” is better than a “for” loop, but is there a performance benefit of using the operator “$” instead of an “if” clause? I suspect that “$” and “if” are simply a matter of taste and, if so, I find using an if clause is much more transparent and leads to fewer misinterpretations. Thus, “$” is best avoided. Is this a correct view?
There is no performance difference between writing either:
- x := a $ b;
- x := if b then a endif;
- x := a onlyif b;
The resulting compiled expression is the same for all three.
So it is indeed a matter of taste which one you prefer. Personally, I think the ‘if’ variant is much too verbose so I have preference for using the $.
However there is a difference between using the ‘if’ expression and the ‘if’ statement. So writing
- if a then x:=b; else x:=0; endif;
Is definitely performing worse than writing it as a single assignment like above.
Good to know the performance difference between an if-then-else expression and statement in mind. Thanks for pointing out.
I agree that choosing between the three different forms of expression is a matter of taste, but my preference is different. I prefer the if-then variant as it makes it easier to explain a model to stakeholders, as stakeholders are often not familiar with AIMMS, but they are familiar with some programming language.
Hi guys,
Thanks for the discussion. I would add another option which we have found to be significant when handling large matrices. This involves a separate assignment statement and an override statement, both of which enable the AIMMS sparcity logic:
x := b;
x | not a := 0;
(though this assumes “not a” already is defined or can be calculated efficiently). Yet another is
empty x;
x | a := b;
Both of these approaches can be much more efficient when managing very-large multi-dimensional arrays.
Now that version 4.97 has been out for some time, it turns out that there is rather strange error where AIMMS suggests to change a $ to a | and when you have done that it asks to change the | to a $.
This usually happens in a constructed set expression like:
{ i $ condition(i) }
If i is an unbounded index then this is indeed a deprecated usage of $ and you should use:
{ i | condition(i) }
The problem with the flipping warnings occurs when i is not an unbound index, as in:
for i do
mySet := { i | condition(i) };
endfor;
Now if this is parsed as a constructed set, then the | is correct, but AIMMS should have given an error because i is already bound by the FOR statement.
If parsed as an enumerated set (that is: a comma separated list of elements between curly braces) then the | should be changed to a $.
So, if you do get in a situation where AIMMS asks to again and again change a $ into a | (and vice versa), please have a look at the statement and check whether you indeed want to re-use the index that is already in the for loop or need to introduce a new index in the set construction.
The warning problem will of course be fixed in a next release, but in the mean time check what you really intended and either write:
for i do
mySet := { i2 | condition(i2) };
endfor;
or:
for i do
mySet := i $ condition(i) ; /* leaving out the curly braces */
endfor;
The latter is how AIMMS did interpret the original statement.