$set stochastic 0
$set erslivestockmodel 1
$ifthen %stochastic%==1
$ ifthen %erslivestockmodel%==1
b(i,"Exports",k) = tempbx(k);
b(i,"Season Average Price",k) = tempbp(k);
b(i,"Feed Use",k) = tempbdf(k);
b(i,"Food",k) = tempbdi(k);
cfixed(i,"Exports",k) = 0;
cfixed(i,"Season Average Price",k) = 0;
cfixed(i,"Feed Use",k) = 0;
cfixed(i,"Food",k) = 0;
$ else
$ include grains.inc
$ endif
$endif
This does not work as nesting is not allowed. You don't get an error message either indicating nesting is not allowed. In some cases you may get a possibly misleading error message, in the worst case it just behaves incorrectly. The documentation in the McCarl User Guide does not mention this limitation. Looks like $ifthen will be less useful in practice than I had hoped.
The workaround is to use a run-time if statement:
$set stochastic 0
$set erslivestockmodel 1
scalars
stochastic /%stochastic%/
erslivestockmodel /%erslivestockmodel%/
;
if(stochastic=1,
if(erslivestockmodel=1,
b(i,"Exports",k) = tempbx(k);
b(i,"Season Average Price",k) = tempbp(k);
b(i,"Feed Use",k) = tempbdf(k);
b(i,"Food",k) = tempbdi(k);
cfixed(i,"Exports",k) = 0;
cfixed(i,"Season Average Price",k) = 0;
cfixed(i,"Feed Use",k) = 0;
cfixed(i,"Food",k) = 0;
else
$ include grains.inc
);
);
This has additional advantages: all branches are syntax-checked even if they are not executed, and we check the type of the parameters using the scalar initializations. Of course we lose some of the compile time features using this approach.
Another workaround would be to place the inner $ifthen in an include file:
$set stochastic 0Conclusion: GAMS users be aware when using nested $ifthen constructs. They are not implemented (correctly) and no error message is produced to warn you about this.
$set erslivestockmodel 1
$ifthen %stochastic%==1
$include gamsbugworkaround.inc
$endif
Hi Erwin,
ReplyDeleteYour first "workaround" is the only way I would think to do it. Can you share what are the "compile time features" you mention that would make your first attempt more interesting to you? Thanks!
When using if(condition,) compared to $ifthen you need to realize if(cond,) is executed at execution time.
ReplyDeleteE.g.
if(condition,
$include xxx.inc
);
will always include the file xxx.inc, even if condition=false.
Another example:
if(condition,
parameter p;
p = 1;
);
is not allowed, as the declaration is compile time.
Erwin
One more example. Suppose you want to $set another thing inside, then this will not work:
ReplyDeleteif(1,
$set name "hello"
else
$set name "world"
);
display "%name%";
This will display world instead of the expected hello.
I see your point.
ReplyDeleteI've never used these compile time conditionals but I can imagine situations in which they might be useful. Specially when used with $include
Thanks.