|
<< Click to Display Table of Contents >> GAMS details |
![]() ![]()
|
Gekko implements syntax that resembles GAMS, in order to facilitate interoperability between the two languages. This section will be augmented, for now only the basics are described.
Translate from GAMS to Gekko
When using MODEL<gms>, Gekko will try to translate the raw (unfolded) GAMS equations into equivalent Gekko statements. The translated equations are shown when using e.g. DISP or DECOMP.
But you may also use this translator more interactively. Simply mark some GAMS code (statement or equation) in your editor, copy it (Ctrl+C), and then in the Gekko main window right-click and select Paste special followed by Paste GAMS --> Gekko. For instance, if the GAMS code is y(i, t) = sum(i, x(i, j, t)), Gekko will paste the corresponding Gekko code y[#i] = sum(#i, x[#i, #j]).
Using a GAMS scalar model
The above-mentioned translation from GAMS to Gekko was straightforward enough, but GAMS statement or equation syntax may become complicated, and for performance reasons, and to ensure that the "true" GAMS equations are used, Gekko offers to use a so-called GAMS scalar model as an interface between GAMS and Gekko. See more about GAMS scalar models under MODEL.
Getting GAMS to produce a scalar model is in principle easy. If you have, for instance, the GAMS statement solve mymodel using mcp;, (solving the model mymodel with the solver MCP), you may simply add this line just before the solve statement: option mcp = convert;. Then, instead of solving the model, GAMS will output two files gams.gms and dict.txt. These files contain the scalar model that Gekko can use for SIM<res>, DECOMP and other things (the files need to be zipped into for instance mymodel.zip, followed by a model <gms> mymodel.zip; in Gekko). Inside mymodel.zip, you may also add a file raw.gms, containing the 'raw' GAMS equations).
The problem with .holdfixed = 1 and exogenous variables
If you are using the GAMS option .holdfixed = 1, exogenous variables will not show up in the scalar equations in the form of variables, but in the form of hard-coded numbers. Therefore, set .holdfixed = 0 before producing the scalar model. This may render the model non-square (# equations and # variables does not match), and if so, GAMS will refuse to produce the scalar model. The following shows a way of mitigating that problem, using GAMS + embedded Python. The example uses the CNS solver and its particular "must be square" error message.
In GAMS first run squarefix1.gms, then run squarefix2.gms. This should produce the files gams.gms and dict.txt. Activate the other equations in squarefix_eqs.gms, and that should work, too. (Using maxExecError in this setup may not be strictly necessary).
squarefix_eqs.gms
* === Too many variables, too few equations ===
* equation e1, e2, e3;
* variable x1, x2, x3, x4;
* e1 .. x1 + x2 + x3 =e= 6;
* e2 .. x1 + 2*x2 + x3 =e= 8;
* e3 .. x3 =e= 2 + x4;
* model m / e1, e2, e3 /;
* === Too many equations, too few variables ===
equation e1, e2, e3;
variable x1, x2, x3;
e1 .. x1 + x2 + x3 =e= 6;
e2 .. x1 + 2*x2 + x3 =e= 8;
e3 .. x3 =e= 2;
model m / e1, e2, e3 /;
x3.fx = 2;
squarefix1.gms
* The model is expected to have name m
$include squarefix_eqs.gms
* This is expected to fail
maxExecError = 100;
option cns = convert;
model temp / m /;
temp.holdfixed = 0;
solve temp using cns;
execerror = 0;
squarefix2.gms
* The model is expected to have name 'm',
* the .lst file the name 'squarefix1.lst',
$include squarefix_eqs.gms
* --- Gets rows minus columns = the number of redundant equations
scalar n_extra;
embeddedCode Python:
import os
filename = "squarefix1.lst"
extra = 0
b = False
with open(filename, "r") as s:
for line in s:
if (b):
m = line.split(" ")
extra = int(m[3]) - int(m[7])
break
if (line.strip() == "**** ERROR: CNS models must be square"):
b = True
gams.set('n_extra', [extra])
if os.path.exists("gams.gms"):
os.remove("gams.gms")
if os.path.exists("dict.txt"):
os.remove("dict.txt")
endEmbeddedCode n_extra
* --- If n_extra is negative, there are too few equations.
* --- If n_extra is positive, there are too few variables.
* --- This is handled by either adding more (irrelevant) equations, or
* --- adding an equation with a sum of (irrelevant) variables.
set super_temp / 1*1000000 /;
set dyn_temp1(super_temp);
set dyn_temp2(super_temp);
dyn_temp1(super_temp) = ord(super_temp) <= max(0, 1 - round(n_extra));
dyn_temp2(super_temp) = ord(super_temp) <= max(0, round(n_extra) + 1);
variable x_temp1;
variable x_temp2[super_temp];
equation e_temp1[super_temp];
equation e_temp2;
e_temp1[super_temp] $ dyn_temp1(super_temp) .. 1 =e= x_temp1;
e_temp2 .. sum(super_temp $ dyn_temp2(super_temp), x_temp2[super_temp]) =e= 0;
model temp / m, e_temp1, e_temp2 /;
temp.holdfixed = 0;
option cns = convert;
solve temp using cns;