The predicates bb_inf/3, bb_inf/5
implement a simple
Branch and Bound search algorithm for Mixed Integer Linear (MIP) Optimization
examples. Serious MIP is not trivial. The implementation
library('clpqr/bb.pl')
is to be understood as a starting point
for more ambitious users who need control over branching, or who
want to add cutting planes, for example.
Anyway, here is a small problem from miplib, a collection of MIP models, housed at Rice University:
NAME: flugpl ROWS: 18 COLUMNS: 18 INTEGER: 11 NONZERO: 46 BEST SOLN: 1201500 (opt) LP SOLN: 1167185.73 SOURCE: Harvey M. Wagner John W. Gregory (Cray Research) E. Andrew Boyd (Rice University) APPLICATION: airline model COMMENTS: no integer variables are binary
% % from file: library('clpqr/examples/mip') % example(flugpl, Obj, Vs, Ints, []) :- Vs = [ Anm1,Anm2,Anm3,Anm4,Anm5,Anm6, Stm1,Stm2,Stm3,Stm4,Stm5,Stm6, UE1,UE2,UE3,UE4,UE5,UE6], Ints = [Stm6, Stm5, Stm4, Stm3, Stm2, Anm6, Anm5, Anm4, Anm3, Anm2, Anm1], Obj = 2700*Stm1 + 1500*Anm1 + 30*UE1 + 2700*Stm2 + 1500*Anm2 + 30*UE2 + 2700*Stm3 + 1500*Anm3 + 30*UE3 + 2700*Stm4 + 1500*Anm4 + 30*UE4 + 2700*Stm5 + 1500*Anm5 + 30*UE5 + 2700*Stm6 + 1500*Anm6 + 30*UE6, allpos(Vs), { Stm1 = 60, 0.9*Stm1 +1*Anm1 -1*Stm2 = 0, 0.9*Stm2 +1*Anm2 -1*Stm3 = 0, 0.9*Stm3 +1*Anm3 -1*Stm4 = 0, 0.9*Stm4 +1*Anm4 -1*Stm5 = 0, 0.9*Stm5 +1*Anm5 -1*Stm6 = 0, 150*Stm1 -100*Anm1 +1*UE1 >= 8000, 150*Stm2 -100*Anm2 +1*UE2 >= 9000, 150*Stm3 -100*Anm3 +1*UE3 >= 8000, 150*Stm4 -100*Anm4 +1*UE4 >= 10000, 150*Stm5 -100*Anm5 +1*UE5 >= 9000, 150*Stm6 -100*Anm6 +1*UE6 >= 12000, -20*Stm1 +1*UE1 =< 0, -20*Stm2 +1*UE2 =< 0, -20*Stm3 +1*UE3 =< 0, -20*Stm4 +1*UE4 =< 0, -20*Stm5 +1*UE5 =< 0, -20*Stm6 +1*UE6 =< 0, Anm1 =< 18, 57 =< Stm2, Stm2 =< 75, Anm2 =< 18, 57 =< Stm3, Stm3 =< 75, Anm3 =< 18, 57 =< Stm4, Stm4 =< 75, Anm4 =< 18, 57 =< Stm5, Stm5 =< 75, Anm5 =< 18, 57 =< Stm6, Stm6 =< 75, Anm6 =< 18 }. allpos([]). allpos([X|Xs]) :- {X >= 0}, allpos(Xs).
We can first check whether the relaxed problem has indeed the quoted infimum:
clp(r) ?- example(flugpl, Obj, _, _, _), inf(Obj, Inf). Inf = 1167185.7255923203
Computing the infimum under the additional constraints that Stm6
,
Stm5
, Stm4
, Stm3
, Stm2
, Anm6
,
Anm5
, Anm4
, Anm3
, Anm2
, Anm1
assume
integer values at the infimum is computationally harder, but the query
does not change much:
clp(r) ?- example(flugpl, Obj, _, Ints, _), bb_inf(Ints, Obj, Inf, Vertex, 0.001). Inf = 1201500.0000000005, Vertex = [75.0,70.0,70.0,60.0,60.0,0.0,12.0,7.0,16.0,6.0,6.0]