[{"data":1,"prerenderedAt":3333},["ShallowReactive",2],{"navigation":3,"\u002Falgorithms\u002Ftransport\u002Ftutorials\u002Fpoint-clouds":174,"\u002Falgorithms\u002Ftransport\u002Ftutorials\u002Fpoint-clouds-surround":3328},[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":3322,"extension":3323,"links":177,"meta":3324,"navigation":3325,"path":99,"seo":3326,"stem":100,"__hash__":3327},"docs\u002F2.algorithms\u002F2.transport\u002F7.tutorials\u002F3.point-clouds.md","Point Clouds and Shapes",null,{"type":179,"value":180,"toc":3311},"minimark",[181,186,198,204,207,211,665,675,686,690,693,1763,1766,1770,1784,1997,2001,2004,2015,2456,2459,2471,2475,2482,2485,3177,3180,3187,3274,3278,3307],[182,183,185],"h2",{"id":184},"the-cost-matrix-bottleneck","The cost matrix bottleneck",[187,188,189,193,194,197],"p",{},[190,191,192],"code",{},"transport.matrix.solve"," requires you to pass an explicit ",[190,195,196],{},"(B, N, M)"," cost tensor. For N = M = 10000 in float32, that is 400 MB per problem in the batch. Even for moderate batch sizes, materialising the cost matrix exhausts GPU memory long before the solver itself becomes the bottleneck.",[187,199,200,203],{},[190,201,202],{},"torchmatch.transport.samples.loss"," solves this by computing the OT loss directly on raw point clouds, never allocating the full N×M matrix. Internally, a Triton kernel streams through the cost block by block, fusing squared-Euclidean cost computation with log-sum-exp accumulation so that only the dual potentials — two vectors of length N and M — need to live in memory.",[187,205,206],{},"The API is simpler too: pass the two point clouds and get a scalar loss.",[182,208,210],{"id":209},"computing-the-loss","Computing the loss",[212,213,218],"pre",{"className":214,"code":215,"language":216,"meta":217,"style":217},"language-python shiki shiki-themes material-theme-lighter github-light github-dark","import torch\nimport torchmatch\n\ndevice = \"cuda\"   # samples.loss requires CUDA\n\nN = 512\n# Source: a ring in 2-D.\nangles = torch.linspace(0, 2 * torch.pi, N)\nx = torch.stack([torch.cos(angles), torch.sin(angles)], dim=1)  # (N, 2)\n\n# Target: uniform random points in a square.\ny = torch.rand(N, 2) * 2 - 1                                    # (N, 2)\n\nx_gpu = x.to(device).requires_grad_(True)\ny_gpu = y.to(device)\n\nloss = torchmatch.transport.samples.loss(x_gpu, y_gpu, blur=0.1)\nprint(f\"Loss: {loss.item():.4f}\")\n\nloss.backward()\nprint(f\"Gradient shape: {x_gpu.grad.shape}\")   # (N, 2)\n","python","",[190,219,220,233,241,248,273,278,290,296,346,409,414,420,459,464,499,520,525,573,612,617,630],{"__ignoreMap":217},[221,222,225,229],"span",{"class":223,"line":224},"line",1,[221,226,228],{"class":227},"sVHd0","import",[221,230,232],{"class":231},"su5hD"," torch\n",[221,234,236,238],{"class":223,"line":235},2,[221,237,228],{"class":227},[221,239,240],{"class":231}," torchmatch\n",[221,242,244],{"class":223,"line":243},3,[221,245,247],{"emptyLinePlaceholder":246},true,"\n",[221,249,251,254,258,262,266,269],{"class":223,"line":250},4,[221,252,253],{"class":231},"device ",[221,255,257],{"class":256},"smGrS","=",[221,259,261],{"class":260},"sjJ54"," \"",[221,263,265],{"class":264},"s_sjI","cuda",[221,267,268],{"class":260},"\"",[221,270,272],{"class":271},"sutJx","   # samples.loss requires CUDA\n",[221,274,276],{"class":223,"line":275},5,[221,277,247],{"emptyLinePlaceholder":246},[221,279,281,284,286],{"class":223,"line":280},6,[221,282,283],{"class":231},"N ",[221,285,257],{"class":256},[221,287,289],{"class":288},"srdBf"," 512\n",[221,291,293],{"class":223,"line":292},7,[221,294,295],{"class":271},"# Source: a ring in 2-D.\n",[221,297,299,302,304,307,311,315,318,321,324,327,330,332,334,338,340,343],{"class":223,"line":298},8,[221,300,301],{"class":231},"angles ",[221,303,257],{"class":256},[221,305,306],{"class":231}," torch",[221,308,310],{"class":309},"sP7_E",".",[221,312,314],{"class":313},"slqww","linspace",[221,316,317],{"class":309},"(",[221,319,320],{"class":288},"0",[221,322,323],{"class":309},",",[221,325,326],{"class":288}," 2",[221,328,329],{"class":256}," *",[221,331,306],{"class":313},[221,333,310],{"class":309},[221,335,337],{"class":336},"skxfh","pi",[221,339,323],{"class":309},[221,341,342],{"class":313}," N",[221,344,345],{"class":309},")\n",[221,347,349,352,354,356,358,361,364,367,369,372,374,377,380,382,384,387,389,391,394,398,400,403,406],{"class":223,"line":348},9,[221,350,351],{"class":231},"x ",[221,353,257],{"class":256},[221,355,306],{"class":231},[221,357,310],{"class":309},[221,359,360],{"class":313},"stack",[221,362,363],{"class":309},"([",[221,365,366],{"class":313},"torch",[221,368,310],{"class":309},[221,370,371],{"class":313},"cos",[221,373,317],{"class":309},[221,375,376],{"class":313},"angles",[221,378,379],{"class":309},"),",[221,381,306],{"class":313},[221,383,310],{"class":309},[221,385,386],{"class":313},"sin",[221,388,317],{"class":309},[221,390,376],{"class":313},[221,392,393],{"class":309},")],",[221,395,397],{"class":396},"s99_P"," dim",[221,399,257],{"class":256},[221,401,402],{"class":288},"1",[221,404,405],{"class":309},")",[221,407,408],{"class":271},"  # (N, 2)\n",[221,410,412],{"class":223,"line":411},10,[221,413,247],{"emptyLinePlaceholder":246},[221,415,417],{"class":223,"line":416},11,[221,418,419],{"class":271},"# Target: uniform random points in a square.\n",[221,421,423,426,428,430,432,435,437,440,442,444,446,448,450,453,456],{"class":223,"line":422},12,[221,424,425],{"class":231},"y ",[221,427,257],{"class":256},[221,429,306],{"class":231},[221,431,310],{"class":309},[221,433,434],{"class":313},"rand",[221,436,317],{"class":309},[221,438,439],{"class":313},"N",[221,441,323],{"class":309},[221,443,326],{"class":288},[221,445,405],{"class":309},[221,447,329],{"class":256},[221,449,326],{"class":288},[221,451,452],{"class":256}," -",[221,454,455],{"class":288}," 1",[221,457,458],{"class":271},"                                    # (N, 2)\n",[221,460,462],{"class":223,"line":461},13,[221,463,247],{"emptyLinePlaceholder":246},[221,465,467,470,472,475,477,480,482,485,488,491,493,497],{"class":223,"line":466},14,[221,468,469],{"class":231},"x_gpu ",[221,471,257],{"class":256},[221,473,474],{"class":231}," x",[221,476,310],{"class":309},[221,478,479],{"class":313},"to",[221,481,317],{"class":309},[221,483,484],{"class":313},"device",[221,486,487],{"class":309},").",[221,489,490],{"class":313},"requires_grad_",[221,492,317],{"class":309},[221,494,496],{"class":495},"s39Yj","True",[221,498,345],{"class":309},[221,500,502,505,507,510,512,514,516,518],{"class":223,"line":501},15,[221,503,504],{"class":231},"y_gpu ",[221,506,257],{"class":256},[221,508,509],{"class":231}," y",[221,511,310],{"class":309},[221,513,479],{"class":313},[221,515,317],{"class":309},[221,517,484],{"class":313},[221,519,345],{"class":309},[221,521,523],{"class":223,"line":522},16,[221,524,247],{"emptyLinePlaceholder":246},[221,526,528,531,533,536,538,541,543,546,548,551,553,556,558,561,563,566,568,571],{"class":223,"line":527},17,[221,529,530],{"class":231},"loss ",[221,532,257],{"class":256},[221,534,535],{"class":231}," torchmatch",[221,537,310],{"class":309},[221,539,540],{"class":336},"transport",[221,542,310],{"class":309},[221,544,545],{"class":336},"samples",[221,547,310],{"class":309},[221,549,550],{"class":313},"loss",[221,552,317],{"class":309},[221,554,555],{"class":313},"x_gpu",[221,557,323],{"class":309},[221,559,560],{"class":313}," y_gpu",[221,562,323],{"class":309},[221,564,565],{"class":396}," blur",[221,567,257],{"class":256},[221,569,570],{"class":288},"0.1",[221,572,345],{"class":309},[221,574,576,580,582,586,589,592,594,596,599,602,605,608,610],{"class":223,"line":575},18,[221,577,579],{"class":578},"sptTA","print",[221,581,317],{"class":309},[221,583,585],{"class":584},"sbsja","f",[221,587,588],{"class":264},"\"Loss: ",[221,590,591],{"class":288},"{",[221,593,550],{"class":313},[221,595,310],{"class":309},[221,597,598],{"class":313},"item",[221,600,601],{"class":309},"()",[221,603,604],{"class":584},":.4f",[221,606,607],{"class":288},"}",[221,609,268],{"class":264},[221,611,345],{"class":309},[221,613,615],{"class":223,"line":614},19,[221,616,247],{"emptyLinePlaceholder":246},[221,618,620,622,624,627],{"class":223,"line":619},20,[221,621,550],{"class":231},[221,623,310],{"class":309},[221,625,626],{"class":313},"backward",[221,628,629],{"class":309},"()\n",[221,631,633,635,637,639,642,644,646,648,651,653,656,658,660,662],{"class":223,"line":632},21,[221,634,579],{"class":578},[221,636,317],{"class":309},[221,638,585],{"class":584},[221,640,641],{"class":264},"\"Gradient shape: ",[221,643,591],{"class":288},[221,645,555],{"class":313},[221,647,310],{"class":309},[221,649,650],{"class":336},"grad",[221,652,310],{"class":309},[221,654,655],{"class":336},"shape",[221,657,607],{"class":288},[221,659,268],{"class":264},[221,661,405],{"class":309},[221,663,664],{"class":271},"   # (N, 2)\n",[187,666,667,670,671,674],{},[190,668,669],{},"blur"," plays the role of ",[190,672,673],{},"sqrt(reg)"," in the matrix face: it sets the effective length scale of the entropic regularisation. Larger blur → smoother, denser matching; smaller blur → sharper, sparser matching.",[187,676,677,678,681,682,685],{},"Gradients flow through both ",[190,679,680],{},"x"," and ",[190,683,684],{},"y",", so both point clouds can be learned parameters.",[182,687,689],{"id":688},"training-a-point-cloud-generator","Training a point-cloud generator",[187,691,692],{},"Any differentiable loss can be a training objective. Here, train a small MLP decoder to map random latent vectors to a target shape:",[212,694,696],{"className":214,"code":695,"language":216,"meta":217,"style":217},"import torch\nimport torch.nn as nn\nimport torchmatch\nimport numpy as np\n\ndevice = \"cuda\"\nrng = np.random.default_rng(42)\n\nclass PointDecoder(nn.Module):\n    def __init__(self, latent_dim=8, n_points=256):\n        super().__init__()\n        self.n_points = n_points\n        self.net = nn.Sequential(\n            nn.Linear(latent_dim, 64),  nn.Tanh(),\n            nn.Linear(64, 128),         nn.Tanh(),\n            nn.Linear(128, n_points * 2),\n        )\n\n    def forward(self, z):\n        return self.net(z).reshape(z.size(0), self.n_points, 2)\n\ndef make_s_shape(n_points=256):\n    t = np.linspace(0, 2 * np.pi, n_points \u002F\u002F 2)\n    top = np.stack([0.5 * np.cos(t), 0.35 + 0.35 * np.sin(t)], axis=1)\n    bot = np.stack([0.5 * np.cos(t + np.pi), -0.35 + 0.35 * np.sin(t + np.pi)], axis=1)\n    pts = np.concatenate([top, bot], axis=0)\n    pts += rng.normal(0, 0.03, pts.shape).astype(np.float32)\n    return pts\n\nLATENT_DIM = 8\nN_POINTS = 256\nmodel = PointDecoder(latent_dim=LATENT_DIM, n_points=N_POINTS).to(device)\noptimizer = torch.optim.Adam(model.parameters(), lr=3e-3)\n\ntarget = torch.from_numpy(make_s_shape(N_POINTS)).to(device)\n\nfor step in range(300):\n    z = torch.randn(1, LATENT_DIM, device=device)\n    pred = model(z).squeeze(0)   # (N_POINTS, 2)\n\n    loss = torchmatch.transport.samples.loss(pred, target, blur=0.05)\n    optimizer.zero_grad()\n    loss.backward()\n    optimizer.step()\n\n    if step % 50 == 0:\n        print(f\"step {step:3d}  loss={loss.item():.4f}\")\n",[190,697,698,704,721,727,740,744,757,784,788,809,846,860,877,899,932,961,987,992,996,1015,1064,1068,1087,1128,1193,1274,1310,1361,1370,1375,1386,1397,1433,1476,1481,1516,1521,1543,1578,1607,1612,1655,1668,1680,1692,1697,1720],{"__ignoreMap":217},[221,699,700,702],{"class":223,"line":224},[221,701,228],{"class":227},[221,703,232],{"class":231},[221,705,706,708,710,712,715,718],{"class":223,"line":235},[221,707,228],{"class":227},[221,709,306],{"class":231},[221,711,310],{"class":309},[221,713,714],{"class":336},"nn",[221,716,717],{"class":227}," as",[221,719,720],{"class":231}," nn\n",[221,722,723,725],{"class":223,"line":243},[221,724,228],{"class":227},[221,726,240],{"class":231},[221,728,729,731,734,737],{"class":223,"line":250},[221,730,228],{"class":227},[221,732,733],{"class":231}," numpy ",[221,735,736],{"class":227},"as",[221,738,739],{"class":231}," np\n",[221,741,742],{"class":223,"line":275},[221,743,247],{"emptyLinePlaceholder":246},[221,745,746,748,750,752,754],{"class":223,"line":280},[221,747,253],{"class":231},[221,749,257],{"class":256},[221,751,261],{"class":260},[221,753,265],{"class":264},[221,755,756],{"class":260},"\"\n",[221,758,759,762,764,767,769,772,774,777,779,782],{"class":223,"line":292},[221,760,761],{"class":231},"rng ",[221,763,257],{"class":256},[221,765,766],{"class":231}," np",[221,768,310],{"class":309},[221,770,771],{"class":336},"random",[221,773,310],{"class":309},[221,775,776],{"class":313},"default_rng",[221,778,317],{"class":309},[221,780,781],{"class":288},"42",[221,783,345],{"class":309},[221,785,786],{"class":223,"line":298},[221,787,247],{"emptyLinePlaceholder":246},[221,789,790,793,797,799,801,803,806],{"class":223,"line":348},[221,791,792],{"class":584},"class",[221,794,796],{"class":795},"sbgvK"," PointDecoder",[221,798,317],{"class":309},[221,800,714],{"class":795},[221,802,310],{"class":309},[221,804,805],{"class":795},"Module",[221,807,808],{"class":309},"):\n",[221,810,811,814,817,819,823,825,829,831,834,836,839,841,844],{"class":223,"line":411},[221,812,813],{"class":584},"    def",[221,815,816],{"class":578}," __init__",[221,818,317],{"class":309},[221,820,822],{"class":821},"smCYv","self",[221,824,323],{"class":309},[221,826,828],{"class":827},"sFwrP"," latent_dim",[221,830,257],{"class":256},[221,832,833],{"class":288},"8",[221,835,323],{"class":309},[221,837,838],{"class":827}," n_points",[221,840,257],{"class":256},[221,842,843],{"class":288},"256",[221,845,808],{"class":309},[221,847,848,852,855,858],{"class":223,"line":416},[221,849,851],{"class":850},"sZMiF","        super",[221,853,854],{"class":309},"().",[221,856,857],{"class":578},"__init__",[221,859,629],{"class":309},[221,861,862,866,868,871,874],{"class":223,"line":422},[221,863,865],{"class":864},"s_hVV","        self",[221,867,310],{"class":309},[221,869,870],{"class":336},"n_points",[221,872,873],{"class":256}," =",[221,875,876],{"class":231}," n_points\n",[221,878,879,881,883,886,888,891,893,896],{"class":223,"line":461},[221,880,865],{"class":864},[221,882,310],{"class":309},[221,884,885],{"class":336},"net",[221,887,873],{"class":256},[221,889,890],{"class":231}," nn",[221,892,310],{"class":309},[221,894,895],{"class":313},"Sequential",[221,897,898],{"class":309},"(\n",[221,900,901,904,906,909,911,914,916,919,921,924,926,929],{"class":223,"line":466},[221,902,903],{"class":313},"            nn",[221,905,310],{"class":309},[221,907,908],{"class":313},"Linear",[221,910,317],{"class":309},[221,912,913],{"class":313},"latent_dim",[221,915,323],{"class":309},[221,917,918],{"class":288}," 64",[221,920,379],{"class":309},[221,922,923],{"class":313},"  nn",[221,925,310],{"class":309},[221,927,928],{"class":313},"Tanh",[221,930,931],{"class":309},"(),\n",[221,933,934,936,938,940,942,945,947,950,952,955,957,959],{"class":223,"line":501},[221,935,903],{"class":313},[221,937,310],{"class":309},[221,939,908],{"class":313},[221,941,317],{"class":309},[221,943,944],{"class":288},"64",[221,946,323],{"class":309},[221,948,949],{"class":288}," 128",[221,951,379],{"class":309},[221,953,954],{"class":313},"         nn",[221,956,310],{"class":309},[221,958,928],{"class":313},[221,960,931],{"class":309},[221,962,963,965,967,969,971,974,976,979,982,984],{"class":223,"line":522},[221,964,903],{"class":313},[221,966,310],{"class":309},[221,968,908],{"class":313},[221,970,317],{"class":309},[221,972,973],{"class":288},"128",[221,975,323],{"class":309},[221,977,978],{"class":313}," n_points ",[221,980,981],{"class":256},"*",[221,983,326],{"class":288},[221,985,986],{"class":309},"),\n",[221,988,989],{"class":223,"line":527},[221,990,991],{"class":309},"        )\n",[221,993,994],{"class":223,"line":575},[221,995,247],{"emptyLinePlaceholder":246},[221,997,998,1000,1004,1006,1008,1010,1013],{"class":223,"line":614},[221,999,813],{"class":584},[221,1001,1003],{"class":1002},"sGLFI"," forward",[221,1005,317],{"class":309},[221,1007,822],{"class":821},[221,1009,323],{"class":309},[221,1011,1012],{"class":827}," z",[221,1014,808],{"class":309},[221,1016,1017,1020,1023,1025,1027,1029,1032,1034,1037,1039,1041,1043,1046,1048,1050,1052,1054,1056,1058,1060,1062],{"class":223,"line":619},[221,1018,1019],{"class":227},"        return",[221,1021,1022],{"class":864}," self",[221,1024,310],{"class":309},[221,1026,885],{"class":313},[221,1028,317],{"class":309},[221,1030,1031],{"class":313},"z",[221,1033,487],{"class":309},[221,1035,1036],{"class":313},"reshape",[221,1038,317],{"class":309},[221,1040,1031],{"class":313},[221,1042,310],{"class":309},[221,1044,1045],{"class":313},"size",[221,1047,317],{"class":309},[221,1049,320],{"class":288},[221,1051,379],{"class":309},[221,1053,1022],{"class":864},[221,1055,310],{"class":309},[221,1057,870],{"class":336},[221,1059,323],{"class":309},[221,1061,326],{"class":288},[221,1063,345],{"class":309},[221,1065,1066],{"class":223,"line":632},[221,1067,247],{"emptyLinePlaceholder":246},[221,1069,1071,1074,1077,1079,1081,1083,1085],{"class":223,"line":1070},22,[221,1072,1073],{"class":584},"def",[221,1075,1076],{"class":1002}," make_s_shape",[221,1078,317],{"class":309},[221,1080,870],{"class":827},[221,1082,257],{"class":256},[221,1084,843],{"class":288},[221,1086,808],{"class":309},[221,1088,1090,1093,1095,1097,1099,1101,1103,1105,1107,1109,1111,1113,1115,1117,1119,1121,1124,1126],{"class":223,"line":1089},23,[221,1091,1092],{"class":231},"    t ",[221,1094,257],{"class":256},[221,1096,766],{"class":231},[221,1098,310],{"class":309},[221,1100,314],{"class":313},[221,1102,317],{"class":309},[221,1104,320],{"class":288},[221,1106,323],{"class":309},[221,1108,326],{"class":288},[221,1110,329],{"class":256},[221,1112,766],{"class":313},[221,1114,310],{"class":309},[221,1116,337],{"class":336},[221,1118,323],{"class":309},[221,1120,978],{"class":313},[221,1122,1123],{"class":256},"\u002F\u002F",[221,1125,326],{"class":288},[221,1127,345],{"class":309},[221,1129,1131,1134,1136,1138,1140,1142,1144,1147,1149,1151,1153,1155,1157,1160,1162,1165,1168,1170,1172,1174,1176,1178,1180,1182,1184,1187,1189,1191],{"class":223,"line":1130},24,[221,1132,1133],{"class":231},"    top ",[221,1135,257],{"class":256},[221,1137,766],{"class":231},[221,1139,310],{"class":309},[221,1141,360],{"class":313},[221,1143,363],{"class":309},[221,1145,1146],{"class":288},"0.5",[221,1148,329],{"class":256},[221,1150,766],{"class":313},[221,1152,310],{"class":309},[221,1154,371],{"class":313},[221,1156,317],{"class":309},[221,1158,1159],{"class":313},"t",[221,1161,379],{"class":309},[221,1163,1164],{"class":288}," 0.35",[221,1166,1167],{"class":256}," +",[221,1169,1164],{"class":288},[221,1171,329],{"class":256},[221,1173,766],{"class":313},[221,1175,310],{"class":309},[221,1177,386],{"class":313},[221,1179,317],{"class":309},[221,1181,1159],{"class":313},[221,1183,393],{"class":309},[221,1185,1186],{"class":396}," axis",[221,1188,257],{"class":256},[221,1190,402],{"class":288},[221,1192,345],{"class":309},[221,1194,1196,1199,1201,1203,1205,1207,1209,1211,1213,1215,1217,1219,1221,1224,1227,1229,1231,1233,1235,1237,1240,1242,1244,1246,1248,1250,1252,1254,1256,1258,1260,1262,1264,1266,1268,1270,1272],{"class":223,"line":1195},25,[221,1197,1198],{"class":231},"    bot ",[221,1200,257],{"class":256},[221,1202,766],{"class":231},[221,1204,310],{"class":309},[221,1206,360],{"class":313},[221,1208,363],{"class":309},[221,1210,1146],{"class":288},[221,1212,329],{"class":256},[221,1214,766],{"class":313},[221,1216,310],{"class":309},[221,1218,371],{"class":313},[221,1220,317],{"class":309},[221,1222,1223],{"class":313},"t ",[221,1225,1226],{"class":256},"+",[221,1228,766],{"class":313},[221,1230,310],{"class":309},[221,1232,337],{"class":336},[221,1234,379],{"class":309},[221,1236,452],{"class":256},[221,1238,1239],{"class":288},"0.35",[221,1241,1167],{"class":256},[221,1243,1164],{"class":288},[221,1245,329],{"class":256},[221,1247,766],{"class":313},[221,1249,310],{"class":309},[221,1251,386],{"class":313},[221,1253,317],{"class":309},[221,1255,1223],{"class":313},[221,1257,1226],{"class":256},[221,1259,766],{"class":313},[221,1261,310],{"class":309},[221,1263,337],{"class":336},[221,1265,393],{"class":309},[221,1267,1186],{"class":396},[221,1269,257],{"class":256},[221,1271,402],{"class":288},[221,1273,345],{"class":309},[221,1275,1277,1280,1282,1284,1286,1289,1291,1294,1296,1299,1302,1304,1306,1308],{"class":223,"line":1276},26,[221,1278,1279],{"class":231},"    pts ",[221,1281,257],{"class":256},[221,1283,766],{"class":231},[221,1285,310],{"class":309},[221,1287,1288],{"class":313},"concatenate",[221,1290,363],{"class":309},[221,1292,1293],{"class":313},"top",[221,1295,323],{"class":309},[221,1297,1298],{"class":313}," bot",[221,1300,1301],{"class":309},"],",[221,1303,1186],{"class":396},[221,1305,257],{"class":256},[221,1307,320],{"class":288},[221,1309,345],{"class":309},[221,1311,1313,1315,1318,1321,1323,1326,1328,1330,1332,1335,1337,1340,1342,1344,1346,1349,1351,1354,1356,1359],{"class":223,"line":1312},27,[221,1314,1279],{"class":231},[221,1316,1317],{"class":256},"+=",[221,1319,1320],{"class":231}," rng",[221,1322,310],{"class":309},[221,1324,1325],{"class":313},"normal",[221,1327,317],{"class":309},[221,1329,320],{"class":288},[221,1331,323],{"class":309},[221,1333,1334],{"class":288}," 0.03",[221,1336,323],{"class":309},[221,1338,1339],{"class":313}," pts",[221,1341,310],{"class":309},[221,1343,655],{"class":336},[221,1345,487],{"class":309},[221,1347,1348],{"class":313},"astype",[221,1350,317],{"class":309},[221,1352,1353],{"class":313},"np",[221,1355,310],{"class":309},[221,1357,1358],{"class":336},"float32",[221,1360,345],{"class":309},[221,1362,1364,1367],{"class":223,"line":1363},28,[221,1365,1366],{"class":227},"    return",[221,1368,1369],{"class":231}," pts\n",[221,1371,1373],{"class":223,"line":1372},29,[221,1374,247],{"emptyLinePlaceholder":246},[221,1376,1378,1381,1383],{"class":223,"line":1377},30,[221,1379,1380],{"class":864},"LATENT_DIM",[221,1382,873],{"class":256},[221,1384,1385],{"class":288}," 8\n",[221,1387,1389,1392,1394],{"class":223,"line":1388},31,[221,1390,1391],{"class":864},"N_POINTS",[221,1393,873],{"class":256},[221,1395,1396],{"class":288}," 256\n",[221,1398,1400,1403,1405,1407,1409,1411,1413,1415,1417,1419,1421,1423,1425,1427,1429,1431],{"class":223,"line":1399},32,[221,1401,1402],{"class":231},"model ",[221,1404,257],{"class":256},[221,1406,796],{"class":313},[221,1408,317],{"class":309},[221,1410,913],{"class":396},[221,1412,257],{"class":256},[221,1414,1380],{"class":578},[221,1416,323],{"class":309},[221,1418,838],{"class":396},[221,1420,257],{"class":256},[221,1422,1391],{"class":578},[221,1424,487],{"class":309},[221,1426,479],{"class":313},[221,1428,317],{"class":309},[221,1430,484],{"class":313},[221,1432,345],{"class":309},[221,1434,1436,1439,1441,1443,1445,1448,1450,1453,1455,1458,1460,1463,1466,1469,1471,1474],{"class":223,"line":1435},33,[221,1437,1438],{"class":231},"optimizer ",[221,1440,257],{"class":256},[221,1442,306],{"class":231},[221,1444,310],{"class":309},[221,1446,1447],{"class":336},"optim",[221,1449,310],{"class":309},[221,1451,1452],{"class":313},"Adam",[221,1454,317],{"class":309},[221,1456,1457],{"class":313},"model",[221,1459,310],{"class":309},[221,1461,1462],{"class":313},"parameters",[221,1464,1465],{"class":309},"(),",[221,1467,1468],{"class":396}," lr",[221,1470,257],{"class":256},[221,1472,1473],{"class":288},"3e-3",[221,1475,345],{"class":309},[221,1477,1479],{"class":223,"line":1478},34,[221,1480,247],{"emptyLinePlaceholder":246},[221,1482,1484,1487,1489,1491,1493,1496,1498,1501,1503,1505,1508,1510,1512,1514],{"class":223,"line":1483},35,[221,1485,1486],{"class":231},"target ",[221,1488,257],{"class":256},[221,1490,306],{"class":231},[221,1492,310],{"class":309},[221,1494,1495],{"class":313},"from_numpy",[221,1497,317],{"class":309},[221,1499,1500],{"class":313},"make_s_shape",[221,1502,317],{"class":309},[221,1504,1391],{"class":578},[221,1506,1507],{"class":309},")).",[221,1509,479],{"class":313},[221,1511,317],{"class":309},[221,1513,484],{"class":313},[221,1515,345],{"class":309},[221,1517,1519],{"class":223,"line":1518},36,[221,1520,247],{"emptyLinePlaceholder":246},[221,1522,1524,1527,1530,1533,1536,1538,1541],{"class":223,"line":1523},37,[221,1525,1526],{"class":227},"for",[221,1528,1529],{"class":231}," step ",[221,1531,1532],{"class":227},"in",[221,1534,1535],{"class":578}," range",[221,1537,317],{"class":309},[221,1539,1540],{"class":288},"300",[221,1542,808],{"class":309},[221,1544,1546,1549,1551,1553,1555,1558,1560,1562,1564,1567,1569,1572,1574,1576],{"class":223,"line":1545},38,[221,1547,1548],{"class":231},"    z ",[221,1550,257],{"class":256},[221,1552,306],{"class":231},[221,1554,310],{"class":309},[221,1556,1557],{"class":313},"randn",[221,1559,317],{"class":309},[221,1561,402],{"class":288},[221,1563,323],{"class":309},[221,1565,1566],{"class":578}," LATENT_DIM",[221,1568,323],{"class":309},[221,1570,1571],{"class":396}," device",[221,1573,257],{"class":256},[221,1575,484],{"class":313},[221,1577,345],{"class":309},[221,1579,1581,1584,1586,1589,1591,1593,1595,1598,1600,1602,1604],{"class":223,"line":1580},39,[221,1582,1583],{"class":231},"    pred ",[221,1585,257],{"class":256},[221,1587,1588],{"class":313}," model",[221,1590,317],{"class":309},[221,1592,1031],{"class":313},[221,1594,487],{"class":309},[221,1596,1597],{"class":313},"squeeze",[221,1599,317],{"class":309},[221,1601,320],{"class":288},[221,1603,405],{"class":309},[221,1605,1606],{"class":271},"   # (N_POINTS, 2)\n",[221,1608,1610],{"class":223,"line":1609},40,[221,1611,247],{"emptyLinePlaceholder":246},[221,1613,1615,1618,1620,1622,1624,1626,1628,1630,1632,1634,1636,1639,1641,1644,1646,1648,1650,1653],{"class":223,"line":1614},41,[221,1616,1617],{"class":231},"    loss ",[221,1619,257],{"class":256},[221,1621,535],{"class":231},[221,1623,310],{"class":309},[221,1625,540],{"class":336},[221,1627,310],{"class":309},[221,1629,545],{"class":336},[221,1631,310],{"class":309},[221,1633,550],{"class":313},[221,1635,317],{"class":309},[221,1637,1638],{"class":313},"pred",[221,1640,323],{"class":309},[221,1642,1643],{"class":313}," target",[221,1645,323],{"class":309},[221,1647,565],{"class":396},[221,1649,257],{"class":256},[221,1651,1652],{"class":288},"0.05",[221,1654,345],{"class":309},[221,1656,1658,1661,1663,1666],{"class":223,"line":1657},42,[221,1659,1660],{"class":231},"    optimizer",[221,1662,310],{"class":309},[221,1664,1665],{"class":313},"zero_grad",[221,1667,629],{"class":309},[221,1669,1671,1674,1676,1678],{"class":223,"line":1670},43,[221,1672,1673],{"class":231},"    loss",[221,1675,310],{"class":309},[221,1677,626],{"class":313},[221,1679,629],{"class":309},[221,1681,1683,1685,1687,1690],{"class":223,"line":1682},44,[221,1684,1660],{"class":231},[221,1686,310],{"class":309},[221,1688,1689],{"class":313},"step",[221,1691,629],{"class":309},[221,1693,1695],{"class":223,"line":1694},45,[221,1696,247],{"emptyLinePlaceholder":246},[221,1698,1700,1703,1705,1708,1711,1714,1717],{"class":223,"line":1699},46,[221,1701,1702],{"class":227},"    if",[221,1704,1529],{"class":231},[221,1706,1707],{"class":256},"%",[221,1709,1710],{"class":288}," 50",[221,1712,1713],{"class":256}," ==",[221,1715,1716],{"class":288}," 0",[221,1718,1719],{"class":309},":\n",[221,1721,1723,1726,1728,1730,1733,1735,1737,1740,1742,1745,1747,1749,1751,1753,1755,1757,1759,1761],{"class":223,"line":1722},47,[221,1724,1725],{"class":578},"        print",[221,1727,317],{"class":309},[221,1729,585],{"class":584},[221,1731,1732],{"class":264},"\"step ",[221,1734,591],{"class":288},[221,1736,1689],{"class":313},[221,1738,1739],{"class":584},":3d",[221,1741,607],{"class":288},[221,1743,1744],{"class":264},"  loss=",[221,1746,591],{"class":288},[221,1748,550],{"class":313},[221,1750,310],{"class":309},[221,1752,598],{"class":313},[221,1754,601],{"class":309},[221,1756,604],{"class":584},[221,1758,607],{"class":288},[221,1760,268],{"class":264},[221,1762,345],{"class":309},[187,1764,1765],{},"The Wasserstein loss is well-suited to this task: it measures how far the generated point cloud is from the target in the geometric sense, independent of which generated point corresponds to which target point.",[182,1767,1769],{"id":1768},"cpu-fallback","CPU fallback",[187,1771,1772,1775,1776,1779,1780,1783],{},[190,1773,1774],{},"samples.loss"," raises ",[190,1777,1778],{},"RuntimeError"," on CPU because the Triton kernels require a CUDA device. For testing or environments without a GPU, fall back to the matrix face with ",[190,1781,1782],{},"torch.cdist",":",[212,1785,1787],{"className":214,"code":1786,"language":216,"meta":217,"style":217},"if pred.device.type == \"cuda\":\n    loss = torchmatch.transport.samples.loss(pred, target, blur=0.05)\nelse:\n    C = torch.cdist(pred.unsqueeze(0), target.unsqueeze(0)).pow(2)\n    log_plan = torchmatch.transport.matrix.solve(C, reg=0.05 ** 2, n_iter=100)\n    loss = (log_plan.exp() * C).sum()\n",[190,1788,1789,1816,1854,1861,1912,1966],{"__ignoreMap":217},[221,1790,1791,1794,1797,1799,1801,1803,1806,1808,1810,1812,1814],{"class":223,"line":224},[221,1792,1793],{"class":227},"if",[221,1795,1796],{"class":231}," pred",[221,1798,310],{"class":309},[221,1800,484],{"class":336},[221,1802,310],{"class":309},[221,1804,1805],{"class":336},"type",[221,1807,1713],{"class":256},[221,1809,261],{"class":260},[221,1811,265],{"class":264},[221,1813,268],{"class":260},[221,1815,1719],{"class":309},[221,1817,1818,1820,1822,1824,1826,1828,1830,1832,1834,1836,1838,1840,1842,1844,1846,1848,1850,1852],{"class":223,"line":235},[221,1819,1617],{"class":231},[221,1821,257],{"class":256},[221,1823,535],{"class":231},[221,1825,310],{"class":309},[221,1827,540],{"class":336},[221,1829,310],{"class":309},[221,1831,545],{"class":336},[221,1833,310],{"class":309},[221,1835,550],{"class":313},[221,1837,317],{"class":309},[221,1839,1638],{"class":313},[221,1841,323],{"class":309},[221,1843,1643],{"class":313},[221,1845,323],{"class":309},[221,1847,565],{"class":396},[221,1849,257],{"class":256},[221,1851,1652],{"class":288},[221,1853,345],{"class":309},[221,1855,1856,1859],{"class":223,"line":243},[221,1857,1858],{"class":227},"else",[221,1860,1719],{"class":309},[221,1862,1863,1866,1868,1870,1872,1875,1877,1879,1881,1884,1886,1888,1890,1892,1894,1896,1898,1900,1902,1905,1907,1910],{"class":223,"line":250},[221,1864,1865],{"class":231},"    C ",[221,1867,257],{"class":256},[221,1869,306],{"class":231},[221,1871,310],{"class":309},[221,1873,1874],{"class":313},"cdist",[221,1876,317],{"class":309},[221,1878,1638],{"class":313},[221,1880,310],{"class":309},[221,1882,1883],{"class":313},"unsqueeze",[221,1885,317],{"class":309},[221,1887,320],{"class":288},[221,1889,379],{"class":309},[221,1891,1643],{"class":313},[221,1893,310],{"class":309},[221,1895,1883],{"class":313},[221,1897,317],{"class":309},[221,1899,320],{"class":288},[221,1901,1507],{"class":309},[221,1903,1904],{"class":313},"pow",[221,1906,317],{"class":309},[221,1908,1909],{"class":288},"2",[221,1911,345],{"class":309},[221,1913,1914,1917,1919,1921,1923,1925,1927,1930,1932,1935,1937,1940,1942,1945,1947,1949,1952,1954,1956,1959,1961,1964],{"class":223,"line":275},[221,1915,1916],{"class":231},"    log_plan ",[221,1918,257],{"class":256},[221,1920,535],{"class":231},[221,1922,310],{"class":309},[221,1924,540],{"class":336},[221,1926,310],{"class":309},[221,1928,1929],{"class":336},"matrix",[221,1931,310],{"class":309},[221,1933,1934],{"class":313},"solve",[221,1936,317],{"class":309},[221,1938,1939],{"class":313},"C",[221,1941,323],{"class":309},[221,1943,1944],{"class":396}," reg",[221,1946,257],{"class":256},[221,1948,1652],{"class":288},[221,1950,1951],{"class":256}," **",[221,1953,326],{"class":288},[221,1955,323],{"class":309},[221,1957,1958],{"class":396}," n_iter",[221,1960,257],{"class":256},[221,1962,1963],{"class":288},"100",[221,1965,345],{"class":309},[221,1967,1968,1970,1972,1975,1978,1980,1983,1985,1987,1990,1992,1995],{"class":223,"line":280},[221,1969,1617],{"class":231},[221,1971,257],{"class":256},[221,1973,1974],{"class":309}," (",[221,1976,1977],{"class":231},"log_plan",[221,1979,310],{"class":309},[221,1981,1982],{"class":313},"exp",[221,1984,601],{"class":309},[221,1986,329],{"class":256},[221,1988,1989],{"class":231}," C",[221,1991,487],{"class":309},[221,1993,1994],{"class":313},"sum",[221,1996,629],{"class":309},[182,1998,2000],{"id":1999},"unbalanced-ot-handling-outliers","Unbalanced OT: handling outliers",[187,2002,2003],{},"Standard OT enforces the marginal constraints exactly: every unit of source mass must be transported to the target, and vice versa. When the source contains outliers — points far from any plausible target — this forces nearby inliers to stretch toward the outliers to satisfy the row-sum constraint, distorting the matching.",[187,2005,2006,2010,2011,2014],{},[2007,2008,2009],"strong",{},"Unbalanced OT"," relaxes the marginal constraints with a KL penalty. Points that cannot find a reasonable match are soft-discarded rather than forced into the plan. The ",[190,2012,2013],{},"reach"," parameter controls this: smaller values discard outliers more aggressively.",[212,2016,2018],{"className":214,"code":2017,"language":216,"meta":217,"style":217},"import torch\nimport torchmatch\n\ndevice = \"cuda\"\nN_CLEAN = 200\nN_OUTLIERS = 30\n\nrng_t = torch.Generator().manual_seed(0)\nangles = torch.linspace(0, 2 * torch.pi, N_CLEAN)\nx_clean = torch.stack([torch.cos(angles), torch.sin(angles)], dim=1)\n\n# Outliers far from the ring.\noutliers = torch.rand(N_OUTLIERS, 2, generator=rng_t) * 1.5 + 2.5\nx_noisy = torch.cat([x_clean, outliers], dim=0).to(device)\n\ny = x_clean.to(device)   # clean target\n\nloss_balanced   = torchmatch.transport.samples.loss(x_noisy, y, blur=0.1)\nloss_unbalanced = torchmatch.transport.samples.loss(x_noisy, y, blur=0.1, reach=0.3)\n\nprint(f\"Balanced   loss: {loss_balanced.item():.4f}\")\nprint(f\"Unbalanced loss: {loss_unbalanced.item():.4f}\")\n",[190,2019,2020,2026,2032,2036,2048,2058,2068,2072,2097,2132,2179,2183,2188,2231,2273,2277,2299,2303,2343,2392,2396,2426],{"__ignoreMap":217},[221,2021,2022,2024],{"class":223,"line":224},[221,2023,228],{"class":227},[221,2025,232],{"class":231},[221,2027,2028,2030],{"class":223,"line":235},[221,2029,228],{"class":227},[221,2031,240],{"class":231},[221,2033,2034],{"class":223,"line":243},[221,2035,247],{"emptyLinePlaceholder":246},[221,2037,2038,2040,2042,2044,2046],{"class":223,"line":250},[221,2039,253],{"class":231},[221,2041,257],{"class":256},[221,2043,261],{"class":260},[221,2045,265],{"class":264},[221,2047,756],{"class":260},[221,2049,2050,2053,2055],{"class":223,"line":275},[221,2051,2052],{"class":864},"N_CLEAN",[221,2054,873],{"class":256},[221,2056,2057],{"class":288}," 200\n",[221,2059,2060,2063,2065],{"class":223,"line":280},[221,2061,2062],{"class":864},"N_OUTLIERS",[221,2064,873],{"class":256},[221,2066,2067],{"class":288}," 30\n",[221,2069,2070],{"class":223,"line":292},[221,2071,247],{"emptyLinePlaceholder":246},[221,2073,2074,2077,2079,2081,2083,2086,2088,2091,2093,2095],{"class":223,"line":298},[221,2075,2076],{"class":231},"rng_t ",[221,2078,257],{"class":256},[221,2080,306],{"class":231},[221,2082,310],{"class":309},[221,2084,2085],{"class":313},"Generator",[221,2087,854],{"class":309},[221,2089,2090],{"class":313},"manual_seed",[221,2092,317],{"class":309},[221,2094,320],{"class":288},[221,2096,345],{"class":309},[221,2098,2099,2101,2103,2105,2107,2109,2111,2113,2115,2117,2119,2121,2123,2125,2127,2130],{"class":223,"line":348},[221,2100,301],{"class":231},[221,2102,257],{"class":256},[221,2104,306],{"class":231},[221,2106,310],{"class":309},[221,2108,314],{"class":313},[221,2110,317],{"class":309},[221,2112,320],{"class":288},[221,2114,323],{"class":309},[221,2116,326],{"class":288},[221,2118,329],{"class":256},[221,2120,306],{"class":313},[221,2122,310],{"class":309},[221,2124,337],{"class":336},[221,2126,323],{"class":309},[221,2128,2129],{"class":578}," N_CLEAN",[221,2131,345],{"class":309},[221,2133,2134,2137,2139,2141,2143,2145,2147,2149,2151,2153,2155,2157,2159,2161,2163,2165,2167,2169,2171,2173,2175,2177],{"class":223,"line":411},[221,2135,2136],{"class":231},"x_clean ",[221,2138,257],{"class":256},[221,2140,306],{"class":231},[221,2142,310],{"class":309},[221,2144,360],{"class":313},[221,2146,363],{"class":309},[221,2148,366],{"class":313},[221,2150,310],{"class":309},[221,2152,371],{"class":313},[221,2154,317],{"class":309},[221,2156,376],{"class":313},[221,2158,379],{"class":309},[221,2160,306],{"class":313},[221,2162,310],{"class":309},[221,2164,386],{"class":313},[221,2166,317],{"class":309},[221,2168,376],{"class":313},[221,2170,393],{"class":309},[221,2172,397],{"class":396},[221,2174,257],{"class":256},[221,2176,402],{"class":288},[221,2178,345],{"class":309},[221,2180,2181],{"class":223,"line":416},[221,2182,247],{"emptyLinePlaceholder":246},[221,2184,2185],{"class":223,"line":422},[221,2186,2187],{"class":271},"# Outliers far from the ring.\n",[221,2189,2190,2193,2195,2197,2199,2201,2203,2205,2207,2209,2211,2214,2216,2219,2221,2223,2226,2228],{"class":223,"line":461},[221,2191,2192],{"class":231},"outliers ",[221,2194,257],{"class":256},[221,2196,306],{"class":231},[221,2198,310],{"class":309},[221,2200,434],{"class":313},[221,2202,317],{"class":309},[221,2204,2062],{"class":578},[221,2206,323],{"class":309},[221,2208,326],{"class":288},[221,2210,323],{"class":309},[221,2212,2213],{"class":396}," generator",[221,2215,257],{"class":256},[221,2217,2218],{"class":313},"rng_t",[221,2220,405],{"class":309},[221,2222,329],{"class":256},[221,2224,2225],{"class":288}," 1.5",[221,2227,1167],{"class":256},[221,2229,2230],{"class":288}," 2.5\n",[221,2232,2233,2236,2238,2240,2242,2245,2247,2250,2252,2255,2257,2259,2261,2263,2265,2267,2269,2271],{"class":223,"line":466},[221,2234,2235],{"class":231},"x_noisy ",[221,2237,257],{"class":256},[221,2239,306],{"class":231},[221,2241,310],{"class":309},[221,2243,2244],{"class":313},"cat",[221,2246,363],{"class":309},[221,2248,2249],{"class":313},"x_clean",[221,2251,323],{"class":309},[221,2253,2254],{"class":313}," outliers",[221,2256,1301],{"class":309},[221,2258,397],{"class":396},[221,2260,257],{"class":256},[221,2262,320],{"class":288},[221,2264,487],{"class":309},[221,2266,479],{"class":313},[221,2268,317],{"class":309},[221,2270,484],{"class":313},[221,2272,345],{"class":309},[221,2274,2275],{"class":223,"line":501},[221,2276,247],{"emptyLinePlaceholder":246},[221,2278,2279,2281,2283,2286,2288,2290,2292,2294,2296],{"class":223,"line":522},[221,2280,425],{"class":231},[221,2282,257],{"class":256},[221,2284,2285],{"class":231}," x_clean",[221,2287,310],{"class":309},[221,2289,479],{"class":313},[221,2291,317],{"class":309},[221,2293,484],{"class":313},[221,2295,405],{"class":309},[221,2297,2298],{"class":271},"   # clean target\n",[221,2300,2301],{"class":223,"line":527},[221,2302,247],{"emptyLinePlaceholder":246},[221,2304,2305,2308,2310,2312,2314,2316,2318,2320,2322,2324,2326,2329,2331,2333,2335,2337,2339,2341],{"class":223,"line":575},[221,2306,2307],{"class":231},"loss_balanced   ",[221,2309,257],{"class":256},[221,2311,535],{"class":231},[221,2313,310],{"class":309},[221,2315,540],{"class":336},[221,2317,310],{"class":309},[221,2319,545],{"class":336},[221,2321,310],{"class":309},[221,2323,550],{"class":313},[221,2325,317],{"class":309},[221,2327,2328],{"class":313},"x_noisy",[221,2330,323],{"class":309},[221,2332,509],{"class":313},[221,2334,323],{"class":309},[221,2336,565],{"class":396},[221,2338,257],{"class":256},[221,2340,570],{"class":288},[221,2342,345],{"class":309},[221,2344,2345,2348,2350,2352,2354,2356,2358,2360,2362,2364,2366,2368,2370,2372,2374,2376,2378,2380,2382,2385,2387,2390],{"class":223,"line":614},[221,2346,2347],{"class":231},"loss_unbalanced ",[221,2349,257],{"class":256},[221,2351,535],{"class":231},[221,2353,310],{"class":309},[221,2355,540],{"class":336},[221,2357,310],{"class":309},[221,2359,545],{"class":336},[221,2361,310],{"class":309},[221,2363,550],{"class":313},[221,2365,317],{"class":309},[221,2367,2328],{"class":313},[221,2369,323],{"class":309},[221,2371,509],{"class":313},[221,2373,323],{"class":309},[221,2375,565],{"class":396},[221,2377,257],{"class":256},[221,2379,570],{"class":288},[221,2381,323],{"class":309},[221,2383,2384],{"class":396}," reach",[221,2386,257],{"class":256},[221,2388,2389],{"class":288},"0.3",[221,2391,345],{"class":309},[221,2393,2394],{"class":223,"line":619},[221,2395,247],{"emptyLinePlaceholder":246},[221,2397,2398,2400,2402,2404,2407,2409,2412,2414,2416,2418,2420,2422,2424],{"class":223,"line":632},[221,2399,579],{"class":578},[221,2401,317],{"class":309},[221,2403,585],{"class":584},[221,2405,2406],{"class":264},"\"Balanced   loss: ",[221,2408,591],{"class":288},[221,2410,2411],{"class":313},"loss_balanced",[221,2413,310],{"class":309},[221,2415,598],{"class":313},[221,2417,601],{"class":309},[221,2419,604],{"class":584},[221,2421,607],{"class":288},[221,2423,268],{"class":264},[221,2425,345],{"class":309},[221,2427,2428,2430,2432,2434,2437,2439,2442,2444,2446,2448,2450,2452,2454],{"class":223,"line":1070},[221,2429,579],{"class":578},[221,2431,317],{"class":309},[221,2433,585],{"class":584},[221,2435,2436],{"class":264},"\"Unbalanced loss: ",[221,2438,591],{"class":288},[221,2440,2441],{"class":313},"loss_unbalanced",[221,2443,310],{"class":309},[221,2445,598],{"class":313},[221,2447,601],{"class":309},[221,2449,604],{"class":584},[221,2451,607],{"class":288},[221,2453,268],{"class":264},[221,2455,345],{"class":309},[187,2457,2458],{},"The unbalanced loss is lower because the outlier points are not forced to participate in the matching. Gradient-wise, the gradient through the inlier points is less contaminated by the outliers' distorting pull.",[187,2460,2461,2462,2464,2465,2467,2468,2470],{},"The ",[190,2463,2013],{}," parameter is in the same units as ",[190,2466,669],{},". A practical rule: set ",[190,2469,2013],{}," to roughly the largest inlier-to-target distance you are willing to tolerate; anything further will be soft-discarded.",[182,2472,2474],{"id":2473},"wasserstein-barycenters","Wasserstein barycenters",[187,2476,2477,2478,2481],{},"The Euclidean mean of two distributions is a pixel-wise average: blurring. The ",[2007,2479,2480],{},"Wasserstein barycenter"," is the distribution that minimises the average OT distance to a set of input distributions. It preserves structure in a geometrically meaningful way.",[187,2483,2484],{},"Consider three concentric rings at radii 0.5, 1.0, and 1.5. Their Euclidean mean is a smeared annulus. Their Wasserstein barycenter is a clean ring at radius 1.0.",[212,2486,2488],{"className":214,"code":2487,"language":216,"meta":217,"style":217},"import torch\nimport numpy as np\n\nrng = np.random.default_rng(7)\n\ndef make_ring(n, radius=1.0, noise=0.05):\n    angles = np.linspace(0, 2 * np.pi, n, endpoint=False).astype(np.float32)\n    pts = np.stack([radius * np.cos(angles), radius * np.sin(angles)], axis=1)\n    pts += rng.normal(0, noise, pts.shape).astype(np.float32)\n    return torch.from_numpy(pts)\n\nN = 64\nshapes = [make_ring(N, r) for r in [0.5, 1.0, 1.5]]\n\n# Euclidean mean: blurs the three rings into a smeared annulus.\nmean_euclidean = torch.stack(shapes).mean(dim=0)\n\n# A free-support Wasserstein barycenter could be computed by optimising\n# a point cloud Z to minimise the average OT loss to each input shape:\n# loss = sum_i samples.loss(Z, shapes[i], blur=0.05) \u002F len(shapes)\n# Gradient descent on Z converges to the Wasserstein barycenter.\nZ = make_ring(N, radius=1.0).to(\"cuda\").requires_grad_(True)\nopt = torch.optim.Adam([Z], lr=1e-2)\nshapes_gpu = [s.to(\"cuda\") for s in shapes]\n\nfor _ in range(200):\n    loss = sum(\n        torchmatch.transport.samples.loss(Z, s, blur=0.05)\n        for s in shapes_gpu\n    ) \u002F len(shapes_gpu)\n    opt.zero_grad()\n    loss.backward()\n    opt.step()\n\nprint(f\"Barycenter radius ≈ {Z.detach().norm(dim=1).mean().item():.2f}\")\n# ≈ 1.0 — the geometric mean of 0.5, 1.0, 1.5\n",[190,2489,2490,2496,2506,2510,2533,2537,2570,2628,2684,2726,2743,2747,2756,2804,2808,2813,2847,2851,2856,2861,2866,2871,2914,2947,2986,2990,3008,3019,3055,3067,3085,3096,3106,3116,3120,3172],{"__ignoreMap":217},[221,2491,2492,2494],{"class":223,"line":224},[221,2493,228],{"class":227},[221,2495,232],{"class":231},[221,2497,2498,2500,2502,2504],{"class":223,"line":235},[221,2499,228],{"class":227},[221,2501,733],{"class":231},[221,2503,736],{"class":227},[221,2505,739],{"class":231},[221,2507,2508],{"class":223,"line":243},[221,2509,247],{"emptyLinePlaceholder":246},[221,2511,2512,2514,2516,2518,2520,2522,2524,2526,2528,2531],{"class":223,"line":250},[221,2513,761],{"class":231},[221,2515,257],{"class":256},[221,2517,766],{"class":231},[221,2519,310],{"class":309},[221,2521,771],{"class":336},[221,2523,310],{"class":309},[221,2525,776],{"class":313},[221,2527,317],{"class":309},[221,2529,2530],{"class":288},"7",[221,2532,345],{"class":309},[221,2534,2535],{"class":223,"line":275},[221,2536,247],{"emptyLinePlaceholder":246},[221,2538,2539,2541,2544,2546,2549,2551,2554,2556,2559,2561,2564,2566,2568],{"class":223,"line":280},[221,2540,1073],{"class":584},[221,2542,2543],{"class":1002}," make_ring",[221,2545,317],{"class":309},[221,2547,2548],{"class":827},"n",[221,2550,323],{"class":309},[221,2552,2553],{"class":827}," radius",[221,2555,257],{"class":256},[221,2557,2558],{"class":288},"1.0",[221,2560,323],{"class":309},[221,2562,2563],{"class":827}," noise",[221,2565,257],{"class":256},[221,2567,1652],{"class":288},[221,2569,808],{"class":309},[221,2571,2572,2575,2577,2579,2581,2583,2585,2587,2589,2591,2593,2595,2597,2599,2601,2604,2606,2609,2611,2614,2616,2618,2620,2622,2624,2626],{"class":223,"line":292},[221,2573,2574],{"class":231},"    angles ",[221,2576,257],{"class":256},[221,2578,766],{"class":231},[221,2580,310],{"class":309},[221,2582,314],{"class":313},[221,2584,317],{"class":309},[221,2586,320],{"class":288},[221,2588,323],{"class":309},[221,2590,326],{"class":288},[221,2592,329],{"class":256},[221,2594,766],{"class":313},[221,2596,310],{"class":309},[221,2598,337],{"class":336},[221,2600,323],{"class":309},[221,2602,2603],{"class":313}," n",[221,2605,323],{"class":309},[221,2607,2608],{"class":396}," endpoint",[221,2610,257],{"class":256},[221,2612,2613],{"class":495},"False",[221,2615,487],{"class":309},[221,2617,1348],{"class":313},[221,2619,317],{"class":309},[221,2621,1353],{"class":313},[221,2623,310],{"class":309},[221,2625,1358],{"class":336},[221,2627,345],{"class":309},[221,2629,2630,2632,2634,2636,2638,2640,2642,2645,2647,2649,2651,2653,2655,2657,2659,2662,2664,2666,2668,2670,2672,2674,2676,2678,2680,2682],{"class":223,"line":298},[221,2631,1279],{"class":231},[221,2633,257],{"class":256},[221,2635,766],{"class":231},[221,2637,310],{"class":309},[221,2639,360],{"class":313},[221,2641,363],{"class":309},[221,2643,2644],{"class":313},"radius ",[221,2646,981],{"class":256},[221,2648,766],{"class":313},[221,2650,310],{"class":309},[221,2652,371],{"class":313},[221,2654,317],{"class":309},[221,2656,376],{"class":313},[221,2658,379],{"class":309},[221,2660,2661],{"class":313}," radius ",[221,2663,981],{"class":256},[221,2665,766],{"class":313},[221,2667,310],{"class":309},[221,2669,386],{"class":313},[221,2671,317],{"class":309},[221,2673,376],{"class":313},[221,2675,393],{"class":309},[221,2677,1186],{"class":396},[221,2679,257],{"class":256},[221,2681,402],{"class":288},[221,2683,345],{"class":309},[221,2685,2686,2688,2690,2692,2694,2696,2698,2700,2702,2704,2706,2708,2710,2712,2714,2716,2718,2720,2722,2724],{"class":223,"line":348},[221,2687,1279],{"class":231},[221,2689,1317],{"class":256},[221,2691,1320],{"class":231},[221,2693,310],{"class":309},[221,2695,1325],{"class":313},[221,2697,317],{"class":309},[221,2699,320],{"class":288},[221,2701,323],{"class":309},[221,2703,2563],{"class":313},[221,2705,323],{"class":309},[221,2707,1339],{"class":313},[221,2709,310],{"class":309},[221,2711,655],{"class":336},[221,2713,487],{"class":309},[221,2715,1348],{"class":313},[221,2717,317],{"class":309},[221,2719,1353],{"class":313},[221,2721,310],{"class":309},[221,2723,1358],{"class":336},[221,2725,345],{"class":309},[221,2727,2728,2730,2732,2734,2736,2738,2741],{"class":223,"line":411},[221,2729,1366],{"class":227},[221,2731,306],{"class":231},[221,2733,310],{"class":309},[221,2735,1495],{"class":313},[221,2737,317],{"class":309},[221,2739,2740],{"class":313},"pts",[221,2742,345],{"class":309},[221,2744,2745],{"class":223,"line":416},[221,2746,247],{"emptyLinePlaceholder":246},[221,2748,2749,2751,2753],{"class":223,"line":422},[221,2750,283],{"class":231},[221,2752,257],{"class":256},[221,2754,2755],{"class":288}," 64\n",[221,2757,2758,2761,2763,2766,2769,2771,2773,2775,2778,2780,2783,2786,2788,2790,2792,2794,2797,2799,2801],{"class":223,"line":461},[221,2759,2760],{"class":231},"shapes ",[221,2762,257],{"class":256},[221,2764,2765],{"class":309}," [",[221,2767,2768],{"class":313},"make_ring",[221,2770,317],{"class":309},[221,2772,439],{"class":313},[221,2774,323],{"class":309},[221,2776,2777],{"class":313}," r",[221,2779,405],{"class":309},[221,2781,2782],{"class":227}," for",[221,2784,2785],{"class":231}," r ",[221,2787,1532],{"class":227},[221,2789,2765],{"class":309},[221,2791,1146],{"class":288},[221,2793,323],{"class":309},[221,2795,2796],{"class":288}," 1.0",[221,2798,323],{"class":309},[221,2800,2225],{"class":288},[221,2802,2803],{"class":309},"]]\n",[221,2805,2806],{"class":223,"line":466},[221,2807,247],{"emptyLinePlaceholder":246},[221,2809,2810],{"class":223,"line":501},[221,2811,2812],{"class":271},"# Euclidean mean: blurs the three rings into a smeared annulus.\n",[221,2814,2815,2818,2820,2822,2824,2826,2828,2831,2833,2836,2838,2841,2843,2845],{"class":223,"line":522},[221,2816,2817],{"class":231},"mean_euclidean ",[221,2819,257],{"class":256},[221,2821,306],{"class":231},[221,2823,310],{"class":309},[221,2825,360],{"class":313},[221,2827,317],{"class":309},[221,2829,2830],{"class":313},"shapes",[221,2832,487],{"class":309},[221,2834,2835],{"class":313},"mean",[221,2837,317],{"class":309},[221,2839,2840],{"class":396},"dim",[221,2842,257],{"class":256},[221,2844,320],{"class":288},[221,2846,345],{"class":309},[221,2848,2849],{"class":223,"line":527},[221,2850,247],{"emptyLinePlaceholder":246},[221,2852,2853],{"class":223,"line":575},[221,2854,2855],{"class":271},"# A free-support Wasserstein barycenter could be computed by optimising\n",[221,2857,2858],{"class":223,"line":614},[221,2859,2860],{"class":271},"# a point cloud Z to minimise the average OT loss to each input shape:\n",[221,2862,2863],{"class":223,"line":619},[221,2864,2865],{"class":271},"# loss = sum_i samples.loss(Z, shapes[i], blur=0.05) \u002F len(shapes)\n",[221,2867,2868],{"class":223,"line":632},[221,2869,2870],{"class":271},"# Gradient descent on Z converges to the Wasserstein barycenter.\n",[221,2872,2873,2876,2878,2880,2882,2884,2886,2888,2890,2892,2894,2896,2898,2900,2902,2904,2906,2908,2910,2912],{"class":223,"line":1070},[221,2874,2875],{"class":231},"Z ",[221,2877,257],{"class":256},[221,2879,2543],{"class":313},[221,2881,317],{"class":309},[221,2883,439],{"class":313},[221,2885,323],{"class":309},[221,2887,2553],{"class":396},[221,2889,257],{"class":256},[221,2891,2558],{"class":288},[221,2893,487],{"class":309},[221,2895,479],{"class":313},[221,2897,317],{"class":309},[221,2899,268],{"class":260},[221,2901,265],{"class":264},[221,2903,268],{"class":260},[221,2905,487],{"class":309},[221,2907,490],{"class":313},[221,2909,317],{"class":309},[221,2911,496],{"class":495},[221,2913,345],{"class":309},[221,2915,2916,2919,2921,2923,2925,2927,2929,2931,2933,2936,2938,2940,2942,2945],{"class":223,"line":1089},[221,2917,2918],{"class":231},"opt ",[221,2920,257],{"class":256},[221,2922,306],{"class":231},[221,2924,310],{"class":309},[221,2926,1447],{"class":336},[221,2928,310],{"class":309},[221,2930,1452],{"class":313},[221,2932,363],{"class":309},[221,2934,2935],{"class":313},"Z",[221,2937,1301],{"class":309},[221,2939,1468],{"class":396},[221,2941,257],{"class":256},[221,2943,2944],{"class":288},"1e-2",[221,2946,345],{"class":309},[221,2948,2949,2952,2954,2956,2959,2961,2963,2965,2967,2969,2971,2973,2975,2978,2980,2983],{"class":223,"line":1130},[221,2950,2951],{"class":231},"shapes_gpu ",[221,2953,257],{"class":256},[221,2955,2765],{"class":309},[221,2957,2958],{"class":231},"s",[221,2960,310],{"class":309},[221,2962,479],{"class":313},[221,2964,317],{"class":309},[221,2966,268],{"class":260},[221,2968,265],{"class":264},[221,2970,268],{"class":260},[221,2972,405],{"class":309},[221,2974,2782],{"class":227},[221,2976,2977],{"class":231}," s ",[221,2979,1532],{"class":227},[221,2981,2982],{"class":231}," shapes",[221,2984,2985],{"class":309},"]\n",[221,2987,2988],{"class":223,"line":1195},[221,2989,247],{"emptyLinePlaceholder":246},[221,2991,2992,2994,2997,2999,3001,3003,3006],{"class":223,"line":1276},[221,2993,1526],{"class":227},[221,2995,2996],{"class":231}," _ ",[221,2998,1532],{"class":227},[221,3000,1535],{"class":578},[221,3002,317],{"class":309},[221,3004,3005],{"class":288},"200",[221,3007,808],{"class":309},[221,3009,3010,3012,3014,3017],{"class":223,"line":1312},[221,3011,1617],{"class":231},[221,3013,257],{"class":256},[221,3015,3016],{"class":578}," sum",[221,3018,898],{"class":309},[221,3020,3021,3024,3026,3028,3030,3032,3034,3036,3038,3040,3042,3045,3047,3049,3051,3053],{"class":223,"line":1363},[221,3022,3023],{"class":313},"        torchmatch",[221,3025,310],{"class":309},[221,3027,540],{"class":336},[221,3029,310],{"class":309},[221,3031,545],{"class":336},[221,3033,310],{"class":309},[221,3035,550],{"class":313},[221,3037,317],{"class":309},[221,3039,2935],{"class":313},[221,3041,323],{"class":309},[221,3043,3044],{"class":313}," s",[221,3046,323],{"class":309},[221,3048,565],{"class":396},[221,3050,257],{"class":256},[221,3052,1652],{"class":288},[221,3054,345],{"class":309},[221,3056,3057,3060,3062,3064],{"class":223,"line":1372},[221,3058,3059],{"class":227},"        for",[221,3061,2977],{"class":313},[221,3063,1532],{"class":227},[221,3065,3066],{"class":313}," shapes_gpu\n",[221,3068,3069,3072,3075,3078,3080,3083],{"class":223,"line":1377},[221,3070,3071],{"class":309},"    )",[221,3073,3074],{"class":256}," \u002F",[221,3076,3077],{"class":578}," len",[221,3079,317],{"class":309},[221,3081,3082],{"class":313},"shapes_gpu",[221,3084,345],{"class":309},[221,3086,3087,3090,3092,3094],{"class":223,"line":1388},[221,3088,3089],{"class":231},"    opt",[221,3091,310],{"class":309},[221,3093,1665],{"class":313},[221,3095,629],{"class":309},[221,3097,3098,3100,3102,3104],{"class":223,"line":1399},[221,3099,1673],{"class":231},[221,3101,310],{"class":309},[221,3103,626],{"class":313},[221,3105,629],{"class":309},[221,3107,3108,3110,3112,3114],{"class":223,"line":1435},[221,3109,3089],{"class":231},[221,3111,310],{"class":309},[221,3113,1689],{"class":313},[221,3115,629],{"class":309},[221,3117,3118],{"class":223,"line":1478},[221,3119,247],{"emptyLinePlaceholder":246},[221,3121,3122,3124,3126,3128,3131,3133,3135,3137,3140,3142,3145,3147,3149,3151,3153,3155,3157,3159,3161,3163,3166,3168,3170],{"class":223,"line":1483},[221,3123,579],{"class":578},[221,3125,317],{"class":309},[221,3127,585],{"class":584},[221,3129,3130],{"class":264},"\"Barycenter radius ≈ ",[221,3132,591],{"class":288},[221,3134,2935],{"class":313},[221,3136,310],{"class":309},[221,3138,3139],{"class":313},"detach",[221,3141,854],{"class":309},[221,3143,3144],{"class":313},"norm",[221,3146,317],{"class":309},[221,3148,2840],{"class":396},[221,3150,257],{"class":256},[221,3152,402],{"class":288},[221,3154,487],{"class":309},[221,3156,2835],{"class":313},[221,3158,854],{"class":309},[221,3160,598],{"class":313},[221,3162,601],{"class":309},[221,3164,3165],{"class":584},":.2f",[221,3167,607],{"class":288},[221,3169,268],{"class":264},[221,3171,345],{"class":309},[221,3173,3174],{"class":223,"line":1518},[221,3175,3176],{"class":271},"# ≈ 1.0 — the geometric mean of 0.5, 1.0, 1.5\n",[187,3178,3179],{},"The barycenter is a ring at the average radius, not a blurred combination of all three. This generalises: the Wasserstein barycenter of a set of shapes is itself a shape with coherent structure.",[182,3181,3183,3184,3186],{"id":3182},"summary-of-samplesloss-parameters","Summary of ",[190,3185,1774],{}," parameters",[3188,3189,3190,3206],"table",{},[3191,3192,3193],"thead",{},[3194,3195,3196,3200,3203],"tr",{},[3197,3198,3199],"th",{},"Parameter",[3197,3201,3202],{},"Role",[3197,3204,3205],{},"Default",[3207,3208,3209,3222,3239,3253],"tbody",{},[3194,3210,3211,3216,3219],{},[3212,3213,3214],"td",{},[190,3215,669],{},[3212,3217,3218],{},"Regularisation length scale (≈ sqrt(ε))",[3212,3220,3221],{},"required",[3194,3223,3224,3228,3235],{},[3212,3225,3226],{},[190,3227,2013],{},[3212,3229,3230,3231,3234],{},"KL relaxation for unbalanced OT; ",[190,3232,3233],{},"None"," = balanced",[3212,3236,3237],{},[190,3238,3233],{},[3194,3240,3241,3246,3249],{},[3212,3242,3243],{},[190,3244,3245],{},"debias",[3212,3247,3248],{},"Apply Sinkhorn divergence debiasing",[3212,3250,3251],{},[190,3252,2613],{},[3194,3254,3255,3260,3270],{},[3212,3256,3257],{},[190,3258,3259],{},"half_cost",[3212,3261,3262,3263,3266,3267],{},"Use ",[190,3264,3265],{},"‖x−y‖"," instead of ",[190,3268,3269],{},"‖x−y‖²",[3212,3271,3272],{},[190,3273,2613],{},[182,3275,3277],{"id":3276},"see-also","See also",[3279,3280,3281,3291,3297,3302],"ul",{},[3282,3283,3284,3287,3288,3290],"li",{},[3285,3286,22],"a",{"href":65},": ",[190,3289,1774],{}," in one page with setup instructions.",[3282,3292,3293,3296],{},[3285,3294,3295],{"href":95},"Sinkhorn algorithm",": the regularisation parameter in depth.",[3282,3298,3299,3301],{},[3285,3300,9],{"href":72},": the Triton streaming kernel and unbalanced OT derivation.",[3282,3303,3304,3306],{},[3285,3305,33],{"href":75},": exact signatures and constraints.",[3308,3309,3310],"style",{},"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 .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}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 .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 .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--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 .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--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 .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}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 .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .smCYv, html code.shiki .smCYv{--shiki-light:#E53935;--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 .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 .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--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 pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":217,"searchDepth":243,"depth":243,"links":3312},[3313,3314,3315,3316,3317,3318,3319,3321],{"id":184,"depth":235,"text":185},{"id":209,"depth":235,"text":210},{"id":688,"depth":235,"text":689},{"id":1768,"depth":235,"text":1769},{"id":1999,"depth":235,"text":2000},{"id":2473,"depth":235,"text":2474},{"id":3182,"depth":235,"text":3320},"Summary of samples.loss parameters",{"id":3276,"depth":235,"text":3277},"Computing OT directly on raw point sets with samples.loss, training a neural network shape generator, handling outliers with unbalanced OT, and computing Wasserstein barycenters.","md",{},{"title":98},{"title":176,"description":3322},"c4B9mHSnuKCTsJ-RU_1YV_ash4dt5COCmGpEhsnzduA",[3329,3331],{"title":94,"path":95,"stem":96,"description":3330,"children":-1},"Why exact OT is expensive, how entropic regularisation fixes it, what the regularisation parameter controls, and when to use Sinkhorn divergence instead of raw Sinkhorn loss.",{"title":102,"path":103,"stem":107,"description":3332,"children":-1},"Material that cuts across both solver families — interactive tutorials, application history, and the benchmark sweep.",1785218164040]