### Table of Contents

# Introduction

This chapter deals with the way in which conditional assignments, expressions and equations are made in GAMS. The index operations already described are very powerful, but it is necessary to allow for exceptions of one sort or another. For example, heavy trucks may not be able to use a particular route because of a weak bridge, or some sectors in an economy may not produce exportable products. Exceptions such as these may easily be modeled with a logical condition combined with the dollar operator `'$'`

, a very powerful feature of GAMS introduced in this chapter.

This chapter is organized as follows: We will introduce the general form of the dollar condition first and then we will focus on the various types of logical conditions. Next, we will discuss how dollar conditions are used to build conditional assignments, conditional indexed operations and conditional equations. We will conclude the chapter by showing that in certain cases conditions may be modeled using filtering sets instead of the dollar operator. Programming flow control features such as the if statement, the loop, the while statement, and the for statement are not covered in this chapter. These can be found in the chapter Programming Flow Control Features.

# The Dollar Condition

The dollar operator is one of the most powerful features in GAMS. The general syntax for a conditional expression is:

```
term $ logical_condition
```

Here, `term`

can be a number, a (indexed) symbol, and also a complex expression. The dollar operator may be read as *under the condition that* the following `logical_condition`

evaluates to `TRUE`

(or is unequal 0).

Consider the following simple condition, where `a`

and `b`

are scalars.

if (b > 1.5), then a = 2

This can be written in GAMS using the dollar operator as follows.

```
a $ (b > 1.5) = 2 ;
```

Note that the `term`

is the scalar `a`

and the `logical`

`condition`

is the expression \((b > 1.5)\). If the condition is not satisfied, no assignment is made. To make it clear, this conditional assignment may be read as: '*given that b is greater than 1.5, a equals 2*'.

Logical conditions may take various forms, they are introduced in the next section. Conditional expressions may be used in the context of assignments, indexed operations and equations. These topics are covered in later sections of this chapter.

- Note
- Logical conditions used with the dollar operator cannot contain variables. However, variable attributes are allowed.

# Logical Conditions

Logical conditions are special expressions that evaluate to a value of either `TRUE`

or `FALSE`

. Logical conditions may be numerical expressions and numerical relations, they may refer to set membership and they may also contain acronyms. In the following subsections this is shown in the context of simple conditional assignments with the dollar operator on the left-hand side (compare section Dollar on the Left).

In this section we use many examples to illustrate the concepts that are being introduced. In all these examples `a`

and `b`

are scalars, `s`

, `t`

, `u`

and `v`

are parameters, and `i`

and `j`

are sets.

## Logical Conditions: Numerical Expressions

Numerical expressions may serve as logical conditions: a result of zero is treated as the logical value `FALSE`

and a non-zero result is treated as the logical value `TRUE`

. The following example illustrates this point.

```
b $ (2*a - 4) = 7;
```

Here the numerical expression \((2*a - 4)\) is the logical condition. The numerical expression is zero if `a`

equals 2, and non-zero otherwise. Hence the logical value of the expression is `FALSE`

for \(a=2\) and `TRUE`

for all other values of `a`

. The assignment is only made if the numerical expression evaluates to `TRUE`

, otherwise no assignment is made.

- Attention
- Values of the extended range arithmetic such as
`inf`

are also allowed in logical conditions. If the result of a numerical expression used as a logical condition takes any of these values, the logical value is`TRUE`

, even for e.g.`eps`

, which is numerically 0.

Observe that functions are also allowed in logical conditions. If they evaluate to zero, the logical condition is `FALSE`

, otherwise it is `TRUE`

. Consider the following example:

```
b $ cos(a) = 7;
```

Note that the assignment is only made if the cosine of `a`

does not equal zero.

## Logical Conditions: Numerical Relational Operators

Numerical relational operators compare two numerical expressions and return a logical value. For completeness, all numerical relational operators are listed in Table 1.

**Table 1:** Numerical Relational Operators

Consider the following examples.

```
b $ (a < 0) = 10;
b $ (sqr(a) > a) = 12;
a $ ( sum(i, s(i)) > 0 ) = 7;
t(i) $ (a <> 0) = t(i) + 1;
```

In the first line the logical condition is the relational expression \((a < 0)\). The assignment is only made if this expression is `TRUE`

, that is, if the scalar `a`

is negative. The logical condition in the second line is a bit more complex. It evaluates to `FALSE`

