Skip to main content

Beginning on 4.97 AIMMS version, warning and possibly errors will reinforce the differences between the pipe sign (|) and the dollar sign ($)

A new article discusses deeply the historical reasons and the differences, but you can also have a peak of the differences below. 

 

Dollar Sign

The $ is used to impose a condition on a part of an expression as in:

A(i) := B(i) $ C(i);

This is semantically the same as:

A(i) := if C(i) then B(i) else 0 endif;


Pipe Sign

The operator | is used to restrict an index domain. An index domain can be specified at several places in the model:

  • At the left-hand-side of a multi-dimensional assignment:
    A((i,j) | restriction(i,j)) := rhs(i,j)

  • In an iterative operator:
    sum((i,j) | restriction(i,j), term(i,j) )

  • In the index domain attribute of an identifier: 
    Index domain: (i,j) | restriction(i,j)

  • In a for statement: 
    for (i,j) | restriction(i,j) do

        ! some code 

    endfor;

  • In a constructed set expression: 
    MySet := { i | restriction(i) }

    ! or

    MyRelation := { (i,j) | restriction(i,j) }

 

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.

 


Reply


Didn't find what you were looking for? Try searching on our documentation pages:

AIMMS Developer & PRO | AIMMS How-To | AIMMS SC Navigator