xpress04.gms : XPRESS test suite - solution enumerator example

Description

Test the XPRESS solution enumerator - in this case, it should return
the set of all MIP solutions, exactly as computed by
cutting and repeated solves.

Contributor: Steve Dirkse, Jan 2012


Small Model of Type : MIP


Category : GAMS Test library


Main file : xpress04.gms

$title XPRESS test suite - solution enumerator example (XPRESS04,SEQ=550)

$onText
Test the XPRESS solution enumerator - in this case, it should return
the set of all MIP solutions, exactly as computed by
cutting and repeated solves.

Contributor: Steve Dirkse, Jan 2012
$offText

$set GAMSlo %GAMS.lo%
$if %GAMS.ide% == 1 $set GAMSlo 2

$set FLAGS lo=%GAMSlo%
$if %DEMOSIZE% == 1 $set FLAGS --DEMOSIZE=1 %FLAGS%

$if not exist mip05.gms $call testlib -q mip05

* first generate all solutions using GAMS, cuts, and solves in a loop
$call gams mip05.gms mip=xpress %FLAGS%
$if errorlevel 1 $abort Generating solutions with cuts failed
* should have solution info in queensSolsCuts.gdx

* next generate all solutions using the XPRESS MIP solution enumerator
$onEcho > xpress.322
solnpool           queensSolsPool.gdx
solnpoolDupPolicy  0
solnpoolPop        2
* Disable symmetry reductions
symmetry           0

* with XPRESS 26.01 we need to do a little more to get all 92 solutions,
* as described in an email from FICO's Michael Perregaard, May 2014:
*   The controls you should set to prevent the Optimizer from dropping any
*   symmetric or dominated solutions are:
*     In PRESOLVEOPS clear the following bits:
*        0 – singleton column removal
*        3 – dual reductions
*        5 – duplicated column reductions
*     so set PRESOLVEOPS = 438
presolveops        438

*     In PRESOLVEOPS clear the following bits:
*     Disable dual reductions in node-to-node presolving by clearing bit 4
*     of MIPPRESOLVE. That is, set MIPPRESOLVE=-17
mippresolve        -17

*     Disable in-tree presolve by setting TREEPRESOLVE = 0
treepresolve       0
$offEcho
$call gams mip05.gms mip=xpress optfile=322 --SKIPCUTS=1 %FLAGS%
$if errorlevel 1 $abort Generating solutions with XPRESS enumerator failed


* finally read in the GDX files and verify content is the same
set
  cuts        'solutions generated by cutting'
  pool        'solutions generated by enumerator & solnpool'
  p2(pool)
  i           'size of chess board'
  ;
alias(i,j);
alias(pool,ppool);
parameter
  found(cuts)
  solsCuts(cuts,i,j)    'solutions generated by cutting'
  sol(i,j)              'solution generated by enumerator & solnpool'
  tmp(i,j)
  ;
scalars
  nCuts    'number of solutions generated with cuts'
  nPool    'number of solutions generated with enumerator & solnpool'
  done
  ;
binary variable x(i,j)  'square is occupied by a queen';

$gdxIn queensSolsCuts
$load cuts=n i solsCuts=sols
$gdxIn
$gdxIn queensSolsPool
$load pool=index
$gdxIn
nCuts = card(cuts);
nPool = card(pool);
abort$[nPool <> nCuts] 'different number of solutions', nPool, nCuts;

file fpool;
found(cuts) = 0;
x.l(i,j) = 0;
loop{pool,
  p2(ppool) = no;  p2(pool) = yes;
  put_utility fpool 'gdxin' / pool.te(pool);
  execute_loadpoint;
  sol(i,j) = round(x.l(i,j));
  display sol;
* now loop over the solutions from the cut set to find a match
  done = 0;
  loop{cuts$[not done],
    tmp(i,j) = sol(i,j) - solsCuts(cuts,i,j);
    if {(0 eq card(tmp)),
*     we have a match
      abort$[found(cuts)] 'solnpool solution matches already-matched cut solution', p2, sol;
      found(cuts) = 1;
      done = 1;
    };
  };
  abort$[not done] 'solnpool solution not found in solsCuts', p2, sol;
};
abort$[card(found) <> nCuts] 'solution from cuts not found in pool', found;

* for debugging you can skip the cleanup, o/w this test leaves a mess
* $goTo alldone

execute 'rm -f  queensSols*.gdx soln_queens_p*.gdx';

$label alldone