Sunday, February 7, 2010

GAMS: EPS in nonlinear equations

In GAMS the special value EPS is to be considered as zero when evaluated numerically. There may be an issue when some data has the value EPS and this data is part of a nonlinear equation. My intuition said: no problem consider it as a zero in model generation. But this is not actually what is happening:

scalar
  d 
/EPS/
*  d  /0/
;


variable
  x1,x2
  y1,y2
  dummy
;

* initial values
  x1.L=0;
  x2.L=1200;
  y1.L=2338.1350485176;
  y2.L=2671.64029257648;


equation
   e,edummy;

e.. x1 =e= x2*(y2/y1-1)*d ;

edummy.. dummy =e= 0;

model m /all/;
option nlp=conopt,iterlim=0;
solve m using nlp minimizing dummy;

This should generate e.. x1=e=0; but it does not. The listing file is showing very strange things:

---- e  =E= 

e..  x1 + (EPS)*x2 + (EPS)*y1 + (EPS)*y2 =E= 0 ; (LHS = EPS)




                           LOWER          LEVEL          UPPER         MARGINAL

---- EQU e                   .          -171.1647          .             EPS    INFES

I.e. GAMS does not get rid of the EPS, actually the partial derivatives are evaluated to EPS which is strange. Secondly GAMS considers this equation feasible at the initial point, but CONOPT does not. When it evaluates the equation at the initial point it says it is infeasible by 171.16747. It looks like something is really wrong here.

When we look at what Convert generates:

Variables  x1,x2,x3,x4,x5;

Equations  e1,e2;

e1.. -(-1 + x4/x3)*x2 + x1 =E= 0;

e2..    x5 =E= 0;

we see that the multiplication by d is dropped. This does not look correct to me, and potentially a serious problem. I start to suspect that wrong code is being generated here by GAMS.

This is not an issue for 99.99% of the models as they have no EPS values residing in the data. I used it to flag that this data came from empty cells in a spreadsheet, so I could distinguish them from zero in certain operations.

As this is generated code by a tool that translates Excel formulas, I can easily generate the following as work around:

e.. x1 =e= x2*(y2/y1-1)*(d$(d<>0)) ;

When this is done for all references to data this looks really ugly but at least this will make sure the correct function evaluation code is generated. In GAMS the condition $d<>0 will evaluate to false for d=EPS.