[{"data":1,"prerenderedAt":430},["ShallowReactive",2],{"dev-\u002Fdeveloper\u002Fexamples\u002Fmaximum-independent-set":3},{"id":4,"title":5,"body":6,"description":408,"extension":409,"faq":410,"meta":423,"navigation":424,"noindex":425,"path":426,"seo":427,"stem":428,"__hash__":429},"content\u002Fdeveloper\u002Fexamples\u002Fmaximum-independent-set.md","Solve the maximum independent set problem in Python",{"type":7,"value":8,"toc":402},"minimark",[9,13,35,40,48,52,63,326,331,335,352,361,365,388,398],[10,11,5],"h1",{"id":12},"solve-the-maximum-independent-set-problem-in-python",[14,15,16,17,21,22,26,27,30,31,34],"p",{},"A ",[18,19,20],"strong",{},"maximum independent set"," is the largest possible set of vertices in a graph\nwith no edge between any two of them — the model behind conflict-free scheduling,\nchannel assignment, and de-duplication. It is NP-hard, and the default answer\nonline — a greedy pass — returns a ",[23,24,25],"em",{},"maximal"," set, not the ",[23,28,29],{},"maximum"," one.\nWith ",[18,32,33],{},"quicopt"," you get the proven maximum in a few lines of Python.",[36,37,39],"h2",{"id":38},"the-naive-approach","The naive approach",[14,41,42,43,47],{},"A greedy pass grows a set until nothing else fits — a\nlocally-stuck answer that is usually smaller than the true maximum. Enumerating\nall subsets to find the largest is ",[44,45,46],"code",{},"O(2^n)",". Model it instead.",[36,49,51],{"id":50},"model-it-as-a-milp","Model it as a MILP",[14,53,54,55,58,59,62],{},"A binary variable ",[44,56,57],{},"x[i]"," selects vertex ",[44,60,61],{},"i",". For every edge, at most one endpoint\nmay be chosen. Maximize the number of selected vertices:",[64,65,71],"pre",{"className":66,"code":67,"filename":68,"language":69,"meta":70,"style":70},"language-python shiki shiki-themes github-dark","from ortools.math_opt.python import mathopt\nfrom quicopt import Client\nedges = [(0,1),(0,2),(1,2),(2,3),(3,4),(3,5),(4,5)]\nN = 6\nmodel = mathopt.Model(name=\"mis\")\nx = [model.add_binary_variable(name=f\"x{i}\") for i in range(N)]\nfor (i, j) in edges:                      # no two adjacent vertices both chosen\n    model.add_linear_constraint(x[i] + x[j] \u003C= 1)\nmodel.maximize(sum(x))\nprint(Client().solve(model).display)\n","max_independent_set.py","python","",[44,72,73,92,105,183,194,218,268,285,305,317],{"__ignoreMap":70},[74,75,78,82,86,89],"span",{"class":76,"line":77},"line",1,[74,79,81],{"class":80},"snl16","from",[74,83,85],{"class":84},"s95oV"," ortools.math_opt.python ",[74,87,88],{"class":80},"import",[74,90,91],{"class":84}," mathopt\n",[74,93,95,97,100,102],{"class":76,"line":94},2,[74,96,81],{"class":80},[74,98,99],{"class":84}," quicopt ",[74,101,88],{"class":80},[74,103,104],{"class":84}," Client\n",[74,106,108,111,114,117,121,124,127,130,132,134,137,139,141,143,145,147,149,151,154,156,158,160,163,165,167,169,172,174,176,178,180],{"class":76,"line":107},3,[74,109,110],{"class":84},"edges ",[74,112,113],{"class":80},"=",[74,115,116],{"class":84}," [(",[74,118,120],{"class":119},"sDLfK","0",[74,122,123],{"class":84},",",[74,125,126],{"class":119},"1",[74,128,129],{"class":84},"),(",[74,131,120],{"class":119},[74,133,123],{"class":84},[74,135,136],{"class":119},"2",[74,138,129],{"class":84},[74,140,126],{"class":119},[74,142,123],{"class":84},[74,144,136],{"class":119},[74,146,129],{"class":84},[74,148,136],{"class":119},[74,150,123],{"class":84},[74,152,153],{"class":119},"3",[74,155,129],{"class":84},[74,157,153],{"class":119},[74,159,123],{"class":84},[74,161,162],{"class":119},"4",[74,164,129],{"class":84},[74,166,153],{"class":119},[74,168,123],{"class":84},[74,170,171],{"class":119},"5",[74,173,129],{"class":84},[74,175,162],{"class":119},[74,177,123],{"class":84},[74,179,171],{"class":119},[74,181,182],{"class":84},")]\n",[74,184,186,189,191],{"class":76,"line":185},4,[74,187,188],{"class":84},"N ",[74,190,113],{"class":80},[74,192,193],{"class":119}," 6\n",[74,195,197,200,202,205,209,211,215],{"class":76,"line":196},5,[74,198,199],{"class":84},"model ",[74,201,113],{"class":80},[74,203,204],{"class":84}," mathopt.Model(",[74,206,208],{"class":207},"s9osk","name",[74,210,113],{"class":80},[74,212,214],{"class":213},"sU2Wk","\"mis\"",[74,216,217],{"class":84},")\n",[74,219,221,224,226,229,231,233,236,239,242,244,247,250,253,256,259,262,265],{"class":76,"line":220},6,[74,222,223],{"class":84},"x ",[74,225,113],{"class":80},[74,227,228],{"class":84}," [model.add_binary_variable(",[74,230,208],{"class":207},[74,232,113],{"class":80},[74,234,235],{"class":80},"f",[74,237,238],{"class":213},"\"x",[74,240,241],{"class":119},"{",[74,243,61],{"class":84},[74,245,246],{"class":119},"}",[74,248,249],{"class":213},"\"",[74,251,252],{"class":84},") ",[74,254,255],{"class":80},"for",[74,257,258],{"class":84}," i ",[74,260,261],{"class":80},"in",[74,263,264],{"class":119}," range",[74,266,267],{"class":84},"(N)]\n",[74,269,271,273,276,278,281],{"class":76,"line":270},7,[74,272,255],{"class":80},[74,274,275],{"class":84}," (i, j) ",[74,277,261],{"class":80},[74,279,280],{"class":84}," edges:                      ",[74,282,284],{"class":283},"sAwPA","# no two adjacent vertices both chosen\n",[74,286,288,291,294,297,300,303],{"class":76,"line":287},8,[74,289,290],{"class":84},"    model.add_linear_constraint(x[i] ",[74,292,293],{"class":80},"+",[74,295,296],{"class":84}," x[j] ",[74,298,299],{"class":80},"\u003C=",[74,301,302],{"class":119}," 1",[74,304,217],{"class":84},[74,306,308,311,314],{"class":76,"line":307},9,[74,309,310],{"class":84},"model.maximize(",[74,312,313],{"class":119},"sum",[74,315,316],{"class":84},"(x))\n",[74,318,320,323],{"class":76,"line":319},10,[74,321,322],{"class":119},"print",[74,324,325],{"class":84},"(Client().solve(model).display)\n",[327,328],"term-result",{":rows":329,"cmd":330},"[\"├── shots\",\"│   ├── 1 · primal-dual · global   2   0.02s  ◀ best\",\"│   ├── 2 · primal-dual · global   2   0.01s\",\"│   └── 3 · primal                 2   0.02s\",\"├── status:     optimal\",\"├── feasible:   true\",\"├── objective:  2.0\",\"├── x:          x0=0, x1=1, x2=0, x3=1, x4=0, x5=0  (6 variables)\",\"└── solve_time: 0.0168 s\"]","$ python max_independent_set.py",[36,332,334],{"id":333},"what-you-get","What you get",[14,336,337,340,341,344,345,347,348,351],{},[44,338,339],{},"status: optimal"," means the solver ",[18,342,343],{},"proved"," no larger independent set exists —\nsize ",[44,346,136],{}," (vertices ",[44,349,350],{},"{1, 3}","). The graph is two triangles joined by an edge, so at\nmost one vertex per triangle can be chosen; the solver finds that bound and\nproves it, rather than getting stuck like a greedy pass.",[14,353,354,355,360],{},"The same model scales to large graphs — see how quicopt does on the public QOBLIB\nindependent-set instances in the ",[356,357,359],"a",{"href":358},"\u002Fbenchmarks\u002Fmis","MIS benchmark",".",[36,362,364],{"id":363},"next","Next",[366,367,368,376,381],"ul",{},[369,370,371,372],"li",{},"The problem class behind this: ",[356,373,375],{"href":374},"\u002Fproblems\u002Fmilp","Mixed-integer linear (MILP)",[369,377,378,379],{},"The QUBO\u002FIsing view + measured results: ",[356,380,359],{"href":358},[369,382,383,384],{},"Set up the client and solve your first model: ",[356,385,387],{"href":386},"\u002Fdeveloper\u002Fdocs\u002Fquickstart","Getting started",[14,389,390,393,394,397],{},[18,391,392],{},"Reference:"," R. M. Karp, ",[23,395,396],{},"Reducibility Among Combinatorial Problems",", in\nComplexity of Computer Computations, 1972.",[399,400,401],"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 .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 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);}",{"title":70,"searchDepth":94,"depth":94,"links":403},[404,405,406,407],{"id":38,"depth":94,"text":39},{"id":50,"depth":94,"text":51},{"id":333,"depth":94,"text":334},{"id":363,"depth":94,"text":364},"A maximum independent set is the largest possible set of vertices in a graph\nwith no edge between any two of them — the model behind conflict-free scheduling,\nchannel assignment, and de-duplication. It is NP-hard, and the default answer\nonline — a greedy pass — returns a maximal set, not the maximum one.\nWith quicopt you get the proven maximum in a few lines of Python.","md",[411,414,417,420],{"q":412,"a":413},"Isn't a greedy maximal independent set enough?","That returns a maximal set — one you can't extend — which is usually not the maximum (globally largest). This MILP returns the provably largest set.",{"q":415,"a":416},"What's the difference between maximal and maximum?","Maximal = locally stuck (no vertex can be added). Maximum = globally largest. Greedy methods give maximal; the solver gives maximum.",{"q":418,"a":419},"Is this related to max-cut and QUBO?","Yes — independent set has an equivalent QUBO\u002FIsing form and is a standard quantum-inspired benchmark. Here we use the clean MILP formulation, which proves optimality.",{"q":421,"a":422},"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.",{},true,false,"\u002Fdeveloper\u002Fexamples\u002Fmaximum-independent-set",{"title":5,"description":408},"developer\u002Fexamples\u002Fmaximum-independent-set","7-RjcLrP_W5cborthp3_vUMUFeT2EXJn2u58ypBXEFc",1794337679429]