if \(0 \leq a \leq 1\). For all other values of `a`

, it evaluates to `TRUE`

. So the assignment is made for all values of `a`

, except for those values of `a`

that are in the closed interval \([0, 1]\). Note that if \(a = -3\), then the logical condition in the first line will be `TRUE`

, so `b`

will become 10. In addition, the logical condition in the second line will be `TRUE`

, so `b`

will change to 12. The logical condition in the third line evaluates to `TRUE`

if the sum of all values of the parameter `s`

is strictly positive. Then `a`

is assigned the value of 7. The assignment in the last line depends on whether `a`

is non-zero. If `a`

is zero no assignment is made, otherwise all entries of the parameter `t`

are updated.

Note that acronyms may also be used with relational operators to build logical conditions. However, only the equality operator `=`

and inequality operator `<>`

are allowed in the context of acronyms, since they have no numerical values and the other operators would be meaningless. For an example, see section Acronym Usage.

## Logical Conditions: Logical Operators

GAMS offers standard logical operators that may combine two or more logical conditions to build complex logical expressions. For example, if several expressions are required to be `TRUE`

simultaneously, they may be connected with the operator `and`

. The logical operators available in GAMS are listed in Table 2 and Table 3. Another way to construct complex logical conditions is by nesting them. For details, see subsection Nested Dollar Conditions below.

**Table 2:** Logical Operators

The logical values of these operators are summarized in the following truth table.

`x` | `y` | `not x` | `x and y` | `x or y` | `x xor y` | `x imp y` | `x eqv y` |
---|---|---|---|---|---|---|---|

`FALSE` | `FALSE` | `TRUE` | `FALSE` | `FALSE` | `FALSE` | `TRUE` | `TRUE` |

`FALSE` | `TRUE` | `TRUE` | `FALSE` | `TRUE` | `TRUE` | `TRUE` | `FALSE` |

`TRUE` | `FALSE` | `FALSE` | `FALSE` | `TRUE` | `TRUE` | `FALSE` | `FALSE` |

`TRUE` | `TRUE` | `FALSE` | `TRUE` | `TRUE` | `FALSE` | `TRUE` | `TRUE` |

**Table 3:** Truth Table of Logical Operators

The following somewhat artificial examples serve as illustration.

```
Set i / i1*i5 /;
Parameter s(i) / i1 3, i2 5, i4 8 /
t(i) / i1*i4 13 /
u(i) / i2 1 /
v(i) / i1 7, i3 2 /;
u(i) $ (not s(i)) = v(i);
u(i) $ (s(i) and u(i) and t(i)) = s(i);
u(i) $ (s(i) or v(i) or t(i)) = 4;
```

Note that there are three conditional assignments for the parameter `u`

. In the first assignment the logical condition is `(not s(i))`

. This condition holds for all entries of `s`

that are not specified and therefore zero by default: `s('i3')`

and `s('i5')`

. Hence `u('i3')`

and `u('i5')`

are assigned the values of `v('i3')`

and `v('i5')`

respectively. The value of `v('i3')`

is 2 and the value of `v('i5')`

is zero by default. After the first assignment we have `u('i2')=1`

and `u('i3')=2`

, all other values of `u`

are zero. Note that the logical condition failed for `u('i2')`

and therefore its value remained unchanged. The logical condition in the second assignment is `TRUE`

for those labels of the set `i`

that have non-zero entries in the parameters `s`

, `u`

and `t`

simultaneously. This condition holds only for `i2`

. Therefore `u('i2')=s('i2')=5`

and all other values of `u`

remain unchanged, resulting in non-zero values only for `u('i2')`

and `u('i3')`

. The logical condition in the last assignment evaluates to `TRUE`

for all labels of the set `i`

that have at least one non-zero entry in the parameters `s`

, `v`

and `t`

. This holds for all labels except for `i5`

. Therefore `u('i5')`

stays zero and all other values of `u`

are changed to 4. These examples demonstrate the power of the dollar operator combined with logical operators. Even more complex logical conditions are possible; see subsection Mixed Logical Conditions below for details.

## Logical Conditions: Set Membership and Set Functions

Apart from numerical and relational expressions, set membership and functions referencing set elements may be used as a logical condition. Consider the following example as illustration for set membership as logical condition.

