16 #ifndef UTIL_GRAPH_UTIL_H_
17 #define UTIL_GRAPH_UTIL_H_
28 #include "absl/container/flat_hash_map.h"
29 #include "absl/container/inlined_vector.h"
30 #include "ortools/base/hash.h"
31 #include "ortools/base/map_util.h"
53 template <
class Graph>
55 template <
class Graph>
57 template <
class Graph>
59 template <
class Graph>
63 template <
class Graph>
71 template <
class Graph>
73 const std::vector<int>& new_node_index);
85 template <
class Graph>
87 const std::vector<int>& nodes);
100 template <
class Graph>
106 typedef typename Graph::OutgoingOrOppositeIncomingArcIterator
ArcIterator;
113 return graph_.
Head(ArcIterator::operator*());
122 const auto& arc_range = graph_.OutgoingOrOppositeIncomingArcs(node);
134 template <
class Graph>
151 template <
class Graph>
164 template <
class Graph>
168 template <
class Graph>
186 template <
class Graph>
188 bool die_if_not_symmetric);
192 template <
class Graph>
195 if (graph.
Tail(arc) == graph.
Head(arc))
return true;
200 template <
class Graph>
204 std::vector<bool> tmp_node_mask(graph.
num_nodes(),
false);
208 if (tmp_node_mask[head])
return true;
209 tmp_node_mask[head] =
true;
212 tmp_node_mask[graph.
Head(arc)] =
false;
218 template <
class Graph>
230 reverse_graph.
Build();
232 std::vector<ArcIndex> count(graph.
num_nodes(), 0);
235 ++count[graph.
Head(arc)];
238 if (--count[reverse_graph.
Head(arc)] < 0)
return false;
241 if (count[graph.
Head(arc)] != 0)
return false;
247 template <
class Graph>
250 static_assert(std::numeric_limits<NodeIndex>::max() <= INT_MAX,
251 "GraphIsWeaklyConnected() isn't yet implemented for graphs"
252 " that support more than INT_MAX nodes. Reach out to"
253 " or-core-team@ if you need this.");
263 template <
class Graph>
265 std::unique_ptr<Graph> new_graph(
267 for (
const auto node : graph.
AllNodes()) {
269 new_graph->AddArc(node, graph.
Head(arc));
276 template <
class Graph>
278 const std::vector<int>& new_node_index) {
280 const int num_nodes = old_graph.
num_nodes();
281 CHECK_EQ(new_node_index.size(), num_nodes);
282 std::unique_ptr<Graph> new_graph(
new Graph(num_nodes, old_graph.
num_arcs()));
287 new_graph->AddArc(new_node_index[node],
288 new_node_index[old_graph.
Head(arc)]);
295 template <
class Graph>
297 const std::vector<int>& nodes) {
301 std::vector<NodeIndex> new_node_index(old_graph.
num_nodes(), -1);
302 for (
NodeIndex new_index = 0; new_index < nodes.size(); ++new_index) {
303 new_node_index[nodes[new_index]] = new_index;
310 if (new_node_index[old_graph.
Head(arc)] != -1) ++num_arcs;
317 std::unique_ptr<Graph> new_graph(
new Graph(nodes.size(), num_arcs));
318 for (
NodeIndex new_tail = 0; new_tail < nodes.size(); ++new_tail) {
319 const NodeIndex old_tail = nodes[new_tail];
321 const NodeIndex new_head = new_node_index[old_graph.
Head(arc)];
322 if (new_head != -1) new_graph->AddArc(new_tail, new_head);
329 template <
class Graph>
334 std::vector<bool> tmp_node_mask(graph.
num_nodes(),
false);
338 if (head != tail && !tmp_node_mask[head]) {
339 tmp_node_mask[head] =
true;
340 g->AddArc(tail, head);
344 tmp_node_mask[graph.
Head(arc)] =
false;
351 template <
class Graph>
353 if (arc_path->empty())
return;
356 std::map<int, int> last_arc_leaving_node;
357 for (
const int arc : *arc_path) last_arc_leaving_node[graph.
Tail(arc)] = arc;
361 last_arc_leaving_node[graph.
Head(arc_path->back())] = -1;
365 int node = graph.
Tail(arc_path->front());
367 while (new_size < arc_path->size()) {
368 const int arc = gtl::FindOrDie(last_arc_leaving_node, node);
369 if (arc == -1)
break;
370 (*arc_path)[new_size++] = arc;
371 node = graph.
Head(arc);
373 arc_path->resize(new_size);
376 template <
class Graph>
378 if (arc_path.empty())
return false;
380 seen.insert(graph.
Tail(arc_path.front()));
381 for (
const int arc : arc_path) {
382 if (!gtl::InsertIfNotPresent(&seen, graph.
Head(arc)))
return true;
387 template <
class Graph>
389 const Graph& graph,
bool die_if_not_symmetric) {
390 std::vector<int> reverse_arc(graph.
num_arcs(), -1);
394 absl::flat_hash_map<std::pair< int,
int>,
395 absl::InlinedVector<int, 4>>
398 for (
int arc = 0; arc < graph.
num_arcs(); ++arc) {
399 const int tail = graph.
Tail(arc);
400 const int head = graph.
Head(arc);
403 reverse_arc[arc] = arc;
407 auto it = arc_map.find({head, tail});
408 if (it != arc_map.end()) {
411 reverse_arc[arc] = it->second.back();
412 reverse_arc[it->second.back()] = arc;
413 if (it->second.size() > 1) {
414 it->second.pop_back();
420 arc_map[{tail, head}].push_back(arc);
425 int64_t num_unmapped_arcs = 0;
426 for (
const auto& p : arc_map) {
427 num_unmapped_arcs += p.second.size();
429 DCHECK_EQ(std::count(reverse_arc.begin(), reverse_arc.end(), -1),
432 if (die_if_not_symmetric) {
433 CHECK_EQ(arc_map.size(), 0)
434 <<
"The graph is not symmetric: " << arc_map.size() <<
" of "
435 << graph.
num_arcs() <<
" arcs did not have a reverse.";
bool AddEdge(int node1, int node2)
void SetNumberOfNodes(int num_nodes)
int GetNumberOfComponents() const
IntegerRange< ArcIndex > AllForwardArcs() const
ArcIndexType num_arcs() const
NodeIndexType num_nodes() const
IntegerRange< NodeIndex > AllNodes() const
NodeIndexType Tail(ArcIndexType arc) const
NodeIndexType Head(ArcIndexType arc) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
NodeIndexType Head(ArcIndexType arc) const
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
Graph::NodeIndex operator*() const
AdjacencyListIterator(const Graph &graph, ArcIterator &&arc_it)
UndirectedAdjacencyListsOfDirectedGraph(const Graph &graph)
Graph::OutgoingOrOppositeIncomingArcIterator ArcIterator
BeginEndWrapper< AdjacencyListIterator > operator[](int node) const
std::vector< int > ComputeOnePossibleReverseArcMapping(const Graph &graph, bool die_if_not_symmetric)
bool PathHasCycle(const Graph &graph, const std::vector< int > &arc_path)
void RemoveCyclesFromPath(const Graph &graph, std::vector< int > *arc_path)
bool GraphHasDuplicateArcs(const Graph &graph)
std::unique_ptr< Graph > RemoveSelfArcsAndDuplicateArcs(const Graph &graph)
std::unique_ptr< Graph > GetSubgraphOfNodes(const Graph &graph, const std::vector< int > &nodes)
bool GraphHasSelfArcs(const Graph &graph)
bool GraphIsSymmetric(const Graph &graph)
bool IsSubsetOf0N(const std::vector< int > &v, int n)
std::vector< int > GetConnectedComponents(int num_nodes, const UndirectedGraph &graph)
std::unique_ptr< Graph > RemapGraph(const Graph &graph, const std::vector< int > &new_node_index)
std::vector< int > GetWeaklyConnectedComponents(const Graph &graph)
bool GraphIsWeaklyConnected(const Graph &graph)
bool IsValidPermutation(const std::vector< int > &v)
std::unique_ptr< Graph > CopyGraph(const Graph &graph)