ปัญหาอาหาร Stigler

ในส่วนนี้ เราจะแสดงวิธีแก้โจทย์คลาสสิกที่เรียกว่าอาหารสติ๊กเลอร์ ซึ่งตั้งชื่อตามเศรษฐศาสตร์ จอร์จ สติ๊กเลอร์ผู้ได้รับรางวัลโนเบล ผู้คิดค้นวิธีตอบสนองความต้องการทางโภชนาการพื้นฐานด้วยชุดอาหารที่ไม่แพง เขามองว่าเป็นแบบฝึกหัดทางคณิตศาสตร์ ไม่ใช่คำแนะนำในการกิน แม้ว่าแนวคิดเรื่องการคำนวณโภชนาการที่เหมาะสมจะเริ่มได้รับความนิยมเมื่อเร็วๆ นี้

อาหารของ Stigler กำหนดมาให้มีคุณสมบัติตรงตามเกณฑ์ขั้นต่ำดังต่อไปนี้

รายการสารอาหาร

สารอาหาร ปริมาณที่แนะนำในแต่ละวัน
แคลอรี 3,000 แคลอรี
โปรตีน 70 กรัม
แคลเซียม 0.8 กรัม
เหล็ก 12 มิลลิกรัม
วิตามินเอ 5,000 หน่วย IU
ไธอามีน (วิตามินบี 1) 1.8 มิลลิกรัม
ไรโบเฟลวิน (วิตามินบี 2) 2.7 มิลลิกรัม
ไนอาซิน 18 มิลลิกรัม
กรดแอสคอร์บิก (วิตามินซี) 75 มิลลิกรัม

ชุดอาหารที่ Stigler ได้รับการประเมินเป็นภาพสะท้อนจากเหตุการณ์ในอดีต (1944) ข้อมูลโภชนาการด้านล่างเป็นต่อดอลลาร์ ไม่ใช่ต่อหน่วย ดังนั้นวัตถุประสงค์คือการกำหนดจำนวนเงินที่จะใช้จ่ายกับอาหารแต่ละอย่าง

รายการโภคภัณฑ์

