/* 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/ */ 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), SlotS = Slot[S], 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), Row = X[I], element(J, Row, Val). % matrix_element(X, I, J, Val) => % freeze(I, (element(I, X, Row),freeze(J,element(J,Row,Val)))).