26#ifndef ORTOOLS_GRAPH_PERFECT_MATCHING_H_
27#define ORTOOLS_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;
414 void AddToDualObjective(
CostValue delta);
421 return root_blossom_node_[edge.tail];
424 return root_blossom_node_[edge.head];
431 return root_blossom_node_[edge.OtherEnd(node)];
439 DCHECK_EQ(node, Tail(edge));
448 const std::vector<NodeIndex>& SubNodes(
NodeIndex n);
451 bool is_initialized_ =
false;
454 util_intops::StrongVector<EdgeIndex, Edge> edges_;
455 util_intops::StrongVector<NodeIndex, Node> nodes_;
459 util_intops::StrongVector<NodeIndex, NodeIndex> root_blossom_node_;
463 util_intops::StrongVector<NodeIndex, std::vector<EdgeIndex>> graph_;
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_;
479 AdjustablePriorityQueue<Edge, std::greater<Edge>> plus_plus_pq_;
480 AdjustablePriorityQueue<Edge, std::greater<Edge>> plus_free_pq_;
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)
std::string DebugString() const
void UpdateAllTrees(CostValue delta)
CostValue DualObjective() const
void Augment(EdgeIndex e)
void DisplayStats() const
CostValue ComputeMaxCommonTreeDualDeltaAndResetPrimalEdgeQueue()
DEFINE_INT_TYPE(NodeIndex, int)
bool DebugDualsAreFeasible() const
const Edge & GetEdge(int e) const
CostValue Slack(const Edge &edge) const
NodeIndex Match(NodeIndex n) const
void DebugUpdateNodeDual(NodeIndex n, CostValue delta)
BlossomGraph(int num_nodes)
void DebugCheckNoPossiblePrimalUpdates()
std::string NodeDebugString(NodeIndex n) const
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
void Expand(NodeIndex to_expand)
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
const std::vector< int > & Matches() const
ABSL_MUST_USE_RESULT Status Solve()
MinCostPerfectMatching(int num_nodes)
BlossomGraph::CostValue CostValue
BlossomGraph::NodeIndex NodeIndex
bool operator>(const Edge &other) const
void SetHeapIndex(int index)
NodeIndex OtherEnd(NodeIndex n) const
Edge(NodeIndex t, NodeIndex h, CostValue c)
CostValue saved_pseudo_dual
std::vector< NodeIndex > saved_blossom
std::vector< NodeIndex > blossom
CostValue tree_dual_delta