/* Shortest path problem in Picat. Problem and model from Winston "Operations Research", page 415. When to buy/sell a car depending on the cost of maintenance etc. This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ % import util. % import mip. % import sat. import cp. main => time2(go). go => timex(Time), new_car(NewCar), trade_in(TradeIn), maintenance(Maintenance), supply(Supply), demand(Demand), % decision variables % cost matrix Cost = new_array(Time,Time+1), % the "delivery-table" (in transhipment parlor) X = new_array(Time,Time+1), X :: 0..1000, Z #= sum([X[I,J]*Cost[I,J] : I in 1..Time, J in 1..Time+1]), foreach(I in 1..Time,J in 1..Time+1) Cost[I,J] #>= 0, X[I,J] #>= 0, Cost[I,J] #<= 1000 end, % cost matrix: % cost[i,j] = maintenance cost incurred during years i, i+1,..j-1 % + cost of purchasing new car at beginning of year i % - trade-in value received at beginning of year j foreach(I in 1..Time, J in I+1..Time+1) Cost[I,J] #= NewCar + sum([Maintenance[K] : K in 1..J-I]) - TradeIn[J-I] end, % new_car^2 in the lower diagonal foreach(I in 1..Time, J in 1..Time+1, J < I) Cost[I,J] #= NewCar*NewCar end, % rows represent the timex foreach(I in 1..Time) sum([X[I,J] : J in 1..Time+1]) #= Supply[I] end, % what strategy to choose foreach(J in 1..Time+1) sum([X[I,J] : I in 1..Time]) #= Demand[J] end, println(solve), solve($[ff,split,min(Z)], X ++ Cost), println(z=Z), println("X:"), print_matrix(X), println("Cost:"), print_matrix(Cost), nl. print_matrix(M) => foreach(Row in M) foreach(I in Row) printf("%4d ", I) end, nl end, nl. timex(Time) => Time = 5. new_car(NewCar) => NewCar = 12. % car trade-in price, in 1000 dollar trade_in(TradeIn) => TradeIn = [7, 6, 2, 1, 0]. % cost to repair a car year x % in 1000 dollar maintenance(Maintenance) => Maintenance = [2, 4, 5, 9,12]. % The "transshipment table" which is the key to this % type of modelling. % 2..5 is transshipment points with "unlimited" supply and demand % supply(Supply) => Supply = [1,11,11,11,11,0]. demand(Demand) => Demand = [0,11,11,11,11,1].