Aspen SCM‎ > ‎SCM Planning‎ > ‎

6. Families of Sets and the No-match Flag

Need for Families of Sets

One limitation of Aspen SCM Planning’s approach to LP modelling is that the value of each set can only be established once, i.e. there is only a single internal index for each set. This matters because the natural formulation of an LP model often involves having two loops over the same set.

For instance in the transportation problem we referred to the variable xij as the amount of material from source i used at destination j. In practice some sources may also be destinations and we might prefer to have a single set of locations which indexes the x variables twice independently. Aspen SCM Planning does not permit this: we must have distinct sets for each independent subscript of a decision variable or constraint.

In a multi-time-period model we may have decision variables yt as the increment of capacity added in time period t. Then our constraint for time period t will typically be of the form:

ut – Σt' < t yt'  ≤  CAP0        for all t

where ut is the production in time period t and CAP0 is the initial capacity.

This constraint says that the current production must be less than or equal to the initial capacity plus the sum of incremental capacities added in all the preceding time periods. Viewed from the perspective of the columns, the decision variable for the increment of capacity added in time period t must appear in the constraint for each subsequent time period.

When the matrix is generated, GEN loops over the time periods for the yt decision variables. It sets the internal index for the set TIME (or whatever we are calling it). There is no further internal index which can be set for TIME which would allow us to perform an independent loop in order to get entries in the rows for each subsequent time period. We are therefore forced to define another set, say TIM2 (best not to have one name wholly contained in another) which happens to have the same elements as TIME.

We could define the generic column for y indexed by TIME and the generic row by TIM2. But then we would have to define the u variable as indexed by TIM2 as it has the same index as the generic row. So as the non-standard behaviour is associated with the y variable, it seems more natural to define the generic column for the u variables and the generic row as indexed by TIME and the generic column for the y variables as indexed by TIM2.

Where we have more than one set with similar members we could keep them completely separate. But there are occasions when it is useful to be able to tie them together. For instance, in this model we might have another constraint which relates the yt variable directly to the ut variable, e.g. incremental capacity added in a time period must be less than 10% of production in that time period:

yt – 0.1 ut  ≤  0        for all t

Here we would like yt to be indexed by TIME. But it isn’t; it’s indexed by TIM2. We could write the constraint as:

Σt' IFSAMEt't yt' – 0.1 ut  ≤  0        for all t

where IFSAMEt't = 1 if t' = t and 0 otherwise. This would work with independent sets TIME and TIM2.

Families of Sets and the “No-match” Flag

Fortunately, Aspen SCM Planning provides a mechanism to handle relationships in which we want two sets with identical members sometimes to be connected and sometimes to be disconnected. It is through the concept of families of sets.

When you define a set you can specify among its attributes that it is the subset of some other set. Although you can specify any set, whether it is actually a superset of the current one, SCM Planning has some rules which it checks when you run CHECK SUBSET (or CHECK ALL):
  • each element in a set must also be in the set of which it is declared to be a subset;
  • a set cannot be both a subset and a superset.
These rules mean that the universe of sets can be partitioned into families each of which consists of a single parent (superset) together with zero or more children (subsets). In particular, where two (or more) sets have identical members, one can be designated as the parent with the others as subsets. It does not matter which is designated as the parent.

Suppose that the sets TIME and TIM2 from the multi-time-period example are put into the same family, e.g. by declaring TIM2 to be a subset of TIME. Then in implementing the constraint

yt – 0.1 ut  ≤  0        for all t

we do not need to worry that the generic column for yt is indexed by TIM2 when the generic row is indexed by TIME. The fact that TIM2 and TIME are in the same family means that by default when GEN establishes the value of the set TIM2 this also establishes TIME at the same value. In other words, when GEN loops over the set TIM2 and sets its internal index, GEN also sets the internal index of TIME to the same value.

The “no-match” flag * allows this rule to be overridden. In the constraint

ut – Σt' < t yt'  ≤  CAP0        for all t

we want the loop over TIME for the generic row to be independent of the loop over TIM2 for the generic column for yt.

We do this by specifying that the index of the generic row is *TIME rather than TIME. When GEN loops over TIM2 for the yt variables, this does not set the internal index of TIME for the generic row. There is then a separate loop over TIME for the generic row. We need to arrange the coefficient of yt’ in the row for period t so that it is 1 for t' < t (i.e. TIM2 < TIME) and 0 otherwise.

You might wonder what happens with the ut term in this generic row. The generic column for ut has the index TIME while the generic row has the index *TIME. Does this mean that there will be a second loop over TIME for the generic row independent of the loop over TIME for the generic column ut? The answer is “No”: there is only one internal index of the set TIME and this is set when generating the columns so there is no second loop over TIME when generating the rows.

Family Rule

The Family Rule states that

When the value of a set is established for a column or a row, this automatically establishes all other sets in the same family at the same value, except:
  1. for those other sets in the family which separately index the same generic row or column;
  2. for those other sets in the family whose entry in ROWS or COLS is preceded by the No-match marker *.
We have seen how the main rule and Exception 2 work in our discussion of the multi-time-period example.
Exception 1 means that in our transportation example if we declare SOURCE to be a subset of DEST we do not need to use a No-match marker in defining the generic column for our xij variables:


When Exception 1 has been invoked and there are other sets in the same family, it is the value of the final independent set which is adopted by the other sets in the same family. Thus with xij, other sets in the same family as SOURCE and DEST would take the value adopted by DEST.

When a multi-dimensional incidence table is evaluated for a generic column, this establishes the values of all its indexing sets. Some of those sets may index generic rows rather than columns (e.g. in multi-time-period models; see Representing Multiple Terms for a Decision Variable in a Constraint). If those sets are in the same family as sets which index the generic column, there is no need to specify a no-match flag on the generic row as the row index will take its required value based on the column index and the incidence table.

Family Rule with Proper Subsets

Where a set in a family is a proper subset of another over which GEN is looping, it is possible that the Family Rule will require the set to be established at some value which is not in the set. In this case the entry is suppressed. This behaviour is entirely natural and is usually not even noticed.

Suppose that we had a loop over columns for the supply of material from elements of the set SOURCE. We might also have some constraint which applied to destinations. Then where a source was also a destination we would have an entry in the matrix, but there would be no such entry where a source was not a destination.

Where tables have to be evaluated for non-existent members of a set, GEN regards the value as 0 (for numeric tables) or blank (for character tables).

Back                                Next