```
Set i / i1*i5 /
j(i) / i1*i3 / ;
Parameter s(i) / i1 3, i2 5, i3 11, i4 8, i5 1 /
t(i);
t(i) $ j(i) = s(i) + 3;
```

Note that the set `j`

is a subset of the set `i`

and that the parameter `t`

is declared but not defined. The conditional expression `t(i)$j(i)`

in the last line restricts the assignment to the members of the subset `j`

since only they satisfy the condition `j(i)`

. The values for `t('i4')`

and `t('i5')`

remain unchanged. In this case this means that they are zero (by default). Note that there is an alternative formulation for this type of conditional assignment; for details see subsection Filtering Sets in Assignments below.

- Note
- Only the membership of subsets and dynamic sets may be used as logical conditions.

The use of set membership as a logical condition is an extremely powerful feature of GAMS, see section Conditional Equations below for more examples.

Logical conditions may contain functions that return particular values depending on the position of elements in sets, the size of sets or the comparison of set elements to each other or text strings. These functions are presented in Table 4.

Function | Description and Comments |
---|---|

`sameAs(element1,element2)` or `sameAs("text",element2)` or `sameAs(element1,"text")` | Returns `TRUE` if `element1` is identical to `element2` or `element1` is identical to `text` , and `FALSE` otherwise. |

`diag(element1,element2)` or `diag("text",element2)` or `diag(element1,"text")` | Same as function `sameAs` , but returns numerical value 1 for `TRUE` and 0 for `FALSE` . |

`card(set_name)` | Returns the number of elements in a set. Note that this can also be called with a quoted text and returns the number of characters of that text in that case. For more details, see section The Card Operator. |

`ord(set_name)` | Returns the relative position of an element in a set. Note that `ord` may be used only with one-dimensional, static, ordered sets. For more details, see section The Ord Operator. |

**Table 4:** Functions Referencing Sets

In the following example we have two sets of cities and we want to know how many of them feature in both sets.

```
Set i / Beijing, Calcutta, Mumbai, Sydney, Johannesburg, Cairo /;
Set j / Rome, Paris, Boston, Cairo, Munich, Calcutta, Barcelona /;
Scalar b;
b = sum((i,j)$sameAs(i,j),1);
```

Note that in the assignment statement we sum over both sets and we use the function `sameAs`

to restrict the domain of the indexed operation to those label combinations `(i,j)`

where the function `sameAs`

evaluates as `TRUE`

. Thus only identical elements are counted.

Note that in this example the function `diag`

could have been used with the same result.

The functions `ord`

and `card`

are frequently used to single out the first or last element of an ordered set. For example, we may want to fix a variable for the first and last elements of a set:

```
x.fx(i) $ (ord(i) = 1) = 3;
x.fx(i) $ (ord(i) = card(i)) = 7;
```

In the first assignment the variable `x`

is fixed for the first element of the set `i`

and in the second assignment `x`

is fixed for the final element of `i`

.

- Note
- As an alternative to the formulation above, one could also use the set attributes
`first`

and`last`

to get the same result:`x.fx(i) $ (i.first) = 3; x.fx(i) $ (i.last) = 7;`

## Numerical Values of Logical Conditions

We have seen that logical conditions may take the form of numerical expressions, expressions with relational operators, complex expressions using logical operators, set membership and set functions. However, GAMS does not have a Boolean data type.

- Attention
- GAMS follows the convention that the result of a relational operation is zero if the assertion is
`FALSE`

, and 1 if it is`TRUE`

.

Consider the following example as illustration.

```
x = (1 < 2) + (2 < 3);
```

The expression to the right of the assignment evaluates to 2 since both logical conditions within parentheses are `TRUE`

and therefore assume a value of 1. Note that this is different from the assignment below:

```
x = (1 < 2) or (2 < 3)
```

This assignment evaluates to 1, since both statements to the left and right of `or`

are `TRUE`

and therefore the whole expression is `TRUE`

.

## Mixed Logical Conditions

The building blocks introduced in the subsections above may be combined to generate more complex logical conditions. These may contain standard arithmetic operations, numerical relational operations and logical operations. All operations, their symbols and their order of precedence are given in Table 5. Note that 1 denotes the highest order of precedence and 7 denotes the lowest order of precedence. As usual, the default order of precedence holds only in the absence of parentheses and operators (symbols) on the same level are evaluated from left to right.

Type of Operation | Operation | Operator | Order of precedence |
---|---|---|---|

