Masalah Diet Stigler

Di bagian ini, kami menunjukkan cara menyelesaikan masalah klasik yang disebut diet Stigler, yang dinamai seperti nama peraih Nobel George Stigler dalam bidang ekonomi, peraih Nobel George Stigler, yang menghitung cara murah untuk memenuhi kebutuhan nutrisi dasar berdasarkan satu set makanan. Ia menganggap ini sebagai latihan matematika, bukan sebagai rekomendasi pola makan, meskipun gagasan menghitung nutrisi optimal baru-baru ini menjadi tren.

Diet Stigler mengamanatkan bahwa persyaratan minimum berikut harus dipenuhi:

Daftar nutrisi

Nutrisi Asupan Harian yang Direkomendasikan
Kalori 3.000 kalori
Protein 70 gram
Kalsium 0,8 gram
Besi 12 miligram
Vitamin A 5.000 IU
Tiamin (Vitamin B1) 1,8 miligram
Riboflavin (Vitamin B2) 2,7 miligram
Niasin 18 miligram
Asam Askorbat (Vitamin C) 75 miligram

Serangkaian makanan yang dievaluasi Stigler adalah cerminan dari waktu (1944). Data gizi di bawah ini adalah per dolar, bukan per unit, jadi tujuannya adalah menentukan jumlah dolar yang akan dibelanjakan untuk setiap bahan makanan.

Daftar komoditas

Komoditas Satuan Harga 1939 (sen) Kalori (kkal) Protein (g) Kalsium (g) Zat besi (mg) Vitamin A (KIU) Tiamin (mg) Riboflavin (mg) Niasin (mg) Asam Askorbat (mg)
Tepung Terigu (Diperkaya) 10 lb. 36 44,7 1411 2 365 0 55.4 33.3 441 0
Kuning makaroni 1 lb. 14.1 11.6 418 0.7 54 0 3.2 1.9 68 0
Sereal Gandum (Diperkaya) 28 oz 24.2 11.8 377 14.4 175 0 14.4 8.8 114 0
Serpihan Jagung 8 ons 7.1 11.4 252 0,1 56 0 13.5 2.3 68 0
Makanan Jagung 1 lb. 4.6 36.0 897 1.7 99 30.9 17.4 7,9 106 0
Grit Hominy 24 ons 8.5 28.6 680 0.8 80 0 10.6 1.6 110 0
Beras 1 lb. 7.5 21.2 460 0.6 41 0 2 4,8 60 0
Gandum Roll 1 lb. 7.1 25,3 907 5.1 341 0 37.1 8.9 64 0
Roti Putih (Diperkaya) 1 lb. 7,9 15.0 488 2.5 115 0 13.8 8.5 126 0
Roti Gandum Utuh 1 lb. 9.1 12.2 484 2.7 125 0 13.9 6.4 160 0
Roti Gandum Hitam 1 lb. 9.1 12.4 439 1.1 82 0 9.9 3 66 0
Kue Pound 1 lb. 24,8 8.0 130 0.4 31 18,9 2.8 3 17 0
Cracker Soda 1 lb. 15.1 12.5 288 0.5 50 0 0 0 0 0
Susu 1 kuantitas 11 6.1 310 10.5 18 16.8 4 16 7 177
Susu Evaporasi (kaleng) 14,5 oz. 6.7 8.4 422 15.1 9 26 3 23.5 11 60
Mentega 1 lb. 30.8 10.8 9 0,2 3 44.2 0 0,2 2 0
Oleomargarin 1 lb. 16.1 20,6 17 0.6 6 55.8 0,2 0 0 0
Telur 1 doz. 32.6 2.9 238 1.0 52 18,6 2.8 6.5 1 0
Keju (Cheddar) 1 lb. 24.2 7.4 448 16.4 19 28.1 0.8 10.3 4 0
Krim 1/2 poin 14.1 3.5 49 1.7 3 16,9 0.6 2.5 0 17
Selai Kacang 1 lb. 17,9 15.7 661 1.0 48 0 9.6 8.1 471 0
Mayones 1/2 poin 16.7 8.6 18 0,2 8 2.7 0.4 0.5 0 0
Crisco 1 lb. 20.3 20,1 0 0 0 0 0 0 0 0
Lemak Babi 1 lb. 9.8 41.7 0 0 0 0,2 0 0.5 5 0
Steak Sirloin 1 lb. 39.6 2.9 166 0,1 34 0,2 2.1 2.9 69 0
Steak Bundar 1 lb. 36.4 2.2 214 0,1 32 0.4 2.5 2.4 87 0
Iga Panggang 1 lb. 29.2 3.4 213 0,1 33 0 0 2 0 0
Kepala Panggang 1 lb. 22,6 3.6 309 0,2 46 0.4 1 4 120 0
Pelat 1 lb. 14.6 8.5 404 0,2 62 0 0,9 0 0 0
Hati (Daging Sapi) 1 lb. 26.8 2.2 333 0,2 139 169.2 6.4 50,8 316 525
Kaki Domba 1 lb. 27.6 3.1 245 0,1 20 0 2.8 3.9 86 0
Daging Domba (Tulang) 1 lb. 36,6 3.3 140 0,1 15 0 1.7 2.7 54 0
Daging Babi 1 lb. 30,7 3.5 196 0,2 30 0 17.4 2.7 60 0
Daging Babi Daging Panggang 1 lb. 24.2 4,4 249 0.3 37 0 18.2 3.6 79 0
Bakon 1 lb. 25,6 10.4 152 0,2 23 0 1.8 1.8 71 0
Ham, diasap 1 lb. 27.4 6.7 212 0,2 31 0 9.9 3.3 50 0
Babi Garam 1 lb. 16 18,8 164 0,1 26 0 1.4 1.8 0 0
Ayam Panggang 1 lb. 30.3 1.8 184 0,1 30 0,1 0,9 1.8 68 46
Potongan Daging Sapi Muda 1 lb. 42.3 1.7 156 0,1 24 0 1.4 2.4 57 0
Salmon, Merah Muda (kaleng) 16 oz 13 5.8 705 6.8 45 3.5 1 4.9 209 0
Apel 1 lb. 4,4 5.8 27 0.5 36 7.3 3.6 2.7 5 544
Pisang 1 lb. 6.1 4.9 60 0.4 30 17.4 2.5 3.5 28 498
Lemon 1 doz. 26 1.0 21 0.5 14 0 0.5 0 4 952
Jeruk 1 doz. 30.9 2.2 40 1.1 18 11.1 3.6 1.3 10 1998
Kacang Hijau 1 lb. 7.1 2.4 138 3.7 80 69 4.3 5.8 37 862
Kubis 1 lb. 3.7 2.6 125 4.0 36 7.2 9 4.5 26 5369
Wortel 1 ikat 4.7 2.7 73 2.8 43 188.5 6.1 4.3 89 608
Seledri 1 tangkai 7.3 0,9 51 3.0 23 0,9 1.4 1.4 9 313
Lulu 1 kepala 8.2 0.4 27 1.1 22 112.4 1.8 3.4 11 449
Bawang Bombay 1 lb. 3.6 5.8 166 3.8 59 16.6 4.7 5.9 21 1184
Kentang 15 lb. 34 14.3 336 1.8 118 6.7 29.4 7.1 198 2522
Bayam 1 lb. 8.1 1.1 106 0 138 918,4 5.7 13.8 33 2755
Ubi 1 lb. 5.1 9.6 138 2.7 54 290.7 8.4 5.4 83 1912
Persik (kaleng) No. 2 1/2 16.8 3.7 20 0.4 10 21.5 0.5 1 31 196
Pir (kaleng) No. 2 1/2 20.4 3.0 8 0.3 8 0.8 0.8 0.8 5 81
Nanas (kaleng) No. 2 1/2 21.3 2.4 16 0.4 8 2 2.8 0.8 7 399
Asparagus (kaleng) No. 2 27,7 0.4 33 0.3 12 16.3 1.4 2.1 17 272
Kacang Hijau (kaleng) No. 2 10 1.0 54 2 65 53.9 1.6 4.3 32 431
Babi dan Kacang (kaleng) 16 oz 7.1 7.5 364 4 134 3.5 8.3 7.7 56 0
Jagung (kaleng) No. 2 10.4 5.2 136 0,2 16 12 1.6 2.7 42 218
Kacang polong (kaleng) No. 2 13.8 2.3 136 0.6 45 34.9 4.9 2.5 37 370
Tomat (kaleng) No. 2 8.6 1.3 63 0.7 38 53.2 3.4 2.5 36 1253
Sup Tomat (kaleng) 10 1/2 ons 7.6 1.6 71 0.6 43 57.9 3.5 2.4 67 862
Persik, Kering 1 lb. 15.7 8.5 87 1.7 173 86.8 1,2 4.3 55 57
Prune, Kering 1 lb. 9 12,8 99 2.5 154 85.7 3.9 4.3 65 257
Kismis, Kering 15 ons 9.4 13.5 104 2.5 136 4.5 6.3 1.4 24 136
Kacang Polong, Kering 1 lb. 7,9 20.0 1367 4.2 345 2.9 28.7 18.4 162 0
Kacang Lima, Kering 1 lb. 8.9 17.4 1055 3.7 459 5.1 26.9 38.2 93 0
Kacang Angkatan Laut, Kering 1 lb. 5.9 26.9 1691 11.4 792 0 38.4 24,6 217 0
Kopi 1 lb. 22,4 0 0 0 0 0 4 5.1 50 0
Teh 1/4 lb 17.4 0 0 0 0 0 0 2.3 42 0
Kakao 8 ons 8.6 8.7 237 3 72 0 2 11.9 40 0
Cokelat 8 ons 16.2 8.0 77 1.3 39 0 0,9 3.4 14 0
Gula 10 lb. 51,7 34.9 0 0 0 0 0 0 0 0
Sirop Jagung 24 ons 13.7 14.7 0 0.5 74 0 0 0 5 0
Molase 18 oz 13.6 9.0 0 10.3 244 0 1.9 7.5 146 0
Pengawet Stroberi 1 lb. 20.5 6.4 11 0.4 7 0,2 0,2 0.4 3 0

Karena semua nutrisi telah dinormalisasi berdasarkan harga, tujuan kita hanyalah meminimalkan jumlah makanan.

Pada tahun 1944, Stigler menghitung jawaban terbaik yang dia bisa, dan mencatatnya dengan sedih:

...sepertinya tidak ada metode langsung untuk menemukan nilai minimum fungsi linear yang bergantung pada kondisi linear.

Ia menemukan diet yang harganya $39,93 per tahun, pada tahun 1939 dolar. Pada tahun 1947, Jack Laderman menggunakan metode simpleks (merupakan penemuan terbaru!) untuk menentukan solusi yang optimal. Butuh waktu 120 hari kerja yang terdiri dari sembilan pegawai menggunakan kalkulator meja untuk mendapatkan jawaban.

Larutan menggunakan pemecah linear

Bagian berikut menampilkan program yang memecahkan masalah diet Stigler.

Mengimpor wrapper pemecah masalah linear

