Difference: SetsInAMPL (1 vs. 15)

Revision 152019-11-10 - MichaelOSullivan

Line: 1 to 1
 
META TOPICPARENT name="AMPLSyntax"
<-- Ready to Review - done - Lauren-->

Sets in AMPL

Line: 221 to 221
  -- MichaelOSullivan - 27 Feb 2008
Changed:
<
<
META FILEATTACHMENT attachment="latexa4ed27399944f27be0955f861782ef5e.png" attr="h" comment="" date="1204112900" name="latexa4ed27399944f27be0955f861782ef5e.png" stream="GLOB(0xa5f5874)" tmpFilename="latexa4ed27399944f27be0955f861782ef5e.png" user="MichaelOSullivan" version="1"
>
>
META FILEATTACHMENT attachment="latex704b4237de4fa37b4ba7c43172873488.png" attr="h" comment="" date="1573418167" name="latex704b4237de4fa37b4ba7c43172873488.png" user="MichaelOSullivan" version="1"

Revision 142010-09-16 - MichaelOSullivan

Line: 1 to 1
 
META TOPICPARENT name="AMPLSyntax"
<-- Ready to Review - done - Lauren-->

Sets in AMPL

Line: 36 to 36
 
  1. Use a logical expression (after the :) to indicate if an element (or pair of elements, or “tuple” of elements) should be included in the set.

Generic Set Expression

Changed:
<
<
{  in , [ in ,  in , …] :   } 
>
>
{ <e> in <S>, [<f> in <T>, <g> in <U>, …] :   <logical expression involving e [f, g, …]>} 
  Set expressions may also involve one or more set operators:
Line: 54 to 54
  Sets are usually defined in a data file:
Changed:
<
<
set NODES := Youngstown Pittsburgh Cincinnati 'Kansas City' Chicago              Albany Houston Tempe Gary ; 
>
>
set NODES := Youngstown Pittsburgh Cincinnati 'Kansas City' Chicago
             Albany Houston Tempe Gary ;
  although they may be defined during declaration using either an explicit set literal or using a set expression:
Changed:
<
<
set KIND := {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'};  set COMPONENT := {C in CLASSES : (kind[C] = 'HOST'  ) or              (kind[C] = 'DEVICE') or              (kind[C] = 'HUB'   ) or              (kind[C] = 'SWITCH')};  set FABRIC := NODE union LINK; 
>
>
set KIND := {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'};
set COMPONENT := {C in CLASSES : (kind[C] = 'HOST'  ) or
                                 (kind[C] = 'DEVICE') or
                                 (kind[C] = 'HUB'   ) or
                                 (kind[C] = 'SWITCH')};
set FABRIC := NODE union LINK;
  and sets may also be defined dynamically:
Changed:
<
<
set SEARCH within VERTICES; let SEARCH := {v in VERTICES: (v, w) in EDGES}; 
>
>
set SEARCH within VERTICES;
let SEARCH := {v in VERTICES: (v, w) in EDGES};
 

Defining 2-Dimensional Sets

There are three different ways to define 2-dimensional sets. The "best" way to use depends on the set.

Changed:
<
<
  1. Using a List You simply list the elements in the set. This is good for sparse sets.

    model; set ARCS within NODES cross NODES; data; set ARCS := (Youngstown, Albany), (Youngstown, Cincinnati), ... ; 
  2. Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
    set ARCS: Cincinnati 'Kansas City' Chicago Albany Houston Tempe Gary := Youngstown + + + + - - - Pittsburgh + + + - - - + Cincinnati - - - + + - - 'Kansas City' - - - - + + - Chicago - - - - - + + ; 
  3. Using an Array You define a list of column indices for each row index. This is a good for sets with a few elements for each row.
    set ARCS := (Youngstown, *) Cincinnati ‘Kansas City’ Chicago Albany (Pittsburgh, *) Cincinnati ‘Kansas City’ Chicago Gary (Cincinnati, *) Albany Houston ... 
>
>
  1. Using a List You simply list the elements in the set. This is good for sparse sets.

       model;
       set ARCS within NODES cross NODES;
       data;
       set ARCS := (Youngstown, Albany), (Youngstown, Cincinnati), ... ;
       
  2. Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
set ARCS:
              Cincinnati 'Kansas City' Chicago Albany Houston Tempe Gary :=
Youngstown    +           +            +       +      -       -     -
Pittsburgh    +           +            +       -      -       -     +
Cincinnati    -           -            -       +      +       -     -
'Kansas City' -           -            -       -      +       +     -
Chicago       -           -            -       -      -       +     +
 ;
  1. Using an Array You define a list of column indices for each row index. This is a good for sets with a few elements for each row.
set ARCS :=
(Youngstown, *) Cincinnati ‘Kansas City’ Chicago Albany
(Pittsburgh, *) Cincinnati ‘Kansas City’ Chicago Gary
(Cincinnati, *) Albany Houston ...
  Return to top
Line: 82 to 117
  AMPL will put the elements in this set in the order they appear in the data file (or let statement). AMPL also understands the following operations for ordered sets:
Changed:
<
<
ord(e, ORD_SET)   # The position of e in ORD_SET first(ORD_SET)    # The first element in ORD_SET last(ORD_SET)     # The last element in ORD_SET prev(e, ORD_SET)  # The element before e in ORD_SET next(e, ORD_SET)  # The element after e in ORD_SET member(i, ORDSET) # The element at position i in ORD_SET 
>
>
ord(e, ORD_SET)   # The position of e in ORD_SET
first(ORD_SET)    # The first element in ORD_SET
last(ORD_SET)     # The last element in ORD_SET
prev(e, ORD_SET)  # The element before e in ORD_SET
next(e, ORD_SET)  # The element after e in ORD_SET
member(i, ORDSET) # The element at position i in ORD_SET
  Return to top
Line: 90 to 132
  Consider the following AMPL statement from the The American Steel Planning Problem. We use ord in the creation of TIME_ARCS:
Changed:
<
<
# The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=    { (m, t) in TIME_NODES, (n, u) in TIME_NODES :      ( ( (m, n) in ARCS) and (t = u) ) or # The transportation arcs      ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The storage arcs 
>
>
# The set of time-staged arcs
set TIME_ARCS within TIME_NODES cross TIME_NODES :=
  { (m, t) in TIME_NODES, (n, u) in TIME_NODES :
    ( ( (m, n) in ARCS) and (t = u) ) or # The transportation arcs
	( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The storage arcs
  There are many concepts within this one statement, let's look at them one at a time.
Line: 99 to 147
 There are many operations we can perform on sets (see Set Expressions). We have seen that cross creates all pairs of two sets, so TIME_NODES cross TIME_NODES creates a set of all pairs of TIME_NODES.

Some set operations may be looped over indexing sets. For example, to generate all the transportation arcs in the time-staged network you could use the following statement:

Changed:
<
<
set TRANSPORT_ARCS := union {t in MONTHS} (union {(m, n) ARCS} {(m, t, n, t)}); 
or you could loop over MONTHS and ARCS simultaneously:
set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)}; 
>
>
set TRANSPORT_ARCS := union {t in MONTHS} (union {(m, n) ARCS} {(m, t, n, t)});
or you could loop over MONTHS and ARCS simultaneously:
set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)};
 

Set Membership and Subsets

Revision 132010-09-13 - MichaelOSullivan

Line: 1 to 1
 
META TOPICPARENT name="AMPLSyntax"
<-- Ready to Review - done - Lauren-->

Sets in AMPL

Line: 20 to 20
 Return to top

Declaring a Set

Changed:
<
<
Sets are declared using the set keyword followed by a label, possibly some attributes and either a set literal or set expression. The most common attribute is set by the within keyword. This specifies that the set will only contain elements from the following set definition:
set ARCS within NODES cross NODES;
# Elements of ARCS must have both elements in NODES

If you need a multi-dimensional set, but don't have the 1-dimensional sets to construct it yet you can use the dimen keyword:

set ROUTES dimen 2;
There are some other set attributes, but we will not use them here.
>
>
Sets are declared using the set keyword followed by a label, possibly some attributes and either a set literal or set expression. The most common attribute is set by the within keyword. This specifies that the set will only contain elements from the following set definition:
set ARCS within NODES cross NODES; # Elements of ARCS must have both elements in NODES 

If you need a multi-dimensional set, but don't have the 1-dimensional sets to construct it yet you can use the dimen keyword:

set ROUTES dimen 2; 
There are some other set attributes, but we will not use them here.
  Set literals can be defined as a list of elements:
Changed:
<
<
{'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'}
or a sequence of numbers:
param start;
param end > start;
param step;
set NUMBERS := start .. end by step;
If the by step is missing, the step is assumed to be 1:
set NUMBERS := 1..5; # NUMBERS = {1, 2, 3, 4, 5}
Note Automatic set generation can only be done in the model environment, in the data environment you must define the set explicitly:
set NUMBERS := 1 2 3 4 5; # NUMBERS = {1, 2, 3, 4 5}
>
>
{'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'} 
or a sequence of numbers:
param start; param end > start; param step; set NUMBERS := start .. end by step; 
If the by step is missing, the step is assumed to be 1:
set NUMBERS := 1..5; # NUMBERS = {1, 2, 3, 4, 5} 
Note Automatic set generation can only be done in the model environment, in the data environment you must define the set explicitly:
set NUMBERS := 1 2 3 4 5; # NUMBERS = {1, 2, 3, 4 5} 
  Return to top
Line: 59 to 36
 
  1. Use a logical expression (after the :) to indicate if an element (or pair of elements, or “tuple” of elements) should be included in the set.

Generic Set Expression

Changed:
<
<
{ <e> in <S>, [<f> in <T>, <g> in <U>, …] :
  <logical expression involving e [f, g, …]>}
>
>
{  in , [ in ,  in , …] :   } 
  Set expressions may also involve one or more set operators:
Line: 80 to 54
  Sets are usually defined in a data file:
Changed:
<
<
set NODES := Youngstown Pittsburgh Cincinnati 'Kansas City' Chicago
             Albany Houston Tempe Gary ;
>
>
set NODES := Youngstown Pittsburgh Cincinnati 'Kansas City' Chicago              Albany Houston Tempe Gary ; 
  although they may be defined during declaration using either an explicit set literal or using a set expression:
Changed:
<
<
set KIND := {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'};

set COMPONENT := {C in CLASSES : (kind[C] = 'HOST'  ) or
				 (kind[C] = 'DEVICE') or
				 (kind[C] = 'HUB'   ) or
				 (kind[C] = 'SWITCH')};

set FABRIC := NODE union LINK;
>
>
set KIND := {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'};  set COMPONENT := {C in CLASSES : (kind[C] = 'HOST'  ) or              (kind[C] = 'DEVICE') or              (kind[C] = 'HUB'   ) or              (kind[C] = 'SWITCH')};  set FABRIC := NODE union LINK; 
  and sets may also be defined dynamically:
Changed:
<
<
set SEARCH within VERTICES;
let SEARCH := {v in VERTICES: (v, w) in EDGES};
>
>
set SEARCH within VERTICES; let SEARCH := {v in VERTICES: (v, w) in EDGES}; 
 

Defining 2-Dimensional Sets

There are three different ways to define 2-dimensional sets. The "best" way to use depends on the set.

Changed:
<
<
  1. Using a List You simply list the elements in the set. This is good for sparse sets.

    model;
    set ARCS within NODES cros NODES;
    
    data;
    
    set ARCS := (Youngstown, Albany), (Youngstown, Cincinnati), ... ;
    
  2. Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
    set ARCS:   Cincinnati 'Kansas City' Chicago Albany Houston Tempe Gary :=
    Youngstown         +          +         +      +       -      -    -
    Pittsburgh         +          +         +      -       -      -    +
    Cincinnati         -          -         -      +       +      -    -
    'Kansas City'      -          -         -      -       +      +    -
    Chicago            -          -         -      -       -      +    + ;
    
  3. Using an Array You define a list of column indices for each row index. This is a good for sets with a few elements for each row.
    set ARCS :=
    (Youngstown, *) Cincinnati ‘Kansas City’ Chicago Albany
    (Pittsburgh, *) Cincinnati ‘Kansas City’ Chicago Gary
    (Cincinnati, *) Albany Houston ...
    
>
>
  1. Using a List You simply list the elements in the set. This is good for sparse sets.

    model; set ARCS within NODES cross NODES; data; set ARCS := (Youngstown, Albany), (Youngstown, Cincinnati), ... ; 
  2. Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
    set ARCS: Cincinnati 'Kansas City' Chicago Albany Houston Tempe Gary := Youngstown + + + + - - - Pittsburgh + + + - - - + Cincinnati - - - + + - - 'Kansas City' - - - - + + - Chicago - - - - - + + ; 
  3. Using an Array You define a list of column indices for each row index. This is a good for sets with a few elements for each row.
    set ARCS := (Youngstown, *) Cincinnati ‘Kansas City’ Chicago Albany (Pittsburgh, *) Cincinnati ‘Kansas City’ Chicago Gary (Cincinnati, *) Albany Houston ... 
  Return to top
Line: 148 to 78
  You can create sets where the elements are ordered using the ordered keyword during definition.
Changed:
<
<
set MONTHS ordered;
>
>
set MONTHS ordered; 
  AMPL will put the elements in this set in the order they appear in the data file (or let statement). AMPL also understands the following operations for ordered sets:
Changed:
<
<
ord(e, ORD_SET)   # The position of e in ORD_SET
first(ORD_SET)    # The first element in ORD_SET
last(ORD_SET)     # The last element in ORD_SET
prev(e, ORD_SET)  # The element before e in ORD_SET
next(e, ORD_SET)  # The element after e in ORD_SET
member(i, ORDSET) # The element at position i in ORD_SET
>
>
ord(e, ORD_SET)   # The position of e in ORD_SET first(ORD_SET)    # The first element in ORD_SET last(ORD_SET)     # The last element in ORD_SET prev(e, ORD_SET)  # The element before e in ORD_SET next(e, ORD_SET)  # The element after e in ORD_SET member(i, ORDSET) # The element at position i in ORD_SET 
  Return to top
Line: 169 to 90
  Consider the following AMPL statement from the The American Steel Planning Problem. We use ord in the creation of TIME_ARCS:
Changed:
<
<
# The set of time-staged arcs
set TIME_ARCS within TIME_NODES cross TIME_NODES :=
   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :
     ( ( (m, n) in ARCS) and (t = u) ) or # The transportation arcs
     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The storage arcs
>
>
# The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=    { (m, t) in TIME_NODES, (n, u) in TIME_NODES :      ( ( (m, n) in ARCS) and (t = u) ) or # The transportation arcs      ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The storage arcs 
  There are many concepts within this one statement, let's look at them one at a time.
Line: 184 to 99
 There are many operations we can perform on sets (see Set Expressions). We have seen that cross creates all pairs of two sets, so TIME_NODES cross TIME_NODES creates a set of all pairs of TIME_NODES.

Some set operations may be looped over indexing sets. For example, to generate all the transportation arcs in the time-staged network you could use the following statement:

Changed:
<
<
set TRANSPORT_ARCS := union {t in MONTHS} (union {(m, n) ARCS} {(m, t, n, t)});
or you could loop over MONTHS and ARCS simultaneously:
set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)};
>
>
set TRANSPORT_ARCS := union {t in MONTHS} (union {(m, n) ARCS} {(m, t, n, t)}); 
or you could loop over MONTHS and ARCS simultaneously:
set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)}; 
 

Set Membership and Subsets

We have seen how to loop over a set using the in keyword. This keyword also provides a logical check if an element is in a set, e.g., (m, n) in ARCS is true if the pair (m, n) is in the set ARCS and false otherwise. We may restrict a set to be a subset of an existing set by using the keyword within, e. g.,

Changed:
<
<
set ARCS within NODES cross NODES;
means each arc is created between two nodes.
>
>
set ARCS within NODES cross NODES; 
means each arc is created between two nodes.
 

Ordered Set Operators

The final condition on TIME_ARCS

Changed:
<
<
    ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )};
creates the "storage" arcs. We could use next(t, MONTHS) = u or t = prev(u, MONTHS) except for a problem when t is June or u is April, respectively. When you use prev or next you must be careful of the first and last members of the set respectively. However, you can use first or last to check if you are using these elements.
>
>
    ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; 
creates the "storage" arcs. We could use next(t, MONTHS) = u or t = prev(u, MONTHS) except for a problem when t is June or u is April, respectively. When you use prev or next you must be careful of the first and last members of the set respectively. However, you can use first or last to check if you are using these elements.
  Return to top

Restricted Sets

When using display or printf statements we saw that we could restrict the members of a set being printed, e.g.,