Standard arithmetic operation | Exponentiation | `**` | 1 |

Standard arithmetic operation | Multiplication, Division | `*, /` | 2 |

Standard arithmetic operation | Unary operators: Plus, Minus | `+, -` | 3 |

Standard arithmetic operation | Binary operators: Addition, Subtraction | `+, -` | 3 |

Numerical Relational operation | All | `<, <=, =, <>, >=, >` | 4 |

Logical operation | Negation | `not` | 5 |

Logical operation | Logical Conjunction | `and` | 6 |

Logical operation | All other logical operations | `or` , `xor` , `imp` , `eqv` | 7 |

**Table 5:** Complete Hierarchy for Operator Precedence in GAMS

- Note
- We recommend to use parentheses rather than relying on the order of precedence of operators. Parentheses prevent errors and make the intention clear.

Consider the following example:

```
x - 5*y and z - 5
(x - (5*y)) and (z-5)
```

These two complex logical conditions are equivalent. However, the parentheses make the second expression easier to understand.

Some simple examples of complex logical conditions, their numerical values and their logical values are given in Table 6.

Logical Condition | Numerical Value | Logical Value |
---|---|---|

`(1 < 2) + (3 < 4)` | 2 | `TRUE` |

`(2 < 1) and (3 < 4)` | 0 | `FALSE` |

`(4*5 - 3) + (10/8)` | 18.25 | `TRUE` |

`(4*5 - 3) or (10 - 8)` | 1 | `TRUE` |

`(4 and 5) + (2*3 <= 6)` | 2 | `TRUE` |

`(4 and 0) + (2*3 < 6)` | 0 | `FALSE` |

**Table 6:** Examples of Complex Logical Conditions

## Nested Dollar Conditions

An alternative way to model complex logical conditions is by nesting them. The syntax is:

```
term $ (logical_condition1$(logical_condition2$(...)))
```

Note that in nested dollar conditions all succeeding expressions after the dollar operator must be enclosed in parentheses. The nested expression is equivalent to the following conditional expression that uses the logical operator `and`

instead of the nesting:

```
term $ (logical_condition1 and logical_condition2 and ...)
```

Consider the following example. Note that `i`

, `j(i)`

and `k(i)`

are sets, and `u(i)`

and `v(i)`

are parameters.

```
u(i) $ (j(i)$k(i)) = v(i) ;
```

The assignment will be made only for those members of the set `i`

that are members of both sets `j`

and `k`

. Note the position of the parentheses in the dollar condition. The assignment statement above can be rewritten in the following way.

```
u(i) $ (j(i) and k(i)) = v(i) ;
```

- Note
- We recommend to use the logical
`and`

operator instead of nesting dollar operators, because this formulation is easier to read.

# Conditional Assignments

A conditional assignment is an assignment statement with a dollar condition on the left-hand side or on the right-hand side. Most examples until now were conditional assignments with the dollar operator on the left.

- Attention
- The effect of the dollar condition is significantly different depending on which side of the assignment it is located.

The next two subsections describe the use of the dollar condition on each side of the assignment. Note that in many cases it may be possible to use either of the two forms of the dollar condition to describe an assignment. We recommend to choose the clearer formulation.

Note that if the logical condition in an assignment statement refers to set membership, then under certain conditions the restriction may be expressed without the use of the dollar operator. For details, see section Filtering Sets in Assignments below.

## Dollar on the Left

If the dollar condition is on the left-hand side of an assignment, an assignment is made only in case the logical condition is satisfied. If the logical condition is not satisfied then no assignment is made and the previous content of the parameter on the left will remain unchanged. In case the parameter on the left-hand side of the assignment has not previously been initialized or assigned any values, zeros will be used for any label for which the assignment was suppressed.

Consider the following example adapted from [CHENERY]. Note that the parameter `sig`

has been previously defined in the model.

```
rho(i) $ (sig(i) <> 0) = (1./sig(i)) - 1. ;
```

In this assignment `rho(i)`

is calculated and the dollar condition on the left protects against dividing by zero. If any of the values associated with the parameter `sig`

turns out to be zero, no assignment is made and the previous values of `rho(i)`

remain. As it happens, `rho(i)`

was not previously initialized, and therefore all the labels for which `sig(i)`

is zero will result in a value of zero.

Now recall the convention that non-zero implies `TRUE`

and zero implies `FALSE`

