1.3.49
 
Loading...
Searching...
No Matches
Hungarian.cpp
1#include "Hungarian.h"
2
3double HungarianAlgorithm::Solve(const std::vector<std::vector<double>> &DistMatrix, std::vector<int> &Assignment) {
4 int n = static_cast<int>(DistMatrix.size());
5 if (n == 0) {
6 Assignment.clear();
7 return 0.0;
8 }
9 int m = static_cast<int>(DistMatrix[0].size());
10 int dim = std::max(n, m);
11
12 // Build a square cost matrix 'a', filling missing entries with a large cost
13 std::vector<std::vector<double>> a(dim, std::vector<double>(dim, (std::numeric_limits<double>::max)()));
14 for (int i = 0; i < n; ++i) {
15 for (int j = 0; j < m; ++j) {
16 double v = DistMatrix[i][j];
17 a[i][j] = std::isfinite(v) ? v : ((std::numeric_limits<double>::max)() * 0.5);
18 }
19 }
20
21 // u, v are the dual potentials; p, way are the matching helpers
22 std::vector<double> u(dim + 1, 0.0), v2(dim + 1, 0.0);
23 std::vector<int> p(dim + 1, 0), way(dim + 1, 0);
24
25 // Main loop: one row per iteration
26 for (int i = 1; i <= dim; ++i) {
27 p[0] = i;
28 int j0 = 0;
29 std::vector<double> minv(dim + 1, (std::numeric_limits<double>::max)());
30 std::vector<bool> used(dim + 1, false);
31
32 do {
33 used[j0] = true;
34 int i0 = p[j0], j1 = 0;
35 double delta = (std::numeric_limits<double>::max)();
36
37 // Try to improve the matching by looking at all free columns
38 for (int j = 1; j <= dim; ++j) {
39 if (used[j])
40 continue;
41 double cur = a[i0 - 1][j - 1] - u[i0] - v2[j];
42 if (cur < minv[j]) {
43 minv[j] = cur;
44 way[j] = j0;
45 }
46 if (minv[j] < delta) {
47 delta = minv[j];
48 j1 = j;
49 }
50 }
51
52 // Update potentials
53 for (int j = 0; j <= dim; ++j) {
54 if (used[j]) {
55 u[p[j]] += delta;
56 v2[j] -= delta;
57 } else {
58 minv[j] -= delta;
59 }
60 }
61
62 j0 = j1;
63 } while (p[j0] != 0);
64
65 // Now invert the path to grow the matching
66 do {
67 int j1 = way[j0];
68 p[j0] = p[j1];
69 j0 = j1;
70 } while (j0 != 0);
71 }
72
73 // Build the result
74 Assignment.assign(n, -1);
75 for (int j = 1; j <= dim; ++j) {
76 if (p[j] <= n && j <= m) {
77 Assignment[p[j] - 1] = j - 1;
78 }
79 }
80
81 // Compute the actual cost
82 double cost = 0.0;
83 for (int i = 0; i < n; ++i) {
84 int j = Assignment[i];
85 if (j >= 0 && j < m) {
86 cost += DistMatrix[i][j];
87 }
88 }
89 return cost;
90}