Impor wrapper linear solver OR-Tools, sebuah antarmuka untuk pemecah linear [GLOP](/optimization/mip/glop0, seperti ditunjukkan di bawah ini.

Python

from ortools.linear_solver import pywraplp

C++

#include <array>
#include <memory>
#include <string>
#include <utility>  // std::pair
#include <vector>

#include "absl/flags/flag.h"
#include "absl/log/flags.h"
#include "ortools/base/init_google.h"
#include "ortools/base/logging.h"
#include "ortools/linear_solver/linear_solver.h"

Java

import com.google.ortools.Loader;
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
import java.util.ArrayList;
import java.util.List;

C#

using System;
using System.Collections.Generic;
using Google.OrTools.LinearSolver;

Data untuk masalah

Kode berikut membuat array nutrients untuk persyaratan nutrisi minimum, dan array data untuk tabel data nutrisi dalam solusi apa pun.

Python

# Nutrient minimums.
nutrients = [
    ["Calories (kcal)", 3],
    ["Protein (g)", 70],
    ["Calcium (g)", 0.8],
    ["Iron (mg)", 12],
    ["Vitamin A (KIU)", 5],
    ["Vitamin B1 (mg)", 1.8],
    ["Vitamin B2 (mg)", 2.7],
    ["Niacin (mg)", 18],
    ["Vitamin C (mg)", 75],
]

# Commodity, Unit, 1939 price (cents), Calories (kcal), Protein (g),
# Calcium (g), Iron (mg), Vitamin A (KIU), Vitamin B1 (mg), Vitamin B2 (mg),
# Niacin (mg), Vitamin C (mg)
data = [
    # fmt: off
  ['Wheat Flour (Enriched)', '10 lb.', 36, 44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0],
  ['Macaroni', '1 lb.', 14.1, 11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0],
  ['Wheat Cereal (Enriched)', '28 oz.', 24.2, 11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0],
  ['Corn Flakes', '8 oz.', 7.1, 11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0],
  ['Corn Meal', '1 lb.', 4.6, 36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0],
  ['Hominy Grits', '24 oz.', 8.5, 28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0],
  ['Rice', '1 lb.', 7.5, 21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0],
  ['Rolled Oats', '1 lb.', 7.1, 25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0],
  ['White Bread (Enriched)', '1 lb.', 7.9, 15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0],
  ['Whole Wheat Bread', '1 lb.', 9.1, 12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0],
  ['Rye Bread', '1 lb.', 9.1, 12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0],
  ['Pound Cake', '1 lb.', 24.8, 8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0],
  ['Soda Crackers', '1 lb.', 15.1, 12.5, 288, 0.5, 50, 0, 0, 0, 0, 0],
  ['Milk', '1 qt.', 11, 6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177],
  ['Evaporated Milk (can)', '14.5 oz.', 6.7, 8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60],
  ['Butter', '1 lb.', 30.8, 10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0],
  ['Oleomargarine', '1 lb.', 16.1, 20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0],
  ['Eggs', '1 doz.', 32.6, 2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0],
  ['Cheese (Cheddar)', '1 lb.', 24.2, 7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0],
  ['Cream', '1/2 pt.', 14.1, 3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17],
  ['Peanut Butter', '1 lb.', 17.9, 15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0],
  ['Mayonnaise', '1/2 pt.', 16.7, 8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0],
  ['Crisco', '1 lb.', 20.3, 20.1, 0, 0, 0, 0, 0, 0, 0, 0],
  ['Lard', '1 lb.', 9.8, 41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0],
  ['Sirloin Steak', '1 lb.', 39.6, 2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0],
  ['Round Steak', '1 lb.', 36.4, 2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0],
  ['Rib Roast', '1 lb.', 29.2, 3.4, 213, 0.1, 33, 0, 0, 2, 0, 0],
  ['Chuck Roast', '1 lb.', 22.6, 3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0],
  ['Plate', '1 lb.', 14.6, 8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0],
  ['Liver (Beef)', '1 lb.', 26.8, 2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525],
  ['Leg of Lamb', '1 lb.', 27.6, 3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0],
  ['Lamb Chops (Rib)', '1 lb.', 36.6, 3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0],
  ['Pork Chops', '1 lb.', 30.7, 3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0],
  ['Pork Loin Roast', '1 lb.', 24.2, 4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0],
  ['Bacon', '1 lb.', 25.6, 10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0],
  ['Ham, smoked', '1 lb.', 27.4, 6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0],
  ['Salt Pork', '1 lb.', 16, 18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0],
  ['Roasting Chicken', '1 lb.', 30.3, 1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46],
  ['Veal Cutlets', '1 lb.', 42.3, 1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0],
  ['Salmon, Pink (can)', '16 oz.', 13, 5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0],
  ['Apples', '1 lb.', 4.4, 5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544],
  ['Bananas', '1 lb.', 6.1, 4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498],
  ['Lemons', '1 doz.', 26, 1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952],
  ['Oranges', '1 doz.', 30.9, 2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998],
  ['Green Beans', '1 lb.', 7.1, 2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862],
  ['Cabbage', '1 lb.', 3.7, 2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369],
  ['Carrots', '1 bunch', 4.7, 2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608],
  ['Celery', '1 stalk', 7.3, 0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313],
  ['Lettuce', '1 head', 8.2, 0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449],
  ['Onions', '1 lb.', 3.6, 5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184],
  ['Potatoes', '15 lb.', 34, 14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522],
  ['Spinach', '1 lb.', 8.1, 1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755],
  ['Sweet Potatoes', '1 lb.', 5.1, 9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912],
  ['Peaches (can)', 'No. 2 1/2', 16.8, 3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196],
  ['Pears (can)', 'No. 2 1/2', 20.4, 3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81],
  ['Pineapple (can)', 'No. 2 1/2', 21.3, 2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399],
  ['Asparagus (can)', 'No. 2', 27.7, 0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272],
  ['Green Beans (can)', 'No. 2', 10, 1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431],
  ['Pork and Beans (can)', '16 oz.', 7.1, 7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0],
  ['Corn (can)', 'No. 2', 10.4, 5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218],
  ['Peas (can)', 'No. 2', 13.8, 2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370],
  ['Tomatoes (can)', 'No. 2', 8.6, 1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253],
  ['Tomato Soup (can)', '10 1/2 oz.', 7.6, 1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862],
  ['Peaches, Dried', '1 lb.', 15.7, 8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57],
  ['Prunes, Dried', '1 lb.', 9, 12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257],
  ['Raisins, Dried', '15 oz.', 9.4, 13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136],
  ['Peas, Dried', '1 lb.', 7.9, 20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0],
  ['Lima Beans, Dried', '1 lb.', 8.9, 17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0],
  ['Navy Beans, Dried', '1 lb.', 5.9, 26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0],
  ['Coffee', '1 lb.', 22.4, 0, 0, 0, 0, 0, 4, 5.1, 50, 0],
  ['Tea', '1/4 lb.', 17.4, 0, 0, 0, 0, 0, 0, 2.3, 42, 0],
  ['Cocoa', '8 oz.', 8.6, 8.7, 237, 3, 72, 0, 2, 11.9, 40, 0],
  ['Chocolate', '8 oz.', 16.2, 8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0],
  ['Sugar', '10 lb.', 51.7, 34.9, 0, 0, 0, 0, 0, 0, 0, 0],
  ['Corn Syrup', '24 oz.', 13.7, 14.7, 0, 0.5, 74, 0, 0, 0, 5, 0],
  ['Molasses', '18 oz.', 13.6, 9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0],
  ['Strawberry Preserves', '1 lb.', 20.5, 6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0],
    # fmt: on
]

C++

// Nutrient minimums.
const std::vector<std::pair<std::string, double>> nutrients = {
    {"Calories (kcal)", 3.0}, {"Protein (g)", 70.0},
    {"Calcium (g)", 0.8},     {"Iron (mg)", 12.0},
    {"Vitamin A (kIU)", 5.0}, {"Vitamin B1 (mg)", 1.8},
    {"Vitamin B2 (mg)", 2.7}, {"Niacin (mg)", 18.0},
    {"Vitamin C (mg)", 75.0}};

struct Commodity {
  std::string name;  //!< Commodity name
  std::string unit;  //!< Unit
  double price;      //!< 1939 price per unit (cents)
  //! Calories (kcal),
  //! Protein (g),
  //! Calcium (g),
  //! Iron (mg),
  //! Vitamin A (kIU),
  //! Vitamin B1 (mg),
  //! Vitamin B2 (mg),
  //! Niacin (mg),
  //! Vitamin C (mg)
  std::array<double, 9> nutrients;
};

std::vector<Commodity> data = {
    {"Wheat Flour (Enriched)",
     "10 lb.",
     36,
     {44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0}},
    {"Macaroni", "1 lb.", 14.1, {11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0}},
    {"Wheat Cereal (Enriched)",
     "28 oz.",
     24.2,
     {11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0}},
    {"Corn Flakes", "8 oz.", 7.1, {11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0}},
    {"Corn Meal",
     "1 lb.",
     4.6,
     {36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0}},
    {"Hominy Grits",
     "24 oz.",
     8.5,
     {28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0}},
    {"Rice", "1 lb.", 7.5, {21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0}},
    {"Rolled Oats", "1 lb.", 7.1, {25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0}},
    {"White Bread (Enriched)",
     "1 lb.",
     7.9,
     {15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0}},
    {"Whole Wheat Bread",
     "1 lb.",
     9.1,
     {12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0}},
    {"Rye Bread", "1 lb.", 9.1, {12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0}},
    {"Pound Cake", "1 lb.", 24.8, {8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0}},
    {"Soda Crackers", "1 lb.", 15.1, {12.5, 288, 0.5, 50, 0, 0, 0, 0, 0}},
    {"Milk", "1 qt.", 11, {6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177}},
    {"Evaporated Milk (can)",
     "14.5 oz.",
     6.7,
     {8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60}},
    {"Butter", "1 lb.", 30.8, {10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0}},
    {"Oleomargarine", "1 lb.", 16.1, {20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0}},
    {"Eggs", "1 doz.", 32.6, {2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0}},
    {"Cheese (Cheddar)",
     "1 lb.",
     24.2,
     {7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0}},
    {"Cream", "1/2 pt.", 14.1, {3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17}},
    {"Peanut Butter",
     "1 lb.",
     17.9,
     {15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0}},
    {"Mayonnaise", "1/2 pt.", 16.7, {8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0}},
    {"Crisco", "1 lb.", 20.3, {20.1, 0, 0, 0, 0, 0, 0, 0, 0}},
    {"Lard", "1 lb.", 9.8, {41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0}},
    {"Sirloin Steak",
     "1 lb.",
     39.6,
     {2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0}},
    {"Round Steak", "1 lb.", 36.4, {2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0}},
    {"Rib Roast", "1 lb.", 29.2, {3.4, 213, 0.1, 33, 0, 0, 2, 0, 0}},
    {"Chuck Roast", "1 lb.", 22.6, {3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0}},
    {"Plate", "1 lb.", 14.6, {8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0}},
    {"Liver (Beef)",
     "1 lb.",
     26.8,
     {2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525}},
    {"Leg of Lamb", "1 lb.", 27.6, {3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0}},
    {"Lamb Chops (Rib)",
     "1 lb.",
     36.6,
     {3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0}},
    {"Pork Chops", "1 lb.", 30.7, {3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0}},
    {"Pork Loin Roast",
     "1 lb.",
     24.2,
     {4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0}},
    {"Bacon", "1 lb.", 25.6, {10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0}},
    {"Ham, smoked", "1 lb.", 27.4, {6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0}},
    {"Salt Pork", "1 lb.", 16, {18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0}},
    {"Roasting Chicken",
     "1 lb.",
     30.3,
     {1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46}},
    {"Veal Cutlets", "1 lb.", 42.3, {1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0}},
    {"Salmon, Pink (can)",
     "16 oz.",
     13,
     {5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0}},
    {"Apples", "1 lb.", 4.4, {5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544}},
    {"Bananas", "1 lb.", 6.1, {4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498}},
    {"Lemons", "1 doz.", 26, {1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952}},
    {"Oranges", "1 doz.", 30.9, {2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998}},
    {"Green Beans", "1 lb.", 7.1, {2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862}},
    {"Cabbage", "1 lb.", 3.7, {2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369}},
    {"Carrots", "1 bunch", 4.7, {2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608}},
    {"Celery", "1 stalk", 7.3, {0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313}},
    {"Lettuce", "1 head", 8.2, {0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449}},
    {"Onions", "1 lb.", 3.6, {5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184}},
    {"Potatoes",
     "15 lb.",
     34,
     {14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522}},
    {"Spinach", "1 lb.", 8.1, {1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755}},
    {"Sweet Potatoes",
     "1 lb.",
     5.1,
     {9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912}},
    {"Peaches (can)",
     "No. 2 1/2",
     16.8,
     {3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196}},
    {"Pears (can)",
     "No. 2 1/2",
     20.4,
     {3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81}},
    {"Pineapple (can)",
     "No. 2 1/2",
     21.3,
     {2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399}},
    {"Asparagus (can)",
     "No. 2",
     27.7,
     {0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272}},
    {"Green Beans (can)",
     "No. 2",
     10,
     {1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431}},
    {"Pork and Beans (can)",
     "16 oz.",
     7.1,
     {7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0}},
    {"Corn (can)", "No. 2", 10.4, {5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218}},
    {"Peas (can)",
     "No. 2",
     13.8,
     {2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370}},
    {"Tomatoes (can)",
     "No. 2",
     8.6,
     {1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253}},
    {"Tomato Soup (can)",
     "10 1/2 oz.",
     7.6,
     {1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862}},
    {"Peaches, Dried",
     "1 lb.",
     15.7,
     {8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57}},
    {"Prunes, Dried",
     "1 lb.",
     9,
     {12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257}},
    {"Raisins, Dried",
     "15 oz.",
     9.4,
     {13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136}},
    {"Peas, Dried",
     "1 lb.",
     7.9,
     {20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0}},
    {"Lima Beans, Dried",
     "1 lb.",
     8.9,
     {17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0}},
    {"Navy Beans, Dried",
     "1 lb.",
     5.9,
     {26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0}},
    {"Coffee", "1 lb.", 22.4, {0, 0, 0, 0, 0, 4, 5.1, 50, 0}},
    {"Tea", "1/4 lb.", 17.4, {0, 0, 0, 0, 0, 0, 2.3, 42, 0}},
    {"Cocoa", "8 oz.", 8.6, {8.7, 237, 3, 72, 0, 2, 11.9, 40, 0}},
    {"Chocolate", "8 oz.", 16.2, {8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0}},
    {"Sugar", "10 lb.", 51.7, {34.9, 0, 0, 0, 0, 0, 0, 0, 0}},
    {"Corn Syrup", "24 oz.", 13.7, {14.7, 0, 0.5, 74, 0, 0, 0, 5, 0}},
    {"Molasses", "18 oz.", 13.6, {9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0}},
    {"Strawberry Preserves",
     "1 lb.",
     20.5,
     {6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0}}};

Java

// Nutrient minimums.
List<Object[]> nutrients = new ArrayList<>();
nutrients.add(new Object[] {"Calories (kcal)", 3.0});
nutrients.add(new Object[] {"Protein (g)", 70.0});
nutrients.add(new Object[] {"Calcium (g)", 0.8});
nutrients.add(new Object[] {"Iron (mg)", 12.0});
nutrients.add(new Object[] {"Vitamin A (kIU)", 5.0});
nutrients.add(new Object[] {"Vitamin B1 (mg)", 1.8});
nutrients.add(new Object[] {"Vitamin B2 (mg)", 2.7});
nutrients.add(new Object[] {"Niacin (mg)", 18.0});
nutrients.add(new Object[] {"Vitamin C (mg)", 75.0});

List<Object[]> data = new ArrayList<>();
data.add(new Object[] {"Wheat Flour (Enriched)", "10 lb.", 36,
    new double[] {44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0}});
data.add(new Object[] {
    "Macaroni", "1 lb.", 14.1, new double[] {11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0}});
data.add(new Object[] {"Wheat Cereal (Enriched)", "28 oz.", 24.2,
    new double[] {11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0}});
data.add(new Object[] {
    "Corn Flakes", "8 oz.", 7.1, new double[] {11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0}});
data.add(new Object[] {
    "Corn Meal", "1 lb.", 4.6, new double[] {36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0}});
data.add(new Object[] {
    "Hominy Grits", "24 oz.", 8.5, new double[] {28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0}});
data.add(
    new Object[] {"Rice", "1 lb.", 7.5, new double[] {21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0}});
data.add(new Object[] {
    "Rolled Oats", "1 lb.", 7.1, new double[] {25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0}});
data.add(new Object[] {"White Bread (Enriched)", "1 lb.", 7.9,
    new double[] {15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0}});
data.add(new Object[] {"Whole Wheat Bread", "1 lb.", 9.1,
    new double[] {12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0}});
data.add(new Object[] {
    "Rye Bread", "1 lb.", 9.1, new double[] {12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0}});
data.add(new Object[] {
    "Pound Cake", "1 lb.", 24.8, new double[] {8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0}});
data.add(new Object[] {
    "Soda Crackers", "1 lb.", 15.1, new double[] {12.5, 288, 0.5, 50, 0, 0, 0, 0, 0}});
data.add(
    new Object[] {"Milk", "1 qt.", 11, new double[] {6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177}});
data.add(new Object[] {"Evaporated Milk (can)", "14.5 oz.", 6.7,
    new double[] {8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60}});
data.add(
    new Object[] {"Butter", "1 lb.", 30.8, new double[] {10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0}});
data.add(new Object[] {
    "Oleomargarine", "1 lb.", 16.1, new double[] {20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0}});
data.add(new Object[] {
    "Eggs", "1 doz.", 32.6, new double[] {2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0}});
data.add(new Object[] {"Cheese (Cheddar)", "1 lb.", 24.2,
    new double[] {7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0}});
data.add(new Object[] {
    "Cream", "1/2 pt.", 14.1, new double[] {3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17}});
data.add(new Object[] {
    "Peanut Butter", "1 lb.", 17.9, new double[] {15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0}});
data.add(new Object[] {
    "Mayonnaise", "1/2 pt.", 16.7, new double[] {8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0}});
data.add(new Object[] {"Crisco", "1 lb.", 20.3, new double[] {20.1, 0, 0, 0, 0, 0, 0, 0, 0}});
data.add(new Object[] {"Lard", "1 lb.", 9.8, new double[] {41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0}});
data.add(new Object[] {
    "Sirloin Steak", "1 lb.", 39.6, new double[] {2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0}});
data.add(new Object[] {
    "Round Steak", "1 lb.", 36.4, new double[] {2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0}});
data.add(
    new Object[] {"Rib Roast", "1 lb.", 29.2, new double[] {3.4, 213, 0.1, 33, 0, 0, 2, 0, 0}});
data.add(new Object[] {
    "Chuck Roast", "1 lb.", 22.6, new double[] {3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0}});
data.add(
    new Object[] {"Plate", "1 lb.", 14.6, new double[] {8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0}});
data.add(new Object[] {"Liver (Beef)", "1 lb.", 26.8,
    new double[] {2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525}});
data.add(new Object[] {
    "Leg of Lamb", "1 lb.", 27.6, new double[] {3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0}});
data.add(new Object[] {
    "Lamb Chops (Rib)", "1 lb.", 36.6, new double[] {3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0}});
data.add(new Object[] {
    "Pork Chops", "1 lb.", 30.7, new double[] {3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0}});
data.add(new Object[] {
    "Pork Loin Roast", "1 lb.", 24.2, new double[] {4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0}});
data.add(new Object[] {
    "Bacon", "1 lb.", 25.6, new double[] {10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0}});
data.add(new Object[] {
    "Ham, smoked", "1 lb.", 27.4, new double[] {6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0}});
data.add(new Object[] {
    "Salt Pork", "1 lb.", 16, new double[] {18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0}});
data.add(new Object[] {"Roasting Chicken", "1 lb.", 30.3,
    new double[] {1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46}});
data.add(new Object[] {
    "Veal Cutlets", "1 lb.", 42.3, new double[] {1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0}});
data.add(new Object[] {
    "Salmon, Pink (can)", "16 oz.", 13, new double[] {5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0}});
data.add(new Object[] {
    "Apples", "1 lb.", 4.4, new double[] {5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544}});
data.add(new Object[] {
    "Bananas", "1 lb.", 6.1, new double[] {4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498}});
data.add(
    new Object[] {"Lemons", "1 doz.", 26, new double[] {1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952}});
data.add(new Object[] {
    "Oranges", "1 doz.", 30.9, new double[] {2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998}});
data.add(new Object[] {
    "Green Beans", "1 lb.", 7.1, new double[] {2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862}});
data.add(new Object[] {
    "Cabbage", "1 lb.", 3.7, new double[] {2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369}});
data.add(new Object[] {
    "Carrots", "1 bunch", 4.7, new double[] {2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608}});
data.add(new Object[] {
    "Celery", "1 stalk", 7.3, new double[] {0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313}});
data.add(new Object[] {
    "Lettuce", "1 head", 8.2, new double[] {0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449}});
data.add(new Object[] {
    "Onions", "1 lb.", 3.6, new double[] {5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184}});
data.add(new Object[] {
    "Potatoes", "15 lb.", 34, new double[] {14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522}});
data.add(new Object[] {
    "Spinach", "1 lb.", 8.1, new double[] {1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755}});
data.add(new Object[] {"Sweet Potatoes", "1 lb.", 5.1,
    new double[] {9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912}});
data.add(new Object[] {"Peaches (can)", "No. 2 1/2", 16.8,
    new double[] {3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196}});
data.add(new Object[] {
    "Pears (can)", "No. 2 1/2", 20.4, new double[] {3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81}});
data.add(new Object[] {
    "Pineapple (can)", "No. 2 1/2", 21.3, new double[] {2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399}});
data.add(new Object[] {"Asparagus (can)", "No. 2", 27.7,
    new double[] {0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272}});
data.add(new Object[] {
    "Green Beans (can)", "No. 2", 10, new double[] {1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431}});
data.add(new Object[] {"Pork and Beans (can)", "16 oz.", 7.1,
    new double[] {7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0}});
data.add(new Object[] {
    "Corn (can)", "No. 2", 10.4, new double[] {5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218}});
data.add(new Object[] {
    "Peas (can)", "No. 2", 13.8, new double[] {2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370}});
data.add(new Object[] {
    "Tomatoes (can)", "No. 2", 8.6, new double[] {1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253}});
data.add(new Object[] {"Tomato Soup (can)", "10 1/2 oz.", 7.6,
    new double[] {1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862}});
data.add(new Object[] {
    "Peaches, Dried", "1 lb.", 15.7, new double[] {8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57}});
data.add(new Object[] {
    "Prunes, Dried", "1 lb.", 9, new double[] {12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257}});
data.add(new Object[] {"Raisins, Dried", "15 oz.", 9.4,
    new double[] {13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136}});
data.add(new Object[] {
    "Peas, Dried", "1 lb.", 7.9, new double[] {20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0}});
data.add(new Object[] {"Lima Beans, Dried", "1 lb.", 8.9,
    new double[] {17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0}});
data.add(new Object[] {"Navy Beans, Dried", "1 lb.", 5.9,
    new double[] {26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0}});
data.add(new Object[] {"Coffee", "1 lb.", 22.4, new double[] {0, 0, 0, 0, 0, 4, 5.1, 50, 0}});
data.add(new Object[] {"Tea", "1/4 lb.", 17.4, new double[] {0, 0, 0, 0, 0, 0, 2.3, 42, 0}});
data.add(
    new Object[] {"Cocoa", "8 oz.", 8.6, new double[] {8.7, 237, 3, 72, 0, 2, 11.9, 40, 0}});
data.add(new Object[] {
    "Chocolate", "8 oz.", 16.2, new double[] {8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0}});
data.add(new Object[] {"Sugar", "10 lb.", 51.7, new double[] {34.9, 0, 0, 0, 0, 0, 0, 0, 0}});
data.add(new Object[] {
    "Corn Syrup", "24 oz.", 13.7, new double[] {14.7, 0, 0.5, 74, 0, 0, 0, 5, 0}});
data.add(new Object[] {
    "Molasses", "18 oz.", 13.6, new double[] {9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0}});
data.add(new Object[] {"Strawberry Preserves", "1 lb.", 20.5,
    new double[] {6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0}});

C#

// Nutrient minimums.
(String Name, double Value)[] nutrients =
    new[] { ("Calories (kcal)", 3.0), ("Protein (g)", 70.0),    ("Calcium (g)", 0.8),
            ("Iron (mg)", 12.0),      ("Vitamin A (kIU)", 5.0), ("Vitamin B1 (mg)", 1.8),
            ("Vitamin B2 (mg)", 2.7), ("Niacin (mg)", 18.0),    ("Vitamin C (mg)", 75.0) };

(String Name, String Unit, double Price, double[] Nutrients)[] data = new[] {
    ("Wheat Flour (Enriched)", "10 lb.", 36, new double[] { 44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0 }),
    ("Macaroni", "1 lb.", 14.1, new double[] { 11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0 }),
    ("Wheat Cereal (Enriched)", "28 oz.", 24.2, new double[] { 11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0 }),
    ("Corn Flakes", "8 oz.", 7.1, new double[] { 11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0 }),
    ("Corn Meal", "1 lb.", 4.6, new double[] { 36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0 }),
    ("Hominy Grits", "24 oz.", 8.5, new double[] { 28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0 }),
    ("Rice", "1 lb.", 7.5, new double[] { 21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0 }),
    ("Rolled Oats", "1 lb.", 7.1, new double[] { 25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0 }),
    ("White Bread (Enriched)", "1 lb.", 7.9, new double[] { 15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0 }),
    ("Whole Wheat Bread", "1 lb.", 9.1, new double[] { 12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0 }),
    ("Rye Bread", "1 lb.", 9.1, new double[] { 12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0 }),
    ("Pound Cake", "1 lb.", 24.8, new double[] { 8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0 }),
    ("Soda Crackers", "1 lb.", 15.1, new double[] { 12.5, 288, 0.5, 50, 0, 0, 0, 0, 0 }),
    ("Milk", "1 qt.", 11, new double[] { 6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177 }),
    ("Evaporated Milk (can)", "14.5 oz.", 6.7, new double[] { 8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60 }),
    ("Butter", "1 lb.", 30.8, new double[] { 10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0 }),
    ("Oleomargarine", "1 lb.", 16.1, new double[] { 20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0 }),
    ("Eggs", "1 doz.", 32.6, new double[] { 2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0 }),
    ("Cheese (Cheddar)", "1 lb.", 24.2, new double[] { 7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0 }),
    ("Cream", "1/2 pt.", 14.1, new double[] { 3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17 }),
    ("Peanut Butter", "1 lb.", 17.9, new double[] { 15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0 }),
    ("Mayonnaise", "1/2 pt.", 16.7, new double[] { 8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0 }),
    ("Crisco", "1 lb.", 20.3, new double[] { 20.1, 0, 0, 0, 0, 0, 0, 0, 0 }),
    ("Lard", "1 lb.", 9.8, new double[] { 41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0 }),
    ("Sirloin Steak", "1 lb.", 39.6, new double[] { 2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0 }),
    ("Round Steak", "1 lb.", 36.4, new double[] { 2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0 }),
    ("Rib Roast", "1 lb.", 29.2, new double[] { 3.4, 213, 0.1, 33, 0, 0, 2, 0, 0 }),
    ("Chuck Roast", "1 lb.", 22.6, new double[] { 3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0 }),
    ("Plate", "1 lb.", 14.6, new double[] { 8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0 }),
    ("Liver (Beef)", "1 lb.", 26.8, new double[] { 2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525 }),
    ("Leg of Lamb", "1 lb.", 27.6, new double[] { 3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0 }),
    ("Lamb Chops (Rib)", "1 lb.", 36.6, new double[] { 3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0 }),
    ("Pork Chops", "1 lb.", 30.7, new double[] { 3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0 }),
    ("Pork Loin Roast", "1 lb.", 24.2, new double[] { 4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0 }),
    ("Bacon", "1 lb.", 25.6, new double[] { 10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0 }),
    ("Ham, smoked", "1 lb.", 27.4, new double[] { 6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0 }),
    ("Salt Pork", "1 lb.", 16, new double[] { 18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0 }),
    ("Roasting Chicken", "1 lb.", 30.3, new double[] { 1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46 }),
    ("Veal Cutlets", "1 lb.", 42.3, new double[] { 1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0 }),
    ("Salmon, Pink (can)", "16 oz.", 13, new double[] { 5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0 }),
    ("Apples", "1 lb.", 4.4, new double[] { 5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544 }),
    ("Bananas", "1 lb.", 6.1, new double[] { 4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498 }),
    ("Lemons", "1 doz.", 26, new double[] { 1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952 }),
    ("Oranges", "1 doz.", 30.9, new double[] { 2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998 }),
    ("Green Beans", "1 lb.", 7.1, new double[] { 2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862 }),
    ("Cabbage", "1 lb.", 3.7, new double[] { 2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369 }),
    ("Carrots", "1 bunch", 4.7, new double[] { 2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608 }),
    ("Celery", "1 stalk", 7.3, new double[] { 0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313 }),
    ("Lettuce", "1 head", 8.2, new double[] { 0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449 }),
    ("Onions", "1 lb.", 3.6, new double[] { 5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184 }),
    ("Potatoes", "15 lb.", 34, new double[] { 14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522 }),
    ("Spinach", "1 lb.", 8.1, new double[] { 1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755 }),
    ("Sweet Potatoes", "1 lb.", 5.1, new double[] { 9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912 }),
    ("Peaches (can)", "No. 2 1/2", 16.8, new double[] { 3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196 }),
    ("Pears (can)", "No. 2 1/2", 20.4, new double[] { 3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81 }),
    ("Pineapple (can)", "No. 2 1/2", 21.3, new double[] { 2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399 }),
    ("Asparagus (can)", "No. 2", 27.7, new double[] { 0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272 }),
    ("Green Beans (can)", "No. 2", 10, new double[] { 1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431 }),
    ("Pork and Beans (can)", "16 oz.", 7.1, new double[] { 7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0 }),
    ("Corn (can)", "No. 2", 10.4, new double[] { 5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218 }),
    ("Peas (can)", "No. 2", 13.8, new double[] { 2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370 }),
    ("Tomatoes (can)", "No. 2", 8.6, new double[] { 1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253 }),
    ("Tomato Soup (can)", "10 1/2 oz.", 7.6, new double[] { 1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862 }),
    ("Peaches, Dried", "1 lb.", 15.7, new double[] { 8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57 }),
    ("Prunes, Dried", "1 lb.", 9, new double[] { 12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257 }),
    ("Raisins, Dried", "15 oz.", 9.4, new double[] { 13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136 }),
    ("Peas, Dried", "1 lb.", 7.9, new double[] { 20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0 }),
    ("Lima Beans, Dried", "1 lb.", 8.9, new double[] { 17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0 }),
    ("Navy Beans, Dried", "1 lb.", 5.9, new double[] { 26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0 }),
    ("Coffee", "1 lb.", 22.4, new double[] { 0, 0, 0, 0, 0, 4, 5.1, 50, 0 }),
    ("Tea", "1/4 lb.", 17.4, new double[] { 0, 0, 0, 0, 0, 0, 2.3, 42, 0 }),
    ("Cocoa", "8 oz.", 8.6, new double[] { 8.7, 237, 3, 72, 0, 2, 11.9, 40, 0 }),
    ("Chocolate", "8 oz.", 16.2, new double[] { 8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0 }),
    ("Sugar", "10 lb.", 51.7, new double[] { 34.9, 0, 0, 0, 0, 0, 0, 0, 0 }),
    ("Corn Syrup", "24 oz.", 13.7, new double[] { 14.7, 0, 0.5, 74, 0, 0, 0, 5, 0 }),
    ("Molasses", "18 oz.", 13.6, new double[] { 9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0 }),
    ("Strawberry Preserves", "1 lb.", 20.5, new double[] { 6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0 })
};

Mendeklarasikan pemecah LP

Kode berikut membuat instance wrapper MPsolver.

Python

# Instantiate a Glop solver and naming it.
solver = pywraplp.Solver.CreateSolver("GLOP")
if not solver:
    return

C++

// Create the linear solver with the GLOP backend.
std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver("GLOP"));

