41 #include <visp3/core/vpMunkres.h> 43 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) && \ 44 (!defined(_MSC_VER) || ( (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) && (_MSC_VER >= 1911) ) ) 53 ostream &operator<<(ostream &os, const pair<unsigned int, unsigned int> &val)
55 os <<
"[" << val.first <<
"," << val.second <<
"]";
60 #ifdef VISP_HAVE_CATCH2 61 #define CATCH_CONFIG_RUNNER 64 TEST_CASE(
"Check Munkres-based assignment",
"[visp_munkres]")
66 auto testMunkres = [](
const std::vector<std::vector<double> > &cost_matrix,
67 const std::vector<std::pair<unsigned int, unsigned int> > &expected_pairs) {
69 REQUIRE(expected_pairs.size() == munkres_pairs.size());
70 for (
auto i = 0u; i < munkres_pairs.size(); i++) {
71 REQUIRE(expected_pairs.at(i) == munkres_pairs.at(i));
75 SECTION(
"Square cost matrix")
77 std::vector<std::vector<double> > costs{};
78 costs.push_back(std::vector<double>{3, 1, 2});
79 costs.push_back(std::vector<double>{2, 3, 1});
80 costs.push_back(std::vector<double>{1, 2, 3});
82 std::vector<std::pair<unsigned int, unsigned int> > expected_pairs{};
83 expected_pairs.emplace_back(0, 1);
84 expected_pairs.emplace_back(1, 2);
85 expected_pairs.emplace_back(2, 0);
87 testMunkres(costs, expected_pairs);
90 SECTION(
"Horizontal cost matrix")
92 std::vector<std::vector<double> > costs{};
93 costs.push_back(std::vector<double>{4, 1, 2, 3});
94 costs.push_back(std::vector<double>{3, 4, 1, 2});
95 costs.push_back(std::vector<double>{2, 3, 4, 1});
97 std::vector<std::pair<unsigned int, unsigned int> > expected_pairs{};
98 expected_pairs.emplace_back(0, 1);
99 expected_pairs.emplace_back(1, 2);
100 expected_pairs.emplace_back(2, 3);
102 testMunkres(costs, expected_pairs);
105 SECTION(
"Vertical cost matrix")
107 std::vector<std::vector<double> > costs{};
108 costs.push_back(std::vector<double>{4, 1, 2});
109 costs.push_back(std::vector<double>{3, 4, 1});
110 costs.push_back(std::vector<double>{2, 3, 4});
111 costs.push_back(std::vector<double>{1, 2, 3});
113 std::vector<std::pair<unsigned int, unsigned int> > expected_pairs{};
114 expected_pairs.emplace_back(0, 1);
115 expected_pairs.emplace_back(1, 2);
116 expected_pairs.emplace_back(3, 0);
118 testMunkres(costs, expected_pairs);
122 int main(
int argc,
char *argv[])
124 Catch::Session session;
125 session.applyCommandLine(argc, argv);
127 return session.run();
132 bool testMunkres(
const std::vector<std::vector<double> > &costs_matrix,
133 const std::vector<std::pair<unsigned int, unsigned int> > &expected_pairs)
137 if (pairs.size() != expected_pairs.size()) {
139 std::cerr <<
"Expected nb of association | Munkres nb of association: " 140 << expected_pairs.size() <<
" | " << pairs.size()
146 for (
auto i = 0u; i < pairs.size(); i++) {
147 if (expected_pairs.at(i) != pairs.at(i)) {
150 std::cout <<
"Cost matrix:" << std::endl;
151 for (
const auto &cost_row : costs_matrix) {
153 for (
const auto &cost : cost_row) {
154 std::cout << cost <<
" | ";
156 std::cout << std::endl;
158 std::cout << std::endl;
161 std::cerr <<
"FAIL: " 162 <<
"Expected association | Munkres association: " << expected_pairs.at(i) <<
" | " << pairs.at(i)
174 std::vector<std::vector<double> > costs{};
175 costs.push_back(std::vector<double>{3, 4, 1, 2});
176 costs.push_back(std::vector<double>{3, 4, 2, 1});
177 costs.push_back(std::vector<double>{1, 2, 3, 4});
178 costs.push_back(std::vector<double>{2, 1, 4, 3});
180 std::vector<std::pair<unsigned int, unsigned int> > pairs{};
181 pairs.emplace_back(0, 2);
182 pairs.emplace_back(1, 3);
183 pairs.emplace_back(2, 0);
184 pairs.emplace_back(3, 1);
186 return testMunkres(costs, pairs);
191 std::vector<std::vector<double> > costs{};
192 costs.push_back(std::vector<double>{3, 2, 1});
193 costs.push_back(std::vector<double>{4, 3, 2});
194 costs.push_back(std::vector<double>{1, 4, 3});
195 costs.push_back(std::vector<double>{2, 1, 4});
197 std::vector<std::pair<unsigned int, unsigned int> > pairs{};
198 pairs.emplace_back(0, 2);
199 pairs.emplace_back(2, 0);
200 pairs.emplace_back(3, 1);
202 return testMunkres(costs, pairs);
207 std::vector<std::vector<double> > costs{};
208 costs.push_back(std::vector<double>{2, 3, 4, 1});
209 costs.push_back(std::vector<double>{4, 1, 2, 3});
210 costs.push_back(std::vector<double>{1, 2, 3, 4});
212 std::vector<std::pair<unsigned int, unsigned int> > pairs{};
213 pairs.emplace_back(0, 3);
214 pairs.emplace_back(1, 1);
215 pairs.emplace_back(2, 0);
217 return testMunkres(costs, pairs);
222 if (not testSquareMat()) {
226 if (not testVertMat()) {
230 if (not testHorMat()) {
239 int main() {
return EXIT_SUCCESS; }
static std::vector< std::pair< unsigned int, unsigned int > > run(std::vector< std::vector< Type > > costs)