[{"data":1,"prerenderedAt":820},["ShallowReactive",2],{"navigation":3,"\u002Falgorithms\u002Fassignment\u002Fchoosing":174,"\u002Falgorithms\u002Fassignment\u002Fchoosing-surround":815},[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":176,"api":177,"body":178,"description":808,"extension":809,"links":810,"meta":811,"navigation":812,"path":38,"seo":813,"stem":39,"__hash__":814},"docs\u002F2.algorithms\u002F1.assignment\u002F5.choosing.md","Choosing the right op","direct",{"type":179,"value":180,"toc":797},"minimark",[181,200,205,301,306,455,459,521,524,589,593,700,704,776,780,793],[182,183,184,188,189,192,193,196,197,199],"p",{},[185,186,187],"code",{},"torchmatch.assignment.solve"," automates the choice between the ops below using\nthe same rules this page describes. Read this guide when you want to\noverride the automatic backend selection (",[185,190,191],{},"AUTO","), when you need to understand\nwhich op ",[185,194,195],{},"solve"," is selecting, or when you are benchmarking. The indented\nblockquotes below each rule show what ",[185,198,195],{}," picks at that branch.",[201,202,204],"h2",{"id":203},"single-problem-decision-tree","Single-problem decision tree",[206,207,212],"pre",{"className":208,"code":209,"language":210,"meta":211,"style":211},"language-mermaid shiki shiki-themes material-theme-lighter github-light github-dark","flowchart TD\n    A[Single problem\u003Cbr\u002F>cost: 2D tensor] --> B{Device?}\n    B -->|CPU| C{N×M ≤ 64?}\n    B -->|CUDA| D{N \u003C 32?}\n\n    C -->|Yes| E[jonker_scalar]\n    C -->|No| F{Square and\u003Cbr\u002F>N ≤ 256 and smooth?}\n    F -->|Yes| G[jonker_compact]\n    F -->|No| H[jonker_dense]\n\n    D -->|Yes| I[munkres]\n    D -->|No| J{Integer-tied costs?}\n    J -->|Yes| I\n    J -->|No| K[lawler\u003Cbr\u002F>note: CPU JV often faster]\n","mermaid","",[185,213,214,223,229,235,241,248,254,260,266,272,277,283,289,295],{"__ignoreMap":211},[215,216,219],"span",{"class":217,"line":218},"line",1,[215,220,222],{"class":221},"su5hD","flowchart TD\n",[215,224,226],{"class":217,"line":225},2,[215,227,228],{"class":221},"    A[Single problem\u003Cbr\u002F>cost: 2D tensor] --> B{Device?}\n",[215,230,232],{"class":217,"line":231},3,[215,233,234],{"class":221},"    B -->|CPU| C{N×M ≤ 64?}\n",[215,236,238],{"class":217,"line":237},4,[215,239,240],{"class":221},"    B -->|CUDA| D{N \u003C 32?}\n",[215,242,244],{"class":217,"line":243},5,[215,245,247],{"emptyLinePlaceholder":246},true,"\n",[215,249,251],{"class":217,"line":250},6,[215,252,253],{"class":221},"    C -->|Yes| E[jonker_scalar]\n",[215,255,257],{"class":217,"line":256},7,[215,258,259],{"class":221},"    C -->|No| F{Square and\u003Cbr\u002F>N ≤ 256 and smooth?}\n",[215,261,263],{"class":217,"line":262},8,[215,264,265],{"class":221},"    F -->|Yes| G[jonker_compact]\n",[215,267,269],{"class":217,"line":268},9,[215,270,271],{"class":221},"    F -->|No| H[jonker_dense]\n",[215,273,275],{"class":217,"line":274},10,[215,276,247],{"emptyLinePlaceholder":246},[215,278,280],{"class":217,"line":279},11,[215,281,282],{"class":221},"    D -->|Yes| I[munkres]\n",[215,284,286],{"class":217,"line":285},12,[215,287,288],{"class":221},"    D -->|No| J{Integer-tied costs?}\n",[215,290,292],{"class":217,"line":291},13,[215,293,294],{"class":221},"    J -->|Yes| I\n",[215,296,298],{"class":217,"line":297},14,[215,299,300],{"class":221},"    J -->|No| K[lawler\u003Cbr\u002F>note: CPU JV often faster]\n",[302,303,305],"h3",{"id":304},"rules-of-thumb","Rules of thumb",[307,308,309,333,375,399,420,443],"ul",{},[310,311,312,316,317,320,321],"li",{},[313,314,315],"strong",{},"CPU default",": ",[185,318,319],{},"jonker_dense",". Holds up across distributions,\nfastest at N ≥ 256.",[322,323,324],"blockquote",{},[182,325,326,329,330,332],{},[185,327,328],{},"solve(cost)"," picks ",[185,331,319],{}," for rectangular CPU inputs above\nthe scalar threshold.",[310,334,335,316,338,341,342,345,346,349,350,353,354,357,358,361,362,365,366],{},[313,336,337],{},"CPU small smooth",[185,339,340],{},"jonker_compact"," for square ",[185,343,344],{},"N ≤ 256"," with\n",[185,347,348],{},"uniform"," \u002F ",[185,351,352],{},"gamma"," costs (smooth here means continuously distributed,\nas opposed to integer-valued or highly tied; 20 to 30 % faster than\ndense). Falls behind ",[185,355,356],{},"dense"," on ",[185,359,360],{},"iou"," and ",[185,363,364],{},"gated_sparse",".",[322,367,368],{},[182,369,370,329,372,374],{},[185,371,328],{},[185,373,340],{}," for square CPU inputs above the\nscalar threshold.",[310,376,377,316,380,383,384,386,387],{},[313,378,379],{},"Portable, no vector instructions",[185,381,382],{},"jonker_scalar",". Useful when\ndeploying to CPUs without AVX2 SIMD support. Within 2× of the\nAVX2-optimized variants on ",[185,385,360],{}," costs; 2 to 4× slower on dense\nuniform costs.",[322,388,389],{},[182,390,391,329,393,395,396,365],{},[185,392,328],{},[185,394,382],{}," when ",[185,397,398],{},"N*M ≤ 64",[310,400,401,316,404,407,408],{},[313,402,403],{},"CUDA, any N, integer-tied costs",[185,405,406],{},"munkres"," (Munkres' single-path\nimplementation). The only case where a CUDA-based solver beats the\nCPU Jonker-Volgenant solvers, sometimes by 2× at N = 1024.",[322,409,410],{},[182,411,412,329,414,416,417,365],{},[185,413,328],{},[185,415,406],{}," for 2D CUDA inputs with ",[185,418,419],{},"N \u003C 32",[310,421,422,316,425,428,429,431,432],{},[313,423,424],{},"CUDA, N ≥ 512, dense costs",[185,426,427],{},"lawler",". Faster than ",[185,430,406],{}," for\nlarge, fully-populated cost matrices because its parallel search\nstrategy finds augmenting paths more efficiently at scale.",[322,433,434],{},[182,435,436,329,438,416,440,365],{},[185,437,328],{},[185,439,427],{},[185,441,442],{},"N ≥ 32",[310,444,445,316,448,450,451,454],{},[313,446,447],{},"CUDA, N ≤ 256, dense costs",[185,449,406],{}," leads on CUDA, but CPU JV\nruns ",[313,452,453],{},"10 to 100× faster"," at these sizes. Use CUDA only when the\ndata already sits on the device and the H2D round-trip dominates.",[201,456,458],{"id":457},"batched-decision-tree","Batched decision tree",[206,460,462],{"className":208,"code":461,"language":210,"meta":211,"style":211},"flowchart TD\n    A[Batched problems\u003Cbr\u002F>costs: 3D tensor B×N×M] --> B{Device?}\n    B -->|CUDA + square + K ≤ 64| C[jonker_dense_batch CUDA]\n    B -->|CUDA + K > 64| D[move to CPU\u003Cbr\u002F>jonker_dense_batch]\n    B -->|CPU| E{Square and\u003Cbr\u002F>N ≤ 256 and smooth?}\n\n    E -->|Yes| F[jonker_compact_batch]\n    E -->|No| G[jonker_dense_batch]\n\n    C -.->|need per-problem unpack| H[*_batch_unpacked variants]\n    F -.->|need per-problem unpack| H\n    G -.->|need per-problem unpack| H\n",[185,463,464,468,473,478,483,488,492,497,502,506,511,516],{"__ignoreMap":211},[215,465,466],{"class":217,"line":218},[215,467,222],{"class":221},[215,469,470],{"class":217,"line":225},[215,471,472],{"class":221},"    A[Batched problems\u003Cbr\u002F>costs: 3D tensor B×N×M] --> B{Device?}\n",[215,474,475],{"class":217,"line":231},[215,476,477],{"class":221},"    B -->|CUDA + square + K ≤ 64| C[jonker_dense_batch CUDA]\n",[215,479,480],{"class":217,"line":237},[215,481,482],{"class":221},"    B -->|CUDA + K > 64| D[move to CPU\u003Cbr\u002F>jonker_dense_batch]\n",[215,484,485],{"class":217,"line":243},[215,486,487],{"class":221},"    B -->|CPU| E{Square and\u003Cbr\u002F>N ≤ 256 and smooth?}\n",[215,489,490],{"class":217,"line":250},[215,491,247],{"emptyLinePlaceholder":246},[215,493,494],{"class":217,"line":256},[215,495,496],{"class":221},"    E -->|Yes| F[jonker_compact_batch]\n",[215,498,499],{"class":217,"line":262},[215,500,501],{"class":221},"    E -->|No| G[jonker_dense_batch]\n",[215,503,504],{"class":217,"line":268},[215,505,247],{"emptyLinePlaceholder":246},[215,507,508],{"class":217,"line":274},[215,509,510],{"class":221},"    C -.->|need per-problem unpack| H[*_batch_unpacked variants]\n",[215,512,513],{"class":217,"line":279},[215,514,515],{"class":221},"    F -.->|need per-problem unpack| H\n",[215,517,518],{"class":217,"line":285},[215,519,520],{"class":221},"    G -.->|need per-problem unpack| H\n",[302,522,305],{"id":523},"rules-of-thumb-1",[307,525,526,547,575],{},[310,527,528,531,532,535,536],{},[313,529,530],{},"Tracking after gating"," (B ≤ 64 frames, N ≤ 64 boxes, IoU \u002F gated\ncosts): ",[185,533,534],{},"jonker_dense_batch"," on CUDA wins. About 1.3 to 2 ms per call\nat typical sizes.",[322,537,538],{},[182,539,540,543,544,365],{},[185,541,542],{},"solve(costs)"," picks the CUDA backend for square 3D CUDA inputs with\n",[185,545,546],{},"K ≤ 64",[310,548,549,552,553,555,556,565],{},[313,550,551],{},"Many small problems in a batch",": CPU ",[185,554,534],{}," scales\nlinearly with the batch size B because problems run in parallel CPU\nthreads. The CUDA tiled variant scales sublinearly for small N because\nthe GPU is already saturated handling each problem; adding more\nproblems to the batch gives diminishing returns.",[322,557,558],{},[182,559,560,329,562,564],{},[185,561,542],{},[185,563,534],{}," for rectangular 3D CPU\ninputs.",[322,566,567],{},[182,568,569,329,571,574],{},[185,570,542],{},[185,572,573],{},"jonker_compact_batch"," for square 3D CPU inputs.",[310,576,577,580,581,584,585,588],{},[313,578,579],{},"Per-problem unpack",": when the alternative iterates B problems in\nPython to extract ",[185,582,583],{},"(matches, unmatched_rows, unmatched_cols)",", the\n",[185,586,587],{},"_unpacked"," variants cost about 5 % more in-kernel and eliminate the\nPython loop entirely.",[201,590,592],{"id":591},"picking-by-distribution","Picking by distribution",[594,595,596,612],"table",{},[597,598,599],"thead",{},[600,601,602,606,609],"tr",{},[603,604,605],"th",{},"Your costs look like",[603,607,608],{},"Best CPU",[603,610,611],{},"Best CUDA",[613,614,615,639,649,667,681],"tbody",{},[600,616,617,624,632],{},[618,619,620,623],"td",{},[185,621,622],{},"U(0, 1)"," random",[618,625,626,628,629,631],{},[185,627,340],{}," (small N), ",[185,630,319],{}," (large N)",[618,633,634,628,636,638],{},[185,635,406],{},[185,637,427],{}," (large N), but CPU is faster",[600,640,641,644,647],{},[618,642,643],{},"Gamma \u002F long-tail score",[618,645,646],{},"same as uniform",[618,648,646],{},[600,650,651,657,662],{},[618,652,653,656],{},[185,654,655],{},"1 - IoU"," (object-detection overlap cost, common in tracking)",[618,658,659,661],{},[185,660,319],{}," (slightly faster than compact on iou)",[618,663,664,666],{},[185,665,427],{}," when forced to CUDA, but CPU runs 10× faster",[600,668,669,672,677],{},[618,670,671],{},"Mostly +inf (cost matrix is sparse: many entries are set to +inf to mark forbidden or implausible pairings)",[618,673,674,676],{},[185,675,319],{}," (compact slows down 2× here)",[618,678,679],{},[185,680,406],{},[600,682,683,686,691],{},[618,684,685],{},"Small integer support (costs drawn from a small set of integer values, causing many ties)",[618,687,688,690],{},[185,689,319],{}," (3× faster than uniform)",[618,692,693,695,696,699],{},[185,694,406],{}," (",[313,697,698],{},"100× faster than uniform",", finally beats CPU)",[201,701,703],{"id":702},"picking-by-tracing-requirements","Picking by tracing requirements",[594,705,706,716],{},[597,707,708],{},[600,709,710,713],{},[603,711,712],{},"Requirement",[603,714,715],{},"OK to use",[613,717,718,726,736,767],{},[600,719,720,723],{},[618,721,722],{},"Eager mode (no compile)",[618,724,725],{},"All ops",[600,727,728,733],{},[618,729,730],{},[185,731,732],{},"torch.compile(default)",[618,734,735],{},"All ops (every op registers a shape-inference kernel required by the compiler)",[600,737,738,744],{},[618,739,740,743],{},[185,741,742],{},"torch.compile(mode=\"reduce-overhead\")"," (CUDA graphs)",[618,745,746,748,749,751,752,755,756,758,759,762,763,766],{},[185,747,534],{}," CUDA backend only. ",[185,750,406],{},", ",[185,753,754],{},"hybrid",", and ",[185,757,427],{}," are tagged ",[185,760,761],{},"cudagraph_unsafe"," — they synchronize with the CPU during execution and cannot be captured into a CUDA graph, so they will raise an error under ",[185,764,765],{},"reduce-overhead"," mode.",[600,768,769,774],{},[618,770,771],{},[185,772,773],{},"torch.export",[618,775,725],{},[201,777,779],{"id":778},"see-also","See also",[307,781,782,788],{},[310,783,784,787],{},[785,786,156],"a",{"href":157},": interactive per-op latency across\ncontributor hardware.",[310,789,790,792],{},[785,791,162],{"href":163},": how to run the\nsuite on your own machine.",[794,795,796],"style",{},"html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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);}",{"title":211,"searchDepth":231,"depth":231,"links":798},[799,802,805,806,807],{"id":203,"depth":225,"text":204,"children":800},[801],{"id":304,"depth":231,"text":305},{"id":457,"depth":225,"text":458,"children":803},[804],{"id":523,"depth":231,"text":305},{"id":591,"depth":225,"text":592},{"id":702,"depth":225,"text":703},{"id":778,"depth":225,"text":779},"A decision tree drawn from the 540-case benchmark sweep, with rules of thumb by problem size, cost distribution, and tracing requirement.","md",null,{},{"title":37},{"title":176,"description":808},"PMoBwe_tF5J23k7nRXK-t5C8L_45kVxkTvOxVnhvR9w",[816,818],{"title":33,"path":34,"stem":35,"description":817,"children":-1},"Input rules, output convention, and graph-capture notes for torchmatch.assignment ops.",{"title":41,"path":42,"stem":43,"description":819,"children":-1},"Hands-on Jupyter notebooks covering the linear assignment problem — from first principles through SORT-style object tracking.",1785218159644]