/* Cutting stock problem - stage 2 in Picat. See the description of the problem in cutting_stock.pi and the stage 1 program: cutting_stock_stage1.pi This is the stage 2 program of: - stage 1: one Picat program generates the pattern using CP (since it's fastest) and save the patterns into a file. - state 2: another Picat program (this program) reads the pattern file and solves the main problem. The data for the problem is generated by cutting_stock_stage1.pi and saved in the file cutting_stock_data.pi This model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import mip. % MIP is the fastest on solving the main problem (stage 2) % import smt. main => go. go ?=> nolog, % The data file generated by cutting_stock_stage1.pi File = "cutting_stock_data.pi", cl(File), master_width(MasterWidth), demand(Demand), patterns(Patterns), wastes(Wastes), max_x(MaxX), type(Type), println(type=Type), PLen = Patterns.len, println(patternsLen=PLen), if Type == rolls then cutting_stock(MasterWidth,Demand,Patterns,Wastes,MaxX,Type, X,Rolls,Waste,Rolls) else cutting_stock(MasterWidth,Demand,Patterns,Wastes,MaxX,Type, X,Rolls,Waste,Waste) end, println(x=[[P,X[P]] : P in 1..PLen, X[P] > 0]), println(rolls=Rolls), println(waste=Waste), println(numPatterns=sum([1: I in 1..PLen, X[I] > 0])), foreach(I in 1..PLen) if X[I] > 0 then println([i=I,x=X[I],pattern=Patterns[I]]) end end, nl. go => true. % % Solve the custting stock problem. % % Is there a way to reduce the upper limit of Waste? % cutting_stock(MasterWidth,Demand,Patterns,Wastes,MaxX,Type, X,Rolls,Waste,Z) => N = Demand.len, TotalWidth = sum([Demand[I,1]*Demand[I,2] : I in 1..N]), MinRolls = ceiling(TotalWidth/MasterWidth), println([totalWidth=TotalWidth,minRolls=MinRolls]), PLen = Patterns.len, % How many of each pattern should be used? X = new_list(PLen), X :: 0..MaxX, foreach(I in 1..N) % exactly the number of demands: % sum([X[P]*Patterns[P,I] : P in 1..PLen]) #= Demand[I,2] % at least the number of demands: sum([X[P]*Patterns[P,I] : P in 1..PLen]) #>= Demand[I,2] end, Rolls #= sum(X), Rolls #>= MinRolls, Waste #= sum([X[J]*Wastes[J] : J in 1..PLen]), println(rolls=Rolls), println(waste=Waste), if Type == rolls then Z #= Rolls elseif Type == waste then Z #= Waste else println("Wrong type"=Type), fail end, Vars = X ++ [Rolls,Waste], if var(Z) then solve($[min(Z),inout,split,report(printf("z:%d\n",Z))],Vars) % waste % solve($[min(Z),ff,split,report(printf("z:%d\n",Z))],Vars) % rolls else solve($[degree,split],Vars) end.