Map two sets via an intermediate set

Problems with syntax of GAMS
Post Reply
benj
User
User
Posts: 1
Joined: 2 years ago

Map two sets via an intermediate set

Post by benj »

Dear Forum,

actually I would think my problem is quite easy to solve but it seems like it don't use the right keywords for my search.

I want to map two sets via an "intermediate set". So let's say I have three sets: a, b and c. And I have two more sets which map a with b and b with c. What I now want is one additional set, which is a mapping of a and c, based on the two existing mappings.

Code: Select all

Sets a       / j1*j2 / 
     b       / k1*k3 /
     c       / h1*h3 /
     ab(a,b) / j1.k1, j2.k2, j2.k3 / 
     bc(b,c) / k1.h1, k1.h2, k2.h3 /
Now needed is a set ac, which maps a with c, based on the sets ab and bc. The solution would be this:

Code: Select all

Set ac(a,c) / j1.h1, j1.h2, j2.h3 /
Would be super happy if someone could help me out!

Benj
abhosekar
Moderator
Moderator
Posts: 295
Joined: 3 years ago

Re: Map two sets via an intermediate set

Post by abhosekar »

Good question.
If I rephrase your question, it will become clearer: For a given b, you want ac to be true if ab(a, b) is true and bc(b, c) is true.
Write that in the GAMS way and you are done:

Code: Select all

Sets a       / j1*j2 / 
     b       / k1*k3 /
     c       / h1*h3 /
     ab(a,b) / j1.k1, j2.k2, j2.k3 / 
     bc(b,c) / k1.h1, k1.h2, k2.h3 /
     ;
     
set ac(a, c);

loop(b,
ac(a, c)$(ab(a, b) and bc(b, c)) = yes;
);
display ac; 
You will see ac displayed in the .lst file. All I am doing is looping over b and populating ac as needed.
Hope this helps.
- Atharv
User avatar
bussieck
Moderator
Moderator
Posts: 1033
Joined: 7 years ago

Re: Map two sets via an intermediate set

Post by bussieck »

The solution of my colleague Atharv works correctly and well. For very large data parallel assignment statements are way faster than loops, so in case you have very large data you might want to know how to do this fast with parallel assignment statements. The trick is to first build a three dimensional map abc and then project the b out. I parameterized the code so I can run for large n (even though the mapping between a, b, and c is trivial)

Code: Select all

$if not set n $set n 10
Sets a       / j1*j%n% / 
     b       / k1*k%n% /
     c       / h1*h%n% /
     ab(a,b) / #a:#b / 
     bc(b,c) / #b:#c /
     
set abc(a,b,c), ac(a,c);
loop(b, ac(a, c)$(ab(a, b) and bc(b, c)) = yes);
option clear=ac;
abc(a,b,c) = ab(a,b) and bc(b,c);
ac(a,c) = sum(b, abc(a,b,c));
When running this with n=10000 the profiler (profile=1) tells me about the execution speed (first column is the execution time in seconds):

Code: Select all

     8.906   0.053GB         9 Loop       
     0.047   0.065GB        12 Assignment ac (100000)
     0.016   0.055GB        11 Assignment abc (100000)
The last assignment to ac can also be replaced by "option ac<abc;" which goes even faster but is not easy to read.

-Michael
Post Reply