[{"data":1,"prerenderedAt":764},["ShallowReactive",2],{"navigation":3,"\u002Falgorithms\u002Fassignment\u002Freference":174,"\u002Falgorithms\u002Fassignment\u002Freference-surround":759},[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":753,"extension":754,"links":177,"meta":755,"navigation":756,"path":34,"seo":757,"stem":35,"__hash__":758},"docs\u002F2.algorithms\u002F1.assignment\u002F4.reference.md","Operations reference",null,{"type":179,"value":180,"toc":742},"minimark",[181,191,194,199,202,232,242,253,257,268,315,327,331,334,378,382,388,426,430,440,446,460,587,597,602,615,709,722,726,738],[182,183,184,185,190],"p",{},"Signatures, parameter types, and per-op descriptions are auto-generated from the source and browseable in the ",[186,187,189],"a",{"href":188},"\u002Fapi\u002Fassignment","API reference →",".",[182,192,193],{},"This page covers cross-cutting rules that apply to every op.",[195,196,198],"h2",{"id":197},"namespace","Namespace",[182,200,201],{},"Every op binds under two equivalent names:",[203,204,205,220],"ul",{},[206,207,208,215,216,219],"li",{},[209,210,211],"strong",{},[212,213,214],"code",{},"torchmatch.assignment.ops.\u003Cop>",": the Python attribute binding\n(autocomplete-friendly, importable via\n",[212,217,218],{},"from torchmatch.assignment.ops import \u003Cop>",").",[206,221,222,227,228,231],{},[209,223,224],{},[212,225,226],{},"torch.ops.assignment.\u003Cop>",": the PyTorch op-namespace form (use\ninside ",[212,229,230],{},"torch.compile"," regions or for dynamic dispatch by name).",[182,233,234,235,238,239,190],{},"Both names point to the same callable: ",[212,236,237],{},"torchmatch.assignment.ops.jonker_dense is torch.ops.assignment.jonker_dense"," returns ",[212,240,241],{},"True",[182,243,244,245,248,249,252],{},"Outputs are ",[212,246,247],{},"int64"," row→col tensors with ",[212,250,251],{},"-1"," for unmatched rows.",[195,254,256],{"id":255},"input-semantics","Input semantics",[182,258,259,260,263,264,267],{},"These rules hold for every op under ",[212,261,262],{},"torch.ops.assignment.*",", both\nthrough ",[212,265,266],{},"torchmatch.assignment.solve"," and through direct op calls:",[203,269,270,288,302],{},[206,271,272,275,276,279,280,283,284,287],{},[212,273,274],{},"+inf"," is a ",[209,277,278],{},"forbidden edge"," (a row-column pair that must not be\nassigned). The op rewrites it internally to a large finite sentinel\n",[212,281,282],{},"(max_finite + 1) * (K + 1)"," where ",[212,285,286],{},"K = max(rows, cols)",". The\ncaller does not need to sanitise the tensor first.",[206,289,290,293,294,297,298,301],{},[212,291,292],{},"NaN"," is ",[209,295,296],{},"rejected"," with a ",[212,299,300],{},"RuntimeError",". NaN signals an upstream\nbug (zero-norm cosine, singular Kalman covariance, log of zero); it\nis never a valid forbidden-edge marker.",[206,303,304,293,307,297,309,311,312,314],{},[212,305,306],{},"-inf",[209,308,296],{},[212,310,300],{},". An unboundedly cheap\nedge would force the solver into an infinite loop, and ",[212,313,306],{}," has no\nmeaningful \"must-not-assign\" interpretation either.",[182,316,317,319,320,323,324,326],{},[212,318,266],{}," raises ",[212,321,322],{},"ValueError"," for the same NaN \u002F ",[212,325,306],{},"\nconditions before reaching a backend; direct op calls raise the same\nclass of error from the C++ entry point.",[195,328,330],{"id":329},"output-convention","Output convention",[182,332,333],{},"For every op:",[203,335,336,342,366,373],{},[206,337,338,339,341],{},"Output dtype is ",[212,340,247],{}," (\"long\").",[206,343,344,345,348,349,352,353,356,357,348,360,352,363,365],{},"Single-problem ops return shape ",[212,346,347],{},"(N,)",". ",[212,350,351],{},"out[i] = j"," means row ",[212,354,355],{},"i","\nmatches column ",[212,358,359],{},"j",[212,361,362],{},"out[i] = -1",[212,364,355],{}," is unmatched.",[206,367,368,369,372],{},"Batched ops return shape ",[212,370,371],{},"(B, N)"," with the same per-row semantics.",[206,374,375,376,190],{},"Matches into padded columns (from rectangular inputs in the JV ops)\nmap to ",[212,377,251],{},[195,379,381],{"id":380},"tracing-graph-capture","Tracing & graph capture",[182,383,384,385,387],{},"Every op registers a FakeTensor kernel (a shape-only stub used by ",[212,386,230],{}," to trace the op without running real computation):",[203,389,390,417,423],{},[206,391,392,393,396,397,400,401,404,405,408,409,412,413,416],{},"The CUDA primed-zeros Hungarian ops — ",[212,394,395],{},"munkres",", ",[212,398,399],{},"hybrid",", and\n",[212,402,403],{},"lawler"," — are ",[212,406,407],{},"cudagraph_unsafe",". They perform host-side\n",[212,410,411],{},"cudaStreamSynchronize"," calls to read managed-memory iteration flags;\nunder ",[212,414,415],{},"torch.compile(mode=\"reduce-overhead\")"," they trigger a graph break.",[206,418,419,422],{},[212,420,421],{},"jonker_dense_batch"," (CUDA backend) is fully capturable.",[206,424,425],{},"The CPU ops carry no graph constraints; they do not participate in\nCUDA-graph capture.",[195,427,429],{"id":428},"pure-python-functions","Pure-Python functions",[182,431,432,433,435,436,439],{},"Two functions live outside ",[212,434,262],{}," and are called directly\nfrom ",[212,437,438],{},"torchmatch.assignment",":",[441,442,444],"h3",{"id":443},"auction_assignment",[212,445,443],{},[182,447,448,449,452,453,456,457,190],{},"Bertsekas' synchronous auction algorithm — an iterative, pure-Python solver\nthat works on CPU and CUDA without the compiled extension. Unlike the ops\nabove, it returns a ",[209,450,451],{},"triple"," ",[212,454,455],{},"(matches, unmatched_rows, unmatched_cols)","\nrather than a row→col tensor, and is not wired into ",[212,458,459],{},"solve",[461,462,467],"pre",{"className":463,"code":464,"language":465,"meta":466,"style":466},"language-python shiki shiki-themes material-theme-lighter github-light github-dark","torchmatch.assignment.auction_assignment(\n    cost_matrix: Tensor,   # (N, M) float; +inf = forbidden; NaN\u002F-inf rejected\n    bid_size: float,       # bid step; epsilon = min(bid_size \u002F min(N,M), 1e-3)\n    max_iters: int = 100_000,\n) -> tuple[Tensor, Tensor, Tensor]\n# (K,2) matches, (N-K,) unmatched_rows, (M-K,) unmatched_cols\n","python","",[212,468,469,493,511,528,551,581],{"__ignoreMap":466},[470,471,474,478,481,485,487,490],"span",{"class":472,"line":473},"line",1,[470,475,477],{"class":476},"su5hD","torchmatch",[470,479,190],{"class":480},"sP7_E",[470,482,484],{"class":483},"skxfh","assignment",[470,486,190],{"class":480},[470,488,443],{"class":489},"slqww",[470,491,492],{"class":480},"(\n",[470,494,496,499,501,504,507],{"class":472,"line":495},2,[470,497,498],{"class":489},"    cost_matrix",[470,500,439],{"class":480},[470,502,503],{"class":489}," Tensor",[470,505,506],{"class":480},",",[470,508,510],{"class":509},"sutJx","   # (N, M) float; +inf = forbidden; NaN\u002F-inf rejected\n",[470,512,514,517,519,523,525],{"class":472,"line":513},3,[470,515,516],{"class":489},"    bid_size",[470,518,439],{"class":480},[470,520,522],{"class":521},"sZMiF"," float",[470,524,506],{"class":480},[470,526,527],{"class":509},"       # bid step; epsilon = min(bid_size \u002F min(N,M), 1e-3)\n",[470,529,531,534,536,540,544,548],{"class":472,"line":530},4,[470,532,533],{"class":489},"    max_iters",[470,535,439],{"class":480},[470,537,539],{"class":538},"s99_P"," int",[470,541,543],{"class":542},"smGrS"," =",[470,545,547],{"class":546},"srdBf"," 100_000",[470,549,550],{"class":480},",\n",[470,552,554,557,561,564,567,570,572,574,576,578],{"class":472,"line":553},5,[470,555,556],{"class":480},")",[470,558,560],{"class":559},"srjyR"," ->",[470,562,563],{"class":476}," tuple",[470,565,566],{"class":480},"[",[470,568,569],{"class":476},"Tensor",[470,571,506],{"class":480},[470,573,503],{"class":476},[470,575,506],{"class":480},[470,577,503],{"class":476},[470,579,580],{"class":480},"]\n",[470,582,584],{"class":472,"line":583},6,[470,585,586],{"class":509},"# (K,2) matches, (N-K,) unmatched_rows, (M-K,) unmatched_cols\n",[182,588,589,590,592,593,596],{},"Integer and low-precision (float16, bfloat16) inputs are cast to float32\nautomatically. Raises ",[212,591,300],{}," if convergence is not reached within\n",[212,594,595],{},"max_iters"," iterations.",[441,598,600],{"id":599},"assignment_cost",[212,601,599],{},[182,603,604,605,607,608,610,611,614],{},"Computes the total cost of a LAP solution. Accepts the output of ",[212,606,459],{}," or\nthe row→col column from ",[212,609,443],{},"'s ",[212,612,613],{},"matches"," tensor.",[461,616,618],{"className":463,"code":617,"language":465,"meta":466,"style":466},"torchmatch.assignment.assignment_cost(\n    cost: Tensor,          # (N, M) or (B, N, M), float32\u002Ffloat64\n    matches: Tensor,       # (N,) or (B, N), int64; -1 = unmatched\n    *,\n    reduction: str = \"sum\",  # \"sum\" | \"mean\" | \"none\"\n) -> Tensor  # scalar \u002F (B,) \u002F (N,) \u002F (B,N) depending on ndim and reduction\n",[212,619,620,634,648,662,669,697],{"__ignoreMap":466},[470,621,622,624,626,628,630,632],{"class":472,"line":473},[470,623,477],{"class":476},[470,625,190],{"class":480},[470,627,484],{"class":483},[470,629,190],{"class":480},[470,631,599],{"class":489},[470,633,492],{"class":480},[470,635,636,639,641,643,645],{"class":472,"line":495},[470,637,638],{"class":489},"    cost",[470,640,439],{"class":480},[470,642,503],{"class":489},[470,644,506],{"class":480},[470,646,647],{"class":509},"          # (N, M) or (B, N, M), float32\u002Ffloat64\n",[470,649,650,653,655,657,659],{"class":472,"line":513},[470,651,652],{"class":489},"    matches",[470,654,439],{"class":480},[470,656,503],{"class":489},[470,658,506],{"class":480},[470,660,661],{"class":509},"       # (N,) or (B, N), int64; -1 = unmatched\n",[470,663,664,667],{"class":472,"line":530},[470,665,666],{"class":542},"    *",[470,668,550],{"class":480},[470,670,671,674,676,679,681,685,689,692,694],{"class":472,"line":553},[470,672,673],{"class":489},"    reduction",[470,675,439],{"class":480},[470,677,678],{"class":538}," str",[470,680,543],{"class":542},[470,682,684],{"class":683},"sjJ54"," \"",[470,686,688],{"class":687},"s_sjI","sum",[470,690,691],{"class":683},"\"",[470,693,506],{"class":480},[470,695,696],{"class":509},"  # \"sum\" | \"mean\" | \"none\"\n",[470,698,699,701,703,706],{"class":472,"line":583},[470,700,556],{"class":480},[470,702,560],{"class":559},[470,704,705],{"class":476}," Tensor  ",[470,707,708],{"class":509},"# scalar \u002F (B,) \u002F (N,) \u002F (B,N) depending on ndim and reduction\n",[182,710,711,712,714,715,718,719,190],{},"Unmatched rows (",[212,713,251],{},") contribute ",[212,716,717],{},"0"," to the result regardless of ",[212,720,721],{},"reduction",[195,723,725],{"id":724},"see-also","See also",[203,727,728,733],{},[206,729,730,732],{},[186,731,9],{"href":30},": why the two families exist.",[206,734,735,737],{},[186,736,156],{"href":157},": per-op latency across cost\ndistributions, with use-case recommendations.",[739,740,741],"style",{},"html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .slqww, html code.shiki .slqww{--shiki-light:#6182B8;--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 .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srjyR, html code.shiki .srjyR{--shiki-light:#90A4AE;--shiki-light-font-style:inherit;--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}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 .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}",{"title":466,"searchDepth":513,"depth":513,"links":743},[744,745,746,747,748,752],{"id":197,"depth":495,"text":198},{"id":255,"depth":495,"text":256},{"id":329,"depth":495,"text":330},{"id":380,"depth":495,"text":381},{"id":428,"depth":495,"text":429,"children":749},[750,751],{"id":443,"depth":513,"text":443},{"id":599,"depth":513,"text":599},{"id":724,"depth":495,"text":725},"Input rules, output convention, and graph-capture notes for torchmatch.assignment ops.","md",{},{"title":33},{"title":176,"description":753},"rFzJ6QFrqPOAMmgOUh-FO68spcGJ4HEFdntmnPIGtZg",[760,762],{"title":9,"path":30,"stem":31,"description":761,"children":-1},"The linear assignment problem, the Hungarian primal-dual method, and the three implementations torchmatch ships (Munkres, Lawler, Jonker-Volgenant).",{"title":37,"path":38,"stem":39,"description":763,"children":-1},"A decision tree drawn from the 540-case benchmark sweep, with rules of thumb by problem size, cost distribution, and tracing requirement.",1785218159644]