I often see models with set elements 1,2,…. Here is an example:
Of course if we have real data often we can use real names. But in some cases we need to use numbers as IDs. This is also typically the case when we don’t have real data and have to invent things. BTW, inventing data for a model is actually a very useful exercise: it will force you to think about the model in a more structured way.
If I have to invent labels I tend not to use 1,2,3,… but rather prefix the number by a string indicating what it is, e.g.:
| set i /i1*i10/ j /j1*j10/ w 'warehouse' /wh1*wh12/ ; |
The reason to use these longer labels is that the output of the model becomes easier to interpret. Below is an example:
Notes
- It makes sense to use this approach even with real (not invented) numeric IDs. Once the data arrives in GAMS it is often not so easy to “repair” set element labels. If the data is sitting in a database it can be helpful to prefix numeric IDs in the SQL query:
SELECT 'pr' || productid
FROM table
For a spreadsheet, often the easiest way is to insert a column or create a copy of the table with the new prefixed names. - The construct i.val does not work with numbers that are prefixed. I usually work around this to create a parameter val(i) that contains the value of element i. If needed I create a superset of i that has an easy way to populate val(s). E.g.
set
s /i3*i10/
i(s) /i3*i5,i8*i10/
;
parameter val(s);
val(s) = ord(s)+2;
* now we can use val(i) - It is not always possible to distinguish dimensions by their element names. E.g.
set i 'nodes' /node1*node10/;
alias (i,j);
positive variable flow(i,j);
Here, by nature, the two indices i and j have the same names because they have the same domain.