Vcsn  2.5.dev
Be Rational
is-acyclic.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <unordered_map>
4 
5 #include <boost/optional.hpp>
6 
7 #include <vcsn/core/automaton.hh>
8 #include <vcsn/core/fwd.hh>
9 #include <vcsn/ctx/traits.hh>
10 #include <vcsn/dyn/automaton.hh>
11 #include <vcsn/misc/attributes.hh>
12 #include <vcsn/misc/builtins.hh>
13 
14 namespace vcsn
15 {
16  namespace detail
17  {
19  template <Automaton Aut>
21  {
22  public:
23  using automaton_t = std::remove_cv_t<Aut>;
26 
28  boost::optional<label_t> label = {})
29  : aut_(aut)
30  , one_(label)
31  {}
32 
34  bool operator()()
35  {
36  return none_of(aut_->states(),
37  [this](auto s) { return this->has_circuit_(s); });
38  }
39 
40  private:
43  {
44  auto it = tag_.find(s);
45  if (it == tag_.end())
46  {
47  tag_[s] = unknown;
48  // Code duplication because `out(aut_, s, *one)` and
49  // `out(aut_, s)` have different return types.
50  if (one_)
51  {
52  for (auto t : out(aut_, s, *one_))
53  if ((aut_->dst_of(t) == s && aut_->label_of(t) == *one_)
54  || has_circuit_(aut_->dst_of(t)))
55  {
56  tag_[s] = circuit;
57  return true;
58  }
59  }
60  else
61  {
62  for (auto t : out(aut_, s))
63  if (aut_->dst_of(t) == s || has_circuit_(aut_->dst_of(t)))
64  {
65  tag_[s] = circuit;
66  return true;
67  }
68  }
69  tag_[s] = ok;
70  return false;
71  }
72 
73  // Switch with respect to tag_[s].
74  switch (it->second)
75  {
76  case unknown:
77  // s is reached while we are exploring successors of s:
78  // there is a circuit.
79  tag_[s] = circuit;
80  return true;
81  case ok:
82  // Otherwise the graph reachable from s has already been explored.
83  return false;
84  case circuit:
85  return true;
86  }
88  }
89 
90  enum status
91  {
95  ok,
98  };
99 
100  // States not in the map have not been reached yet.
101  std::unordered_map<state_t, status> tag_;
102 
104  boost::optional<label_t> one_;
105  };
106  }
107 
111  template <Automaton Aut>
112  ATTRIBUTE_CONST
113  std::enable_if_t<context_t_of<Aut>::has_one(), bool>
114  is_eps_acyclic(const Aut& aut)
115  {
116  auto is_acyclic = detail::is_acyclic_impl<Aut>{aut, aut->labelset()->one()};
117  return is_acyclic();
118  }
119 
120  template <Automaton Aut>
121  ATTRIBUTE_CONST
122  std::enable_if_t<!context_t_of<Aut>::has_one(), bool>
123  is_eps_acyclic(const Aut&)
124  {
125  return true;
126  }
127 
128  template <Automaton Aut>
129  ATTRIBUTE_CONST
130  bool
131  is_acyclic(const Aut& aut)
132  {
134  return is_acyclic();
135  }
136 
137  namespace dyn
138  {
139  namespace detail
140  {
142  template <Automaton Aut>
143  bool is_eps_acyclic(const automaton& aut)
144  {
145  return is_eps_acyclic(aut->as<Aut>());
146  }
147  }
148  }
149 } // namespace vcsn
bool operator()()
Whether the automaton is acyclic.
Definition: is-acyclic.hh:34
ATTRIBUTE_CONST std::enable_if_t< context_t_of< Aut >::has_one(), bool > is_eps_acyclic(const Aut &aut)
Detect epsilon-circuits.
Definition: is-acyclic.hh:114
std::unordered_map< state_t, status > tag_
Definition: is-acyclic.hh:101
label_t_of< automaton_t > label_t
Definition: is-acyclic.hh:25
boost::optional< label_t > one_
Definition: is-acyclic.hh:104
std::remove_cv_t< Aut > automaton_t
Definition: is-acyclic.hh:23
ATTRIBUTE_CONST bool is_acyclic(const Aut &aut)
Definition: is-acyclic.hh:131
typename detail::label_t_of_impl< base_t< ValueSet > >::type label_t_of
Definition: traits.hh:62
bool none_of(const Range &r, Predicate p)
Definition: algorithm.hh:193
There is an circuit accessible from s.
Definition: is-acyclic.hh:97
bool has_circuit_(state_t s)
Whether a circuit is accessible from s.
Definition: is-acyclic.hh:42
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:86
Definition: a-star.hh:8
value_impl< detail::label_tag > label
Definition: fwd.hh:32
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
There is no circuit accessible from s.
Definition: is-acyclic.hh:95
auto & as()
Extract wrapped typed automaton.
Definition: automaton.hh:37
A dyn automaton.
Definition: automaton.hh:17
The graph reachable from s is under exploration.
Definition: is-acyclic.hh:93
is_acyclic_impl(const automaton_t &aut, boost::optional< label_t > label={})
Definition: is-acyclic.hh:27
state_t_of< automaton_t > state_t
Definition: is-acyclic.hh:24
#define BUILTIN_UNREACHABLE()
Definition: builtins.hh:13