Defining Derived Sets

To define a derived set, you specify:

the name of the set,
its parent sets,
optionally, its members, and
optionally, any attributes the set members have.

A derived set definition has the following syntax:

setname( parent_set_list) [ / member_list /] [: attribute_list];

The setname is a standard LINGO name you choose to name the set.

The parent_set_list is a list of previously defined sets, separated by commas. Without specifying a member_list element, LINGO constructs all combinations of members from each parent set to create the members of the new derived set. As an example, consider the following sets section:

SETS:

  PRODUCT / A B/;

  MACHINE / M N/;

  WEEK / 1..2/;

  ALLOWED( PRODUCT, MACHINE, WEEK);

ENDSETS

Sets PRODUCT, MACHINE, and WEEK are primitive sets, while ALLOWED is derived from parent sets PRODUCT, MACHINE, and WEEK. Taking all the combinations of members from the three parent sets, we come up with the following members in the ALLOWED set:

ALLOWED Set Membership:

Index

Member

1

(A,M,1)

2

(A,M,2)

3

(A,N,1)

4

(A,N,2)

5

(B,M,1)

6

(B,M,2)

7

(B,N,1)

8

(B,N,2)

The member_list is optional, and is used when you want to limit the set to being some subset of the full set of combinations derived from the parent sets. The member_list may alternatively be specified in a model’s data section (for details on this see Introduction to the Data Section).

If the member_list is omitted, the derived set will consist of all combinations of the members from the parent sets. When a set does not have a member_list and, therefore, contains all possible combinations of members, it is referred to as being a dense set. When a set includes a member_list that limits it to being a subset of its dense form, we say the set is sparse.

A derived set's member_list may be constructed using either:

an explicit member list, or,
a membership filter.

When using the explicit member list method to specify a derived set's member_list, you must explicitly list all the members you want to include in the set. Each listed member must be a member of the dense set formed from all possible combinations of the parent sets. Returning to our small example above, if we had used an explicit member list in the definition of the derived set ALLOWED as follows:

ALLOWED( PRODUCT, MACHINE, WEEK)

/ A M 1, A N 2, B N 1/;

then ALLOWED would not have had the full complement of eight members. Instead, ALLOWED would have consisted of the three member sparse set: (A,M,1), (A,N,2), and (B,N,1).   Note that the commas in the list of set members are optional and were added only for readability purposes.

If you have a large, sparse set, explicitly listing all members can become cumbersome. Fortunately, in many sparse sets, the members all satisfy some condition that differentiates them from the non-members. If you could just specify this condition, you could save yourself a lot of effort. This is exactly how the membership filter method works. Using the membership filter method of defining a derived set's member_list involves specifying a logical condition that each potential set member must satisfy for inclusion in the final set. You can look at the logical condition as a filter to keep out potential members that don't satisfy some criteria.

As an example of a membership filter, suppose you have already defined a set called TRUCKS, and each truck has an attribute called CAPACITY. You would like to derive a subset from TRUCKS that contains only those trucks capable of hauling big loads. You could use an explicit member list, and explicitly enter each of the trucks that can carry heavy loads. However, why do all that work when you can use a membership filter as follows:

HEAVY_DUTY( TRUCKS) | CAPACITY( &1) #GT# 50000:;

We have named the set HEAVY_DUTY and have derived it from the parent set, TRUCKS. The vertical bar character (|) is used to mark the beginning of a membership filter. The membership filter allows only those trucks that have a hauling capacity (CAPACITY( &1)) greater than (#GT#) 50,000 into the HEAVY_DUTY set. The &1 symbol in the filter is known as a set index placeholder. When building a derived set that uses a membership filter, LINGO generates all the combinations of parent set members. Each combination is then "plugged" into the membership condition to see if it passes the test. The first primitive parent set's member is plugged into &1, the second into &2, and so on. In this example, we have only one parent set (TRUCKS), so &2 would not have made sense. The symbol #GT# is a logical operator and means "greater than."

The logical operators recognized by LINGO are:

#EQ#

equal

#NE#

not equal

#GE#

greater-than-or-equal-to

#GT#

greater than

#LT#

less than

#LE#

less-than-or-equal-to

In addition to listing a derived set's members in a model's sets section, derived set members may also be listed in a model's data section.  Some users may prefer this alternative approach in that a set's members are actually input data for the model.  Therefore, listing set members in a model's data section, along with all other data, is a more natural approach that makes a model more readable.  All the various techniques listed above for enumerating a primitive set's members are also valid in a data section, with the exception of the membership filter method.  An example of defining derived set members in a data section follow:

SETS:

  PRODUCT;

  MACHINE;

  WEEK;

  ALLOWED( PRODUCT, MACHINE, WEEK);

ENDSETS

DATA:

  PRODUCT =  P1..P3;

  MACHINE =  M1..M3;

  WEEK    =  W1..W4;

  ALLOWED =

             P1  M1  W1

             P2  M1  W3

             P3  M1  W2

             P3  M3  W4

  ;

ENDDATA

Inputting a Derived Set in a Data Section

For some models, it may be useful to create an empty, or null, derived set.  This is particularly true if you wish to create the set dynamically through the use of the @INSERT function. To do this, add a statement such as the following to a data section: MYDERIVEDSET = ;.  In other words, simply omit the list of set members. For example, suppose in the previous example we wanted the ALLOWED set to be initialized to being null.  We could do this with the following:

SETS:

  PRODUCT;

  MACHINE;

  WEEK;

  ALLOWED( PRODUCT, MACHINE, WEEK);

ENDSETS

DATA:

  PRODUCT =  P1..P3;

  MACHINE =  M1..M3;

  WEEK    =  W1..W4;

  ALLOWED =  ;

ENDDATA

Inputting a Null Derived Set in a Data Section