Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "munkres/munkres.h"
00027 #include "limits.h"
00028
00029 munkres::munkres(void)
00030 {
00031
00032 diag_on = false;
00033 }
00034
00035 munkres::~munkres(void)
00036 {
00037 }
00038
00039
00040 void munkres::load_weights(std::vector<std::vector<int> > x)
00041 {
00042
00043 int a = x.size(), b = x[0].size();
00044
00045
00046
00047 std::vector<int> ivector;
00048 cell default_cell;
00049 std::vector<cell> default_vector;
00050
00051
00052
00053
00054 if (a > b)
00055 {
00056
00057 num_rows = b;
00058 num_columns = a;
00059 ivector.resize(num_columns, -1);
00060 weight_array.resize(num_rows, ivector);
00061 default_vector.resize(num_columns, default_cell);
00062 cell_array.resize(num_rows, default_vector);
00063
00064
00065 for (int i = 0; i < num_rows; i++)
00066 {
00067 for (int j = 0; j < num_columns; j++)
00068 {
00069 weight_array[i][j] = x[j][i];
00070 cell_array[i][j].weight = x[j][i];
00071 }
00072 }
00073 }
00074
00075
00076 else
00077 {
00078
00079 num_rows = a;
00080 num_columns = b;
00081 ivector.resize(num_columns, -1);
00082 weight_array.resize(num_rows, ivector);
00083 default_vector.resize(num_columns, default_cell);
00084 cell_array.resize(num_rows, default_vector);
00085
00086
00087 for (int i = 0; i < num_rows; i++)
00088 {
00089 for (int j = 0; j < num_columns; j++)
00090 {
00091 weight_array[i][j] = x[i][j];
00092 cell_array[i][j].weight = x[i][j];
00093 }
00094 }
00095 }
00096
00097
00098 row_starred.resize(num_rows, false);
00099 row_cov.resize(num_rows, false);
00100 column_starred.resize(num_columns, false);
00101 column_cov.resize(num_columns, false);
00102
00103 if (diag_on)
00104 {
00105 diagnostic(1);
00106 }
00107
00108 }
00109
00110
00111 int munkres::assign(ordered_pair *matching)
00112 {
00113
00114
00115 int total_cost = 0;
00116
00117
00118 bool matching_found = false;
00119
00120
00121 if (diag_on)
00122 {
00123 diagnostic(1);
00124 }
00125
00126
00127 matching_found = find_a_matching();
00128
00129
00130 if (diag_on)
00131 {
00132 diagnostic(1);
00133 }
00134
00135
00136 for (int i = 0; i < num_rows; i++)
00137 {
00138 for (int j = 0; j < num_columns; j++)
00139 {
00140 if (cell_array[i][j].starred)
00141 {
00142 matching[i].col = j;
00143 matching[i].row = i;
00144 total_cost += weight_array[i][j];
00145 }
00146 }
00147 }
00148 return total_cost;
00149 }
00150
00151
00152
00153 int munkres::find_star_row(int r)
00154 {
00155
00156
00157 for (int i = 0; i < num_columns; i++)
00158 {
00159
00160 if (cell_array[r][i].starred == true)
00161 {
00162 row_starred[r] = true;
00163 column_starred[i] = true;
00164 return i;
00165 }
00166 }
00167
00168 return -1;
00169 }
00170
00171 int munkres::find_star_column(int c)
00172 {
00173
00174 for (int i = 0; i < num_rows; i++)
00175 {
00176
00177 if (cell_array[i][c].starred == true)
00178 {
00179 column_starred[c] = true;
00180 row_starred[i] = true;
00181 return i;
00182 }
00183 }
00184
00185 return -1;
00186 }
00187
00188 int munkres::find_prime_row(int r)
00189 {
00190
00191
00192 for (int i = 0; i < num_columns; i++)
00193 {
00194
00195
00196 if (cell_array[r][i].primed == true)
00197 {
00198 return i;
00199 }
00200 }
00201
00202 return -1;
00203 }
00204
00205 int munkres::find_prime_column(int c)
00206 {
00207
00208 for (int i = 0; i < num_rows; i++)
00209 {
00210
00211
00212 if (cell_array[i][c].primed == true)
00213 {
00214 return i;
00215 }
00216 }
00217
00218 return -1;
00219 }
00220
00221
00222
00223 bool munkres::find_a_matching(void)
00224 {
00225 step1();
00226 step2();
00227 return step3();
00228 }
00229
00230
00231
00232
00233
00234
00235 void munkres::step1(void)
00236 {
00237
00238 int smallest = 0;
00239
00240 for (int i = 0; i < num_rows; i++)
00241 {
00242
00243 while (smallest == 0)
00244 {
00245 smallest = cell_array[i][0].weight;
00246
00247 if (smallest == 0)
00248 {
00249 if (i < num_rows - 1)
00250 i++;
00251 else
00252 break;
00253 }
00254 }
00255
00256 for (int j = 1; j < num_columns; j++)
00257 {
00258
00259
00260 if (cell_array[i][j].weight == 0)
00261 {
00262 smallest = 0;
00263
00264 j = num_columns;
00265 }
00266
00267
00268
00269 else if (cell_array[i][j].weight < smallest)
00270 {
00271 smallest = cell_array[i][j].weight;
00272 }
00273 }
00274
00275
00276
00277 if (smallest != 0)
00278 {
00279
00280
00281 for (int j = 0; j < num_columns; j++)
00282 {
00283 cell_array[i][j].weight -= smallest;
00284 }
00285 }
00286
00287
00288 smallest = 0;
00289 }
00290
00291 if (diag_on)
00292 {
00293 std::cerr << "Step 1" << std::endl;
00294 diagnostic(2);
00295 }
00296 }
00297
00298
00299
00300 void munkres::step2(void)
00301 {
00302
00303 for (int i = 0; i < num_rows; i++)
00304 {
00305
00306 for (int j = 0; j < num_columns; j++)
00307 {
00308
00309 if (cell_array[i][j].weight == 0)
00310 {
00311
00312 if (!row_starred[i])
00313 {
00314
00315 find_star_row(i);
00316 }
00317
00318
00319 if (!column_starred[j])
00320 {
00321
00322 find_star_column(j);
00323 }
00324
00325
00326 if (!row_starred[i] && !column_starred[j])
00327 {
00328
00329 cell_array[i][j].starred = true;
00330
00331 row_starred[i] = true;
00332
00333 column_starred[j] = true;
00334 }
00335 }
00336 }
00337 }
00338
00339 if (diag_on)
00340 {
00341 std::cerr << "Step 2" << std::endl;
00342 diagnostic(3);
00343 }
00344 }
00345
00346
00347
00348
00349 bool munkres::step3(void)
00350 {
00351
00352 int iter = 0;
00353
00354
00355 for (int i = 0; i < num_columns; i++)
00356 {
00357
00358 if (column_starred[i])
00359 {
00360
00361 column_cov[i] = true;
00362 }
00363 }
00364
00365 for (int i = 0; i < num_columns; i++)
00366 {
00367 if (column_cov[i])
00368 {
00369 iter++;
00370 }
00371 }
00372
00373 if (diag_on)
00374 {
00375 std::cerr << "Step 3" << std::endl;
00376 diagnostic(6);
00377 }
00378
00379
00380 if (iter == num_rows)
00381 {
00382
00383 return true;
00384 }
00385
00386
00387 else
00388 return step4();
00389 }
00390
00391
00392
00393
00394
00395
00401 bool munkres::step4(void)
00402 {
00403 while (true)
00404 {
00405
00406 int row = -1;
00407 int col = -1;
00408 for (int i = 0; i < num_rows; i++)
00409 {
00410 for (int j = 0; j < num_columns; j++)
00411 {
00412 if (cell_array[i][j].weight == 0 && row_cov[i] == false && column_cov[j] == false)
00413 {
00414 row = i;
00415 col = j;
00416 break;
00417 }
00418 }
00419 if (row != -1)
00420 break;
00421 }
00422
00423
00424 if (row == -1)
00425 {
00426 if (diag_on)
00427 {
00428 std::cerr << "Step 4" << std::endl;
00429 diagnostic(6);
00430 }
00431 return step6();
00432 }
00433
00434 else
00435 {
00436 cell_array[row][col].primed = true;
00437
00438
00439 if (row_starred[row] == false)
00440 {
00441 if (diag_on)
00442 {
00443 std::cerr << "Step 4: " << row << ", " << col << std::endl;
00444 diagnostic(6);
00445 }
00446 return step5(row, col);
00447 }
00448
00449 else
00450 {
00451 row_cov[row] = true;
00452 int starredZeroCol = 0;
00453 for (starredZeroCol = 0; starredZeroCol < num_rows; starredZeroCol++)
00454 if (cell_array[row][starredZeroCol].starred == true)
00455 break;
00456 column_cov[starredZeroCol] = false;
00457 }
00458 }
00459 }
00460
00461 return false;
00462
00463
00465
00466
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 bool munkres::step5(int r, int c)
00558 {
00559
00560
00561 bool done = false;
00562
00563
00564 bool looking_for_star = true;
00565
00566
00567
00568
00569
00570 int a;
00571
00572
00573 while (!done)
00574 {
00575 switch (looking_for_star)
00576 {
00577
00578
00579 case true:
00580
00581
00582 a = r;
00583
00584
00585 if (!column_starred[c])
00586 {
00587
00588 cell_array[r][c].primed = false;
00589
00590 cell_array[r][c].starred = true;
00591
00592 row_starred[r] = true;
00593
00594 done = true;
00595 }
00596 else
00597 {
00598
00599
00600 r = find_star_column(c);
00601
00602 cell_array[a][c].primed = false;
00603
00604 cell_array[a][c].starred = true;
00605
00606 row_starred[a] = true;
00607
00608 looking_for_star = false;
00609 }
00610
00611
00612
00613 column_starred[c] = true;
00614 break;
00615
00616
00617 case false:
00618
00619
00620 cell_array[r][c].primed = false;
00621
00622 cell_array[r][c].starred = false;
00623
00624
00625 row_starred[r] = false;
00626
00627
00628
00629 c = find_prime_row(r);
00630
00631
00632 looking_for_star = true;
00633 break;
00634 }
00635 }
00636
00637
00638 for (int i = 0; i < num_rows; i++)
00639 {
00640 for (int j = 0; j < num_columns; j++)
00641 {
00642 cell_array[i][j].primed = false;
00643 }
00644 row_cov[i] = false;
00645 }
00646
00647
00648 for (int i = 0; i < num_columns; i++)
00649 column_cov[i] = false;
00650
00651 if (diag_on)
00652 {
00653 std::cerr << "Step 5" << std::endl;
00654 diagnostic(6);
00655 }
00656
00657 return step3();
00658 }
00659
00660
00661
00662
00666
00669 bool munkres::step6()
00670 {
00671
00672 int minVal = INT_MAX;
00673 for (int i = 0; i < num_rows; i++)
00674 for (int j = 0; j < num_columns; j++)
00675 if (row_cov[i] == false && column_cov[j] == false)
00676 if (minVal > cell_array[i][j].weight)
00677 minVal = cell_array[i][j].weight;
00678
00679
00680 for (int i = 0; i < num_rows; i++)
00681 {
00682
00683 for (int j = 0; j < num_columns; j++)
00684 {
00685
00686 if (column_cov[j] == false)
00687 {
00688
00689 cell_array[i][j].weight -= minVal;
00690 }
00691
00692
00693 else if (row_cov[i] == true)
00694 cell_array[i][j].weight += minVal;
00695 }
00696 }
00697
00698 if (diag_on)
00699 {
00700 std::cerr << "Step 6" << std::endl;
00701 diagnostic(6);
00702 }
00703
00704 return step4();
00705 }
00706
00707
00708
00709 void munkres::diagnostic(int a) const
00710 {
00711 switch (a)
00712 {
00713
00714 case 1:
00715 std::cerr << std::endl << "Base Weights" << std::endl;
00716 for (int i = 0; i < num_rows; i++)
00717 {
00718 for (int j = 0; j < num_columns; j++)
00719 {
00720 std::cerr << weight_array[i][j] << " | ";
00721 }
00722 std::cerr << std::endl;
00723 }
00724 std::cerr << std::endl;
00725 break;
00726
00727
00728 case 2:
00729 std::cerr << std::endl << "Current Weights" << std::endl;
00730 for (int i = 0; i < num_rows; i++)
00731 {
00732 for (int j = 0; j < num_columns; j++)
00733 {
00734 std::cerr << cell_array[i][j].weight << " | ";
00735 }
00736 std::cerr << std::endl;
00737 }
00738 std::cerr << std::endl;
00739 break;
00740
00741
00742 case 3:
00743 std::cerr << std::endl << "Starred values" << std::endl;
00744 for (int i = 0; i < num_rows; i++)
00745 {
00746 for (int j = 0; j < num_columns; j++)
00747 {
00748 if (cell_array[i][j].starred == true)
00749 {
00750 std::cerr << cell_array[i][j].weight << "* | ";
00751 }
00752 else
00753 {
00754 std::cerr << cell_array[i][j].weight << " | ";
00755 }
00756 }
00757 std::cerr << std::endl;
00758 }
00759 std::cerr << std::endl;
00760 break;
00761
00762
00763 case 4:
00764 std::cerr << std::endl << "Starred values and Lines" << std::endl;
00765 for (int i = 0; i < num_rows; i++)
00766 {
00767 for (int j = 0; j < num_columns; j++)
00768 {
00769 if (cell_array[i][j].starred == true)
00770 {
00771 std::cerr << cell_array[i][j].weight << "* | ";
00772 }
00773 else
00774 {
00775 std::cerr << cell_array[i][j].weight << " | ";
00776 }
00777 }
00778
00779 if (row_cov[i])
00780 {
00781 std::cerr << " X";
00782 }
00783 std::cerr << std::endl;
00784 }
00785
00786 for (int i = 0; i < num_columns; i++)
00787 {
00788 if (column_cov[i])
00789 {
00790
00791 std::cerr << "X | ";
00792 }
00793 else
00794 {
00795 std::cerr << " | ";
00796 }
00797 }
00798 std::cerr << std::endl;
00799 break;
00800
00801
00802 case 5:
00803 std::cerr << std::endl << "Primed values and Lines" << std::endl;
00804 for (int i = 0; i < num_rows; i++)
00805 {
00806 for (int j = 0; j < num_columns; j++)
00807 {
00808 if (cell_array[i][j].primed == true)
00809 {
00810 std::cerr << cell_array[i][j].weight << "' | ";
00811 }
00812 else
00813 {
00814 std::cerr << cell_array[i][j].weight << " | ";
00815 }
00816 }
00817
00818 if (row_cov[i])
00819 {
00820 std::cerr << " X";
00821 }
00822 std::cerr << std::endl;
00823 }
00824
00825 for (int i = 0; i < num_columns; i++)
00826 {
00827 if (column_cov[i])
00828 {
00829
00830 std::cerr << "X | ";
00831 }
00832 else
00833 {
00834 std::cerr << " | ";
00835 }
00836 }
00837 std::cerr << std::endl;
00838 break;
00839
00840
00841 case 6:
00842 std::cerr << std::endl << "Starred values and Lines" << std::endl;
00843 for (int i = 0; i < num_rows; i++)
00844 {
00845 for (int j = 0; j < num_columns; j++)
00846 {
00847 if (cell_array[i][j].starred == true)
00848 {
00849 std::cerr << cell_array[i][j].weight << "* | ";
00850 }
00851 else if (cell_array[i][j].primed == true)
00852 {
00853 std::cerr << cell_array[i][j].weight << "' | ";
00854 }
00855 else
00856 {
00857 std::cerr << cell_array[i][j].weight << " | ";
00858 }
00859 }
00860
00861 if (row_cov[i])
00862 {
00863 std::cerr << " X";
00864 }
00865
00866 else
00867 {
00868 std::cerr << " ";
00869 }
00870 if (row_starred[i])
00871 {
00872 std::cerr << " *";
00873 }
00874 std::cerr << std::endl;
00875 }
00876
00877 for (int i = 0; i < num_columns; i++)
00878 {
00879 if (column_cov[i])
00880 {
00881
00882 std::cerr << "X | ";
00883 }
00884 else
00885 {
00886 std::cerr << " | ";
00887 }
00888 }
00889 std::cerr << std::endl;
00890
00891 for (int i = 0; i < num_columns; i++)
00892 {
00893 if (column_starred[i])
00894 {
00895
00896 std::cerr << "* | ";
00897 }
00898 else
00899 {
00900 std::cerr << " | ";
00901 }
00902 }
00903 std::cerr << std::endl;
00904 break;
00905
00906 default:
00907 break;
00908 }
00909 }