Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
is-eps-acyclic.hh
Go to the documentation of this file.
1 #ifndef VCSN_ALGOS_IS_EPS_ACYCLIC_HH
2 # define VCSN_ALGOS_IS_EPS_ACYCLIC_HH
3 
4 # include <unordered_map>
5 
6 # include <vcsn/ctx/traits.hh>
7 # include <vcsn/misc/attributes.hh>
8 # include <vcsn/dyn/automaton.hh>
9 # include <vcsn/core/fwd.hh>
10 
11 namespace vcsn
12 {
13  namespace detail
14  {
15 
16  template <typename Aut,
17  bool has_one = context_t_of<Aut>::has_one()>
19 
23  template <typename Aut>
24  struct epsilon_acyclic<Aut, true>
25  {
26  using automaton_t = typename std::remove_cv<Aut>::type;
29  std::unordered_map<state_t, char> tag;
30  /*
31  tag gives the status of the state s;
32  if s is not in the map, the state has not been reached yet;
33  if tag[s]='u', the status is unknown, the graph reachable from s is
34  under exploration
35  if tag[s]='o', the status is "ok": there is no eps-circuit accessible
36  from s
37  if tag[s]='c', there is an eps-circuit accessible from s
38  */
39 
40  const automaton_t& aut_;
42 
43  // Return true if an epsilon-circuit is accessible from s by
44  // epsilon-transitions.
46  {
47  auto it = tag.find(s);
48  if (it == tag.end())
49  {
50  tag[s] = 'u';
51  for (auto t : aut_->out(s, empty_word))
52  if (has_epsilon_circuit(aut_->dst_of(t)))
53  {
54  tag[s] = 'c';
55  return true;
56  }
57  tag[s] = 'o';
58  return false;
59  }
60 
61  // Switch with respect to tag[s].
62  switch (it->second)
63  {
64  case 'u':
65  // s is reached while we are exploring successors of s:
66  // there is a circuit.
67  tag[s] = 'c';
68  return true;
69  // Otherwise the graph reachable from s has already been explored.
70  case 'o':
71  return false;
72  default: //'c'
73  return true;
74  }
75  }
76 
78  : aut_(aut)
79  , empty_word(aut->labelset()->one())
80  {
81  }
82 
84  {
85  for (auto s : aut_->states())
86  if (has_epsilon_circuit(s))
87  return false;
88  return true;
89  }
90  };
91 
92  template <typename Aut>
93  struct epsilon_acyclic<Aut, false>
94  {
95  using automaton_t = typename std::remove_cv<Aut>::type;
96 
97  constexpr epsilon_acyclic(const automaton_t&)
98  {}
99 
100  static constexpr bool is_eps_acyclic()
101  {
102  return true;
103  }
104  };
105  }
106 
107  template <typename Aut>
108  ATTRIBUTE_CONST
109  bool is_eps_acyclic(const Aut& aut)
110  {
112  return t.is_eps_acyclic();
113  }
114 
115  /*---------------------.
116  | dyn::is_eps_acyclic. |
117  `---------------------*/
118 
119  namespace dyn
120  {
121  namespace detail
122  {
123 
124  template <typename Aut>
125  bool is_eps_acyclic(const automaton& aut)
126  {
127  return is_eps_acyclic(aut->as<Aut>());
128  }
129 
131  (const automaton&) -> bool);
132 
133  }
134  }
135 } // namespace vcsn
136 
137 #endif // !VCSN_ALGOS_IS_EPS_ACYCLIC_HH
std::unordered_map< state_t, char > tag
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
constexpr epsilon_acyclic(const automaton_t &)
typename std::remove_cv< Aut >::type automaton_t
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:33
ATTRIBUTE_CONST bool is_eps_acyclic(const Aut &aut)
typename std::remove_cv< Aut >::type automaton_t
bool is_eps_acyclic(const automaton &aut)
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:35