Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
scc.hh
Go to the documentation of this file.
1 #ifndef VCSN_ALGOS_SCC_HH
2 # define VCSN_ALGOS_SCC_HH
3 
4 # include <stack>
5 
6 # include <vcsn/dyn/automaton.hh>
7 # include <vcsn/dyn/fwd.hh>
8 # include <vcsn/algos/transpose.hh>
9 # include <vcsn/misc/builtins.hh>
11 # include <vcsn/misc/set.hh>
12 # include <vcsn/misc/vector.hh> // has
13 
14 namespace vcsn
15 {
16  /*-------------------------------.
17  | strongly connected component. |
18  `-------------------------------*/
19 
20  namespace detail
21  {
23  template <typename Aut>
24  using component_t = std::set<state_t_of<Aut>>;
25 
27  template <typename Aut>
28  using components_t = std::vector<component_t<Aut>>;
29 
32  template <typename Aut>
34  {
35  public:
39 
40  scc_tarjan_impl(const Aut& aut)
41  {
42  for (auto s : aut->states())
43  if (!has(marked_, s))
44  dfs(s, aut);
45  }
46 
48  {
49  return components_;
50  }
51 
52  private:
53  void dfs(state_t s, const Aut& aut)
54  {
55  std::size_t min = curr_vertex_num_++;
56  low_.emplace(s, min);
57  marked_.emplace(s);
58  stack_.push(s);
59 
60  for (auto t : aut->out(s))
61  {
62  auto dst = aut->dst_of(t);
63  if (!has(marked_, dst))
64  dfs(dst, aut);
65  if (low_[dst] < min)
66  min = low_[dst];
67  }
68  if (min < low_[s])
69  {
70  low_[s] = min;
71  return;
72  }
73 
74  state_t w;
75  components_.emplace_back(component_t{});
76  do
77  {
78  w = stack_.top();
79  stack_.pop();
80  components_[curr_comp_num_].emplace(w);
81  // This vertex belong only one component
82  // so remove it by update low value to max size.
83  low_[w] = aut->num_states() + 1;
84  }
85  while (w != s);
87  }
88 
90  std::size_t curr_comp_num_ = 0;
92  std::size_t curr_vertex_num_ = 0;
96  std::set<state_t> marked_;
98  std::unordered_map<state_t, std::size_t> low_;
100  std::stack<state_t> stack_;
101  };
102  }
103 
104 
105  /*--------------------.
106  | reverse_postorder. |
107  `--------------------*/
108 
109  namespace detail
110  {
113  template <typename Aut>
115  {
116  public:
118 
119  reverse_postorder_impl(const Aut& aut)
120  {
121  for (auto s : aut->all_states())
122  if (!has(marked_, s))
123  dfs(s, aut);
124  }
125 
126  std::stack<state_t>& reverse_post()
127  {
128  return rvp_;
129  }
130 
131  private:
132  void dfs(state_t s, const Aut& aut)
133  {
134  marked_.emplace(s);
135  for (auto t : aut->out(s))
136  {
137  auto dst = aut->dst_of(t);
138  if (!has(marked_, dst))
139  dfs(dst, aut);
140  }
141  rvp_.push(s);
142  }
143  std::stack<state_t> rvp_;
144  std::set<state_t> marked_;
145  std::stack<state_t> todo_;
146  };
147  }
148 
150  template <typename Aut>
151  std::stack<state_t_of<Aut>>
152  reverse_postorder(const Aut& aut)
153  {
155  return dv.reverse_post();
156  }
157 
158 
159  /*---------------.
160  | scc_kosaraju. |
161  `---------------*/
162 
163  namespace detail
164  {
167  template <typename Aut>
169  {
170  public:
174 
175  scc_kosaraju_impl(const Aut& aut)
176  {
177  auto trans = ::vcsn::transpose(aut);
178  auto todo = ::vcsn::reverse_postorder(trans);
179  while (!todo.empty())
180  {
181  auto s = todo.top();
182  todo.pop();
183  if (!has(marked_, s))
184  {
185  dfs(s, aut);
186  ++num_;
187  }
188  }
189  }
190 
192  {
193  return components_;
194  }
195 
196  private:
197  void dfs(state_t s, const Aut& aut)
198  {
199  marked_.emplace(s);
200  if (num_ == components_.size())
201  components_.emplace_back(component_t{s});
202  else
203  components_[num_].emplace(s);
204 
205  for (auto t : aut->out(s))
206  {
207  auto dst = aut->dst_of(t);
208  if (!has(marked_, dst))
209  dfs(dst, aut);
210  }
211  }
212 
214  std::size_t num_ = 0;
216  std::set<state_t> marked_;
217  };
218  }
219 
220  enum class SCC_ALGO
221  {
222  TARJAN = 0,
223  KOSARAJU = 1
224  };
225 
227  template <typename Aut>
228  const detail::components_t<Aut>
229  scc(const Aut& aut, SCC_ALGO algo = SCC_ALGO::TARJAN)
230  {
231  switch (algo)
232  {
233  case SCC_ALGO::TARJAN:
234  {
236  return scc.components();
237  }
238  case SCC_ALGO::KOSARAJU:
239  {
241  return scc.components();
242  }
243  }
245  }
246 
248  template <typename Aut>
249  typename Aut::element_type::automaton_nocv_t
250  aut_of_component(const detail::component_t<Aut>& com, const Aut& aut)
251  {
252  using res_t = typename Aut::element_type::automaton_nocv_t;
253  res_t res = make_shared_ptr<res_t>(aut->context());
254  std::unordered_map<state_t_of<Aut>, state_t_of<res_t>> map;
255  auto s0 = *com.begin();
256  map[s0] = res->new_state();
257  res->set_initial(map[s0]);
258  for (auto s : com)
259  {
260  if (!has(map, s))
261  map[s] = res->new_state();
262  for (auto t : aut->out(s))
263  {
264  auto dst = aut->dst_of(t);
265  if (!has(com, dst))
266  continue;
267  if (!has(map, dst))
268  map[dst] = res->new_state();
269  res->new_transition(map[s], map[dst], aut->label_of(t));
270  }
271  }
272  return res;
273  }
274 
275 
277  template <typename Aut>
278  std::size_t num_sccs(const Aut& aut)
279  {
280  return scc(aut).size();
281  }
282 
283  namespace dyn
284  {
285  namespace detail
286  {
287  // Bridge.
288  template <typename Aut>
289  std::size_t num_sccs(const automaton& aut)
290  {
291  const auto& a = aut->as<Aut>();
293  }
294 
296  (const automaton&) -> std::size_t);
297  }
298  }
299 
300 }
301 #endif // !VCSN_ALGOS_SCC_HH
void dfs(state_t s, const Aut &aut)
Definition: scc.hh:197
std::size_t num_sccs(const automaton &aut)
Definition: scc.hh:289
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
std::size_t curr_comp_num_
The current component number.
Definition: scc.hh:90
std::stack< state_t > stack_
Contains list vertices same the component.
Definition: scc.hh:100
Aut::element_type::automaton_nocv_t aut_of_component(const detail::component_t< Aut > &com, const Aut &aut)
Generate a subautomaton corresponding to an SCC.
Definition: scc.hh:250
void dfs(state_t s, const Aut &aut)
Definition: scc.hh:132
std::stack< state_t > & reverse_post()
Definition: scc.hh:126
SCC_ALGO
Definition: scc.hh:220
detail::component_t< Aut > component_t
Definition: scc.hh:37
std::size_t num_
The current component number.
Definition: scc.hh:214
components_t components_
Definition: scc.hh:215
std::stack< state_t_of< Aut > > reverse_postorder(const Aut &aut)
Get all vertices in reverse postorder.
Definition: scc.hh:152
detail::components_t< Aut > components_t
Definition: scc.hh:173
std::size_t num_sccs(const Aut &aut)
Get number of strongly connected components.
Definition: scc.hh:278
Use Tarjan's algorithm to find all strongly connected components.
Definition: scc.hh:33
std::set< state_t_of< Aut >> component_t
An strongly-connected component: list of states.
Definition: scc.hh:24
std::set< state_t > marked_
Definition: scc.hh:144
void dfs(state_t s, const Aut &aut)
Definition: scc.hh:53
reverse_postorder_impl(const Aut &aut)
Definition: scc.hh:119
std::unordered_map< state_t, std::size_t > low_
low_[s] is minimum of vertex that it can go
Definition: scc.hh:98
std::stack< state_t > rvp_
Definition: scc.hh:143
std::set< state_t > marked_
List visited vertices.
Definition: scc.hh:96
scc_kosaraju_impl(const Aut &aut)
Definition: scc.hh:175
state_t_of< Aut > state_t
Definition: scc.hh:36
auto map(const std::tuple< Ts...> &ts, Fun f) -> decltype(map_tuple_(f, ts, make_index_sequence< sizeof...(Ts)>()))
Map a function on a tuple, return tuple of the results.
Definition: tuple.hh:101
const components_t components()
Definition: scc.hh:191
detail::component_t< Aut > component_t
Definition: scc.hh:172
detail::components_t< Aut > components_t
Definition: scc.hh:38
std::stack< state_t > todo_
Definition: scc.hh:145
const detail::components_t< Aut > scc(const Aut &aut, SCC_ALGO algo=SCC_ALGO::TARJAN)
Find all strongly connected components of aut.
Definition: scc.hh:229
Use Kosajaju algorithm for finding all of strongly connected components.
Definition: scc.hh:168
Get all vertices in reverse postorder by using depth first search.
Definition: scc.hh:114
components_t components_
All compnents.
Definition: scc.hh:94
Aut transpose(const transpose_automaton< Aut > &aut)
Definition: transpose.hh:230
state_t_of< Aut > state_t
Definition: scc.hh:117
std::size_t curr_vertex_num_
The current visited vertex.
Definition: scc.hh:92
state_t_of< Aut > state_t
Definition: scc.hh:171
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:35
std::set< state_t > marked_
Definition: scc.hh:216
const components_t components()
Definition: scc.hh:47
#define BUILTIN_UNREACHABLE()
Definition: builtins.hh:14
scc_tarjan_impl(const Aut &aut)
Definition: scc.hh:40
std::vector< component_t< Aut >> components_t
A set of strongly-connected components.
Definition: scc.hh:28
bool has(const std::map< Key, Value, Compare, Alloc > &s, const Key &e)
Definition: map.hh:35