Java

// Create the linear solver with the GLOP backend.
MPSolver solver = MPSolver.createSolver("GLOP");
if (solver == null) {
  System.out.println("Could not create solver GLOP");
  return;
}

C#

// Create the linear solver with the GLOP backend.
Solver solver = Solver.CreateSolver("GLOP");
if (solver is null)
{
    return;
}

Membuat variabel

Kode berikut membuat variabel untuk masalah.

Python

# Declare an array to hold our variables.
foods = [solver.NumVar(0.0, solver.infinity(), item[0]) for item in data]

print("Number of variables =", solver.NumVariables())

C++

std::vector<MPVariable*> foods;
const double infinity = solver->infinity();
for (const Commodity& commodity : data) {
  foods.push_back(solver->MakeNumVar(0.0, infinity, commodity.name));
}
LOG(INFO) << "Number of variables = " << solver->NumVariables();

Java

double infinity = java.lang.Double.POSITIVE_INFINITY;
List<MPVariable> foods = new ArrayList<>();
for (int i = 0; i < data.size(); ++i) {
  foods.add(solver.makeNumVar(0.0, infinity, (String) data.get(i)[0]));
}
System.out.println("Number of variables = " + solver.numVariables());

C#

List<Variable> foods = new List<Variable>();
for (int i = 0; i < data.Length; ++i)
{
    foods.Add(solver.MakeNumVar(0.0, double.PositiveInfinity, data[i].Name));
}
Console.WriteLine($"Number of variables = {solver.NumVariables()}");