. The assignment above could therefore be written as:

```
rho(i) $ sig(i) = (1./sig(i)) - 1. ;
```

In the following examples `i`

is a set and `s`

and `t`

are parameters.

```
s(i) $ t(i) = t(i);
s(i) $ ((t(i)-1) > 0) = t(i)**0.5;
```

Note that the first assignment is suppressed if the value of the parameter `t`

equals zero. The second assignment is suppressed for values of the parameter `t`

that are smaller or equal to 1.

- Note
- The first of the last two examples is special in the way that the logical condition used with the dollar on the left and the expression on the right hand side of the assignment are actually the same. This allows to use a shorter notation using the combined
`$=`

assignment. That assignment is equivalent to the following one (which called sparse assignment):`s(i) $= t(i);`

## Sparse Assignments

Sparse assignments will assign a value to the left-hand side of the `=`

sign only if the right-hand side is nonzero. This behavior is triggered using the `$=`

notation as in the following example.

```
Set i /a,b,c/
Parameter d1(i) "Initial data" /a 1, b 1, c 1/
d2(i) "Data to be used to overwrite d1" /a 0, b -2 /
d3(i) "Empty data parameter";
* Initialize d3 to d1
d3(i) = d1(i);
* Use dollar on the left to overwrite d3 with non-zero values from d2
d3(i)$d2(i) = d2(i);
* Result: d3('a')=1; d3('b')=-2; d3('c')=1;
* Re-Initialize d3 to d1
d3(i) = d1(i);
* Use sparse assignment to overwrite d3 with non-zero values from d2
d3(i) $= d2(i);
* Result: d3('a')=1; d3('b')=-2; d3('c')=1;
```

Note that in the final assignments above, the values of the parameter `d3(i)`

are replaced with values from parameter `d2(i)`

only if the entry in `d2(i)`

is non-zero, the other values are left untouched. Both assignments are equivalent.

## Dollar on the Right

If the dollar condition is on the right-hand side of an assignment statement, an assignment will *always* be made. In case the logical condition is not satisfied the value of zero is assigned.

Above we had the following simple conditional assignment:

```
a $ (b > 1.5) = 2;
```

Now we move the dollar condition to the right-hand side:

```
a = 2 $ (b > 1.5) ;
```

This is equivalent to:

```
if (b > 1.5) then (a = 2), else (a = 0)
```

Note that an `if-then-else`

type of construct is implied, but the `else`

operation is predefined and never made explicit. The `else`

could be made explicit with the following formulation:

```
a = 2 $ (b > 1.5) + 0 $ (b <= 1.5) ;
```

The use of this feature is more apparent in instances when an `else`

condition needs to be made explicit. Consider the next example adapted from the fertilizer model [FERTD] . The set `i`

is the set of plants, and we are calculating `mur(i)`

, the cost of transporting imported raw materials. In some cases a barge trip must be followed by a road trip because the plant is not alongside the river and we must combine the separate costs. The assignment is:

```
mur(i) = (1.0 +. 0030*ied(i,'barge')) $ ied(i,'barge')
+ (0.5 + .0144*ied(i,'road' )) $ ied(i,'road' );
```

This means that if the entry in the distance table `ied`

is not zero, then the cost of shipping using that link is added to the total cost. If there is no distance entry, there is no contribution to the cost, presumably because that mode is not used.

Consider another example for a conditional assignment with the dollar operator on the right:

```
b = sum(i,t(i)) $ (a > 0) + 4;
```

Here `a`

and `b`

are scalars, `i`

is a set and `t`

is a parameter. If the scalar `a`

is positive, the scalar `b`

is assigned the sum of all values of the parameter `t`

plus 4. If `a`

is zero or negative, `b`

becomes just 4. Note that the sum is only computed if the condition holds, this potentially makes the program faster.

# Conditional Indexed Operations

We have seen how exceptions in assignments are modeled with dollar conditions. Dollar conditions are also used in indexed operations, where they control the domain of operation. This is conceptually similar to the conditional assignment with the dollar on the left.

Consider the following example adapted from [GTM], a gas trade model for interrelated gas markets. Here the set `i`

contains supply regions and the parameter `supc`

models supply capacities. The scalar `tsupc`

is computed with the following statement:

```
tsupc = sum(i $ (supc(i) <> inf), supc(i)) ;
```

This assignment restricts the sum to the *finite* values of the parameter `supc`

