[{"data":1,"prerenderedAt":507},["ShallowReactive",2],{"dev-\u002Fdeveloper\u002Fexamples\u002Fdiet":3},{"id":4,"title":5,"body":6,"description":489,"extension":490,"faq":491,"meta":501,"navigation":89,"noindex":502,"path":503,"seo":504,"stem":505,"__hash__":506},"content\u002Fdeveloper\u002Fexamples\u002Fdiet.md","Solve the diet problem in Python",{"type":7,"value":8,"toc":483},"minimark",[9,13,26,31,34,38,41,412,417,421,435,438,442,468,479],[10,11,5],"h1",{"id":12},"solve-the-diet-problem-in-python",[14,15,16,17,21,22,25],"p",{},"The ",[18,19,20],"strong",{},"diet problem"," — choose how much of each food to buy so a set of nutrient\nrequirements is met at minimum cost — is the problem that motivated early linear\nprogramming (Stigler, 1945) and still the cleanest way to learn LP. With\n",[18,23,24],{},"quicopt"," it is a few lines in Python.",[27,28,30],"h2",{"id":29},"the-naive-approach","The naive approach",[14,32,33],{},"The tempting shortcut is to greedily pick the cheapest food per nutrient, or to\ntry combinations by hand. Because each food contributes to several nutrients at\nonce, that misses the cheapest balanced mix. The problem is linear — solve it\nexactly.",[27,35,37],{"id":36},"model-it-as-an-lp","Model it as an LP",[14,39,40],{},"A continuous variable per food is the quantity to buy. One constraint per\nnutrient enforces its minimum, and the objective minimizes total cost:",[42,43,49],"pre",{"className":44,"code":45,"filename":46,"language":47,"meta":48,"style":48},"language-python shiki shiki-themes github-dark","from ortools.math_opt.python import mathopt\nfrom quicopt import Client\n\n# Choose food quantities meeting nutrient minimums at minimum cost.\ncost    = [2.0, 3.5, 1.5, 4.0]\nprotein = [4.0, 6.0, 3.0, 8.0]\niron    = [2.0, 1.0, 4.0, 3.0]\nN = len(cost)\n\nmodel = mathopt.Model(name=\"diet\")\nx = [model.add_variable(lb=0.0, name=f\"food_{i}\") for i in range(N)]\nmodel.add_linear_constraint(sum(protein[i] * x[i] for i in range(N)) >= 20.0)\nmodel.add_linear_constraint(sum(iron[i] * x[i] for i in range(N)) >= 10.0)\nmodel.minimize(sum(cost[i] * x[i] for i in range(N)))\n\nclient = Client()\nprint(client.solve(model).display)\n","diet.py","python","",[50,51,52,71,84,91,98,133,162,189,203,208,232,293,330,361,387,392,403],"code",{"__ignoreMap":48},[53,54,57,61,65,68],"span",{"class":55,"line":56},"line",1,[53,58,60],{"class":59},"snl16","from",[53,62,64],{"class":63},"s95oV"," ortools.math_opt.python ",[53,66,67],{"class":59},"import",[53,69,70],{"class":63}," mathopt\n",[53,72,74,76,79,81],{"class":55,"line":73},2,[53,75,60],{"class":59},[53,77,78],{"class":63}," quicopt ",[53,80,67],{"class":59},[53,82,83],{"class":63}," Client\n",[53,85,87],{"class":55,"line":86},3,[53,88,90],{"emptyLinePlaceholder":89},true,"\n",[53,92,94],{"class":55,"line":93},4,[53,95,97],{"class":96},"sAwPA","# Choose food quantities meeting nutrient minimums at minimum cost.\n",[53,99,101,104,107,110,114,117,120,122,125,127,130],{"class":55,"line":100},5,[53,102,103],{"class":63},"cost    ",[53,105,106],{"class":59},"=",[53,108,109],{"class":63}," [",[53,111,113],{"class":112},"sDLfK","2.0",[53,115,116],{"class":63},", ",[53,118,119],{"class":112},"3.5",[53,121,116],{"class":63},[53,123,124],{"class":112},"1.5",[53,126,116],{"class":63},[53,128,129],{"class":112},"4.0",[53,131,132],{"class":63},"]\n",[53,134,136,139,141,143,145,147,150,152,155,157,160],{"class":55,"line":135},6,[53,137,138],{"class":63},"protein ",[53,140,106],{"class":59},[53,142,109],{"class":63},[53,144,129],{"class":112},[53,146,116],{"class":63},[53,148,149],{"class":112},"6.0",[53,151,116],{"class":63},[53,153,154],{"class":112},"3.0",[53,156,116],{"class":63},[53,158,159],{"class":112},"8.0",[53,161,132],{"class":63},[53,163,165,168,170,172,174,176,179,181,183,185,187],{"class":55,"line":164},7,[53,166,167],{"class":63},"iron    ",[53,169,106],{"class":59},[53,171,109],{"class":63},[53,173,113],{"class":112},[53,175,116],{"class":63},[53,177,178],{"class":112},"1.0",[53,180,116],{"class":63},[53,182,129],{"class":112},[53,184,116],{"class":63},[53,186,154],{"class":112},[53,188,132],{"class":63},[53,190,192,195,197,200],{"class":55,"line":191},8,[53,193,194],{"class":63},"N ",[53,196,106],{"class":59},[53,198,199],{"class":112}," len",[53,201,202],{"class":63},"(cost)\n",[53,204,206],{"class":55,"line":205},9,[53,207,90],{"emptyLinePlaceholder":89},[53,209,211,214,216,219,223,225,229],{"class":55,"line":210},10,[53,212,213],{"class":63},"model ",[53,215,106],{"class":59},[53,217,218],{"class":63}," mathopt.Model(",[53,220,222],{"class":221},"s9osk","name",[53,224,106],{"class":59},[53,226,228],{"class":227},"sU2Wk","\"diet\"",[53,230,231],{"class":63},")\n",[53,233,235,238,240,243,246,248,251,253,255,257,260,263,266,269,272,275,278,281,284,287,290],{"class":55,"line":234},11,[53,236,237],{"class":63},"x ",[53,239,106],{"class":59},[53,241,242],{"class":63}," [model.add_variable(",[53,244,245],{"class":221},"lb",[53,247,106],{"class":59},[53,249,250],{"class":112},"0.0",[53,252,116],{"class":63},[53,254,222],{"class":221},[53,256,106],{"class":59},[53,258,259],{"class":59},"f",[53,261,262],{"class":227},"\"food_",[53,264,265],{"class":112},"{",[53,267,268],{"class":63},"i",[53,270,271],{"class":112},"}",[53,273,274],{"class":227},"\"",[53,276,277],{"class":63},") ",[53,279,280],{"class":59},"for",[53,282,283],{"class":63}," i ",[53,285,286],{"class":59},"in",[53,288,289],{"class":112}," range",[53,291,292],{"class":63},"(N)]\n",[53,294,296,299,302,305,308,311,313,315,317,319,322,325,328],{"class":55,"line":295},12,[53,297,298],{"class":63},"model.add_linear_constraint(",[53,300,301],{"class":112},"sum",[53,303,304],{"class":63},"(protein[i] ",[53,306,307],{"class":59},"*",[53,309,310],{"class":63}," x[i] ",[53,312,280],{"class":59},[53,314,283],{"class":63},[53,316,286],{"class":59},[53,318,289],{"class":112},[53,320,321],{"class":63},"(N)) ",[53,323,324],{"class":59},">=",[53,326,327],{"class":112}," 20.0",[53,329,231],{"class":63},[53,331,333,335,337,340,342,344,346,348,350,352,354,356,359],{"class":55,"line":332},13,[53,334,298],{"class":63},[53,336,301],{"class":112},[53,338,339],{"class":63},"(iron[i] ",[53,341,307],{"class":59},[53,343,310],{"class":63},[53,345,280],{"class":59},[53,347,283],{"class":63},[53,349,286],{"class":59},[53,351,289],{"class":112},[53,353,321],{"class":63},[53,355,324],{"class":59},[53,357,358],{"class":112}," 10.0",[53,360,231],{"class":63},[53,362,364,367,369,372,374,376,378,380,382,384],{"class":55,"line":363},14,[53,365,366],{"class":63},"model.minimize(",[53,368,301],{"class":112},[53,370,371],{"class":63},"(cost[i] ",[53,373,307],{"class":59},[53,375,310],{"class":63},[53,377,280],{"class":59},[53,379,283],{"class":63},[53,381,286],{"class":59},[53,383,289],{"class":112},[53,385,386],{"class":63},"(N)))\n",[53,388,390],{"class":55,"line":389},15,[53,391,90],{"emptyLinePlaceholder":89},[53,393,395,398,400],{"class":55,"line":394},16,[53,396,397],{"class":63},"client ",[53,399,106],{"class":59},[53,401,402],{"class":63}," Client()\n",[53,404,406,409],{"class":55,"line":405},17,[53,407,408],{"class":112},"print",[53,410,411],{"class":63},"(client.solve(model).display)\n",[413,414],"term-result",{":rows":415,"cmd":416},"[\"├── shots\",\"│   ├── 1 · primal-dual · global   10   0.04s  ◀ best\",\"│   └── 2 · primal-dual · global   10   0.05s\",\"├── status:     optimal\",\"├── feasible:   true\",\"├── objective:  10.0\",\"├── x:          food_0=5, food_1=0, food_2=0, food_3=0  (4 variables)\",\"└── solve_time: 0.0491 s\"]","$ python diet.py",[27,418,420],{"id":419},"what-you-get","What you get",[14,422,423,426,427,430,431,434],{},[50,424,425],{},"status: optimal"," means the plan is ",[18,428,429],{},"proven"," cheapest — cost ",[50,432,433],{},"10.0",", meeting\nboth the protein (≥20) and iron (≥10) minimums, in a fraction of a second.",[14,436,437],{},"The same model scales to hundreds of foods and dozens of nutrients — you change\nthe data, not the method. (An illustrative optimization example, not nutritional\nadvice.)",[27,439,441],{"id":440},"next","Next",[443,444,445,454,461],"ul",{},[446,447,448,449],"li",{},"The problem class behind this: ",[450,451,453],"a",{"href":452},"\u002Fproblems\u002Flp","Linear programming (LP)",[446,455,456,457],{},"A runnable model for every supported class: ",[450,458,460],{"href":459},"\u002Fdeveloper\u002Fexamples\u002Fby-class","Examples",[446,462,463,464],{},"Set up the client and solve your first model: ",[450,465,467],{"href":466},"\u002Fdeveloper\u002Fdocs\u002Fquickstart","Getting started",[14,469,470,473,474,478],{},[18,471,472],{},"Reference:"," G. J. Stigler, ",[475,476,477],"em",{},"The Cost of Subsistence",", Journal of Farm\nEconomics, 1945.",[480,481,482],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":48,"searchDepth":73,"depth":73,"links":484},[485,486,487,488],{"id":29,"depth":73,"text":30},{"id":36,"depth":73,"text":37},{"id":419,"depth":73,"text":420},{"id":440,"depth":73,"text":441},"The diet problem — choose how much of each food to buy so a set of nutrient\nrequirements is met at minimum cost — is the problem that motivated early linear\nprogramming (Stigler, 1945) and still the cleanest way to learn LP. With\nquicopt it is a few lines in Python.","md",[492,495,498],{"q":493,"a":494},"Why not just pick the cheapest food that covers each nutrient?","Foods contribute to several nutrients at once, so a greedy pick over- or under-shoots and costs more. The LP balances all nutrients simultaneously at minimum cost.",{"q":496,"a":497},"Can I add upper bounds or variety constraints?","Yes — maximum servings, calorie caps, or 'at least k foods' are extra linear constraints on the same model.",{"q":499,"a":500},"Is quicopt free to use?","Yes, to start: sign up for a free account, install the client with pip install \"quicopt[mathopt]\" and set your API key. The free account solves models with up to 50 variables and has a limited compute allowance; no license is needed.",{},false,"\u002Fdeveloper\u002Fexamples\u002Fdiet",{"title":5,"description":489},"developer\u002Fexamples\u002Fdiet","t8_PClhqdgNw732OCvapypW-chu51DTLAV6i5p71M68",1794337679420]