Google OR-Tools: ortools/graph/util.h Source File
27#include "absl/container/btree_map.h"
28#include "absl/container/flat_hash_map.h"
29#include "absl/container/inlined_vector.h"
31#include "absl/types/span.h"
37namespace util {
74 absl::Span<const int> new_node_index);
88 absl::Span<const int> nodes);
105 "for forward graphs, directly use `Graph::operator[]`");
110 typedef typename Graph::OutgoingOrOppositeIncomingArcIterator ArcIterator;
121 const Graph& graph_;
132 const Graph& graph_;
152bool IsSubsetOf0N(absl::Span<const int> v, int n);
178bool PathHasCycle(const Graph& graph, absl::Span<const int> arc_path);
197 bool die_if_not_symmetric);
203 for (const auto arc : graph.AllForwardArcs()) {
213 std::vector<bool> tmp_node_mask(graph.num_nodes(), false);
214 for (const NodeIndex tail : graph.AllNodes()) {
215 for (const ArcIndex arc : graph.OutgoingArcs(tail)) {
216 const NodeIndex head = graph.Head(arc);
217 if (tmp_node_mask[head]) return true;
218 tmp_node_mask[head] = true;
220 for (const ArcIndex arc : graph.OutgoingArcs(tail)) {
221 tmp_node_mask[graph.Head(arc)] = false;
233 graph.num_arcs());
234 for (const NodeIndex node : graph.AllNodes()) {
235 for (const ArcIndex arc : graph.OutgoingArcs(node)) {
236 reverse_graph.AddArc(graph.Head(arc), node);
239 reverse_graph.Build();
241 std::vector<ArcIndex> count(graph.num_nodes(), 0);
242 for (const NodeIndex node : graph.AllNodes()) {
243 for (const ArcIndex arc : graph.OutgoingArcs(node)) {
244 ++count[graph.Head(arc)];
246 for (const ArcIndex arc : reverse_graph.OutgoingArcs(node)) {
247 if (--count[reverse_graph.Head(arc)] < 0) return false;
249 for (const ArcIndex arc : graph.OutgoingArcs(node)) {
250 if (count[graph.Head(arc)] != 0) return false;
259 static_assert(std::numeric_limits<NodeIndex>::max() <= INT_MAX,
260 "GraphIsWeaklyConnected() isn't yet implemented for graphs"
261 " that support more than INT_MAX nodes. Reach out to"
262 " or-core-team@ if you need this.");
263 if (graph.num_nodes() == 0) return true;
274 std::unique_ptr<Graph> new_graph(
276 for (const auto node : graph.AllNodes()) {
277 for (const auto arc : graph.OutgoingArcs(node)) {
278 new_graph->AddArc(node, graph.Head(arc));
287 absl::Span<const int> new_node_index) {
289 const int num_nodes = old_graph.num_nodes();
290 CHECK_EQ(new_node_index.size(), num_nodes);
291 std::unique_ptr<Graph> new_graph(new Graph(num_nodes, old_graph.num_arcs()));
294 for (const NodeIndex node : old_graph.AllNodes()) {
295 for (const ArcIndex arc : old_graph.OutgoingArcs(node)) {
296 new_graph->AddArc(new_node_index[node],
297 new_node_index[old_graph.Head(arc)]);
306 absl::Span<const int> nodes) {
310 std::vector<NodeIndex> new_node_index(old_graph.num_nodes(), -1);
311 for (NodeIndex new_index = 0; new_index < nodes.size(); ++new_index) {
312 new_node_index[nodes[new_index]] = new_index;
317 for (const NodeIndex node : nodes) {
318 for (const ArcIndex arc : old_graph.OutgoingArcs(node)) {
319 if (new_node_index[old_graph.Head(arc)] != -1) ++num_arcs;
326 std::unique_ptr<Graph> new_graph(new Graph(nodes.size(), num_arcs));
327 for (NodeIndex new_tail = 0; new_tail < nodes.size(); ++new_tail) {
328 const NodeIndex old_tail = nodes[new_tail];
329 for (const ArcIndex arc : old_graph.OutgoingArcs(old_tail)) {
330 const NodeIndex new_head = new_node_index[old_graph.Head(arc)];
331 if (new_head != -1) new_graph->AddArc(new_tail, new_head);
340 std::unique_ptr<Graph> g(new Graph(graph.num_nodes(), graph.num_arcs()));
343 std::vector<bool> tmp_node_mask(graph.num_nodes(), false);
344 for (const NodeIndex tail : graph.AllNodes()) {
345 for (const ArcIndex arc : graph.OutgoingArcs(tail)) {
346 const NodeIndex head = graph.Head(arc);
347 if (head != tail && !tmp_node_mask[head]) {
348 tmp_node_mask[head] = true;
352 for (const ArcIndex arc : graph.OutgoingArcs(tail)) {
353 tmp_node_mask[graph.Head(arc)] = false;
362 if (arc_path->empty()) return;
365 absl::btree_map<int, int> last_arc_leaving_node;
366 for (const int arc : *arc_path) last_arc_leaving_node[graph.Tail(arc)] = arc;
370 last_arc_leaving_node[graph.Head(arc_path->back())] = -1;
374 int node = graph.Tail(arc_path->front());
376 while (new_size < arc_path->size()) {
377 const int arc = gtl::FindOrDie(last_arc_leaving_node, node);
379 (*arc_path)[new_size++] = arc;
380 node = graph.Head(arc);
387 if (arc_path.empty()) return false;
389 seen.insert(graph.Tail(arc_path.front()));
398 const Graph& graph, bool die_if_not_symmetric) {
399 std::vector<int> reverse_arc(graph.num_arcs(), -1);
403 absl::flat_hash_map<std::pair< int, int>,
404 absl::InlinedVector<int, 4>>
407 for (int arc = 0; arc < graph.num_arcs(); ++arc) {
408 const int tail = graph.Tail(arc);
409 const int head = graph.Head(arc);
416 auto it = arc_map.find({head, tail});
417 if (it != arc_map.end()) {
420 reverse_arc[arc] = it->second.back();
421 reverse_arc[it->second.back()] = arc;
422 if (it->second.size() > 1) {
429 arc_map[{tail, head}].push_back(arc);
434 int64_t num_unmapped_arcs = 0;
435 for (const auto& p : arc_map) {
436 num_unmapped_arcs += p.second.size();
438 DCHECK_EQ(std::count(reverse_arc.begin(), reverse_arc.end(), -1),
441 if (die_if_not_symmetric) {
442 CHECK_EQ(arc_map.size(), 0)
443 << "The graph is not symmetric: " << arc_map.size() << " of "
444 << graph.num_arcs() << " arcs did not have a reverse.";
bool AddEdge(int node1, int node2)
void SetNumberOfNodes(int num_nodes)
int GetNumberOfComponents() const
NodeIndexType num_nodes() const
ArcIndexType num_arcs() const
IntegerRange< NodeIndex > AllNodes() const
static constexpr bool kHasNegativeReverseArcs
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
NodeIndexType Head(ArcIndexType arc) const
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
IntegerRange< ArcIndexType > OutgoingArcs(NodeIndexType node) const
void Build(std::vector< ArcIndexType > *permutation) final
NodeIndexType Head(ArcIndexType arc) const
AdjacencyListIterator(const Graph &graph, ArcIterator &&arc_it)
Definition util.h:113
Graph::NodeIndex operator*() const
Definition util.h:116
Graph::OutgoingOrOppositeIncomingArcIterator ArcIterator
Definition util.h:110
UndirectedAdjacencyListsOfDirectedGraph(const Graph &graph)
Definition util.h:107
BeginEndWrapper< AdjacencyListIterator > operator[](int node) const
Definition util.h:125
bool InsertIfNotPresent(Collection *const collection, const typename Collection::value_type &value)
const Collection::value_type::second_type & FindOrDie(const Collection &collection, const typename Collection::value_type::first_type &key)
void RemoveCyclesFromPath(const Graph &graph, std::vector< int > *arc_path)
Definition util.h:361
bool IsValidPermutation(absl::Span< const int > v)
Definition util.h:155
std::unique_ptr< Graph > CopyGraph(const Graph &graph)
Definition util.h:273
std::vector< int > GetConnectedComponents(int num_nodes, const UndirectedGraph &graph)
UndirectedAdjacencyListsOfDirectedGraph(const Graph &) -> UndirectedAdjacencyListsOfDirectedGraph< Graph >
bool PathHasCycle(const Graph &graph, absl::Span< const int > arc_path)
Definition util.h:386
bool GraphHasDuplicateArcs(const Graph &graph)
Definition util.h:210
bool GraphIsSymmetric(const Graph &graph)
Definition util.h:228
std::unique_ptr< Graph > RemapGraph(const Graph &graph, absl::Span< const int > new_node_index)
Definition util.h:286
std::unique_ptr< Graph > RemoveSelfArcsAndDuplicateArcs(const Graph &graph)
Definition util.h:339
std::vector< int > GetWeaklyConnectedComponents(const Graph &graph)
Definition util.h:144
bool GraphIsWeaklyConnected(const Graph &graph)
Definition util.h:257
bool GraphHasSelfArcs(const Graph &graph)
Definition util.h:202
bool IsSubsetOf0N(absl::Span< const int > v, int n)
std::unique_ptr< Graph > GetSubgraphOfNodes(const Graph &graph, absl::Span< const int > nodes)
Definition util.h:305
std::vector< int > ComputeOnePossibleReverseArcMapping(const Graph &graph, bool die_if_not_symmetric)
Definition util.h:397