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 = NULL);
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 = NULL) {
317 if (!int_sorter_.
GetNext(&node_index, cyclic_ptr,
318 output_cycle_nodes ? &cycle_int_nodes_ : NULL)) {
319 if (*cyclic_ptr && output_cycle_nodes != NULL) {
320 output_cycle_nodes->clear();
321 for (
const int int_node : cycle_int_nodes_) {
322 output_cycle_nodes->push_back(nodes_[int_node]);
327 *node = nodes_[node_index];
344 nodes_.resize(node_to_index_.size());
347 for (
auto& node_and_index : node_to_index_) {
348 nodes_[node_and_index.second] = std::move(node_and_index.first);
362 absl::flat_hash_map<T, int, Hash, KeyEqual> node_to_index_;
365 std::vector<T> nodes_;
372 std::vector<int> cycle_int_nodes_;
376 int LookupOrInsertNode(
const T& node) {
386template <
typename T,
typename Sorter>
388 Sorter* sorter,
const std::vector<std::pair<T, T>>& arcs,
389 std::vector<T>* topological_order, std::vector<T>* cycle) {
390 topological_order->clear();
391 for (
const auto& arc : arcs) {
392 sorter->AddEdge(arc.first, arc.second);
395 sorter->StartTraversal();
397 while (sorter->GetNext(&
next, &cyclic, cycle)) {
398 topological_order->push_back(
next);
403template <
bool stable_sort = false>
405 int num_nodes,
const std::vector<std::pair<int, int>>& arcs,
406 std::vector<int>* topological_order) {
408 return RunTopologicalSorter<int, decltype(sorter)>(
409 &sorter, arcs, topological_order,
nullptr);
412template <
typename T,
bool stable_sort = false>
414 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs,
415 std::vector<T>* topological_order) {
417 for (
const T& node :
nodes) {
420 return RunTopologicalSorter<T, decltype(sorter)>(&sorter, arcs,
421 topological_order,
nullptr);
425template <
typename T,
typename Sorter>
427 Sorter* sorter,
const std::vector<std::pair<T, T>>& arcs) {
428 std::vector<T> topo_order;
434template <
bool stable_sort = false>
436 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
441template <
typename T,
bool stable_sort = false>
443 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs) {
445 for (
const T& node :
nodes) {
454 int num_nodes,
const std::vector<std::pair<int, int>>& arcs,
455 std::vector<int>* topological_order) {
456 return internal::DenseIntTopologicalSortImpl<false>(num_nodes, arcs,
461 int num_nodes,
const std::vector<std::pair<int, int>>& arcs,
462 std::vector<int>* topological_order) {
463 return internal::DenseIntTopologicalSortImpl<true>(num_nodes, arcs,
469 const std::vector<std::pair<T, T>>& arcs,
470 std::vector<T>* topological_order) {
471 return internal::TopologicalSortImpl<T, false>(
nodes, arcs,
477 const std::vector<std::pair<T, T>>& arcs,
478 std::vector<T>* topological_order) {
479 return internal::TopologicalSortImpl<T, true>(
nodes, arcs, topological_order);
483 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
484 return internal::DenseIntTopologicalSortOrDieImpl<false>(num_nodes, arcs);
488 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
489 return internal::DenseIntTopologicalSortOrDieImpl<true>(num_nodes, arcs);
494 const std::vector<std::pair<T, T>>& arcs) {
495 return internal::TopologicalSortOrDieImpl<T, false>(
nodes, arcs);
500 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs) {
501 return internal::TopologicalSortOrDieImpl<T, true>(
nodes, arcs);
512template <
typename T,
bool stable_sort =
false,
513 typename Hash =
typename absl::flat_hash_map<T, int>::hasher,
515 typename absl::flat_hash_map<T, int, Hash>::key_equal>
522 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
526 int num_nodes,
const std::vector<std::pair<int, int>>& arcs) {
531 const std::vector<T>&
nodes,
const std::vector<std::pair<T, T>>& arcs) {
532 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=NULL)
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)
bool GetNext(int *next_node_index, bool *cyclic, std::vector< int > *output_cycle_nodes=NULL)
static int RemoveDuplicates(std::vector< AdjacencyList > *lists, int skip_lists_smaller_than)
DenseIntTopologicalSorterTpl()
int GetCurrentFringeSize()
std::vector< int > AdjacencyList
bool TraversalStarted() const
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