Download
/*
Car sequencing in Picat.
This model is based on the car sequencing model in
Pascal Van Hentenryck
"The OPL Optimization Programming Language", page 184ff.
(Via other implementations:
http://www.hakank.org/google_or_tools/car.py
http://www.hakank.org/minizinc/car.mzn
http://www.hakank.org/bprolog/car.pl
)
Model created by Hakan Kjellerstrand, hakank@gmail.com
See also my Picat page: http://www.hakank.org/picat/
*/
% Licenced under CC-BY-4.0 : http://creativecommons.org/licenses/by/4.0/
import cp.
main => go.
go =>
NbCars = 6,
Cars = 1..NbCars,
NbOptions = 5,
Options = 1..NbOptions,
NbSlots = 10,
Slots = 1..NbSlots,
Demand = [1, 1, 2, 2, 2, 2],
Option = [[1, 0, 0, 0, 1, 1],
[0, 0, 1, 1, 0, 1],
[1, 0, 0, 0, 1, 0],
[1, 1, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0]],
Capacity = [[1,2],
[2,3],
[1,3],
[2,5],
[1,5]],
% OptionDemand = [],
% foreach(I in Options)
% OD #= sum([ Demand[J]*Option[I,J] : J in Cars]),
% OptionDemand := OptionDemand ++ [OD]
% end,
OptionDemand = [sum([Demand[J]*Option[I,J] : J in Cars]) : I in Options],
%
% decision variables
%
Slot = new_list(NbSlots),
Slot :: 1..NbCars,
Setup = new_array(NbOptions,NbSlots),
Setup :: 0..1,
% To minimize
Z #= sum([S*Slot[S] : S in Cars]),
%
% Constraints
%
foreach(C in Cars)
sum([(Slot[S] #= C) : S in Slots]) #= Demand[C]
end,
foreach(O in Options, S in 1..(NbSlots - Capacity[O,2] + 1))
sum([Setup[O,J] : J in S..S + Capacity[O,2]- 1]) #=< Capacity[O,1]
end,
%% This don't work
% foreach(O in Options, S in Slots)
% Setup[O,S] #= Option[O,Slot[S]]
% end,
%% Instead one has to use a couple of element/3.
foreach(O in Options, S in Slots)
element(S,Slot,SlotS),
matrix_element(Option,O,SlotS,SS),
Setup[O,S] #= SS
end,
foreach(O in Options, I in 1..OptionDemand[O])
sum([Setup[O,S] : S in 1..(NbSlots - I * Capacity[O,2])]) #>=
(OptionDemand[O] - I * Capacity[O,1])
end,
Vars = Slot ++ Setup,
solve([$min(Z)], Vars),
writeln(z=Z),
printf("slot:\n%w\n", Slot),
printf("setup:\n"),
foreach(Row in Setup) writeln(Row.to_list()) end,
nl.
% matrix_element(X, I, J, Val) =>
% element(I, X, Row),
% element(J, Row, Val).
matrix_element(X, I, J, Val) =>
freeze(I, (element(I, X, Row),freeze(J,element(J,Row,Val)))).