Vcsn  2.1
Be Rational
is-ambiguous.hh
Go to the documentation of this file.
1 #pragma once
2 
4 #include <vcsn/algos/distance.hh>
5 #include <vcsn/algos/conjunction.hh> // conjunction
6 #include <vcsn/algos/scc.hh>
7 #include <vcsn/dyn/fwd.hh>
8 
9 namespace vcsn
10 {
11 
12  /*---------------.
13  | is_ambiguous. |
14  `---------------*/
15 
21  template <typename Aut>
22  bool is_ambiguous(const Aut& aut,
24  {
25  auto prod = conjunction(aut, aut);
26  // Check if there useful states outside of the diagonal. Since
27  // the conjunction is accessible, check only for coaccessibles states.
28  auto coaccessible = coaccessible_states(prod);
29  for (const auto& o: prod->origins())
30  if (std::get<0>(o.second) != std::get<1>(o.second)
31  && has(coaccessible, o.first))
32  {
33  witness = o.second;
34  return true;
35  }
36  return false;
37  }
38 
39  template <typename Aut>
40  bool is_ambiguous(const Aut& aut)
41  {
42  std::tuple<state_t_of<Aut>, state_t_of<Aut>> dummy;
43  return is_ambiguous(aut, dummy);
44  }
45 
46  namespace dyn
47  {
48  namespace detail
49  {
51  template <typename Aut>
52  bool is_ambiguous(const automaton& aut)
53  {
54  return is_ambiguous(aut->as<Aut>());
55  }
56  }
57  }
58 
59 
60  /*-----------------.
61  | ambiguous_word. |
62  `-----------------*/
63 
64  template <typename Aut>
66  {
67  std::tuple<state_t_of<Aut>, state_t_of<Aut>> witness;
68  require(is_ambiguous(aut, witness),
69  "automaton is unambiguous");
70  const auto& ls = *aut->labelset();
71  word_t_of<Aut> res;
72  // Find the shortest word from initial to the witness.
73  auto s = std::get<0>(witness);
74  for (auto t: path_bfs(aut, aut->pre(), s))
75  {
76  auto l = aut->label_of(t);
77  if (!ls.is_special(l))
78  res = ls.mul(res, l);
79  }
80  for (auto t: path_bfs(aut, s, aut->post()))
81  {
82  auto l = aut->label_of(t);
83  if (!ls.is_special(l))
84  res = ls.mul(res, l);
85  }
86  return res;
87  }
88 
89 
90  namespace dyn
91  {
92  namespace detail
93  {
95  template <typename Aut>
96  label
98  {
99  const auto& a = aut->as<Aut>();
100  auto word = vcsn::ambiguous_word(a);
101  return make_label(make_wordset(*a->labelset()), word);
102  }
103  }
104  }
105 
106 
107 
108  /*---------------------.
109  | is_cycle_ambiguous. |
110  `---------------------*/
111 
113  template <typename Aut>
114  bool is_cycle_ambiguous(const Aut& aut)
115  {
116  // Find all strongly connected components.
117  const auto& coms = strong_components(aut,
119  if (getenv("VCSN_DEBUG"))
120  {
121  std::cerr << "number states of automaton: " <<
122  aut->num_states() << std::endl;
123  std::cerr << "number components: " <<
124  coms.size() << std::endl;
125  }
126 
127  // Check each component if it is cycle-ambiguous.
128  if (coms.size() == 1)
129  return is_cycle_ambiguous_scc(aut);
130  for (const auto &c : coms)
131  {
132  const auto& a = aut_of_component(c, aut);
133  if (is_cycle_ambiguous_scc(a))
134  return true;
135  }
136  return false;
137  }
138 
141  template <typename Aut>
142  bool is_cycle_ambiguous_scc(const Aut& aut)
143  {
144  auto prod = conjunction(aut, aut);
145  const auto& coms = strong_components(prod,
147  const auto& origins = prod->origins();
148  // In one SCC of prod = aut & aut, if there exist two states (s0,
149  // s0) (on the diagonal) and (s1, s2) with s1 != s2 (off the
150  // diagonal) then aut has two cycles with the same label:
151  // s0->s1->s0 and s0->s2->s0.
152  for (const auto& c : coms)
153  {
154  bool on = false;
155  bool off = false;
156  for (auto s : c)
157  {
158  auto p = origins.at(s);
159  if (std::get<0>(p) == std::get<1>(p))
160  on = true;
161  else
162  off = true;
163  if (on && off)
164  return true;
165  }
166  }
167  return false;
168  }
169 
170  namespace dyn
171  {
172  namespace detail
173  {
175  template <typename Aut>
176  bool
178  {
179  const auto& a = aut->as<Aut>();
181  }
182  }
183  }
184 }
states_t< Aut > coaccessible_states(const Aut &a, bool strict=true)
The set of coaccessible states, including post(), and possibly pre().
Definition: accessible.hh:64
std::shared_ptr< const detail::label_base > label
Definition: fwd.hh:59
std::vector< transition_t_of< Aut > > path_bfs(const Aut &aut, state_t_of< Aut > start, state_t_of< Aut > end)
A shortest path between two states.
Definition: distance.hh:233
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:48
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.
Definition: scc.hh:491
filter_automaton< Aut > coaccessible(const Aut &a)
Coaccessible part of an automaton.
Definition: accessible.hh:142
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
Definition: tuple.hh:28
typename labelset_t_of< base_t< ValueSet >>::word_t word_t_of
Definition: traits.hh:65
bool is_ambiguous(const Aut &aut)
Definition: is-ambiguous.hh:40
fresh_automaton_t_of< Aut > aut_of_component(const detail::component_t< Aut > &com, const Aut &aut)
Generate a subautomaton corresponding to an SCC.
Definition: scc.hh:512
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:261
auto conjunction(const Auts &...as) -> tuple_automaton< decltype(meet_automata(as...)), Auts...>
Build the (accessible part of the) conjunction.
Definition: conjunction.hh:553
word_t_of< Aut > ambiguous_word(const Aut &aut)
Definition: is-ambiguous.hh:65
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:75
bool is_cycle_ambiguous_scc(const Aut &aut)
Whether aut is cycle-ambiguous.
bool is_cycle_ambiguous(const automaton &aut)
Bridge.
bool is_cycle_ambiguous(const Aut &aut)
Whether aut is cycle-ambiguous.
ATTRIBUTE_PURE bool has(const std::deque< T, Allocator > &s, const T &e)
Whether e is member of s.
Definition: deque.hh:13
bool is_ambiguous(const automaton &aut)
Bridge.
Definition: is-ambiguous.hh:52
label ambiguous_word(const automaton &aut)
Bridge.
Definition: is-ambiguous.hh:97
label make_label(const LabelSet &ls, const typename LabelSet::value_t &l)
Definition: label.hh:80