Metode MakeNumVar membuat satu variabel, food[i], untuk setiap baris tabel. Seperti disebutkan sebelumnya, data nutrisi adalah per dolar sehingga food[i] adalah jumlah uang yang akan dibelanjakan untuk komoditas i.

Menentukan batasan

Batasan untuk diet Stigler mengharuskan jumlah total nutrisi yang disediakan oleh semua makanan minimal harus memenuhi persyaratan minimum untuk setiap nutrisi. Selanjutnya, kita tulis batasan ini sebagai ketidaksetaraan yang melibatkan array data dan nutrients, serta variabel food[i].

Pertama, jumlah i nutrisi yang disediakan oleh j makanan per dolar adalah data[j][i+3] (kita menambahkan 3 ke indeks kolom karena data nutrisi dimulai di kolom keempat pada data.) Karena jumlah uang yang akan dibelanjakan untuk makanan j adalah food[j], jumlah nutrisi i yang disediakan oleh j makanan adalah \(data[j][i+3] \cdot food[j]\). Terakhir, karena persyaratan minimum untuk nutrisi i adalah nutrients[i][1], kita dapat menulis batasan i sebagai berikut:

\( \sum_{j} data[j][i+3] \cdot food[j] \geq nutrients[i][1] \;\;\;\;\; (1) \)
Kode berikut menentukan batasan ini.

Python

# Create the constraints, one per nutrient.
constraints = []
for i, nutrient in enumerate(nutrients):
    constraints.append(solver.Constraint(nutrient[1], solver.infinity()))
    for j, item in enumerate(data):
        constraints[i].SetCoefficient(foods[j], item[i + 3])

print("Number of constraints =", solver.NumConstraints())

C++

// Create the constraints, one per nutrient.
std::vector<MPConstraint*> constraints;
for (std::size_t i = 0; i < nutrients.size(); ++i) {
  constraints.push_back(
      solver->MakeRowConstraint(nutrients[i].second, infinity));
  for (std::size_t j = 0; j < data.size(); ++j) {
    constraints.back()->SetCoefficient(foods[j], data[j].nutrients[i]);
  }
}
LOG(INFO) << "Number of constraints = " << solver->NumConstraints();

Java

MPConstraint[] constraints = new MPConstraint[nutrients.size()];
for (int i = 0; i < nutrients.size(); ++i) {
  constraints[i] = solver.makeConstraint(
      (double) nutrients.get(i)[1], infinity, (String) nutrients.get(i)[0]);
  for (int j = 0; j < data.size(); ++j) {
    constraints[i].setCoefficient(foods.get(j), ((double[]) data.get(j)[3])[i]);
  }
  // constraints.add(constraint);
}
System.out.println("Number of constraints = " + solver.numConstraints());

C#

List<Constraint> constraints = new List<Constraint>();
for (int i = 0; i < nutrients.Length; ++i)
{
    Constraint constraint =
        solver.MakeConstraint(nutrients[i].Value, double.PositiveInfinity, nutrients[i].Name);
    for (int j = 0; j < data.Length; ++j)
    {
        constraint.SetCoefficient(foods[j], data[j].Nutrients[i]);
    }
    constraints.Add(constraint);
}
Console.WriteLine($"Number of constraints = {solver.NumConstraints()}");

Metode Python Constraint (sesuai dengan metode C++ MakeRowConstraint) membuat batasan untuk masalah tersebut. Untuk setiap i, constraint(nutrients[i][1], solver.infinity)

