# Stock Cutting Problem
# Product catalog
set PRODUCTS;
param pLength{PRODUCTS};
param demand{PRODUCTS};
# Raw Materials
set RAW;
param rLength{RAW};
param avail{RAW};
# Set of production pieces indexed by products
set Q{p in PRODUCTS} := 1..demand[p] ;
# Set of stock pieces indexed by raw materials
set S{r in RAW} := 1..avail[r];
# Cutting assignments
var y{p in PRODUCTS, q in Q[p], r in RAW, s in S[r]} binary;
# Indicator if an item of raw material is used
var u{r in RAW, s in S[r]} binary;
# Length of waste from each piece of raw material
var w{r in RAW, s in S[r]} >= 0;
# Cut each product piece only once
s.t. A{p in PRODUCTS, q in Q[p]} : sum{r in RAW, s in S[r]} y[p,q,r,s] = 1;
# For each product, cut enough pieces to exactly meet demand
s.t. B{p in PRODUCTS} : sum{q in Q[p], r in RAW, s in S[r]} y[p,q,r,s] = demand[p];
# For each piece of raw material, do not exceed length
s.t. C{r in RAW, s in S[r]} :
sum{p in PRODUCTS, q in Q[p]} pLength[p]*y[p,q,r,s] + w[r,s] = rLength[r];
# Determine if a piece of raw material is used.
s.t. D{r in RAW, s in S[r]} : 15*u[r,s] >= sum{p in PRODUCTS, q in Q[p]} y[p,q,r,s];
# Minimize number of bars, with weights to favoring long pieces
minimize NumberOfBars: sum{r in RAW, s in S[r]} rLength[r]*u[r,s];
solve;
printf "Cutting Plan\n";
for {r in RAW} : {
printf " Raw Material Type %s \n", r;
for {s in S[r]} : {
printf " Piece %g : Remainder = %2g : Cut products ", s, w[r,s];
for {p in PRODUCTS} : {
for {q in Q[p] : y[p,q,r,s]} : {
printf "%s ", p;
}
}
printf "\n";
}
printf "\n";
}
printf "Production Plan\n";
for {p in PRODUCTS} : {
printf " Product %s \n", p;
for {q in Q[p]} : {
printf " Piece %g : Cut from stock ", q;
for {r in RAW} : {
for {s in S[r] : y[p,q,r,s]} : {
printf "%s ", r;
}
}
printf "\n";
}
printf "\n";
}
data;
param : PRODUCTS : pLength demand :=
'7m' 7 3
'6m' 6 2
'4m' 4 6
'3m' 3 1 ;
param : RAW : rLength avail :=
'15m' 15 3
'10m' 10 3;
end;