ex2.gms : External Equation - Example 2

Description

```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.
```

Small Model of Type : GAMS

Category : GAMS Test library

Main file : ex2.gms

``````\$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'
\$ifi %system.buildcode%==vs8 \$set suf

\$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.buildcode%==deg \$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;
``````
GAMS Development Corp.
GAMS Software GmbH

General Information and Sales
U.S. (+1) 202 342-0180
Europe: (+49) 221 949-9170