[{"data":1,"prerenderedAt":906},["ShallowReactive",2],{"dev-\u002Fdeveloper\u002Fapi":3},{"id":4,"title":5,"body":6,"description":899,"extension":900,"meta":901,"navigation":114,"path":902,"seo":903,"stem":904,"__hash__":905},"content\u002Fdeveloper\u002Fapi.md","API reference",{"type":7,"value":8,"toc":887},"minimark",[9,13,17,47,76,83,86,134,203,214,220,229,263,310,323,330,486,505,509,580,586,592,668,713,730,737,740,800,860,871,875,878,883],[10,11,5],"h1",{"id":12},"api-reference",[14,15,16],"p",{},"The supported way to call Quicopt is the official Python client:",[18,19,24],"pre",{"className":20,"code":21,"language":22,"meta":23,"style":23},"language-bash shiki shiki-themes github-dark","pip install \"quicopt[mathopt]\"   # or quicopt[pyomo]\n","bash","",[25,26,27],"code",{"__ignoreMap":23},[28,29,32,36,40,43],"span",{"class":30,"line":31},"line",1,[28,33,35],{"class":34},"svObZ","pip",[28,37,39],{"class":38},"sU2Wk"," install",[28,41,42],{"class":38}," \"quicopt[mathopt]\"",[28,44,46],{"class":45},"sAwPA","   # or quicopt[pyomo]\n",[14,48,49,50,53,54,57,58,61,62,69,70,75],{},"This page describes it in full — ",[25,51,52],{},"Client",", ",[25,55,56],{},"solve()",", the ",[25,59,60],{},"Result"," it returns,\nerror handling, and the async job API for long solves. Package links:\n",[63,64,68],"a",{"href":65,"rel":66},"https:\u002F\u002Fpypi.org\u002Fproject\u002Fquicopt\u002F",[67],"nofollow","PyPI"," ·\n",[63,71,74],{"href":72,"rel":73},"https:\u002F\u002Fgithub.com\u002Ftimbode\u002Fquicopt-python",[67],"source & docs"," (Apache-2.0).",[77,78,80],"h2",{"id":79},"clientbase_url-api_keynone-timeout600",[25,81,82],{},"Client(base_url, api_key=None, *, timeout=60.0)",[14,84,85],{},"A connection to the Quicopt service. It holds your API key — and if you don't\nhave one, your very first call sets one up automatically:",[18,87,91],{"className":88,"code":89,"language":90,"meta":23,"style":23},"language-python shiki shiki-themes github-dark","from quicopt import Client\n\nclient = Client(\"https:\u002F\u002Ftry.quicoptapi.pgi.fz-juelich.de\")\n","python",[25,92,93,109,116],{"__ignoreMap":23},[28,94,95,99,103,106],{"class":30,"line":31},[28,96,98],{"class":97},"snl16","from",[28,100,102],{"class":101},"s95oV"," quicopt ",[28,104,105],{"class":97},"import",[28,107,108],{"class":101}," Client\n",[28,110,112],{"class":30,"line":111},2,[28,113,115],{"emptyLinePlaceholder":114},true,"\n",[28,117,119,122,125,128,131],{"class":30,"line":118},3,[28,120,121],{"class":101},"client ",[28,123,124],{"class":97},"=",[28,126,127],{"class":101}," Client(",[28,129,130],{"class":38},"\"https:\u002F\u002Ftry.quicoptapi.pgi.fz-juelich.de\"",[28,132,133],{"class":101},")\n",[135,136,137,153],"table",{},[138,139,140],"thead",{},[141,142,143,147,150],"tr",{},[144,145,146],"th",{},"Parameter",[144,148,149],{},"Type",[144,151,152],{},"Meaning",[154,155,156,172,187],"tbody",{},[141,157,158,164,169],{},[159,160,161],"td",{},[25,162,163],{},"base_url",[159,165,166],{},[25,167,168],{},"str",[159,170,171],{},"the service address",[141,173,174,179,184],{},[159,175,176],{},[25,177,178],{},"api_key",[159,180,181,183],{},[25,182,168],{},", optional",[159,185,186],{},"a key you already have; leave it out and the first call sets one up",[141,188,189,194,200],{},[159,190,191],{},[25,192,193],{},"timeout",[159,195,196,199],{},[25,197,198],{},"float",", keyword-only",[159,201,202],{},"per-request timeout in seconds (default 60)",[14,204,205,206,209,210,213],{},"After the first call the key is readable back from ",[25,207,208],{},"client.api_key"," — pass it\nto a later ",[25,211,212],{},"Client(url, api_key=...)"," to keep solving as the same caller across\nruns.",[77,215,217],{"id":216},"clientsolvemodel-gzipfalse",[25,218,219],{},"client.solve(model, *, gzip=False)",[14,221,222,223,228],{},"Solves a model synchronously and returns a ",[63,224,226],{"href":225},"#the-result-object",[25,227,60],{},". This\nis the call you'll use most:",[18,230,232],{"className":88,"code":231,"language":90,"meta":23,"style":23},"result = client.solve(model)\nprint(result.status, result.objective)\nprint(result.display)        # the framed, ready-to-print summary\n",[25,233,234,244,253],{"__ignoreMap":23},[28,235,236,239,241],{"class":30,"line":31},[28,237,238],{"class":101},"result ",[28,240,124],{"class":97},[28,242,243],{"class":101}," client.solve(model)\n",[28,245,246,250],{"class":30,"line":111},[28,247,249],{"class":248},"sDLfK","print",[28,251,252],{"class":101},"(result.status, result.objective)\n",[28,254,255,257,260],{"class":30,"line":118},[28,256,249],{"class":248},[28,258,259],{"class":101},"(result.display)        ",[28,261,262],{"class":45},"# the framed, ready-to-print summary\n",[135,264,265,275],{},[138,266,267],{},[141,268,269,271,273],{},[144,270,146],{},[144,272,149],{},[144,274,152],{},[154,276,277,295],{},[141,278,279,284,287],{},[159,280,281],{},[25,282,283],{},"model",[159,285,286],{},"Pyomo or MathOpt model",[159,288,289,290,294],{},"the model to solve, passed directly — the client converts it for you (see ",[63,291,293],{"href":292},"\u002Fdeveloper\u002Fdata-format","Modeling front-ends",")",[141,296,297,302,307],{},[159,298,299],{},[25,300,301],{},"gzip",[159,303,304,199],{},[25,305,306],{},"bool",[159,308,309],{},"compress the request body — useful for large models",[14,311,312,313,315,316,322],{},"If the service declines a request — for example a problem class that isn't\nsolved yet — ",[25,314,56],{}," raises ",[63,317,319],{"href":318},"#errors-quicopterror",[25,320,321],{},"QuicoptError",". A declined\nrequest never returns a half-filled result.",[77,324,326,327,329],{"id":325},"the-result-object","The ",[25,328,60],{}," object",[135,331,332,343],{},[138,333,334],{},[141,335,336,339,341],{},[144,337,338],{},"Field",[144,340,149],{},[144,342,152],{},[154,344,345,374,395,414,429,458,472],{},[141,346,347,352,356],{},[159,348,349],{},[25,350,351],{},"status",[159,353,354],{},[25,355,168],{},[159,357,358,361,362,361,365,361,368,361,371],{},[25,359,360],{},"optimal"," · ",[25,363,364],{},"heuristic",[25,366,367],{},"iteration_limit",[25,369,370],{},"infeasible",[25,372,373],{},"unbounded",[141,375,376,381,389],{},[159,377,378],{},[25,379,380],{},"objective",[159,382,383,385,386],{},[25,384,198],{}," or ",[25,387,388],{},"None",[159,390,391,392,394],{},"objective value; ",[25,393,388],{}," when there is no solution",[141,396,397,402,408],{},[159,398,399],{},[25,400,401],{},"feasible",[159,403,404,385,406],{},[25,405,306],{},[25,407,388],{},[159,409,410,411,413],{},"whether the returned solution satisfies all constraints; ",[25,412,388],{}," where that's undefined (e.g. an unconstrained heuristic)",[141,415,416,421,426],{},[159,417,418],{},[25,419,420],{},"solution",[159,422,423],{},[25,424,425],{},"dict[str, float]",[159,427,428],{},"variable name → value; empty for infeasible\u002Funbounded",[141,430,431,436,442],{},[159,432,433],{},[25,434,435],{},"model_class",[159,437,438,385,440],{},[25,439,168],{},[25,441,388],{},[159,443,444,445,53,448,53,451,53,454,457],{},"how the service classified the model (",[25,446,447],{},"lp",[25,449,450],{},"qp",[25,452,453],{},"milp",[25,455,456],{},"qubo",", …)",[141,459,460,465,469],{},[159,461,462],{},[25,463,464],{},"solve_time_seconds",[159,466,467],{},[25,468,198],{},[159,470,471],{},"solve wall time",[141,473,474,479,483],{},[159,475,476],{},[25,477,478],{},"display",[159,480,481],{},[25,482,168],{},[159,484,485],{},"the framed console report — print it and you get the result view from the examples",[14,487,488,489,493,494,496,497,500,501,504],{},"With the ",[490,491,492],"strong",{},"MathOpt"," front-end, ",[25,495,420],{}," keys are your variable names from the\nmodel — name your variables and you can read the result without bookkeeping.\nThe ",[490,498,499],{},"Pyomo"," front-end currently returns generic ",[25,502,503],{},"x1, x2, …"," keys.",[77,506,508],{"id":507},"status-semantics","Status semantics",[510,511,512,524,537,546,573],"ul",{},[513,514,515,519,520,523],"li",{},[490,516,517],{},[25,518,360],{}," — proven optimum (typical for LP\u002FQP\u002FMILP); ",[25,521,522],{},"feasible: True",".",[513,525,526,530,531,533,534,536],{},[490,527,528],{},[25,529,364],{}," — best solution found across several shots, optimality not\nproven (typical for QUBO); ",[25,532,401],{}," is ",[25,535,388],{}," when there are no constraints\nto check.",[513,538,539,543,544,523],{},[490,540,541],{},[25,542,367],{}," — the solver stopped at its iteration cap and returns\nthe best point found (can happen on hard NLPs); treat it like ",[25,545,364],{},[513,547,548,552,553,555,556,53,558,560,561,564,565,568,569,523],{},[490,549,550],{},[25,551,370],{}," — no assignment satisfies the constraints; ",[25,554,380],{}," is\n",[25,557,388],{},[25,559,420],{}," is empty. This is a ",[490,562,563],{},"regular status, not an error"," —\ncheck ",[25,566,567],{},"result.status"," rather than catching exceptions. There's a\n",[63,570,572],{"href":571},"\u002Fdeveloper\u002Fexamples#handling-an-infeasible-model","worked example",[513,574,575,579],{},[490,576,577],{},[25,578,373],{}," — the objective can be improved without limit; also a regular\nstatus.",[77,581,583,584],{"id":582},"errors-quicopterror","Errors: ",[25,585,321],{},[14,587,588,589,591],{},"Anything the service declines raises ",[25,590,321],{}," with three useful fields:",[18,593,595],{"className":88,"code":594,"language":90,"meta":23,"style":23},"from quicopt import Client, QuicoptError\n\ntry:\n    result = client.solve(model)\nexcept QuicoptError as e:\n    print(e.reason)     # stable code, e.g. \"unsupported_model\"\n    print(e.display)    # the service's readable message, with a help contact\n",[25,596,597,608,612,620,630,645,657],{"__ignoreMap":23},[28,598,599,601,603,605],{"class":30,"line":31},[28,600,98],{"class":97},[28,602,102],{"class":101},[28,604,105],{"class":97},[28,606,607],{"class":101}," Client, QuicoptError\n",[28,609,610],{"class":30,"line":111},[28,611,115],{"emptyLinePlaceholder":114},[28,613,614,617],{"class":30,"line":118},[28,615,616],{"class":97},"try",[28,618,619],{"class":101},":\n",[28,621,623,626,628],{"class":30,"line":622},4,[28,624,625],{"class":101},"    result ",[28,627,124],{"class":97},[28,629,243],{"class":101},[28,631,633,636,639,642],{"class":30,"line":632},5,[28,634,635],{"class":97},"except",[28,637,638],{"class":101}," QuicoptError ",[28,640,641],{"class":97},"as",[28,643,644],{"class":101}," e:\n",[28,646,648,651,654],{"class":30,"line":647},6,[28,649,650],{"class":248},"    print",[28,652,653],{"class":101},"(e.reason)     ",[28,655,656],{"class":45},"# stable code, e.g. \"unsupported_model\"\n",[28,658,660,662,665],{"class":30,"line":659},7,[28,661,650],{"class":248},[28,663,664],{"class":101},"(e.display)    ",[28,666,667],{"class":45},"# the service's readable message, with a help contact\n",[135,669,670,678],{},[138,671,672],{},[141,673,674,676],{},[144,675,338],{},[144,677,152],{},[154,679,680,694,703],{},[141,681,682,687],{},[159,683,684],{},[25,685,686],{},"reason",[159,688,689,690,693],{},"a stable snake_case code, e.g. ",[25,691,692],{},"unsupported_model"," for a problem class that isn't solved yet",[141,695,696,700],{},[159,697,698],{},[25,699,478],{},[159,701,702],{},"the framed, human-readable message — including how to get in touch",[141,704,705,710],{},[159,706,707],{},[25,708,709],{},"status_code",[159,711,712],{},"the HTTP status behind it",[14,714,715,716,718,719,721,722,726,727,729],{},"Remember: ",[25,717,370],{}," and ",[25,720,373],{}," are ",[723,724,725],"em",{},"results",", not errors — you get a\nnormal ",[25,728,60],{}," for those.",[77,731,733,734],{"id":732},"async-jobs-clientsubmit","Async jobs: ",[25,735,736],{},"client.submit()",[14,738,739],{},"For a long solve, don't block — submit the model and poll a job handle:",[18,741,743],{"className":88,"code":742,"language":90,"meta":23,"style":23},"job = client.submit(model)      # returns immediately\n\njob.status()                    # {\"status\": \"queued\" | \"running\" | \"done\", ...}\nresult = job.result()           # polls until done, returns the same Result as solve()\nprint(job.log())                # the solver log so far\njob.delete()                    # remove the job and its stored result\n",[25,744,745,758,762,770,782,792],{"__ignoreMap":23},[28,746,747,750,752,755],{"class":30,"line":31},[28,748,749],{"class":101},"job ",[28,751,124],{"class":97},[28,753,754],{"class":101}," client.submit(model)      ",[28,756,757],{"class":45},"# returns immediately\n",[28,759,760],{"class":30,"line":111},[28,761,115],{"emptyLinePlaceholder":114},[28,763,764,767],{"class":30,"line":118},[28,765,766],{"class":101},"job.status()                    ",[28,768,769],{"class":45},"# {\"status\": \"queued\" | \"running\" | \"done\", ...}\n",[28,771,772,774,776,779],{"class":30,"line":622},[28,773,238],{"class":101},[28,775,124],{"class":97},[28,777,778],{"class":101}," job.result()           ",[28,780,781],{"class":45},"# polls until done, returns the same Result as solve()\n",[28,783,784,786,789],{"class":30,"line":632},[28,785,249],{"class":248},[28,787,788],{"class":101},"(job.log())                ",[28,790,791],{"class":45},"# the solver log so far\n",[28,793,794,797],{"class":30,"line":647},[28,795,796],{"class":101},"job.delete()                    ",[28,798,799],{"class":45},"# remove the job and its stored result\n",[135,801,802,811],{},[138,803,804],{},[141,805,806,809],{},[144,807,808],{},"Method",[144,810,152],{},[154,812,813,823,840,850],{},[141,814,815,820],{},[159,816,817],{},[25,818,819],{},"job.status()",[159,821,822],{},"the job's state and a tail of its log",[141,824,825,830],{},[159,826,827],{},[25,828,829],{},"job.result(wait=True, timeout=120.0, poll=0.5)",[159,831,832,833,835,836,839],{},"the finished ",[25,834,60],{},"; with ",[25,837,838],{},"wait=False"," it fetches once and raises if the job isn't done yet",[141,841,842,847],{},[159,843,844],{},[25,845,846],{},"job.log()",[159,848,849],{},"the job's full plain-text log",[141,851,852,857],{},[159,853,854],{},[25,855,856],{},"job.delete()",[159,858,859],{},"delete the job and its stored result on the server",[14,861,862,865,866,868,869,523],{},[25,863,864],{},"submit()"," takes the same models and the same ",[25,867,301],{}," option as ",[25,870,56],{},[77,872,874],{"id":873},"beyond-the-free-tier","Beyond the free tier",[14,876,877],{},"The free tier is a one-time entry point to try the API. Questions about the\nclient, or real models you want to try Quicopt on? Just ask:",[879,880],"contact-cta",{"sub":881,"title":882},"Whether something's unclear or you want to try Quicopt on your real models — tell us what you're optimizing.","Questions? Talk to us.",[884,885,886],"style",{},"html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}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);}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 .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}",{"title":23,"searchDepth":111,"depth":111,"links":888},[889,890,891,893,894,896,898],{"id":79,"depth":111,"text":82},{"id":216,"depth":111,"text":219},{"id":325,"depth":111,"text":892},"The Result object",{"id":507,"depth":111,"text":508},{"id":582,"depth":111,"text":895},"Errors: QuicoptError",{"id":732,"depth":111,"text":897},"Async jobs: client.submit()",{"id":873,"depth":111,"text":874},"The quicopt Python client in full — Client, solve(), the Result fields, error handling, and the async job API.","md",{},"\u002Fdeveloper\u002Fapi",{"title":5,"description":899},"developer\u002Fapi","2JSnPCkKuKXWM3dNjHwsOdQ5evRK84uJqwavqx5wquE",1783518720545]