GLOP - Stigler diet

Problem: choose the cheapest mix of foods that satisfies daily minimum nutrition requirements.

Show code
import { initMPSolver, MPSolver, setWorkerBridgeEnabled } from 'or-tools-wasm/mp-solver';

setWorkerBridgeEnabled(true);
await initMPSolver();
const solver = MPSolver.CreateSolver('GLOP');
solver.SetNumThreads(4);

const nutrients = [
  { name: 'Calories (kcal)', minimum: 3 },
  { name: 'Protein (g)', minimum: 70 },
  { name: 'Calcium (g)', minimum: 0.8 },
];
const data = [
  { name: 'Wheat Flour', nutrients: [44.7, 1411, 2] },
  { name: 'Macaroni', nutrients: [11.6, 418, 0.7] },
  { name: 'Milk', nutrients: [6.1, 310, 10.5] },
  { name: 'Eggs', nutrients: [2.9, 238, 1] },
  { name: 'Spinach', nutrients: [1.1, 106, 0] },
];

const foods = data.map((food) => solver.NumVar(0, solver.infinity(), food.name));

nutrients.forEach((nutrient, nutrientIndex) => {
  const ct = solver.Constraint(nutrient.minimum, solver.infinity());
  data.forEach((food, foodIndex) => {
    ct.SetCoefficient(foods[foodIndex], food.nutrients[nutrientIndex]);
  });
});

const objective = solver.Objective();
foods.forEach((food) => objective.SetCoefficient(food, 1));
objective.SetMinimization();
await solver.Solve();
  • This is a continuous linear program: foods can be bought in fractional daily units.
  • The objective is to minimize annual food cost.
  • Each nutrient is a lower-bound constraint that the selected food mix must satisfy.
  • Expand any food card to edit its label, unit, color, and nutrient contributions.
  • Change the nutrient requirement inputs to make the diet easier, harder, or impossible.
  • The result is a mathematically cheap diet, not a realistic meal plan.

Food Catalog

Nutrient Requirements

Receipt

Run the solver to view the annual diet cost and selected foods.

Status / Response: