munkre.cpp
Go to the documentation of this file.
2 
3 using namespace tuw;
4 
5 std::vector<std::pair<size_t, size_t>> Munkre::find_minimum_assignment ( const cv::Mat_<double> costmatrix ) {
6  cv::Mat_<double> C;
7  cv::Mat_<Zero> M;
8  std::vector<bool> row_cover, col_cover;
9  std::vector<std::pair<size_t, size_t>> path, result;
10  bool done = false;
11  bool transpose;
12  size_t k;
13  size_t step = 0;
14 
15  while (!done) {
16  // invariance check
17  assert ( 0 <= step && step <= 7);
18  assert ( C.cols >= C.rows );
19  assert ( (C.rows == M.rows && C.cols == M.cols) || step < 3 );
20  assert ( M.rows == row_cover.size() && M.cols == col_cover.size() );
21 
22  switch (step) {
23  case 0:
24  step_0 (costmatrix, C, transpose, k, step);
25  break;
26  case 1:
27  step_1 (C, step);
28  break;
29  case 2:
30  step_2 (C, M, row_cover, col_cover, step);
31  break;
32  case 3:
33  step_3 (M, col_cover, k, step);
34  break;
35  case 4:
36  step_4 (C, M, row_cover, col_cover, path, step);
37  break;
38  case 5:
39  step_5 (M, row_cover, col_cover, path, step);
40  break;
41  case 6:
42  step_6 (C, row_cover, col_cover, step);
43  break;
44  case 7:
45  step_7 (M, transpose, result, k, step);
46  done = true;
47  break;
48  default:
49  assert ( false );
50  break;
51  }
52 
53  //print (C, M, row_cover, col_cover, step);
54  }
55 
56  return result;
57 }
58 
59 void Munkre::step_0 (const cv::Mat_<double> costmatrix, cv::Mat_<double> &C, bool &transpose, size_t &k, size_t &step) {
60  assert( step == 0 );
61 
62  // copy/save original data
63  C = costmatrix.clone();
64 
65  // C must have at least as many columns as rows
66  if ( C.rows > C.cols) {
67  C = C.t();
68  transpose = true;
69  } else {
70  transpose = false;
71  }
72 
73  k = C.rows;
74  step = 1;
75 }
76 
77 void Munkre::step_1 (cv::Mat_<double> &C, size_t &step) {
78  assert( step == 1 );
79 
80  for (size_t r = 0; r < C.rows; r++) {
81  // find smallest element in current row
82  double min = C[r][0];
83  for (size_t c = 1; c < C.cols; c++) {
84  if ( C[r][c] < min )
85  min = C[r][c];
86  }
87 
88  // subtract smallest element from every element in current row
89  for (size_t c = 0; c < C.cols; c++) {
90  C[r][c] -= min;
91  if ( std::abs ( C[r][c] ) < __DBL_MIN__)
92  C[r][c] = 0;
93  }
94  }
95 
96  step = 2;
97 }
98 
99 void Munkre::step_2 (const cv::Mat_<double> C, cv::Mat_<Zero> &M, std::vector<bool> &row_cover, std::vector<bool> &col_cover, size_t &step) {
100  assert ( step == 2 );
101 
102  /* M[r][c] =
103  * UNDEF ... C[r][c] is undefined yet
104  * STAR ... C[r][c] is a starred zero
105  * PRIME ... C[r][c] is a primed zero
106  */
107  M = cv::Mat_<Zero> ( C.rows, C.cols, UNDEF );
108 
109  /* row_cover[r] =
110  * false ... row r contains no starred zero
111  * true ... row r contains a starred zero
112  */
113  row_cover = std::vector<bool> ( C.rows );
114 
115  /* col_cover[c] =
116  * false ... column c contains no starred zero
117  * true ... column c contains a starred zero
118  */
119  col_cover = std::vector<bool> ( C.cols );
120 
121  // find zeros and if applicable mark them starred
122  for (size_t r = 0; r < C.rows; r++) {
123  for (size_t c = 0; c < C.cols; c++) {
124  if ( C[r][c] == 0 && !row_cover[r] && !col_cover[c] ) {
125  M[r][c] = STAR;
126  row_cover[r] = true;
127  col_cover[c] = true;
128  }
129  }
130  }
131 
132  // clear covers
133  for (size_t r = 0; r < row_cover.size(); r++)
134  row_cover[r] = false;
135  for (size_t c = 0; c < col_cover.size(); c++)
136  col_cover[c] = false;
137 
138  step = 3;
139 }
140 
141 void Munkre::step_3 (const cv::Mat_<Zero> M, std::vector<bool> &col_cover, const size_t k, size_t &step) {
142  assert ( step == 3 );
143 
144  // cover and count all columns containing a starred zero
145  size_t count = 0;
146  for (size_t c = 0; c < M.cols; c++) {
147  for (size_t r = 0; r < M.rows; r++) {
148  if (M[r][c] == 1) {
149  col_cover[c] = true;
150  count++;
151  break;
152  }
153  }
154  }
155 
156  if (count >= k)
157  step = 7;
158  else
159  step = 4;
160 }
161 
162 void Munkre::step_4 (const cv::Mat_<double> C, cv::Mat_<Zero> &M, std::vector<bool> &row_cover, std::vector<bool> &col_cover, std::vector<std::pair<size_t, size_t>> &path, size_t &step) {
163  assert ( step == 4 );
164 
165  while (true) {
166  int row, col;
167  find_uncovered_zero(C, row_cover, col_cover, row, col);
168  if ( 0 <= row && row < M.rows && 0 <= col && col < M.cols ) {
169  // prime the found uncovered zero
170  M[row][col] = PRIME;
171  size_t col_prime = col;
172 
173  col = find_zero_in_row(M, row, STAR);
174  if (!(0 <= col && col < M.cols)) {
175  // no starred zero in the row containing the currently primed zero
176  path = std::vector<std::pair<size_t, size_t>> (1);
177  path[0] = std::pair<size_t, size_t>((size_t) row, (size_t) col_prime);
178  step = 5;
179  break;
180  } else {
181  // cover the row containing the currently primed zero and
182  // uncover the column containing the found starred zero
183  row_cover[row] = true;
184  col_cover[col] = false;
185  }
186  } else {
187  // no uncovered zero left
188  step = 6;
189  break;
190  }
191  }
192 }
193 
194 void Munkre::step_5 (cv::Mat_<Zero> M, std::vector<bool> &row_cover, std::vector<bool> &col_cover, std::vector<std::pair<size_t, size_t>> &path, size_t &step) {
195  assert ( step == 5 );
196  assert ( path.size() == 1 );
197 
198  while (true) {
199  int row, col;
200  std::pair<size_t, size_t> Z0, Z1, Z2;
201 
202  // Z0...primed zero (of last time)
203  Z0 = path[path.size()-1];
204 
205  // Z1...starred zero in the column of Z0 (can exist)
206  row = find_zero_in_col(M, Z0.second, STAR);
207  if ( 0 <= row && row < M.rows ) {
208  Z1 = std::pair<size_t, size_t> ((size_t) row, Z0.second);
209  path.push_back(Z1);
210  } else break;
211 
212  // Z2...primed zero in the row of Z1 (must exist).
213  col = find_zero_in_row(M, Z1.first, PRIME);
214  assert ( 0 <= col && col < M.cols);
215  Z2 = std::pair<size_t, size_t> (Z1.first, (size_t) col);
216  path.push_back(Z2);
217  }
218 
219  // augment path
220  // - starred zero gets unstarred
221  // - primed zero gets starred
222  for (size_t i = 0; i < path.size(); i++) {
223  assert ( M[path[i].first][path[i].second] == PRIME ||
224  M[path[i].first][path[i].second] == STAR );
225 
226  if (M[path[i].first][path[i].second] == STAR)
227  M[path[i].first][path[i].second] = UNDEF;
228  else
229  M[path[i].first][path[i].second] = STAR;
230  }
231 
232  // erase primes
233  for (size_t r = 0; r < M.rows; r++) {
234  for (size_t c = 0; c < M.cols; c++) {
235  if (M[r][c] == PRIME)
236  M[r][c] = UNDEF;
237  }
238  }
239 
240  // clear covers
241  for (size_t r = 0; r < row_cover.size(); r++)
242  row_cover[r] = false;
243  for (size_t c = 0; c < col_cover.size(); c++)
244  col_cover[c] = false;
245 
246  step = 3;
247 }
248 
249 void Munkre::step_6 (cv::Mat_<double> C, const std::vector<bool> row_cover, const std::vector<bool> col_cover, size_t &step) {
250  assert ( step == 6 );
251 
252  // find smallest uncovered element
253  double min = std::numeric_limits<double>::infinity();
254  for (size_t r = 0; r < C.rows; r++) {
255  for (size_t c = 0; c < C.cols; c++) {
256  if (!row_cover[r] && !col_cover[c] && C[r][c] < min)
257  min = C[r][c];
258  }
259  }
260  assert ( min < std::numeric_limits<double>::infinity() );
261 
262  // add found value to every element of each covered row and
263  // subtract found value from every element of each uncovered column
264  for (size_t r = 0; r < C.rows; r++) {
265  for (size_t c = 0; c < C.cols; c++) {
266  if (row_cover[r])
267  C[r][c] += min;
268  if (!col_cover[c])
269  C[r][c] -= min;
270  if ( std::abs ( C[r][c] ) < __DBL_MIN__)
271  C[r][c] = 0;
272  }
273  }
274 
275  step = 4;
276 }
277 
278 void Munkre::step_7 (const cv::Mat_<Zero> M, const bool transpose, std::vector<std::pair<size_t, size_t>> &result, size_t &k, size_t &step) {
279  assert ( step == 7 );
280 
281  // prepare result
282  size_t i = 0;
283  result = std::vector<std::pair<size_t, size_t>> (k);
284  for (size_t r = 0; r < M.rows; r++) {
285  for (size_t c = 0; c < M.cols; c++) {
286  bool col_finish = false;
287  if (M[r][c] == STAR) {
288  assert ( !col_finish );
289 
290  // restore original arrangement
291  if (transpose)
292  result[i] = std::pair<size_t, size_t> (c, r);
293  else
294  result[i] = std::pair<size_t, size_t> (r, c);
295 
296  col_finish = true;
297  i++;
298  }
299  }
300  }
301  assert ( i == k );
302 
303  step = 8;
304 }
305 
306 void Munkre::find_uncovered_zero (const cv::Mat_<double> C, const std::vector<bool> row_cover, const std::vector<bool> col_cover, int &row, int &col) {
307  assert ( C.rows == row_cover.size() && C.cols == col_cover.size() );
308 
309  row = -1;
310  col = -1;
311  for (size_t r = 0; r < C.rows; r++) {
312  for (size_t c = 0; c < C.cols; c++) {
313  if (C[r][c] == 0 && !row_cover[r] && !col_cover[c]) {
314  row = r;
315  col = c;
316  return;
317  }
318  }
319  }
320 }
321 
322 int Munkre::find_zero_in_row (const cv::Mat_<Zero> M, const size_t row, const Zero type) {
323  for (size_t c = 0; c < M.cols; c++) {
324  if (M[row][c] == type)
325  return c;
326  }
327 
328  return -1;
329 }
330 
331 int Munkre::find_zero_in_col (const cv::Mat_<Zero> M, const size_t col, const Zero type) {
332  for (size_t r = 0; r < M.rows; r++) {
333  if (M[r][col] == type)
334  return r;
335  }
336 
337  return -1;
338 }
339 
340 void Munkre::print (const cv::Mat_<double> C, const cv::Mat_<Zero> M, const std::vector<bool> row_cover, const std::vector<bool> col_cover, const size_t step) {
341  printf("next step %lu:\n", step);
342 
343  for (size_t r = 0; r < C.rows; r++) {
344  if (r == 0)
345  printf("[");
346  else
347  printf(" ");
348 
349  for (size_t c = 0; c < C.cols; c++) {
350  if (row_cover[r] || col_cover[c])
351  printf("(");
352  else
353  printf(" ");
354 
355  printf("%.2f", C[r][c]);
356 
357  if (row_cover[r] || col_cover[c])
358  printf(")");
359  else
360  printf(" ");
361 
362  if (M.rows == C.rows && M.cols == C.cols) {
363  switch (M[r][c]) {
364  case UNDEF:
365  printf(" ");
366  break;
367  case STAR:
368  printf("*");
369  break;
370  case PRIME:
371  printf("'");
372  break;
373  }
374  }
375 
376  if (c < C.cols - 1)
377  printf(", ");
378  }
379 
380  if (r == C.rows-1)
381  printf("]\n");
382  else
383  printf(";\n");
384  }
385 }
static void find_uncovered_zero(const cv::Mat_< double > C, const std::vector< bool > row_cover, const std::vector< bool > col_cover, int &row, int &col)
Definition: munkre.cpp:306
static int find_zero_in_col(const cv::Mat_< Zero > M, const size_t col, const Zero type)
Definition: munkre.cpp:331
static void step_0(const cv::Mat_< double > costmatrix, cv::Mat_< double > &C, bool &transpose, size_t &k, size_t &step)
Definition: munkre.cpp:59
static void step_2(const cv::Mat_< double > C, cv::Mat_< Zero > &M, std::vector< bool > &row_cover, std::vector< bool > &col_cover, size_t &step)
Definition: munkre.cpp:99
static void step_6(cv::Mat_< double > C, const std::vector< bool > row_cover, const std::vector< bool > col_cover, size_t &step)
Definition: munkre.cpp:249
static void step_5(cv::Mat_< Zero > M, std::vector< bool > &row_cover, std::vector< bool > &col_cover, std::vector< std::pair< size_t, size_t >> &path, size_t &step)
Definition: munkre.cpp:194
Definition: ekf_slam.h:8
static int find_zero_in_row(const cv::Mat_< Zero > M, const size_t row, const Zero type)
Definition: munkre.cpp:322
static void print(const cv::Mat_< double > C, const cv::Mat_< Zero > M, const std::vector< bool > row_cover, const std::vector< bool > col_cover, const size_t step)
Definition: munkre.cpp:340
static void step_4(const cv::Mat_< double > C, cv::Mat_< Zero > &M, std::vector< bool > &row_cover, std::vector< bool > &col_cover, std::vector< std::pair< size_t, size_t >> &path, size_t &step)
Definition: munkre.cpp:162
static std::vector< std::pair< size_t, size_t > > find_minimum_assignment(const cv::Mat_< double > costmatrix)
Definition: munkre.cpp:5
static void step_7(const cv::Mat_< Zero > M, const bool transpose, std::vector< std::pair< size_t, size_t >> &result, size_t &k, size_t &step)
Definition: munkre.cpp:278
unsigned int step
static void step_1(cv::Mat_< double > &C, size_t &step)
Definition: munkre.cpp:77
static void step_3(const cv::Mat_< Zero > M, std::vector< bool > &col_cover, const size_t k, size_t &step)
Definition: munkre.cpp:141
int min(int a, int b)


tuw_marker_slam
Author(s): Markus Macsek
autogenerated on Mon Jun 10 2019 15:39:09