Rima Manual: A Blending Problem

[ Contents | Previous: Sums | Next: Structures ]

We wish to make a dog food that meets nutritional requirements at lowest cost by blending a number of ingredients, each of which is composed of a number of nutrients.

(This problem is courtesy of an example by Mike Trick)

We'll construct this model using only arrays, but after the next sections on structures, you'll see there's a cleaner way to structure the model.

First, we declare some references:


i, I = rima.R"i, I"               -- ingredients
n, N = rima.R"n, N"               -- nutrients
c = rima.R"c"                     -- cost of ingredients
pn = rima.R"pn"                   -- nutrients in each product
l = rima.R"l"                     -- limits on nutrients
Q = rima.R"Q"                     -- Quantity of product we're producing
f = rima.R"f"                     -- ingredient fractions (result)

Then we set up our problem:


blending_problem = rima.mp.new{
  sense = "minimise",
  objective = rima.sum{i=I}(c[i] * f[i]),
  make_quantity = rima.mp.C(rima.sum{i=I}(f[i]), "==", Q)
}
blending_problem.sufficient_nutrients[{n=N}] = rima.mp.C(rima.sum{i=I}(pn[i][n] * f[i]), ">=", Q * l[n])
blending_problem.f[{i=I}] = rima.positive()

Note that the last two lines are array assignments for a constraint and for variable bounds.

As before, we can print out the blending problem:


print(blending_problem)
--> Minimise:
-->   sum{i in I}(c[i]*f[i])
--> Subject to:
-->   make_quantity:               sum{i in I}(f[i]) == Q
-->   sufficient_nutrients[n in N]: sum{i in I}(f[i]*pn[i, n]) >= Q*l[n]
-->   0 <= f[i] <= inf, f[i] real for all i in I

Next, we define the data for the model:


whiskas_data = {
  I = {"chicken", "beef", "mutton", "rice", "wheat bran", "gel"},
  N = {"protein", "fat", "fibre", "salt"},
  c = { 0.013, 0.008, 0.010, 0.002, 0.005, 0.001 },
  l = { 0.08, 0.06, -0.02, -0.004 },
  pn =
  {
    chicken           = { 0.100,  0.080, -0.001, -0.002 },
    beef              = { 0.200,  0.100, -0.005, -0.005 },
    mutton            = { 0.150,  0.110, -0.003, -0.007 },
    rice              = { 0.000,  0.010, -0.100, -0.002 },
    ["wheat bran"]    = { 0.040,  0.010, -0.150, -0.008 },
    gel               = { 0.000,  0.000, -0.000, -0.000 },
  },
}

And finally, solve:


primal, dual = rima.mp.solve(blending_problem, whiskas_data, { Q = 100 })
print(primal.objective)                             --> 0.52
print(primal.f.chicken)                             --> 0
print(primal.f.beef)                                --> 60
print(primal.f.mutton)                              --> 0
print(primal.f.rice)                                --> 0
print(primal.f["wheat bran"])                       --> 0
print(primal.f.gel)                                 --> 40

[ Contents | Previous: Sums | Next: Structures ]