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