Compare commits
10 Commits
3aa2b20a74
...
9cabdce600
Author | SHA1 | Date |
---|---|---|
Joris van Rantwijk | 9cabdce600 | |
Joris van Rantwijk | 327e83e701 | |
Joris van Rantwijk | d8d44f6171 | |
Joris van Rantwijk | 4b7fab3f43 | |
Joris van Rantwijk | 9b064de4d8 | |
Joris van Rantwijk | 9c669f2d03 | |
Joris van Rantwijk | 731b202af3 | |
Joris van Rantwijk | 250fd4ea94 | |
Joris van Rantwijk | a9010855a5 | |
Joris van Rantwijk | dd452f73da |
|
@ -77,3 +77,27 @@ jobs:
|
|||
- name: Run unittests
|
||||
run: python3 python/test_mwmatching.py
|
||||
|
||||
# Run tests on C++ code.
|
||||
test-cpp:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Boost
|
||||
run: sudo apt-get install -y libboost-test-dev
|
||||
- name: Show GCC version
|
||||
run: g++ --version
|
||||
- name: Build mwmatching
|
||||
run: make -C cpp run_matching test_mwmatching
|
||||
- name: Run unittests
|
||||
run: cpp/test_mwmatching
|
||||
- name: Run test graphs
|
||||
run: >
|
||||
python3 tests/run_test.py --solver cpp/run_matching --verify
|
||||
tests/graphs/chain_n1000.edge
|
||||
tests/graphs/chain_n5000.edge
|
||||
tests/graphs/sparse_delta_n1004.edge
|
||||
tests/graphs/triangles_n1002.edge
|
||||
tests/graphs/triangles_n5001.edge
|
||||
tests/graphs/random_n1000_m10000.edge
|
||||
tests/graphs/random_n2000_m10000.edge
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ This repository is probably not the best place if ...
|
|||
test_mwmatching.py : Unit tests
|
||||
run_matching.py : Command-line program to run the matching algorithm
|
||||
|
||||
cpp/
|
||||
mwmatching.h : C++ implementation of maximum weight matching
|
||||
test_mwmatching.cpp : Unit tests
|
||||
run_matching.cpp : Command-line program to run the matching algorithm
|
||||
|
||||
tests/
|
||||
generate/ : Python programs to generate graphs
|
||||
graphs/ : Collection of graphs and matching outputs
|
||||
|
|
1154
cpp/mwmatching.h
1154
cpp/mwmatching.h
File diff suppressed because it is too large
Load Diff
|
@ -363,6 +363,132 @@ BOOST_AUTO_TEST_CASE(test_fail_bad_graph)
|
|||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
||||
/* ********** Test corner cases of maximum_weight_matching() ********** */
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(test_corner_cases)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test1)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 4, 26}, {1, 3, 31}, {1, 4, 49}};
|
||||
Matching expect = {{0, 4}, {1, 3}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test2)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 2, 42}, {0, 4, 36}, {2, 3, 26}};
|
||||
Matching expect = {{0, 4}, {2, 3}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test3)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 4, 43}, {1, 4, 28}, {2, 4, 38}};
|
||||
Matching expect = {{0, 4}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test4)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 50}, {0, 3, 46}, {0, 4, 45}};
|
||||
Matching expect = {{0, 1}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test5)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 35}, {0, 3, 36}, {0, 4, 46}};
|
||||
Matching expect = {{0, 4}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test6)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 50}, {0, 4, 51}, {0, 5, 34}, {1, 2, 43}, {1, 4, 57}, {2, 5, 47}, {3, 4, 17}};
|
||||
Matching expect = {{0, 1}, {2, 5}, {3, 4}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test7)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 34}, {0, 3, 19}, {1, 2, 45}, {1, 3, 30}, {1, 4, 37}, {2, 4, 36}};
|
||||
Matching expect = {{0, 1}, {2, 4}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test8)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 48}, {0, 3, 42}, {0, 4, 57}, {1, 3, 51}, {1, 5, 36}, {2, 3, 23}, {4, 5, 46}};
|
||||
Matching expect = {{0, 1}, {2, 3}, {4, 5}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test9)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 21}, {0, 2, 25}, {1, 4, 40}, {2, 3, 10}, {2, 5, 40}, {3, 5, 31}, {4, 5, 58}};
|
||||
Matching expect = {{0, 2}, {1, 4}, {3, 5}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test10)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 2, 7}, {0, 5, 20}, {1, 2, 50}, {1, 4, 46}, {2, 3, 35}, {2, 4, 8}, {2, 5, 25}, {3, 5, 47}};
|
||||
Matching expect = {{0, 5}, {1, 4}, {2, 3}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test11)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 42}, {0, 2, 60}, {1, 3, 34}, {1, 4, 58}, {1, 5, 52}, {2, 5, 60}, {3, 5, 34}, {4, 5, 57}};
|
||||
Matching expect = {{0, 2}, {1, 4}, {3, 5}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test12)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 23}, {0, 2, 26}, {0, 3, 2}, {0, 4, 41}, {2, 4, 36}};
|
||||
Matching expect = {{0, 1}, {2, 4}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test13)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 3, 58}, {0, 4, 49}, {1, 5, 34}, {2, 3, 22}, {2, 5, 42}, {4, 5, 36}};
|
||||
Matching expect = {{0, 4}, {1, 5}, {2, 3}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test14)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 29}, {0, 3, 35}, {0, 4, 42}, {1, 2, 12}, {2, 4, 29}, {3, 4, 44}};
|
||||
Matching expect = {{0, 1}, {3, 4}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test15)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 4, 53}, {0, 5, 42}, {1, 4, 45}, {2, 4, 59}, {2, 6, 39}, {4, 5, 69}, {4, 6, 52}};
|
||||
Matching expect = {{0, 5}, {1, 4}, {2, 6}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test16)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 2, 13}, {1, 2, 11}, {2, 3, 39}, {2, 4, 17}, {3, 4, 35}};
|
||||
Matching expect = {{0, 2}, {3, 4}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test17)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 48}, {0, 2, 44}, {0, 4, 48}, {1, 4, 36}, {3, 4, 31}};
|
||||
Matching expect = {{0, 2}, {1, 4}};
|
||||
BOOST_TEST(mwmatching::maximum_weight_matching(edges) == expect);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
||||
/* ********** Test adjust_weights_for_maximum_cardinality_matching() ********** */
|
||||
|
||||
template <typename WeightType>
|
||||
|
@ -497,3 +623,129 @@ BOOST_AUTO_TEST_CASE(test41_maxcard)
|
|||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
||||
/* ********** Test verification ********** */
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(test_verification)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_success)
|
||||
{
|
||||
using mwmatching::impl::NO_VERTEX;
|
||||
EdgeVectorLong edges = {{0, 1, 10}, {1, 2, 11}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {NO_VERTEX, 2, 1};
|
||||
ctx.vertex_dual = {0, 20, 2};
|
||||
ctx.nontrivial_blossom.clear();
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_asymmetric_matching)
|
||||
{
|
||||
using mwmatching::impl::NO_VERTEX;
|
||||
EdgeVectorLong edges = {{0, 1, 10}, {1, 2, 11}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {NO_VERTEX, 2, 0};
|
||||
ctx.vertex_dual = {0, 20, 2};
|
||||
ctx.nontrivial_blossom.clear();
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_nonexistent_matched_edge)
|
||||
{
|
||||
using mwmatching::impl::NO_VERTEX;
|
||||
EdgeVectorLong edges = {{0, 1, 10}, {1, 2, 11}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {2, NO_VERTEX, 0};
|
||||
ctx.vertex_dual = {11, 11, 11};
|
||||
ctx.nontrivial_blossom.clear();
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_negative_vertex_dual)
|
||||
{
|
||||
using mwmatching::impl::NO_VERTEX;
|
||||
EdgeVectorLong edges = {{0, 1, 10}, {1, 2, 11}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {NO_VERTEX, 2, 1};
|
||||
ctx.vertex_dual = {-2, 22, 0};
|
||||
ctx.nontrivial_blossom.clear();
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_unmatched_nonzero_dual)
|
||||
{
|
||||
using mwmatching::impl::NO_VERTEX;
|
||||
EdgeVectorLong edges = {{0, 1, 10}, {1, 2, 11}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {NO_VERTEX, 2, 1};
|
||||
ctx.vertex_dual = {9, 11, 11};
|
||||
ctx.nontrivial_blossom.clear();
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_negative_edge_slack)
|
||||
{
|
||||
using mwmatching::impl::NO_VERTEX;
|
||||
EdgeVectorLong edges = {{0, 1, 10}, {1, 2, 11}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {NO_VERTEX, 2, 1};
|
||||
ctx.vertex_dual = {0, 11, 11};
|
||||
ctx.nontrivial_blossom.clear();
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_matched_edge_slack)
|
||||
{
|
||||
using mwmatching::impl::NO_VERTEX;
|
||||
EdgeVectorLong edges = {{0, 1, 10}, {1, 2, 11}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {NO_VERTEX, 2, 1};
|
||||
ctx.vertex_dual = {0, 20, 11};
|
||||
ctx.nontrivial_blossom.clear();
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_negative_blossom_dual)
|
||||
{
|
||||
EdgeVectorLong edges = {{0, 1, 7}, {0, 2, 8}, {1, 2, 9}, {2, 3, 6}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {1, 0, 3, 2};
|
||||
ctx.vertex_dual = {4, 6, 8, 4};
|
||||
mwmatching::impl::Blossom<long> b0(0);
|
||||
mwmatching::impl::Blossom<long> b1(1);
|
||||
mwmatching::impl::Blossom<long> b2(2);
|
||||
ctx.nontrivial_blossom.emplace_back(
|
||||
std::vector<mwmatching::impl::Blossom<long>*>{&b0, &b1, &b2},
|
||||
std::deque<mwmatching::VertexPair>{{0, 1}, {1, 2}, {2, 0}});
|
||||
ctx.nontrivial_blossom.front().dual_var = -2;
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_blossom_not_full)
|
||||
{
|
||||
using mwmatching::impl::NO_VERTEX;
|
||||
EdgeVectorLong edges = {{0, 1, 7}, {0, 2, 2}, {1, 2, 5}, {0, 3, 8}, {1, 4, 8}};
|
||||
mwmatching::impl::MatchingContext<long> ctx(edges);
|
||||
ctx.vertex_mate = {3, 4, NO_VERTEX, 0, 1};
|
||||
ctx.vertex_dual = {4, 10, 0, 12, 6};
|
||||
mwmatching::impl::Blossom<long> b0(0);
|
||||
mwmatching::impl::Blossom<long> b1(1);
|
||||
mwmatching::impl::Blossom<long> b2(2);
|
||||
ctx.nontrivial_blossom.emplace_back(
|
||||
std::vector<mwmatching::impl::Blossom<long>*>{&b0, &b1, &b2},
|
||||
std::deque<mwmatching::VertexPair>{{0, 1}, {1, 2}, {2, 0}});
|
||||
ctx.nontrivial_blossom.front().dual_var = 2;
|
||||
mwmatching::impl::MatchingVerifier<long> verifier(ctx);
|
||||
BOOST_TEST(verifier.verify() == false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
Loading…
Reference in New Issue