Tindakan ini akan membuat batasan dengan kombinasi linear variabel food[j] (ditentukan berikutnya) lebih besar dari atau sama dengan nutrients[i][1]. Koefisien ekspresi linear ditentukan oleh metode SetCoefficient sebagai berikut: SetCoefficient(food[j], data[j][i+3]

Tindakan ini menetapkan koefisien food[j] menjadi data[j][i+3].

Dengan menggabungkan semua ini, kode menentukan batasan yang dinyatakan dalam (1) di atas.

Membuat tujuan

Kode berikut mendefinisikan fungsi objektif untuk soal ini.

Python

# Objective function: Minimize the sum of (price-normalized) foods.
objective = solver.Objective()
for food in foods:
    objective.SetCoefficient(food, 1)
objective.SetMinimization()

C++

MPObjective* const objective = solver->MutableObjective();
for (size_t i = 0; i < data.size(); ++i) {
  objective->SetCoefficient(foods[i], 1);
}
objective->SetMinimization();

Java

MPObjective objective = solver.objective();
for (int i = 0; i < data.size(); ++i) {
  objective.setCoefficient(foods.get(i), 1);
}
objective.setMinimization();

C#

Objective objective = solver.Objective();
for (int i = 0; i < data.Length; ++i)
{
    objective.SetCoefficient(foods[i], 1);
}
objective.SetMinimization();

Fungsi objektif adalah total biaya makanan, yang merupakan jumlah dari variabel food[i].

Metode SetCoefficient menetapkan koefisien fungsi objektif, yang semuanya 1 dalam kasus ini. Terakhir, SetMinimization mendeklarasikan ini sebagai masalah minimalisasi.

Memanggil pemecah masalah

Kode berikut memanggil pemecah.

Python

print(f"Solving with {solver.SolverVersion()}")
status = solver.Solve()

C++

const MPSolver::ResultStatus result_status = solver->Solve();

Java

final MPSolver.ResultStatus resultStatus = solver.solve();

C#

Solver.ResultStatus resultStatus = solver.Solve();

Glop memecahkan masalah pada komputer biasa dalam waktu kurang dari 300 milidetik:

Menampilkan solusi

Kode berikut menampilkan solusi.

Python

# Check that the problem has an optimal solution.
if status != solver.OPTIMAL:
    print("The problem does not have an optimal solution!")
    if status == solver.FEASIBLE:
        print("A potentially suboptimal solution was found.")
    else:
        print("The solver could not solve the problem.")
        exit(1)

# Display the amounts (in dollars) to purchase of each food.
nutrients_result = [0] * len(nutrients)
print("\nAnnual Foods:")
for i, food in enumerate(foods):
    if food.solution_value() > 0.0:
        print("{}: ${}".format(data[i][0], 365.0 * food.solution_value()))
        for j, _ in enumerate(nutrients):
            nutrients_result[j] += data[i][j + 3] * food.solution_value()
print("\nOptimal annual price: ${:.4f}".format(365.0 * objective.Value()))

print("\nNutrients per day:")
for i, nutrient in enumerate(nutrients):
    print(
        "{}: {:.2f} (min {})".format(nutrient[0], nutrients_result[i], nutrient[1])
    )

C++

// Check that the problem has an optimal solution.
if (result_status != MPSolver::OPTIMAL) {
  LOG(INFO) << "The problem does not have an optimal solution!";
  if (result_status == MPSolver::FEASIBLE) {
    LOG(INFO) << "A potentially suboptimal solution was found";
  } else {
    LOG(INFO) << "The solver could not solve the problem.";
    return;
  }
}

std::vector<double> nutrients_result(nutrients.size());
LOG(INFO) << "";
LOG(INFO) << "Annual Foods:";
for (std::size_t i = 0; i < data.size(); ++i) {
  if (foods[i]->solution_value() > 0.0) {
    LOG(INFO) << data[i].name << ": $"
              << std::to_string(365. * foods[i]->solution_value());
    for (std::size_t j = 0; j < nutrients.size(); ++j) {
      nutrients_result[j] +=
          data[i].nutrients[j] * foods[i]->solution_value();
    }
  }
}
LOG(INFO) << "";
LOG(INFO) << "Optimal annual price: $"
          << std::to_string(365. * objective->Value());
LOG(INFO) << "";
LOG(INFO) << "Nutrients per day:";
for (std::size_t i = 0; i < nutrients.size(); ++i) {
  LOG(INFO) << nutrients[i].first << ": "
            << std::to_string(nutrients_result[i]) << " (min "
            << std::to_string(nutrients[i].second) << ")";
}

Java

// Check that the problem has an optimal solution.
if (resultStatus != MPSolver.ResultStatus.OPTIMAL) {
  System.err.println("The problem does not have an optimal solution!");
  if (resultStatus == MPSolver.ResultStatus.FEASIBLE) {
    System.err.println("A potentially suboptimal solution was found.");
  } else {
    System.err.println("The solver could not solve the problem.");
    return;
  }
}

// Display the amounts (in dollars) to purchase of each food.
double[] nutrientsResult = new double[nutrients.size()];
System.out.println("\nAnnual Foods:");
for (int i = 0; i < foods.size(); ++i) {
  if (foods.get(i).solutionValue() > 0.0) {
    System.out.println((String) data.get(i)[0] + ": $" + 365 * foods.get(i).solutionValue());
    for (int j = 0; j < nutrients.size(); ++j) {
      nutrientsResult[j] += ((double[]) data.get(i)[3])[j] * foods.get(i).solutionValue();
    }
  }
}
System.out.println("\nOptimal annual price: $" + 365 * objective.value());

System.out.println("\nNutrients per day:");
for (int i = 0; i < nutrients.size(); ++i) {
  System.out.println(
      nutrients.get(i)[0] + ": " + nutrientsResult[i] + " (min " + nutrients.get(i)[1] + ")");
}

C#

// Check that the problem has an optimal solution.
if (resultStatus != Solver.ResultStatus.OPTIMAL)
{
    Console.WriteLine("The problem does not have an optimal solution!");
    if (resultStatus == Solver.ResultStatus.FEASIBLE)
    {
        Console.WriteLine("A potentially suboptimal solution was found.");
    }
    else
    {
        Console.WriteLine("The solver could not solve the problem.");
        return;
    }
}

// Display the amounts (in dollars) to purchase of each food.
double[] nutrientsResult = new double[nutrients.Length];
Console.WriteLine("\nAnnual Foods:");
for (int i = 0; i < foods.Count; ++i)
{
    if (foods[i].SolutionValue() > 0.0)
    {
        Console.WriteLine($"{data[i].Name}: ${365 * foods[i].SolutionValue():N2}");
        for (int j = 0; j < nutrients.Length; ++j)
        {
            nutrientsResult[j] += data[i].Nutrients[j] * foods[i].SolutionValue();
        }
    }
}
Console.WriteLine($"\nOptimal annual price: ${365 * objective.Value():N2}");

Console.WriteLine("\nNutrients per day:");
for (int i = 0; i < nutrients.Length; ++i)
{
    Console.WriteLine($"{nutrients[i].Name}: {nutrientsResult[i]:N2} (min {nutrients[i].Value})");
}

Berikut adalah output program.

make rpy_stigler_diet
"/usr/bin/python3.11" ortools/linear_solver/samples/stigler_diet.py
Number of variables = 77
Number of constraints = 9

Annual Foods:
Wheat Flour (Enriched): $10.774457511918223
Liver (Beef): $0.6907834111074193
Cabbage: $4.093268864842877
Spinach: $1.8277960703546996
Navy Beans, Dried: $22.275425687243036

Optimal annual price: $39.6617

Nutrients per day:
Calories (kcal): 3.00 (min 3)
Protein (g): 147.41 (min 70)
Calcium (g): 0.80 (min 0.8)
Iron (mg): 60.47 (min 12)
Vitamin A (KIU): 5.00 (min 5)
Vitamin B1 (mg): 4.12 (min 1.8)
Vitamin B2 (mg): 2.70 (min 2.7)
Niacin (mg): 27.32 (min 18)
Vitamin C (mg): 75.00 (min 75)

Advanced usage:
Problem solved in  1  milliseconds
Problem solved in  14  iterations

Menyelesaikan kode untuk program

Kode lengkap untuk program diet Stigler ditampilkan di bawah ini.

Python

"""The Stigler diet problem.

A description of the problem can be found here:
https://en.wikipedia.org/wiki/Stigler_diet.
"""
from ortools.linear_solver import pywraplp


def main():
    """Entry point of the program."""
    # Instantiate the data problem.
    # Nutrient minimums.
    nutrients = [
        ["Calories (kcal)", 3],
        ["Protein (g)", 70],
        ["Calcium (g)", 0.8],
        ["Iron (mg)", 12],
        ["Vitamin A (KIU)", 5],
        ["Vitamin B1 (mg)", 1.8],
        ["Vitamin B2 (mg)", 2.7],
        ["Niacin (mg)", 18],
        ["Vitamin C (mg)", 75],
    ]

    # Commodity, Unit, 1939 price (cents), Calories (kcal), Protein (g),
    # Calcium (g), Iron (mg), Vitamin A (KIU), Vitamin B1 (mg), Vitamin B2 (mg),
    # Niacin (mg), Vitamin C (mg)
    data = [
        # fmt: off
      ['Wheat Flour (Enriched)', '10 lb.', 36, 44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0],
      ['Macaroni', '1 lb.', 14.1, 11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0],
      ['Wheat Cereal (Enriched)', '28 oz.', 24.2, 11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0],
      ['Corn Flakes', '8 oz.', 7.1, 11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0],
      ['Corn Meal', '1 lb.', 4.6, 36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0],
      ['Hominy Grits', '24 oz.', 8.5, 28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0],
      ['Rice', '1 lb.', 7.5, 21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0],
      ['Rolled Oats', '1 lb.', 7.1, 25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0],
      ['White Bread (Enriched)', '1 lb.', 7.9, 15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0],
      ['Whole Wheat Bread', '1 lb.', 9.1, 12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0],
      ['Rye Bread', '1 lb.', 9.1, 12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0],
      ['Pound Cake', '1 lb.', 24.8, 8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0],
      ['Soda Crackers', '1 lb.', 15.1, 12.5, 288, 0.5, 50, 0, 0, 0, 0, 0],
      ['Milk', '1 qt.', 11, 6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177],
      ['Evaporated Milk (can)', '14.5 oz.', 6.7, 8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60],
      ['Butter', '1 lb.', 30.8, 10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0],
      ['Oleomargarine', '1 lb.', 16.1, 20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0],
      ['Eggs', '1 doz.', 32.6, 2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0],
      ['Cheese (Cheddar)', '1 lb.', 24.2, 7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0],
      ['Cream', '1/2 pt.', 14.1, 3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17],
      ['Peanut Butter', '1 lb.', 17.9, 15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0],
      ['Mayonnaise', '1/2 pt.', 16.7, 8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0],
      ['Crisco', '1 lb.', 20.3, 20.1, 0, 0, 0, 0, 0, 0, 0, 0],
      ['Lard', '1 lb.', 9.8, 41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0],
      ['Sirloin Steak', '1 lb.', 39.6, 2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0],
      ['Round Steak', '1 lb.', 36.4, 2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0],
      ['Rib Roast', '1 lb.', 29.2, 3.4, 213, 0.1, 33, 0, 0, 2, 0, 0],
      ['Chuck Roast', '1 lb.', 22.6, 3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0],
      ['Plate', '1 lb.', 14.6, 8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0],
      ['Liver (Beef)', '1 lb.', 26.8, 2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525],
      ['Leg of Lamb', '1 lb.', 27.6, 3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0],
      ['Lamb Chops (Rib)', '1 lb.', 36.6, 3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0],
      ['Pork Chops', '1 lb.', 30.7, 3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0],
      ['Pork Loin Roast', '1 lb.', 24.2, 4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0],
      ['Bacon', '1 lb.', 25.6, 10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0],
      ['Ham, smoked', '1 lb.', 27.4, 6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0],
      ['Salt Pork', '1 lb.', 16, 18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0],
      ['Roasting Chicken', '1 lb.', 30.3, 1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46],
      ['Veal Cutlets', '1 lb.', 42.3, 1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0],
      ['Salmon, Pink (can)', '16 oz.', 13, 5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0],
      ['Apples', '1 lb.', 4.4, 5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544],
      ['Bananas', '1 lb.', 6.1, 4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498],
      ['Lemons', '1 doz.', 26, 1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952],
      ['Oranges', '1 doz.', 30.9, 2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998],
      ['Green Beans', '1 lb.', 7.1, 2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862],
      ['Cabbage', '1 lb.', 3.7, 2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369],
      ['Carrots', '1 bunch', 4.7, 2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608],
      ['Celery', '1 stalk', 7.3, 0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313],
      ['Lettuce', '1 head', 8.2, 0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449],
      ['Onions', '1 lb.', 3.6, 5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184],
      ['Potatoes', '15 lb.', 34, 14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522],
      ['Spinach', '1 lb.', 8.1, 1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755],
      ['Sweet Potatoes', '1 lb.', 5.1, 9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912],
      ['Peaches (can)', 'No. 2 1/2', 16.8, 3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196],
      ['Pears (can)', 'No. 2 1/2', 20.4, 3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81],
      ['Pineapple (can)', 'No. 2 1/2', 21.3, 2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399],
      ['Asparagus (can)', 'No. 2', 27.7, 0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272],
      ['Green Beans (can)', 'No. 2', 10, 1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431],
      ['Pork and Beans (can)', '16 oz.', 7.1, 7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0],
      ['Corn (can)', 'No. 2', 10.4, 5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218],
      ['Peas (can)', 'No. 2', 13.8, 2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370],
      ['Tomatoes (can)', 'No. 2', 8.6, 1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253],
      ['Tomato Soup (can)', '10 1/2 oz.', 7.6, 1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862],
      ['Peaches, Dried', '1 lb.', 15.7, 8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57],
      ['Prunes, Dried', '1 lb.', 9, 12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257],
      ['Raisins, Dried', '15 oz.', 9.4, 13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136],
      ['Peas, Dried', '1 lb.', 7.9, 20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0],
      ['Lima Beans, Dried', '1 lb.', 8.9, 17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0],
      ['Navy Beans, Dried', '1 lb.', 5.9, 26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0],
      ['Coffee', '1 lb.', 22.4, 0, 0, 0, 0, 0, 4, 5.1, 50, 0],
      ['Tea', '1/4 lb.', 17.4, 0, 0, 0, 0, 0, 0, 2.3, 42, 0],
      ['Cocoa', '8 oz.', 8.6, 8.7, 237, 3, 72, 0, 2, 11.9, 40, 0],
      ['Chocolate', '8 oz.', 16.2, 8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0],
      ['Sugar', '10 lb.', 51.7, 34.9, 0, 0, 0, 0, 0, 0, 0, 0],
      ['Corn Syrup', '24 oz.', 13.7, 14.7, 0, 0.5, 74, 0, 0, 0, 5, 0],
      ['Molasses', '18 oz.', 13.6, 9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0],
      ['Strawberry Preserves', '1 lb.', 20.5, 6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0],
        # fmt: on
    ]

    # Instantiate a Glop solver and naming it.
    solver = pywraplp.Solver.CreateSolver("GLOP")
    if not solver:
        return

    # Declare an array to hold our variables.
    foods = [solver.NumVar(0.0, solver.infinity(), item[0]) for item in data]

    print("Number of variables =", solver.NumVariables())

    # Create the constraints, one per nutrient.
    constraints = []
    for i, nutrient in enumerate(nutrients):
        constraints.append(solver.Constraint(nutrient[1], solver.infinity()))
        for j, item in enumerate(data):
            constraints[i].SetCoefficient(foods[j], item[i + 3])

    print("Number of constraints =", solver.NumConstraints())

    # Objective function: Minimize the sum of (price-normalized) foods.
    objective = solver.Objective()
    for food in foods:
        objective.SetCoefficient(food, 1)
    objective.SetMinimization()

    print(f"Solving with {solver.SolverVersion()}")
    status = solver.Solve()

    # Check that the problem has an optimal solution.
    if status != solver.OPTIMAL:
        print("The problem does not have an optimal solution!")
        if status == solver.FEASIBLE:
            print("A potentially suboptimal solution was found.")
        else:
            print("The solver could not solve the problem.")
            exit(1)

    # Display the amounts (in dollars) to purchase of each food.
    nutrients_result = [0] * len(nutrients)
    print("\nAnnual Foods:")
    for i, food in enumerate(foods):
        if food.solution_value() > 0.0:
            print("{}: ${}".format(data[i][0], 365.0 * food.solution_value()))
            for j, _ in enumerate(nutrients):
                nutrients_result[j] += data[i][j + 3] * food.solution_value()
    print("\nOptimal annual price: ${:.4f}".format(365.0 * objective.Value()))

    print("\nNutrients per day:")
    for i, nutrient in enumerate(nutrients):
        print(
            "{}: {:.2f} (min {})".format(nutrient[0], nutrients_result[i], nutrient[1])
        )

    print("\nAdvanced usage:")
    print(f"Problem solved in {solver.wall_time():d} milliseconds")
    print(f"Problem solved in {solver.iterations():d} iterations")


if __name__ == "__main__":
    main()

C++

// The Stigler diet problem.
#include <array>
#include <memory>
#include <string>
#include <utility>  // std::pair
#include <vector>

#include "absl/flags/flag.h"
#include "absl/log/flags.h"
#include "ortools/base/init_google.h"
#include "ortools/base/logging.h"
#include "ortools/linear_solver/linear_solver.h"

namespace operations_research {
void StiglerDiet() {
  // Nutrient minimums.
  const std::vector<std::pair<std::string, double>> nutrients = {
      {"Calories (kcal)", 3.0}, {"Protein (g)", 70.0},
      {"Calcium (g)", 0.8},     {"Iron (mg)", 12.0},
      {"Vitamin A (kIU)", 5.0}, {"Vitamin B1 (mg)", 1.8},
      {"Vitamin B2 (mg)", 2.7}, {"Niacin (mg)", 18.0},
      {"Vitamin C (mg)", 75.0}};

  struct Commodity {
    std::string name;  //!< Commodity name
    std::string unit;  //!< Unit
    double price;      //!< 1939 price per unit (cents)
    //! Calories (kcal),
    //! Protein (g),
    //! Calcium (g),
    //! Iron (mg),
    //! Vitamin A (kIU),
    //! Vitamin B1 (mg),
    //! Vitamin B2 (mg),
    //! Niacin (mg),
    //! Vitamin C (mg)
    std::array<double, 9> nutrients;
  };

  std::vector<Commodity> data = {
      {"Wheat Flour (Enriched)",
       "10 lb.",
       36,
       {44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0}},
      {"Macaroni", "1 lb.", 14.1, {11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0}},
      {"Wheat Cereal (Enriched)",
       "28 oz.",
       24.2,
       {11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0}},
      {"Corn Flakes", "8 oz.", 7.1, {11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0}},
      {"Corn Meal",
       "1 lb.",
       4.6,
       {36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0}},
      {"Hominy Grits",
       "24 oz.",
       8.5,
       {28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0}},
      {"Rice", "1 lb.", 7.5, {21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0}},
      {"Rolled Oats", "1 lb.", 7.1, {25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0}},
      {"White Bread (Enriched)",
       "1 lb.",
       7.9,
       {15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0}},
      {"Whole Wheat Bread",
       "1 lb.",
       9.1,
       {12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0}},
      {"Rye Bread", "1 lb.", 9.1, {12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0}},
      {"Pound Cake", "1 lb.", 24.8, {8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0}},
      {"Soda Crackers", "1 lb.", 15.1, {12.5, 288, 0.5, 50, 0, 0, 0, 0, 0}},
      {"Milk", "1 qt.", 11, {6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177}},
      {"Evaporated Milk (can)",
       "14.5 oz.",
       6.7,
       {8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60}},
      {"Butter", "1 lb.", 30.8, {10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0}},
      {"Oleomargarine", "1 lb.", 16.1, {20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0}},
      {"Eggs", "1 doz.", 32.6, {2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0}},
      {"Cheese (Cheddar)",
       "1 lb.",
       24.2,
       {7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0}},
      {"Cream", "1/2 pt.", 14.1, {3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17}},
      {"Peanut Butter",
       "1 lb.",
       17.9,
       {15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0}},
      {"Mayonnaise", "1/2 pt.", 16.7, {8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0}},
      {"Crisco", "1 lb.", 20.3, {20.1, 0, 0, 0, 0, 0, 0, 0, 0}},
      {"Lard", "1 lb.", 9.8, {41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0}},
      {"Sirloin Steak",
       "1 lb.",
       39.6,
       {2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0}},
      {"Round Steak", "1 lb.", 36.4, {2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0}},
      {"Rib Roast", "1 lb.", 29.2, {3.4, 213, 0.1, 33, 0, 0, 2, 0, 0}},
      {"Chuck Roast", "1 lb.", 22.6, {3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0}},
      {"Plate", "1 lb.", 14.6, {8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0}},
      {"Liver (Beef)",
       "1 lb.",
       26.8,
       {2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525}},
      {"Leg of Lamb", "1 lb.", 27.6, {3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0}},
      {"Lamb Chops (Rib)",
       "1 lb.",
       36.6,
       {3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0}},
      {"Pork Chops", "1 lb.", 30.7, {3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0}},
      {"Pork Loin Roast",
       "1 lb.",
       24.2,
       {4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0}},
      {"Bacon", "1 lb.", 25.6, {10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0}},
      {"Ham, smoked", "1 lb.", 27.4, {6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0}},
      {"Salt Pork", "1 lb.", 16, {18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0}},
      {"Roasting Chicken",
       "1 lb.",
       30.3,
       {1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46}},
      {"Veal Cutlets", "1 lb.", 42.3, {1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0}},
      {"Salmon, Pink (can)",
       "16 oz.",
       13,
       {5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0}},
      {"Apples", "1 lb.", 4.4, {5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544}},
      {"Bananas", "1 lb.", 6.1, {4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498}},
      {"Lemons", "1 doz.", 26, {1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952}},
      {"Oranges", "1 doz.", 30.9, {2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998}},
      {"Green Beans", "1 lb.", 7.1, {2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862}},
      {"Cabbage", "1 lb.", 3.7, {2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369}},
      {"Carrots", "1 bunch", 4.7, {2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608}},
      {"Celery", "1 stalk", 7.3, {0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313}},
      {"Lettuce", "1 head", 8.2, {0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449}},
      {"Onions", "1 lb.", 3.6, {5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184}},
      {"Potatoes",
       "15 lb.",
       34,
       {14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522}},
      {"Spinach", "1 lb.", 8.1, {1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755}},
      {"Sweet Potatoes",
       "1 lb.",
       5.1,
       {9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912}},
      {"Peaches (can)",
       "No. 2 1/2",
       16.8,
       {3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196}},
      {"Pears (can)",
       "No. 2 1/2",
       20.4,
       {3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81}},
      {"Pineapple (can)",
       "No. 2 1/2",
       21.3,
       {2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399}},
      {"Asparagus (can)",
       "No. 2",
       27.7,
       {0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272}},
      {"Green Beans (can)",
       "No. 2",
       10,
       {1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431}},
      {"Pork and Beans (can)",
       "16 oz.",
       7.1,
       {7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0}},
      {"Corn (can)", "No. 2", 10.4, {5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218}},
      {"Peas (can)",
       "No. 2",
       13.8,
       {2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370}},
      {"Tomatoes (can)",
       "No. 2",
       8.6,
       {1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253}},
      {"Tomato Soup (can)",
       "10 1/2 oz.",
       7.6,
       {1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862}},
      {"Peaches, Dried",
       "1 lb.",
       15.7,
       {8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57}},
      {"Prunes, Dried",
       "1 lb.",
       9,
       {12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257}},
      {"Raisins, Dried",
       "15 oz.",
       9.4,
       {13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136}},
      {"Peas, Dried",
       "1 lb.",
       7.9,
       {20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0}},
      {"Lima Beans, Dried",
       "1 lb.",
       8.9,
       {17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0}},
      {"Navy Beans, Dried",
       "1 lb.",
       5.9,
       {26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0}},
      {"Coffee", "1 lb.", 22.4, {0, 0, 0, 0, 0, 4, 5.1, 50, 0}},
      {"Tea", "1/4 lb.", 17.4, {0, 0, 0, 0, 0, 0, 2.3, 42, 0}},
      {"Cocoa", "8 oz.", 8.6, {8.7, 237, 3, 72, 0, 2, 11.9, 40, 0}},
      {"Chocolate", "8 oz.", 16.2, {8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0}},
      {"Sugar", "10 lb.", 51.7, {34.9, 0, 0, 0, 0, 0, 0, 0, 0}},
      {"Corn Syrup", "24 oz.", 13.7, {14.7, 0, 0.5, 74, 0, 0, 0, 5, 0}},
      {"Molasses", "18 oz.", 13.6, {9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0}},
      {"Strawberry Preserves",
       "1 lb.",
       20.5,
       {6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0}}};

  // Create the linear solver with the GLOP backend.
  std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver("GLOP"));

  std::vector<MPVariable*> foods;
  const double infinity = solver->infinity();
  for (const Commodity& commodity : data) {
    foods.push_back(solver->MakeNumVar(0.0, infinity, commodity.name));
  }
  LOG(INFO) << "Number of variables = " << solver->NumVariables();

  // Create the constraints, one per nutrient.
  std::vector<MPConstraint*> constraints;
  for (std::size_t i = 0; i < nutrients.size(); ++i) {
    constraints.push_back(
        solver->MakeRowConstraint(nutrients[i].second, infinity));
    for (std::size_t j = 0; j < data.size(); ++j) {
      constraints.back()->SetCoefficient(foods[j], data[j].nutrients[i]);
    }
  }
  LOG(INFO) << "Number of constraints = " << solver->NumConstraints();

  MPObjective* const objective = solver->MutableObjective();
  for (size_t i = 0; i < data.size(); ++i) {
    objective->SetCoefficient(foods[i], 1);
  }
  objective->SetMinimization();

  const MPSolver::ResultStatus result_status = solver->Solve();

  // Check that the problem has an optimal solution.
  if (result_status != MPSolver::OPTIMAL) {
    LOG(INFO) << "The problem does not have an optimal solution!";
    if (result_status == MPSolver::FEASIBLE) {
      LOG(INFO) << "A potentially suboptimal solution was found";
    } else {
      LOG(INFO) << "The solver could not solve the problem.";
      return;
    }
  }

  std::vector<double> nutrients_result(nutrients.size());
  LOG(INFO) << "";
  LOG(INFO) << "Annual Foods:";
  for (std::size_t i = 0; i < data.size(); ++i) {
    if (foods[i]->solution_value() > 0.0) {
      LOG(INFO) << data[i].name << ": $"
                << std::to_string(365. * foods[i]->solution_value());
      for (std::size_t j = 0; j < nutrients.size(); ++j) {
        nutrients_result[j] +=
            data[i].nutrients[j] * foods[i]->solution_value();
      }
    }
  }
  LOG(INFO) << "";
  LOG(INFO) << "Optimal annual price: $"
            << std::to_string(365. * objective->Value());
  LOG(INFO) << "";
  LOG(INFO) << "Nutrients per day:";
  for (std::size_t i = 0; i < nutrients.size(); ++i) {
    LOG(INFO) << nutrients[i].first << ": "
              << std::to_string(nutrients_result[i]) << " (min "
              << std::to_string(nutrients[i].second) << ")";
  }

  LOG(INFO) << "";
  LOG(INFO) << "Advanced usage:";
  LOG(INFO) << "Problem solved in " << solver->wall_time() << " milliseconds";
  LOG(INFO) << "Problem solved in " << solver->iterations() << " iterations";
}
}  // namespace operations_research

