$title XPRESS test suite - solution enumerator example (XPRESS05,SEQ=554) $onText Test the XPRESS solution enumerator. To test we use a variant of the dice model (adjusted to avoid multiple representations of the same solution). The test model is a maximization having 15 solutions with obj=21, 794 solutions with obj=20, and plenty of solutions with obj=19. We test a number of things: 1. Return all optimal solutions (i.e. obj = 21) 2. Return all solutions with obj = 20 or 21 3. Return the 15 best solutions 4. Return the 16 best solutions 5. Return the 150 best solutions 6. Return the 900 best solutions 7. Return first 20 solutions with obj 20 or 21 8. Return first 200 solutions with obj >= 18 Contributor: Steve Dirkse, Jan 2012 $offText $ifThen %DEMOSIZE% == 1 $ log This test is too big to run in demo mode: exiting $ abort.noError $endIf $if not exist mip06.gms $call testlib -q mip06 $onEcho > poolObj.gms * read in solutions and compute their objectives set pool 'solutions generated' p2(pool) d 'number of dice' f 'die faces' v 'face values' map(d,f,v) 'maps dice faces to values' win(d,f,f) 'true if faceVal(d,f) beats faceVal(d++,fp)' ; alias(f,fp),(d,dp); parameter obj(pool) faceVal(d,f) 'value on die face - will be integer' vals(v) 'possible face values' chk(v) ; scalar ok / 0 /; binary variables mapv(d,f,v) 'maps dice faces to values' ; $gdxIn diceDef $load f d v vals $gdxIn $gdxIn %INFILE% $load pool=index $gdxIn execute_unload '%OUTFILE%', ok; ok = 525; file fpool; loop{pool, p2(pool) = no; p2(pool) = yes; put_utility fpool 'gdxin' / pool.te(pool); execute_loadpoint mapv=map; map(d,f,v) = round(mapv.l(d,f,v)); display map; chk(v) = 1 - sum{map(d,f,v), 1}; abort$card(chk) 'bad map', chk, map; faceVal(d,f) = sum{map(d,f,v), vals(v)}; win(d,f,fp) = [faceVal(d,f) > faceVal(d++1,fp) + 0.5]; obj(pool) = smin{d, sum{win(d,f,fp), 1}}; }; execute_unload '%OUTFILE%', ok, pool, obj; $offEcho sets pool 'possible solutions' / file1*file999 / p(pool) ; parameter obj(pool) chk(pool) ; scalar cnt; * ------------------------------------------------------------------------- * 1. Return all optimal solutions (i.e. obj = 21) $onEcho > xpress.101 solnpool diceSols101.gdx solnpoolPrefix test101 solnpoolDupPolicy 3 solnpoolPop 2 solnpoolVerbosity 2 mipabscutoff 20.5 * by default, the pool has a very large capacity $offEcho $call gams mip06.gms mip=xpress optfile=101 --SKIPCUTS=1 lo=%GAMS.lo% $if errorlevel 1 $abort Generating solutions for run 101 with XPRESS enumerator failed $call gams poolObj.gms --infile=diceSols101 --outfile=diceObjs101 lo=%GAMS.lo% $if errorlevel 1 $abort Computing/checking objectives failed p(pool) = no; obj(pool) = 0; chk(pool) = 0; execute_load 'diceObjs101', p=pool, obj; abort$[card(p) <> 15] 'test 101: should have 15 solutions of 21', p, obj; chk(p) = obj(p) - 21; abort$[card(chk)] 'test 101: should have 15 solutions of 21', chk, p, obj; * ------------------------------------------------------------------------- * 2. Return all solutions with obj = 20 or 21 $onEcho > xpress.102 solnpool diceSols102.gdx solnpoolPrefix test102 solnpoolDupPolicy 3 solnpoolPop 2 solnpoolVerbosity 2 mipabscutoff 19.5 * by default, the pool has a very large capacity $offEcho $call gams mip06.gms mip=xpress optfile=102 --SKIPCUTS=1 lo=%GAMS.lo% $if errorlevel 1 $abort Generating solutions for run 102 with XPRESS enumerator failed $call gams poolObj.gms --infile=diceSols102 --outfile=diceObjs102 lo=%GAMS.lo% $if errorlevel 1 $abort Computing/checking objectives failed * expect 809 sols: 15 with obj=21, 794 with obj=20 p(pool) = no; obj(pool) = 0; chk(pool) = 0; execute_load 'diceObjs102', p=pool, obj; abort$[card(p) <> 809] 'test 102: should have 809 solutions', p, obj; cnt = sum{p$[obj(p) = 21], 1}; abort$[cnt <> 15] 'test 102: should have 15 solutions of 21', cnt, p, obj; cnt = sum{p$[obj(p) = 20], 1}; abort$[cnt <> 794] 'test 102: should have 794 solutions of 20', cnt, p, obj; * ------------------------------------------------------------------------- * 3. Return the 15 best solutions $onEcho > xpress.103 * return the 15 best solutions * this is the default behavior if you have a fixed capacity solnpoolCapacity 15 solnpool diceSols103.gdx solnpoolPrefix test103 solnpoolDupPolicy 3 solnpoolPop 2 solnpoolVerbosity 2 $offEcho $call gams mip06.gms mip=xpress optfile=103 --SKIPCUTS=1 lo=%GAMS.lo% $if errorlevel 1 $abort Generating solutions for run 103 with XPRESS enumerator failed $call gams poolObj.gms --infile=diceSols103 --outfile=diceObjs103 lo=%GAMS.lo% $if errorlevel 1 $abort Computing/checking objectives failed * expect 15 sols with obj=21 p(pool) = no; obj(pool) = 0; chk(pool) = 0; execute_load 'diceObjs103', p=pool, obj; abort$[card(p) <> 15] 'test 103: should have 15 solutions of 21', p, obj; cnt = sum{p$[obj(p) = 21], 1}; abort$[cnt <> 15] 'test 103: should have 15 solutions of 21', cnt, p, obj; * ------------------------------------------------------------------------- * 4. Return the 16 best solutions $onEcho > xpress.104 * return the 16 best solutions * this is the default behavior if you have a fixed capacity solnpoolCapacity 16 solnpool diceSols104.gdx solnpoolPrefix test104 solnpoolDupPolicy 3 solnpoolPop 2 solnpoolVerbosity 2 $offEcho $call gams mip06.gms mip=xpress optfile=104 --SKIPCUTS=1 lo=%GAMS.lo% $if errorlevel 1 $abort Generating solutions for run 104 with XPRESS enumerator failed $call gams poolObj.gms --infile=diceSols104 --outfile=diceObjs104 lo=%GAMS.lo% $if errorlevel 1 $abort Computing/checking objectives failed * expect 15 sols with obj=21, 1 with obj=20 p(pool) = no; obj(pool) = 0; chk(pool) = 0; execute_load 'diceObjs104', p=pool, obj; abort$[card(p) <> 16] 'test 104: should have 16 solutions', p, obj; cnt = sum{p$[obj(p) = 21], 1}; abort$[cnt <> 15] 'test 104: should have 15 solutions of 21', cnt, p, obj; cnt = sum{p$[obj(p) = 20], 1}; abort$[cnt <> 1] 'test 104: should have 1 solution of 20', cnt, p, obj; * ------------------------------------------------------------------------- * 5. Return the 150 best solutions $onEcho > xpress.105 * return the 150 best solutions * this is the default behavior if you have a fixed capacity solnpoolCapacity 150 solnpool diceSols105.gdx solnpoolPrefix test105 solnpoolDupPolicy 3 solnpoolPop 2 solnpoolVerbosity 2 $offEcho $call gams mip06.gms mip=xpress optfile=105 --SKIPCUTS=1 lo=%GAMS.lo% $if errorlevel 1 $abort Generating solutions for run 105 with XPRESS enumerator failed $call gams poolObj.gms --infile=diceSols105 --outfile=diceObjs105 lo=%GAMS.lo% $if errorlevel 1 $abort Computing/checking objectives failed * expect 15 sols with obj=21, 135 with obj=20 p(pool) = no; obj(pool) = 0; chk(pool) = 0; execute_load 'diceObjs105', p=pool, obj; abort$[card(p) <> 150] 'test 105: should have 150 solutions', p, obj; cnt = sum{p$[obj(p) = 21], 1}; abort$[cnt <> 15] 'test 105: should have 15 solutions of 21', cnt, p, obj; cnt = sum{p$[obj(p) = 20], 1}; abort$[cnt <> 135] 'test 105: should have 135 solutions of 20', cnt, p, obj; * ------------------------------------------------------------------------- * 6. Return the 900 best solutions $onEcho > xpress.106 * return the 900 best solutions * this is the default behavior if you have a fixed capacity solnpoolCapacity 900 solnpool diceSols106.gdx solnpoolPrefix test106 solnpoolDupPolicy 3 solnpoolPop 2 solnpoolVerbosity 2 $offEcho $call gams mip06.gms mip=xpress optfile=106 --SKIPCUTS=1 lo=%GAMS.lo% $if errorlevel 1 $abort Generating solutions for run 106 with XPRESS enumerator failed $call gams poolObj.gms --infile=diceSols106 --outfile=diceObjs106 lo=%GAMS.lo% $if errorlevel 1 $abort Computing/checking objectives failed * expect 15 sols with obj=21, 794 with obj=20, and 91 with obj=19 p(pool) = no; obj(pool) = 0; chk(pool) = 0; execute_load 'diceObjs106', p=pool, obj; abort$[card(p) <> 900] 'test 106: should have 900 solutions', p, obj; cnt = sum{p$[obj(p) = 21], 1}; abort$[cnt <> 15] 'test 106: should have 15 solutions of 21', cnt, p, obj; cnt = sum{p$[obj(p) = 20], 1}; abort$[cnt <> 794] 'test 106: should have 794 solutions of 20', cnt, p, obj; cnt = sum{p$[obj(p) = 19], 1}; abort$[cnt <> 91] 'test 106: should have 91 solutions of 19', cnt, p, obj; * ------------------------------------------------------------------------- * 7. Return first 20 solutions with obj 20 or 21 $onEcho > xpress.107 * return the first 20 solutions with obj >= 20 * setting cullRounds = 0 stops enumeration as soon as the pool is full mipabscutoff 19.5 solnpoolCapacity 20 solnPoolCullRounds 0 solnpool diceSols107.gdx solnpoolPrefix test107 solnpoolDupPolicy 3 solnpoolPop 2 solnpoolVerbosity 2 $offEcho $call gams mip06.gms mip=xpress optfile=107 --SKIPCUTS=1 lo=%GAMS.lo% $if errorlevel 1 $abort Generating solutions for run 107 with XPRESS enumerator failed $call gams poolObj.gms --infile=diceSols107 --outfile=diceObjs107 lo=%GAMS.lo% $if errorlevel 1 $abort Computing/checking objectives failed * expect 20 sols with obj >= 20 p(pool) = no; obj(pool) = 0; chk(pool) = 0; execute_load 'diceObjs107', p=pool, obj; abort$[card(p) <> 20] 'test 107: should have 20 solutions', p, obj; * abort$[card(p) > 11] 'test 107: should have 10 (maybe 11) solutions', p, obj; chk(p) = [obj(p) < 20]; abort$[card(chk)] 'test 107: should have 20 solutions with obj >= 20', chk, p, obj; * ------------------------------------------------------------------------- * 8. Return first 200 solutions with obj >= 18 $onEcho > xpress.108 * return the first 200 solutions with obj >= 18 * setting cullRounds = 0 stops enumeration as soon as the pool is full mipabscutoff 17.5 solnpoolCapacity 200 solnPoolCullRounds 0 solnpool diceSols108.gdx solnpoolPrefix test108 solnpoolDupPolicy 3 solnpoolPop 2 solnpoolVerbosity 2 $offEcho $call gams mip06.gms mip=xpress optfile=108 --SKIPCUTS=1 lo=%GAMS.lo% $if errorlevel 1 $abort Generating solutions for run 108 with XPRESS enumerator failed $call gams poolObj.gms --infile=diceSols108 --outfile=diceObjs108 lo=%GAMS.lo% $if errorlevel 1 $abort Computing/checking objectives failed * expect 200 sols with obj >= 18 p(pool) = no; obj(pool) = 0; chk(pool) = 0; execute_load 'diceObjs108', p=pool, obj; abort$[card(p) <> 200] 'test 108: should have 200 solutions', p, obj; chk(p) = [obj(p) < 18]; abort$[card(chk)] 'test 108: should have 200 solutions with obj >= 18', chk, p, obj; * ------------------------------------------------------------------------- * for debugging you can skip the cleanup, o/w this test leaves a mess * $goTo alldone execute 'rm -f xpress.10?'; execute 'rm -f test10?_dice_p*.gdx'; execute 'rm -f diceDef.gdx diceSols10?.gdx diceObjs10?.gdx'; $label alldone