table_constraint
table_constraint |
Purpose
This constraint can be used to propagate a user-defined constraint over n variables defined through a list of valid tuples (its propagation is based on the GAC2001 algorithm (cf.
[Bes01]).
Synopsis
function table_constraint(vars:array of cpvar, tuple:array) : cpctr
function table_constraint(vars:array of cpvar, tuple:set) : cpctr
function table_constraint(vars:cpvarlist, tuple:array) : cpctr
function table_constraint(vars:cpvarlist, tuple:set) : cpctr
Arguments
|
vars
|
an array or cpvarlist of decision variables
|
|
tuple
|
the list of valid tuples for the decision variables
|
Return value
An n-ary table constraint over a set of variables
Example
The following example shows how to use the table_constraint constraint to solve a bin packing problem:
model "table_constraint example"
uses "kalis"
parameters
N = 30 ! Max number of bins
MAX_TIME = 15 ! Max time allowed to solver
end-parameters
setparam("KALIS_MAX_COMPUTATION_TIME",MAX_TIME)
forward procedure print_sol
declarations
! *** Data ***
MATERIAL = 1..5 ! Corresponds to ["Glass","Plastic","Steel","Wood","Copper"]
INITIAL_SUPPLY : array(MATERIAL) of integer
BINTYPE = 0..3 ! Corresponds to ["Unassigned", "Red", "Blue", "Green"]
BINS = 1..N ! Set of bins
CAPACITY : array(BINTYPE) of integer ! Capacity per type
WEIGHT : array(BINTYPE) of integer ! Weights for bin type selection
! *** Decision variables ***
var_bin : array(BINS) of cpvar ! Bin usage
var_type : array(BINS) of cpvar ! Bin type
var_capa : array(BINS) of cpvar ! Bin capacity
var_qty_material : array(BINS,MATERIAL) of cpvar ! Qty per material in bins
objective : cpvar
strategy : cpbranching ! Branching strategy
! Configuration of the table_constraint
var_table : array(BINS) of cpvarlist ! Assignment variables per bin
list_valid_tuple : set of list of integer ! Permissible tuples
end-declarations
! Initialisation of the data arrays
INITIAL_SUPPLY::(1..5)[12,10,8,12,8]
CAPACITY::(0..3)[0,5,5,6]
WEIGHT::(0..3)[0,1,1,1]
! Define the cpvar and their domains
forall(i in BINS) do
setname(var_bin(i), "use of bin (" + i + ")")
setdomain(var_bin(i),0,1)
setname(var_type(i), "type of bin (" + i + ")")
setdomain(var_type(i),BINTYPE)
setname(var_capa(i), "capacity of bin (" + i + ")")
var_capa(i) = element(CAPACITY,var_type(i))
forall(m in MATERIAL) do
setname(var_qty_material(i,m),
"Quantity of material (" + m + ") in bin (" + i + ")")
setdomain(var_qty_material(i,m),0,max(c in BINTYPE) CAPACITY(c))
end-do
end-do
! Capacity constraint
forall(i in BINS) do
sum(m in MATERIAL) var_qty_material(i,m) <= var_capa(i)
var_bin(i) = element(WEIGHT,var_type(i))
end-do
! Satisfy of the supply constraint
forall(m in MATERIAL)
sum(i in BINS) var_qty_material(i,m) = INITIAL_SUPPLY(m)
! Define a list of valid tuples
maxcap:= max(c in BINTYPE) CAPACITY(c)
forall(type in BINTYPE, qmat_1,qmat_2,qmat_3,
qmat_4,qmat_5 in 0..maxcap) do
! red can contain glass, cooper, wood and at most 1 wood component
if type = 1 and
qmat_2 = 0 and qmat_3 = 0 and qmat_4 <= 1 then
list_valid_tuple += {[type, qmat_1, qmat_2,qmat_3,qmat_4,qmat_5]}
! blue can contain glass, steel, cooper
elif type = 2 and qmat_2 = 0 and qmat_4 = 0 then
list_valid_tuple += {[type, qmat_1, qmat_2,qmat_3,qmat_4,qmat_5]}
! green can contain plastic, copper, wood and at most 2 wood components
elif type = 3 and
qmat_1 = 0 and qmat_3 = 0 and qmat_4 <= 2 then
list_valid_tuple += {[type, qmat_1, qmat_2,qmat_3,qmat_4,qmat_5]}
! unassigned
elif type = 0 and
qmat_1 = 0 and qmat_2 = 0 and qmat_3 = 0 and qmat_4 = 0 and qmat_5 = 0 then
list_valid_tuple += {[type, qmat_1, qmat_2,qmat_3,qmat_4,qmat_5]}
end-if
! wood requires plastic;
if qmat_4 >= 1 and qmat_2 >= 1 then
list_valid_tuple += {[type, qmat_1, qmat_2,qmat_3,qmat_4,qmat_5]}
end-if
! glass exclusive with copper;
if qmat_1 = 0 or qmat_5 = 0 then
list_valid_tuple += {[type, qmat_1, qmat_2,qmat_3,qmat_4,qmat_5]}
end-if
! copper excludes plastic.
if qmat_5 = 0 or qmat_2 = 0 then
list_valid_tuple += {[type, qmat_1, qmat_2,qmat_3,qmat_4,qmat_5]}
end-if
end-do
! Definition of table constraint
forall(i in BINS) do
var_table(i) += var_type(i)
forall(m in MATERIAL) var_table(i) += var_qty_material(i,m);
table_constraint(var_table(i), list_valid_tuple)
end-do
! Define the objective
setname(objective,"total number of bins")
setdomain(objective,0,N)
objective = sum(i in BINS) var_bin(i)
! Propagate the constraints
if not cp_propagate then
writeln("Problem is infeasible")
exit(1)
end-if
! Define a branching strategy
strategy := assign_var(KALIS_MAX_DEGREE,KALIS_MAX_TO_MIN)
cp_set_branching(strategy)
! And solve the problem
if not cp_minimize(objective) then
writeln("Problem is infeasible")
exit(1)
end-if
! Display solution and solver stats
print_sol
cp_show_stats
! **** Solution display ****
procedure print_sol
forall(i in BINS | getsol(var_type(i)) > 0) do
writeln("Bin ",i, " chosen : type=", getsol(var_type(i)),
"; capa=", getsol(var_capa(i)),
"; Glass=", getsol(var_qty_material(i,1)),
"; Plastic=", getsol(var_qty_material(i,2)),
"; Steel=", getsol(var_qty_material(i,3)),
"; Wood=", getsol(var_qty_material(i,4)),
"; Copper=", getsol(var_qty_material(i,5)))
end-do
end-procedure
end-model
