60#ifndef UTIL_GRAPH_TOPOLOGICALSORTER_H__
61#define UTIL_GRAPH_TOPOLOGICALSORTER_H__
67#include "absl/base/attributes.h"
68#include "absl/container/flat_hash_map.h"
81 int num_nodes,
const std::vector<std::pair<int, int>>& arcs,
82 std::vector<int>* topological_order);
86 int num_nodes,
const std::vector<std::pair<int, int>>& arcs,
87 std::vector<int>* topological_order);
96 int num_nodes,
const std::vector<std::pair<int, int>>& arcs);
102 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs,
103 std::vector<T>* topological_order);
106 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs,
107 std::vector<T>* topological_order);
112 int num_nodes,
const std::vector<std::pair<int, int>>& arcs);
114 int num_nodes,
const std::vector<std::pair<int, int>>& arcs);
117 const std::vector<std::pair<T, T>>& arcs);
120 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs);
124template <
typename T,
typename Sorter>
126 Sorter* sorter,
const std::vector<std::pair<T, T>>& arcs,
127 std::vector<T>* topological_order_or_cycle);
141template <
bool stable_sort = false>
150 : traversal_started_(false),
152 num_edges_added_since_last_duplicate_removal_(0) {}
158 : adjacency_lists_(num_nodes),
159 traversal_started_(false),
161 num_edges_added_since_last_duplicate_removal_(0) {}
172 void AddEdge(
int from,
int to);
177 bool GetNext(
int* next_node_index,
bool* cyclic,
178 std::vector<int>* output_cycle_nodes =
nullptr);
182 return nodes_with_zero_indegree_.size();
195 int skip_lists_smaller_than);
202 std::vector<AdjacencyList> adjacency_lists_;
204 bool traversal_started_;
208 typename std::conditional<
211 std::priority_queue<int, std::vector<int>, std::greater<int>>,
212 std::queue<int>>::type nodes_with_zero_indegree_;
213 std::vector<int> indegree_;
218 int num_edges_added_since_last_duplicate_removal_;
224extern template class DenseIntTopologicalSorterTpl<false>;
225extern template class DenseIntTopologicalSorterTpl<true>;
265template <
typename T,
bool stable_sort =
false,
266 typename Hash =
typename absl::flat_hash_map<T, int>::hasher,
268 typename absl::flat_hash_map<T, int, Hash>::key_equal>
291 const int from_int = LookupOrInsertNode(from);
292 const int to_int = LookupOrInsertNode(to);
293 int_sorter_.
AddEdge(from_int, to_int);
314 std::vector<T>* output_cycle_nodes =
nullptr) {
318 &node_index, cyclic_ptr,
319 output_cycle_nodes ? &cycle_int_nodes_ :
nullptr)) {
320 if (*cyclic_ptr && output_cycle_nodes !=
nullptr) {
321 output_cycle_nodes->clear();
322 for (
const int int_node : cycle_int_nodes_) {
323 output_cycle_nodes->push_back(nodes_[int_node]);
328 *node = nodes_[node_index];
345 nodes_.resize(node_to_index_.size());
348 for (
auto& node_and_index : node_to_index_) {
349 nodes_[node_and_index.second] = std::move(node_and_index.first);
363 absl::flat_hash_map<T, int, Hash, KeyEqual> node_to_index_;
366 std::vector<T> nodes_;
373 std::vector<int> cycle_int_nodes_;
377 int LookupOrInsertNode(
const T& node) {
387template <
typename T,
typename Sorter>
389 Sorter* sorter,
const std::vector<std::pair<T, T>>& arcs,
390 std::vector<T>* topological_order, std::vector<T>* cycle) {
391 topological_order->clear();
392 for (
const auto&
arc : arcs) {
393 sorter->AddEdge(
arc.first,
arc.second);
396 sorter->StartTraversal();
398 while (sorter->GetNext(&
next, &cyclic, cycle)) {
399 topological_order->push_back(
next);
404template <
bool stable_sort = false>
406 int num_nodes,
const std::vector<std::pair<int, int>>& arcs,
407 std::vector<int>* topological_order) {
409 return RunTopologicalSorter<int, decltype(sorter)>(
410 &sorter, arcs, topological_order,
nullptr);
413template <
typename T,
bool stable_sort = false>
415 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs,
416 std::vector<T>* topological_order) {
418 for (
const T& node :
nodes) {
421 return RunTopologicalSorter<T, decltype(sorter)>(&sorter, arcs,
422 topological_order,
nullptr);
426template <
typename T,
typename Sorter>
428 Sorter* sorter,
const std::vector<std::pair<T, T>>& arcs) {
429 std::vector<T> topo_order;
435template <
bool stable_sort = false>
437 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
442template <
typename T,
bool stable_sort = false>
444 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs) {
446 for (
const T& node :
nodes) {
455 int num_nodes,
const std::vector<std::pair<int, int>>& arcs,
456 std::vector<int>* topological_order) {
457 return internal::DenseIntTopologicalSortImpl<false>(num_nodes, arcs,
462 int num_nodes,
const std::vector<std::pair<int, int>>& arcs,
463 std::vector<int>* topological_order) {
464 return internal::DenseIntTopologicalSortImpl<true>(num_nodes, arcs,
470 const std::vector<std::pair<T, T>>& arcs,
471 std::vector<T>* topological_order) {
472 return internal::TopologicalSortImpl<T, false>(
nodes, arcs,
478 const std::vector<std::pair<T, T>>& arcs,
479 std::vector<T>* topological_order) {
480 return internal::TopologicalSortImpl<T, true>(
nodes, arcs, topological_order);
484 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
485 return internal::DenseIntTopologicalSortOrDieImpl<false>(num_nodes, arcs);
489 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
490 return internal::DenseIntTopologicalSortOrDieImpl<true>(num_nodes, arcs);
495 const std::vector<std::pair<T, T>>& arcs) {
496 return internal::TopologicalSortOrDieImpl<T, false>(
nodes, arcs);
501 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs) {
502 return internal::TopologicalSortOrDieImpl<T, true>(
nodes, arcs);
513template <
typename T,
bool stable_sort =
false,
514 typename Hash =
typename absl::flat_hash_map<T, int>::hasher,
516 typename absl::flat_hash_map<T, int, Hash>::key_equal>
523 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
527 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
532 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs) {
533 return ::util::StableTopologicalSortOrDie<T>(
nodes, arcs);
void AddEdge(const T &from, const T &to)
bool GetNext(T *node, bool *cyclic_ptr, std::vector< T > *output_cycle_nodes=nullptr)
int GetCurrentFringeSize()
bool TraversalStarted() const
void AddNode(const T &node)
void ExtractCycle(std::vector< int > *cycle_nodes) const
void AddEdge(int from, int to)
void AddNode(int node_index)
DenseIntTopologicalSorterTpl(int num_nodes)
static int RemoveDuplicates(std::vector< AdjacencyList > *lists, int skip_lists_smaller_than)
DenseIntTopologicalSorterTpl()
int GetCurrentFringeSize()
std::vector< int > AdjacencyList
bool TraversalStarted() const
bool GetNext(int *next_node_index, bool *cyclic, std::vector< int > *output_cycle_nodes=nullptr)
auto LogContainer(const ContainerT &container, const PolicyT &policy) -> decltype(gtl::LogRange(container.begin(), container.end(), policy))
Collection::value_type::second_type & LookupOrInsert(Collection *const collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
void STLClearHashIfBig(T *obj, size_t limit)
std::vector< int > DenseIntStableTopologicalSortOrDie(int num_nodes, const std::vector< std::pair< int, int > > &arcs)
std::vector< T > StableTopologicalSortOrDie(const std::vector< T > &nodes, const std::vector< std::pair< T, T > > &arcs)
std::vector< int > DenseIntTopologicalSortOrDie(int num_nodes, const std::vector< std::pair< int, int > > &arcs)
std::vector< T > RunTopologicalSorterOrDie(Sorter *sorter, const std::vector< std::pair< T, T > > &arcs)
std::vector< T > TopologicalSortOrDieImpl(const std::vector< T > &nodes, const std::vector< std::pair< T, T > > &arcs)
ABSL_MUST_USE_RESULT bool DenseIntTopologicalSortImpl(int num_nodes, const std::vector< std::pair< int, int > > &arcs, std::vector< int > *topological_order)
std::vector< int > DenseIntTopologicalSortOrDieImpl(int num_nodes, const std::vector< std::pair< int, int > > &arcs)
ABSL_MUST_USE_RESULT bool RunTopologicalSorter(Sorter *sorter, const std::vector< std::pair< T, T > > &arcs, std::vector< T > *topological_order_or_cycle)
ABSL_MUST_USE_RESULT bool TopologicalSortImpl(const std::vector< T > &nodes, const std::vector< std::pair< T, T > > &arcs, std::vector< T > *topological_order)
uint64_t Hash(uint64_t num, uint64_t c)
std::vector< T > TopologicalSortOrDie(const std::vector< T > &nodes, const std::vector< std::pair< T, T > > &arcs)
ABSL_MUST_USE_RESULT bool DenseIntTopologicalSort(int num_nodes, const std::vector< std::pair< int, int > > &arcs, std::vector< int > *topological_order)
ABSL_MUST_USE_RESULT bool TopologicalSort(const std::vector< T > &nodes, const std::vector< std::pair< T, T > > &arcs, std::vector< T > *topological_order)
std::vector< int > DenseIntStableTopologicalSortOrDie(int num_nodes, const std::vector< std::pair< int, int > > &arcs)
::util::internal::DenseIntTopologicalSorterTpl< true > DenseIntStableTopologicalSorter
std::vector< int > FindCycleInDenseIntGraph(int num_nodes, const std::vector< std::pair< int, int > > &arcs)
std::vector< int > DenseIntTopologicalSortOrDie(int num_nodes, const std::vector< std::pair< int, int > > &arcs)
ABSL_MUST_USE_RESULT bool StableTopologicalSort(const std::vector< T > &nodes, const std::vector< std::pair< T, T > > &arcs, std::vector< T > *topological_order)
std::vector< T > StableTopologicalSortOrDie(const std::vector< T > &nodes, const std::vector< std::pair< T, T > > &arcs)
::util::internal::DenseIntTopologicalSorterTpl< false > DenseIntTopologicalSorter
ABSL_MUST_USE_RESULT bool DenseIntStableTopologicalSort(int num_nodes, const std::vector< std::pair< int, int > > &arcs, std::vector< int > *topological_order)
::util::DenseIntStableTopologicalSorter DenseIntStableTopologicalSorter
::util::DenseIntTopologicalSorter DenseIntTopologicalSorter