Friday, August 7, 2009

GAMS: speed of loops

In GAMS models I often see loops where they are not really needed. E.g.

loop(i,
   loop(j,
      loop(k,
         q(i,j,k) = 1;
)));

can be written as:

q(i,j,k) = 1;

Consider the larger fragment:

set i /i1*i200/;
alias(i,j,k);

parameter p(i,j,k);
p(i,j,k) = 1;

parameter q(i,j,k);
loop(i,
   loop(j,
      loop(k,
         q(i,j,k) = 1;
)));

parameter q2(i,j,k);
loop((i,j,k),
   q2(i,j,k) = 1;
);

The timing for the direct assignment to p(i,j,k) is 0.78 seconds. The time to populate q(i,j,k) is 18 seconds. The slightly different loop to fill q2 takes the same time: also 18 seconds. The difference is merely syntax. So if possible try not to use loops: not only is the code more compact, but it also performs better.

A more dramatic example is here (with card(i)=card(j)=card(k)=50):

p(i,j,k) = max(0,p(i,j,k)); 0.031 secs
loop((i,j,k),
  
if(p(i,j,k)<0, p(i,j,k)=0);
);
36.4 secs

2 comments:

  1. can you speed up this code?
    i must finish so many codes till monday. please can u help me?
    *option limrow=100;

    Set i nodes /n1*n40/;

    Alias (i,j);

    Scalar
    EAmp /100e-6/
    EElec /50e-3/
    Prx
    radius Radius of System /112.8338/
    energy /100/
    ;

    Parameters

    y(i) y coordinate of node-i
    x(i) x coordinate of node-i

    s(i) data generated at node-i

    d(i,j) distance between node-i and node-j
    Ptx(i,j) consumed energy for transmission of data from node-i to node-j

    random_radius radius
    angle angle
    M big number
    Lin Max In Flow
    Lout Max Out Flow
    l
    tekrar

    ;

    Variables
    t time
    Positive Variables
    f(i,j);

    Binary Variable
    a(i,j)

    ;


    Equations
    noFlow(i,j) no flow
    flowBalance(i) flow balance
    energyConstraint(i) energy constraint
    binaryConstraint(i,j)
    inConstraint(i)
    outConstraint(i);

    noFlow(i,j)$(ord(i)=ord(j) or ord(i)=1).. f(i,j) =e= 0;
    flowBalance(i)$(ord(i)>1).. -sum(j,f(i,j)) + sum(j,f(j,i)) + t*s(i) =e= 0;
    energyConstraint(i)$(ord(i)>1).. Prx*(sum(j$(ord(j)>1),f(j,i)))+sum(j,(Ptx(i,j)*f(i,j)))=l=energy;
    binaryConstraint(i,j)$(ord(i)>1).. f(i,j) =l= M*a(i,j);
    inConstraint(i)$(ord(i)>1).. sum(j$(ord(j)>1),a(j,i))=l=Lin;
    outConstraint(i)$(ord(i)>1).. sum(j,a(i,j))=l=Lout;

    file Sonuc /Sonuc.txt/;

    file Coordinate /Coordinate.txt/;

    file Flow /Flow.txt/;

    option iterlim=10000000;
    option reslim=10000000;
    option optcr=0.001;

    Model minimumBattery /All/;

    for (tekrar=1 to 100 by 1,
    for(l=2 to card(i),

    angle=360*uniform(0,1);
    random_radius= radius*sqrt(uniform(0,1));

    x(i)$(ord(i)=l) = random_radius * cos(angle);
    y(i)$(ord(i)=l) = random_radius * sin(angle);


    );
    x('n1')=0;
    y('n1')=0;

    d(i,j) = sqrt((sqr(x(i)-x(j))+sqr(y(i)-y(j))));

    Ptx(i,j)$(ord(i)<> ord(j) and ord(i)<>1) = EElec + EAmp*sqr(d(i,j));

    Prx = EElec;

    s(i)$(ord(i)>1)=1000;

    M=100000;
    Lin=1;
    Lout=1;

    Solve minimumBattery using mip maximizing t;
    *------------------------------------------------

    option x :0:0:1; display x;
    option y :0:0:1; display y;

    * the set element labels are identified using their set identifier and the suffix (.tl)
    put Coordinate;
    loop(i,
    put i.tl:4:0 x(i):12:0 y(i):12:0/;
    );

    * Bir degiskening degerini yazdirmak icin (.l) kullaniyoruz
    *----Sonucu "LinearTopology_SingleTopology_Sonuc.txt" dosyasina yaz ---
    put Sonuc;
    put 'Lifetime' tekrar t.l:12:8 /;
    $ontext
    loop(i,
    loop(j,
    put$(f.l(i,j)>0) i.tl:4:0 j.tl:4:0 f.l(i,j):12:3 /;
    );
    );
    $offtext
    put Flow;
    loop(i,
    loop(j,
    put$(f.l(i,j)>0) i.tl:4:0 j.tl:4:0 f.l(i,j):12:3 /;
    );
    );
    );

    ReplyDelete
  2. I suggest to discuss this with your teacher.

    ReplyDelete