Indexing Expressions

Introduction

An indexing expression is an expression that describes a collection of tuples. A tuple is an ordered list of objects, which can contain one object, two (a pair), three (a triplet), four (a quartet), five (a quintet), etc.

In algebraic notation, collection of tuples are indicated by phrases such as this:

\text{for all} i \in I,\ j \in J \text{such that} i \neq j

The collection of tuples indicated by this phrase are all pairs (i, j) where i is a member of set I, j is a member of set J and i is distinct from j. Translating this phrase to AMPL, we get the following indexing expression:

{ i in I, j in J : i != j }

Iterators and Conditions

Any set expression in an indexing expression can be preceded by an iterator of the resulting set. An iterator is basically an object that represents any and all members of a set:

{ i in I, j in J : i != j }

There are two main occasions when we want to use iterators. First, when we want to filter out the tuples of an indexing expression according to a logical condition. Second, when subsequent expressions in the same scope of a given set expression will need to refer to the members of the resulting set of that expression.

In the indexing expression above, the iterators are only needed because we want to filter out the resulting pairs (i,j) such that only pairs where i is different from j are returned. If we wanted all pairs (i,j), we could have ommited the definition of iterators as well as the condition part of the expression.

We also use iterators to refer to the members of the set in subsequent expressions in the same scope, as exemplified below:

{ i in I, k in K[ i ]}

The above expression returns all pairs (i,k) where i is a member of set I and k is a member of set K_i. Although in this example the reference to members of set I occurs inside the indexing expression, it can also occur outside of it, as long as the reference is made in the same scope. This happens in sum expressions, for-loops, display commands and many other contexts.

An iterator only exists within the scope in which it is defined. The end of the scope is usually the end of the statement — ;, after which iterators defined within that statement no longer exist. An exception is for-loops, where iterators defined in the header of the loop exist until the end of the loop — }.

Common Uses of Indexing Expressions

Indexing expressions are used for a variety of different purposes. We highlight five common use cases in this section.

1. Declaration of Model Entity Collections

param cost {E} ;

In declaration statements, indexing expressions are used to declare collections of model entities. We can have collections of any model entity: parameters, sets, variables, objective functions, contraints and more (see Model Entities).

The above example shows a parameter collection declaration. The indexing expression indicates that the collection is indexed over all members os set E, meaning that for every member e of that set we have a cost[e] associated with it.

2. Math Expression Reduction Operators

sum {(i,j) in E : i != 1} cost[i,j] * x[i,j]
\displaystyle \sum_{\substack{(i,j) \in E \\ i \neq 1}} cost_{ij}\ x_{ij}

Math expression reduction operators, such as sum and prod, take an indexing expression that indicates what are the tuples associated with each term of the expression.

In the above example you can see the AMPL expression and the same expression in algebraic notation. The indexing expression implements the part underneath the \sum symbol.

3. For-loops

for {i in 1..10} { # statements }

In for-loops, indexing expressions are used to indicate what are the tuples associated with each iteration of the loop.

The above example shows a loop that will iterate over the set 1..10. The iterator i can be used within the body of the loop. It indicates the set member associated with the current iteration.

4. Iterated Commands

let {(i,j) in E} x[i,j] := x0[i,j];

Some commands, such as let, display, drop and fix, can take an indexing expression that indicates the tuples over which the command will iterate.

In general, iterated commands are shorthands for for-loops with a single statement. For instance, the above example is a more compact version of the following loop:

for {(i,j) in E} { let x[i,j] := x0[i,j]; }

This general rule does not apply to printing commands, whose iterated versions don't produce the exact same result as its equivalent for-loop.

5. Set Expression

set S = {i in I : i in K} ;

Indexing expressions are set defining expressions themselves, and can appear wherever set expressions are required. The set defined by an indexing expression is the set of tuples indicated in it.

In the above example, we are declaring the set S and initializing it with the expression {i in I : i in K}, which returns all the members of set I that are also in set K.

It is often the case that the same result can be achieved in multiple ways in AMPL. The above declaration statement is equivalent to set S = I inter K;. Both set expressions return the intersection between sets I and K.