.

In indexed operations the logical condition is often a set. This set is called the *conditional* *set* and assignments are made only for labels that are elements of the conditional set. This concept plays an important role in dynamic sets.

Multi-dimensional sets are introduced in section Multi-Dimensional Sets. In the example used there a two-dimensional set is used to define the mapping between countries and ports. Another typical example for a multi-dimensional set is a set-to-set mapping that defines the relationship between states and regions. This is useful for aggregating data from the state to the regional level. Consider the following example:

```
Sets r "regions" / north, south /
s "states" / florida, texas, vermont, maine /
corr(r,s) / north.(vermont,maine)
south.(florida,texas) /;
Parameter y(r) "income for each region"
income(s) "income of each state"
/ florida 4.5, vermont 4.2
texas 6.4, maine 4.1 / ;
```

The set `corr`

links the states to their respective regions, the parameter `income`

is the income of each state. The parameter `y`

is computed with the following assignment statement:

```
y(r) = sum(s $ corr(r,s), income(s)) ;
```

The conditional set `corr(r,s)`

restricts the domain of the summation: for each region `r`

the summation over the set `s`

is restricted to the label combinations `(r,s)`

that are elements of the set `corr(r,s)`

. Conceptually, this is analogous to the Boolean value `TRUE`

or the arithmetic value `non-zero`

. The effect is that only the contributions of `vermont`

and `maine`

are included in the total for `north`

, and `south`

is the sum of the incomes from only `texas`

and `florida`

.

Note that the summation above can also be written as:

```
y(r) = sum(s,income(s) $ corr(r,s));
```

In this formulation the parameter `income`

is controlled by the conditional set `corr`

instead of the index `s`

. Note that both formulations yield the same result, but the second alternative is more difficult to read.

In the next example the logical condition on the right-hand side appears in the context of an indexed operation, but it does not refer to the index. Thus it is treated similarly to a dollar on the right logical condition. Note that `a`

and `b`

are scalars, `i`

is a set and `s`

is a parameter.

```
b = sum(i $ a, s(i));
```

Here the scalar `b`

is assigned the sum of the values of the parameter `s`

only if `a`

does not equal zero. Otherwise `b`

will be assigned the value zero. Observe that the following alternative formulation will generally be faster than the assignment above:

```
b = sum(i, s(i)) $ a;
```

Note that if the logical condition in the context of indexed operations refers to set membership, then under certain conditions the restriction may be expressed without the use of the dollar operator. For details, see section Filtering Controlling Indices in Indexed Operations below.

# Conditional Equations

The dollar operator is also used for exception handling in equations. The next two subsections discuss the two main uses of dollar operators in the context of equations: in the body of an equation and over the domain of definition.

## Dollar Operators within the Algebra of Equations

A dollar operator in the algebraic formulation of an equation is analogous to the dollar control on the right of assignments, as presented in section Dollar on the Right. Assuming that "the right" means the right of the `'..'`

then the analogy is even closer. As in the context of assignments, an `if-else`

operation is implied. It is used to exclude parts of the definition from some of the generated constraints.

Consider the following example adapted from the production model [CHENERY].

```
Set i "sectors" / light-ind, food+agr, heavy-ind, services /
t(i) "tradables" / light-ind, food+agr, heavy-ind /;
Variables x(i) "quantity of output"
y(i) "final consumption"
e(i) "quantity of exports"
m(i) "quantity of imports";
Equations mb(i) "material balance";
mb(i).. x(i) =g= y(i) + (e(i) - m(i)) $ t(i) ;
```

Note that in the equation definition in the last line, the term `(e(i) - m(i))`

on the right-hand side of the equation is added only for those elements of the set `i`

that also belong to the subset `t(i)`

, so that the element `services`

is excluded.

Further, conditional indexed operations may also feature in expressions in equation definitions. The supply balance equation from the gas trade model [GTM] is an example. Note that the set `i`

contains the supply regions, the set `j`

contains the demand regions, and the two-dimensional set `ij`

is the set of feasible links; the variable `x`

denotes the shipment of natural gas and the variable `s`

denotes the regional supply.

```
sb(i).. sum(j $ ij(i,j), x(i,j)) =l= s(i) ;
```

Similar to the assignment example seen before, the conditional set `ij(i,j)`

restricts the domain of the summation: for each supply region `i`