int main(int argc, char** argv) {
  InitGoogle(argv[0], &argc, &argv, true);
  absl::SetFlag(&FLAGS_stderrthreshold, 0);
  operations_research::StiglerDiet();
  return EXIT_SUCCESS;
}

Java

// The Stigler diet problem.
package com.google.ortools.linearsolver.samples;
import com.google.ortools.Loader;
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
import java.util.ArrayList;
import java.util.List;

/** Stigler diet example. */
public final class StiglerDiet {
  public static void main(String[] args) {
    Loader.loadNativeLibraries();
    // Nutrient minimums.
    List<Object[]> nutrients = new ArrayList<>();
    nutrients.add(new Object[] {"Calories (kcal)", 3.0});
    nutrients.add(new Object[] {"Protein (g)", 70.0});
    nutrients.add(new Object[] {"Calcium (g)", 0.8});
    nutrients.add(new Object[] {"Iron (mg)", 12.0});
    nutrients.add(new Object[] {"Vitamin A (kIU)", 5.0});
    nutrients.add(new Object[] {"Vitamin B1 (mg)", 1.8});
    nutrients.add(new Object[] {"Vitamin B2 (mg)", 2.7});
    nutrients.add(new Object[] {"Niacin (mg)", 18.0});
    nutrients.add(new Object[] {"Vitamin C (mg)", 75.0});

    List<Object[]> data = new ArrayList<>();
    data.add(new Object[] {"Wheat Flour (Enriched)", "10 lb.", 36,
        new double[] {44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0}});
    data.add(new Object[] {
        "Macaroni", "1 lb.", 14.1, new double[] {11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0}});
    data.add(new Object[] {"Wheat Cereal (Enriched)", "28 oz.", 24.2,
        new double[] {11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0}});
    data.add(new Object[] {
        "Corn Flakes", "8 oz.", 7.1, new double[] {11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0}});
    data.add(new Object[] {
        "Corn Meal", "1 lb.", 4.6, new double[] {36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0}});
    data.add(new Object[] {
        "Hominy Grits", "24 oz.", 8.5, new double[] {28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0}});
    data.add(
        new Object[] {"Rice", "1 lb.", 7.5, new double[] {21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0}});
    data.add(new Object[] {
        "Rolled Oats", "1 lb.", 7.1, new double[] {25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0}});
    data.add(new Object[] {"White Bread (Enriched)", "1 lb.", 7.9,
        new double[] {15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0}});
    data.add(new Object[] {"Whole Wheat Bread", "1 lb.", 9.1,
        new double[] {12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0}});
    data.add(new Object[] {
        "Rye Bread", "1 lb.", 9.1, new double[] {12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0}});
    data.add(new Object[] {
        "Pound Cake", "1 lb.", 24.8, new double[] {8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0}});
    data.add(new Object[] {
        "Soda Crackers", "1 lb.", 15.1, new double[] {12.5, 288, 0.5, 50, 0, 0, 0, 0, 0}});
    data.add(
        new Object[] {"Milk", "1 qt.", 11, new double[] {6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177}});
    data.add(new Object[] {"Evaporated Milk (can)", "14.5 oz.", 6.7,
        new double[] {8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60}});
    data.add(
        new Object[] {"Butter", "1 lb.", 30.8, new double[] {10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0}});
    data.add(new Object[] {
        "Oleomargarine", "1 lb.", 16.1, new double[] {20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0}});
    data.add(new Object[] {
        "Eggs", "1 doz.", 32.6, new double[] {2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0}});
    data.add(new Object[] {"Cheese (Cheddar)", "1 lb.", 24.2,
        new double[] {7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0}});
    data.add(new Object[] {
        "Cream", "1/2 pt.", 14.1, new double[] {3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17}});
    data.add(new Object[] {
        "Peanut Butter", "1 lb.", 17.9, new double[] {15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0}});
    data.add(new Object[] {
        "Mayonnaise", "1/2 pt.", 16.7, new double[] {8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0}});
    data.add(new Object[] {"Crisco", "1 lb.", 20.3, new double[] {20.1, 0, 0, 0, 0, 0, 0, 0, 0}});
    data.add(new Object[] {"Lard", "1 lb.", 9.8, new double[] {41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0}});
    data.add(new Object[] {
        "Sirloin Steak", "1 lb.", 39.6, new double[] {2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0}});
    data.add(new Object[] {
        "Round Steak", "1 lb.", 36.4, new double[] {2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0}});
    data.add(
        new Object[] {"Rib Roast", "1 lb.", 29.2, new double[] {3.4, 213, 0.1, 33, 0, 0, 2, 0, 0}});
    data.add(new Object[] {
        "Chuck Roast", "1 lb.", 22.6, new double[] {3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0}});
    data.add(
        new Object[] {"Plate", "1 lb.", 14.6, new double[] {8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0}});
    data.add(new Object[] {"Liver (Beef)", "1 lb.", 26.8,
        new double[] {2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525}});
    data.add(new Object[] {
        "Leg of Lamb", "1 lb.", 27.6, new double[] {3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0}});
    data.add(new Object[] {
        "Lamb Chops (Rib)", "1 lb.", 36.6, new double[] {3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0}});
    data.add(new Object[] {
        "Pork Chops", "1 lb.", 30.7, new double[] {3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0}});
    data.add(new Object[] {
        "Pork Loin Roast", "1 lb.", 24.2, new double[] {4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0}});
    data.add(new Object[] {
        "Bacon", "1 lb.", 25.6, new double[] {10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0}});
    data.add(new Object[] {
        "Ham, smoked", "1 lb.", 27.4, new double[] {6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0}});
    data.add(new Object[] {
        "Salt Pork", "1 lb.", 16, new double[] {18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0}});
    data.add(new Object[] {"Roasting Chicken", "1 lb.", 30.3,
        new double[] {1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46}});
    data.add(new Object[] {
        "Veal Cutlets", "1 lb.", 42.3, new double[] {1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0}});
    data.add(new Object[] {
        "Salmon, Pink (can)", "16 oz.", 13, new double[] {5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0}});
    data.add(new Object[] {
        "Apples", "1 lb.", 4.4, new double[] {5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544}});
    data.add(new Object[] {
        "Bananas", "1 lb.", 6.1, new double[] {4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498}});
    data.add(
        new Object[] {"Lemons", "1 doz.", 26, new double[] {1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952}});
    data.add(new Object[] {
        "Oranges", "1 doz.", 30.9, new double[] {2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998}});
    data.add(new Object[] {
        "Green Beans", "1 lb.", 7.1, new double[] {2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862}});
    data.add(new Object[] {
        "Cabbage", "1 lb.", 3.7, new double[] {2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369}});
    data.add(new Object[] {
        "Carrots", "1 bunch", 4.7, new double[] {2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608}});
    data.add(new Object[] {
        "Celery", "1 stalk", 7.3, new double[] {0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313}});
    data.add(new Object[] {
        "Lettuce", "1 head", 8.2, new double[] {0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449}});
    data.add(new Object[] {
        "Onions", "1 lb.", 3.6, new double[] {5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184}});
    data.add(new Object[] {
        "Potatoes", "15 lb.", 34, new double[] {14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522}});
    data.add(new Object[] {
        "Spinach", "1 lb.", 8.1, new double[] {1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755}});
    data.add(new Object[] {"Sweet Potatoes", "1 lb.", 5.1,
        new double[] {9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912}});
    data.add(new Object[] {"Peaches (can)", "No. 2 1/2", 16.8,
        new double[] {3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196}});
    data.add(new Object[] {
        "Pears (can)", "No. 2 1/2", 20.4, new double[] {3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81}});
    data.add(new Object[] {
        "Pineapple (can)", "No. 2 1/2", 21.3, new double[] {2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399}});
    data.add(new Object[] {"Asparagus (can)", "No. 2", 27.7,
        new double[] {0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272}});
    data.add(new Object[] {
        "Green Beans (can)", "No. 2", 10, new double[] {1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431}});
    data.add(new Object[] {"Pork and Beans (can)", "16 oz.", 7.1,
        new double[] {7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0}});
    data.add(new Object[] {
        "Corn (can)", "No. 2", 10.4, new double[] {5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218}});
    data.add(new Object[] {
        "Peas (can)", "No. 2", 13.8, new double[] {2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370}});
    data.add(new Object[] {
        "Tomatoes (can)", "No. 2", 8.6, new double[] {1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253}});
    data.add(new Object[] {"Tomato Soup (can)", "10 1/2 oz.", 7.6,
        new double[] {1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862}});
    data.add(new Object[] {
        "Peaches, Dried", "1 lb.", 15.7, new double[] {8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57}});
    data.add(new Object[] {
        "Prunes, Dried", "1 lb.", 9, new double[] {12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257}});
    data.add(new Object[] {"Raisins, Dried", "15 oz.", 9.4,
        new double[] {13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136}});
    data.add(new Object[] {
        "Peas, Dried", "1 lb.", 7.9, new double[] {20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0}});
    data.add(new Object[] {"Lima Beans, Dried", "1 lb.", 8.9,
        new double[] {17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0}});
    data.add(new Object[] {"Navy Beans, Dried", "1 lb.", 5.9,
        new double[] {26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0}});
    data.add(new Object[] {"Coffee", "1 lb.", 22.4, new double[] {0, 0, 0, 0, 0, 4, 5.1, 50, 0}});
    data.add(new Object[] {"Tea", "1/4 lb.", 17.4, new double[] {0, 0, 0, 0, 0, 0, 2.3, 42, 0}});
    data.add(
        new Object[] {"Cocoa", "8 oz.", 8.6, new double[] {8.7, 237, 3, 72, 0, 2, 11.9, 40, 0}});
    data.add(new Object[] {
        "Chocolate", "8 oz.", 16.2, new double[] {8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0}});
    data.add(new Object[] {"Sugar", "10 lb.", 51.7, new double[] {34.9, 0, 0, 0, 0, 0, 0, 0, 0}});
    data.add(new Object[] {
        "Corn Syrup", "24 oz.", 13.7, new double[] {14.7, 0, 0.5, 74, 0, 0, 0, 5, 0}});
    data.add(new Object[] {
        "Molasses", "18 oz.", 13.6, new double[] {9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0}});
    data.add(new Object[] {"Strawberry Preserves", "1 lb.", 20.5,
        new double[] {6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0}});


    // Create the linear solver with the GLOP backend.
    MPSolver solver = MPSolver.createSolver("GLOP");
    if (solver == null) {
      System.out.println("Could not create solver GLOP");
      return;
    }

    double infinity = java.lang.Double.POSITIVE_INFINITY;
    List<MPVariable> foods = new ArrayList<>();
    for (int i = 0; i < data.size(); ++i) {
      foods.add(solver.makeNumVar(0.0, infinity, (String) data.get(i)[0]));
    }
    System.out.println("Number of variables = " + solver.numVariables());

    MPConstraint[] constraints = new MPConstraint[nutrients.size()];
    for (int i = 0; i < nutrients.size(); ++i) {
      constraints[i] = solver.makeConstraint(
          (double) nutrients.get(i)[1], infinity, (String) nutrients.get(i)[0]);
      for (int j = 0; j < data.size(); ++j) {
        constraints[i].setCoefficient(foods.get(j), ((double[]) data.get(j)[3])[i]);
      }
      // constraints.add(constraint);
    }
    System.out.println("Number of constraints = " + solver.numConstraints());

    MPObjective objective = solver.objective();
    for (int i = 0; i < data.size(); ++i) {
      objective.setCoefficient(foods.get(i), 1);
    }
    objective.setMinimization();

    final MPSolver.ResultStatus resultStatus = solver.solve();

    // Check that the problem has an optimal solution.
    if (resultStatus != MPSolver.ResultStatus.OPTIMAL) {
      System.err.println("The problem does not have an optimal solution!");
      if (resultStatus == MPSolver.ResultStatus.FEASIBLE) {
        System.err.println("A potentially suboptimal solution was found.");
      } else {
        System.err.println("The solver could not solve the problem.");
        return;
      }
    }

    // Display the amounts (in dollars) to purchase of each food.
    double[] nutrientsResult = new double[nutrients.size()];
    System.out.println("\nAnnual Foods:");
    for (int i = 0; i < foods.size(); ++i) {
      if (foods.get(i).solutionValue() > 0.0) {
        System.out.println((String) data.get(i)[0] + ": $" + 365 * foods.get(i).solutionValue());
        for (int j = 0; j < nutrients.size(); ++j) {
          nutrientsResult[j] += ((double[]) data.get(i)[3])[j] * foods.get(i).solutionValue();
        }
      }
    }
    System.out.println("\nOptimal annual price: $" + 365 * objective.value());

    System.out.println("\nNutrients per day:");
    for (int i = 0; i < nutrients.size(); ++i) {
      System.out.println(
          nutrients.get(i)[0] + ": " + nutrientsResult[i] + " (min " + nutrients.get(i)[1] + ")");
    }

    System.out.println("\nAdvanced usage:");
    System.out.println("Problem solved in " + solver.wallTime() + " milliseconds");
    System.out.println("Problem solved in " + solver.iterations() + " iterations");
  }

