embpy07.gms : Test no_match_limit for model instance

Description

With this test we test a model instance with extra updater records and expect
with a sufficiently large no_match_limit to succeed even if the entire updater
has been squeezed out of the model.

Contributor: Michael Bussieck, March 2021

  On the major platforms (Windows, Linux, Mac), GMSPYTHONLIB gets automatically set
  to use the internal Python installation in sysdir/GMSPython.


Small Model of Type : GAMS


Category : GAMS Test library


Main file : embpy07.gms

$Title Test no_match_limit for model instance (embpy07,SEQ=859)

$ontext
With this test we test a model instance with extra updater records and expect
with a sufficiently large no_match_limit to succeed even if the entire updater
has been squeezed out of the model.

Contributor: Michael Bussieck, March 2021
$offtext

* On the major platforms (Windows, Linux, Mac), GMSPYTHONLIB gets automatically set 
* to use the internal Python installation in sysdir/GMSPython.
$if not setEnv GMSPYTHONLIB $abort.noError Embedded code Python not ready to be used
$log --- Using Python library %sysEnv.GMSPYTHONLIB%

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

Parameter
   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;

Parameter pen(*) / #j 999, doesNotExist 999 /, useShort /1/;
Variable
   x(i,j)   'shipment quantities in cases'
   short(j) 'supply slack'
   z        'total transportation costs in thousands of dollars';

Positive Variable x;

Equation
   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)) + sum(j, short(j)*pen(j))$useShort;

supply(i).. sum(j, x(i,j)) =l= a(i);

demand(j).. sum(i, x(i,j)) =g= b(j) - short(j)$useShort;

Model transport / all /;

Set s 'scenarios to run' / base, run1, run2 /;

Table newsupply(s,i) 'updater for a (capacity)'
         seattle  san-diego
   base      350        600
   run1      300        650
   run2      400        550;

Table newdemand(s,j) 'updater for b (demand)'
         new-york  chicago  topeka
   base       325      300     275
   run1       325      300     275
   run2       350      300     250;

$set solverlog
$if set useSolverLog $set solverlog output=sys.stdout
embeddedCode Python:
def solveMI(mi, symIn=[], symOut=[], nomatchlimit=0):
  for sym in symIn:
    gams.db[sym].copy_symbol(mi.sync_db[sym])
  miopt = GamsModelInstanceOpt(no_match_limit = nomatchlimit)
  mi.solve(mi_opt=miopt)
  for sym in symOut:
    try:
      gams.db[sym].clear() # Explicitly clear the symbol to ensure setting "writtenTo" flag for sym
      mi.sync_db[sym].copy_symbol(gams.db[sym])
    except:
      pass
pauseEmbeddedCode
abort$execerror 'Python error. Check the log';

$libInclude pyEmbMI tMI 'transport us lp min z' -all_model_types=cplex a.Zero b.Zero pen.Zero
useShort = 0;
$libInclude pyEmbMI tMInoShort 'transport us lp min z' -all_model_types=cplex a.Zero b.Zero pen.Zero

Parameter repX 'collector for level of x';

loop(s,
   a(i) = newsupply(s,i);
   b(j) = newdemand(s,j);
   continueEmbeddedCode:
   solveMI(tMI,['a','b','pen'],['x'])  # will fail because of additional uel "doesnotexist" in pen
   pauseEmbeddedCode x
);
abort$(execerror=0) 'expect execution errors';
execerror = 0;
loop(s,
   a(i) = newsupply(s,i);
   b(j) = newdemand(s,j);
   continueEmbeddedCode:
   solveMI(tMI,['a','b','pen'],['x'],999)  # nomatchlimit because of additional uel "doesnotexist"
   pauseEmbeddedCode x
   repX('short',s,i,j) = x.l(i,j);
);
abort$(execerror<>0) 'expect no execution errors';

loop(s,
   a(i) = newsupply(s,i);
   b(j) = newdemand(s,j);
   continueEmbeddedCode:
   solveMI(tMInoShort,['a','b','pen'],['x'])  # nomatchlimit because of squeezed out pen
   pauseEmbeddedCode x
);
abort$(execerror=0) 'expect execution errors';
execerror = 0;
loop(s,
   a(i) = newsupply(s,i);
   b(j) = newdemand(s,j);
   continueEmbeddedCode:
   solveMI(tMInoShort,['a','b','pen'],['x'],999)  # nomatchlimit because of squeezed out pen
   pauseEmbeddedCode x
   repX('noshort',s,i,j) = x.l(i,j);
);
abort$(execerror<>0) 'expect no execution errors';

option  repX:0:2:2;
display repX;

Set error(s) 'empty solution';
error(s) = sum((i,j), repX('short',s,i,j)) = 0;
abort$card(error) 'Missing solution (short) for some scenarios', error;
error(s) = sum((i,j), repX('noshort',s,i,j)) = 0;
abort$card(error) 'Missing solution (noshort) for some scenarios', error;