16 #ifndef UTIL_GRAPH_UTIL_H_ 17 #define UTIL_GRAPH_UTIL_H_ 24 #include <unordered_map> 27 #include "ortools/base/hash.h" 28 #include "ortools/base/map_util.h" 50 template <
class Graph>
52 template <
class Graph>
54 template <
class Graph>
56 template <
class Graph>
60 template <
class Graph>
68 template <
class Graph>
70 const std::vector<int>& new_node_index);
82 template <
class Graph>
84 const std::vector<int>& nodes);
97 template <
class Graph>
103 typedef typename Graph::OutgoingOrOppositeIncomingArcIterator
ArcIterator;
110 return graph_.
Head(ArcIterator::operator*());
118 BeginEndWrapper<AdjacencyListIterator>
operator[](
int node)
const {
119 const auto& arc_range = graph_.OutgoingOrOppositeIncomingArcs(node);
131 template <
class Graph>
148 template <
class Graph>
161 template <
class Graph>
165 template <
class Graph>
180 template <
class Graph>
182 bool die_if_not_symmetric);
186 template <
class Graph>
189 if (graph.
Tail(arc) == graph.
Head(arc))
return true;
194 template <
class Graph>
198 std::vector<bool> tmp_node_mask(graph.
num_nodes(),
false);
202 if (tmp_node_mask[head])
return true;
203 tmp_node_mask[head] =
true;
206 tmp_node_mask[graph.
Head(arc)] =
false;
212 template <
class Graph>
224 reverse_graph.Build();
226 std::vector<ArcIndex> count(graph.
num_nodes(), 0);
229 ++count[graph.
Head(arc)];
231 for (
const ArcIndex arc : reverse_graph.OutgoingArcs(node)) {
232 if (--count[reverse_graph.Head(arc)] < 0)
return false;
235 if (count[graph.
Head(arc)] != 0)
return false;
241 template <
class Graph>
244 static_assert(std::numeric_limits<NodeIndex>::max() <= INT_MAX,
245 "GraphIsWeaklyConnected() isn't yet implemented for graphs" 246 " that support more than INT_MAX nodes. Reach out to" 247 " or-core-team@ if you need this.");
257 template <
class Graph>
259 std::unique_ptr<Graph> new_graph(
261 for (
const auto node : graph.
AllNodes()) {
263 new_graph->AddArc(node, graph.
Head(arc));
270 template <
class Graph>
272 const std::vector<int>& new_node_index) {
274 const int num_nodes = old_graph.
num_nodes();
275 CHECK_EQ(new_node_index.size(), num_nodes);
276 std::unique_ptr<Graph> new_graph(
new Graph(num_nodes, old_graph.
num_arcs()));
281 new_graph->AddArc(new_node_index[node],
282 new_node_index[old_graph.
Head(arc)]);
289 template <
class Graph>
291 const std::vector<int>& nodes) {
295 std::vector<NodeIndex> new_node_index(old_graph.
num_nodes(), -1);
296 for (
NodeIndex new_index = 0; new_index < nodes.size(); ++new_index) {
297 new_node_index[nodes[new_index]] = new_index;
304 if (new_node_index[old_graph.
Head(arc)] != -1) ++num_arcs;
311 std::unique_ptr<Graph> new_graph(
new Graph(nodes.size(), num_arcs));
312 for (
NodeIndex new_tail = 0; new_tail < nodes.size(); ++new_tail) {
313 const NodeIndex old_tail = nodes[new_tail];
315 const NodeIndex new_head = new_node_index[old_graph.
Head(arc)];
316 if (new_head != -1) new_graph->AddArc(new_tail, new_head);
323 template <
class Graph>
328 std::vector<bool> tmp_node_mask(graph.
num_nodes(),
false);
332 if (head != tail && !tmp_node_mask[head]) {
333 tmp_node_mask[head] =
true;
334 g->AddArc(tail, head);
338 tmp_node_mask[graph.
Head(arc)] =
false;
345 template <
class Graph>
347 if (arc_path->empty())
return;
350 std::map<int, int> last_arc_leaving_node;
351 for (
const int arc : *arc_path) last_arc_leaving_node[graph.
Tail(arc)] = arc;
355 last_arc_leaving_node[graph.
Head(arc_path->back())] = -1;
359 int node = graph.
Tail(arc_path->front());
361 while (new_size < arc_path->size()) {
362 const int arc = gtl::FindOrDie(last_arc_leaving_node, node);
363 if (arc == -1)
break;
364 (*arc_path)[new_size++] = arc;
365 node = graph.
Head(arc);
367 arc_path->resize(new_size);
370 template <
class Graph>
372 if (arc_path.empty())
return false;
374 seen.insert(graph.
Tail(arc_path.front()));
375 for (
const int arc : arc_path) {
376 if (!gtl::InsertIfNotPresent(&seen, graph.
Head(arc)))
return true;
381 template <
class Graph>
383 const Graph& graph,
bool die_if_not_symmetric) {
384 std::vector<int> reverse_arc(graph.
num_arcs(), -1);
385 std::unordered_multimap<std::pair< int,
int>,
388 for (
int arc = 0; arc < graph.
num_arcs(); ++arc) {
389 const int tail = graph.
Tail(arc);
390 const int head = graph.
Head(arc);
393 reverse_arc[arc] = arc;
397 auto it = arc_map.find({head, tail});
398 if (it != arc_map.end()) {
401 reverse_arc[arc] = it->second;
402 reverse_arc[it->second] = arc;
406 arc_map.insert({{tail, head}, arc});
410 DCHECK_EQ(std::count(reverse_arc.begin(), reverse_arc.end(), -1),
412 if (die_if_not_symmetric) {
413 CHECK_EQ(arc_map.size(), 0)
414 <<
"The graph is not symmetric: " << arc_map.size() <<
" of " 415 << graph.
num_arcs() <<
" arcs did not have a reverse.";
422 #endif // UTIL_GRAPH_UTIL_H_ IntegerRange< ArcIndex > AllForwardArcs() const
bool IsValidPermutation(const std::vector< int > &v)
Returns true iff the given vector is a permutation of [0..size()-1].
This can be used to view a directed graph (that supports reverse arcs) from graph....
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
void SetNumberOfNodes(int num_nodes)
Sets the number of nodes in the graph.
std::unique_ptr< Graph > RemoveSelfArcsAndDuplicateArcs(const Graph &graph)
Returns a copy of "graph", without self-arcs and duplicate arcs.
Graph::NodeIndex operator *() const
Overwrite operator* to return the heads of the arcs.
ListGraph Graph
Defining the simplest Graph interface as Graph for convenience.
std::vector< int > ComputeOnePossibleReverseArcMapping(const Graph &graph, bool die_if_not_symmetric)
Returns a vector representing a mapping from arcs to arcs such that each arc is mapped to another arc...
NodeIndexType num_nodes() const
Returns the number of valid nodes in the graph.
NOTE(user): The rest of the functions below should also be in namespace util, but for historical reas...
bool GraphHasDuplicateArcs(const Graph &graph)
NodeIndexType Tail(ArcIndexType arc) const
Returns the tail/head of a valid arc.
std::vector< int > GetConnectedComponents(int num_nodes, const UndirectedGraph &graph)
Finds the connected components of the graph, using BFS internally.
bool GraphIsWeaklyConnected(const Graph &graph)
bool GraphHasSelfArcs(const Graph &graph)
Here's a set of simple diagnosis tools.
std::unique_ptr< Graph > RemapGraph(const Graph &graph, const std::vector< int > &new_node_index)
Creates a remapped copy of graph "graph", where node i becomes node new_node_index[i].
bool IsSubsetOf0N(const std::vector< int > &v, int n)
Returns true iff the given vector is a subset of [0..n-1], i.e.
std::unique_ptr< Graph > GetSubgraphOfNodes(const Graph &graph, const std::vector< int > &nodes)
Gets the induced subgraph of "graph" restricted to the nodes in "nodes": the resulting graph will hav...
Most efficient implementation of a graph without reverse arcs:
bool GraphIsSymmetric(const Graph &graph)
NodeIndexType Head(ArcIndexType arc) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
Allows to iterate over the forward arcs that verify Tail(arc) == node.
int GetNumberOfComponents() const
bool PathHasCycle(const Graph &graph, const std::vector< int > &arc_path)
Returns true iff the given path contains a cycle.
IntegerRange< NodeIndex > AllNodes() const
Allows nice range-based for loop: for (const NodeIndex node : graph.AllNodes()) { ....
ArcIndexType num_arcs() const
Returns the number of valid arcs in the graph.
std::vector< int > GetWeaklyConnectedComponents(const Graph &graph)
Computes the weakly connected components of a directed graph that provides the OutgoingOrOppositeInco...
AdjacencyListIterator(const Graph &graph, ArcIterator &&arc_it)
NodeIndexType NodeIndex
Typedef so you can use Graph::NodeIndex and Graph::ArcIndex to be generic but also to improve the rea...
UndirectedAdjacencyListsOfDirectedGraph(const Graph &graph)
void AddEdge(int node1, int node2)
The main API is the same as ConnectedComponentsFinder (below): see the homonymous functions there.
Graph::OutgoingOrOppositeIncomingArcIterator ArcIterator
void RemoveCyclesFromPath(const Graph &graph, std::vector< int > *arc_path)
Given an arc path, changes it to a sub-path with the same source and destination but without any cycl...
std::unique_ptr< Graph > CopyGraph(const Graph &graph)
Returns a fresh copy of a given graph.
int32 NodeIndex
Standard instantiation of ForwardEbertGraph (named 'ForwardStarGraph') of EbertGraph (named 'StarGrap...
Basic graph implementation without reverse arc.
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
BeginEndWrapper< AdjacencyListIterator > operator[](int node) const
Returns a pseudo-container of all the nodes adjacent to "node".