Description
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 Compared to xpress05, we read the solution from the merged solution pool file rather than from individual point files. Contributor: Michael Bussieck/Steve Dirkse, May 2013
Small Model of Type : MIP
Category : GAMS Test library
Main file : xpress06.gms
$title XPRESS test suite - solution enumerator example with solnPoolMerge (XPRESS06,SEQ=612)
$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
Compared to xpress05, we read the solution from the merged solution pool
file rather than from individual point files.
Contributor: Michael Bussieck/Steve Dirkse, May 2013
$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'
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 /;
Parameter
mapv(pool,d,f,v) 'maps dice faces to values'
;
$gdxIn diceDef
$load f d v vals
$gdxIn
$gdxIn %INFILE%
$load pool=index mapv=map
$gdxIn
execute_unload '%OUTFILE%', ok;
ok = 525;
loop{pool,
map(d,f,v) = round(mapv(pool,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' /
test101_dice_p1*test101_dice_p999,
test102_dice_p1*test102_dice_p999,
test103_dice_p1*test103_dice_p999,
test104_dice_p1*test104_dice_p999,
test105_dice_p1*test105_dice_p999,
test106_dice_p1*test106_dice_p999,
test107_dice_p1*test107_dice_p999,
test108_dice_p1*test108_dice_p999
/
p(pool)
;
parameter
obj(pool)
chk(pool)
;
scalar cnt;
* -------------------------------------------------------------------------
* 1. Return all optimal solutions (i.e. obj = 21)
$onEcho > xpress.101
solnpoolMerge 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
solnpoolMerge 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
solnpoolMerge 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
solnpoolMerge 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
solnpoolMerge 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
solnpoolMerge 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 10 solutions with obj >= 20
* setting cullRounds = 0 stops enumeration as soon as the pool is full
mipabscutoff 19.5
solnpoolCapacity 20
solnPoolCullRounds 0
solnpoolMerge 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;
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
solnpoolMerge 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 diceDef.gdx diceSols10?.gdx diceObjs10?.gdx';
$label alldone