diff --git a/doc/maximum_weighted_matching.html b/doc/maximum_weighted_matching.html
index 32e60799..79d934e6 100644
--- a/doc/maximum_weighted_matching.html
+++ b/doc/maximum_weighted_matching.html
@@ -21,7 +21,7 @@ void maximum_weighted_matching(const Graph& g, MateMap mate);
template <typename Graph, typename MateMap, typename VertexIndexMap>
void maximum_weighted_matching(const Graph& g, MateMap mate, VertexIndexMap vm);
-template <typename Graph, typename MateMap, typename VertexIndexMap, typename EdgeWeightMap, bool Verify = true>
+template <typename Graph, typename MateMap, typename VertexIndexMap, typename EdgeWeightMap>
void maximum_weighted_matching(const Graph& g, MateMap mate, VertexIndexMap vm, EdgeWeightMap weights);
template <typename Graph, typename MateMap>
@@ -121,13 +121,6 @@ If edge weights are integers, the algorithm uses only integer computations.
This is achieved by internally multiplying edge weights by 2, which ensures that all dual variables are also integers.
-
-After computing the maximum matching, a verification step may be performed to check that the matching is optimal.
-The verification step is simpler and faster (O(V2)) than the search for the matching.
-It always succeeds unless there is a bug in the matching algorithm.
-Since verification checks for exact optimality, it can only be used if edge weights are integers.
-
-
In addition, a brute-force implementation brute_force_maximum_weighted_matching is provided.
This algorithm simply searches all possible matchings and selects one with the maximum weight sum.
diff --git a/include/boost/graph/maximum_weighted_matching.hpp b/include/boost/graph/maximum_weighted_matching.hpp
index 0135cf8e..a3e10d4e 100644
--- a/include/boost/graph/maximum_weighted_matching.hpp
+++ b/include/boost/graph/maximum_weighted_matching.hpp
@@ -24,7 +24,6 @@
#include
#include
#include
-#include
#include // for std::tie
#include // for std::pair, std::swap
#include
@@ -1405,235 +1404,6 @@ struct maximum_weighted_matching_context
for (vertex_t x : make_iterator_range(vertices(g)))
put(mate, x, vertex_mate[x]);
}
-
- /** Check that the array "vertex_mate" is consistent. */
- bool verify_vertex_mate()
- {
- vertices_size_t num_matched_vertex = 0;
- for (vertex_t x : make_iterator_range(vertices(g)))
- {
- vertex_t y = vertex_mate[x];
- if (y != null_vertex)
- {
- ++num_matched_vertex;
- if (vertex_mate[y] != x)
- return false;
- }
- }
-
- edges_size_t num_matched_edge = 0;
- for (const edge_t& e : make_iterator_range(edges(g)))
- {
- if (vertex_mate[source(e, g)] == target(e, g))
- ++num_matched_edge;
- }
-
- return num_matched_vertex == 2 * num_matched_edge;
- }
-
- /**
- * Verify that vertex dual variables are non-negative,
- * and all unmatched vertices have zero dual.
- */
- bool verify_vertex_duals()
- {
- for (vertex_t x : make_iterator_range(vertices(g)))
- {
- if (vertex_dual[x] < 0)
- return false;
- if ((vertex_mate[x] == null_vertex) && (vertex_dual[x] != 0))
- return false;
- }
- return true;
- }
-
- /** Verify that blossom dual variables are non-negative. */
- bool verify_blossom_duals()
- {
- for (const nontrivial_blossom_t& blossom : nontrivial_blossom)
- {
- if (blossom.dual_var < 0)
- return false;
- }
- return true;
- }
-
- /** Verify slack of edges between trivial blossoms. */
- bool verify_trivial_blossom_edges()
- {
- for (const edge_t& e : make_iterator_range(edges(g)))
- {
- vertex_t x = source(e, g);
- vertex_t y = target(e, g);
- if ((! trivial_blossom[x].parent) && (! trivial_blossom[y].parent))
- {
- weight_t w = weight_factor * get(edge_weights, e);
- weight_t dual_sum = vertex_dual[x] + vertex_dual[y];
- // Edge slack must be non-negative.
- if (w > dual_sum)
- return false;
- // Matched edges must have slack zero.
- if ((vertex_mate[x] == y) && (w != dual_sum))
- return false;
- }
- }
- return true;
- }
-
- /** Verify one top-level blossom and its edges. */
- bool verify_blossom(const nontrivial_blossom_t* blossom)
- {
- // This function recursively descends down the blossom structure.
- // It checks the number of matched edges in every sub-blossom.
- // It also checks the slack of edges contained in this blossom
- // and of edges incident on this blossom.
-
- // For each vertex, deepest level on current recursion path
- // that contains the vertex.
- vertex_map< vertices_size_t > vertex_depth(num_vertices(g), vm);
-
- // At each recursion depth, sum of duals of containing blossoms.
- std::vector< weight_t > path_sum_dual = {0};
-
- // At each recursion depth, number of internally matched vertices.
- std::vector< vertices_size_t > path_num_matched = {0};
-
- // Use an explicit stack to avoid deep call chains.
- using sub_blossom_iterator = typename std::list<
- typename nontrivial_blossom_t::sub_blossom_t >::const_iterator;
- std::stack< std::pair<
- const nontrivial_blossom_t*, sub_blossom_iterator > > stack;
-
- stack.emplace(blossom, blossom->subblossoms.cbegin());
- while (! stack.empty())
- {
- vertices_size_t depth = stack.size();
- blossom = stack.top().first;
- auto subblossom_it = stack.top().second;
-
- if (subblossom_it == blossom->subblossoms.cbegin())
- {
- // Entering a new (sub)-blossom.
- if (blossom->subblossoms.size() < 3) {
- return false;
- }
-
- // Update the depth of vertices in this sub-blossom.
- for_vertices_in_blossom(blossom,
- [&vertex_depth,depth](vertex_t x) {
- vertex_depth[x] = depth;
- });
-
- // Calculate the sum of blossom duals at the new depth.
- path_sum_dual.push_back(
- path_sum_dual.back() + blossom->dual_var);
-
- // Initialize the number of matched edges at the new depth.
- path_num_matched.push_back(0);
- }
-
- if (subblossom_it != blossom->subblossoms.cend())
- {
- // Update the sub-blossom pointer at the current depth.
- ++(stack.top().second);
-
- // Examine a sub-blossom.
- blossom_t* b = subblossom_it->blossom;
- BOOST_ASSERT(b->parent == blossom);
- nontrivial_blossom_t* ntb = b->nontrivial();
- if (ntb)
- {
- // Prepare to descend into the sub-blossom.
- stack.emplace(ntb, ntb->subblossoms.cbegin());
- }
- else
- {
- // Handle single vertex.
- vertex_t x = b->base_vertex;
- for (const edge_t& e : make_iterator_range(out_edges(x, g)))
- {
- BOOST_ASSERT(source(e, g) == x);
- vertex_t y = target(e, g);
- // Find the smallest blossom that contains this edge.
- vertices_size_t edge_depth = vertex_depth[y];
- // Verify edge slack.
- weight_t w = weight_factor * get(edge_weights, e);
- weight_t dual_sum = vertex_dual[x] + vertex_dual[y]
- + path_sum_dual[edge_depth];
- // Edge slack must be non-negative.
- if (w > dual_sum)
- return false;
- // Matched edges must have slack zero.
- if ((vertex_mate[x] == y) && (w != dual_sum))
- return false;
- // Update number of internally matched vertices.
- if ((vertex_mate[x] == y) && (edge_depth > 0))
- path_num_matched[edge_depth] += 1;
- }
- }
- }
- else
- {
- // Leaving the current (sub)-blossom.
- // Count the number of vertices inside this blossom.
- vertices_size_t blossom_num_vertex = 0;
- for_vertices_in_blossom(blossom,
- [&blossom_num_vertex](vertex_t) {
- ++blossom_num_vertex;
- });
-
- // Check that the (sub)-blossom is "full".
- // A blossom is full if all except one of its vertices
- // are matched to another vertex within the blossom.
- vertices_size_t blossom_num_matched = path_num_matched[depth];
- if (blossom_num_vertex != blossom_num_matched + 1)
- return false;
-
- // Update the number of matched edges in the parent blossom.
- path_num_matched[depth - 1] += path_num_matched[depth];
-
- // Restore the depth of vertices.
- for_vertices_in_blossom(blossom,
- [&vertex_depth,depth](vertex_t x) {
- vertex_depth[x] = depth - 1;
- });
-
- // Remove the blossom from the stack.
- path_sum_dual.pop_back();
- path_num_matched.pop_back();
- stack.pop();
- }
- }
-
- return true;
- }
-
- /** Verify blossoms and their edges. */
- bool verify_blossoms()
- {
- // Recursively verify each non-trivial top-level blossom.
- // This takes total time O(V^2).
- for (const nontrivial_blossom_t& blossom : nontrivial_blossom)
- {
- if (! blossom.parent)
- {
- if (! verify_blossom(&blossom))
- return false;
- }
- }
- return true;
- }
-
- /** Verify that the optimum solution has been found. */
- bool verify()
- {
- return (verify_vertex_mate()
- && verify_vertex_duals()
- && verify_blossom_duals()
- && verify_trivial_blossom_edges()
- && verify_blossoms());
- return true;
- }
};
} // namespace detail
@@ -1645,11 +1415,6 @@ struct maximum_weighted_matching_context
* This function takes time O(V^3).
* This function uses memory size O(V + E).
*
- * @tparam Verify True to verify the matching.
- * This is only supported for integer edge weights.
- * Verification will always succeed unless there is a bug
- * in the matching algorithm.
- *
* @param g Input graph.
* The graph type must be a model of VertexListGraph
* and EdgeListGraph and IncidenceGraph.
@@ -1670,7 +1435,7 @@ struct maximum_weighted_matching_context
* @throw boost::bad_graph If the input graph is not valid.
*/
template < typename Graph, typename MateMap, typename VertexIndexMap,
- typename EdgeWeightMap, bool Verify = true >
+ typename EdgeWeightMap >
void maximum_weighted_matching(
const Graph& g, MateMap mate, VertexIndexMap vm, EdgeWeightMap weights)
{
@@ -1695,14 +1460,6 @@ void maximum_weighted_matching(
Graph, VertexIndexMap, EdgeWeightMap >
matching(g, vm, weights);
matching.run();
-
- typedef typename property_traits< EdgeWeightMap >::value_type weight_t;
- if (Verify && std::numeric_limits< weight_t >::is_integer)
- {
- if (! matching.verify())
- throw std::logic_error("Incorrect solution.");
- }
-
matching.extract_matching(mate);
}