Changed:
<
<
display {(m, n) in ARCS : Supply[m] > 0}; # Display all arcs from supply nodes
>
>
display {(m, n) in ARCS : Supply[m] > 0}; # Display all arcs from supply nodes 
  We can do this when creating sets, e. g., TIME_NODES, or when using a set as an index for variables, parameters or constraints. For example, rather than setting the upper bound of UnderProduction to be 0 for all non-supply nodes (since non-supply nodes don't produce anything) we could only create this variable for the supply nodes (in fact this may be preferable since there will be less variables).
Changed:
<
<
var UnderProduction {(n, t) in TIME_NODES : Supply[n, t] > 0} >= 0, integer;
>
>
var UnderProduction {(n, t) in TIME_NODES : Supply[n, t] > 0} >= 0, integer; 
  We could make sure this variable is only added to the constraints for the supply nodes (e.g., ConserveFlow constraints) by using a conditional expression.
Changed:
<
<
subject to ConserveFlow {(n, t) in TIME_NODES}:
   sum {(m, s) in TIME_NODES: (m, s, n, t) in TIME_ARCS}
     Shipment[m, s, n, t] + Supply[n, t] -
     if Supply[n, t] > 0 then UnderProduction[n, t] = ... 
>
>
subject to ConserveFlow {(n, t) in TIME_NODES}:    sum {(m, s) in TIME_NODES: (m, s, n, t) in TIME_ARCS}      Shipment[m, s, n, t] + Supply[n, t] -      if Supply[n, t] > 0 then UnderProduction[n, t] = ...  
  Return to top
Line: 238 to 132
  We have already seen different ways of declaring 2-dimensional sets. We have now encountered higher dimensional sets, e.g., TIME_ARCS has 4 dimensions. We generated TIME_ARCS automatically, but we could have specified it using a data file.
Changed:
<
<
set TIME_ARCS within TIME_NODES cross TIME_NODES;
>
>
set TIME_ARCS within TIME_NODES cross TIME_NODES; 
  List
Changed:
<
<
set TIME_ARCS := (Youngstown, April, Albany, April)
                  (Youngstown, April, Youngstown, May) ... ;
>
>
set TIME_ARCS := (Youngstown, April, Albany, April)                   (Youngstown, April, Youngstown, May) ... ; 
  Table
Changed:
<
<
set TIME_ARCS : =
(*, May, *, May)  Cincinnati 'Kansas City' Albany ... :=
Youngstown         +          +            +      ...
Pittsburgh         +          +            -      ...
... ;
>
>
set TIME_ARCS : = (*, May, *, May)  Cincinnati 'Kansas City' Albany ... := Youngstown         +          +            +      ... Pittsburgh         +          +            -      ... ... ; 
  Array
Changed:
<
<
set TIME_ARCS := (*, May, *, May) (Youngstown, Cincinnati) ... ... ;
>
>
set TIME_ARCS := (*, May, *, May) (Youngstown, Cincinnati) ... ... ; 
  or
Changed:
<
<
set TIME_ARCS := (Youngstown, May, *, May) Cincinnati 'Kansas City' ... ... ;
>
>
set TIME_ARCS := (Youngstown, May, *, May) Cincinnati 'Kansas City' ... ... ; 
  Return to top

Efficient Generation of Sets

When creating models, generating sets by looping over all possibilities and removing those that don't fit some conditions (e.g., like the TIME_ARCS statement) can take a long time if there are many possibilities. This is time that could be spent solving the model! If possible you should try to create sets by building them up from smaller building block, rather than by creating an enormous set and pruning it. For example, instead of using this statement

Changed:
<
<
# The set of time-staged arcs
set TIME_ARCS within TIME_NODES cross TIME_NODES :=
   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :
     ( ( (m, n) in ARCS) and (t = u) ) or # The transportation arcs
     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The storage arcs
>
>
# The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=    { (m, t) in TIME_NODES, (n, u) in TIME_NODES :      ( ( (m, n) in ARCS) and (t = u) ) or # The transportation arcs      ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The storage arcs 
  to create TIME_ARCS you could use these statements
Changed:
<
<
set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)};
set STORAGE_ARCS := union {t in MONTHS, (m, n) in ARCS : t <> last(MONTHS)}
   {(m, t, n, next(t, MONTHS)};

set TIME_ARCS within TIME_NODES cross TIME_NODES :=
  TRANSPORT_ARCS union STORAGE_ARCS;
>
>
set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)}; set STORAGE_ARCS := union {t in MONTHS, (m, n) in ARCS : t <> last(MONTHS)}    {(m, t, n, next(t, MONTHS)};  set TIME_ARCS within TIME_NODES cross TIME_NODES :=   TRANSPORT_ARCS union STORAGE_ARCS; 
  Rather than looping over all possibilities and only keeping those that are appropriate, the new statement only loops over smaller sets that can be used to build up the TIME_NODES set efficiently.

Revision 122009-10-09 - MichaelOSullivan

Line: 1 to 1
 
META TOPICPARENT name="AMPLSyntax"
<-- Ready to Review - done - Lauren-->

Sets in AMPL

Line: 152 to 152
 set MONTHS ordered;
Changed:
<
<
AMPL will puts the elements in this set in the order they appear in the data file (or let statement). AMPL also understands the following operations for ordered sets:
>
>
AMPL will put the elements in this set in the order they appear in the data file (or let statement). AMPL also understands the following operations for ordered sets:
 
ord(e, ORD_SET)   # The position of e in ORD_SET

Line: 194 to 194
 

Set Membership and Subsets

Changed:
<
<
We have seen how loop over a set using the in keyword. This keyword also provides a logical check if an element is in a set, e.g., (m, n) in ARCS is true if the pair (m, n) is in the set ARCS and false otherwise. We may restrict a set to be a subset of an existing set by using the keyword {\tt within}, e. g.,
>
>
We have seen how to loop over a set using the in keyword. This keyword also provides a logical check if an element is in a set, e.g., (m, n) in ARCS is true if the pair (m, n) is in the set ARCS and false otherwise. We may restrict a set to be a subset of an existing set by using the keyword within, e. g.,
 
set ARCS within NODES cross NODES;

Revision 112008-04-06 - MichaelOSullivan

Line: 1 to 1
 
META TOPICPARENT name="AMPLSyntax"
<-- Ready to Review - done - Lauren-->

Sets in AMPL

Line: 20 to 20
 Return to top

Declaring a Set

Changed:
<
<
Sets are declared using the set keyword followed by a label, possibly some attributes and either a set literal or set expression. The most common attribute is set by the within keyword. This specifies that the set will only contain elements from the following set definition:
set ARCS within NODES cross NODES; # Elements of ARCS must have both elements in NODES 
If you need a multi-dimensional set, but don't have the 1-dimensional sets to construct it yet you can use the dimen keyword:
set ROUTES dimen 2; 
There are some other set attributes, but we will not use them.
>
>
Sets are declared using the set keyword followed by a label, possibly some attributes and either a set literal or set expression. The most common attribute is set by the within keyword. This specifies that the set will only contain elements from the following set definition:
set ARCS within NODES cross NODES;
# Elements of ARCS must have both elements in NODES

If you need a multi-dimensional set, but don't have the 1-dimensional sets to construct it yet you can use the dimen keyword:

set ROUTES dimen 2;
There are some other set attributes, but we will not use them here.
  Set literals can be defined as a list of elements:
Changed:
<
<
{'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'} 
or a sequence of numbers:
param start; param end > start; param step;  set NUMBERS := start .. end by step; 
If the by step is missing, the step is assumed to be 1
set NUMBERS := 1..5; # NUMBERS = {1, 2, 3, 4, 5} 
Note Automatic set generation can only be done in the model environment, in the data environment you must define the set explicitly:
set NUMBERS := 1 2 3 4 5; # NUMBERS = {1, 2, 3, 4 5} 
>
>
{'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'}
or a sequence of numbers:
param start;
param end > start;
param step;
set NUMBERS := start .. end by step;
If the by step is missing, the step is assumed to be 1:
set NUMBERS := 1..5; # NUMBERS = {1, 2, 3, 4, 5}
Note Automatic set generation can only be done in the model environment, in the data environment you must define the set explicitly:
set NUMBERS := 1 2 3 4 5; # NUMBERS = {1, 2, 3, 4 5}
  Return to top
Line: 145 to 171
 
# The set of time-staged arcs

Changed:
<
<
set TIME_ARCS within TIME_NODES cross TIME_NODES := { (m, t) in TIME_NODES, (n, u) in TIME_NODES : ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage
>
>
set TIME_ARCS within TIME_NODES cross TIME_NODES := { (m, t) in TIME_NODES, (n, u) in TIME_NODES : ( ( (m, n) in ARCS) and (t = u) ) or # The transportation arcs ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The storage arcs
 

There are many concepts within this one statement, let's look at them one at a time.

Revision 102008-04-06 - MichaelOSullivan

Line: 1 to 1
 
META TOPICPARENT name="AMPLSyntax"
<-- Ready to Review - done - Lauren-->

Sets in AMPL

Line: 55 to 55
 Sets are usually defined in a data file:


Changed:
<
<
set NODES := Youngstown Pittsburgh Cincinnati 'Kansas City' Chicago Albany Houston Tempe Gary ;
>
>
set NODES := Youngstown Pittsburgh Cincinnati 'Kansas City' Chicago Albany Houston Tempe Gary ;
 

although they may be defined during declaration using either an explicit set literal or using a set expression:

Line: 252 to 253
 # The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES := { (m, t) in TIME_NODES, (n, u) in TIME_NODES :
Changed:
<
<
( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage
>
>
( ( (m, n) in ARCS) and (t = u) ) or # The transportation arcs ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The storage arcs
 

to create TIME_ARCS you could use these statements

Line: 263 to 264
 set STORAGE_ARCS := union {t in MONTHS, (m, n) in ARCS : t <> last(MONTHS)} {(m, t, n, next(t, MONTHS)};
Changed:
<
<
set TIME_ARCS within TIME_NODES cross TIME_NODES := TRANSPORT_ARCS union STORAGE_ARCS;
>
>
set TIME_ARCS within TIME_NODES cross TIME_NODES := TRANSPORT_ARCS union STORAGE_ARCS;
 

Rather than looping over all possibilities and only keeping those that are appropriate, the new statement only loops over smaller sets that can be used to build up the TIME_NODES set efficiently.

Revision 92008-03-11 - MichaelOSullivan

Line: 1 to 1
 
META TOPICPARENT name="AMPLSyntax"
<-- Ready to Review - done - Lauren-->

Sets in AMPL

Line: 246 to 246
 Return to top

Efficient Generation of Sets

Changed:
<
<
When creating models, generating sets by looping over all possibilities and removing those that don't fit some conditions (e.g., like the TIME_ARCS statement) can take a long time if there are many possibilities. This is time that could be spent solving the model! If possible you should try to create sets by building them up from smaller building block, rather than by creating an enormous set and pruning it. For example, instead of using this statement
# The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :     ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage 
to create TIME_ARCS you could use these statement
set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)}; set STORAGE_ARCS := union {t in MONTHS, (m, n) in ARCS : t <> last(MONTHS)}   {(m, t, n, next(t, MONTHS)}; set TIME_ARCS within TIME_NODES cross TIME_NODES := TRANSPORT_ARCS union STORAGE_ARCS; 
Rather than looping over all possibilities and only keeping those that are appropriate, the new statement only loops over smaller sets that can be used to build up the TIME_NODES set efficiently.

Return to top

-- MichaelOSullivan - 27 Feb 2008

>
>
When creating models, generating sets by looping over all possibilities and removing those that don't fit some conditions (e.g., like the TIME_ARCS statement) can take a long time if there are many possibilities. This is time that could be spent solving the model! If possible you should try to create sets by building them up from smaller building block, rather than by creating an enormous set and pruning it. For example, instead of using this statement
# The set of time-staged arcs
set TIME_ARCS within TIME_NODES cross TIME_NODES :=
   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :
     ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation
     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage

to create TIME_ARCS you could use these statements

set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)};
set STORAGE_ARCS := union {t in MONTHS, (m, n) in ARCS : t <> last(MONTHS)}
   {(m, t, n, next(t, MONTHS)};

set TIME_ARCS within TIME_NODES cross TIME_NODES := TRANSPORT_ARCS union STORAGE_ARCS;

Rather than looping over all possibilities and only keeping those that are appropriate, the new statement only loops over smaller sets that can be used to build up the TIME_NODES set efficiently.

Return to top

-- MichaelOSullivan - 27 Feb 2008

 
META FILEATTACHMENT attachment="latexa4ed27399944f27be0955f861782ef5e.png" attr="h" comment="" date="1204112900" name="latexa4ed27399944f27be0955f861782ef5e.png" stream="GLOB(0xa5f5874)" tmpFilename="latexa4ed27399944f27be0955f861782ef5e.png" user="MichaelOSullivan" version="1"

Revision 82008-03-11 - MichaelOSullivan

Line: 1 to 1
 
META TOPICPARENT name="AMPLSyntax"
<-- Ready to Review - done - Lauren-->

Sets in AMPL

Line: 96 to 96
 
  • Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
    
    
  • Changed:
    <
    <
    set ARCS: Cincinnati ‘Kansas City’ Chicago Albany Houston Tempe Gary :=
    >
    >
    set ARCS: Cincinnati 'Kansas City' Chicago Albany Houston Tempe Gary :=
     Youngstown + + + + - - - Pittsburgh + + + - - - + Cincinnati - - - + + - -
    Changed:
    <
    <
    ‘Kansas City’ - - - - + + -
    >
    >
    'Kansas City' - - - - + + -
     Chicago - - - - - + + ;
    Line: 121 to 121
      You can create sets where the elements are ordered using the ordered keyword during definition.
    Changed:
    <
    <
    Up to here - Mike
    >
    >
    set MONTHS ordered;
    

    AMPL will puts the elements in this set in the order they appear in the data file (or let statement). AMPL also understands the following operations for ordered sets:

    ord(e, ORD_SET)   # The position of e in ORD_SET
    first(ORD_SET)    # The first element in ORD_SET
    last(ORD_SET)     # The last element in ORD_SET
    prev(e, ORD_SET)  # The element before e in ORD_SET
    next(e, ORD_SET)  # The element after e in ORD_SET
    member(i, ORDSET) # The element at position i in ORD_SET
    

    Return to top

     
    Deleted:
    <
    <
    set MONTHS ordered; 
    AMPL will puts the elements in this set in the order they appear in the data file (or {\tt let} statement). AMPL also understands the following operations for ordered sets:
    ord(e, ORD_SET)   # The position of e in ORD_SET first(ORD_SET)    # The first element in ORD_SET last(ORD_SET)     # The last element in ORD_SET prev(e, ORD_SET)  # The element before e in ORD_SET next(e, ORD_SET)  # The element after e in ORD_SET member(i, ORDSET) # The element at position i in ORD_SET 

    Return to top

     

    Set Example

    Changed:
    <
    <

    Consider the following AMPL statement from the The American Steel Planning Problem. We use ord in the creation of TIME_ARCS:

    # The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :     ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage 
    There are many concepts within this one statement, let's look at them one at a time.

    >
    >
    Consider the following AMPL statement from the The American Steel Planning Problem. We use ord in the creation of TIME_ARCS:

    # The set of time-staged arcs
    set TIME_ARCS within TIME_NODES cross TIME_NODES :=   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :
         ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation
         ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage
    

    There are many concepts within this one statement, let's look at them one at a time.

     

    Set Operations

    Changed:
    <
    <
    There are many operations we can perform on sets (see Set Expressions). We have seen that cross creates all pairs of two sets, so TIME_NODES cross TIME_NODES creates a set of all pairs of TIME_NODES.

    Some set operations may be looped over indexing sets. For example, to generate all the transportation arcs in the time-staged network you could use the following statement

    set TRANSPORT_ARCS := union {t in MONTHS} (union {(m, n) ARCS} {(m, t, n, t)}); 
    or you could loop over {\tt MONTHS} and {\tt ARCS} simultaneously
    set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)}; 

    >
    >
    There are many operations we can perform on sets (see Set Expressions). We have seen that cross creates all pairs of two sets, so TIME_NODES cross TIME_NODES creates a set of all pairs of TIME_NODES.

    Some set operations may be looped over indexing sets. For example, to generate all the transportation arcs in the time-staged network you could use the following statement:

    set TRANSPORT_ARCS := union {t in MONTHS} (union {(m, n) ARCS} {(m, t, n, t)});
    
    or you could loop over MONTHS and ARCS simultaneously:
    set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)};
    
     

    Set Membership and Subsets

    Changed:
    <
    <
    We have seen how loop over a set using the in keyword. This keyword also provides a logical check if an element is in a set, e.g., (m, n) in ARCS is true if the pair (m, n) is in the set ARCS and false otherwise. We may restrict a set to be a subset of an existing set by using the keyword {\tt within}, e. g.,
    set ARCS within NODES cross NODES; 
    means each arc is created between two nodes.

    >
    >
    We have seen how loop over a set using the in keyword. This keyword also provides a logical check if an element is in a set, e.g., (m, n) in ARCS is true if the pair (m, n) is in the set ARCS and false otherwise. We may restrict a set to be a subset of an existing set by using the keyword {\tt within}, e. g.,
    set ARCS within NODES cross NODES;
    
    means each arc is created between two nodes.
     

    Ordered Set Operators

    Changed:
    <
    <
    The final condition on TIME_ARCS
        ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; 
    creates the "storage" arcs. We could use next(t, MONTHS) = u or t = prev(u, MONTHS) except for a problem when t is June or u is April, respectively. When you use prev or next you must be careful of the first and last members of the set respectively. However, you can use first or last to check if you are using these elements.

    Return to top

    >
    >
    The final condition on TIME_ARCS
        ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )};
    
    creates the "storage" arcs. We could use next(t, MONTHS) = u or t = prev(u, MONTHS) except for a problem when t is June or u is April, respectively. When you use prev or next you must be careful of the first and last members of the set respectively. However, you can use first or last to check if you are using these elements.

    Return to top

     

    Restricted Sets

    Changed:
    <
    <
    When using display or printf statements we saw that we could restrict the members of a set being printed, e.g.,
    display {(m, n) in ARCS : Supply[m] > 0}; # Display all arcs from supply nodes 
    We can do this when creating sets, e. g., TIME_NODES, or when using a set as an index for variables, parameters or constraints. For example, rather than setting the upper bound of UnderProduction to be 0 for all non-supply nodes (since non-supply nodes don't produce anything) we could only create this variable for the supply nodes (in fact this may be preferable since there will be less variables).
    var UnderProduction {(n, t) in TIME_NODES : Supply[n, t] > 0} >= 0, integer; 
    We could make sure this variable is only added to the constraints for the supply nodes (e.g., ConserveFlow constraints) by using a conditional expression.
    subject to ConserveFlow {(n, t) in TIME_NODES}:   sum {(m, s) in TIME_NODES: (m, s, n, t) in TIME_ARCS}     Shipment[m, s, n, t] + Supply[n, t] -     if Supply[n, t] > 0 then UnderProduction[n, t] = ... 

    Return to top

    >
    >
    When using display or printf statements we saw that we could restrict the members of a set being printed, e.g.,
    display {(m, n) in ARCS : Supply[m] > 0}; # Display all arcs from supply nodes
    

    We can do this when creating sets, e. g., TIME_NODES, or when using a set as an index for variables, parameters or constraints. For example, rather than setting the upper bound of UnderProduction to be 0 for all non-supply nodes (since non-supply nodes don't produce anything) we could only create this variable for the supply nodes (in fact this may be preferable since there will be less variables).

    var UnderProduction {(n, t) in TIME_NODES : Supply[n, t] > 0} >= 0, integer;
    

    We could make sure this variable is only added to the constraints for the supply nodes (e.g., ConserveFlow constraints) by using a conditional expression.

    subject to ConserveFlow {(n, t) in TIME_NODES}:
       sum {(m, s) in TIME_NODES: (m, s, n, t) in TIME_ARCS}
         Shipment[m, s, n, t] + Supply[n, t] -
         if Supply[n, t] > 0 then UnderProduction[n, t] = ... 
    

    Return to top

     

    Multi-dimensional Sets

    Changed:
    <
    <
    We have already seen different ways of declaring 2-dimensional sets. We have now encountered higher dimensional sets, e.g., TIME_ARCS has 4 dimensions. We generated TIME_ARCS automatically, but we could have specified it using a data file.
    set TIME_ARCS within TIME_NODES cross TIME_NODES; 
    List
    set TIME_ARCS := (Youngstown, April, Albany, April)                  (Youngstown, April, Youngstown, May) ... ; 
    Table
    set TIME_ARCS : = (*, May, *, May)  Cincinnati 'Kansas City' Albany ... := Youngstown         +          +            +      ... Pittsburgh         +          +            -      ... ... ; 
    Array
    set TIME_ARCS := (*, May, *, May) (Youngstown, Cincinnati) ... ... ; 
    or
    set TIME_ARCS := (Youngstown, May, *, May) Cincinnati ‘Kansas City’ ... ... ; 

    Return to top

    >
    >
    We have already seen different ways of declaring 2-dimensional sets. We have now encountered higher dimensional sets, e.g., TIME_ARCS has 4 dimensions. We generated TIME_ARCS automatically, but we could have specified it using a data file.

    set TIME_ARCS within TIME_NODES cross TIME_NODES;
    

    List

    set TIME_ARCS := (Youngstown, April, Albany, April)
                      (Youngstown, April, Youngstown, May) ... ;
    

    Table

    set TIME_ARCS : =
    (*, May, *, May)  Cincinnati 'Kansas City' Albany ... :=
    Youngstown         +          +            +      ...
    Pittsburgh         +          +            -      ...
    ... ;
    

    Array

    set TIME_ARCS := (*, May, *, May) (Youngstown, Cincinnati) ... ... ;
    

    or

    set TIME_ARCS := (Youngstown, May, *, May) Cincinnati 'Kansas City' ... ... ;
    

    Return to top

     

    Efficient Generation of Sets

    When creating models, generating sets by looping over all possibilities and removing those that don't fit some conditions (e.g., like the TIME_ARCS statement) can take a long time if there are many possibilities. This is time that could be spent solving the model! If possible you should try to create sets by building them up from smaller building block, rather than by creating an enormous set and pruning it. For example, instead of using this statement
    # The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :     ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage 
    to create TIME_ARCS you could use these statement
    set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)}; set STORAGE_ARCS := union {t in MONTHS, (m, n) in ARCS : t <> last(MONTHS)}   {(m, t, n, next(t, MONTHS)}; set TIME_ARCS within TIME_NODES cross TIME_NODES := TRANSPORT_ARCS union STORAGE_ARCS; 
    Rather than looping over all possibilities and only keeping those that are appropriate, the new statement only loops over smaller sets that can be used to build up the TIME_NODES set efficiently.

    Return to top

    -- MichaelOSullivan - 27 Feb 2008

    Revision 72008-03-11 - MichaelOSullivan

    Line: 1 to 1
     
    META TOPICPARENT name="AMPLSyntax"
    <-- Ready to Review - done - Lauren-->

    Sets in AMPL

    Line: 23 to 23
     Sets are declared using the set keyword followed by a label, possibly some attributes and either a set literal or set expression. The most common attribute is set by the within keyword. This specifies that the set will only contain elements from the following set definition:
    set ARCS within NODES cross NODES; # Elements of ARCS must have both elements in NODES 
    If you need a multi-dimensional set, but don't have the 1-dimensional sets to construct it yet you can use the dimen keyword:
    set ROUTES dimen 2; 
    There are some other set attributes, but we will not use them.

    Set literals can be defined as a list of elements:

    Changed:
    <
    <
    {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'} 
    or a sequence of numbers:
    param start; param end > start; param step;  set NUMBERS := start .. end by step; 
    If the by step is missing, the step is assumed to be 1
    set NUMBERS := 1..5; # NUMBERS = {1, 2, 3, 4, 5} 
    Note Automatic set generation can only be done in the [[AMPLProcess#model][model environment] should this be a link? - Lauren , in the data environment you must define the set explicitly:
    set NUMBERS := 1 2 3 4 5; # NUMBERS = {1, 2, 3, 4 5} 
    >
    >
    {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'} 
    or a sequence of numbers:
    param start; param end > start; param step;  set NUMBERS := start .. end by step; 
    If the by step is missing, the step is assumed to be 1
    set NUMBERS := 1..5; # NUMBERS = {1, 2, 3, 4, 5} 
    Note Automatic set generation can only be done in the model environment, in the data environment you must define the set explicitly:
    set NUMBERS := 1 2 3 4 5; # NUMBERS = {1, 2, 3, 4 5} 
      Return to top
    Line: 32 to 32
     
    1. Define the elements that make up the set, e.g., s in SUPPLY_NODES, before the colon : operator;
    2. Use a logical expression (after the :) to indicate if an element (or pair of elements, or “tuple” of elements) should be included in the set.
    Changed:
    <
    <
    Generic Set Expression Fix underlining - Lauren
    {  in , [ in ,  in , ...] :   } Set expressions may also involve one or more _set operators_: 
    1. =A union B= gives the set of elements in either =A= or =B=;
    2. =A inter B= gives the set of elements in both =A= and =B=;
    3. =A diff B= gives the set of elements in =A= that are not in =B=;
    4. =A symdiff B= gives the set of elements in either =A= or =B= but not both;
    5. =A cross B= gives the two-dimensional set of all pairs =a= $\in$ =A=, =b= $\in$ =B=. This can also be defined by ={a in A, b in B}=.

    You will see examples of set expressions throughout the rest of this page.

    [[#top][Return to top]]

    >
    >
    Generic Set Expression
    { <e> in <S>, [<f> in <T>, <g> in <U>, …] :
      <logical expression involving e [f, g, …]>}
    

    Set expressions may also involve one or more set operators:

    1. A union B gives the set of elements in either A or B;
    2. A inter B gives the set of elements in both A and B;
    3. A diff B gives the set of elements in A that are not in B;
    4. A symdiff B gives the set of elements in either A or B but not both;
    5. A cross B gives the two-dimensional set of all pairs a $\in$ A, b $\in$ B. This can also be defined by {a in A, b in B}.

    You will see examples of set expressions throughout the rest of this page.

    Return to top

     

    Defining a Set

    Changed:
    <
    <

    Sets are usually defined in a data file:

    set NODES := Youngstown Pittsburgh Cincinnati ‘Kansas City’ Chicago              Albany Houston Tempe Gary ; 
    although they may be defined during declaration using either an explicit set literal or using a set expression:
    set KIND := {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'};  set COMPONENT := {C in CLASSES : (kind[C] = 'HOST'  ) or              (kind[C] = 'DEVICE') or              (kind[C] = 'HUB'   ) or              (kind[C] = 'SWITCH')};  set FABRIC := NODE union LINK; 
    and sets may also be defined dynamically:
    set SEARCH within VERTICES;  let SEARCH := {v in VERTICES: (v, w) in EDGES}; 

    >
    >
    Sets are usually defined in a data file:

    set NODES := Youngstown Pittsburgh Cincinnati 'Kansas City' Chicago              Albany Houston Tempe Gary ;
    

    although they may be defined during declaration using either an explicit set literal or using a set expression:

    set KIND := {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'};
    
    set COMPONENT := {C in CLASSES : (kind[C] = 'HOST'  ) or
    				 (kind[C] = 'DEVICE') or
    				 (kind[C] = 'HUB'   ) or
    				 (kind[C] = 'SWITCH')};
    
    set FABRIC := NODE union LINK;
    

    and sets may also be defined dynamically:

    set SEARCH within VERTICES;
    let SEARCH := {v in VERTICES: (v, w) in EDGES};
    
     

    Defining 2-Dimensional Sets

    Changed:
    <
    <
    There are three different ways to define 2-dimensional sets. The "best" way to use depends on the set.
    1. Using a List You simply list the elements in the set. This is good for sparse sets.
      model; set ARCS within NODES cros NODES; data; set ARCS := (Youngstown, Albany), (Youngstown, Cincinnati), ... ; 
    2. Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
      set ARCS: Cincinnati ‘Kansas City’ Chicago Albany Houston Tempe Gary := Youngstown + + + + - - - Pittsburgh + + + - - - + Cincinnati - - - + + - - ‘Kansas City’ - - - - + + - Chicago - - - - - + + ; 
    3. Using an Array You define a list of column indices for each row index. This is a good for sets with a few elements for each row.
      set ARCS := (Youngstown, *) Cincinnati ‘Kansas City’ Chicago Albany (Pittsburgh, *) Cincinnati ‘Kansas City’ Chicago Gary (Cincinnati, *) Albany Houston ... 

    Return to top

    >
    >
    There are three different ways to define 2-dimensional sets. The "best" way to use depends on the set.

    1. Using a List You simply list the elements in the set. This is good for sparse sets.

      model;
      set ARCS within NODES cros NODES;
      
      data;
      
      set ARCS := (Youngstown, Albany), (Youngstown, Cincinnati), ... ;
      
    2. Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
      set ARCS:   Cincinnati ‘Kansas City’ Chicago Albany Houston Tempe Gary :=
      Youngstown         +          +         +      +       -      -    -
      Pittsburgh         +          +         +      -       -      -    +
      Cincinnati         -          -         -      +       +      -    -
      ‘Kansas City’      -          -         -      -       +      +    -
      Chicago            -          -         -      -       -      +    + ;
      
    3. Using an Array You define a list of column indices for each row index. This is a good for sets with a few elements for each row.
      set ARCS :=
      (Youngstown, *) Cincinnati ‘Kansas City’ Chicago Albany
      (Pittsburgh, *) Cincinnati ‘Kansas City’ Chicago Gary
      (Cincinnati, *) Albany Houston ...
      

    Return to top

     

    Ordered Sets

    Changed:
    <
    <

    You can create sets where the elements are ordered using the ordered keyword during definition.

    set MONTHS ordered; 
    AMPL will puts the elements in this set in the order they appear in the data file (or {\tt let} statement). AMPL also understands the following operations for ordered sets:
    ord(e, ORD_SET)   # The position of e in ORD_SET first(ORD_SET)    # The first element in ORD_SET last(ORD_SET)     # The last element in ORD_SET prev(e, ORD_SET)  # The element before e in ORD_SET next(e, ORD_SET)  # The element after e in ORD_SET member(i, ORDSET) # The element at position i in ORD_SET 

    Return to top

    >
    >
    You can create sets where the elements are ordered using the ordered keyword during definition.

    Up to here - Mike

    set MONTHS ordered; 
    AMPL will puts the elements in this set in the order they appear in the data file (or {\tt let} statement). AMPL also understands the following operations for ordered sets:
    ord(e, ORD_SET)   # The position of e in ORD_SET first(ORD_SET)    # The first element in ORD_SET last(ORD_SET)     # The last element in ORD_SET prev(e, ORD_SET)  # The element before e in ORD_SET next(e, ORD_SET)  # The element after e in ORD_SET member(i, ORDSET) # The element at position i in ORD_SET 

    Return to top

     

    Set Example

    Consider the following AMPL statement from the The American Steel Planning Problem. We use ord in the creation of TIME_ARCS:

    # The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :     ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage 
    There are many concepts within this one statement, let's look at them one at a time.

    Set Operations

    Revision 62008-03-09 - LaurenJackson

    Line: 1 to 1
     
    META TOPICPARENT name="AMPLSyntax"
    Changed:
    <
    <
    <-- Ready to Review -->
    >
    >
    <-- Ready to Review - done - Lauren-->
     

    Sets in AMPL

    Changed:
    <
    <
    1. Description
    2. Declaring a Set
    3. Set Expressions
    4. Defining a Set
    5. Ordered Sets
    6. Set Example
    7. Restricted Sets
    8. Multi-Dimensional Sets
    9. Effcient Generation of Sets
    >
    >
    1. Description
    2. Declaring a Set
    3. Set Expressions
    4. Defining a Set
    5. Ordered Sets
    6. Set Example
    7. Restricted Sets
    8. Multi-Dimensional Sets
    9. Efficient Generation of Sets
     

    Description

    Line: 20 to 20
     Return to top

    Declaring a Set

    Changed:
    <
    <
    Sets are declared using the set keyword followed by a label, possibly some attributes and either a set literal or set expression. The most common attribute is set by the within keyword. This specifies that the set will only contain elements from the following set definition:
    set ARCS within NODES cross NODES; # Elements of ARCS must have both elements in NODES
    
    If you need a multi-dimensional set, but don't have the 1-dimensional sets to construct it yet you can use the dimen keyword:
    set ROUTES dimen 2;
    
    There are some other set attributes, but we will not use them.
    >
    >
    Sets are declared using the set keyword followed by a label, possibly some attributes and either a set literal or set expression. The most common attribute is set by the within keyword. This specifies that the set will only contain elements from the following set definition:
    set ARCS within NODES cross NODES; # Elements of ARCS must have both elements in NODES 
    If you need a multi-dimensional set, but don't have the 1-dimensional sets to construct it yet you can use the dimen keyword:
    set ROUTES dimen 2; 
    There are some other set attributes, but we will not use them.
      Set literals can be defined as a list of elements:
    Changed:
    <
    <
    {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'}
    
    or a sequence of numbers:
    param start;
    param end > start;
    param step;
    
    set NUMBERS := start .. end by step;
    
    If the by step is missing, the step is assumed to be 1
    set NUMBERS := 1..5; # NUMBERS = {1, 2, 3, 4, 5}
    
    Note Automatic set generation can only be done in the [[AMPLProcess#model][model environment], in the data environment you must define the set explicitly:
    set NUMBERS := 1 2 3 4 5; # NUMBERS = {1, 2, 3, 4 5}
    
    >
    >
    {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'} 
    or a sequence of numbers:
    param start; param end > start; param step;  set NUMBERS := start .. end by step; 
    If the by step is missing, the step is assumed to be 1
    set NUMBERS := 1..5; # NUMBERS = {1, 2, 3, 4, 5} 
    Note Automatic set generation can only be done in the [[AMPLProcess#model][model environment] should this be a link? - Lauren , in the data environment you must define the set explicitly:
    set NUMBERS := 1 2 3 4 5; # NUMBERS = {1, 2, 3, 4 5} 
      Return to top

    Set Expressions

    Set expressions take the following form (which can be extended to higher dimensional sets):
    1. Define the elements that make up the set, e.g., s in SUPPLY_NODES, before the colon : operator;
    Changed:
    <
    <
    1. Use a logical expression (after the :) to indicate if an element (or pair of elements, or “tuple” of elements) should be included in the set.

    Generic Set Expression

    { <e> in <S>, [<f> in <T>, <g> in <U>, ...] :
      <logical expression involving e [f, g, ...]>}
    
    Set expressions may also involve one or more set operators:
    1. A union B gives the set of elements in either A or B;
    2. A inter B gives the set of elements in both A and B;
    3. A diff B gives the set of elements in A that are not in B;
    4. A symdiff B gives the set of elements in either A or B but not both;
    5. A cross B gives the two-dimensional set of all pairs a $\in$ A, b $\in$ B.
      This can also be defined by {a in A, b in B}.

    You will see examples of set expressions throughout the rest of this page.

    Return to top

    >
    >
    1. Use a logical expression (after the :) to indicate if an element (or pair of elements, or “tuple” of elements) should be included in the set.
     
    Added:
    >
    >
    Generic Set Expression Fix underlining - Lauren
    {  in , [ in ,  in , ...] :   } Set expressions may also involve one or more _set operators_: 
    1. =A union B= gives the set of elements in either =A= or =B=;
    2. =A inter B= gives the set of elements in both =A= and =B=;
    3. =A diff B= gives the set of elements in =A= that are not in =B=;
    4. =A symdiff B= gives the set of elements in either =A= or =B= but not both;
    5. =A cross B= gives the two-dimensional set of all pairs =a= $\in$ =A=, =b= $\in$ =B=. This can also be defined by ={a in A, b in B}=.

    You will see examples of set expressions throughout the rest of this page.

    [[#top][Return to top]]

     

    Defining a Set

    Changed:
    <
    <
    Sets are usually defined in a data file:
    set NODES := Youngstown Pittsburgh Cincinnati ‘Kansas City’ Chicago
                 Albany Houston Tempe Gary ;
    
    although they may be defined during declaration using either an explicit set literal or using a set expression:
    set KIND := {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'};
    
    set COMPONENT := {C in CLASSES : (kind[C] = 'HOST'  ) or
    				 (kind[C] = 'DEVICE') or
    				 (kind[C] = 'HUB'   ) or
    				 (kind[C] = 'SWITCH')};
    
    set FABRIC := NODE union LINK;
    
    and sets may also be defined dynamically:
    set SEARCH within VERTICES;
    
    let SEARCH := {v in VERTICES: (v, w) in EDGES};
    
    >
    >

    Sets are usually defined in a data file:

    set NODES := Youngstown Pittsburgh Cincinnati ‘Kansas City’ Chicago              Albany Houston Tempe Gary ; 
    although they may be defined during declaration using either an explicit set literal or using a set expression:
    set KIND := {'HOST', 'DEVICE', 'SWITCH', 'HUB', 'LINK', 'SUPERLINK'};  set COMPONENT := {C in CLASSES : (kind[C] = 'HOST'  ) or              (kind[C] = 'DEVICE') or              (kind[C] = 'HUB'   ) or              (kind[C] = 'SWITCH')};  set FABRIC := NODE union LINK; 
    and sets may also be defined dynamically:
    set SEARCH within VERTICES;  let SEARCH := {v in VERTICES: (v, w) in EDGES}; 

     

    Defining 2-Dimensional Sets

    Changed:
    <
    <
    There are three different ways to define 2-dimensional sets. The "best" way to use depends on the set.
    1. Using a List You simply list the elements in the set. This is good for sparse sets.
      model;
      set ARCS within NODES cros NODES;
      
      data;
      
      set ARCS := (Youngstown, Albany), (Youngstown, Cincinnati), ... ;
      
    2. Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
      set ARCS:   Cincinnati ‘Kansas City’ Chicago Albany Houston Tempe Gary :=
      Youngstown         +          +         +      +       -      -    -
      Pittsburgh         +          +         +      -       -      -    +
      Cincinnati         -          -         -      +       +      -    -
      ‘Kansas City’      -          -         -      -       +      +    -
      Chicago            -          -         -      -       -      +    + ;
      
    3. Using an Array You define a list of column indices for each row index. This is a good for sets with a few elements for each row.
      set ARCS :=
      (Youngstown, *) Cincinnati ‘Kansas City’ Chicago Albany
      (Pittsburgh, *) Cincinnati ‘Kansas City’ Chicago Gary
      (Cincinnati, *) Albany Houston ...
      

    Return to top

    >
    >
    There are three different ways to define 2-dimensional sets. The "best" way to use depends on the set.
    1. Using a List You simply list the elements in the set. This is good for sparse sets.
      model; set ARCS within NODES cros NODES; data; set ARCS := (Youngstown, Albany), (Youngstown, Cincinnati), ... ; 
    2. Using a Table You give a table using the first index set for the rows and the second index set for the columns, then you place a + where an element exists and a - where there is no element. This is good for dense sets.
      set ARCS: Cincinnati ‘Kansas City’ Chicago Albany Houston Tempe Gary := Youngstown + + + + - - - Pittsburgh + + + - - - + Cincinnati - - - + + - - ‘Kansas City’ - - - - + + - Chicago - - - - - + + ; 
    3. Using an Array You define a list of column indices for each row index. This is a good for sets with a few elements for each row.
      set ARCS := (Youngstown, *) Cincinnati ‘Kansas City’ Chicago Albany (Pittsburgh, *) Cincinnati ‘Kansas City’ Chicago Gary (Cincinnati, *) Albany Houston ... 

    Return to top

     

    Ordered Sets

    Changed:
    <
    <
    You can create sets where the elements are ordered using the ordered keyword during definition.
    set MONTHS ordered;
    
    AMPL will puts the elements in this set in the order they appear in the data file (or {\tt let} statement). AMPL also understands the following operations for ordered sets:
    ord(e, ORD_SET)   # The position of e in ORD_SET
    first(ORD_SET)    # The first element in ORD_SET
    last(ORD_SET)     # The last element in ORD_SET
    prev(e, ORD_SET)  # The element before e in ORD_SET
    next(e, ORD_SET)  # The element after e in ORD_SET
    member(i, ORDSET) # The element at position i in ORD_SET
    

    Return to top

    >
    >

    You can create sets where the elements are ordered using the ordered keyword during definition.

    set MONTHS ordered; 
    AMPL will puts the elements in this set in the order they appear in the data file (or {\tt let} statement). AMPL also understands the following operations for ordered sets:
    ord(e, ORD_SET)   # The position of e in ORD_SET first(ORD_SET)    # The first element in ORD_SET last(ORD_SET)     # The last element in ORD_SET prev(e, ORD_SET)  # The element before e in ORD_SET next(e, ORD_SET)  # The element after e in ORD_SET member(i, ORDSET) # The element at position i in ORD_SET 

    Return to top

     

    Set Example

    Changed:
    <
    <
    Consider the following AMPL statement from the The American Steel Planning Problem. We use ord in the creation of TIME_ARCS:
    # The set of time-staged arcs
    set TIME_ARCS within TIME_NODES cross TIME_NODES :=
      { (m, t) in TIME_NODES, (n, u) in TIME_NODES :
        ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation
        ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage
    
    There are many concepts within this one statement, let's look at them one at a time.
    >
    >

    Consider the following AMPL statement from the The American Steel Planning Problem. We use ord in the creation of TIME_ARCS:

    # The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :     ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage 
    There are many concepts within this one statement, let's look at them one at a time.

     

    Set Operations

    Changed:
    <
    <
    There are many operations we can perform on sets (see Set Expressions). We have seen that cross creates all pairs of two sets, so TIME_NODES cross TIME_NODES creates a set of all pairs of TIME_NODES.

    Some set operations may be looped over indexing sets. For example, to generate all the transportation arcs in the time-staged network you could use the following statement

    set TRANSPORT_ARCS := union {t in MONTHS} (union {(m, n) ARCS} {(m, t, n, t)});
    
    or you could loop over {\tt MONTHS} and {\tt ARCS} simultaneously
    set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)};
    
    >
    >
    There are many operations we can perform on sets (see Set Expressions). We have seen that cross creates all pairs of two sets, so TIME_NODES cross TIME_NODES creates a set of all pairs of TIME_NODES.

    Some set operations may be looped over indexing sets. For example, to generate all the transportation arcs in the time-staged network you could use the following statement

    set TRANSPORT_ARCS := union {t in MONTHS} (union {(m, n) ARCS} {(m, t, n, t)}); 
    or you could loop over {\tt MONTHS} and {\tt ARCS} simultaneously
    set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)}; 

     

    Set Membership and Subsets

    Changed:
    <
    <
    We have seen how loop over a set using the in keyword. This keyword also provides a logical check if an element is in a set, e.g., (m, n) in ARCS is true if the pair (m, n) is in the set ARCS and false otherwise. We may restrict a set to be a subset of an existing set by using the keyword {\tt within}, e. g.,
    set ARCS within NODES cross NODES;
    
    means each arc is created between two nodes.
    >
    >
    We have seen how loop over a set using the in keyword. This keyword also provides a logical check if an element is in a set, e.g., (m, n) in ARCS is true if the pair (m, n) is in the set ARCS and false otherwise. We may restrict a set to be a subset of an existing set by using the keyword {\tt within}, e. g.,
    set ARCS within NODES cross NODES; 
    means each arc is created between two nodes.

     

    Ordered Set Operators

    Changed:
    <
    <
    The final condition on TIME_ARCS
        ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )};
    
    creates the "storage" arcs. We could use next(t, MONTHS) = u or t = prev(u, MONTHS) except for a problem when t is June or u is April, respectively. When you use prev or next you must be careful of the first and last members of the set respectively. However, you can use first or last to check if you are using these elements.

    Return to top

    >
    >
    The final condition on TIME_ARCS
        ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; 
    creates the "storage" arcs. We could use next(t, MONTHS) = u or t = prev(u, MONTHS) except for a problem when t is June or u is April, respectively. When you use prev or next you must be careful of the first and last members of the set respectively. However, you can use first or last to check if you are using these elements.

    Return to top

     

    Restricted Sets

    Changed:
    <
    <
    When using display or printf statements we saw that we could restrict the members of a set being printed, e.g.,
    display {(m, n) in ARCS : Supply[m] > 0}; # Display all arcs from supply nodes
    
    We can do this when creating sets, e. g., TIME_NODES, or when using a set as an index for variables, parameters or constraints. For example, rather than setting the upper bound of UnderProduction to be 0 for all non-supply nodes (since non-supply nodes don't produce anything) we could only create this variable for the supply nodes (in fact this may be preferable since there will be less variables).
    var UnderProduction {(n, t) in TIME_NODES : Supply[n, t] > 0} >= 0, integer;
    
    We could make sure this variable is only added to the constraints for the supply nodes (e.g., ConserveFlow constraints) by using a conditional expression.
    subject to ConserveFlow {(n, t) in TIME_NODES}:
      sum {(m, s) in TIME_NODES: (m, s, n, t) in TIME_ARCS}
        Shipment[m, s, n, t] + Supply[n, t] -
        if Supply[n, t] > 0 then UnderProduction[n, t] = ...
    

    Return to top

    >
    >
    When using display or printf statements we saw that we could restrict the members of a set being printed, e.g.,
    display {(m, n) in ARCS : Supply[m] > 0}; # Display all arcs from supply nodes 
    We can do this when creating sets, e. g., TIME_NODES, or when using a set as an index for variables, parameters or constraints. For example, rather than setting the upper bound of UnderProduction to be 0 for all non-supply nodes (since non-supply nodes don't produce anything) we could only create this variable for the supply nodes (in fact this may be preferable since there will be less variables).
    var UnderProduction {(n, t) in TIME_NODES : Supply[n, t] > 0} >= 0, integer; 
    We could make sure this variable is only added to the constraints for the supply nodes (e.g., ConserveFlow constraints) by using a conditional expression.
    subject to ConserveFlow {(n, t) in TIME_NODES}:   sum {(m, s) in TIME_NODES: (m, s, n, t) in TIME_ARCS}     Shipment[m, s, n, t] + Supply[n, t] -     if Supply[n, t] > 0 then UnderProduction[n, t] = ... 

    Return to top

     

    Multi-dimensional Sets

    Changed:
    <
    <
    We have already seen different ways of declaring 2-dimensional sets. We have now encountered higher dimensional sets, e.g., TIME_ARCS has 4 dimensions. We generated TIME_ARCS automatically, but we could have specified it using a data file.
    set TIME_ARCS within TIME_NODES cross TIME_NODES;
    
    List
    set TIME_ARCS := (Youngstown, April, Albany, April)
                     (Youngstown, April, Youngstown, May) ... ;
    
    Table
    set TIME_ARCS : =
    (*, May, *, May)  Cincinnati 'Kansas City' Albany ... :=
    Youngstown         +          +            +      ...
    Pittsburgh         +          +            -      ...
    ... ;
    
    Array
    set TIME_ARCS :=
    (*, May, *, May) (Youngstown, Cincinnati) ...
    ... ;
    
    or
    set TIME_ARCS :=
    (Youngstown, May, *, May) Cincinnati ‘Kansas City’ ...
    ... ;
    

    Return to top

    >
    >
    We have already seen different ways of declaring 2-dimensional sets. We have now encountered higher dimensional sets, e.g., TIME_ARCS has 4 dimensions. We generated TIME_ARCS automatically, but we could have specified it using a data file.
    set TIME_ARCS within TIME_NODES cross TIME_NODES; 
    List
    set TIME_ARCS := (Youngstown, April, Albany, April)                  (Youngstown, April, Youngstown, May) ... ; 
    Table
    set TIME_ARCS : = (*, May, *, May)  Cincinnati 'Kansas City' Albany ... := Youngstown         +          +            +      ... Pittsburgh         +          +            -      ... ... ; 
    Array
    set TIME_ARCS := (*, May, *, May) (Youngstown, Cincinnati) ... ... ; 
    or
    set TIME_ARCS := (Youngstown, May, *, May) Cincinnati ‘Kansas City’ ... ... ; 

    Return to top

     

    Efficient Generation of Sets

    Changed:
    <
    <
    When creating models, generating sets by looping over all possibilities and removing those that don't fit some conditions (e.g., like the TIME_ARCS statement) can take a long time if there are many possibilities. This is time that could be spent solving the model! If possible you should try to create sets by building them up from smaller building block, rather than by creating an enormous set and pruning it. For example, instead of using this statement
    # The set of time-staged arcs
    set TIME_ARCS within TIME_NODES cross TIME_NODES :=
      { (m, t) in TIME_NODES, (n, u) in TIME_NODES :
        ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation
        ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage
    
    to create TIME_ARCS you could use these statement
    set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)};
    set STORAGE_ARCS := union {t in MONTHS, (m, n) in ARCS : t <> last(MONTHS)}
      {(m, t, n, next(t, MONTHS)};
    set TIME_ARCS within TIME_NODES cross TIME_NODES := TRANSPORT_ARCS union STORAGE_ARCS;
    
    Rather than looping over all possibilities and only keeping those that are appropriate, the new statement only loops over smaller sets that can be used to build up the TIME_NODES set efficiently.

    Return to top

    -- MichaelOSullivan - 27 Feb 2008

    >
    >
    When creating models, generating sets by looping over all possibilities and removing those that don't fit some conditions (e.g., like the TIME_ARCS statement) can take a long time if there are many possibilities. This is time that could be spent solving the model! If possible you should try to create sets by building them up from smaller building block, rather than by creating an enormous set and pruning it. For example, instead of using this statement
    # The set of time-staged arcs set TIME_ARCS within TIME_NODES cross TIME_NODES :=   { (m, t) in TIME_NODES, (n, u) in TIME_NODES :     ( ( (m, n) in ARCS) and (t = u) ) or # The arcs used for transportation     ( (m = n) and (ord(t, MONTHS) + 1 = ord(u, MONTHS)) )}; # The arcs used for storage 
    to create TIME_ARCS you could use these statement
    set TRANSPORT_ARCS := union {t in MONTHS, (m, n) in ARCS} {(m, t, n, t)}; set STORAGE_ARCS := union {t in MONTHS, (m, n) in ARCS : t <> last(MONTHS)}   {(m, t, n, next(t, MONTHS)}; set TIME_ARCS within TIME_NODES cross TIME_NODES := TRANSPORT_ARCS union STORAGE_ARCS; 
    Rather than looping over all possibilities and only keeping those that are appropriate, the new statement only loops over smaller sets that can be used to build up the TIME_NODES set efficiently.

    Return to top

    -- MichaelOSullivan - 27 Feb 2008

     
    META FILEATTACHMENT attachment="latexa4ed27399944f27be0955f861782ef5e.png" attr="h" comment="" date="1204112900" name="latexa4ed27399944f27be0955f861782ef5e.png" stream="GLOB(0xa5f5874)" tmpFilename="latexa4ed27399944f27be0955f861782ef5e.png" user="MichaelOSullivan" version="1"

    Revision 12008-02-27 - MichaelOSullivan

    Line: 1 to 1
     
    This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
    Ideas, requests, problems regarding TWiki? Send feedback