icut.gms : Integer Cut Example

Description

Sometimes it may be required to exclude certain integer solutions.
Additional constraints, called cuts, can be added to exclude such
solutions. To exclude the k'th integer solution we can write:

cut(k).. sum(i, abs(x(i) - xsol(i,k)) =g= 1;

The absolute function has to be simulated using 0/1 variables
and some additional constraints. When the solution to be excluded
is at lower or upper bound, we do not need additional 0/1 variables.

In this example we simply show how to enumerate all possible
combinations of four integer variables.

Reference

• GAMS Development Corporation, Formulation and Language Example.

Small Model of Type : MIP

Category : GAMS Model library

Main file : icut.gms

\$title Integer Cut Example (ICUT,SEQ=160)

\$onText
Sometimes it may be required to exclude certain integer solutions.
Additional constraints, called cuts, can be added to exclude such
solutions. To exclude the k'th integer solution we can write:

cut(k).. sum(i, abs(x(i) - xsol(i,k)) =g= 1;

The absolute function has to be simulated using 0/1 variables
and some additional constraints. When the solution to be excluded
is at lower or upper bound, we do not need additional 0/1 variables.

In this example we simply show how to enumerate all possible
combinations of four integer variables.

GAMS Development Corporation, Formulation and Language Example.

Keywords: mixed integer linear programming, GAMS formulation and language examples,
integer cuts, mathematics
\$offText

\$eolCom //

Set
i        'index on integer variable' / 1*4 /
ie(i)    'variables fixed'
in(i)    'not fixed'
il(i)    'solutions at lower bound'
iu(i)    'solutions at upper bound'
ib(i)    'solution between bounds'
kk       'cut identification set'    / 1*100 /
k(kk)    'dynamic subset of k'
bb(kk,i) 'cut memory'
bl(kk,i) 'cut memory'
bu(kk,i) 'cut memory';

Variable
x(i)    'test variable'
z       'some objective variable'
b(kk,i) 'flip-flop for in between solutions'
u(kk,i) 'changes up'
l(kk,i) 'changes down';

Integer  Variable x;
Binary   Variable b;
Positive Variable u, l;

Equation
cut(kk)     'main cut equations'
cutu(kk,i)  'upper bound limit for inbetween integers'
cutl(kk,i)  'lower bound limit for inbetween integers'
cutul(kk,i) 'definition of positive and negative deviations'
obj         'obj definition';

Parameter
cutrhs(kk)   'cut RHS value'
cutlx(kk,i)  'cut lower bound'
cutux(kk,i)  'cut upper bound'
cuts(kk,i)   'cut solution value'
report(kk,*) 'cut report variable'
whatnext     'loop control variable';

* pick an objective function which will order the solutions
obj..    z =e= sum(i, power(10,card(i) - ord(i))*x(i));

cut(k).. - sum(bu(k,i), x(i)) + sum(bl(k,i),x(i)) + sum(bb(k,i), l(bb) + u(bb)) =g= cutrhs(k);

cutu(bb(k,i))..  u(bb) =l= cutux(bb)*b(bb);

cutl(bb(k,i))..  l(bb) =l= cutlx(bb)*(1 - b(bb));

cutul(bb(k,i)).. x(i)  =e= cuts(bb) + u(bb) - l(bb);

Model enum / all /;

* get an initial solution and set bounds
x.lo(i)   = 2;
x.up(i)   = 4;
x.fx('2') = 3;   // fix one variable
x.up('4') = 3;   // only two values
x.l(i)    = x.lo(i);

k(kk) = no;                        // make cut set empty
ie(i) = yes\$(x.lo(i) = x.up(i));   // find fixed variables
in(i) = yes - ie(i);               // find free variables

whatnext    =  1;  // initial loop control
enum.resUsd =  0;  // inital CPU used
enum.resLim = 60;  // dont spend more than 60 seconds on on problem

* We enumerate all solutions so we are happy with the first solution the solver finds.
enum.optCr = 0;
enum.optCa = 1e06;

loop(kk\$whatnext,
il(in) = yes\$(x.l(in) = x.lo(in));         // find variables at lower
iu(in) = yes\$(x.l(in) = x.up(in));         // find variables at upper
ib(in) = yes - ie(in) - iu(in) - il(in);   // find variables between
k(kk)        = yes;   // add
bl(kk,il)    = yes;   // cut
bu(kk,iu)    = yes;   // information
bb(kk,ib)    = yes;   // as needed
cutux(kk,ib) = x.up(ib) - x.l(ib);
cutlx(kk,ib) = x.l(ib) - x.lo(ib);
cuts(kk,ib)  = x.l(ib);
cutrhs(kk)   = 1 + sum(il, x.l(il)) - sum(iu, x.l(iu));
report(kk,i) = x.l(i);                   // save previous solution
report(kk,'binaries') = card(bb);        // remember binaries
report(kk,'CPU time') = enum.resUsd;     // remember time

solve enum min z using mip;

enum.limCol = 0;                   // turn off
enum.limRow = 0;                   // all
enum.solPrint = %solPrint.Quiet%;  // output
whatnext = enum.modelStat = %modelStat.optimal% or enum.modelStat = %modelStat.integerSolution%;
);

display enum.solveStat, enum.modelStat, report;