sl601.gms : Check correct behavior when using solveLink=6

Description

With GAMS 24.6 a new variant for the SolveLink option and model attribute has
been added. If SolveLink is set to %solveLink.aSyncThreads%, GAMS does not wait
for the solver to return and does not collect the result when a solve statement
is executed. Instead, the model is generated and then passed to the solver in a
separate thread while GAMS continues the execution. This way, multiple models
can be solved in parallel and the results can be collected later.

This is similar to the Grid Facility (SolveLink = %solveLink.asyncGrid%) with
the difference, that the solver does not operate in its own process space but in
a separate thread, which allows efficient in-memory communication between GAMS
and the solver (like it is done with SolveLink = %solveLink.loadLibrary%).
After the solve statement, one can store a handle of the model instance (using
the model attribute mymodel.handle) and use the same functions that are used for
the Grid Facility to collect the solution and deal with the model instance:
HandleCollect(handle), HandleStatus(handle), and HandleDelete(handle).

The new function ReadyCollect(handleParameter [, maxWait]) can be used to wait
until a model is ready to be collected. It can be used for both SolveLink =
%solveLink.aSyncThreads% and SolveLink = %solveLink.asyncGrid%.

In this model the basic functionality is tested.

Keyword: solveLink=%solveLink.aSyncThreads%

Contributor: Lutz Westermann, January 2016


Small Model of Type : GAMS


Category : GAMS Test library


Main file : sl601.gms

$title 'Check correct behavior when using solveLink=%solveLink.aSyncThreads%' (SL601,SEQ=691)

$onText
With GAMS 24.6 a new variant for the SolveLink option and model attribute has
been added. If SolveLink is set to %solveLink.aSyncThreads%, GAMS does not wait
for the solver to return and does not collect the result when a solve statement
is executed. Instead, the model is generated and then passed to the solver in a
separate thread while GAMS continues the execution. This way, multiple models
can be solved in parallel and the results can be collected later.

This is similar to the Grid Facility (SolveLink = %solveLink.asyncGrid%) with
the difference, that the solver does not operate in its own process space but in
a separate thread, which allows efficient in-memory communication between GAMS
and the solver (like it is done with SolveLink = %solveLink.loadLibrary%).
After the solve statement, one can store a handle of the model instance (using
the model attribute mymodel.handle) and use the same functions that are used for
the Grid Facility to collect the solution and deal with the model instance:
HandleCollect(handle), HandleStatus(handle), and HandleDelete(handle).

The new function ReadyCollect(handleParameter [, maxWait]) can be used to wait
until a model is ready to be collected. It can be used for both SolveLink =
%solveLink.aSyncThreads% and SolveLink = %solveLink.asyncGrid%.

In this model the basic functionality is tested.

Keyword: solveLink=%solveLink.aSyncThreads%

Contributor: Lutz Westermann, January 2016
$offText


Sets
     i   canning plants   / seattle, san-diego /
     j   markets          / new-york, chicago, topeka / ;

Parameters
     a(i)  capacity of plant i in cases
       /    seattle     350
            san-diego   600  /
     b(j)  demand at market j in cases
       /    new-york    325
            chicago     300
            topeka      275  / ;

Table d(i,j)  distance in thousands of miles
                  new-york       chicago      topeka
    seattle          2.5           1.7          1.8
    san-diego        2.5           1.8          1.4  ;

Scalar f  freight in dollars per case per thousand miles  /90/ ;

Parameter c(i,j)  transport cost in thousands of dollars per case ;
          c(i,j) = f * d(i,j) / 1000 ;

Variables
     x(i,j)  shipment quantities in cases
     z       total transportation costs in thousands of dollars ;

Positive Variable x ;

Equations
     cost        define objective function
     supply(i)   observe supply limit at plant i
     demand(j)   satisfy demand at market j ;

cost ..        z  =e=  sum((i,j), c(i,j)*x(i,j)) ;
supply(i) ..   sum(j, x(i,j))  =l=  a(i) ;
demand(j) ..   sum(i, x(i,j))  =g=  b(j) ;

Model transport /all/ ;

*Solve model, wait for results, collect result, delete handle and do some checks
$onEcho > SolveWaitCollectDelete.inc
Solve transport using lp minimizing z ;
abort$(ReadyCollect (transport.handle)<>0) 'Problem waiting for model',  transport.handle;
abort$(HandleCollect(transport.handle)<>1) 'Problem collecting results', transport.handle;

abort$(transport.objVal<>153.675) 'wrong objective value';
abort$(z.l<>153.675)              'wrong value for z';

z.l = 0;
* Looks odd, but there was an error, that did not allow this for sl=6
transport.handle = transport.handle;
execute_loadhandle transport;

abort$(HandleDelete (transport.handle)<>0) 'Problem deleteing result',   transport.handle;
$offEcho

* Set solvelink
option solvelink = %solveLink.aSyncThreads%;

* Not every solver works with sl=6, test that the resetting to 3 works if 6 cannot be used
* Select a solver that supports %solveLink.aSyncThreads%
option lp=cplex;
$include SolveWaitCollectDelete.inc
abort$(transport.LinkUsed<>%solveLink.aSyncThreads%) 'sl was reset unexpectedly'

* Select a solver that does not support %solveLink.aSyncThreads%
option lp=minos;
$include SolveWaitCollectDelete.inc
abort$(transport.LinkUsed<>%solveLink.asyncGrid%) 'sl should be reset to %solveLink.asyncGrid%'

* Check return codes of functions
Scalar wrongHandle /111/;
abort$(ReadyCollect(wrongHandle)<>1)  'Expected ReadyCollect to signal that there is no job to wait for';
abort$(HandleStatus(wrongHandle)<>0)  'Expected error return from HandleStatus';
abort$(HandleCollect(wrongHandle)<>0) 'Expected error return from HandleCollect';
abort$(HandleDelete(wrongHandle)<>1)  'Expected error return from HandleDelete';

set       s /s1*s3/;
parameter handles(s);
handles(s)=no;
abort$(ReadyCollect(handles)<>2)  'Expected ReadyCollect to signal that the provided symbol is empty';