  private StiglerDiet() {}
}

C#

// The Stigler diet problem.
using System;
using System.Collections.Generic;
using Google.OrTools.LinearSolver;

public class StiglerDiet
{
    static void Main()
    {
        // Nutrient minimums.
        (String Name, double Value)[] nutrients =
            new[] { ("Calories (kcal)", 3.0), ("Protein (g)", 70.0),    ("Calcium (g)", 0.8),
                    ("Iron (mg)", 12.0),      ("Vitamin A (kIU)", 5.0), ("Vitamin B1 (mg)", 1.8),
                    ("Vitamin B2 (mg)", 2.7), ("Niacin (mg)", 18.0),    ("Vitamin C (mg)", 75.0) };

        (String Name, String Unit, double Price, double[] Nutrients)[] data = new[] {
            ("Wheat Flour (Enriched)", "10 lb.", 36, new double[] { 44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0 }),
            ("Macaroni", "1 lb.", 14.1, new double[] { 11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0 }),
            ("Wheat Cereal (Enriched)", "28 oz.", 24.2, new double[] { 11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0 }),
            ("Corn Flakes", "8 oz.", 7.1, new double[] { 11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0 }),
            ("Corn Meal", "1 lb.", 4.6, new double[] { 36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0 }),
            ("Hominy Grits", "24 oz.", 8.5, new double[] { 28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0 }),
            ("Rice", "1 lb.", 7.5, new double[] { 21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0 }),
            ("Rolled Oats", "1 lb.", 7.1, new double[] { 25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0 }),
            ("White Bread (Enriched)", "1 lb.", 7.9, new double[] { 15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0 }),
            ("Whole Wheat Bread", "1 lb.", 9.1, new double[] { 12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0 }),
            ("Rye Bread", "1 lb.", 9.1, new double[] { 12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0 }),
            ("Pound Cake", "1 lb.", 24.8, new double[] { 8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0 }),
            ("Soda Crackers", "1 lb.", 15.1, new double[] { 12.5, 288, 0.5, 50, 0, 0, 0, 0, 0 }),
            ("Milk", "1 qt.", 11, new double[] { 6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177 }),
            ("Evaporated Milk (can)", "14.5 oz.", 6.7, new double[] { 8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60 }),
            ("Butter", "1 lb.", 30.8, new double[] { 10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0 }),
            ("Oleomargarine", "1 lb.", 16.1, new double[] { 20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0 }),
            ("Eggs", "1 doz.", 32.6, new double[] { 2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0 }),
            ("Cheese (Cheddar)", "1 lb.", 24.2, new double[] { 7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0 }),
            ("Cream", "1/2 pt.", 14.1, new double[] { 3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17 }),
            ("Peanut Butter", "1 lb.", 17.9, new double[] { 15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0 }),
            ("Mayonnaise", "1/2 pt.", 16.7, new double[] { 8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0 }),
            ("Crisco", "1 lb.", 20.3, new double[] { 20.1, 0, 0, 0, 0, 0, 0, 0, 0 }),
            ("Lard", "1 lb.", 9.8, new double[] { 41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0 }),
            ("Sirloin Steak", "1 lb.", 39.6, new double[] { 2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0 }),
            ("Round Steak", "1 lb.", 36.4, new double[] { 2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0 }),
            ("Rib Roast", "1 lb.", 29.2, new double[] { 3.4, 213, 0.1, 33, 0, 0, 2, 0, 0 }),
            ("Chuck Roast", "1 lb.", 22.6, new double[] { 3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0 }),
            ("Plate", "1 lb.", 14.6, new double[] { 8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0 }),
            ("Liver (Beef)", "1 lb.", 26.8, new double[] { 2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525 }),
            ("Leg of Lamb", "1 lb.", 27.6, new double[] { 3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0 }),
            ("Lamb Chops (Rib)", "1 lb.", 36.6, new double[] { 3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0 }),
            ("Pork Chops", "1 lb.", 30.7, new double[] { 3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0 }),
            ("Pork Loin Roast", "1 lb.", 24.2, new double[] { 4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0 }),
            ("Bacon", "1 lb.", 25.6, new double[] { 10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0 }),
            ("Ham, smoked", "1 lb.", 27.4, new double[] { 6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0 }),
            ("Salt Pork", "1 lb.", 16, new double[] { 18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0 }),
            ("Roasting Chicken", "1 lb.", 30.3, new double[] { 1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46 }),
            ("Veal Cutlets", "1 lb.", 42.3, new double[] { 1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0 }),
            ("Salmon, Pink (can)", "16 oz.", 13, new double[] { 5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0 }),
            ("Apples", "1 lb.", 4.4, new double[] { 5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544 }),
            ("Bananas", "1 lb.", 6.1, new double[] { 4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498 }),
            ("Lemons", "1 doz.", 26, new double[] { 1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952 }),
            ("Oranges", "1 doz.", 30.9, new double[] { 2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998 }),
            ("Green Beans", "1 lb.", 7.1, new double[] { 2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862 }),
            ("Cabbage", "1 lb.", 3.7, new double[] { 2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369 }),
            ("Carrots", "1 bunch", 4.7, new double[] { 2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608 }),
            ("Celery", "1 stalk", 7.3, new double[] { 0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313 }),
            ("Lettuce", "1 head", 8.2, new double[] { 0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449 }),
            ("Onions", "1 lb.", 3.6, new double[] { 5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184 }),
            ("Potatoes", "15 lb.", 34, new double[] { 14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522 }),
            ("Spinach", "1 lb.", 8.1, new double[] { 1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755 }),
            ("Sweet Potatoes", "1 lb.", 5.1, new double[] { 9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912 }),
            ("Peaches (can)", "No. 2 1/2", 16.8, new double[] { 3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196 }),
            ("Pears (can)", "No. 2 1/2", 20.4, new double[] { 3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81 }),
            ("Pineapple (can)", "No. 2 1/2", 21.3, new double[] { 2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399 }),
            ("Asparagus (can)", "No. 2", 27.7, new double[] { 0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272 }),
            ("Green Beans (can)", "No. 2", 10, new double[] { 1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431 }),
            ("Pork and Beans (can)", "16 oz.", 7.1, new double[] { 7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0 }),
            ("Corn (can)", "No. 2", 10.4, new double[] { 5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218 }),
            ("Peas (can)", "No. 2", 13.8, new double[] { 2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370 }),
            ("Tomatoes (can)", "No. 2", 8.6, new double[] { 1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253 }),
            ("Tomato Soup (can)", "10 1/2 oz.", 7.6, new double[] { 1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862 }),
            ("Peaches, Dried", "1 lb.", 15.7, new double[] { 8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57 }),
            ("Prunes, Dried", "1 lb.", 9, new double[] { 12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257 }),
            ("Raisins, Dried", "15 oz.", 9.4, new double[] { 13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136 }),
            ("Peas, Dried", "1 lb.", 7.9, new double[] { 20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0 }),
            ("Lima Beans, Dried", "1 lb.", 8.9, new double[] { 17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0 }),
            ("Navy Beans, Dried", "1 lb.", 5.9, new double[] { 26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0 }),
            ("Coffee", "1 lb.", 22.4, new double[] { 0, 0, 0, 0, 0, 4, 5.1, 50, 0 }),
            ("Tea", "1/4 lb.", 17.4, new double[] { 0, 0, 0, 0, 0, 0, 2.3, 42, 0 }),
            ("Cocoa", "8 oz.", 8.6, new double[] { 8.7, 237, 3, 72, 0, 2, 11.9, 40, 0 }),
            ("Chocolate", "8 oz.", 16.2, new double[] { 8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0 }),
            ("Sugar", "10 lb.", 51.7, new double[] { 34.9, 0, 0, 0, 0, 0, 0, 0, 0 }),
            ("Corn Syrup", "24 oz.", 13.7, new double[] { 14.7, 0, 0.5, 74, 0, 0, 0, 5, 0 }),
            ("Molasses", "18 oz.", 13.6, new double[] { 9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0 }),
            ("Strawberry Preserves", "1 lb.", 20.5, new double[] { 6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0 })
        };

        // Create the linear solver with the GLOP backend.
        Solver solver = Solver.CreateSolver("GLOP");
        if (solver is null)
        {
            return;
        }

        List<Variable> foods = new List<Variable>();
        for (int i = 0; i < data.Length; ++i)
        {
            foods.Add(solver.MakeNumVar(0.0, double.PositiveInfinity, data[i].Name));
        }
        Console.WriteLine($"Number of variables = {solver.NumVariables()}");

        List<Constraint> constraints = new List<Constraint>();
        for (int i = 0; i < nutrients.Length; ++i)
        {
            Constraint constraint =
                solver.MakeConstraint(nutrients[i].Value, double.PositiveInfinity, nutrients[i].Name);
            for (int j = 0; j < data.Length; ++j)
            {
                constraint.SetCoefficient(foods[j], data[j].Nutrients[i]);
            }
            constraints.Add(constraint);
        }
        Console.WriteLine($"Number of constraints = {solver.NumConstraints()}");

        Objective objective = solver.Objective();
        for (int i = 0; i < data.Length; ++i)
        {
            objective.SetCoefficient(foods[i], 1);
        }
        objective.SetMinimization();

        Solver.ResultStatus resultStatus = solver.Solve();

        // Check that the problem has an optimal solution.
        if (resultStatus != Solver.ResultStatus.OPTIMAL)
        {
            Console.WriteLine("The problem does not have an optimal solution!");
            if (resultStatus == Solver.ResultStatus.FEASIBLE)
            {
                Console.WriteLine("A potentially suboptimal solution was found.");
            }
            else
            {
                Console.WriteLine("The solver could not solve the problem.");
                return;
            }
        }

        // Display the amounts (in dollars) to purchase of each food.
        double[] nutrientsResult = new double[nutrients.Length];
        Console.WriteLine("\nAnnual Foods:");
        for (int i = 0; i < foods.Count; ++i)
        {
            if (foods[i].SolutionValue() > 0.0)
            {
                Console.WriteLine($"{data[i].Name}: ${365 * foods[i].SolutionValue():N2}");
                for (int j = 0; j < nutrients.Length; ++j)
                {
                    nutrientsResult[j] += data[i].Nutrients[j] * foods[i].SolutionValue();
                }
            }
        }
        Console.WriteLine($"\nOptimal annual price: ${365 * objective.Value():N2}");

        Console.WriteLine("\nNutrients per day:");
        for (int i = 0; i < nutrients.Length; ++i)
        {
            Console.WriteLine($"{nutrients[i].Name}: {nutrientsResult[i]:N2} (min {nutrients[i].Value})");
        }

        Console.WriteLine("\nAdvanced usage:");
        Console.WriteLine($"Problem solved in {solver.WallTime()} milliseconds");
        Console.WriteLine($"Problem solved in {solver.Iterations()} iterations");
    }
}