Dollar or Pipe Sign?
In the AIMMS Language there is a clear distinction on how to use the operator $ and the operator |. This article illustrates this difference.
Dollar Sign
The $ is used to impose a condition on a part of an expression as in:
1A(i) := B(i) $ C(i);
This is semantically the same as:
1A(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:
1A((i,j) | restriction(i,j)) := rhs(i,j)
In an iterative operator:
1sum((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
forstatement:
1for (i,j) | restriction(i,j) do
2 ! some code
3endfor;
In a constructed set expression:
1MySet := { i | restriction(i) }
2! or
3MyRelation := { (i,j) | restriction(i,j) }
A Relevance Parameter Instead of Many Subsets
The pipe restriction is what makes a common modeling shortcut unnecessary. When a sum should only cover the entities relevant to each element of another set, for example, only the companies serving this particular customer, it is tempting to declare a named subset per customer. A single binary relevance parameter, used as the pipe restriction, scales far better:
sum( i_company | p_companyServesCustomer(i_company, i_customer), <expression> )
p_companyServesCustomer holds 1 for the valid combinations and 0 elsewhere, and the restriction keeps the
sum to exactly those. No subset identifier per element of i_customer needs to be created or maintained.
Note that in tests set membership only; it cannot test a parameter for being non-zero. The restriction
above is the way to express this, not in with a parameter-based condition.
Discussion
However, for historical reasons (mainly because we have supported GAMS language for a long time) this theoretical distinction between the two operators was never imposed by AIMMS,
and you could use $ and | as if they mean the exact same thing. You did not get an error if you used them incorrectly.
In the 4.97 version of AIMMS this has changed. So you now do get a warning when you use $ where a | was expected, and vice versa (and in future versions this will even be an error).
The reason for this is that in older AIMMS versions there has always been an error in how these operators were interpreted and that the interpretation was not consistent.
Let’s Try to Explain:
A very important difference between the two operators is where they appear in the precedence order of operators. Take this example:
1A := B $ C + D;
2! vs.
3A := B | C + D;
According to the precedence rules this should be executed similar to:
1A := (B $ C) + D;
2! vs.
3A := B | (C + D);
However, if you try this in an older AIMMS version you will see that the assignment with the | operator has the exact same result as the assignment with the $ operator.
Of course we could have adapted the Language Reference on this,
and just state there that | and $ are exactly the same, but there is a funny thing with how this precedence rules behave within an index domain specification:
1A((i,j) | B(i,j) + C(i,j) ) := rhs(i,j);
2! vs.
3A((i,j) $ B(i,j) + C(i,j) ) := rhs(i,j);
Both assignments are accepted in older AIMMS versions (and are semantically the same).
In other words, when in an index domain specification both operators behave the same and follow the precedence of the | operator.
When not in an index domain specification, so just somewhere in an expression, the two operators also behave as if they are the same but there they follow the precedence of the $ operator.
Because of this inconsistency and the fact that it has never really behaved as the Language Reference states, the new version of AIMMS is now very strict in where to use which operator.
So, if you have written this in your model:
1for i $ x(i) do
The compiler will now give a warning and suggests to replace the $ by a |.
Similarly, if you have written:
1A := B | C + D;
The compiler will give another warning and suggests to replace the | by a $.
Please note that you should not add parentheses around C + D as well,
because then the statement will not behave the same as before (since, as explained, there was no precedence order difference between | and $).
Certainly for some older models, these new warnings may lead to quite a lot of changes to be made. To assist in that the latest version of AIMMS also has a new feature that can make these improvements semi-automatically.