26#ifndef OR_TOOLS_GRAPH_PERFECT_MATCHING_H_
27#define OR_TOOLS_GRAPH_PERFECT_MATCHING_H_
35#include "absl/base/attributes.h"
61 void Reset(
int num_nodes);
103 DCHECK(optimal_solution_found_);
104 return optimal_cost_;
110 DCHECK(optimal_solution_found_);
111 return matches_[node];
114 DCHECK(optimal_solution_found_);
119 std::unique_ptr<BlossomGraph> graph_;
125 bool optimal_solution_found_ =
false;
126 int64_t optimal_cost_ = 0;
127 int64_t maximum_edge_cost_ = 0;
128 std::vector<int> matches_;
352 int NumMatched()
const {
return nodes_.size() - unmatched_nodes_.size(); }
408 void AppendNodePathToRoot(
NodeIndex n, std::vector<NodeIndex>* path)
const;
421 return root_blossom_node_[
edge.
tail];
424 return root_blossom_node_[
edge.
head];
439 DCHECK_EQ(node, Tail(
edge));
448 const std::vector<NodeIndex>& SubNodes(
NodeIndex n);
451 bool is_initialized_ =
false;
466 std::vector<NodeIndex> subnodes_;
472 std::vector<NodeIndex> unmatched_nodes_;
475 std::vector<EdgeIndex> primal_update_edge_queue_;
476 std::vector<EdgeIndex> possible_shrink_;
481 std::vector<Edge*> tmp_all_tops_;
488 int64_t num_grows_ = 0;
489 int64_t num_augments_ = 0;
490 int64_t num_shrinks_ = 0;
491 int64_t num_expands_ = 0;
492 int64_t num_dual_updates_ = 0;
void AddEdge(NodeIndex tail, NodeIndex head, CostValue cost)
Same comment as MinCostPerfectMatching::AddEdgeWithCost() applies.
std::string DebugString() const
void UpdateAllTrees(CostValue delta)
CostValue DualObjective() const
void Augment(EdgeIndex e)
void ExpandAllBlossoms()
This must be called at the end of the algorithm to recover the matching.
void DisplayStats() const
Display to VLOG(1) some statistic about the solve.
CostValue ComputeMaxCommonTreeDualDeltaAndResetPrimalEdgeQueue()
DEFINE_INT_TYPE(NodeIndex, int)
Typed index used by this class.
bool DebugDualsAreFeasible() const
const Edge & GetEdge(int e) const
CostValue Slack(const Edge &edge) const
Return the "slack" of the given edge.
NodeIndex Match(NodeIndex n) const
void DebugUpdateNodeDual(NodeIndex n, CostValue delta)
int NumMatched() const
Returns the current number of matched nodes.
BlossomGraph(int num_nodes)
Creates a BlossomGraph on the given number of nodes.
void DebugCheckNoPossiblePrimalUpdates()
std::string NodeDebugString(NodeIndex n) const
Display information for debugging.
static const EdgeIndex kNoEdgeIndex
const Node & GetNode(int n) const
std::string EdgeDebugString(EdgeIndex e) const
bool DebugEdgeIsTightAndExternal(const Edge &edge) const
static const NodeIndex kNoNodeIndex
CostValue Dual(const Node &node) const
Returns the dual value of the given node (which might be a pseudo-node).
void Expand(NodeIndex to_expand)
Expands a Blossom into its component.
DEFINE_INT_TYPE(EdgeIndex, int)
bool NodeIsMatched(NodeIndex n) const
ABSL_MUST_USE_RESULT bool Initialize()
DEFINE_INT_TYPE(CostValue, int64_t)
void Grow(EdgeIndex e, NodeIndex tail, NodeIndex head)
static const CostValue kMaxCostValue
int Match(int node) const
void Reset(int num_nodes)
void AddEdgeWithCost(int tail, int head, int64_t cost)
int64_t OptimalCost() const
@ INFEASIBLE
There is no perfect matching in this graph.
@ OPTIMAL
A perfect matching with min-cost has been found.
const std::vector< int > & Matches() const
ABSL_MUST_USE_RESULT Status Solve()
MinCostPerfectMatching(int num_nodes)
In SWIG mode, we don't want anything besides these top-level includes.
An undirected edge between two nodes: tail <-> head.
CostValue pseudo_slack
See the formula is Slack() used to derive the true slack of this edge.
bool operator>(const Edge &other) const
void SetHeapIndex(int index)
NodeIndex OtherEnd(NodeIndex n) const
Returns the "other" end of this edge.
Edge(NodeIndex t, NodeIndex h, CostValue c)
CostValue slack
We only maintain this in debug mode.
CostValue dual
The true dual of this node. We only maintain this in debug mode.
bool is_internal
Whether this node is part of a blossom.
CostValue saved_pseudo_dual
std::vector< NodeIndex > saved_blossom
std::vector< NodeIndex > blossom
CostValue tree_dual_delta