[{"data":1,"prerenderedAt":440},["ShallowReactive",2],{"dev-\u002Fdeveloper\u002Fexamples\u002Fhigher-order-binary":3},{"id":4,"title":5,"body":6,"description":421,"extension":422,"faq":423,"meta":433,"navigation":434,"noindex":435,"path":436,"seo":437,"stem":438,"__hash__":439},"content\u002Fdeveloper\u002Fexamples\u002Fhigher-order-binary.md","Higher-order binary optimization (PUBO) in Python",{"type":7,"value":8,"toc":415},"minimark",[9,13,38,43,46,50,74,316,321,325,351,365,373,377,400,411],[10,11,5],"h1",{"id":12},"higher-order-binary-optimization-pubo-in-python",[14,15,16,17,21,22,25,26,29,30,33,34,37],"p",{},"Not every binary problem is quadratic. When the objective multiplies ",[18,19,20],"strong",{},"three or\nmore"," binary variables together, it is a ",[18,23,24],{},"PUBO"," (polynomial) or ",[18,27,28],{},"HUBO","\n(higher-order) problem — the class quantum computers are built for, here solved\nclassically. ",[18,31,32],{},"quicopt"," optimizes the higher-order objective ",[18,35,36],{},"directly",": no\nreduction to a quadratic QUBO, no auxiliary variables.",[39,40,42],"h2",{"id":41},"the-naive-approach","The naive approach",[14,44,45],{},"The common workaround is to reduce the degree — introduce a helper binary for\neach product of variables until everything is quadratic, then feed a QUBO solver.\nThat inflates the variable count and adds penalty terms that reshape the energy\nlandscape. Solve the objective as written instead.",[39,47,49],{"id":48},"a-worked-example-labs","A worked example: LABS",[14,51,52,53,56,57,60,61,64,65,69,70,73],{},"The ",[18,54,55],{},"low-autocorrelation binary sequence (LABS)"," problem asks for a string of\n±1 symbols that looks as little like a shifted copy of itself as possible. Its\nenergy is a ",[18,58,59],{},"degree-four"," polynomial in the binaries — a genuine PUBO. Modeled\nin ",[18,62,63],{},"Pyomo"," (",[66,67,68],"code",{},"pip install \"quicopt[pyomo]\"","), here for ",[66,71,72],{},"N = 7",":",[75,76,82],"pre",{"className":77,"code":78,"filename":79,"language":80,"meta":81,"style":81},"language-python shiki shiki-themes github-dark","import pyomo.environ as pyo\nfrom quicopt import Client\n# LABS (low-autocorrelation binary sequences) for N=7: a degree-4 (PUBO) energy.\nN = 7\nm = pyo.ConcreteModel()\nm.x = pyo.Var(range(N), domain=pyo.Binary)\ns = [1 - 2 * m.x[i] for i in range(N)]\nm.obj = pyo.Objective(\n    expr=sum(sum(s[i] * s[i + k] for i in range(N - k)) ** 2 for k in range(1, N)),\n    sense=pyo.minimize)\nprint(Client().solve(m).display)\n","labs.py","python","",[66,83,84,103,117,124,137,148,174,215,226,296,307],{"__ignoreMap":81},[85,86,89,93,97,100],"span",{"class":87,"line":88},"line",1,[85,90,92],{"class":91},"snl16","import",[85,94,96],{"class":95},"s95oV"," pyomo.environ ",[85,98,99],{"class":91},"as",[85,101,102],{"class":95}," pyo\n",[85,104,106,109,112,114],{"class":87,"line":105},2,[85,107,108],{"class":91},"from",[85,110,111],{"class":95}," quicopt ",[85,113,92],{"class":91},[85,115,116],{"class":95}," Client\n",[85,118,120],{"class":87,"line":119},3,[85,121,123],{"class":122},"sAwPA","# LABS (low-autocorrelation binary sequences) for N=7: a degree-4 (PUBO) energy.\n",[85,125,127,130,133],{"class":87,"line":126},4,[85,128,129],{"class":95},"N ",[85,131,132],{"class":91},"=",[85,134,136],{"class":135},"sDLfK"," 7\n",[85,138,140,143,145],{"class":87,"line":139},5,[85,141,142],{"class":95},"m ",[85,144,132],{"class":91},[85,146,147],{"class":95}," pyo.ConcreteModel()\n",[85,149,151,154,156,159,162,165,169,171],{"class":87,"line":150},6,[85,152,153],{"class":95},"m.x ",[85,155,132],{"class":91},[85,157,158],{"class":95}," pyo.Var(",[85,160,161],{"class":135},"range",[85,163,164],{"class":95},"(N), ",[85,166,168],{"class":167},"s9osk","domain",[85,170,132],{"class":91},[85,172,173],{"class":95},"pyo.Binary)\n",[85,175,177,180,182,185,188,191,194,197,200,203,206,209,212],{"class":87,"line":176},7,[85,178,179],{"class":95},"s ",[85,181,132],{"class":91},[85,183,184],{"class":95}," [",[85,186,187],{"class":135},"1",[85,189,190],{"class":91}," -",[85,192,193],{"class":135}," 2",[85,195,196],{"class":91}," *",[85,198,199],{"class":95}," m.x[i] ",[85,201,202],{"class":91},"for",[85,204,205],{"class":95}," i ",[85,207,208],{"class":91},"in",[85,210,211],{"class":135}," range",[85,213,214],{"class":95},"(N)]\n",[85,216,218,221,223],{"class":87,"line":217},8,[85,219,220],{"class":95},"m.obj ",[85,222,132],{"class":91},[85,224,225],{"class":95}," pyo.Objective(\n",[85,227,229,232,234,237,240,242,245,248,251,254,257,259,261,263,265,268,271,274,277,279,282,285,287,289,291,293],{"class":87,"line":228},9,[85,230,231],{"class":167},"    expr",[85,233,132],{"class":91},[85,235,236],{"class":135},"sum",[85,238,239],{"class":95},"(",[85,241,236],{"class":135},[85,243,244],{"class":95},"(s[i] ",[85,246,247],{"class":91},"*",[85,249,250],{"class":95}," s[i ",[85,252,253],{"class":91},"+",[85,255,256],{"class":95}," k] ",[85,258,202],{"class":91},[85,260,205],{"class":95},[85,262,208],{"class":91},[85,264,211],{"class":135},[85,266,267],{"class":95},"(N ",[85,269,270],{"class":91},"-",[85,272,273],{"class":95}," k)) ",[85,275,276],{"class":91},"**",[85,278,193],{"class":135},[85,280,281],{"class":91}," for",[85,283,284],{"class":95}," k ",[85,286,208],{"class":91},[85,288,211],{"class":135},[85,290,239],{"class":95},[85,292,187],{"class":135},[85,294,295],{"class":95},", N)),\n",[85,297,299,302,304],{"class":87,"line":298},10,[85,300,301],{"class":167},"    sense",[85,303,132],{"class":91},[85,305,306],{"class":95},"pyo.minimize)\n",[85,308,310,313],{"class":87,"line":309},11,[85,311,312],{"class":135},"print",[85,314,315],{"class":95},"(Client().solve(m).display)\n",[317,318],"term-result",{":rows":319,"cmd":320},"[\"├── shots\",\"│   ├── 1 · primal   91    0.0s\",\"│   ├── 2 · primal    3   0.01s  ◀ best\",\"│   ├── 3 · primal    3   2.54s\",\"│   ├── 4 · primal    3    2.0s\",\"│   └── 5 · primal    3   2.55s\",\"├── status:     heuristic\",\"├── feasible:   n\u002Fa\",\"├── objective:  3.0\",\"├── x:          x1=1, x2=0, x3=1, x4=1, x5=0, x6=0, …  (7 variables)\",\"└── solve_time: 2.5476 s\"]","$ python labs.py",[39,322,324],{"id":323},"what-you-get","What you get",[14,326,327,328,331,332,335,336,338,339,342,343,346,347,350],{},"quicopt returns energy ",[66,329,330],{},"3"," — the ",[18,333,334],{},"known optimum"," for LABS at ",[66,337,72],{}," (established\nby exhaustive results in the literature) — straight from the degree-four\nobjective, with no manual reduction to quadratic. Because a PUBO has no\nconstraints, the status is ",[66,340,341],{},"heuristic"," and ",[66,344,345],{},"feasible"," is ",[66,348,349],{},"n\u002Fa",".",[14,352,353,354,357,358,361,362,364],{},"Read the ",[66,355,356],{},"shots"," block before you read ",[66,359,360],{},"solve_time",". Energy ",[66,363,330],{}," is on the board\nalmost at once; the later shots keep working the non-convex energy and land on\nthe same value, and that is what the two and a half seconds of wall clock pay\nfor. A PUBO gives\nthe solver no dual bound to stop on, so the search has no way to know it is\nfinished except to keep looking.",[14,366,367,368,350],{},"The same directness scales: on the public LABS instances quicopt reaches\nbest-known energies orders of magnitude faster than established solvers — see the\n",[369,370,372],"a",{"href":371},"\u002Fbenchmarks\u002Flabs","LABS benchmark",[39,374,376],{"id":375},"next","Next",[378,379,380,388,393],"ul",{},[381,382,383,384],"li",{},"The problem class behind this: ",[369,385,387],{"href":386},"\u002Fproblems\u002Fpubo","PUBO \u002F higher-order binary",[381,389,390,391],{},"Measured results at scale: ",[369,392,372],{"href":371},[381,394,395,396],{},"The quadratic cousin: ",[369,397,399],{"href":398},"\u002Fdeveloper\u002Fexamples\u002Fmax-cut","Max-cut (QUBO)",[14,401,402,405,406,410],{},[18,403,404],{},"Reference:"," T. Packebusch and S. Mertens, ",[407,408,409],"em",{},"Low autocorrelation binary\nsequences",", Journal of Physics A, 2016.",[412,413,414],"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 .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":81,"searchDepth":105,"depth":105,"links":416},[417,418,419,420],{"id":41,"depth":105,"text":42},{"id":48,"depth":105,"text":49},{"id":323,"depth":105,"text":324},{"id":375,"depth":105,"text":376},"Not every binary problem is quadratic. When the objective multiplies three or\nmore binary variables together, it is a PUBO (polynomial) or HUBO\n(higher-order) problem — the class quantum computers are built for, here solved\nclassically. quicopt optimizes the higher-order objective directly: no\nreduction to a quadratic QUBO, no auxiliary variables.","md",[424,427,430],{"q":425,"a":426},"What's the difference between QUBO and PUBO?","QUBO objectives are degree two (pairwise). PUBO (polynomial) and HUBO (higher-order) allow degree three and up — products of three or more binary variables. Many real binary objectives are naturally higher-order.",{"q":428,"a":429},"Why not just reduce it to a QUBO?","Reducing a degree-k objective to quadratic adds auxiliary variables and penalty terms that blow up the model and distort the landscape. quicopt optimizes the higher-order objective directly, as written.",{"q":431,"a":432},"Is quicopt free to use?","Yes, to start: sign up for a free account, install the client with pip install \"quicopt[pyomo]\" 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.",{},true,false,"\u002Fdeveloper\u002Fexamples\u002Fhigher-order-binary",{"title":5,"description":421},"developer\u002Fexamples\u002Fhigher-order-binary","rRJAV2NJBxhh33qgrDHJAAWqLtxlmHoJbI9CtzcLyhM",1794337679505]