Awali
Another Weighted Automata library
is_eps_acyclic.hh
Go to the documentation of this file.
1 // This file is part of Awali.
2 // Copyright 2016-2022 Sylvain Lombardy, Victor Marsault, Jacques Sakarovitch
3 //
4 // Awali is a free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef AWALI_ALGOS_IS_EPS_ACYCLIC_HH
18 # define AWALI_ALGOS_IS_EPS_ACYCLIC_HH
19 
20 # include <unordered_map>
21 
22 #include <awali/sttc/ctx/traits.hh>
24 
25 namespace awali { namespace sttc {
26 
27  namespace
28  {
29 
30  template <typename Aut,
31  bool has_one = context_t_of<Aut>::has_one()>
32  struct epsilon_acyclic;
33 
38  template <typename Aut>
39  struct epsilon_acyclic<Aut, true>
40  {
41  using automaton_t = typename std::remove_cv<Aut>::type;
42  using label_t = label_t_of<automaton_t>;
43  std::unordered_map<state_t, char> tag;
44  /*
45  tag gives the status of the state s;
46  if s is not in the map, the state has not been reached yet;
47  if tag[s]='u', the status is unknown, the graph reachable from s is
48  under exploration
49  if tag[s]='o', the status is "ok": there is no eps-circuit accessible
50  from s
51  if tag[s]='c', there is an eps-circuit accessible from s
52  */
53 
54  const automaton_t& aut_;
55  label_t empty_word;
56 
57  // Return true if an epsilon-circuit is accessible from s by
58  // epsilon-transitions.
59  bool has_epsilon_circuit(state_t s)
60  {
61  auto it = tag.find(s);
62  if (it == tag.end())
63  {
64  tag[s] = 'u';
65  for (auto t : aut_->out(s, empty_word))
66  if (has_epsilon_circuit(aut_->dst_of(t)))
67  {
68  tag[s] = 'c';
69  return true;
70  }
71  tag[s] = 'o';
72  return false;
73  }
74 
75  // Switch with respect to tag[s].
76  switch (it->second)
77  {
78  case 'u':
79  // s is reached while we are exploring successors of s:
80  // there is a circuit.
81  tag[s] = 'c';
82  return true;
83  // Otherwise the graph reachable from s has already been explored.
84  case 'o':
85  return false;
86  default: //'c'
87  return true;
88  }
89  }
90 
91  epsilon_acyclic(const automaton_t& aut)
92  : aut_(aut)
93  , empty_word(aut->labelset()->one())
94  {
95  }
96 
97  bool is_eps_acyclic()
98  {
99  for (auto s : aut_->states())
100  if (has_epsilon_circuit(s))
101  return false;
102  return true;
103  }
104  };
105 
106  template <typename Aut>
107  struct epsilon_acyclic<Aut, false>
108  {
109  using automaton_t = typename std::remove_cv<Aut>::type;
110 
111  constexpr epsilon_acyclic(const automaton_t&)
112  {}
113 
114  static constexpr bool is_eps_acyclic()
115  {
116  return true;
117  }
118  };
119  }
120 
121  template <typename Aut>
122  ATTRIBUTE_CONST
123  bool is_eps_acyclic(const Aut& aut)
124  {
125  epsilon_acyclic<Aut> t{aut};
126  return t.is_eps_acyclic();
127  }
128 
129 }}//end of ns awali::stc
130 
131 #endif // !AWALI_ALGOS_IS_EPS_ACYCLIC_HH
any_t label_t
Type for (transition) labels; it is an alias to any_t since its precise type depends on the weightset...
Definition: typedefs.hh:48
constant< type_t::one, Label, Weight > one
Definition: fwd.hh:116
ATTRIBUTE_CONST bool is_eps_acyclic(const Aut &aut)
Definition: is_eps_acyclic.hh:123
Main namespace of Awali.
Definition: ato.hh:22
unsigned state_t
Definition: types.hh:21