the summation over the demand regions `j`

is restricted to the label combinations `(i,j)`

that are elements of the set of feasible links `ij(i,j)`

.

## Dollar Control over the Domain of Definition

In case constraints should only be included in the model if particular conditions are met, a dollar condition in the domain of definition of an equation may be used to model this restriction. Such a dollar condition is analogous to the dollar control on the left of assignments. Assuming that "the left" means the left of the symbols `'..'`

then the analogy is even closer.

- Note
- The dollar control over the domain of definition of equations restricts the number of constraints generated to less than the number implied by the domain of the defining sets.

Consider the following example adapted from the Andean fertilizer model [ANDEAN] :

```
gple(w,wp,te) $ ple(w,wp).. yw(w,te) - yw(wp,te) =l= dpack;
```

Here `w`

, `wp`

and `te`

are sets, `ple`

is a two-dimensional parameter, `yw`

is a variable and `dpack`

is a scalar. Note that the dollar condition restricts the first two indices of the domain of the equation to those label combinations that have non-zero entries in the two-dimensional parameter `ple`

.

Sometimes the desired restriction of an equation may be achieved either way: through a condition in the algebra or a condition in the domain of definition. Compare the following two lines, where `eq1`

and `eq2`

are equations, `i`

and `j`

are sets, `b`

is a scalar, `s`

is a parameter and `x`

is a two-dimensional variable.

```
eq1(i) $ b.. sum(j, x(i,j)) =g= -s(i);
eq2(i).. sum(j, x(i,j)) $ b =g= -s(i) $ b;
```

In the first line the dollar condition is in the domain of definition, in the second line the dollar conditions are in the algebraic formulation of the equation. If `b`

is non-zero, the generated equations `eq1`

and `eq2`

will be identical. However, if `b`

is 0, no equation `eq1`

will be generated, but for each `i`

we will see a trivial equation `eq2`

of the form `0 =g= 0;`

.

Note that if the logical condition in the domain of definition of an equation refers to set membership, then under certain conditions the restriction may be expressed without the use of the dollar operator. For details, see section Filtering the Domain of Definition below.

# Filtering Sets

If the logical condition refers to set membership, the restriction modeled with a dollar condition may sometimes be achieved *without* the dollar operator. Consider the following statement, where `i`

and `j(i)`

are sets, and `u`

and `s`

are parameters:

```
u(i) $ j(i) = s(i) ;
```

Note that the assignment is made only for those elements of the set `i`

that are also elements of the subset `j`

. This conditional assignment may be rewritten in a shorter way:

```
u(j) = s(j) ;
```

In this statement the assignment has been filtered through the condition without the dollar operator by using the subset `j`

as the domain for the parameters `u`

and `s`

. This formulation is cleaner and easier to understand. It is particularly useful in the context of multi-dimensional sets (tuples), and it may be used in assignments, indexed operations and the domain of definition of equations.

## Filtering Sets in Assignments

Suppose we want to compute the transportation cost between local collection sites and regional transportation hubs for a fictional parcel delivery service. We define sets for the collection sites and transportation hubs and a two-dimensional set where the collection sites are matched with their respective hubs:

```
Set i "local collection sites" / miami, boston, chicago, houston, phoenix /
j "regional transportation hubs" / newyork, detroit, losangeles, atlanta / ;
Set r(i,j) "regional transportation hub for each local collection site" /
boston .newyork
miami .atlanta
houston .atlanta
chicago .detroit
phoenix .losangeles / ;
Table distance(i,j) "distance in miles"
newyork detroit losangeles atlanta
miami 1327 1387 2737 665
boston 216 699 3052 1068
chicago 843 275 2095 695
houston 1636 1337 1553 814
phoenix 2459 1977 398 1810;
Parameter factor "cost estimate per unit mile"
shipcost(i,j) "cost of transporting parcels from a local collection site to a regional hub per unit" ;
factor = 0.009 ;
shipcost(i,j) $ r(i,j) = factor*distance(i,j) ;
```

The distance between collection sites and transportation hubs is given in the table. The last line is a conditional assignment for the parameter `shipcost`

. This assignment is only made if the label combination `(i,j)`

is an element of the set `r`

. Note that in each instance the indices `i`

and `j`

appear together. Thus the assignment may be simply written as:

```
shipcost(r) = factor*distance(r) ;
```

Note that the assignment is explicitly restricted to the members of the set `r`

