42 #include <visp3/core/vpConfig.h> 44 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) && \ 45 (!defined(_MSC_VER) || ( (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) && (_MSC_VER >= 1911) ) ) 68 template <
typename Type>
69 static std::vector<std::pair<unsigned int, unsigned int> > run(std::vector<std::vector<Type> > costs);
72 enum ZERO_T :
unsigned int;
73 enum STEP_T :
unsigned int;
76 template <
typename Type>
static void padCostMatrix(std::vector<std::vector<Type> > &costs);
79 template <
typename Type>
80 static std::optional<std::pair<unsigned int, unsigned int> > findAZero(
const std::vector<std::vector<Type> > &costs,
81 const std::vector<bool> &row_cover,
82 const std::vector<bool> &col_cover);
83 static std::optional<unsigned int> findStarInRow(
const std::vector<std::vector<ZERO_T> > &mask,
84 const unsigned int &row);
85 static std::optional<unsigned int> findStarInCol(
const std::vector<std::vector<ZERO_T> > &mask,
86 const unsigned int &col);
87 static std::optional<unsigned int> findPrimeInRow(
const std::vector<std::vector<ZERO_T> > &mask,
88 const unsigned int &row);
89 template <
typename Type>
90 static Type findSmallest(
const std::vector<std::vector<Type> > &costs,
const std::vector<bool> &row_cover,
91 const std::vector<bool> &col_cover);
94 static void augmentPath(std::vector<std::vector<ZERO_T> > &mask,
95 const std::vector<std::pair<unsigned int, unsigned int> > &path);
96 static void clearCovers(std::vector<bool> &row_cover, std::vector<bool> &col_cover);
97 static void erasePrimes(std::vector<std::vector<ZERO_T> > &mask);
100 template <
typename Type>
static STEP_T stepOne(std::vector<std::vector<Type> > &costs);
101 template <
typename Type>
102 static STEP_T stepTwo(std::vector<std::vector<Type> > &costs, std::vector<std::vector<ZERO_T> > &mask,
103 std::vector<bool> &row_cover, std::vector<bool> &col_cover);
104 static STEP_T stepThree(
const std::vector<std::vector<ZERO_T> > &mask, std::vector<bool> &col_cover);
105 template <
typename Type>
106 static std::tuple<STEP_T, std::optional<std::pair<unsigned int, unsigned int> > >
107 stepFour(
const std::vector<std::vector<Type> > &costs, std::vector<std::vector<ZERO_T> > &mask,
108 std::vector<bool> &row_cover, std::vector<bool> &col_cover);
109 static STEP_T stepFive(std::vector<std::vector<ZERO_T> > &mask,
const std::pair<unsigned int, unsigned int> &path_0,
110 std::vector<bool> &row_cover, std::vector<bool> &col_cover);
111 template <
typename Type>
112 static STEP_T stepSix(std::vector<std::vector<Type> > &costs,
const std::vector<bool> &row_cover,
113 const std::vector<bool> &col_cover);
116 static constexpr
auto ZeroEpsilon{1e-6};
121 enum vpMunkres::STEP_T :
unsigned int { ENTRY = 0, ONE = 1, TWO = 2, THREE = 3, FOUR = 4, FIVE = 5, SIX = 6, DONE };
128 template <
typename Type>
inline void vpMunkres::padCostMatrix(std::vector<std::vector<Type> > &costs)
130 const auto row_input_size = costs.size();
131 const auto col_input_size = costs.at(0).size();
133 if (row_input_size > col_input_size) {
134 for (
auto &vec : costs)
135 vec.resize(row_input_size, 0);
138 while (costs.size() < col_input_size) {
139 costs.emplace_back(col_input_size, 0);
151 template <
typename Type>
152 inline std::optional<std::pair<unsigned int, unsigned int> >
153 vpMunkres::findAZero(
const std::vector<std::vector<Type> > &costs,
const std::vector<bool> &row_cover,
154 const std::vector<bool> &col_cover)
156 for (
auto row = 0u; row < costs.size(); row++)
157 for (
auto col = 0u; col < costs.size(); col++)
158 if (
vpMath::equal(costs.at(row).at(col),
static_cast<Type
>(vpMunkres::ZeroEpsilon)) && !row_cover.at(row) &&
159 !col_cover.at(col)) {
160 return std::make_optional<std::pair<unsigned int, unsigned int> >(row, col);
174 template <
typename Type>
175 inline Type vpMunkres::findSmallest(
const std::vector<std::vector<Type> > &costs,
const std::vector<bool> &row_cover,
176 const std::vector<bool> &col_cover)
178 auto minval = std::numeric_limits<Type>::max();
179 for (
auto row = 0u; row < costs.size(); row++)
180 for (
auto col = 0u; col < costs.size(); col++)
181 if (minval > costs.at(row).at(col) && !row_cover.at(row) && !col_cover.at(col)) {
182 minval = costs.at(row).at(col);
196 template <
typename Type>
inline vpMunkres::STEP_T vpMunkres::stepOne(std::vector<std::vector<Type> > &costs)
199 std::for_each(begin(costs), end(costs), [](
auto &cost_row) {
200 const auto min_in_row = *std::min_element(begin(cost_row), end(cost_row));
201 std::transform(begin(cost_row), end(cost_row), begin(cost_row),
202 [&min_in_row](
auto &cost) {
return cost - min_in_row; });
206 for (
auto col = 0u; col < costs.size(); ++col) {
207 auto minval = std::numeric_limits<Type>::max();
208 for (
const auto &cost_row : costs) {
209 minval = std::min(minval, cost_row.at(col));
212 for (
auto &cost_row : costs) {
213 cost_row.at(col) -= minval;
231 template <
typename Type>
233 std::vector<std::vector<vpMunkres::ZERO_T> > &mask,
234 std::vector<bool> &row_cover, std::vector<bool> &col_cover)
236 for (
auto row = 0u; row < costs.size(); row++) {
237 for (
auto col = 0u; col < costs.size(); col++) {
238 if (
vpMath::equal(costs.at(row).at(col),
static_cast<Type
>(vpMunkres::ZeroEpsilon)) && !row_cover.at(row) &&
239 !col_cover.at(col)) {
240 mask.at(row).at(col) = vpMunkres::ZERO_T::STARRED;
241 row_cover.at(row) =
true;
242 col_cover.at(col) =
true;
248 clearCovers(row_cover, col_cover);
264 template <
typename Type>
265 inline std::tuple<vpMunkres::STEP_T, std::optional<std::pair<unsigned int, unsigned int> > >
266 vpMunkres::stepFour(
const std::vector<std::vector<Type> > &costs, std::vector<std::vector<vpMunkres::ZERO_T> > &mask,
267 std::vector<bool> &row_cover, std::vector<bool> &col_cover)
269 if (
const auto zero = findAZero(costs, row_cover, col_cover)) {
270 const auto [row, col] = *zero;
271 mask.at(row).at(col) = vpMunkres::ZERO_T::PRIMED;
273 if (
const auto star_in_row = findStarInRow(mask, row)) {
274 row_cover.at(row) =
true;
275 col_cover.at(*star_in_row) =
false;
278 return {
vpMunkres::STEP_T(5), std::make_optional<std::pair<unsigned int, unsigned int> >(row, col)};
294 template <
typename Type>
295 inline vpMunkres::STEP_T vpMunkres::stepSix(std::vector<std::vector<Type> > &costs,
const std::vector<bool> &row_cover,
296 const std::vector<bool> &col_cover)
298 const auto minval = findSmallest(costs, row_cover, col_cover);
299 for (
auto row = 0u; row < costs.size(); row++) {
300 for (
auto col = 0u; col < costs.size(); col++) {
301 if (row_cover.at(row)) {
302 costs.at(row).at(col) += minval;
305 if (!col_cover.at(col)) {
306 costs.at(row).at(col) -= minval;
320 template <
typename Type>
321 inline std::vector<std::pair<unsigned int, unsigned int> >
vpMunkres::run(std::vector<std::vector<Type> > costs)
323 const auto original_row_size = costs.size();
324 const auto original_col_size = costs.front().size();
325 const auto sq_size = std::max(original_row_size, original_col_size);
327 auto mask = std::vector<std::vector<vpMunkres::ZERO_T> >(
328 sq_size, std::vector<vpMunkres::ZERO_T>(sq_size, vpMunkres::ZERO_T::NA));
329 auto row_cover = std::vector<bool>(sq_size,
false);
330 auto col_cover = std::vector<bool>(sq_size,
false);
332 std::optional<std::pair<unsigned int, unsigned int> > path_0{std::nullopt};
334 auto step{vpMunkres::STEP_T::ENTRY};
335 while (step != vpMunkres::STEP_T::DONE) {
337 case vpMunkres::STEP_T::ENTRY:
338 padCostMatrix(costs);
342 step = stepOne(costs);
345 step = stepTwo(costs, mask, row_cover, col_cover);
348 step = stepThree(mask, col_cover);
351 std::tie(step, path_0) = stepFour(costs, mask, row_cover, col_cover);
354 step = stepFive(mask, *path_0, row_cover, col_cover);
357 step = stepSix(costs, row_cover, col_cover);
359 case vpMunkres::STEP_T::DONE:
366 std::vector<std::pair<unsigned int, unsigned int> > ret{};
367 for (
auto i = 0u; i < original_row_size; i++) {
368 if (
const auto it = std::find(begin(mask.at(i)), end(mask.at(i)), vpMunkres::ZERO_T::STARRED);
369 it != end(mask.at(i))) {
370 if (
const unsigned int j = static_cast<unsigned int>(std::distance(begin(mask.at(i)), it));
371 j < original_col_size) {
372 ret.emplace_back(i, j);
static bool equal(double x, double y, double s=0.001)
static std::vector< std::pair< unsigned int, unsigned int > > run(std::vector< std::vector< Type > > costs)