7 #include <boost/range/rbegin.hpp>
8 #include <boost/range/rend.hpp>
37 template <
typename Aut>
41 template <
typename Aut>
50 template <
typename Aut>
59 rvp_.reserve(aut->num_all_states());
60 for (
auto s : aut->states())
74 for (
auto t :
aut_->out(s))
76 auto dst =
aut_->dst_of(t);
93 template <
typename Aut>
95 std::vector<state_t_of<Aut>>
113 template <
typename Aut>
127 for (
auto s :
aut_->states())
140 for (
auto t:
aut_->out(s))
197 template <
typename Aut>
210 while (!todo.empty())
212 auto s = todo.back();
236 for (
auto t :
aut_->out(s))
238 auto dst =
aut_->dst_of(t);
263 template <
typename Aut>
276 for (
auto s :
aut_->states())
296 if (st.pos != st.end)
298 auto dst =
aut_->dst_of(*st.pos);
303 const auto& out =
aut_->out(dst);
304 dfs_stack_.emplace_back(dst, out.begin(), out.end());
347 std::unordered_map<state_t, std::size_t>
number_;
349 std::unordered_map<state_t, std::size_t>
low_;
351 std::size_t
low_max_ = std::numeric_limits<unsigned int>::max();
383 template <
typename Aut>
394 for (
auto s : aut_->states())
407 std::size_t min = curr_state_num_++;
408 low_.emplace(s, min);
412 for (
auto t : aut_->out(s))
414 auto dst = aut_->dst_of(t);
426 components_.emplace_back();
427 auto& com = components_.back();
436 low_[w] = std::numeric_limits<size_t>::max();
445 std::size_t curr_state_num_ = 0;
452 std::unordered_map<state_t, std::size_t>
low_;
474 if (algo ==
"dijkstra")
476 else if (algo ==
"auto" || algo ==
"tarjan_iterative")
478 else if (algo ==
"tarjan_recursive")
480 else if (algo ==
"kosaraju")
483 raise(
"scc: invalid algorithm: ",
str_escape(algo));
488 template <
typename Aut>
490 const detail::components_t<Aut>
509 template <
typename Aut>
515 using res_t = decltype(res);
517 auto s0 = *com.begin();
518 map[s0] = res->new_state();
519 res->set_initial(map[s0]);
523 map[s] = res->new_state();
524 for (
auto t : aut->out(s))
526 auto dst = aut->dst_of(t);
530 map[dst] = res->new_state();
531 res->new_transition(map[s], map[dst], aut->label_of(t));
544 template <
typename Aut>
564 components_.assign(boost::rbegin(cs), boost::rend(cs));
565 size_t num_sccs = components_.size();
566 for (
size_t i = 0; i < num_sccs; ++i)
567 for (
auto s : components_[i])
574 static symbol res(
"scc_automaton<"
581 o <<
"scc_automaton<";
582 aut_->print_set(o, fmt);
586 bool state_has_name(state_t) const
591 std::ostream& print_state_name(state_t s, std::ostream& o,
595 o << component_.at(s) << '.
';
596 aut_->print_state_name(s, o, fmt, true);
600 const component_t& component(unsigned num) const
602 require(num < components_.size(),
603 "component: invalid component number: ",
604 num, ": there are ", components_.size(), " components");
605 return components_[num];
608 const components_t& components() const
613 size_t num_components() const
615 return components_.size();
621 std::map<state_t, size_t> component_;
622 components_t components_;
626 template <typename Aut>
627 using scc_automaton = std::shared_ptr<detail::scc_automaton_impl<Aut>>;
630 template <typename Aut>
633 scc(const Aut& aut, const std::string& algo = "auto")
635 return make_shared_ptr<scc_automaton<Aut>>(aut, scc_algo(algo));
643 template <typename Aut, typename String>
645 automaton scc(const automaton& aut, const std::string& algo)
647 const auto& a = aut->as<Aut>();
648 return make_automaton(::vcsn::scc(a, algo));
658 template <typename Aut>
660 std::size_t num_components(const scc_automaton<Aut>& aut)
662 return aut->num_components();
665 template <typename Aut>
667 std::size_t num_components(const Aut&)
669 raise("num_components: requires an scc_automaton");
677 template <typename Aut>
679 std::size_t num_components(const automaton& aut)
681 const auto& a = aut->as<Aut>();
682 return ::vcsn::num_components(a);
695 template <typename Aut>
697 filter_automaton<scc_automaton<Aut>>
698 component(const scc_automaton<Aut>& aut, unsigned num)
700 return vcsn::filter(aut, aut->component(num));
703 template <typename Aut>
706 component(const Aut&, unsigned)
708 raise("component: requires an scc_automaton");
716 template <typename Aut, typename Unsigned>
718 automaton component(const automaton& aut, unsigned num)
720 const auto& a = aut->as<Aut>();
721 return make_automaton(::vcsn::component(a, num));
733 template <typename Aut>
735 partition_automaton<scc_automaton<Aut>>
736 condense(const scc_automaton<Aut>& aut)
738 auto res = make_shared_ptr<partition_automaton<scc_automaton<Aut>>>(aut);
739 using state_t = state_t_of<Aut>;
741 std::unordered_map<state_t, state_t> map;
743 // Add states to new automaton.
744 std::set<state_t> ss;
745 for (const auto& com : aut->components())
748 ss.insert(begin(com), end(com));
749 state_t new_state = res->new_state(ss);
753 map[aut->pre()] = res->pre();
754 map[aut->post()] = res->post();
756 // Add transitions to new automaton.
757 for (auto t: aut->all_transitions())
759 auto s = map[aut->src_of(t)];
760 auto d = map[aut->dst_of(t)];
762 res->add_transition(s, d, aut->label_of(t), aut->weight_of(t));
767 template <typename Aut>
769 partition_automaton<Aut>
772 raise("condense: requires an scc_automaton");
780 template <typename Aut>
782 automaton condense(const automaton& aut)
784 const auto& a = aut->as<Aut>();
785 return make_automaton(::vcsn::condense(a));
state_t_of< Aut > state_t
scc_tarjan_recursive_impl(const Aut &aut)
scc_kosaraju_impl(const Aut &aut)
state_t_of< Aut > state_t
std::set< state_t > marked_
Store the visited states.
std::ostream & str_escape(std::ostream &os, const std::string &str)
Output a string, escaping special characters.
std::vector< state_t > rvp_
Revert postorder of dfs.
state_t_of< Aut > state_t
scc_tarjan_iterative_impl(const Aut &aut)
weightset_mixin< detail::r_impl > r
std::unordered_set< state_t > marked_
std::ostream & print_set(std::ostream &o, format fmt={}) const
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
Compute the strongly connected components using Dijkstra's algorithm.
scc_dijkstra_impl(const Aut &aut)
std::unordered_map< state_t, std::size_t > low_
low_[s] is minimum of state that it can go.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
std::unordered_map< state_t, std::size_t > number_
Store the visit order of each state.
state_t_of< Aut > state_t
components_t components_
All components.
const detail::components_t< Aut > strong_components(const Aut &aut, scc_algo_t algo=scc_algo_t::tarjan_iterative)
Find all strongly connected components of aut.
detail::components_t< Aut > components_t
std::vector< component_t< Aut >> components_t
A set of strongly-connected components.
std::size_t low_max_
the maximum possible of a value in low_.
detail::component_t< Aut > component_t
Aggregate an automaton, and forward calls to it.
detail::components_t< Aut > components_t
std::size_t curr_state_num_
The current visited state.
const components_t & components() const
std::unordered_map< state_t, std::size_t > low_
low_[s] is minimum of low_{X}, with X is all states on output transitions of s.
transition_t_of< Aut > transition_t
Aut transpose(const transpose_automaton< Aut > &aut)
Tarjan's algorithm to find all strongly connected components: recursive implementation.
detail::component_t< Aut > component_t
scc_automaton< Aut > scc(const Aut &aut, const std::string &algo="auto")
Get scc_automaton from aut.
std::stack< state_t > uncertain_
Stack P contains vertices that have not yet been determined to belong to different strongly connected...
std::unordered_set< state_t > marked_
Visited states.
scc_algo_t scc_algo(const std::string &algo)
fresh_automaton_t_of< Aut > aut_of_component(const detail::component_t< Aut > &com, const Aut &aut)
Generate a subautomaton corresponding to an SCC.
Provide a variadic mul on top of a binary mul(), and one().
std::vector< state_t > stack_
List of states in the same the component.
An automaton decorator that maps states to their scc-number.
std::stack< state_t > unassigned_
Stack S contains all the vertices that have not yet been assigned to a strongly connected component...
Get all states in reverse postorder using depth first search.
const components_t & components() const
std::vector< state_t_of< Aut > > reverse_postorder(const Aut &aut)
Get all states in reverse postorder.
detail::components_t< Aut > components_t
std::vector< state_t > & reverse_post()
detail::component_t< Aut > component_t
Tarjan's algorithm to find all strongly connected components: iterative implementation.
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
reverse_postorder_impl(const Aut &aut)
std::unordered_set< state_t_of< Aut >> component_t
A strongly-connected component: set of states.
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
std::unordered_map< state_t, size_t > component_
For each state, its component number.
components_t components_
All components.
detail::component_t< Aut > component_t
std::unordered_map< state_t, size_t > preorder_
detail::components_t< Aut > components_t
decltype(aut_->out(state_t{}).begin()) iterator_t
Iterator on outgoing transitions.
std::map< state_t, size_t > component_
For each state, its component number.
ATTRIBUTE_PURE bool has(const std::deque< T, Allocator > &s, const T &e)
Whether e is member of s.
Step of one state contain infomation next successor and end iterator(output transitions or successors...
std::size_t num_
The current component number.
std::size_t count_
Current state number (not it's id, but its count).
static symbol sname()
Static name.
detail::components_t< Aut > components_t
const components_t & components() const
state_t_of< Aut > state_t
scc_automaton_impl(const automaton_t &input, scc_algo_t algo)
components_t components_
All the components.
#define BUILTIN_UNREACHABLE()
std::vector< step_t > dfs_stack_
step_t(state_t s, iterator_t p, iterator_t e)
state_t_of< Aut > state_t
std::vector< state_t > stack_
List of states in the same the component.
const components_t & components()
components_t components_
All components.
detail::component_t< Aut > component_t
Compute the strongly connected components using Kosaraju's algorithm.