Sunday, January 10, 2010

GAMS: ifthen

An exogenous condition in an ifthen function can be removed during model generation. In this case only one of the branches need to be passed on to the solver. However this does not always happen:

set i /i1,i2/;
parameter a(i) /
  
i1 1
  
i2 NA
/;

variable y,x(i);
equation e1,e(i);

e1.. y =e= 10;
* this one works ok:
e(i).. x(i) =e= ifthen(a(i)<>
na,a(i),-1);
* this one does not:
*e(i).. x(i) =e= ifthen(a(i)<>na,a(i),sqr(y));

model m/all/;
solve m using cns;

In the first case GAMS will generate a block of simple equations just as we would expect:

---- e  =E= 

e(i1)..  x(i1) =E= 1 ; (LHS = 0, INFES = 1 ****)
e(i2)..  x(i2) =E= -1 ; (LHS = 0, INFES = 1 ****)

However in the second case the exogenous condition is actually passed on to the solver. This leads to:

---- e  =E= 

e(i1)..  (0)*y + x(i1) =E= 0 ; (LHS = -1, INFES = 1 ****)
e(i2)..  (0)*y + x(i2) =E= 0 ; (LHS = 0)

For i1 we would expect the same result as before: x(i1) =e= 1; In this case it really generates a nonlinear if-then-else construct. The condition uses NA, and that results in an error:

**** Exec Error at line 14: A constant in a nonlinear expression in equation e evaluated to NA

This caused some problems for me in some generated code where I translate Excel formulas to GAMS equations. A possible work-around is to check for myself if the condition is exogenous (i.e. does not depend on the level of a variable) and then to generate:

e(i).. x(i) =e= a(i)$(a(i)<>na) + sqr(y)$(a(i)=na);