|
Set element order |
Top Previous Next |
|
GAMS operates on a first in first out basis. The order of output items is always controlled by the first time something is seen. Many users are frustrated with the ordering of set elements in the output. This can be changed. It is worthwhile knowing the rules that ordering follows. GAMS uses something called the unique element list (UEL) to store set elements. This is a single list of all set elements. The elements enter that list in the order of their appearance and that is the order in which they will appear in the output i.e. first in first out. This means if I have the sets ONE and TWO with the elements below (dispset.gms)
set ONE /A,C,B,Total,8/; Set TWO /D,A,F,TOTAL/; Set items1through10 /1*10/; Parameter item(two) /D 1,A 3, F 5/; item("total")=sum(two$(not sameas(two,"total")),item(two)); display item,items1through10;
Then the display output will appear as follows. Note in the display of the parameter item that the output appears with the set element Total in the second position even though it was typed in the last position of the set called TWO and the parameter item is defined over that set.
---- 6 PARAMETER item A 3.000, Total 9.000, D 1.000, F 5.000 ---- 6 SET items1through10 8 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 9 , 10
This occurs because Total was seen before D and F in the sets because it was seen first in set ONE, even though it was listed last in set TWO. Similarly, look what has happened in the display of the set items1through10. Here 8 appears first then 1-7 and 9-10. This happens because the set element 8 appeared in the set ONE before 1-7 and 9-10 were seen. Notes: There are three ways of fixing such problems.
set ONE /A,C,B,Total,new8/ Set TWO /D,A,F,TOTAL2/ Parameter item(two) /D 1,A 3, F 5/; Item("total2")=sum(two$(not sameas(two,"total2")),item(two));
yielding
A 3.000, D 1.000, F 5.000 TOTAL2 9.000 and 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10
where use of total2 which had not been seen before and new8 which will not be seen again, restores the desired ordering.
set UELORDER /A,B,C,D,F,Total,1*20/ set ONE /A,C,B,Total,8/ Set TWO /D,A,F,TOTAL2/ Set items1through10 /1*10/;
In turn the displays would always have "Total" at the end and the 1-10 in the desired order.
Consider the following example where I want to better control appearance of the data in the table "items" on output set one /A,B,C,D,F,Average,ITEMS/; Set PQ /Price,Quantity/; Table Items(one,PQ) Price Quantity A 2 9000 B 6 3000 C 2.5 4000 D 2.1 3000 F 2.4 1.90; items("Average",PQ)= SUM(one,items(one,pq)) /sum(one,1$items(one,pq)); display items;
In turn the display output is
---- PARAMETER ITEMS Price Quantity A 2.000 9000.000 B 6.000 3000.000 C 2.500 4000.000 D 2.100 3000.000 F 2.400 1.900 Average 3.000 3800.380
But suppose I wanted average first. I do this by adding the set numberordr with values r1 through r100. Also I define items1 which is a new parameter with dimension one greater than items which has the numberordr set defining it in the first index position. Then I insure the items I want first have lower values in the numberordr place. (dispset4.gms). I also experiment with another ordering in the parameter items2.
Set numberordr /r1*r100/ set one /A,B,C,D,F,Average/ Set order2(numberordr,one) /r3.(A,D,F),r2.Average,r1.(C,B)/ Set PQ /Price,Quantity/ Table Items(one,PQ) Price Quantity A 2 9000 B 6 3000 C 2.5 4000 D 2.1 3000 F 2.4 1.90; items("Average",PQ)= SUM(one,items(one,pq))/sum(one,1$items(one,pq)); parameter items1(numberordr,one,pq) ordered first way; items1("r2",one,pq)$(not sameas(one,"average")) =items(one,pq); items1("r1","average",pq)=items("average",pq); parameter items2(numberordr,one,pq) ordered second way; items2(numberordr,one,pq) =sum(order2(numberordr,one),items(one,pq)); display items,items1,items2;
In turn the output is
where note by manipulating the association of items in the numberordr set with the things I wish reordered I can rearrange the output. |