สินค้าโภคภัณฑ์ หน่วย ราคาปี 1939 (เซ็นต์) แคลอรี (กิโลแคลอรี) โปรตีน (ก.) แคลเซียม (ก.) ธาตุเหล็ก (มก.) วิตามินเอ (KIU) ไธอามีน (มก.) ไรโบเฟลวิน (มก.) ไนอาซิน (มก.) กรดแอสคอร์บิก (มก.)
แป้งสาลี (เข้มข้น) 10 ปอนด์ 36 44.7 1411 2 365 0 55.4 33.3 441 0
มักกะโรนี 1 ปอนด์ 14.1 11.6 418 0.7 54 0 3.2 1.9 68 0
ซีเรียลข้าวสาลี (เข้มข้น) 28 ออนซ์ 24.2 11.8 377 14.4 175 0 14.4 8.8 114 0
ข้าวโพดเฟลก 8 ออนซ์ 7.1 11.4 252 0.1 56 0 13.5 2.3 68 0
ข้าวโพด 1 ปอนด์ 4.6 36.0 897 1.7 99 30.9 17.4 7.9 106 0
ข้าวโพดบดหยาบ 24 ออนซ์ 8.5 28.6 680 0.8 80 0 10.6 1.6 110 0
ข้าว 1 ปอนด์ 7.5 21.2 460 0.6 41 0 2 4.8 60 0
ข้าวโอ๊ตชนิดรีด 1 ปอนด์ 7.1 25.3 907 5.1 341 0 37.1 8.9 64 0
ขนมปังขาว (เข้มข้น) 1 ปอนด์ 7.9 15.0 488 2.5 115 0 13.8 8.5 126 0
ขนมปังโฮลวีต 1 ปอนด์ 9.1 12.2 484 2.7 125 0 13.9 6.4 160 0
ขนมปังไรย์ 1 ปอนด์ 9.1 12.4 439 1.1 82 0 9.9 3 66 0
เค้กปอนด์ 1 ปอนด์ 24.8 8.0 130 0.4 31 18.9 2.8 3 17 0
แครกเกอร์โซดา 1 ปอนด์ 15.1 12.5 288 0.5 50 0 0 0 0 0
นม 1 ควอร์ต 11 6.1 310 10.5 18 16.8 4 16 7 177
นมข้นจืด (กระป๋อง) 14.5 ออนซ์ 6.7 8.4 422 15.1 9 26 3 23.5 11 60
เนย 1 ปอนด์ 30.8 10.8 9 0.2 3 44.2 0 0.2 2 0
โอลีโอมาร์การีน 1 ปอนด์ 16.1 20.6 17 0.6 6 55.8 0.2 0 0 0
ไข่ 1 โดซ 32.6 2.9 238 1.0 52 18.6 2.8 6.5 1 0
ชีส (เชดดาร์) 1 ปอนด์ 24.2 7.4 448 16.4 19 28.1 0.8 10.3 4 0
ครีม 1/2 คะแนน 14.1 3.5 49 1.7 3 16.9 0.6 2.5 0 17
เนยถั่ว 1 ปอนด์ 17.9 15.7 661 1.0 48 0 9.6 8.1 471 0
มายองเนส 1/2 คะแนน 16.7 8.6 18 0.2 8 2.7 0.4 0.5 0 0
คริสโก 1 ปอนด์ 20.3 20.1 0 0 0 0 0 0 0 0
น้ำมันหมู 1 ปอนด์ 9.8 41.7 0 0 0 0.2 0 0.5 5 0
สเต็กเนื้อเซอร์ลอย 1 ปอนด์ 39.6 2.9 166 0.1 34 0.2 2.1 2.9 69 0
สเต็กทรงกลม 1 ปอนด์ 36.4 2.2 214 0.1 32 0.4 2.5 2.4 87 0
เนื้อซี่โครง 1 ปอนด์ 29.2 3.4 213 0.1 33 0 0 2 0 0
เนื้อย่างแบบเช็ด 1 ปอนด์ 22.6 3.6 309 0.2 46 0.4 1 4 120 0
เพลต 1 ปอนด์ 14.6 8.5 404 0.2 62 0 0.9 0 0 0
ตับ (เนื้อ) 1 ปอนด์ 26.8 2.2 333 0.2 139 169.2 6.4 50.8 316 525
ขาแกะ 1 ปอนด์ 27.6 3.1 245 0.1 20 0 2.8 3.9 86 0
เนื้อแกะ (ซี่โครง) 1 ปอนด์ 36.6 3.3 140 0.1 15 0 1.7 2.7 54 0
พอร์คชอป 1 ปอนด์ 30.7 3.5 196 0.2 30 0 17.4 2.7 60 0
หมูสันนอก 1 ปอนด์ 24.2 4.4 249 0.3 37 0 18.2 3.6 79 0
เบคอน 1 ปอนด์ 25.6 10.4 152 0.2 23 0 1.8 1.8 71 0
แฮมรมควัน 1 ปอนด์ 27.4 6.7 212 0.2 31 0 9.9 3.3 50 0
หมูเกลือ 1 ปอนด์ 16 18.8 164 0.1 26 0 1.4 1.8 0 0
ไก่ย่าง 1 ปอนด์ 30.3 1.8 184 0.1 30 0.1 0.9 1.8 68 46
เนื้อลูกวัว 1 ปอนด์ 42.3 1.7 156 0.1 24 0 1.4 2.4 57 0
แซลมอน สีชมพู (กระป๋อง) 16 ออนซ์ 13 5.8 705 6.8 45 3.5 1 4.9 209 0
สิ่งที่อยู่ 1 ปอนด์ 4.4 5.8 27 0.5 36 7.3 3.6 2.7 5 544
กล้วย 1 ปอนด์ 6.1 4.9 60 0.4 30 17.4 2.5 3.5 28 498
เลมอน 1 โดซ 26 1.0 21 0.5 14 0 0.5 0 4 952
ส้ม 1 โดซ 30.9 2.2 40 1.1 18 11.1 3.6 1.3 10 1998
ถั่วแขก 1 ปอนด์ 7.1 2.4 138 3.7 80 69 4.3 5.8 37 862
กะหล่ำปลี 1 ปอนด์ 3.7 2.6 125 4.0 36 7.2 9 4.5 26 5369
แครอท 1 กลุ่ม 4.7 2.7 73 2.8 43 188.5 6.1 4.3 89 608
คึ่นช่ายฝรั่ง 1 ตัว 7.3 0.9 51 3.0 23 0.9 1.4 1.4 9 313
CANNOT TRANSLATE 1 หัว 8.2 0.4 27 1.1 22 112.4 1.8 3.4 11 449
หัวหอม 1 ปอนด์ 3.6 5.8 166 3.8 59 16.6 4.7 5.9 21 1184
มันฝรั่ง 15 ปอนด์ 34 14.3 336 1.8 118 6.7 29.4 7.1 198 2522
ปวยเล้ง 1 ปอนด์ 8.1 1.1 106 0 138 918.4 5.7 13.8 33 2755
มันเทศ 1 ปอนด์ 5.1 9.6 138 2.7 54 290.7 8.4 5.4 83 1912
ลูกพีช (กระป๋อง) ฉบับที่ 2 1/2 16.8 3.7 20 0.4 10 21.5 0.5 1 31 196
ลูกแพร์ (กระป๋อง) ฉบับที่ 2 1/2 20.4 3.0 8 0.3 8 0.8 0.8 0.8 5 81
สับปะรด (กระป๋อง) ฉบับที่ 2 1/2 21.3 2.4 16 0.4 8 2 2.8 0.8 7 399
หน่อไม้ฝรั่ง (กระป๋อง) ฉบับที่ 2 27.7 0.4 33 0.3 12 16.3 1.4 2.1 17 272
ถั่วเขียว (กระป๋อง) ฉบับที่ 2 10 1.0 54 2 65 53.9 1.6 4.3 32 431
เนื้อหมูและถั่ว (กระป๋อง) 16 ออนซ์ 7.1 7.5 364 4 134 3.5 8.3 7.7 56 0
ข้าวโพด (กระป๋อง) ฉบับที่ 2 10.4 5.2 136 0.2 16 12 1.6 2.7 42 218
ถั่วลันเตา (กระป๋อง) ฉบับที่ 2 13.8 2.3 136 0.6 45 34.9 4.9 2.5 37 370
มะเขือเทศ (กระป๋อง) ฉบับที่ 2 8.6 1.3 63 0.7 38 53.2 3.4 2.5 36 1253
ซุปมะเขือเทศ (กระป๋อง) 10 1/2 ออนซ์ 7.6 1.6 71 0.6 43 57.9 3.5 2.4 67 862
ลูกพีช ตากแห้ง 1 ปอนด์ 15.7 8.5 87 1.7 173 86.8 1.2 4.3 55 57
ลูกพรุนแห้ง 1 ปอนด์ 9 12.8 99 2.5 154 85.7 3.9 4.3 65 257
ลูกเกด อบแห้ง 15 ออนซ์ 9.4 13.5 104 2.5 136 4.5 6.3 1.4 24 136
ถั่วลันเตา อบแห้ง 1 ปอนด์ 7.9 20.0 1367 4.2 345 2.9 28.7 18.4 162 0
ถั่วลิมาอบแห้ง 1 ปอนด์ 8.9 17.4 1055 3.7 459 5.1 26.9 38.2 93 0
ถั่วขาวอบแห้ง 1 ปอนด์ 5.9 26.9 1691 11.4 792 0 38.4 24.6 217 0
กาแฟ 1 ปอนด์ 22.4 0 0 0 0 0 4 5.1 50 0
ชา 1/4 ปอนด์ 17.4 0 0 0 0 0 0 2.3 42 0
โกโก้ 8 ออนซ์ 8.6 8.7 237 3 72 0 2 11.9 40 0
ช็อกโกแลต 8 ออนซ์ 16.2 8.0 77 1.3 39 0 0.9 3.4 14 0
น้ำตาล 10 ปอนด์ 51.7 34.9 0 0 0 0 0 0 0 0
น้ำเชื่อมข้าวโพด 24 ออนซ์ 13.7 14.7 0 0.5 74 0 0 0 5 0
กากน้ำตาล 18 ออนซ์ 13.6 9.0 0 10.3 244 0 1.9 7.5 146 0
สตรอว์เบอร์รีเก็บรักษา 1 ปอนด์ 20.5 6.4 11 0.4 7 0.2 0.2 0.4 3 0

