Blog

# Pipe Signs and Dollar Signs (Expected Changes for 4.97)

• 5 replies
• 169 views

Userlevel 5
+6
• AIMMSian
• 172 replies

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) }`

### 5 replies

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?

Userlevel 3
+3

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.

Userlevel 5
+7

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.

Userlevel 3
+3

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.