{"id":19301303,"url":"https://github.com/fuglede/linearassignment","last_synced_at":"2025-04-22T10:32:29.695Z","repository":{"id":46633629,"uuid":"194449202","full_name":"fuglede/linearassignment","owner":"fuglede","description":"Linear assignment problem solver for .NET.","archived":false,"fork":false,"pushed_at":"2021-10-02T17:55:27.000Z","size":88,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2023-02-27T22:22:14.106Z","etag":null,"topics":["algorithms","combinatorics","computer-science","graph-theory","hacktoberfest","matching","math","operations-research","optimization"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fuglede.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-29T21:18:49.000Z","updated_at":"2022-08-25T06:39:49.000Z","dependencies_parsed_at":"2022-07-20T08:32:06.955Z","dependency_job_id":null,"html_url":"https://github.com/fuglede/linearassignment","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuglede%2Flinearassignment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuglede%2Flinearassignment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuglede%2Flinearassignment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuglede%2Flinearassignment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fuglede","download_url":"https://codeload.github.com/fuglede/linearassignment/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223893310,"owners_count":17220870,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","combinatorics","computer-science","graph-theory","hacktoberfest","matching","math","operations-research","optimization"],"created_at":"2024-11-09T23:17:29.339Z","updated_at":"2024-11-09T23:17:29.916Z","avatar_url":"https://github.com/fuglede.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Linear assignment problem solver in .NET\n\n[![Build status](https://travis-ci.org/fuglede/linearassignment.svg?branch=master)](https://travis-ci.org/fuglede/linearassignment)\n[![.NET Core](https://github.com/fuglede/linearassignment/workflows/.NET%20Core/badge.svg)](https://github.com/fuglede/linearassignment/actions)\n\n\nThis repository includes a pure C# solver for the rectangular [linear assignment problem](https://en.wikipedia.org/wiki/Assignment_problem), also known as the [minimum weight full matching](https://en.wikipedia.org/wiki/Maximum_weight_matching) for [bipartite graphs](https://en.wikipedia.org/wiki/Bipartite_graph).\n\n## The problem\n\nConcretely, the problem we solve is the following: Let *G* = (*V*, *E*) be a [graph](https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)) and assume that *V* is the disjoint union of two sets *X* and *Y*, with |*X*| ≤ |*Y*|, and that for every (*i*, *j*) ∈ *E* we have *i* ∈ *X*, *j* ∈ *Y*. A full matching *M* ⊆ *E* is a subset of edges with the property that every vertex in *X* is incident to exactly one edge in *M*, and every vertex in *Y* is incident to at most one edge in *M*. Let *c* : *E* → **R** be any real function. Our goal is to find a full matching *M* minimizing Σ\u003csub\u003e*e* ∈ *M*\u003c/sub\u003e *c*(*e*).\n\n## Method\n\nWe provide a few different methods for solving the problem. One is based on shortest augmenting paths: At each step of the algorithm, the matching *M* is expanded by using Dijkstra's algorithm to find the shortest augmenting path from a given non-matched element of *X* to a non-matched element of *Y*, and the weights of the graph are updated according to a primal-dual method. We follow the pseudo-code laid out in\n\n    DF Crouse. On implementing 2D rectangular assignment algorithms.\n    IEEE Transactions on Aerospace and Electronic Systems\n    52(4):1679-1696, August 2016\n    doi: 10.1109/TAES.2016.140952\n\nwhich in turn is based closely on Section 4.4 of\n\n    Rainer Burkard, Mauro Dell'Amico, Silvano Martello.\n    Assignment Problems - Revised Reprint\n    Society for Industrial and Applied Mathematics, Philadelphia, 2012\n\nOur algorithm for this method is ported from the C++ implementation in [`scipy.optimize`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linear_sum_assignment.html).\n\nFor sparse inputs, i.e. inputs for which |*E*| is less than |*X*| |*Y*|, we include an implementation of LAPJVsp, which is also based on shortest augmenting paths. This algorithm is described in\n\n    R. Jonker and A. Volgenant. A Shortest Augmenting Path Algorithm for\n    Dense and Sparse Linear Assignment Problems. *Computing*, 38:325-340\n    December 1987.\n\nand our implementation is a port of the Pascal code [available here](http://www.assignmentproblems.com/LAPJV.htm).\n\nWe also include a different method based on the pseudoflow approach to solving minimum cost flow problems. This is closely based on Section 4.6.4 of Assignment Problems, which in turn is based on the cost-scaling assignment (CSA) approach of\n\n    A.V. Goldberg and R. Kennedy.\n    An efficient cost scaling algorithm for the assignment problem.\n    Math. Program., 71:153–177, 1995\n\n## Installation\n\nThe package is available from the public [NuGet Gallery](https://www.nuget.org/packages/LinearAssignment/).\n\n## Example\n\nWith the notation above, assume that *X* consists of 3 vertices, and that *Y* consists of 4 vertices. Then the function *c* may be described by some `double[3, 4]` (or `int[3, 4]` if all weights are integral), each of whose elements is a pair (*i*, *j*) of elements of *X* and *Y* respectively, in which we use `double.PositiveInfinity` to indicate that a given pair is not connected by an edge. Let us assume that such a *c* is given, and let us assume that each vertex in *X* have edges incident with each vertex in *Y*, except for, say, the last vertex in *X* not being connected to the last vertex in *Y*. Then the minimum weight matching may be obtained as follows:\n\n```cs\nvar cost = new[,] {{400, 150, 400, 1}, {400, 450, 600, 2}, {300, 225, 300, double.PositiveInfinity}};\nvar res = Solver.Solve(cost).ColumnAssignment;\n```\n\nThe result is `{1, 3, 2}` indicating that the three vertices of *X* are matched with the second, fourth, and third vertex in *Y* respectively (noting the zero-indexing).\n\nIn addition to being able to use `double.PositiveInfinity` to represent missing edges, it is possible to provide the input cost matrix in [compressed sparse row](https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_(CSR,_CRS_or_Yale_format)) format; depending on the problem structure, this can lead to large performance improvements for the solvers when inputs are sparse.\n\n```cs\n// Represent [[2.5, missing, -1], [1, 2, missing]]\nvar cost = new SparseMatrixDouble(\n    new List\u003cdouble\u003e {2.5, -1, 1, 2},\n    new List\u003cint\u003e {0, 2, 4},\n    new List\u003cint\u003e {0, 2, 0, 1},\n    3);\n// Or if the input is already densely represented:\n// var dense = new[,] {{2.5, double.PositiveInfinity, -1}, {1, 2, double.PositiveInfinity}};\n// var cost = new SparseMatrixDouble(dense);\nSolver.Solve(cost);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuglede%2Flinearassignment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuglede%2Flinearassignment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuglede%2Flinearassignment/lists"}