Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
assignment.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// Simple interface to solve the linear sum assignment problem. It
15// uses about twice as much memory as directly using the
16// LinearSumAssignment class template, but it is as fast and presents
17// a simpler interface. This is the class you should use in most
18// situations.
19//
20// The assignment problem: Given N "left" nodes and N "right" nodes,
21// and a set of left->right arcs with integer costs, find a perfect
22// matching (i.e., each "left" node is assigned to one "right" node)
23// that minimizes the overall cost.
24//
25// Example usage:
26//
27// #include "ortools/graph/assignment.h"
28//
29// SimpleLinearSumAssignment assignment;
30// for (int arc = 0; arc < num_arcs; ++arc) {
31// assignment.AddArcWithCost(head(arc), tail(arc), cost(arc));
32// }
33// if (assignment.Solve() == SimpleLinearSumAssignment::OPTIMAL) {
34// printf("A perfect matching exists.\n");
35// printf("The best possible cost is %d.\n", assignment.OptimalCost());
36// printf("An optimal assignment is:\n");
37// for (int node = 0; node < assignment.NumNodes(); ++node) {
38// printf("left node %d assigned to right node %d with cost %d.\n",
39// node,
40// assignment.RightMate(node),
41// assignment.AssignmentCost(node));
42// }
43// printf("Note that it may not be the unique optimal assignment.");
44// } else {
45// printf("There is an issue with the input or no perfect matching exists.");
46// }
47
48#ifndef OR_TOOLS_GRAPH_ASSIGNMENT_H_
49#define OR_TOOLS_GRAPH_ASSIGNMENT_H_
50
51#include <cstdint>
52#include <vector>
53
54namespace operations_research {
55
57 public:
58 typedef int32_t NodeIndex;
59 typedef int32_t ArcIndex;
60 typedef int64_t CostValue;
61
62 // The constructor takes no size.
63 // New node indices will be created lazily by AddArcWithCost().
65
66#ifndef SWIG
67 // This type is neither copyable nor movable.
70 delete;
71#endif
72
73 // Reserves space for the given number of arcs, to avoid reallocation in
74 // `AddArcWithCost().
75 void ReserveArcs(ArcIndex num_arcs) {
76 arc_tail_.reserve(num_arcs);
77 arc_head_.reserve(num_arcs);
78 arc_cost_.reserve(num_arcs);
79 }
80
81 // Adds an arc from a left node to a right node with a given cost.
82 // * Node indices must be non-negative (>= 0). For a perfect
83 // matching to exist on n nodes, the values taken by "left_node"
84 // must cover [0, n), same for "right_node".
85 // * The arc cost can be any integer, negative, positive or zero.
86 // * After the method finishes, NumArcs() == the returned ArcIndex + 1.
87 ArcIndex AddArcWithCost(NodeIndex left_node, NodeIndex right_node,
88 CostValue cost);
89
90 // Returns the current number of left nodes which is the same as the
91 // number of right nodes. This is one greater than the largest node
92 // index seen so far in AddArcWithCost().
93 NodeIndex NumNodes() const;
94
95 // Returns the current number of arcs in the graph.
96 ArcIndex NumArcs() const;
97
98 // Returns user-provided data.
99 // The implementation will crash if "arc" is not in [0, NumArcs()).
100 NodeIndex LeftNode(ArcIndex arc) const;
101 NodeIndex RightNode(ArcIndex arc) const;
102 CostValue Cost(ArcIndex arc) const;
103
104 // Solves the problem (finds the perfect matching that minimizes the
105 // cost) and returns the solver status.
106 enum Status {
107 OPTIMAL, // The algorithm found a minimum-cost perfect matching.
108 INFEASIBLE, // The given problem admits no perfect matching.
109 POSSIBLE_OVERFLOW, // Some cost magnitude is too large.
110 };
111 Status Solve();
112
113 // Returns the cost of an assignment with minimal cost.
114 // This is 0 if the last Solve() didn't return OPTIMAL.
115 CostValue OptimalCost() const { return optimal_cost_; }
116
117 // Returns the right node assigned to the given left node in the
118 // last solution computed by Solve(). This works only if Solve()
119 // returned OPTIMAL.
120 //
121 // Note: It is possible that there is more than one optimal
122 // solution. The algorithm is deterministic so it will always return
123 // the same solution for a given problem. There is no such guarantee
124 // from one code version to the next, but the code does not change
125 // often.
126 NodeIndex RightMate(NodeIndex left_node) const {
127 return arc_head_[assignment_arcs_[left_node]];
128 }
129
130 // Returns the cost of the arc used for "left_node"'s assignment.
131 // This works only if Solve() returned OPTIMAL.
133 return arc_cost_[assignment_arcs_[left_node]];
134 }
135
136 private:
137 NodeIndex num_nodes_;
138 std::vector<NodeIndex> arc_tail_;
139 std::vector<NodeIndex> arc_head_;
140 std::vector<CostValue> arc_cost_;
141 std::vector<ArcIndex> assignment_arcs_;
142 CostValue optimal_cost_;
143};
144
145} // namespace operations_research
146
147#endif // OR_TOOLS_GRAPH_ASSIGNMENT_H_
ArcIndex NumArcs() const
Returns the current number of arcs in the graph.
Definition assignment.cc:42
SimpleLinearSumAssignment(const SimpleLinearSumAssignment &)=delete
This type is neither copyable nor movable.
NodeIndex RightMate(NodeIndex left_node) const
Definition assignment.h:126
NodeIndex RightNode(ArcIndex arc) const
Definition assignment.cc:51
ArcIndex AddArcWithCost(NodeIndex left_node, NodeIndex right_node, CostValue cost)
Definition assignment.cc:26
CostValue AssignmentCost(NodeIndex left_node) const
Definition assignment.h:132
NodeIndex LeftNode(ArcIndex arc) const
Definition assignment.cc:46
SimpleLinearSumAssignment & operator=(const SimpleLinearSumAssignment &)=delete
In SWIG mode, we don't want anything besides these top-level includes.
double Cost
Basic non-strict type for cost. The speed penalty for using double is ~2%.