เนื่องจากสารอาหารทั้งหมดมีการปรับราคาตามราคามาตรฐาน วัตถุประสงค์ของเราจึงเป็นการลดผลรวมของอาหารให้เหลือน้อยที่สุด

ในปี 1944 Stigler คำนวณคำตอบที่ดีที่สุดเท่าที่เขาจะทำได้ ด้วยความโศกเศร้า

...ไม่มีวิธีโดยตรงใดๆ ในการหาค่าต่ำสุดของฟังก์ชันเชิงเส้นที่อยู่ภายใต้เงื่อนไขเชิงเส้น

เขาค้นพบอาหารชนิดหนึ่งที่ราคา $39.93 ต่อปี ในปี 1939 ในปี 1947 Jack Laderman ใช้วิธีการทางอย่างง่าย (ซึ่งเป็นสิ่งประดิษฐ์ล่าสุด) เพื่อหาทางออกที่ดีที่สุด เสมียน 9 คนนั่งเครื่องคิดเลขบนโต๊ะใช้เวลา 120 วันจึงจะได้คำตอบ

วิธีแก้ปัญหาที่ใช้เครื่องมือแก้โจทย์เชิงเส้น

ส่วนต่อไปนี้นำเสนอโปรแกรมที่ช่วยแก้ปัญหาการควบคุมอาหารของ Stigler

นำเข้า Wrapper เครื่องมือแก้โจทย์เชิงเส้น

นำเข้า Wrapper ของเครื่องมือแก้วิดีโอเชิงเส้น "หรือ" ซึ่งเป็นอินเทอร์เฟซสำหรับเครื่องมือแก้โจทย์เชิงเส้น [GLOP](/optimization/mip/glop0 ดังที่แสดงด้านล่าง)

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;

