[{"data":1,"prerenderedAt":566},["ShallowReactive",2],{"dev-\u002Fdeveloper\u002Fdocs\u002Fmodeling":3},{"id":4,"title":5,"body":6,"description":557,"extension":558,"faq":559,"meta":560,"navigation":293,"noindex":561,"path":562,"seo":563,"stem":564,"__hash__":565},"content\u002Fdeveloper\u002Fdocs\u002Fmodeling.md","Modeling front-ends — Pyomo, OR-Tools MathOpt, JuMP",{"type":7,"value":8,"toc":548},"minimark",[9,14,18,88,93,100,105,196,200,235,250,254,265,466,475,479,508,512,539,544],[10,11,13],"h1",{"id":12},"modeling-front-ends","Modeling front-ends",[15,16,17],"p",{},"There is no Quicopt-specific modeling language to learn. You write the model in\na front-end you already know and hand it to the client's solve call; the client\nconverts it.",[19,20,21,37],"table",{},[22,23,24],"thead",{},[25,26,27,31,34],"tr",{},[28,29,30],"th",{},"Language",[28,32,33],{},"Front-end",[28,35,36],{},"Install",[38,39,40,59,72],"tbody",{},[25,41,42,46,49],{},[43,44,45],"td",{},"Python",[43,47,48],{},"Pyomo, OR-Tools MathOpt",[43,50,51,55,56],{},[52,53,54],"code",{},"pip install \"quicopt[pyomo]\""," or ",[52,57,58],{},"\"quicopt[mathopt]\"",[25,60,61,64,67],{},[43,62,63],{},"Julia",[43,65,66],{},"JuMP",[43,68,69],{},[52,70,71],{},"Pkg.add([\"QuicoptClient\", \"JuMP\"])",[25,73,74,77,80],{},[43,75,76],{},"R, Ruby",[43,78,79],{},"the client's own model",[43,81,82,83],{},"see ",[84,85,87],"a",{"href":86},"\u002Fdeveloper\u002Fdocs\u002Fclients","Client libraries",[89,90,92],"h2",{"id":91},"python-pyomo-and-or-tools-mathopt","Python: Pyomo and OR-Tools MathOpt",[15,94,95,96,99],{},"Both extras can be installed side by side; ",[52,97,98],{},"solve()"," dispatches on the model\ntype you pass in.",[101,102,104],"h3",{"id":103},"what-each-front-end-can-express","What each front-end can express",[19,106,107,119],{},[22,108,109],{},[25,110,111,113,116],{},[28,112],{},[28,114,115],{},"Pyomo",[28,117,118],{},"OR-Tools MathOpt",[38,120,121,139,167,177],{},[25,122,123,126,136],{},[43,124,125],{},"Objectives",[43,127,128,129,132,133],{},"linear, quadratic, and general non-linear — ",[52,130,131],{},"+ - * \u002F ^"," and ",[52,134,135],{},"sin cos exp log sqrt abs",[43,137,138],{},"linear and quadratic",[25,140,141,144,157],{},[43,142,143],{},"Constraints",[43,145,146,149,150,149,153,156],{},[52,147,148],{},"=="," \u002F ",[52,151,152],{},"\u003C=",[52,154,155],{},">="," \u002F ranged, including non-linear expressions",[43,158,159,160,149,162,149,164,166],{},"linear: ",[52,161,148],{},[52,163,152],{},[52,165,155],{}," \u002F ranged and one-sided",[25,168,169,172,175],{},[43,170,171],{},"Variables",[43,173,174],{},"bounds (incl. unbounded), continuous \u002F integer \u002F binary",[43,176,174],{},[25,178,179,182,190],{},[43,180,181],{},"Sense",[43,183,184,149,187],{},[52,185,186],{},"minimize",[52,188,189],{},"maximize",[43,191,192,149,194],{},[52,193,186],{},[52,195,189],{},[101,197,199],{"id":198},"which-one-to-pick","Which one to pick",[201,202,203,218],"ul",{},[204,205,206,209,210,213,214,217],"li",{},[207,208,118],"strong",{}," for LP, QP, MILP, and QUBO models. Your variable names\nsurvive into ",[52,211,212],{},"result.solution",", and the vectorised quadratic form\n(",[52,215,216],{},"x @ Q @ x"," with numpy) is a natural fit for QUBOs.",[204,219,220,222,223,226,227,230,231,234],{},[207,221,115],{}," when the model is genuinely non-linear — ",[52,224,225],{},"exp",", ",[52,228,229],{},"log",",\ntrigonometry, powers beyond quadratic — including MINLP (binary decisions\nmixed into a non-linear model) and higher-order binary polynomials\n(PUBO\u002FHUBO). Note that the Pyomo front-end currently returns generic\n",[52,232,233],{},"x1, x2, …"," solution keys.",[15,236,237,238,244,245,249],{},"Whatever the front-end, the same ",[84,239,241],{"href":240},"\u002Fdeveloper\u002Fdocs\u002Fapi#the-result-object",[52,242,243],{},"Result","\ncomes back, and the ",[84,246,248],{"href":247},"\u002Fdeveloper\u002Fdocs\u002Fapi#status-semantics","status semantics"," are\nidentical.",[89,251,253],{"id":252},"julia-jump","Julia: JuMP",[15,255,256,257,260,261,264],{},"The Julia client reads JuMP models: affine, quadratic and non-linear objectives\nand constraints, variable bounds (unbounded included), integrality, and ",[52,258,259],{},"Min"," or\n",[52,262,263],{},"Max",". The model you build for any other JuMP solver goes to Quicopt as it is:",[266,267,273],"pre",{"className":268,"code":269,"filename":270,"language":271,"meta":272,"style":272},"language-julia shiki shiki-themes github-dark","using QuicoptClient, JuMP\n\n# A tiny mixed-integer model: one continuous and one integer variable.\nmodel = Model()\n@variable(model, x >= 0)\n@variable(model, 0 \u003C= y \u003C= 10, Int)\n@constraint(model, x + 2y \u003C= 14)\n@constraint(model, 3x - y >= 0)\n@objective(model, Max, 3x + 4y)\n\nresult = solve(model)   # reads QUICOPT_API_KEY\nprintln(result.objective)\n","milp.jl","julia","",[52,274,275,288,295,302,318,335,360,384,408,429,434,451],{"__ignoreMap":272},[276,277,280,284],"span",{"class":278,"line":279},"line",1,[276,281,283],{"class":282},"snl16","using",[276,285,287],{"class":286},"s95oV"," QuicoptClient, JuMP\n",[276,289,291],{"class":278,"line":290},2,[276,292,294],{"emptyLinePlaceholder":293},true,"\n",[276,296,298],{"class":278,"line":297},3,[276,299,301],{"class":300},"sAwPA","# A tiny mixed-integer model: one continuous and one integer variable.\n",[276,303,305,308,311,315],{"class":278,"line":304},4,[276,306,307],{"class":286},"model ",[276,309,310],{"class":282},"=",[276,312,314],{"class":313},"sDLfK"," Model",[276,316,317],{"class":286},"()\n",[276,319,321,324,327,329,332],{"class":278,"line":320},5,[276,322,323],{"class":313},"@variable",[276,325,326],{"class":286},"(model, x ",[276,328,155],{"class":282},[276,330,331],{"class":313}," 0",[276,333,334],{"class":286},")\n",[276,336,338,340,343,346,349,352,354,357],{"class":278,"line":337},6,[276,339,323],{"class":313},[276,341,342],{"class":286},"(model, ",[276,344,345],{"class":313},"0",[276,347,348],{"class":282}," \u003C=",[276,350,351],{"class":286}," y ",[276,353,152],{"class":282},[276,355,356],{"class":313}," 10",[276,358,359],{"class":286},", Int)\n",[276,361,363,366,368,371,374,377,379,382],{"class":278,"line":362},7,[276,364,365],{"class":313},"@constraint",[276,367,326],{"class":286},[276,369,370],{"class":282},"+",[276,372,373],{"class":313}," 2",[276,375,376],{"class":286},"y ",[276,378,152],{"class":282},[276,380,381],{"class":313}," 14",[276,383,334],{"class":286},[276,385,387,389,391,394,397,400,402,404,406],{"class":278,"line":386},8,[276,388,365],{"class":313},[276,390,342],{"class":286},[276,392,393],{"class":313},"3",[276,395,396],{"class":286},"x ",[276,398,399],{"class":282},"-",[276,401,351],{"class":286},[276,403,155],{"class":282},[276,405,331],{"class":313},[276,407,334],{"class":286},[276,409,411,414,417,419,421,423,426],{"class":278,"line":410},9,[276,412,413],{"class":313},"@objective",[276,415,416],{"class":286},"(model, Max, ",[276,418,393],{"class":313},[276,420,396],{"class":286},[276,422,370],{"class":282},[276,424,425],{"class":313}," 4",[276,427,428],{"class":286},"y)\n",[276,430,432],{"class":278,"line":431},10,[276,433,294],{"emptyLinePlaceholder":293},[276,435,437,440,442,445,448],{"class":278,"line":436},11,[276,438,439],{"class":286},"result ",[276,441,310],{"class":282},[276,443,444],{"class":313}," solve",[276,446,447],{"class":286},"(model)   ",[276,449,450],{"class":300},"# reads QUICOPT_API_KEY\n",[276,452,454,457,460,463],{"class":278,"line":453},12,[276,455,456],{"class":313},"println",[276,458,459],{"class":286},"(result",[276,461,462],{"class":282},".",[276,464,465],{"class":286},"objective)\n",[15,467,468,469,462],{},"The full list of what the Julia client can express, including stochastic terms\nand orderings, is in its ",[84,470,474],{"href":471,"rel":472},"https:\u002F\u002Fquicopt.github.io\u002FQuicoptClient.jl\u002F",[473],"nofollow","reference ↗",[89,476,478],{"id":477},"r-and-ruby-the-clients-own-model","R and Ruby: the client's own model",[15,480,481,482,485,486,55,488,490,491,495,496,501,502,507],{},"The R and Ruby clients come with their own model object: you declare variables\non it (",[52,483,484],{},"bin_var",", …), state the objective with ",[52,487,186],{},[52,489,189],{},", and\nsolve it. The ",[84,492,494],{"href":493},"\u002Fdeveloper\u002Fdocs\u002Fquickstart","quickstart"," shows a complete example\nin each; the ",[84,497,500],{"href":498,"rel":499},"https:\u002F\u002Fquicopt.github.io\u002Fquicopt-r\u002F",[473],"R reference ↗"," and the\n",[84,503,506],{"href":504,"rel":505},"https:\u002F\u002Fquicopt.github.io\u002Fquicopt-ruby\u002F",[473],"Ruby reference ↗"," list the rest.",[89,509,511],{"id":510},"problem-classes","Problem classes",[15,513,514,515,518,519,523,524,527,528,534,535,538],{},"Today the service solves ",[207,516,517],{},"LP, QP, MILP, MIQP, MINLP, QUBO, PUBO\u002FHUBO, and NLP"," —\nsee the ",[84,520,522],{"href":521},"\u002Fdeveloper\u002Fexamples\u002Fby-class","runnable example for each class",".\n",[207,525,526],{},"Black-box objectives are coming soon","; a model outside\ntoday's classes is declined with a readable message (a\n",[84,529,531],{"href":530},"\u002Fdeveloper\u002Fdocs\u002Fapi#errors-quicopterror",[52,532,533],{},"QuicoptError"," with\n",[52,536,537],{},"reason: \"unsupported_model\"","), never a wrong result.",[540,541],"contact-cta",{"sub":542,"title":543},"Tell us what you're optimizing — we'll let you know as soon as your problem class ships.","Need a class that isn't live yet?",[545,546,547],"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 .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":272,"searchDepth":290,"depth":290,"links":549},[550,554,555,556],{"id":91,"depth":290,"text":92,"children":551},[552,553],{"id":103,"depth":297,"text":104},{"id":198,"depth":297,"text":199},{"id":252,"depth":290,"text":253},{"id":477,"depth":290,"text":478},{"id":510,"depth":290,"text":511},"Which modeling front-end each Quicopt client reads — Pyomo and OR-Tools MathOpt in Python, JuMP in Julia, the client's own model in R and Ruby — and what each can express.","md",null,{},false,"\u002Fdeveloper\u002Fdocs\u002Fmodeling",{"title":5,"description":557},"developer\u002Fdocs\u002Fmodeling","6kyPHmkCTa5il-5SsgsW_PjkX1--u92RIfkuAgkGpcc",1794337679389]