%Exemple 1: linear([](800,400,100,300,100,50,500), [](1200,1000,800,300,100),M,0)
%Exemple 2: linear([](800,400,100,300,100,50,400), [](1200,1000,800,300,100),M,0)

:- lib(ic), lib(branch_and_bound), lib(arrays).


%Auxiliary Function to impose constraints (to be improved)
lengthConstrain(Matrix,Comps,Barras,BarsLen,BarIndex) :-
(for(Z,1,Barras),fromto(0,LHS1,LHS2,LHS), param(Matrix,Comps, BarIndex) do
			LHS2 = LHS1 + (Matrix[Z,BarIndex] * Comps[Z])
),
eval(LHS) #=< BarsLen.


linear(PieceLens, BarLens, M) :-    
    
    %Create a bi-dimensional array, based on the inputs
	dim(PieceLens, [NPieces]),
	dim(BarLens, [NBars]),
	dim(M,[NPieces,NBars]),
	
	M #::0..1,

	%Every Piece must be exactly allocated by only one Bar
	( for(I,1,NPieces), param(M,NBars) do  
   	sum(M[I,1..NBars]) #= 1
 	),  
	
	%The sum of the lengths of all pieces in a bar, cannot exceed the Bar's length
	(for(I,1,NBars), param(M,PieceLens, NPieces, BarLens) do
		lengthConstrain(M,PieceLens,NPieces,BarLens[I],I)
	),
	
	
	dim(U,[NBars]),	
	U #::0..1,
	
	%used to indicate that a bar is used
	(for(I,1,NBars), param(M,NPieces,U) do
	    (for(J,1,NPieces), param(M,I,U) do
		M[J,I] #=< U[I]	
	    )
	),

	%The goal is to minimize the amount of bars used
	Cost #= sum(U[1..NBars]),
   	minimize(labeling(M), Cost).

