[{"data":1,"prerenderedAt":4745},["ShallowReactive",2],{"navigation":3,"\u002Fresources\u002Ftutorials\u002Fassignment\u002F01_the_assignment_problem":174,"\u002Fresources\u002Ftutorials\u002Fassignment\u002F01_the_assignment_problem-surround":4741},[4,8,101,165,170],{"title":5,"path":6,"stem":7},"Getting started","\u002Fgetting-started","1.getting-started",{"title":9,"path":10,"stem":11,"children":12},"Algorithms","\u002Falgorithms","2.algorithms",[13,15,58],{"title":9,"path":10,"stem":14},"2.algorithms\u002Findex",{"title":16,"path":17,"stem":18,"children":19},"Assignment","\u002Falgorithms\u002Fassignment","2.algorithms\u002F1.assignment\u002Findex",[20,21,25,29,32,36,40],{"title":16,"path":17,"stem":18},{"title":22,"path":23,"stem":24},"Quickstart","\u002Falgorithms\u002Fassignment\u002Fquickstart","2.algorithms\u002F1.assignment\u002F1.quickstart",{"title":26,"path":27,"stem":28},"Tracking","\u002Falgorithms\u002Fassignment\u002Ftracking","2.algorithms\u002F1.assignment\u002F2.tracking",{"title":9,"path":30,"stem":31},"\u002Falgorithms\u002Fassignment\u002Falgorithms","2.algorithms\u002F1.assignment\u002F3.algorithms",{"title":33,"path":34,"stem":35},"Reference","\u002Falgorithms\u002Fassignment\u002Freference","2.algorithms\u002F1.assignment\u002F4.reference",{"title":37,"path":38,"stem":39},"Choosing","\u002Falgorithms\u002Fassignment\u002Fchoosing","2.algorithms\u002F1.assignment\u002F5.choosing",{"title":41,"path":42,"stem":43,"children":44},"Tutorials","\u002Falgorithms\u002Fassignment\u002Ftutorials","2.algorithms\u002F1.assignment\u002F6.tutorials\u002Findex",[45,46,50,54],{"title":41,"path":42,"stem":43},{"title":47,"path":48,"stem":49},"Fundamentals","\u002Falgorithms\u002Fassignment\u002Ftutorials\u002Ffundamentals","2.algorithms\u002F1.assignment\u002F6.tutorials\u002F1.fundamentals",{"title":51,"path":52,"stem":53},"Backends","\u002Falgorithms\u002Fassignment\u002Ftutorials\u002Fbackends","2.algorithms\u002F1.assignment\u002F6.tutorials\u002F2.backends",{"title":55,"path":56,"stem":57},"Object tracking","\u002Falgorithms\u002Fassignment\u002Ftutorials\u002Ftracking","2.algorithms\u002F1.assignment\u002F6.tutorials\u002F3.tracking",{"title":59,"path":60,"stem":61,"children":62},"Transport","\u002Falgorithms\u002Ftransport","2.algorithms\u002F2.transport\u002Findex",[63,64,67,71,74,77,80,84],{"title":59,"path":60,"stem":61},{"title":22,"path":65,"stem":66},"\u002Falgorithms\u002Ftransport\u002Fquickstart","2.algorithms\u002F2.transport\u002F1.quickstart",{"title":68,"path":69,"stem":70},"Point-cloud tutorial","\u002Falgorithms\u002Ftransport\u002Fpoint-clouds","2.algorithms\u002F2.transport\u002F2.point-clouds",{"title":9,"path":72,"stem":73},"\u002Falgorithms\u002Ftransport\u002Falgorithms","2.algorithms\u002F2.transport\u002F3.algorithms",{"title":33,"path":75,"stem":76},"\u002Falgorithms\u002Ftransport\u002Freference","2.algorithms\u002F2.transport\u002F4.reference",{"title":37,"path":78,"stem":79},"\u002Falgorithms\u002Ftransport\u002Fchoosing","2.algorithms\u002F2.transport\u002F5.choosing",{"title":81,"path":82,"stem":83},"Building","\u002Falgorithms\u002Ftransport\u002Fbuilding","2.algorithms\u002F2.transport\u002F6.building",{"title":41,"path":85,"stem":86,"children":87},"\u002Falgorithms\u002Ftransport\u002Ftutorials","2.algorithms\u002F2.transport\u002F7.tutorials\u002Findex",[88,89,93,97],{"title":41,"path":85,"stem":86},{"title":90,"path":91,"stem":92},"Optimal transport","\u002Falgorithms\u002Ftransport\u002Ftutorials\u002Foptimal-transport","2.algorithms\u002F2.transport\u002F7.tutorials\u002F1.optimal-transport",{"title":94,"path":95,"stem":96},"Sinkhorn","\u002Falgorithms\u002Ftransport\u002Ftutorials\u002Fsinkhorn","2.algorithms\u002F2.transport\u002F7.tutorials\u002F2.sinkhorn",{"title":98,"path":99,"stem":100},"Point clouds","\u002Falgorithms\u002Ftransport\u002Ftutorials\u002Fpoint-clouds","2.algorithms\u002F2.transport\u002F7.tutorials\u002F3.point-clouds",{"title":102,"path":103,"stem":104,"children":105},"Resources","\u002Fresources","3.resources",[106,108,147,151,155],{"title":102,"path":103,"stem":107},"3.resources\u002Findex",{"title":41,"path":109,"stem":110,"children":111},"\u002Fresources\u002Ftutorials","3.resources\u002F1.tutorials\u002Findex",[112,113,131],{"title":41,"path":109,"stem":110},{"title":16,"path":114,"stem":115,"children":116,"page":130},"\u002Fresources\u002Ftutorials\u002Fassignment","3.resources\u002F1.tutorials\u002Fassignment",[117,122,126],{"title":118,"path":119,"stem":120,"icon":121},"Tutorial 1 — The Assignment Problem","\u002Fresources\u002Ftutorials\u002Fassignment\u002F01_the_assignment_problem","3.resources\u002F1.tutorials\u002Fassignment\u002F01_the_assignment_problem","i-lucide-notebook",{"title":123,"path":124,"stem":125,"icon":121},"Tutorial 2 — Backends and Batching","\u002Fresources\u002Ftutorials\u002Fassignment\u002F02_backends_and_batching","3.resources\u002F1.tutorials\u002Fassignment\u002F02_backends_and_batching",{"title":127,"path":128,"stem":129,"icon":121},"Tutorial 3 — Object Tracking with the Assignment Problem","\u002Fresources\u002Ftutorials\u002Fassignment\u002F03_object_tracking","3.resources\u002F1.tutorials\u002Fassignment\u002F03_object_tracking",false,{"title":59,"path":132,"stem":133,"children":134,"page":130},"\u002Fresources\u002Ftutorials\u002Ftransport","3.resources\u002F1.tutorials\u002Ftransport",[135,139,143],{"title":136,"path":137,"stem":138,"icon":121},"Tutorial 1 — What Is Optimal Transport?","\u002Fresources\u002Ftutorials\u002Ftransport\u002F01_optimal_transport","3.resources\u002F1.tutorials\u002Ftransport\u002F01_optimal_transport",{"title":140,"path":141,"stem":142,"icon":121},"Tutorial 2 — The Sinkhorn Algorithm","\u002Fresources\u002Ftutorials\u002Ftransport\u002F02_sinkhorn_algorithm","3.resources\u002F1.tutorials\u002Ftransport\u002F02_sinkhorn_algorithm",{"title":144,"path":145,"stem":146,"icon":121},"Tutorial 3 — Point-Cloud OT and Shape Learning","\u002Fresources\u002Ftutorials\u002Ftransport\u002F03_point_clouds","3.resources\u002F1.tutorials\u002Ftransport\u002F03_point_clouds",{"title":148,"path":149,"stem":150},"Assignment applications","\u002Fresources\u002Fassignment-applications","3.resources\u002F2.assignment-applications",{"title":152,"path":153,"stem":154},"Transport applications","\u002Fresources\u002Ftransport-applications","3.resources\u002F3.transport-applications",{"title":156,"path":157,"stem":158,"children":159},"Benchmarks","\u002Fresources\u002Fbenchmarks","3.resources\u002F4.benchmarks\u002Findex",[160,161],{"title":156,"path":157,"stem":158},{"title":162,"path":163,"stem":164},"Contributing benchmarks","\u002Fresources\u002Fbenchmarks\u002Fcontributing","3.resources\u002F4.benchmarks\u002Fcontributing",{"title":166,"path":167,"stem":168,"icon":169},"API Reference","\u002Fapi","4.api","i-lucide-package",{"title":171,"path":172,"stem":173},"References","\u002Freferences","5.references",{"id":175,"title":118,"api":176,"body":177,"description":190,"extension":4736,"links":176,"meta":4737,"navigation":4738,"path":119,"seo":4739,"stem":120,"__hash__":4740},"docs\u002F3.resources\u002F1.tutorials\u002Fassignment\u002F01_the_assignment_problem.md",null,{"type":178,"value":179,"toc":4726},"minimark",[180,184,191,214,220,503,508,513,536,543,1259,1265,1270,1273,2565,2570,2573,2577,2591,2903,2906,3525,3530,3533,3540,3593,3597,3611,3856,3859,3998,4003,4007,4018,4501,4504,4508,4511,4676,4679,4683,4711,4722],[181,182,118],"h1",{"id":183},"tutorial-1-the-assignment-problem",[185,186,187],"p",{},[188,189,190],"strong",{},"What you will learn",[192,193,194,198,201,204,207],"ul",{},[195,196,197],"li",{},"What the linear assignment problem (LAP) is and where it appears",[195,199,200],{},"Why finding the best assignment by brute force is impractical beyond ~10 items",[195,202,203],{},"How to represent an assignment problem as a cost matrix",[195,205,206],{},"How to visualise an assignment as a bipartite graph",[195,208,209,210],{},"How to solve your first LAP with ",[211,212,213],"code",{},"torchmatch.assignment.solve",[185,215,216,219],{},[188,217,218],{},"Prerequisites"," — Python, NumPy basics, familiarity with PyTorch tensors.\nNo prior knowledge of combinatorial optimisation is assumed.",[221,222,227],"pre",{"className":223,"code":224,"language":225,"meta":226,"style":226},"language-python shiki shiki-themes material-theme-lighter github-light github-dark","%matplotlib inline\nimport math\nfrom itertools import permutations\n\nimport matplotlib.patches as mpatches\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nimport torchmatch\nfrom scipy.optimize import linear_sum_assignment  # reference solver\n\nplt.rcParams.update({\"figure.dpi\": 120, \"font.size\": 11})\nrng = np.random.default_rng(42)\nprint(\"torchmatch\", torchmatch.__version__, \"| torch\", torch.__version__)\n","python","",[211,228,229,242,252,266,273,295,312,326,334,342,364,369,425,456],{"__ignoreMap":226},[230,231,234,238],"span",{"class":232,"line":233},"line",1,[230,235,237],{"class":236},"smGrS","%",[230,239,241],{"class":240},"su5hD","matplotlib inline\n",[230,243,245,249],{"class":232,"line":244},2,[230,246,248],{"class":247},"sVHd0","import",[230,250,251],{"class":240}," math\n",[230,253,255,258,261,263],{"class":232,"line":254},3,[230,256,257],{"class":247},"from",[230,259,260],{"class":240}," itertools ",[230,262,248],{"class":247},[230,264,265],{"class":240}," permutations\n",[230,267,269],{"class":232,"line":268},4,[230,270,272],{"emptyLinePlaceholder":271},true,"\n",[230,274,276,278,281,285,289,292],{"class":232,"line":275},5,[230,277,248],{"class":247},[230,279,280],{"class":240}," matplotlib",[230,282,284],{"class":283},"sP7_E",".",[230,286,288],{"class":287},"skxfh","patches",[230,290,291],{"class":247}," as",[230,293,294],{"class":240}," mpatches\n",[230,296,298,300,302,304,307,309],{"class":232,"line":297},6,[230,299,248],{"class":247},[230,301,280],{"class":240},[230,303,284],{"class":283},[230,305,306],{"class":287},"pyplot",[230,308,291],{"class":247},[230,310,311],{"class":240}," plt\n",[230,313,315,317,320,323],{"class":232,"line":314},7,[230,316,248],{"class":247},[230,318,319],{"class":240}," numpy ",[230,321,322],{"class":247},"as",[230,324,325],{"class":240}," np\n",[230,327,329,331],{"class":232,"line":328},8,[230,330,248],{"class":247},[230,332,333],{"class":240}," torch\n",[230,335,337,339],{"class":232,"line":336},9,[230,338,248],{"class":247},[230,340,341],{"class":240}," torchmatch\n",[230,343,345,347,350,352,355,357,360],{"class":232,"line":344},10,[230,346,257],{"class":247},[230,348,349],{"class":240}," scipy",[230,351,284],{"class":283},[230,353,354],{"class":240},"optimize ",[230,356,248],{"class":247},[230,358,359],{"class":240}," linear_sum_assignment  ",[230,361,363],{"class":362},"sutJx","# reference solver\n",[230,365,367],{"class":232,"line":366},11,[230,368,272],{"emptyLinePlaceholder":271},[230,370,372,375,377,380,382,386,389,393,397,399,402,406,409,412,415,417,419,422],{"class":232,"line":371},12,[230,373,374],{"class":240},"plt",[230,376,284],{"class":283},[230,378,379],{"class":287},"rcParams",[230,381,284],{"class":283},[230,383,385],{"class":384},"slqww","update",[230,387,388],{"class":283},"({",[230,390,392],{"class":391},"sjJ54","\"",[230,394,396],{"class":395},"s_sjI","figure.dpi",[230,398,392],{"class":391},[230,400,401],{"class":283},":",[230,403,405],{"class":404},"srdBf"," 120",[230,407,408],{"class":283},",",[230,410,411],{"class":391}," \"",[230,413,414],{"class":395},"font.size",[230,416,392],{"class":391},[230,418,401],{"class":283},[230,420,421],{"class":404}," 11",[230,423,424],{"class":283},"})\n",[230,426,428,431,434,437,439,442,444,447,450,453],{"class":232,"line":427},13,[230,429,430],{"class":240},"rng ",[230,432,433],{"class":236},"=",[230,435,436],{"class":240}," np",[230,438,284],{"class":283},[230,440,441],{"class":287},"random",[230,443,284],{"class":283},[230,445,446],{"class":384},"default_rng",[230,448,449],{"class":283},"(",[230,451,452],{"class":404},"42",[230,454,455],{"class":283},")\n",[230,457,459,463,465,467,470,472,474,477,479,483,485,487,490,492,494,497,499,501],{"class":232,"line":458},14,[230,460,462],{"class":461},"sptTA","print",[230,464,449],{"class":283},[230,466,392],{"class":391},[230,468,469],{"class":395},"torchmatch",[230,471,392],{"class":391},[230,473,408],{"class":283},[230,475,476],{"class":384}," torchmatch",[230,478,284],{"class":283},[230,480,482],{"class":481},"s_hVV","__version__",[230,484,408],{"class":283},[230,486,411],{"class":391},[230,488,489],{"class":395},"| torch",[230,491,392],{"class":391},[230,493,408],{"class":283},[230,495,496],{"class":384}," torch",[230,498,284],{"class":283},[230,500,482],{"class":481},[230,502,455],{"class":283},[504,505],"docyard-notebook-output",{"data":506,"kind":507},"dG9yY2htYXRjaCAxLjAuMCB8IHRvcmNoIDIuMTEuMCtjdTEyOAo=","stream",[509,510,512],"h2",{"id":511},"_1-a-concrete-example-taxi-dispatch","1  A concrete example: taxi dispatch",[185,514,515,516,519,520,523,524,527,528,531,532,535],{},"Three taxis wait at different spots in a city.  Three passengers need rides.\nThe ",[188,517,518],{},"cost matrix"," ",[211,521,522],{},"C[i, j]"," holds the travel time (in minutes) from taxi\n",[211,525,526],{},"i"," to passenger ",[211,529,530],{},"j",".  We want to send each taxi to exactly one passenger\nand minimise ",[188,533,534],{},"total"," travel time.",[185,537,538,539,542],{},"This is the ",[188,540,541],{},"linear assignment problem (LAP)",": given a cost matrix, find\nthe one-to-one assignment of rows to columns with minimum total cost.",[221,544,546],{"className":223,"code":545,"language":225,"meta":226,"style":226},"# rows = taxis, columns = passengers\nC = np.array(\n    [\n        [4.0, 1.0, 3.0],  # taxi 0: 4 min to p0, 1 min to p1, 3 min to p2\n        [2.0, 0.5, 5.0],  # taxi 1: very close to p1\n        [3.0, 2.0, 2.0],  # taxi 2: moderate distance to all\n    ],\n    dtype=np.float32,\n)\n\nlabels_row = [\"Taxi 0\", \"Taxi 1\", \"Taxi 2\"]\nlabels_col = [\"Passenger 0\", \"Passenger 1\", \"Passenger 2\"]\n\nfig, ax = plt.subplots(figsize=(5, 3))\nim = ax.imshow(C, cmap=\"YlOrRd_r\", vmin=0, vmax=6)\nax.set_xticks(range(3))\nax.set_yticks(range(3))\nax.set_xticklabels(labels_col, rotation=20, ha=\"right\")\nax.set_yticklabels(labels_row)\nplt.colorbar(im, ax=ax, label=\"Travel time (min)\")\nfor i in range(3):\n    for j in range(3):\n        ax.text(\n            j,\n            i,\n            f\"{C[i, j]:.1f}\",\n            ha=\"center\",\n            va=\"center\",\n            fontsize=13,\n            fontweight=\"bold\",\n            color=\"white\" if C[i, j] > 3 else \"black\",\n        )\nax.set_title(\"Cost matrix  C[taxi, passenger]\")\nplt.tight_layout()\nplt.show()\n",[211,547,548,553,570,575,599,621,642,647,666,670,674,712,748,752,792,849,872,892,933,950,989,1011,1030,1043,1051,1059,1096,1113,1129,1142,1159,1207,1213,1234,1247],{"__ignoreMap":226},[230,549,550],{"class":232,"line":233},[230,551,552],{"class":362},"# rows = taxis, columns = passengers\n",[230,554,555,558,560,562,564,567],{"class":232,"line":244},[230,556,557],{"class":240},"C ",[230,559,433],{"class":236},[230,561,436],{"class":240},[230,563,284],{"class":283},[230,565,566],{"class":384},"array",[230,568,569],{"class":283},"(\n",[230,571,572],{"class":232,"line":254},[230,573,574],{"class":283},"    [\n",[230,576,577,580,583,585,588,590,593,596],{"class":232,"line":268},[230,578,579],{"class":283},"        [",[230,581,582],{"class":404},"4.0",[230,584,408],{"class":283},[230,586,587],{"class":404}," 1.0",[230,589,408],{"class":283},[230,591,592],{"class":404}," 3.0",[230,594,595],{"class":283},"],",[230,597,598],{"class":362},"  # taxi 0: 4 min to p0, 1 min to p1, 3 min to p2\n",[230,600,601,603,606,608,611,613,616,618],{"class":232,"line":275},[230,602,579],{"class":283},[230,604,605],{"class":404},"2.0",[230,607,408],{"class":283},[230,609,610],{"class":404}," 0.5",[230,612,408],{"class":283},[230,614,615],{"class":404}," 5.0",[230,617,595],{"class":283},[230,619,620],{"class":362},"  # taxi 1: very close to p1\n",[230,622,623,625,628,630,633,635,637,639],{"class":232,"line":297},[230,624,579],{"class":283},[230,626,627],{"class":404},"3.0",[230,629,408],{"class":283},[230,631,632],{"class":404}," 2.0",[230,634,408],{"class":283},[230,636,632],{"class":404},[230,638,595],{"class":283},[230,640,641],{"class":362},"  # taxi 2: moderate distance to all\n",[230,643,644],{"class":232,"line":314},[230,645,646],{"class":283},"    ],\n",[230,648,649,653,655,658,660,663],{"class":232,"line":328},[230,650,652],{"class":651},"s99_P","    dtype",[230,654,433],{"class":236},[230,656,657],{"class":384},"np",[230,659,284],{"class":283},[230,661,662],{"class":287},"float32",[230,664,665],{"class":283},",\n",[230,667,668],{"class":232,"line":336},[230,669,455],{"class":283},[230,671,672],{"class":232,"line":344},[230,673,272],{"emptyLinePlaceholder":271},[230,675,676,679,681,684,686,689,691,693,695,698,700,702,704,707,709],{"class":232,"line":366},[230,677,678],{"class":240},"labels_row ",[230,680,433],{"class":236},[230,682,683],{"class":283}," [",[230,685,392],{"class":391},[230,687,688],{"class":395},"Taxi 0",[230,690,392],{"class":391},[230,692,408],{"class":283},[230,694,411],{"class":391},[230,696,697],{"class":395},"Taxi 1",[230,699,392],{"class":391},[230,701,408],{"class":283},[230,703,411],{"class":391},[230,705,706],{"class":395},"Taxi 2",[230,708,392],{"class":391},[230,710,711],{"class":283},"]\n",[230,713,714,717,719,721,723,726,728,730,732,735,737,739,741,744,746],{"class":232,"line":371},[230,715,716],{"class":240},"labels_col ",[230,718,433],{"class":236},[230,720,683],{"class":283},[230,722,392],{"class":391},[230,724,725],{"class":395},"Passenger 0",[230,727,392],{"class":391},[230,729,408],{"class":283},[230,731,411],{"class":391},[230,733,734],{"class":395},"Passenger 1",[230,736,392],{"class":391},[230,738,408],{"class":283},[230,740,411],{"class":391},[230,742,743],{"class":395},"Passenger 2",[230,745,392],{"class":391},[230,747,711],{"class":283},[230,749,750],{"class":232,"line":427},[230,751,272],{"emptyLinePlaceholder":271},[230,753,754,757,759,762,764,767,769,772,774,777,779,781,784,786,789],{"class":232,"line":458},[230,755,756],{"class":240},"fig",[230,758,408],{"class":283},[230,760,761],{"class":240}," ax ",[230,763,433],{"class":236},[230,765,766],{"class":240}," plt",[230,768,284],{"class":283},[230,770,771],{"class":384},"subplots",[230,773,449],{"class":283},[230,775,776],{"class":651},"figsize",[230,778,433],{"class":236},[230,780,449],{"class":283},[230,782,783],{"class":404},"5",[230,785,408],{"class":283},[230,787,788],{"class":404}," 3",[230,790,791],{"class":283},"))\n",[230,793,795,798,800,803,805,808,810,813,815,818,820,822,825,827,829,832,834,837,839,842,844,847],{"class":232,"line":794},15,[230,796,797],{"class":240},"im ",[230,799,433],{"class":236},[230,801,802],{"class":240}," ax",[230,804,284],{"class":283},[230,806,807],{"class":384},"imshow",[230,809,449],{"class":283},[230,811,812],{"class":384},"C",[230,814,408],{"class":283},[230,816,817],{"class":651}," cmap",[230,819,433],{"class":236},[230,821,392],{"class":391},[230,823,824],{"class":395},"YlOrRd_r",[230,826,392],{"class":391},[230,828,408],{"class":283},[230,830,831],{"class":651}," vmin",[230,833,433],{"class":236},[230,835,836],{"class":404},"0",[230,838,408],{"class":283},[230,840,841],{"class":651}," vmax",[230,843,433],{"class":236},[230,845,846],{"class":404},"6",[230,848,455],{"class":283},[230,850,852,855,857,860,862,865,867,870],{"class":232,"line":851},16,[230,853,854],{"class":240},"ax",[230,856,284],{"class":283},[230,858,859],{"class":384},"set_xticks",[230,861,449],{"class":283},[230,863,864],{"class":461},"range",[230,866,449],{"class":283},[230,868,869],{"class":404},"3",[230,871,791],{"class":283},[230,873,875,877,879,882,884,886,888,890],{"class":232,"line":874},17,[230,876,854],{"class":240},[230,878,284],{"class":283},[230,880,881],{"class":384},"set_yticks",[230,883,449],{"class":283},[230,885,864],{"class":461},[230,887,449],{"class":283},[230,889,869],{"class":404},[230,891,791],{"class":283},[230,893,895,897,899,902,904,907,909,912,914,917,919,922,924,926,929,931],{"class":232,"line":894},18,[230,896,854],{"class":240},[230,898,284],{"class":283},[230,900,901],{"class":384},"set_xticklabels",[230,903,449],{"class":283},[230,905,906],{"class":384},"labels_col",[230,908,408],{"class":283},[230,910,911],{"class":651}," rotation",[230,913,433],{"class":236},[230,915,916],{"class":404},"20",[230,918,408],{"class":283},[230,920,921],{"class":651}," ha",[230,923,433],{"class":236},[230,925,392],{"class":391},[230,927,928],{"class":395},"right",[230,930,392],{"class":391},[230,932,455],{"class":283},[230,934,936,938,940,943,945,948],{"class":232,"line":935},19,[230,937,854],{"class":240},[230,939,284],{"class":283},[230,941,942],{"class":384},"set_yticklabels",[230,944,449],{"class":283},[230,946,947],{"class":384},"labels_row",[230,949,455],{"class":283},[230,951,953,955,957,960,962,965,967,969,971,973,975,978,980,982,985,987],{"class":232,"line":952},20,[230,954,374],{"class":240},[230,956,284],{"class":283},[230,958,959],{"class":384},"colorbar",[230,961,449],{"class":283},[230,963,964],{"class":384},"im",[230,966,408],{"class":283},[230,968,802],{"class":651},[230,970,433],{"class":236},[230,972,854],{"class":384},[230,974,408],{"class":283},[230,976,977],{"class":651}," label",[230,979,433],{"class":236},[230,981,392],{"class":391},[230,983,984],{"class":395},"Travel time (min)",[230,986,392],{"class":391},[230,988,455],{"class":283},[230,990,992,995,998,1001,1004,1006,1008],{"class":232,"line":991},21,[230,993,994],{"class":247},"for",[230,996,997],{"class":240}," i ",[230,999,1000],{"class":247},"in",[230,1002,1003],{"class":461}," range",[230,1005,449],{"class":283},[230,1007,869],{"class":404},[230,1009,1010],{"class":283},"):\n",[230,1012,1014,1017,1020,1022,1024,1026,1028],{"class":232,"line":1013},22,[230,1015,1016],{"class":247},"    for",[230,1018,1019],{"class":240}," j ",[230,1021,1000],{"class":247},[230,1023,1003],{"class":461},[230,1025,449],{"class":283},[230,1027,869],{"class":404},[230,1029,1010],{"class":283},[230,1031,1033,1036,1038,1041],{"class":232,"line":1032},23,[230,1034,1035],{"class":240},"        ax",[230,1037,284],{"class":283},[230,1039,1040],{"class":384},"text",[230,1042,569],{"class":283},[230,1044,1046,1049],{"class":232,"line":1045},24,[230,1047,1048],{"class":384},"            j",[230,1050,665],{"class":283},[230,1052,1054,1057],{"class":232,"line":1053},25,[230,1055,1056],{"class":384},"            i",[230,1058,665],{"class":283},[230,1060,1062,1066,1068,1071,1073,1076,1078,1080,1083,1086,1089,1092,1094],{"class":232,"line":1061},26,[230,1063,1065],{"class":1064},"sbsja","            f",[230,1067,392],{"class":395},[230,1069,1070],{"class":404},"{",[230,1072,812],{"class":384},[230,1074,1075],{"class":283},"[",[230,1077,526],{"class":384},[230,1079,408],{"class":283},[230,1081,1082],{"class":384}," j",[230,1084,1085],{"class":283},"]",[230,1087,1088],{"class":1064},":.1f",[230,1090,1091],{"class":404},"}",[230,1093,392],{"class":395},[230,1095,665],{"class":283},[230,1097,1099,1102,1104,1106,1109,1111],{"class":232,"line":1098},27,[230,1100,1101],{"class":651},"            ha",[230,1103,433],{"class":236},[230,1105,392],{"class":391},[230,1107,1108],{"class":395},"center",[230,1110,392],{"class":391},[230,1112,665],{"class":283},[230,1114,1116,1119,1121,1123,1125,1127],{"class":232,"line":1115},28,[230,1117,1118],{"class":651},"            va",[230,1120,433],{"class":236},[230,1122,392],{"class":391},[230,1124,1108],{"class":395},[230,1126,392],{"class":391},[230,1128,665],{"class":283},[230,1130,1132,1135,1137,1140],{"class":232,"line":1131},29,[230,1133,1134],{"class":651},"            fontsize",[230,1136,433],{"class":236},[230,1138,1139],{"class":404},"13",[230,1141,665],{"class":283},[230,1143,1145,1148,1150,1152,1155,1157],{"class":232,"line":1144},30,[230,1146,1147],{"class":651},"            fontweight",[230,1149,433],{"class":236},[230,1151,392],{"class":391},[230,1153,1154],{"class":395},"bold",[230,1156,392],{"class":391},[230,1158,665],{"class":283},[230,1160,1162,1165,1167,1169,1172,1174,1177,1180,1182,1184,1186,1188,1190,1193,1195,1198,1200,1203,1205],{"class":232,"line":1161},31,[230,1163,1164],{"class":651},"            color",[230,1166,433],{"class":236},[230,1168,392],{"class":391},[230,1170,1171],{"class":395},"white",[230,1173,392],{"class":391},[230,1175,1176],{"class":247}," if",[230,1178,1179],{"class":384}," C",[230,1181,1075],{"class":283},[230,1183,526],{"class":384},[230,1185,408],{"class":283},[230,1187,1082],{"class":384},[230,1189,1085],{"class":283},[230,1191,1192],{"class":236}," >",[230,1194,788],{"class":404},[230,1196,1197],{"class":247}," else",[230,1199,411],{"class":391},[230,1201,1202],{"class":395},"black",[230,1204,392],{"class":391},[230,1206,665],{"class":283},[230,1208,1210],{"class":232,"line":1209},32,[230,1211,1212],{"class":283},"        )\n",[230,1214,1216,1218,1220,1223,1225,1227,1230,1232],{"class":232,"line":1215},33,[230,1217,854],{"class":240},[230,1219,284],{"class":283},[230,1221,1222],{"class":384},"set_title",[230,1224,449],{"class":283},[230,1226,392],{"class":391},[230,1228,1229],{"class":395},"Cost matrix  C[taxi, passenger]",[230,1231,392],{"class":391},[230,1233,455],{"class":283},[230,1235,1237,1239,1241,1244],{"class":232,"line":1236},34,[230,1238,374],{"class":240},[230,1240,284],{"class":283},[230,1242,1243],{"class":384},"tight_layout",[230,1245,1246],{"class":283},"()\n",[230,1248,1250,1252,1254,1257],{"class":232,"line":1249},35,[230,1251,374],{"class":240},[230,1253,284],{"class":283},[230,1255,1256],{"class":384},"show",[230,1258,1246],{"class":283},[185,1260,1261],{},[1262,1263],"img",{"alt":226,"src":1264},"\u002F_nb\u002F7c6eba83e27db9fc.png",[1266,1267,1269],"h3",{"id":1268},"visualising-the-problem-as-a-bipartite-graph","Visualising the problem as a bipartite graph",[185,1271,1272],{},"An assignment problem always has this structure: two disjoint groups of\nitems (taxis on the left, passengers on the right), with a potential\nconnection — and a cost — between every item in the left group and every\nitem in the right group.  A valid assignment picks exactly one edge per\nleft node and exactly one edge per right node (a perfect matching).",[221,1274,1276],{"className":223,"code":1275,"language":225,"meta":226,"style":226},"def draw_bipartite(ax, left_labels, right_labels, matching=None, costs=None, title=\"\"):\n    n = len(left_labels)\n    left_x, right_x = 0.15, 0.85\n    left_ys = np.linspace(0.85, 0.15, n)\n    right_ys = np.linspace(0.85, 0.15, n)\n\n    # all edges (grey, thin)\n    for i, ly in enumerate(left_ys):\n        for j, ry in enumerate(right_ys):\n            ax.plot([left_x, right_x], [ly, ry], color=\"#cccccc\", lw=0.8, zorder=1)\n            if costs is not None:\n                mx, my = (left_x + right_x) \u002F 2, (ly + ry) \u002F 2\n                ax.text(\n                    mx,\n                    my,\n                    f\"{costs[i, j]:.1f}\",\n                    fontsize=7,\n                    ha=\"center\",\n                    va=\"center\",\n                    color=\"#888888\",\n                )\n\n    # matched edges (red, thick)\n    if matching is not None:\n        for i, j in enumerate(matching):\n            ax.plot(\n                [left_x, right_x],\n                [left_ys[i], right_ys[j]],\n                color=\"#E03520\",\n                lw=2.5,\n                zorder=2,\n            )\n\n    # nodes\n    for i, (y, lbl) in enumerate(zip(left_ys, left_labels)):\n        ax.scatter(left_x, y, s=600, color=\"#1a6daf\", zorder=3)\n        ax.text(left_x - 0.04, y, lbl, ha=\"right\", va=\"center\", fontsize=10)\n    for j, (y, lbl) in enumerate(zip(right_ys, right_labels)):\n        ax.scatter(right_x, y, s=600, color=\"#d97706\", zorder=3)\n        ax.text(right_x + 0.04, y, lbl, ha=\"left\", va=\"center\", fontsize=10)\n\n    ax.set_xlim(0, 1)\n    ax.set_ylim(0, 1)\n    ax.axis(\"off\")\n    ax.set_title(title)\n\n\nfig, axes = plt.subplots(1, 2, figsize=(11, 4))\ndraw_bipartite(axes[0], labels_row, labels_col, costs=C, title=\"All possible edges\")\n# naive sequential assignment: taxi 0 → passenger 0, taxi 1 → passenger 1, etc.\nnaive = [0, 1, 2]\ncost_naive = sum(C[i, j] for i, j in enumerate(naive))\ndraw_bipartite(\n    axes[1],\n    labels_row,\n    labels_col,\n    matching=naive,\n    costs=C,\n    title=f\"Naïve assignment  (total = {cost_naive:.1f} min)\",\n)\nplt.tight_layout()\nplt.show()\n",[211,1277,1278,1334,1351,1371,1401,1428,1432,1437,1461,1484,1553,1573,1623,1634,1641,1648,1678,1690,1705,1720,1736,1741,1745,1750,1766,1787,1797,1811,1833,1849,1861,1873,1878,1882,1887,1928,1980,2044,2081,2130,2191,2196,2218,2238,2259,2275,2280,2285,2330,2378,2384,2406,2451,2458,2470,2478,2486,2498,2510,2538,2543,2554],{"__ignoreMap":226},[230,1279,1280,1283,1287,1289,1292,1294,1297,1299,1302,1304,1307,1309,1313,1315,1318,1320,1322,1324,1327,1329,1332],{"class":232,"line":233},[230,1281,1282],{"class":1064},"def",[230,1284,1286],{"class":1285},"sGLFI"," draw_bipartite",[230,1288,449],{"class":283},[230,1290,854],{"class":1291},"sFwrP",[230,1293,408],{"class":283},[230,1295,1296],{"class":1291}," left_labels",[230,1298,408],{"class":283},[230,1300,1301],{"class":1291}," right_labels",[230,1303,408],{"class":283},[230,1305,1306],{"class":1291}," matching",[230,1308,433],{"class":236},[230,1310,1312],{"class":1311},"s39Yj","None",[230,1314,408],{"class":283},[230,1316,1317],{"class":1291}," costs",[230,1319,433],{"class":236},[230,1321,1312],{"class":1311},[230,1323,408],{"class":283},[230,1325,1326],{"class":1291}," title",[230,1328,433],{"class":236},[230,1330,1331],{"class":391},"\"\"",[230,1333,1010],{"class":283},[230,1335,1336,1339,1341,1344,1346,1349],{"class":232,"line":244},[230,1337,1338],{"class":240},"    n ",[230,1340,433],{"class":236},[230,1342,1343],{"class":461}," len",[230,1345,449],{"class":283},[230,1347,1348],{"class":384},"left_labels",[230,1350,455],{"class":283},[230,1352,1353,1356,1358,1361,1363,1366,1368],{"class":232,"line":254},[230,1354,1355],{"class":240},"    left_x",[230,1357,408],{"class":283},[230,1359,1360],{"class":240}," right_x ",[230,1362,433],{"class":236},[230,1364,1365],{"class":404}," 0.15",[230,1367,408],{"class":283},[230,1369,1370],{"class":404}," 0.85\n",[230,1372,1373,1376,1378,1380,1382,1385,1387,1390,1392,1394,1396,1399],{"class":232,"line":268},[230,1374,1375],{"class":240},"    left_ys ",[230,1377,433],{"class":236},[230,1379,436],{"class":240},[230,1381,284],{"class":283},[230,1383,1384],{"class":384},"linspace",[230,1386,449],{"class":283},[230,1388,1389],{"class":404},"0.85",[230,1391,408],{"class":283},[230,1393,1365],{"class":404},[230,1395,408],{"class":283},[230,1397,1398],{"class":384}," n",[230,1400,455],{"class":283},[230,1402,1403,1406,1408,1410,1412,1414,1416,1418,1420,1422,1424,1426],{"class":232,"line":275},[230,1404,1405],{"class":240},"    right_ys ",[230,1407,433],{"class":236},[230,1409,436],{"class":240},[230,1411,284],{"class":283},[230,1413,1384],{"class":384},[230,1415,449],{"class":283},[230,1417,1389],{"class":404},[230,1419,408],{"class":283},[230,1421,1365],{"class":404},[230,1423,408],{"class":283},[230,1425,1398],{"class":384},[230,1427,455],{"class":283},[230,1429,1430],{"class":232,"line":297},[230,1431,272],{"emptyLinePlaceholder":271},[230,1433,1434],{"class":232,"line":314},[230,1435,1436],{"class":362},"    # all edges (grey, thin)\n",[230,1438,1439,1441,1444,1446,1449,1451,1454,1456,1459],{"class":232,"line":328},[230,1440,1016],{"class":247},[230,1442,1443],{"class":240}," i",[230,1445,408],{"class":283},[230,1447,1448],{"class":240}," ly ",[230,1450,1000],{"class":247},[230,1452,1453],{"class":461}," enumerate",[230,1455,449],{"class":283},[230,1457,1458],{"class":384},"left_ys",[230,1460,1010],{"class":283},[230,1462,1463,1466,1468,1470,1473,1475,1477,1479,1482],{"class":232,"line":336},[230,1464,1465],{"class":247},"        for",[230,1467,1082],{"class":240},[230,1469,408],{"class":283},[230,1471,1472],{"class":240}," ry ",[230,1474,1000],{"class":247},[230,1476,1453],{"class":461},[230,1478,449],{"class":283},[230,1480,1481],{"class":384},"right_ys",[230,1483,1010],{"class":283},[230,1485,1486,1489,1491,1494,1497,1500,1502,1505,1507,1509,1512,1514,1517,1519,1522,1524,1526,1529,1531,1533,1536,1538,1541,1543,1546,1548,1551],{"class":232,"line":344},[230,1487,1488],{"class":240},"            ax",[230,1490,284],{"class":283},[230,1492,1493],{"class":384},"plot",[230,1495,1496],{"class":283},"([",[230,1498,1499],{"class":384},"left_x",[230,1501,408],{"class":283},[230,1503,1504],{"class":384}," right_x",[230,1506,595],{"class":283},[230,1508,683],{"class":283},[230,1510,1511],{"class":384},"ly",[230,1513,408],{"class":283},[230,1515,1516],{"class":384}," ry",[230,1518,595],{"class":283},[230,1520,1521],{"class":651}," color",[230,1523,433],{"class":236},[230,1525,392],{"class":391},[230,1527,1528],{"class":395},"#cccccc",[230,1530,392],{"class":391},[230,1532,408],{"class":283},[230,1534,1535],{"class":651}," lw",[230,1537,433],{"class":236},[230,1539,1540],{"class":404},"0.8",[230,1542,408],{"class":283},[230,1544,1545],{"class":651}," zorder",[230,1547,433],{"class":236},[230,1549,1550],{"class":404},"1",[230,1552,455],{"class":283},[230,1554,1555,1558,1561,1564,1567,1570],{"class":232,"line":366},[230,1556,1557],{"class":247},"            if",[230,1559,1560],{"class":240}," costs ",[230,1562,1563],{"class":236},"is",[230,1565,1566],{"class":236}," not",[230,1568,1569],{"class":1311}," None",[230,1571,1572],{"class":283},":\n",[230,1574,1575,1578,1580,1583,1585,1588,1591,1594,1596,1599,1602,1605,1607,1609,1612,1614,1616,1618,1620],{"class":232,"line":371},[230,1576,1577],{"class":240},"                mx",[230,1579,408],{"class":283},[230,1581,1582],{"class":240}," my ",[230,1584,433],{"class":236},[230,1586,1587],{"class":283}," (",[230,1589,1590],{"class":240},"left_x ",[230,1592,1593],{"class":236},"+",[230,1595,1504],{"class":240},[230,1597,1598],{"class":283},")",[230,1600,1601],{"class":236}," \u002F",[230,1603,1604],{"class":404}," 2",[230,1606,408],{"class":283},[230,1608,1587],{"class":283},[230,1610,1611],{"class":240},"ly ",[230,1613,1593],{"class":236},[230,1615,1516],{"class":240},[230,1617,1598],{"class":283},[230,1619,1601],{"class":236},[230,1621,1622],{"class":404}," 2\n",[230,1624,1625,1628,1630,1632],{"class":232,"line":427},[230,1626,1627],{"class":240},"                ax",[230,1629,284],{"class":283},[230,1631,1040],{"class":384},[230,1633,569],{"class":283},[230,1635,1636,1639],{"class":232,"line":458},[230,1637,1638],{"class":384},"                    mx",[230,1640,665],{"class":283},[230,1642,1643,1646],{"class":232,"line":794},[230,1644,1645],{"class":384},"                    my",[230,1647,665],{"class":283},[230,1649,1650,1653,1655,1657,1660,1662,1664,1666,1668,1670,1672,1674,1676],{"class":232,"line":851},[230,1651,1652],{"class":1064},"                    f",[230,1654,392],{"class":395},[230,1656,1070],{"class":404},[230,1658,1659],{"class":384},"costs",[230,1661,1075],{"class":283},[230,1663,526],{"class":384},[230,1665,408],{"class":283},[230,1667,1082],{"class":384},[230,1669,1085],{"class":283},[230,1671,1088],{"class":1064},[230,1673,1091],{"class":404},[230,1675,392],{"class":395},[230,1677,665],{"class":283},[230,1679,1680,1683,1685,1688],{"class":232,"line":874},[230,1681,1682],{"class":651},"                    fontsize",[230,1684,433],{"class":236},[230,1686,1687],{"class":404},"7",[230,1689,665],{"class":283},[230,1691,1692,1695,1697,1699,1701,1703],{"class":232,"line":894},[230,1693,1694],{"class":651},"                    ha",[230,1696,433],{"class":236},[230,1698,392],{"class":391},[230,1700,1108],{"class":395},[230,1702,392],{"class":391},[230,1704,665],{"class":283},[230,1706,1707,1710,1712,1714,1716,1718],{"class":232,"line":935},[230,1708,1709],{"class":651},"                    va",[230,1711,433],{"class":236},[230,1713,392],{"class":391},[230,1715,1108],{"class":395},[230,1717,392],{"class":391},[230,1719,665],{"class":283},[230,1721,1722,1725,1727,1729,1732,1734],{"class":232,"line":952},[230,1723,1724],{"class":651},"                    color",[230,1726,433],{"class":236},[230,1728,392],{"class":391},[230,1730,1731],{"class":395},"#888888",[230,1733,392],{"class":391},[230,1735,665],{"class":283},[230,1737,1738],{"class":232,"line":991},[230,1739,1740],{"class":283},"                )\n",[230,1742,1743],{"class":232,"line":1013},[230,1744,272],{"emptyLinePlaceholder":271},[230,1746,1747],{"class":232,"line":1032},[230,1748,1749],{"class":362},"    # matched edges (red, thick)\n",[230,1751,1752,1755,1758,1760,1762,1764],{"class":232,"line":1045},[230,1753,1754],{"class":247},"    if",[230,1756,1757],{"class":240}," matching ",[230,1759,1563],{"class":236},[230,1761,1566],{"class":236},[230,1763,1569],{"class":1311},[230,1765,1572],{"class":283},[230,1767,1768,1770,1772,1774,1776,1778,1780,1782,1785],{"class":232,"line":1053},[230,1769,1465],{"class":247},[230,1771,1443],{"class":240},[230,1773,408],{"class":283},[230,1775,1019],{"class":240},[230,1777,1000],{"class":247},[230,1779,1453],{"class":461},[230,1781,449],{"class":283},[230,1783,1784],{"class":384},"matching",[230,1786,1010],{"class":283},[230,1788,1789,1791,1793,1795],{"class":232,"line":1061},[230,1790,1488],{"class":240},[230,1792,284],{"class":283},[230,1794,1493],{"class":384},[230,1796,569],{"class":283},[230,1798,1799,1802,1804,1806,1808],{"class":232,"line":1098},[230,1800,1801],{"class":283},"                [",[230,1803,1499],{"class":384},[230,1805,408],{"class":283},[230,1807,1504],{"class":384},[230,1809,1810],{"class":283},"],\n",[230,1812,1813,1815,1817,1819,1821,1823,1826,1828,1830],{"class":232,"line":1115},[230,1814,1801],{"class":283},[230,1816,1458],{"class":384},[230,1818,1075],{"class":283},[230,1820,526],{"class":384},[230,1822,595],{"class":283},[230,1824,1825],{"class":384}," right_ys",[230,1827,1075],{"class":283},[230,1829,530],{"class":384},[230,1831,1832],{"class":283},"]],\n",[230,1834,1835,1838,1840,1842,1845,1847],{"class":232,"line":1131},[230,1836,1837],{"class":651},"                color",[230,1839,433],{"class":236},[230,1841,392],{"class":391},[230,1843,1844],{"class":395},"#E03520",[230,1846,392],{"class":391},[230,1848,665],{"class":283},[230,1850,1851,1854,1856,1859],{"class":232,"line":1144},[230,1852,1853],{"class":651},"                lw",[230,1855,433],{"class":236},[230,1857,1858],{"class":404},"2.5",[230,1860,665],{"class":283},[230,1862,1863,1866,1868,1871],{"class":232,"line":1161},[230,1864,1865],{"class":651},"                zorder",[230,1867,433],{"class":236},[230,1869,1870],{"class":404},"2",[230,1872,665],{"class":283},[230,1874,1875],{"class":232,"line":1209},[230,1876,1877],{"class":283},"            )\n",[230,1879,1880],{"class":232,"line":1215},[230,1881,272],{"emptyLinePlaceholder":271},[230,1883,1884],{"class":232,"line":1236},[230,1885,1886],{"class":362},"    # nodes\n",[230,1888,1889,1891,1893,1895,1897,1900,1902,1905,1907,1910,1912,1914,1917,1919,1921,1923,1925],{"class":232,"line":1249},[230,1890,1016],{"class":247},[230,1892,1443],{"class":240},[230,1894,408],{"class":283},[230,1896,1587],{"class":283},[230,1898,1899],{"class":240},"y",[230,1901,408],{"class":283},[230,1903,1904],{"class":240}," lbl",[230,1906,1598],{"class":283},[230,1908,1909],{"class":247}," in",[230,1911,1453],{"class":461},[230,1913,449],{"class":283},[230,1915,1916],{"class":461},"zip",[230,1918,449],{"class":283},[230,1920,1458],{"class":384},[230,1922,408],{"class":283},[230,1924,1296],{"class":384},[230,1926,1927],{"class":283},")):\n",[230,1929,1931,1933,1935,1938,1940,1942,1944,1947,1949,1952,1954,1957,1959,1961,1963,1965,1968,1970,1972,1974,1976,1978],{"class":232,"line":1930},36,[230,1932,1035],{"class":240},[230,1934,284],{"class":283},[230,1936,1937],{"class":384},"scatter",[230,1939,449],{"class":283},[230,1941,1499],{"class":384},[230,1943,408],{"class":283},[230,1945,1946],{"class":384}," y",[230,1948,408],{"class":283},[230,1950,1951],{"class":651}," s",[230,1953,433],{"class":236},[230,1955,1956],{"class":404},"600",[230,1958,408],{"class":283},[230,1960,1521],{"class":651},[230,1962,433],{"class":236},[230,1964,392],{"class":391},[230,1966,1967],{"class":395},"#1a6daf",[230,1969,392],{"class":391},[230,1971,408],{"class":283},[230,1973,1545],{"class":651},[230,1975,433],{"class":236},[230,1977,869],{"class":404},[230,1979,455],{"class":283},[230,1981,1983,1985,1987,1989,1991,1993,1996,1999,2001,2003,2005,2007,2009,2011,2013,2015,2017,2019,2021,2024,2026,2028,2030,2032,2034,2037,2039,2042],{"class":232,"line":1982},37,[230,1984,1035],{"class":240},[230,1986,284],{"class":283},[230,1988,1040],{"class":384},[230,1990,449],{"class":283},[230,1992,1590],{"class":384},[230,1994,1995],{"class":236},"-",[230,1997,1998],{"class":404}," 0.04",[230,2000,408],{"class":283},[230,2002,1946],{"class":384},[230,2004,408],{"class":283},[230,2006,1904],{"class":384},[230,2008,408],{"class":283},[230,2010,921],{"class":651},[230,2012,433],{"class":236},[230,2014,392],{"class":391},[230,2016,928],{"class":395},[230,2018,392],{"class":391},[230,2020,408],{"class":283},[230,2022,2023],{"class":651}," va",[230,2025,433],{"class":236},[230,2027,392],{"class":391},[230,2029,1108],{"class":395},[230,2031,392],{"class":391},[230,2033,408],{"class":283},[230,2035,2036],{"class":651}," fontsize",[230,2038,433],{"class":236},[230,2040,2041],{"class":404},"10",[230,2043,455],{"class":283},[230,2045,2047,2049,2051,2053,2055,2057,2059,2061,2063,2065,2067,2069,2071,2073,2075,2077,2079],{"class":232,"line":2046},38,[230,2048,1016],{"class":247},[230,2050,1082],{"class":240},[230,2052,408],{"class":283},[230,2054,1587],{"class":283},[230,2056,1899],{"class":240},[230,2058,408],{"class":283},[230,2060,1904],{"class":240},[230,2062,1598],{"class":283},[230,2064,1909],{"class":247},[230,2066,1453],{"class":461},[230,2068,449],{"class":283},[230,2070,1916],{"class":461},[230,2072,449],{"class":283},[230,2074,1481],{"class":384},[230,2076,408],{"class":283},[230,2078,1301],{"class":384},[230,2080,1927],{"class":283},[230,2082,2084,2086,2088,2090,2092,2095,2097,2099,2101,2103,2105,2107,2109,2111,2113,2115,2118,2120,2122,2124,2126,2128],{"class":232,"line":2083},39,[230,2085,1035],{"class":240},[230,2087,284],{"class":283},[230,2089,1937],{"class":384},[230,2091,449],{"class":283},[230,2093,2094],{"class":384},"right_x",[230,2096,408],{"class":283},[230,2098,1946],{"class":384},[230,2100,408],{"class":283},[230,2102,1951],{"class":651},[230,2104,433],{"class":236},[230,2106,1956],{"class":404},[230,2108,408],{"class":283},[230,2110,1521],{"class":651},[230,2112,433],{"class":236},[230,2114,392],{"class":391},[230,2116,2117],{"class":395},"#d97706",[230,2119,392],{"class":391},[230,2121,408],{"class":283},[230,2123,1545],{"class":651},[230,2125,433],{"class":236},[230,2127,869],{"class":404},[230,2129,455],{"class":283},[230,2131,2133,2135,2137,2139,2141,2144,2146,2148,2150,2152,2154,2156,2158,2160,2162,2164,2167,2169,2171,2173,2175,2177,2179,2181,2183,2185,2187,2189],{"class":232,"line":2132},40,[230,2134,1035],{"class":240},[230,2136,284],{"class":283},[230,2138,1040],{"class":384},[230,2140,449],{"class":283},[230,2142,2143],{"class":384},"right_x ",[230,2145,1593],{"class":236},[230,2147,1998],{"class":404},[230,2149,408],{"class":283},[230,2151,1946],{"class":384},[230,2153,408],{"class":283},[230,2155,1904],{"class":384},[230,2157,408],{"class":283},[230,2159,921],{"class":651},[230,2161,433],{"class":236},[230,2163,392],{"class":391},[230,2165,2166],{"class":395},"left",[230,2168,392],{"class":391},[230,2170,408],{"class":283},[230,2172,2023],{"class":651},[230,2174,433],{"class":236},[230,2176,392],{"class":391},[230,2178,1108],{"class":395},[230,2180,392],{"class":391},[230,2182,408],{"class":283},[230,2184,2036],{"class":651},[230,2186,433],{"class":236},[230,2188,2041],{"class":404},[230,2190,455],{"class":283},[230,2192,2194],{"class":232,"line":2193},41,[230,2195,272],{"emptyLinePlaceholder":271},[230,2197,2199,2202,2204,2207,2209,2211,2213,2216],{"class":232,"line":2198},42,[230,2200,2201],{"class":240},"    ax",[230,2203,284],{"class":283},[230,2205,2206],{"class":384},"set_xlim",[230,2208,449],{"class":283},[230,2210,836],{"class":404},[230,2212,408],{"class":283},[230,2214,2215],{"class":404}," 1",[230,2217,455],{"class":283},[230,2219,2221,2223,2225,2228,2230,2232,2234,2236],{"class":232,"line":2220},43,[230,2222,2201],{"class":240},[230,2224,284],{"class":283},[230,2226,2227],{"class":384},"set_ylim",[230,2229,449],{"class":283},[230,2231,836],{"class":404},[230,2233,408],{"class":283},[230,2235,2215],{"class":404},[230,2237,455],{"class":283},[230,2239,2241,2243,2245,2248,2250,2252,2255,2257],{"class":232,"line":2240},44,[230,2242,2201],{"class":240},[230,2244,284],{"class":283},[230,2246,2247],{"class":384},"axis",[230,2249,449],{"class":283},[230,2251,392],{"class":391},[230,2253,2254],{"class":395},"off",[230,2256,392],{"class":391},[230,2258,455],{"class":283},[230,2260,2262,2264,2266,2268,2270,2273],{"class":232,"line":2261},45,[230,2263,2201],{"class":240},[230,2265,284],{"class":283},[230,2267,1222],{"class":384},[230,2269,449],{"class":283},[230,2271,2272],{"class":384},"title",[230,2274,455],{"class":283},[230,2276,2278],{"class":232,"line":2277},46,[230,2279,272],{"emptyLinePlaceholder":271},[230,2281,2283],{"class":232,"line":2282},47,[230,2284,272],{"emptyLinePlaceholder":271},[230,2286,2288,2290,2292,2295,2297,2299,2301,2303,2305,2307,2309,2311,2313,2316,2318,2320,2323,2325,2328],{"class":232,"line":2287},48,[230,2289,756],{"class":240},[230,2291,408],{"class":283},[230,2293,2294],{"class":240}," axes ",[230,2296,433],{"class":236},[230,2298,766],{"class":240},[230,2300,284],{"class":283},[230,2302,771],{"class":384},[230,2304,449],{"class":283},[230,2306,1550],{"class":404},[230,2308,408],{"class":283},[230,2310,1604],{"class":404},[230,2312,408],{"class":283},[230,2314,2315],{"class":651}," figsize",[230,2317,433],{"class":236},[230,2319,449],{"class":283},[230,2321,2322],{"class":404},"11",[230,2324,408],{"class":283},[230,2326,2327],{"class":404}," 4",[230,2329,791],{"class":283},[230,2331,2333,2336,2338,2341,2343,2345,2347,2350,2352,2355,2357,2359,2361,2363,2365,2367,2369,2371,2374,2376],{"class":232,"line":2332},49,[230,2334,2335],{"class":384},"draw_bipartite",[230,2337,449],{"class":283},[230,2339,2340],{"class":384},"axes",[230,2342,1075],{"class":283},[230,2344,836],{"class":404},[230,2346,595],{"class":283},[230,2348,2349],{"class":384}," labels_row",[230,2351,408],{"class":283},[230,2353,2354],{"class":384}," labels_col",[230,2356,408],{"class":283},[230,2358,1317],{"class":651},[230,2360,433],{"class":236},[230,2362,812],{"class":384},[230,2364,408],{"class":283},[230,2366,1326],{"class":651},[230,2368,433],{"class":236},[230,2370,392],{"class":391},[230,2372,2373],{"class":395},"All possible edges",[230,2375,392],{"class":391},[230,2377,455],{"class":283},[230,2379,2381],{"class":232,"line":2380},50,[230,2382,2383],{"class":362},"# naive sequential assignment: taxi 0 → passenger 0, taxi 1 → passenger 1, etc.\n",[230,2385,2387,2390,2392,2394,2396,2398,2400,2402,2404],{"class":232,"line":2386},51,[230,2388,2389],{"class":240},"naive ",[230,2391,433],{"class":236},[230,2393,683],{"class":283},[230,2395,836],{"class":404},[230,2397,408],{"class":283},[230,2399,2215],{"class":404},[230,2401,408],{"class":283},[230,2403,1604],{"class":404},[230,2405,711],{"class":283},[230,2407,2409,2412,2414,2417,2419,2421,2423,2425,2427,2429,2431,2434,2436,2438,2440,2442,2444,2446,2449],{"class":232,"line":2408},52,[230,2410,2411],{"class":240},"cost_naive ",[230,2413,433],{"class":236},[230,2415,2416],{"class":461}," sum",[230,2418,449],{"class":283},[230,2420,812],{"class":384},[230,2422,1075],{"class":283},[230,2424,526],{"class":384},[230,2426,408],{"class":283},[230,2428,1082],{"class":384},[230,2430,1085],{"class":283},[230,2432,2433],{"class":247}," for",[230,2435,1443],{"class":384},[230,2437,408],{"class":283},[230,2439,1019],{"class":384},[230,2441,1000],{"class":247},[230,2443,1453],{"class":461},[230,2445,449],{"class":283},[230,2447,2448],{"class":384},"naive",[230,2450,791],{"class":283},[230,2452,2454,2456],{"class":232,"line":2453},53,[230,2455,2335],{"class":384},[230,2457,569],{"class":283},[230,2459,2461,2464,2466,2468],{"class":232,"line":2460},54,[230,2462,2463],{"class":384},"    axes",[230,2465,1075],{"class":283},[230,2467,1550],{"class":404},[230,2469,1810],{"class":283},[230,2471,2473,2476],{"class":232,"line":2472},55,[230,2474,2475],{"class":384},"    labels_row",[230,2477,665],{"class":283},[230,2479,2481,2484],{"class":232,"line":2480},56,[230,2482,2483],{"class":384},"    labels_col",[230,2485,665],{"class":283},[230,2487,2489,2492,2494,2496],{"class":232,"line":2488},57,[230,2490,2491],{"class":651},"    matching",[230,2493,433],{"class":236},[230,2495,2448],{"class":384},[230,2497,665],{"class":283},[230,2499,2501,2504,2506,2508],{"class":232,"line":2500},58,[230,2502,2503],{"class":651},"    costs",[230,2505,433],{"class":236},[230,2507,812],{"class":384},[230,2509,665],{"class":283},[230,2511,2513,2516,2518,2521,2524,2526,2529,2531,2533,2536],{"class":232,"line":2512},59,[230,2514,2515],{"class":651},"    title",[230,2517,433],{"class":236},[230,2519,2520],{"class":1064},"f",[230,2522,2523],{"class":395},"\"Naïve assignment  (total = ",[230,2525,1070],{"class":404},[230,2527,2528],{"class":384},"cost_naive",[230,2530,1088],{"class":1064},[230,2532,1091],{"class":404},[230,2534,2535],{"class":395}," min)\"",[230,2537,665],{"class":283},[230,2539,2541],{"class":232,"line":2540},60,[230,2542,455],{"class":283},[230,2544,2546,2548,2550,2552],{"class":232,"line":2545},61,[230,2547,374],{"class":240},[230,2549,284],{"class":283},[230,2551,1243],{"class":384},[230,2553,1246],{"class":283},[230,2555,2557,2559,2561,2563],{"class":232,"line":2556},62,[230,2558,374],{"class":240},[230,2560,284],{"class":283},[230,2562,1256],{"class":384},[230,2564,1246],{"class":283},[185,2566,2567],{},[1262,2568],{"alt":226,"src":2569},"\u002F_nb\u002Ffeeca02a247f800b.png",[185,2571,2572],{},"The naïve assignment (each taxi goes to the passenger with the same index)\ngives a higher total cost than necessary.  Can we do better?",[509,2574,2576],{"id":2575},"_2-why-brute-force-does-not-scale","2  Why brute force does not scale",[185,2578,2579,2580,2583,2584,2586,2587,2590],{},"For ",[211,2581,2582],{},"n"," taxis and ",[211,2585,2582],{}," passengers there are ",[211,2588,2589],{},"n!"," (n-factorial) possible\nassignments.  For small problems we can check all of them; large problems defeat this approach.",[221,2592,2594],{"className":223,"code":2593,"language":225,"meta":226,"style":226},"def brute_force_lap(C):\n    \"\"\"Return the optimal assignment by checking every permutation.\"\"\"\n    n = C.shape[0]\n    best_cost, best_perm = float(\"inf\"), None\n    for perm in permutations(range(n)):\n        cost = sum(C[i, perm[i]] for i in range(n))\n        if cost \u003C best_cost:\n            best_cost, best_perm = cost, list(perm)\n    return best_perm, best_cost\n\n\nopt_perm, opt_cost = brute_force_lap(C)\nprint(f\"Optimal assignment : taxi {[i for i in range(3)]} → passenger {opt_perm}\")\nprint(f\"Optimal total cost : {opt_cost:.1f} min  (naïve was {cost_naive:.1f} min)\")\n",[211,2595,2596,2609,2622,2641,2672,2694,2737,2753,2779,2792,2796,2800,2820,2868],{"__ignoreMap":226},[230,2597,2598,2600,2603,2605,2607],{"class":232,"line":233},[230,2599,1282],{"class":1064},[230,2601,2602],{"class":1285}," brute_force_lap",[230,2604,449],{"class":283},[230,2606,812],{"class":1291},[230,2608,1010],{"class":283},[230,2610,2611,2615,2619],{"class":232,"line":244},[230,2612,2614],{"class":2613},"s2W-s","    \"\"\"",[230,2616,2618],{"class":2617},"sithA","Return the optimal assignment by checking every permutation.",[230,2620,2621],{"class":2613},"\"\"\"\n",[230,2623,2624,2626,2628,2630,2632,2635,2637,2639],{"class":232,"line":254},[230,2625,1338],{"class":240},[230,2627,433],{"class":236},[230,2629,1179],{"class":240},[230,2631,284],{"class":283},[230,2633,2634],{"class":287},"shape",[230,2636,1075],{"class":283},[230,2638,836],{"class":404},[230,2640,711],{"class":283},[230,2642,2643,2646,2648,2651,2653,2657,2659,2661,2664,2666,2669],{"class":232,"line":268},[230,2644,2645],{"class":240},"    best_cost",[230,2647,408],{"class":283},[230,2649,2650],{"class":240}," best_perm ",[230,2652,433],{"class":236},[230,2654,2656],{"class":2655},"sZMiF"," float",[230,2658,449],{"class":283},[230,2660,392],{"class":391},[230,2662,2663],{"class":395},"inf",[230,2665,392],{"class":391},[230,2667,2668],{"class":283},"),",[230,2670,2671],{"class":1311}," None\n",[230,2673,2674,2676,2679,2681,2684,2686,2688,2690,2692],{"class":232,"line":275},[230,2675,1016],{"class":247},[230,2677,2678],{"class":240}," perm ",[230,2680,1000],{"class":247},[230,2682,2683],{"class":384}," permutations",[230,2685,449],{"class":283},[230,2687,864],{"class":461},[230,2689,449],{"class":283},[230,2691,2582],{"class":384},[230,2693,1927],{"class":283},[230,2695,2696,2699,2701,2703,2705,2707,2709,2711,2713,2716,2718,2720,2723,2725,2727,2729,2731,2733,2735],{"class":232,"line":297},[230,2697,2698],{"class":240},"        cost ",[230,2700,433],{"class":236},[230,2702,2416],{"class":461},[230,2704,449],{"class":283},[230,2706,812],{"class":384},[230,2708,1075],{"class":283},[230,2710,526],{"class":384},[230,2712,408],{"class":283},[230,2714,2715],{"class":384}," perm",[230,2717,1075],{"class":283},[230,2719,526],{"class":384},[230,2721,2722],{"class":283},"]]",[230,2724,2433],{"class":247},[230,2726,997],{"class":384},[230,2728,1000],{"class":247},[230,2730,1003],{"class":461},[230,2732,449],{"class":283},[230,2734,2582],{"class":384},[230,2736,791],{"class":283},[230,2738,2739,2742,2745,2748,2751],{"class":232,"line":314},[230,2740,2741],{"class":247},"        if",[230,2743,2744],{"class":240}," cost ",[230,2746,2747],{"class":236},"\u003C",[230,2749,2750],{"class":240}," best_cost",[230,2752,1572],{"class":283},[230,2754,2755,2758,2760,2762,2764,2767,2769,2772,2774,2777],{"class":232,"line":328},[230,2756,2757],{"class":240},"            best_cost",[230,2759,408],{"class":283},[230,2761,2650],{"class":240},[230,2763,433],{"class":236},[230,2765,2766],{"class":240}," cost",[230,2768,408],{"class":283},[230,2770,2771],{"class":2655}," list",[230,2773,449],{"class":283},[230,2775,2776],{"class":384},"perm",[230,2778,455],{"class":283},[230,2780,2781,2784,2787,2789],{"class":232,"line":336},[230,2782,2783],{"class":247},"    return",[230,2785,2786],{"class":240}," best_perm",[230,2788,408],{"class":283},[230,2790,2791],{"class":240}," best_cost\n",[230,2793,2794],{"class":232,"line":344},[230,2795,272],{"emptyLinePlaceholder":271},[230,2797,2798],{"class":232,"line":366},[230,2799,272],{"emptyLinePlaceholder":271},[230,2801,2802,2805,2807,2810,2812,2814,2816,2818],{"class":232,"line":371},[230,2803,2804],{"class":240},"opt_perm",[230,2806,408],{"class":283},[230,2808,2809],{"class":240}," opt_cost ",[230,2811,433],{"class":236},[230,2813,2602],{"class":384},[230,2815,449],{"class":283},[230,2817,812],{"class":384},[230,2819,455],{"class":283},[230,2821,2822,2824,2826,2828,2831,2833,2835,2838,2840,2842,2844,2846,2848,2850,2853,2855,2858,2860,2862,2864,2866],{"class":232,"line":427},[230,2823,462],{"class":461},[230,2825,449],{"class":283},[230,2827,2520],{"class":1064},[230,2829,2830],{"class":395},"\"Optimal assignment : taxi ",[230,2832,1070],{"class":404},[230,2834,1075],{"class":283},[230,2836,2837],{"class":384},"i ",[230,2839,994],{"class":247},[230,2841,997],{"class":384},[230,2843,1000],{"class":247},[230,2845,1003],{"class":461},[230,2847,449],{"class":283},[230,2849,869],{"class":404},[230,2851,2852],{"class":283},")]",[230,2854,1091],{"class":404},[230,2856,2857],{"class":395}," → passenger ",[230,2859,1070],{"class":404},[230,2861,2804],{"class":384},[230,2863,1091],{"class":404},[230,2865,392],{"class":395},[230,2867,455],{"class":283},[230,2869,2870,2872,2874,2876,2879,2881,2884,2886,2888,2891,2893,2895,2897,2899,2901],{"class":232,"line":458},[230,2871,462],{"class":461},[230,2873,449],{"class":283},[230,2875,2520],{"class":1064},[230,2877,2878],{"class":395},"\"Optimal total cost : ",[230,2880,1070],{"class":404},[230,2882,2883],{"class":384},"opt_cost",[230,2885,1088],{"class":1064},[230,2887,1091],{"class":404},[230,2889,2890],{"class":395}," min  (naïve was ",[230,2892,1070],{"class":404},[230,2894,2528],{"class":384},[230,2896,1088],{"class":1064},[230,2898,1091],{"class":404},[230,2900,2535],{"class":395},[230,2902,455],{"class":283},[504,2904],{"data":2905,"kind":507},"T3B0aW1hbCBhc3NpZ25tZW50IDogdGF4aSBbMCwgMSwgMl0g4oaSIHBhc3NlbmdlciBbMSwgMCwgMl0KT3B0aW1hbCB0b3RhbCBjb3N0IDogNS4wIG1pbiAgKG5hw692ZSB3YXMgNi41IG1pbikK",[221,2907,2909],{"className":223,"code":2908,"language":225,"meta":226,"style":226},"# Show how n! explodes\nns = list(range(1, 16))\nfactorials = [math.factorial(n) for n in ns]\n\nfig, ax = plt.subplots(figsize=(7, 4))\nax.bar(ns, factorials, color=\"#4a90d9\", edgecolor=\"white\")\nax.set_yscale(\"log\")\nax.set_xlabel(\"Problem size n  (number of items per side)\")\nax.set_ylabel(\"Number of assignments to check  (log scale)\")\nax.set_title(\"Brute-force search grows as n!\")\nax.axhline(1e9, color=\"#E03520\", ls=\"--\", lw=1.5, label=\"10⁹  (≈ 1 second of CPU)\")\nax.axhline(1e18, color=\"#b08800\", ls=\"--\", lw=1.5, label=\"10¹⁸  (≈ 30 years of CPU)\")\nax.legend()\nfor i, (n, f) in enumerate(zip(ns, factorials)):\n    if n in (5, 10, 13):\n        ax.text(n, f * 2, f\"n={n}\\n{f:,}\", ha=\"center\", va=\"bottom\", fontsize=8)\nax.set_xticks(ns)\nplt.tight_layout()\nplt.show()\n\nprint(f\"n=10 → {math.factorial(10):,} permutations\")\nprint(f\"n=20 → {math.factorial(20):,} permutations  (infeasible)\")\n",[211,2910,2911,2916,2940,2975,2979,3011,3058,3078,3098,3118,3137,3201,3262,3273,3310,3334,3419,3433,3443,3453,3457,3491],{"__ignoreMap":226},[230,2912,2913],{"class":232,"line":233},[230,2914,2915],{"class":362},"# Show how n! explodes\n",[230,2917,2918,2921,2923,2925,2927,2929,2931,2933,2935,2938],{"class":232,"line":244},[230,2919,2920],{"class":240},"ns ",[230,2922,433],{"class":236},[230,2924,2771],{"class":2655},[230,2926,449],{"class":283},[230,2928,864],{"class":461},[230,2930,449],{"class":283},[230,2932,1550],{"class":404},[230,2934,408],{"class":283},[230,2936,2937],{"class":404}," 16",[230,2939,791],{"class":283},[230,2941,2942,2945,2947,2949,2952,2954,2957,2959,2961,2963,2965,2968,2970,2973],{"class":232,"line":254},[230,2943,2944],{"class":240},"factorials ",[230,2946,433],{"class":236},[230,2948,683],{"class":283},[230,2950,2951],{"class":240},"math",[230,2953,284],{"class":283},[230,2955,2956],{"class":384},"factorial",[230,2958,449],{"class":283},[230,2960,2582],{"class":384},[230,2962,1598],{"class":283},[230,2964,2433],{"class":247},[230,2966,2967],{"class":240}," n ",[230,2969,1000],{"class":247},[230,2971,2972],{"class":240}," ns",[230,2974,711],{"class":283},[230,2976,2977],{"class":232,"line":268},[230,2978,272],{"emptyLinePlaceholder":271},[230,2980,2981,2983,2985,2987,2989,2991,2993,2995,2997,2999,3001,3003,3005,3007,3009],{"class":232,"line":275},[230,2982,756],{"class":240},[230,2984,408],{"class":283},[230,2986,761],{"class":240},[230,2988,433],{"class":236},[230,2990,766],{"class":240},[230,2992,284],{"class":283},[230,2994,771],{"class":384},[230,2996,449],{"class":283},[230,2998,776],{"class":651},[230,3000,433],{"class":236},[230,3002,449],{"class":283},[230,3004,1687],{"class":404},[230,3006,408],{"class":283},[230,3008,2327],{"class":404},[230,3010,791],{"class":283},[230,3012,3013,3015,3017,3020,3022,3025,3027,3030,3032,3034,3036,3038,3041,3043,3045,3048,3050,3052,3054,3056],{"class":232,"line":297},[230,3014,854],{"class":240},[230,3016,284],{"class":283},[230,3018,3019],{"class":384},"bar",[230,3021,449],{"class":283},[230,3023,3024],{"class":384},"ns",[230,3026,408],{"class":283},[230,3028,3029],{"class":384}," factorials",[230,3031,408],{"class":283},[230,3033,1521],{"class":651},[230,3035,433],{"class":236},[230,3037,392],{"class":391},[230,3039,3040],{"class":395},"#4a90d9",[230,3042,392],{"class":391},[230,3044,408],{"class":283},[230,3046,3047],{"class":651}," edgecolor",[230,3049,433],{"class":236},[230,3051,392],{"class":391},[230,3053,1171],{"class":395},[230,3055,392],{"class":391},[230,3057,455],{"class":283},[230,3059,3060,3062,3064,3067,3069,3071,3074,3076],{"class":232,"line":314},[230,3061,854],{"class":240},[230,3063,284],{"class":283},[230,3065,3066],{"class":384},"set_yscale",[230,3068,449],{"class":283},[230,3070,392],{"class":391},[230,3072,3073],{"class":395},"log",[230,3075,392],{"class":391},[230,3077,455],{"class":283},[230,3079,3080,3082,3084,3087,3089,3091,3094,3096],{"class":232,"line":328},[230,3081,854],{"class":240},[230,3083,284],{"class":283},[230,3085,3086],{"class":384},"set_xlabel",[230,3088,449],{"class":283},[230,3090,392],{"class":391},[230,3092,3093],{"class":395},"Problem size n  (number of items per side)",[230,3095,392],{"class":391},[230,3097,455],{"class":283},[230,3099,3100,3102,3104,3107,3109,3111,3114,3116],{"class":232,"line":336},[230,3101,854],{"class":240},[230,3103,284],{"class":283},[230,3105,3106],{"class":384},"set_ylabel",[230,3108,449],{"class":283},[230,3110,392],{"class":391},[230,3112,3113],{"class":395},"Number of assignments to check  (log scale)",[230,3115,392],{"class":391},[230,3117,455],{"class":283},[230,3119,3120,3122,3124,3126,3128,3130,3133,3135],{"class":232,"line":344},[230,3121,854],{"class":240},[230,3123,284],{"class":283},[230,3125,1222],{"class":384},[230,3127,449],{"class":283},[230,3129,392],{"class":391},[230,3131,3132],{"class":395},"Brute-force search grows as n!",[230,3134,392],{"class":391},[230,3136,455],{"class":283},[230,3138,3139,3141,3143,3146,3148,3151,3153,3155,3157,3159,3161,3163,3165,3168,3170,3172,3175,3177,3179,3181,3183,3186,3188,3190,3192,3194,3197,3199],{"class":232,"line":366},[230,3140,854],{"class":240},[230,3142,284],{"class":283},[230,3144,3145],{"class":384},"axhline",[230,3147,449],{"class":283},[230,3149,3150],{"class":404},"1e9",[230,3152,408],{"class":283},[230,3154,1521],{"class":651},[230,3156,433],{"class":236},[230,3158,392],{"class":391},[230,3160,1844],{"class":395},[230,3162,392],{"class":391},[230,3164,408],{"class":283},[230,3166,3167],{"class":651}," ls",[230,3169,433],{"class":236},[230,3171,392],{"class":391},[230,3173,3174],{"class":395},"--",[230,3176,392],{"class":391},[230,3178,408],{"class":283},[230,3180,1535],{"class":651},[230,3182,433],{"class":236},[230,3184,3185],{"class":404},"1.5",[230,3187,408],{"class":283},[230,3189,977],{"class":651},[230,3191,433],{"class":236},[230,3193,392],{"class":391},[230,3195,3196],{"class":395},"10⁹  (≈ 1 second of CPU)",[230,3198,392],{"class":391},[230,3200,455],{"class":283},[230,3202,3203,3205,3207,3209,3211,3214,3216,3218,3220,3222,3225,3227,3229,3231,3233,3235,3237,3239,3241,3243,3245,3247,3249,3251,3253,3255,3258,3260],{"class":232,"line":371},[230,3204,854],{"class":240},[230,3206,284],{"class":283},[230,3208,3145],{"class":384},[230,3210,449],{"class":283},[230,3212,3213],{"class":404},"1e18",[230,3215,408],{"class":283},[230,3217,1521],{"class":651},[230,3219,433],{"class":236},[230,3221,392],{"class":391},[230,3223,3224],{"class":395},"#b08800",[230,3226,392],{"class":391},[230,3228,408],{"class":283},[230,3230,3167],{"class":651},[230,3232,433],{"class":236},[230,3234,392],{"class":391},[230,3236,3174],{"class":395},[230,3238,392],{"class":391},[230,3240,408],{"class":283},[230,3242,1535],{"class":651},[230,3244,433],{"class":236},[230,3246,3185],{"class":404},[230,3248,408],{"class":283},[230,3250,977],{"class":651},[230,3252,433],{"class":236},[230,3254,392],{"class":391},[230,3256,3257],{"class":395},"10¹⁸  (≈ 30 years of CPU)",[230,3259,392],{"class":391},[230,3261,455],{"class":283},[230,3263,3264,3266,3268,3271],{"class":232,"line":427},[230,3265,854],{"class":240},[230,3267,284],{"class":283},[230,3269,3270],{"class":384},"legend",[230,3272,1246],{"class":283},[230,3274,3275,3277,3279,3281,3283,3285,3287,3290,3292,3294,3296,3298,3300,3302,3304,3306,3308],{"class":232,"line":458},[230,3276,994],{"class":247},[230,3278,1443],{"class":240},[230,3280,408],{"class":283},[230,3282,1587],{"class":283},[230,3284,2582],{"class":240},[230,3286,408],{"class":283},[230,3288,3289],{"class":240}," f",[230,3291,1598],{"class":283},[230,3293,1909],{"class":247},[230,3295,1453],{"class":461},[230,3297,449],{"class":283},[230,3299,1916],{"class":461},[230,3301,449],{"class":283},[230,3303,3024],{"class":384},[230,3305,408],{"class":283},[230,3307,3029],{"class":384},[230,3309,1927],{"class":283},[230,3311,3312,3314,3316,3318,3320,3322,3324,3327,3329,3332],{"class":232,"line":794},[230,3313,1754],{"class":247},[230,3315,2967],{"class":240},[230,3317,1000],{"class":236},[230,3319,1587],{"class":283},[230,3321,783],{"class":404},[230,3323,408],{"class":283},[230,3325,3326],{"class":404}," 10",[230,3328,408],{"class":283},[230,3330,3331],{"class":404}," 13",[230,3333,1010],{"class":283},[230,3335,3336,3338,3340,3342,3344,3346,3348,3351,3354,3356,3358,3360,3363,3365,3367,3369,3372,3374,3376,3379,3381,3383,3385,3387,3389,3391,3393,3395,3397,3399,3401,3403,3406,3408,3410,3412,3414,3417],{"class":232,"line":851},[230,3337,1035],{"class":240},[230,3339,284],{"class":283},[230,3341,1040],{"class":384},[230,3343,449],{"class":283},[230,3345,2582],{"class":384},[230,3347,408],{"class":283},[230,3349,3350],{"class":384}," f ",[230,3352,3353],{"class":236},"*",[230,3355,1604],{"class":404},[230,3357,408],{"class":283},[230,3359,3289],{"class":1064},[230,3361,3362],{"class":395},"\"n=",[230,3364,1070],{"class":404},[230,3366,2582],{"class":384},[230,3368,1091],{"class":404},[230,3370,3371],{"class":481},"\\n",[230,3373,1070],{"class":404},[230,3375,2520],{"class":384},[230,3377,3378],{"class":1064},":,",[230,3380,1091],{"class":404},[230,3382,392],{"class":395},[230,3384,408],{"class":283},[230,3386,921],{"class":651},[230,3388,433],{"class":236},[230,3390,392],{"class":391},[230,3392,1108],{"class":395},[230,3394,392],{"class":391},[230,3396,408],{"class":283},[230,3398,2023],{"class":651},[230,3400,433],{"class":236},[230,3402,392],{"class":391},[230,3404,3405],{"class":395},"bottom",[230,3407,392],{"class":391},[230,3409,408],{"class":283},[230,3411,2036],{"class":651},[230,3413,433],{"class":236},[230,3415,3416],{"class":404},"8",[230,3418,455],{"class":283},[230,3420,3421,3423,3425,3427,3429,3431],{"class":232,"line":874},[230,3422,854],{"class":240},[230,3424,284],{"class":283},[230,3426,859],{"class":384},[230,3428,449],{"class":283},[230,3430,3024],{"class":384},[230,3432,455],{"class":283},[230,3434,3435,3437,3439,3441],{"class":232,"line":894},[230,3436,374],{"class":240},[230,3438,284],{"class":283},[230,3440,1243],{"class":384},[230,3442,1246],{"class":283},[230,3444,3445,3447,3449,3451],{"class":232,"line":935},[230,3446,374],{"class":240},[230,3448,284],{"class":283},[230,3450,1256],{"class":384},[230,3452,1246],{"class":283},[230,3454,3455],{"class":232,"line":952},[230,3456,272],{"emptyLinePlaceholder":271},[230,3458,3459,3461,3463,3465,3468,3470,3472,3474,3476,3478,3480,3482,3484,3486,3489],{"class":232,"line":991},[230,3460,462],{"class":461},[230,3462,449],{"class":283},[230,3464,2520],{"class":1064},[230,3466,3467],{"class":395},"\"n=10 → ",[230,3469,1070],{"class":404},[230,3471,2951],{"class":384},[230,3473,284],{"class":283},[230,3475,2956],{"class":384},[230,3477,449],{"class":283},[230,3479,2041],{"class":404},[230,3481,1598],{"class":283},[230,3483,3378],{"class":1064},[230,3485,1091],{"class":404},[230,3487,3488],{"class":395}," permutations\"",[230,3490,455],{"class":283},[230,3492,3493,3495,3497,3499,3502,3504,3506,3508,3510,3512,3514,3516,3518,3520,3523],{"class":232,"line":1013},[230,3494,462],{"class":461},[230,3496,449],{"class":283},[230,3498,2520],{"class":1064},[230,3500,3501],{"class":395},"\"n=20 → ",[230,3503,1070],{"class":404},[230,3505,2951],{"class":384},[230,3507,284],{"class":283},[230,3509,2956],{"class":384},[230,3511,449],{"class":283},[230,3513,916],{"class":404},[230,3515,1598],{"class":283},[230,3517,3378],{"class":1064},[230,3519,1091],{"class":404},[230,3521,3522],{"class":395}," permutations  (infeasible)\"",[230,3524,455],{"class":283},[185,3526,3527],{},[1262,3528],{"alt":226,"src":3529},"\u002F_nb\u002F2287202b12e4eed7.png",[504,3531],{"data":3532,"kind":507},"bj0xMCDihpIgMyw2MjgsODAwIHBlcm11dGF0aW9ucwpuPTIwIOKGkiAyLDQzMiw5MDIsMDA4LDE3Niw2NDAsMDAwIHBlcm11dGF0aW9ucyAgKGluZmVhc2libGUpCg==",[185,3534,3535,3536,3539],{},"Efficient algorithms (like the Hungarian method or Jonker-Volgenant) solve\nthe LAP in ",[188,3537,3538],{},"O(n³)"," time — many orders of magnitude faster than brute force.",[3541,3542,3543,3557],"table",{},[3544,3545,3546],"thead",{},[3547,3548,3549,3552,3555],"tr",{},[3550,3551,2582],"th",{},[3550,3553,3554],{},"Brute force",[3550,3556,3538],{},[3558,3559,3560,3571,3582],"tbody",{},[3547,3561,3562,3565,3568],{},[3563,3564,2041],"td",{},[3563,3566,3567],{},"3.6 million",[3563,3569,3570],{},"1 000",[3547,3572,3573,3576,3579],{},[3563,3574,3575],{},"100",[3563,3577,3578],{},"~10¹⁵⁷",[3563,3580,3581],{},"10⁶",[3547,3583,3584,3587,3590],{},[3563,3585,3586],{},"1000",[3563,3588,3589],{},"∞",[3563,3591,3592],{},"10⁹",[509,3594,3596],{"id":3595},"_3-solving-with-torchmatch","3  Solving with torchmatch",[185,3598,3599,3601,3602,3605,3606,3608,3609,284],{},[211,3600,213],{}," takes a 2-D (or 3-D batched) cost tensor and\nreturns an integer tensor of length ",[211,3603,3604],{},"n_rows",": element ",[211,3607,526],{}," is the column\nassigned to row ",[211,3610,526],{},[221,3612,3614],{"className":223,"code":3613,"language":225,"meta":226,"style":226},"cost_t = torch.tensor(C)\n\nrow_to_col = torchmatch.assignment.solve(cost_t)\nprint(\"row_to_col :\", row_to_col.tolist())\nprint(\"Optimal assignment:\")\nfor taxi, passenger in enumerate(row_to_col.tolist()):\n    print(f\"  taxi {taxi}  →  passenger {passenger}  (cost {C[taxi, passenger]:.1f})\")\ntotal = cost_t[torch.arange(3), row_to_col].sum().item()\nprint(f\"Total cost: {total:.1f}\")\n",[211,3615,3616,3636,3640,3666,3692,3707,3735,3791,3833],{"__ignoreMap":226},[230,3617,3618,3621,3623,3625,3627,3630,3632,3634],{"class":232,"line":233},[230,3619,3620],{"class":240},"cost_t ",[230,3622,433],{"class":236},[230,3624,496],{"class":240},[230,3626,284],{"class":283},[230,3628,3629],{"class":384},"tensor",[230,3631,449],{"class":283},[230,3633,812],{"class":384},[230,3635,455],{"class":283},[230,3637,3638],{"class":232,"line":244},[230,3639,272],{"emptyLinePlaceholder":271},[230,3641,3642,3645,3647,3649,3651,3654,3656,3659,3661,3664],{"class":232,"line":254},[230,3643,3644],{"class":240},"row_to_col ",[230,3646,433],{"class":236},[230,3648,476],{"class":240},[230,3650,284],{"class":283},[230,3652,3653],{"class":287},"assignment",[230,3655,284],{"class":283},[230,3657,3658],{"class":384},"solve",[230,3660,449],{"class":283},[230,3662,3663],{"class":384},"cost_t",[230,3665,455],{"class":283},[230,3667,3668,3670,3672,3674,3677,3679,3681,3684,3686,3689],{"class":232,"line":268},[230,3669,462],{"class":461},[230,3671,449],{"class":283},[230,3673,392],{"class":391},[230,3675,3676],{"class":395},"row_to_col :",[230,3678,392],{"class":391},[230,3680,408],{"class":283},[230,3682,3683],{"class":384}," row_to_col",[230,3685,284],{"class":283},[230,3687,3688],{"class":384},"tolist",[230,3690,3691],{"class":283},"())\n",[230,3693,3694,3696,3698,3700,3703,3705],{"class":232,"line":275},[230,3695,462],{"class":461},[230,3697,449],{"class":283},[230,3699,392],{"class":391},[230,3701,3702],{"class":395},"Optimal assignment:",[230,3704,392],{"class":391},[230,3706,455],{"class":283},[230,3708,3709,3711,3714,3716,3719,3721,3723,3725,3728,3730,3732],{"class":232,"line":297},[230,3710,994],{"class":247},[230,3712,3713],{"class":240}," taxi",[230,3715,408],{"class":283},[230,3717,3718],{"class":240}," passenger ",[230,3720,1000],{"class":247},[230,3722,1453],{"class":461},[230,3724,449],{"class":283},[230,3726,3727],{"class":384},"row_to_col",[230,3729,284],{"class":283},[230,3731,3688],{"class":384},[230,3733,3734],{"class":283},"()):\n",[230,3736,3737,3740,3742,3744,3747,3749,3752,3754,3757,3759,3762,3764,3767,3769,3771,3773,3775,3777,3780,3782,3784,3786,3789],{"class":232,"line":314},[230,3738,3739],{"class":461},"    print",[230,3741,449],{"class":283},[230,3743,2520],{"class":1064},[230,3745,3746],{"class":395},"\"  taxi ",[230,3748,1070],{"class":404},[230,3750,3751],{"class":384},"taxi",[230,3753,1091],{"class":404},[230,3755,3756],{"class":395},"  →  passenger ",[230,3758,1070],{"class":404},[230,3760,3761],{"class":384},"passenger",[230,3763,1091],{"class":404},[230,3765,3766],{"class":395},"  (cost ",[230,3768,1070],{"class":404},[230,3770,812],{"class":384},[230,3772,1075],{"class":283},[230,3774,3751],{"class":384},[230,3776,408],{"class":283},[230,3778,3779],{"class":384}," passenger",[230,3781,1085],{"class":283},[230,3783,1088],{"class":1064},[230,3785,1091],{"class":404},[230,3787,3788],{"class":395},")\"",[230,3790,455],{"class":283},[230,3792,3793,3796,3798,3801,3803,3806,3808,3811,3813,3815,3817,3819,3822,3825,3828,3831],{"class":232,"line":328},[230,3794,3795],{"class":240},"total ",[230,3797,433],{"class":236},[230,3799,3800],{"class":240}," cost_t",[230,3802,1075],{"class":283},[230,3804,3805],{"class":240},"torch",[230,3807,284],{"class":283},[230,3809,3810],{"class":384},"arange",[230,3812,449],{"class":283},[230,3814,869],{"class":404},[230,3816,2668],{"class":283},[230,3818,3683],{"class":240},[230,3820,3821],{"class":283},"].",[230,3823,3824],{"class":384},"sum",[230,3826,3827],{"class":283},"().",[230,3829,3830],{"class":384},"item",[230,3832,1246],{"class":283},[230,3834,3835,3837,3839,3841,3844,3846,3848,3850,3852,3854],{"class":232,"line":336},[230,3836,462],{"class":461},[230,3838,449],{"class":283},[230,3840,2520],{"class":1064},[230,3842,3843],{"class":395},"\"Total cost: ",[230,3845,1070],{"class":404},[230,3847,534],{"class":384},[230,3849,1088],{"class":1064},[230,3851,1091],{"class":404},[230,3853,392],{"class":395},[230,3855,455],{"class":283},[504,3857],{"data":3858,"kind":507},"cm93X3RvX2NvbCA6IFsxLCAwLCAyXQpPcHRpbWFsIGFzc2lnbm1lbnQ6CiAgdGF4aSAwICDihpIgIHBhc3NlbmdlciAxICAoY29zdCAxLjApCiAgdGF4aSAxICDihpIgIHBhc3NlbmdlciAwICAoY29zdCAyLjApCiAgdGF4aSAyICDihpIgIHBhc3NlbmdlciAyICAoY29zdCAyLjApClRvdGFsIGNvc3Q6IDUuMAo=",[221,3860,3862],{"className":223,"code":3861,"language":225,"meta":226,"style":226},"# Visualise the optimal matching\nfig, ax = plt.subplots(figsize=(5.5, 4))\ndraw_bipartite(\n    ax,\n    labels_row,\n    labels_col,\n    matching=row_to_col.tolist(),\n    costs=C,\n    title=f\"Optimal assignment  (total = {total:.1f} min)\",\n)\nplt.tight_layout()\nplt.show()\n",[211,3863,3864,3869,3902,3908,3914,3920,3926,3941,3951,3974,3978,3988],{"__ignoreMap":226},[230,3865,3866],{"class":232,"line":233},[230,3867,3868],{"class":362},"# Visualise the optimal matching\n",[230,3870,3871,3873,3875,3877,3879,3881,3883,3885,3887,3889,3891,3893,3896,3898,3900],{"class":232,"line":244},[230,3872,756],{"class":240},[230,3874,408],{"class":283},[230,3876,761],{"class":240},[230,3878,433],{"class":236},[230,3880,766],{"class":240},[230,3882,284],{"class":283},[230,3884,771],{"class":384},[230,3886,449],{"class":283},[230,3888,776],{"class":651},[230,3890,433],{"class":236},[230,3892,449],{"class":283},[230,3894,3895],{"class":404},"5.5",[230,3897,408],{"class":283},[230,3899,2327],{"class":404},[230,3901,791],{"class":283},[230,3903,3904,3906],{"class":232,"line":254},[230,3905,2335],{"class":384},[230,3907,569],{"class":283},[230,3909,3910,3912],{"class":232,"line":268},[230,3911,2201],{"class":384},[230,3913,665],{"class":283},[230,3915,3916,3918],{"class":232,"line":275},[230,3917,2475],{"class":384},[230,3919,665],{"class":283},[230,3921,3922,3924],{"class":232,"line":297},[230,3923,2483],{"class":384},[230,3925,665],{"class":283},[230,3927,3928,3930,3932,3934,3936,3938],{"class":232,"line":314},[230,3929,2491],{"class":651},[230,3931,433],{"class":236},[230,3933,3727],{"class":384},[230,3935,284],{"class":283},[230,3937,3688],{"class":384},[230,3939,3940],{"class":283},"(),\n",[230,3942,3943,3945,3947,3949],{"class":232,"line":328},[230,3944,2503],{"class":651},[230,3946,433],{"class":236},[230,3948,812],{"class":384},[230,3950,665],{"class":283},[230,3952,3953,3955,3957,3959,3962,3964,3966,3968,3970,3972],{"class":232,"line":336},[230,3954,2515],{"class":651},[230,3956,433],{"class":236},[230,3958,2520],{"class":1064},[230,3960,3961],{"class":395},"\"Optimal assignment  (total = ",[230,3963,1070],{"class":404},[230,3965,534],{"class":384},[230,3967,1088],{"class":1064},[230,3969,1091],{"class":404},[230,3971,2535],{"class":395},[230,3973,665],{"class":283},[230,3975,3976],{"class":232,"line":344},[230,3977,455],{"class":283},[230,3979,3980,3982,3984,3986],{"class":232,"line":366},[230,3981,374],{"class":240},[230,3983,284],{"class":283},[230,3985,1243],{"class":384},[230,3987,1246],{"class":283},[230,3989,3990,3992,3994,3996],{"class":232,"line":371},[230,3991,374],{"class":240},[230,3993,284],{"class":283},[230,3995,1256],{"class":384},[230,3997,1246],{"class":283},[185,3999,4000],{},[1262,4001],{"alt":226,"src":4002},"\u002F_nb\u002F6748bfaa6f508b69.png",[509,4004,4006],{"id":4005},"_4-rectangular-problems-and-forbidden-edges","4  Rectangular problems and forbidden edges",[185,4008,4009,4010,4013,4014,4017],{},"Real problems are often ",[188,4011,4012],{},"rectangular"," (more items on one side than the\nother) or have ",[188,4015,4016],{},"forbidden pairs"," (some assignments are infeasible).\ntorchmatch handles both.",[221,4019,4021],{"className":223,"code":4020,"language":225,"meta":226,"style":226},"# More taxis than passengers — some taxis stay idle (get assigned -1)\nC_rect = torch.tensor(\n    [\n        [4.0, 1.0],\n        [2.0, 0.5],\n        [3.0, 2.0],\n        [1.5, 3.5],  # extra taxi\n    ],\n    dtype=torch.float32,\n)\n\nresult = torchmatch.assignment.solve(C_rect)\nprint(\"Rectangular (4 taxis, 2 passengers):\", result.tolist())\nprint(\" -1 means the taxi is unassigned\")\n\n# Forbidden edges: set to +inf\nC_gated = torch.tensor(\n    [\n        [4.0, float(\"inf\"), 3.0],  # taxi 0 cannot reach passenger 1\n        [float(\"inf\"), 0.5, 5.0],  # taxi 1 cannot reach passenger 0\n        [3.0, 2.0, float(\"inf\")],  # taxi 2 cannot reach passenger 2\n    ],\n    dtype=torch.float32,\n)\n\nresult_gated = torchmatch.assignment.solve(C_gated)\nprint(\"\\nWith forbidden edges (+inf):\", result_gated.tolist())\ntotal_gated = sum(\n    C_gated[i, j].item()\n    for i, j in enumerate(result_gated.tolist())\n    if j >= 0 and C_gated[i, j] != float(\"inf\")\n)\nprint(f\"Total feasible cost: {total_gated:.1f}\")\n",[211,4022,4023,4028,4043,4047,4059,4071,4083,4099,4103,4117,4121,4125,4149,4173,4188,4192,4197,4212,4216,4243,4271,4299,4303,4317,4321,4325,4349,4375,4386,4405,4430,4473,4477],{"__ignoreMap":226},[230,4024,4025],{"class":232,"line":233},[230,4026,4027],{"class":362},"# More taxis than passengers — some taxis stay idle (get assigned -1)\n",[230,4029,4030,4033,4035,4037,4039,4041],{"class":232,"line":244},[230,4031,4032],{"class":240},"C_rect ",[230,4034,433],{"class":236},[230,4036,496],{"class":240},[230,4038,284],{"class":283},[230,4040,3629],{"class":384},[230,4042,569],{"class":283},[230,4044,4045],{"class":232,"line":254},[230,4046,574],{"class":283},[230,4048,4049,4051,4053,4055,4057],{"class":232,"line":268},[230,4050,579],{"class":283},[230,4052,582],{"class":404},[230,4054,408],{"class":283},[230,4056,587],{"class":404},[230,4058,1810],{"class":283},[230,4060,4061,4063,4065,4067,4069],{"class":232,"line":275},[230,4062,579],{"class":283},[230,4064,605],{"class":404},[230,4066,408],{"class":283},[230,4068,610],{"class":404},[230,4070,1810],{"class":283},[230,4072,4073,4075,4077,4079,4081],{"class":232,"line":297},[230,4074,579],{"class":283},[230,4076,627],{"class":404},[230,4078,408],{"class":283},[230,4080,632],{"class":404},[230,4082,1810],{"class":283},[230,4084,4085,4087,4089,4091,4094,4096],{"class":232,"line":314},[230,4086,579],{"class":283},[230,4088,3185],{"class":404},[230,4090,408],{"class":283},[230,4092,4093],{"class":404}," 3.5",[230,4095,595],{"class":283},[230,4097,4098],{"class":362},"  # extra taxi\n",[230,4100,4101],{"class":232,"line":328},[230,4102,646],{"class":283},[230,4104,4105,4107,4109,4111,4113,4115],{"class":232,"line":336},[230,4106,652],{"class":651},[230,4108,433],{"class":236},[230,4110,3805],{"class":384},[230,4112,284],{"class":283},[230,4114,662],{"class":287},[230,4116,665],{"class":283},[230,4118,4119],{"class":232,"line":344},[230,4120,455],{"class":283},[230,4122,4123],{"class":232,"line":366},[230,4124,272],{"emptyLinePlaceholder":271},[230,4126,4127,4130,4132,4134,4136,4138,4140,4142,4144,4147],{"class":232,"line":371},[230,4128,4129],{"class":240},"result ",[230,4131,433],{"class":236},[230,4133,476],{"class":240},[230,4135,284],{"class":283},[230,4137,3653],{"class":287},[230,4139,284],{"class":283},[230,4141,3658],{"class":384},[230,4143,449],{"class":283},[230,4145,4146],{"class":384},"C_rect",[230,4148,455],{"class":283},[230,4150,4151,4153,4155,4157,4160,4162,4164,4167,4169,4171],{"class":232,"line":427},[230,4152,462],{"class":461},[230,4154,449],{"class":283},[230,4156,392],{"class":391},[230,4158,4159],{"class":395},"Rectangular (4 taxis, 2 passengers):",[230,4161,392],{"class":391},[230,4163,408],{"class":283},[230,4165,4166],{"class":384}," result",[230,4168,284],{"class":283},[230,4170,3688],{"class":384},[230,4172,3691],{"class":283},[230,4174,4175,4177,4179,4181,4184,4186],{"class":232,"line":458},[230,4176,462],{"class":461},[230,4178,449],{"class":283},[230,4180,392],{"class":391},[230,4182,4183],{"class":395}," -1 means the taxi is unassigned",[230,4185,392],{"class":391},[230,4187,455],{"class":283},[230,4189,4190],{"class":232,"line":794},[230,4191,272],{"emptyLinePlaceholder":271},[230,4193,4194],{"class":232,"line":851},[230,4195,4196],{"class":362},"# Forbidden edges: set to +inf\n",[230,4198,4199,4202,4204,4206,4208,4210],{"class":232,"line":874},[230,4200,4201],{"class":240},"C_gated ",[230,4203,433],{"class":236},[230,4205,496],{"class":240},[230,4207,284],{"class":283},[230,4209,3629],{"class":384},[230,4211,569],{"class":283},[230,4213,4214],{"class":232,"line":894},[230,4215,574],{"class":283},[230,4217,4218,4220,4222,4224,4226,4228,4230,4232,4234,4236,4238,4240],{"class":232,"line":935},[230,4219,579],{"class":283},[230,4221,582],{"class":404},[230,4223,408],{"class":283},[230,4225,2656],{"class":2655},[230,4227,449],{"class":283},[230,4229,392],{"class":391},[230,4231,2663],{"class":395},[230,4233,392],{"class":391},[230,4235,2668],{"class":283},[230,4237,592],{"class":404},[230,4239,595],{"class":283},[230,4241,4242],{"class":362},"  # taxi 0 cannot reach passenger 1\n",[230,4244,4245,4247,4250,4252,4254,4256,4258,4260,4262,4264,4266,4268],{"class":232,"line":952},[230,4246,579],{"class":283},[230,4248,4249],{"class":2655},"float",[230,4251,449],{"class":283},[230,4253,392],{"class":391},[230,4255,2663],{"class":395},[230,4257,392],{"class":391},[230,4259,2668],{"class":283},[230,4261,610],{"class":404},[230,4263,408],{"class":283},[230,4265,615],{"class":404},[230,4267,595],{"class":283},[230,4269,4270],{"class":362},"  # taxi 1 cannot reach passenger 0\n",[230,4272,4273,4275,4277,4279,4281,4283,4285,4287,4289,4291,4293,4296],{"class":232,"line":991},[230,4274,579],{"class":283},[230,4276,627],{"class":404},[230,4278,408],{"class":283},[230,4280,632],{"class":404},[230,4282,408],{"class":283},[230,4284,2656],{"class":2655},[230,4286,449],{"class":283},[230,4288,392],{"class":391},[230,4290,2663],{"class":395},[230,4292,392],{"class":391},[230,4294,4295],{"class":283},")],",[230,4297,4298],{"class":362},"  # taxi 2 cannot reach passenger 2\n",[230,4300,4301],{"class":232,"line":1013},[230,4302,646],{"class":283},[230,4304,4305,4307,4309,4311,4313,4315],{"class":232,"line":1032},[230,4306,652],{"class":651},[230,4308,433],{"class":236},[230,4310,3805],{"class":384},[230,4312,284],{"class":283},[230,4314,662],{"class":287},[230,4316,665],{"class":283},[230,4318,4319],{"class":232,"line":1045},[230,4320,455],{"class":283},[230,4322,4323],{"class":232,"line":1053},[230,4324,272],{"emptyLinePlaceholder":271},[230,4326,4327,4330,4332,4334,4336,4338,4340,4342,4344,4347],{"class":232,"line":1061},[230,4328,4329],{"class":240},"result_gated ",[230,4331,433],{"class":236},[230,4333,476],{"class":240},[230,4335,284],{"class":283},[230,4337,3653],{"class":287},[230,4339,284],{"class":283},[230,4341,3658],{"class":384},[230,4343,449],{"class":283},[230,4345,4346],{"class":384},"C_gated",[230,4348,455],{"class":283},[230,4350,4351,4353,4355,4357,4359,4362,4364,4366,4369,4371,4373],{"class":232,"line":1098},[230,4352,462],{"class":461},[230,4354,449],{"class":283},[230,4356,392],{"class":391},[230,4358,3371],{"class":481},[230,4360,4361],{"class":395},"With forbidden edges (+inf):",[230,4363,392],{"class":391},[230,4365,408],{"class":283},[230,4367,4368],{"class":384}," result_gated",[230,4370,284],{"class":283},[230,4372,3688],{"class":384},[230,4374,3691],{"class":283},[230,4376,4377,4380,4382,4384],{"class":232,"line":1115},[230,4378,4379],{"class":240},"total_gated ",[230,4381,433],{"class":236},[230,4383,2416],{"class":461},[230,4385,569],{"class":283},[230,4387,4388,4391,4393,4395,4397,4399,4401,4403],{"class":232,"line":1131},[230,4389,4390],{"class":384},"    C_gated",[230,4392,1075],{"class":283},[230,4394,526],{"class":384},[230,4396,408],{"class":283},[230,4398,1082],{"class":384},[230,4400,3821],{"class":283},[230,4402,3830],{"class":384},[230,4404,1246],{"class":283},[230,4406,4407,4409,4411,4413,4415,4417,4419,4421,4424,4426,4428],{"class":232,"line":1144},[230,4408,1016],{"class":247},[230,4410,1443],{"class":384},[230,4412,408],{"class":283},[230,4414,1019],{"class":384},[230,4416,1000],{"class":247},[230,4418,1453],{"class":461},[230,4420,449],{"class":283},[230,4422,4423],{"class":384},"result_gated",[230,4425,284],{"class":283},[230,4427,3688],{"class":384},[230,4429,3691],{"class":283},[230,4431,4432,4434,4436,4439,4442,4445,4448,4450,4452,4454,4456,4458,4461,4463,4465,4467,4469,4471],{"class":232,"line":1161},[230,4433,1754],{"class":247},[230,4435,1019],{"class":384},[230,4437,4438],{"class":236},">=",[230,4440,4441],{"class":404}," 0",[230,4443,4444],{"class":247}," and",[230,4446,4447],{"class":384}," C_gated",[230,4449,1075],{"class":283},[230,4451,526],{"class":384},[230,4453,408],{"class":283},[230,4455,1082],{"class":384},[230,4457,1085],{"class":283},[230,4459,4460],{"class":236}," !=",[230,4462,2656],{"class":2655},[230,4464,449],{"class":283},[230,4466,392],{"class":391},[230,4468,2663],{"class":395},[230,4470,392],{"class":391},[230,4472,455],{"class":283},[230,4474,4475],{"class":232,"line":1209},[230,4476,455],{"class":283},[230,4478,4479,4481,4483,4485,4488,4490,4493,4495,4497,4499],{"class":232,"line":1215},[230,4480,462],{"class":461},[230,4482,449],{"class":283},[230,4484,2520],{"class":1064},[230,4486,4487],{"class":395},"\"Total feasible cost: ",[230,4489,1070],{"class":404},[230,4491,4492],{"class":384},"total_gated",[230,4494,1088],{"class":1064},[230,4496,1091],{"class":404},[230,4498,392],{"class":395},[230,4500,455],{"class":283},[504,4502],{"data":4503,"kind":507},"UmVjdGFuZ3VsYXIgKDQgdGF4aXMsIDIgcGFzc2VuZ2Vycyk6IFstMSwgMSwgLTEsIDBdCiAtMSBtZWFucyB0aGUgdGF4aSBpcyB1bmFzc2lnbmVkCgpXaXRoIGZvcmJpZGRlbiBlZGdlcyAoK2luZik6IFsyLCAxLCAwXQpUb3RhbCBmZWFzaWJsZSBjb3N0OiA2LjUK",[509,4505,4507],{"id":4506},"_5-comparing-to-scipy","5  Comparing to scipy",[185,4509,4510],{},"torchmatch produces the same optimal assignments as SciPy's reference\nsolver, but stays inside the PyTorch ecosystem (no NumPy round-trip),\nsupports batching, and runs on GPU.",[221,4512,4514],{"className":223,"code":4513,"language":225,"meta":226,"style":226},"# Verify correctness against scipy\nscipy_rows, scipy_cols = linear_sum_assignment(C)\nscipy_assignment = scipy_cols.tolist()\ntm_assignment = torchmatch.assignment.solve(torch.tensor(C)).tolist()\n\nprint(\"scipy assignment :\", scipy_assignment)\nprint(\"torchmatch       :\", tm_assignment)\nassert scipy_assignment == tm_assignment, \"Mismatch!\"\nprint(\"✓ Results match\")\n",[211,4515,4516,4521,4542,4558,4594,4598,4618,4638,4661],{"__ignoreMap":226},[230,4517,4518],{"class":232,"line":233},[230,4519,4520],{"class":362},"# Verify correctness against scipy\n",[230,4522,4523,4526,4528,4531,4533,4536,4538,4540],{"class":232,"line":244},[230,4524,4525],{"class":240},"scipy_rows",[230,4527,408],{"class":283},[230,4529,4530],{"class":240}," scipy_cols ",[230,4532,433],{"class":236},[230,4534,4535],{"class":384}," linear_sum_assignment",[230,4537,449],{"class":283},[230,4539,812],{"class":384},[230,4541,455],{"class":283},[230,4543,4544,4547,4549,4552,4554,4556],{"class":232,"line":254},[230,4545,4546],{"class":240},"scipy_assignment ",[230,4548,433],{"class":236},[230,4550,4551],{"class":240}," scipy_cols",[230,4553,284],{"class":283},[230,4555,3688],{"class":384},[230,4557,1246],{"class":283},[230,4559,4560,4563,4565,4567,4569,4571,4573,4575,4577,4579,4581,4583,4585,4587,4590,4592],{"class":232,"line":268},[230,4561,4562],{"class":240},"tm_assignment ",[230,4564,433],{"class":236},[230,4566,476],{"class":240},[230,4568,284],{"class":283},[230,4570,3653],{"class":287},[230,4572,284],{"class":283},[230,4574,3658],{"class":384},[230,4576,449],{"class":283},[230,4578,3805],{"class":384},[230,4580,284],{"class":283},[230,4582,3629],{"class":384},[230,4584,449],{"class":283},[230,4586,812],{"class":384},[230,4588,4589],{"class":283},")).",[230,4591,3688],{"class":384},[230,4593,1246],{"class":283},[230,4595,4596],{"class":232,"line":275},[230,4597,272],{"emptyLinePlaceholder":271},[230,4599,4600,4602,4604,4606,4609,4611,4613,4616],{"class":232,"line":297},[230,4601,462],{"class":461},[230,4603,449],{"class":283},[230,4605,392],{"class":391},[230,4607,4608],{"class":395},"scipy assignment :",[230,4610,392],{"class":391},[230,4612,408],{"class":283},[230,4614,4615],{"class":384}," scipy_assignment",[230,4617,455],{"class":283},[230,4619,4620,4622,4624,4626,4629,4631,4633,4636],{"class":232,"line":314},[230,4621,462],{"class":461},[230,4623,449],{"class":283},[230,4625,392],{"class":391},[230,4627,4628],{"class":395},"torchmatch       :",[230,4630,392],{"class":391},[230,4632,408],{"class":283},[230,4634,4635],{"class":384}," tm_assignment",[230,4637,455],{"class":283},[230,4639,4640,4643,4646,4649,4651,4653,4655,4658],{"class":232,"line":328},[230,4641,4642],{"class":247},"assert",[230,4644,4645],{"class":240}," scipy_assignment ",[230,4647,4648],{"class":236},"==",[230,4650,4635],{"class":240},[230,4652,408],{"class":283},[230,4654,411],{"class":391},[230,4656,4657],{"class":395},"Mismatch!",[230,4659,4660],{"class":391},"\"\n",[230,4662,4663,4665,4667,4669,4672,4674],{"class":232,"line":336},[230,4664,462],{"class":461},[230,4666,449],{"class":283},[230,4668,392],{"class":391},[230,4670,4671],{"class":395},"✓ Results match",[230,4673,392],{"class":391},[230,4675,455],{"class":283},[504,4677],{"data":4678,"kind":507},"c2NpcHkgYXNzaWdubWVudCA6IFsxLCAwLCAyXQp0b3JjaG1hdGNoICAgICAgIDogWzEsIDAsIDJdCuKckyBSZXN1bHRzIG1hdGNoCg==",[509,4680,4682],{"id":4681},"summary","Summary",[192,4684,4685,4692,4695,4701],{},[195,4686,4687,4688,4691],{},"The ",[188,4689,4690],{},"linear assignment problem"," finds the minimum-cost one-to-one\nmapping between two sets of items.",[195,4693,4694],{},"Brute force is O(n!) and impractical for n > ~10.",[195,4696,4697,4700],{},[211,4698,4699],{},"torchmatch.assignment.solve(cost)"," solves in O(n³) using\nhardware-optimised kernels (AVX2 on CPU, CUDA on GPU).",[195,4702,4703,4704,4707,4708,284],{},"Rectangular inputs and forbidden edges (",[211,4705,4706],{},"+inf",") are handled natively;\nunassigned rows return ",[211,4709,4710],{},"-1",[185,4712,4713,4716,4717,4721],{},[188,4714,4715],{},"Next",": ",[4718,4719,123],"a",{"href":4720},"02_backends_and_batching.ipynb","\nexplores the different solvers, when to choose each, and how to solve\nthousands of problems at once.",[4723,4724,4725],"style",{},"html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .slqww, html code.shiki .slqww{--shiki-light:#6182B8;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sFwrP, html code.shiki .sFwrP{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#24292E;--shiki-default-font-style:inherit;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s2W-s, html code.shiki .s2W-s{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#032F62;--shiki-default-font-style:inherit;--shiki-dark:#9ECBFF;--shiki-dark-font-style:inherit}html pre.shiki code .sithA, html code.shiki .sithA{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#032F62;--shiki-default-font-style:inherit;--shiki-dark:#9ECBFF;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":226,"searchDepth":254,"depth":254,"links":4727},[4728,4731,4732,4733,4734,4735],{"id":511,"depth":244,"text":512,"children":4729},[4730],{"id":1268,"depth":254,"text":1269},{"id":2575,"depth":244,"text":2576},{"id":3595,"depth":244,"text":3596},{"id":4005,"depth":244,"text":4006},{"id":4506,"depth":244,"text":4507},{"id":4681,"depth":244,"text":4682},"md",{"notebook":271},{"icon":121},{"title":118,"description":190},"U7RhGAcFOcwpZgGIHUBb8qY4McP32ncxcmA1PTsFhzc",[4742,4744],{"title":41,"path":109,"stem":110,"description":4743,"children":-1},"Interactive Jupyter notebooks covering both the assignment and transport families, from first principles through applied examples.",{"title":123,"path":124,"stem":125,"description":190,"icon":121,"children":-1},1785218165785]