HLPL / VerTeX Modelling Language Documentation

← lessons

Multi-resource production

Two products, two resources.

Chapter: IX — Resource allocation · lesson id multi-resource · practice lesson


A factory makes two products. Each consumes labour and material at different rates, and each sells at a different price.

You have caps on labour (100 hours) and material (90 units). Variables q_p are continuous (any real quantity ≥ 0). Maximise total revenue.

This is a classic LP. The optimum sits where the two resource constraints meet — both bind.

Predict before running

At an LP optimum with two constraints, how many constraints typically bind?

Starter code

model production
set P = {1, 2}
const price = {3, 5}, forall p in P
const labour = {2, 4}, forall p in P
const material = {3, 2}, forall p in P
const LAB = 100
const MAT = 90
var 0 <= q, forall p in P
constr sum_{p in P}{labour_{p} * q_{p}} <= LAB
constr sum_{p in P}{material_{p} * q_{p}} <= MAT
max sum_{p in P}{price_{p} * q_{p}}
end

import elytica
def main():
  elytica.init_model("production")
  elytica.run_model("production")
  for i in [1,2]:
    print("q"+str(i), "=", elytica.get_variable_value("production", "q"+str(i)))
  print("obj =", elytica.get_best_primal_bound("production"))
  return 0

Hint

Solve the two equations simultaneously: 2q₁+4q₂=100, 3q₁+2q₂=90. Both bind at the optimum.

What counts as correct

Mastery variant

Different prices and resource budgets. Where do both constraints meet now?

model production_v
set P = {1, 2}
const price = {4, 7}, forall p in P
const labour = {3, 2}, forall p in P
const material = {1, 4}, forall p in P
const LAB = 60
const MAT = 80
var 0 <= q, forall p in P
constr sum_{p in P}{labour_{p} * q_{p}} <= LAB
constr sum_{p in P}{material_{p} * q_{p}} <= MAT
max sum_{p in P}{price_{p} * q_{p}}
end

import elytica
def main():
  elytica.init_model("production_v")
  elytica.run_model("production_v")
  for i in [1,2]:
    print("q"+str(i), "=", elytica.get_variable_value("production_v", "q"+str(i)))
  print("obj =", elytica.get_best_primal_bound("production_v"))
  return 0

Read this through MCP: read with path: "lessons/multi-resource", or resource hlpl://lessons/multi-resource.