ข้อมูลสําหรับปัญหา

โค้ดต่อไปนี้สร้างอาร์เรย์ nutrients สำหรับความต้องการสารอาหารขั้นต่ำ และอาร์เรย์ data สำหรับตารางข้อมูลโภชนาการในคำตอบใดๆ

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 })
};

ประกาศเครื่องมือแก้โจทย์ LP

โค้ดต่อไปนี้จะสร้างอินสแตนซ์ของ 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;
}

สร้างตัวแปร

โค้ดต่อไปนี้จะสร้างตัวแปรสําหรับปัญหา

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()}");

เมธอด MakeNumVar จะสร้างตัวแปร food[i] 1 รายการสำหรับแต่ละแถวของตาราง ดังที่กล่าวไว้ก่อนหน้านี้ ข้อมูลโภชนาการเป็นค่าใช้จ่ายต่อดอลลาร์ ดังนั้น food[i] จึงเป็นจำนวนเงินที่ใช้จ่ายไปกับสินค้าโภคภัณฑ์ i

กําหนดข้อจํากัด

ข้อจำกัดสำหรับอาหารของ Stigler จำเป็นต้องมีปริมาณสารอาหารที่ได้รับจากอาหารทุกชนิดเป็นข้อกำหนดขั้นต่ำสำหรับสารอาหารแต่ละอย่าง ต่อไป เราจะเขียนข้อจำกัดเหล่านี้เป็นอสมการที่เกี่ยวข้องกับอาร์เรย์ data และ nutrients และตัวแปร food[i]

อย่างแรก ปริมาณสารอาหารiที่ได้จากอาหารjต่อดอลลาร์คือdata[j][i+3] (เราเพิ่ม 3 ลงในดัชนีคอลัมน์เนื่องจากข้อมูลสารอาหารเริ่มต้นในคอลัมน์ที่ 4 ของdata) เนื่องจากจำนวนเงินที่ใช้จ่ายไปกับอาหารjคือ food[j] ปริมาณสารอาหารiที่ได้จากอาหารjจึงเท่ากับ\(data[j][i+3] \cdot food[j]\) สุดท้าย เนื่องจากข้อกำหนดขั้นต่ำสำหรับสารอาหาร i คือ nutrients[i][1] เราจึงเขียนข้อจำกัด i ได้ดังนี้

\( \sum_{j} data[j][i+3] \cdot food[j] \geq nutrients[i][1] \;\;\;\;\; (1) \)
โค้ดต่อไปนี้จะระบุข้อจำกัดเหล่านี้

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()}");

เมธอด Python Constraint (ตามเมธอด C++ MakeRowConstraint) จะสร้างข้อจำกัดสำหรับปัญหา สําหรับแต่ละ i, constraint(nutrients[i][1], solver.infinity)

ซึ่งสร้างข้อจำกัดที่ชุดค่าผสมเชิงเส้นของตัวแปร food[j] (ถัดไปกำหนดไว้) มากกว่าหรือเท่ากับ nutrients[i][1] สัมประสิทธิ์ของนิพจน์เชิงเส้นจะกำหนดโดยเมธอด SetCoefficient ดังนี้ SetCoefficient(food[j], data[j][i+3]

การดำเนินการนี้จะกำหนดสัมประสิทธิ์ของ food[j] เป็น data[j][i+3]

เมื่อรวมข้อมูลทั้งหมดนี้เข้าด้วยกัน โค้ดจะกำหนดข้อจำกัดที่แสดงในข้อ (1) ด้านบน

สร้างวัตถุประสงค์

โค้ดต่อไปนี้กำหนดฟังก์ชันวัตถุประสงค์ของโจทย์

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();

ฟังก์ชันวัตถุประสงค์คือค่าใช้จ่ายรวมของอาหาร ซึ่งก็คือผลรวมของตัวแปร food[i]

เมธอด SetCoefficient จะตั้งค่าสัมประสิทธิ์ของฟังก์ชันวัตถุประสงค์ ซึ่งในกรณีนี้คือ 1 ทั้งหมด สุดท้าย SetMinimization ประกาศว่านี่คือปัญหาที่ลดลง

เรียกใช้เครื่องมือแก้โจทย์

โค้ดต่อไปนี้จะเรียกเครื่องมือแก้โจทย์

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 จะแก้ปัญหาในคอมพิวเตอร์ทั่วไปได้ภายในเวลาไม่ถึง 300 มิลลิวินาที

แสดงคำตอบ

โค้ดต่อไปนี้จะแสดงโซลูชัน

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})");
}

นี่คือเอาต์พุตของโปรแกรม

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

เขียนโค้ดโปรแกรมให้เสร็จสมบูรณ์

ดูรหัสทั้งหมดของโปรแกรมอาหาร Stigler ได้ที่ด้านล่าง

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");
    }
}