$title External Equation - Example 2 (EX2,SEQ=565) $offSymList offsymxref $onText This is the second in a sequence of examples that show how to use the external equations (=X=) facility with GAMS/CONOPT. The second model is also simple unconstrained quadratic model and the quadratic function is defined in an external equation. But this time we communicate the data from GAMS via a put file including information on the size of the model. We can now change the data in GAMS without reprogramming the Fortran or C routine. The model is slightly convoluted. We want to be able to solve it for different subsets I of the Domain D. $offText set D Domain for the variables / i1*i14 /; set I(D) Subset for actual optimization; alias (D,E), (i,j); Parameter Q(D,D) Covariance Matrix X0(D) Targets; Q(D,E) = power(0.5, abs(ord(D)-ord(E)) ); X0(D) = ord(D) / card(D); display Q, x0; variable x(D), z; equation zdef, zdefX; * Define I for the first solve to hold 7 elements I(D) = yes$(ord(D) le 7); * The desired equation, implemented in GAMS, is zdef.. sum {(i,j), (x(i)-x0(i)) * Q(i,j) * (x(j)-x0(j)) } =e= z; * It is implemented as an external equation as: zdefX.. sum {D$I(D), ord(D)*x(D) } + (card(I)+1)* z =X= 1; $onText See the comments in ex1.gms for further details. We use D instead of I in the equation since I is now a dynamic set and we cannot use ord(I). The size of the set I and the model data is now written to the file ex2.put using PUT statements. Note that we end with a putclose statement so the file is closed when we read it in the external module. $offText file f / ex2.put /; f.nw = 0; f.nd = 13; f.nr = 0; put f card(i):0:0 /; f.nr = 2; loop {i, put x0(i) /; loop {j, put q(i,j) /; }; }; putclose f; $ set pre $ifI %system.filesys%==unix $set pre 'lib' $ set suf '64' $set N ex2 $set c_cbN %pre%%N%c_cb%suf% $set d_cbN %pre%%N%d_cb%suf% $set f_cbN %pre%%N%f_cb%suf% model %N% 'GAMS implementation' / zdef /; model %c_cbN% 'External equations in C, with callbacks' / zdefX /; model %d_cbN% 'External equations in Delphi with callbacks' / zdefX /; model %f_cbN% 'External equations in F77, with callbacks' / zdefX /; option limcol = 0; $onText Create a summary table where we compare the expected results, x0 with the actual results, x.l, to ensure that data have been communicated correctly to the external equation. $offText parameter report(*,*,*) 'Solution Summary'; option report:5; scalar totdist /0/; * reuse the same code several times $onEchoV > runme.gms z.l = 0; z.m = 0; x.l(i) = 0; x.m(i) = 0; zdef.l = 0; zdef.m = 0; solve %1 using nlp minimizing z; abort$(%1.solvestat %2) 'problems running model %1'; execerror = 0; report('Solve ','Stat', '%1') = %1.solvestat; report('Model ','Stat', '%1') = %1.modelstat; report(i,'Target', '%1') = x0(i); report(i,'Value', '%1') = x.l(i); report(i,'Distance','%1') = abs(x.l(i) - x0(i)); totdist = totdist + sum(i,abs(x.l(i) - x0(i))); $offEcho $ set ext '.dll' $ifI %system.filesys%==unix $set ext '.so' $ifI %system.platform%==dex $set ext '.dylib' $ifI %system.platform%==dax $set ext '.dylib' $ set eq $ifI %system.filesys%==unix $set eq "'" $if set runall $set runC_cb '1' set runD_cb '1' set runF_cb '1' $ifThen not set nocomp $ ifI set runC_cb $call gams complink lo=%gams.lo% --lang=c --files=ex2c_cb.c --libname=%c_cbN%%ext% $ if errorlevel 1 $abort Error compiling C Library $ ifI set runD_cb $call gams complink lo=%gams.lo% --lang=Delphi --files=ex2d_cb.dpr $ if errorlevel 1 $abort Error compiling Delphi Library $ ifI set runF_cb $call gams complink lo=%gams.lo% --lang=fortran90 --files=%eq%"gehelper.f90 msg2_f.f90 ex2f_cb.f90"%eq% --libname=%f_cbN%%ext% $ if errorlevel 1 $abort Error compiling Fortran90 Library $endIf $ batInclude runme %N% '<> 1' $if set runC_cb $batInclude runme %c_cbN% '<> 1' $if set runD_cb $batInclude runme %d_cbN% '<> 1' $if set runF_cb $batInclude runme %f_cbN% '<> 1' display report; if ((totdist < 1.0E-6), display "@@@@ #Test passed."; else abort totdist, "@@@@ #Test not passed. Inspect ex2.lst for details."; ); $onText Now define I to hold all 14 elements. This should give rise to an error since we have only allocated space for 10 elements in the Fortran and Delphi routine. The C-version allocates memory dynamically and will work correctly. $offText I(D) = yes; $onText When we open the PUT file again for writing it will by default be overwritten, which is what we need: $offText * start over with new data and empty report f.nr = 0; put f card(i):0:0 /; f.nr = 2; loop {i, put x0(i) /; loop {j, put q(i,j) /; }; }; putclose f; option clear = report; totdist = 0; $ batInclude runme %N% '<> 1' $if set runC_cb $batInclude runme %c_cbN% '<> 1' $if set runD_cb $batInclude runme %d_cbN% ' = 1' $if set runF_cb $batInclude runme %f_cbN% ' = 1' display report;