39 #include <visp3/core/vpMunkres.h>
42 #if ((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
47 #ifndef DOXYGEN_SHOULD_SKIP_THIS
52 ostream &operator<<(ostream &os,
const pair<unsigned int, unsigned int> &val)
54 os <<
"[" << val.first <<
"," << val.second <<
"]";
60 #ifdef VISP_HAVE_CATCH2
61 #define CATCH_CONFIG_RUNNER
64 #ifdef ENABLE_VISP_NAMESPACE
68 TEST_CASE(
"Check Munkres-based assignment",
"[visp_munkres]")
70 auto testMunkres = [](
const std::vector<std::vector<double> > &cost_matrix,
71 const std::vector<std::pair<unsigned int, unsigned int> > &expected_pairs) {
72 const auto munkres_pairs = vpMunkres::run(cost_matrix);
73 REQUIRE(expected_pairs.size() == munkres_pairs.size());
74 for (
auto i = 0u; i < munkres_pairs.size(); i++) {
75 REQUIRE(expected_pairs.at(i) == munkres_pairs.at(i));
79 SECTION(
"Square cost matrix")
81 std::vector<std::vector<double> > costs {};
82 costs.push_back(std::vector<double>{3, 1, 2});
83 costs.push_back(std::vector<double>{2, 3, 1});
84 costs.push_back(std::vector<double>{1, 2, 3});
86 std::vector<std::pair<unsigned int, unsigned int> > expected_pairs {};
87 expected_pairs.emplace_back(0, 1);
88 expected_pairs.emplace_back(1, 2);
89 expected_pairs.emplace_back(2, 0);
91 testMunkres(costs, expected_pairs);
94 SECTION(
"Horizontal cost matrix")
96 std::vector<std::vector<double> > costs {};
97 costs.push_back(std::vector<double>{4, 1, 2, 3});
98 costs.push_back(std::vector<double>{3, 4, 1, 2});
99 costs.push_back(std::vector<double>{2, 3, 4, 1});
101 std::vector<std::pair<unsigned int, unsigned int> > expected_pairs {};
102 expected_pairs.emplace_back(0, 1);
103 expected_pairs.emplace_back(1, 2);
104 expected_pairs.emplace_back(2, 3);
106 testMunkres(costs, expected_pairs);
109 SECTION(
"Vertical cost matrix")
111 std::vector<std::vector<double> > costs {};
112 costs.push_back(std::vector<double>{4, 1, 2});
113 costs.push_back(std::vector<double>{3, 4, 1});
114 costs.push_back(std::vector<double>{2, 3, 4});
115 costs.push_back(std::vector<double>{1, 2, 3});
117 std::vector<std::pair<unsigned int, unsigned int> > expected_pairs {};
118 expected_pairs.emplace_back(0, 1);
119 expected_pairs.emplace_back(1, 2);
120 expected_pairs.emplace_back(3, 0);
122 testMunkres(costs, expected_pairs);
126 int main(
int argc,
char *argv[])
128 Catch::Session session;
129 session.applyCommandLine(argc, argv);
131 return session.run();
136 bool testMunkres(
const std::vector<std::vector<double> > &costs_matrix,
137 const std::vector<std::pair<unsigned int, unsigned int> > &expected_pairs)
139 const auto pairs = vpMunkres::run(costs_matrix);
141 if (pairs.size() != expected_pairs.size()) {
143 std::cerr <<
"Expected nb of association | Munkres nb of association: "
144 << expected_pairs.size() <<
" | " << pairs.size()
150 for (
auto i = 0u; i < pairs.size(); i++) {
151 if (expected_pairs.at(i) != pairs.at(i)) {
154 std::cout <<
"Cost matrix:" << std::endl;
155 for (
const auto &cost_row : costs_matrix) {
157 for (
const auto &cost : cost_row) {
158 std::cout << cost <<
" | ";
160 std::cout << std::endl;
162 std::cout << std::endl;
165 std::cerr <<
"FAIL: "
166 <<
"Expected association | Munkres association: " << expected_pairs.at(i) <<
" | " << pairs.at(i)
178 std::vector<std::vector<double> > costs {};
179 costs.push_back(std::vector<double>{3, 4, 1, 2});
180 costs.push_back(std::vector<double>{3, 4, 2, 1});
181 costs.push_back(std::vector<double>{1, 2, 3, 4});
182 costs.push_back(std::vector<double>{2, 1, 4, 3});
184 std::vector<std::pair<unsigned int, unsigned int> > pairs {};
185 pairs.emplace_back(0, 2);
186 pairs.emplace_back(1, 3);
187 pairs.emplace_back(2, 0);
188 pairs.emplace_back(3, 1);
190 return testMunkres(costs, pairs);
195 std::vector<std::vector<double> > costs {};
196 costs.push_back(std::vector<double>{3, 2, 1});
197 costs.push_back(std::vector<double>{4, 3, 2});
198 costs.push_back(std::vector<double>{1, 4, 3});
199 costs.push_back(std::vector<double>{2, 1, 4});
201 std::vector<std::pair<unsigned int, unsigned int> > pairs {};
202 pairs.emplace_back(0, 2);
203 pairs.emplace_back(2, 0);
204 pairs.emplace_back(3, 1);
206 return testMunkres(costs, pairs);
211 std::vector<std::vector<double> > costs {};
212 costs.push_back(std::vector<double>{2, 3, 4, 1});
213 costs.push_back(std::vector<double>{4, 1, 2, 3});
214 costs.push_back(std::vector<double>{1, 2, 3, 4});
216 std::vector<std::pair<unsigned int, unsigned int> > pairs {};
217 pairs.emplace_back(0, 3);
218 pairs.emplace_back(1, 1);
219 pairs.emplace_back(2, 0);
221 return testMunkres(costs, pairs);
226 if (not testSquareMat()) {
230 if (not testVertMat()) {
234 if (not testHorMat()) {
243 int main() {
return EXIT_SUCCESS; }