.. _program_listing_file_src_munkres.hpp: Program Listing for File munkres.hpp ==================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/munkres.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* This file is part of brille. Copyright © 2019,2020 Greg Tucker brille is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. brille is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with brille. If not, see . */ #ifndef BRILLE_MUNKRES_H_ #define BRILLE_MUNKRES_H_ #include #include #include #include namespace brille::assignment { enum marker { NORMAL, STARED, PRIMED, }; template class Munkres{ private: size_t N; std::vector cost; std::vector mask; int step; std::vector rowcover; std::vector colcover; size_t stored_row; size_t stored_col; bool finished; public: Munkres(size_t n, std::vector cmat = std::vector()) : N(n), cost(cmat), step(1){ if (cost.size()0) ? false : true; while (!done) { // show(); switch (step) { case 1: step_one(); break; case 2: step_two(); break; case 3: step_three(); break; case 4: step_four(); break; case 5: step_five(); break; case 6: step_six(); break; case 7: finished=true; done=true; break; default: done=true; } } return finished; } std::vector& get_cost(void){ return cost;} const std::vector& get_cost(void) const { return cost; } bool get_assignment(size_t* out){ if (!finished) run_assignment(); if (finished){ for (size_t r=0; r= N) ? 7 : 4; } void step_four(){ // Find a noncovered zero and prime it. If there is no starred zero in the // row containing this primed zero, go to step 5. // Otherwise, cover this row and uncover the column containing the starred // zero. Continue in this manner until there are no uncovered zeros left. // Save the smallest uncovered value and go to step 6. long long row = -1; long long col = -1; bool done = false; while (!done){ find_a_zero(row,col); if (row < 0){ done = true; step = 6; } else { size_t r = (size_t)row; size_t c = (size_t)col; mask[r*N+c] = marker::PRIMED; col = get_col_of_star_in_row(row); if (col>=0) { c = (size_t)col; rowcover[r] = 1; colcover[c] = 0; } else { done = true; step = 5; stored_row = r; stored_col = c; } } } } void step_five(){ // Construct a series of alternating primed and starred zeros as follows: // Let Z0 represent the uncovered primed zero found in step 4. // Let Z1 denote the starred zero in the column of Z0 (if any). // Let Z2 denote the primed zero in the row of Z1 (always present if Z1 exists) // Continue until the series terminates at a primed zero that has no starred // zero in its column. // Unstar each starred zero of the series. // Star each primed zero of the series. // Erase all primes and uncover every line in the matrix. // Return to step three. // path contains pairs of row/column values where we have found // either a star or a prime that is part of the alternating sequence. std::forward_list> path {{stored_row, stored_col}}; size_t rowcol[2] = {0,stored_col}; // the starting point is a PRIMED (found previously in step 4). const marker whichmark[2] = {marker::STARED, marker::PRIMED}; // starting with i=0 --> we look first along a row for a STARED zero. for (size_t i=0; rowcol[i]::max)(); for (size_t r=0; r