; the dollar operator is not necessary. Observe that if the indices `i`

or `j`

appear separately in any assignment, the above simplification cannot be made. For example, consider the case where the shipping cost depends not only on the parameter `factor`

and the distance between collection sites and regional hubs, but also on the congestion at the regional hub. We introduce a new parameter `congestfac`

that models the congestion at each regional hub and is indexed only over the set `j:`

```
Parameter congestfac(j) "congestion factor" /
newyork 1.5
detroit 0.7
losangeles 1.2
atlanta 0.9/ ;
```

The new cost of shipment is computed as follows:

```
shipcost(i,j) $ r(i,j) = factor*congestfac(j)*distance(i,j) ;
```

Note that this conditional assignment *cannot* be reformulated as:

```
shipcost(r) = factor*congestfac(j)*distance(r) ;
```

In the representation above the index `j`

appears on the right-hand side, but not on the left-hand side. GAMS will flag this assignment as an error. However, the following representation will work:

```
shipcost(r(i,j)) = factor*congestfac(j)*distance(r) ;
```

In this formulation the set `r`

is explicitly denoted as a tuple of the sets `i`

and `j`

. The set `j`

may then appear on the right-hand side.

## Filtering Controlling Indices in Indexed Operations

Similarly, the controlling indices in indexed operations may be filtered through the conditional set without the use of the dollar operator. We continue with the shipping cost example from the last subsection. The total cost of shipment is obtained through the equation that follows. We also include the variable definitions for clarity.

```
Variable shipped(i,j), totcost ;
Equation costequ ;
costequ.. totcost =e= sum((i,j) $ r(i,j), shipcost(i,j)*shipped(i,j));
```

Here the variable `shipped`

is the number of parcels shipped from the local collection site `i`

to the regional transportation hub `j`

, and the variable `totcost`

is the total cost of all shipments. Note that she summation in the equation is restricted to the label combinations that are elements of the set `r`

. Alternatively, the equation above may be written as:

```
costequ.. totcost =e= sum(r, shipcost(r)*shipped(r));
```

In this formulation the summation is performed explicitly only over the elements of the set `r`

, no dollar condition is necessary. However, if the expression in the equation included a term dependent only on index `j`

, then we would have to reformulate differently. Suppose the equation included also the congestion factor `congestfac`

that is indexed only over `j:`

```
cost.. totcost =e= sum((i,j) $ r(i,j), factor*congestfac(j)*distance(i,j)*shipped(i,j));
```

In this case the equation needs to be simplified in the following way:

```
cost.. totcost =e= sum(r(i,j), factor*congestfac(j)*distance(r)*shipped(r));
```

Like before, the domain of the indexed operation `sum`

is the set `r`

. But this time the domain of `r`

has to be named explicitly, so that the parameter `congestfac`

which is indexed only over the set `j`

is permitted in the scope of the indexed operation. Note that this reasoning is analogous to the reasoning for filtering sets in assignments in the subsection above.

## Filtering the Domain of Definition

The rules for filtering sets that we have introduced in subsections Filtering Sets in Assignments and Filtering Controlling Indices in Indexed Operations also apply in the context of equation domains. We continue with the parcel transport example introduced above and add a binary variable `bin`

, the parameter `bigM`

and the equation `connect`

to the model. Recall that `shipped(i,j)`

is a variable and `r(i,j)`

is a set.

```
Parameter bigM(i,j) ;
Binary variable bin(i,j) ;
Equation connect(i,j) ;
connect(i,j) $ r(i,j).. shipped(i,j) =l= bigM(i,j)*bin(i,j) ;
```

The dollar condition restricts the domain of definition of the equation `connect`

to those label combinations of the sets `i`

and `j`

that are elements of the set `r`

. The equation relates the continuous variable `shipped(i,j)`

to the binary variable `bin(i,j)`

. Note that each domain in the equation is the index pair `(i,j)`

. So the equation may be simplified as follows:

```
connect(r).. shipped(r) =l= bigM(r)*bin(r) ;
```

In this formulation the domain of the equation is explicitly restricted to the members of the set `r`

, without the use of a dollar condition. Note that if the right-hand side of the equation contained any term that was indexed over `i`

or `j`

separately, then the domain of definition of the equation would have to be simplified as:

```
connect(r(i,j))
```

The reasoning is the same as in the case of assignments and indexed operations.