Vcsn  2.8
Be Rational
is-ambiguous.hh
Go to the documentation of this file.
1 #pragma once
2 
4 #include <vcsn/algos/shortest.hh>
5 #include <vcsn/algos/conjunction.hh> // conjunction
6 #include <vcsn/algos/scc.hh>
7 #include <vcsn/dyn/fwd.hh>
8 #include <vcsn/dyn/value.hh>
9 
10 namespace vcsn
11 {
12 
13  /*---------------.
14  | is_ambiguous. |
15  `---------------*/
16 
17  namespace detail
18  {
20  template <Automaton Aut>
22  {
23  static_assert(labelset_t_of<Aut>::is_free(),
24  "is_ambiguous: requires free labelset");
25  using automaton_t = Aut;
26  using conjunction_t
27  = decltype(conjunction(std::declval<automaton_t>(),
28  std::declval<automaton_t>()));
30 
34  // FIXME: this product should not take weights into account!
35  : conj_{conjunction(aut, aut)}
36  {}
37 
41  bool operator()()
42  {
43  // Check if there useful states outside of the diagonal.
44  // Since the conjunction is accessible, check only for
45  // coaccessibles states.
47  for (const auto& o: conj_->origins())
48  if (std::get<0>(o.second) != std::get<1>(o.second)
49  && has(coaccessible, o.first))
50  {
51  witness_ = o.first;
52  return true;
53  }
54  return false;
55  }
56 
60  {
61  require(witness_ != conj_->null_state(),
62  "ambiguous_word: automaton is unambiguous, "
63  "or has not been tested, for ambiguity");
64  const auto ls = make_wordset(*conj_->labelset());
65 
66  auto p1 = shortest(conj_, conj_->pre(), witness_);
67  auto p2 = shortest(conj_, witness_, conj_->post());
68 
69  assert(!p1.empty() || !p2.empty()
70  || !"ambiguous_word: did not find an ambiguous word");
71  return ls.mul(p1.empty() ? ls.one() : p1.begin()->first,
72  p2.empty() ? ls.one() : p2.begin()->first);
73  }
74 
79  state_t_of<conjunction_t> witness_ = conj_->null_state();
80  };
81  }
82 
87  template <Automaton Aut>
88  bool is_ambiguous(const Aut& aut)
89  {
91  return is_ambiguous();
92  }
93 
94  namespace dyn
95  {
96  namespace detail
97  {
99  template <Automaton Aut>
100  bool is_ambiguous(const automaton& aut)
101  {
102  return is_ambiguous(aut->as<Aut>());
103  }
104  }
105  }
106 
107 
108  /*-----------------.
109  | ambiguous_word. |
110  `-----------------*/
111 
112  template <Automaton Aut>
114  {
116  require(is_ambiguous(), "ambiguous_word: automaton is unambiguous");
117  return is_ambiguous.ambiguous_word();
118  }
119 
120  namespace dyn
121  {
122  namespace detail
123  {
125  template <Automaton Aut>
126  label
128  {
129  const auto& a = aut->as<Aut>();
130  auto word = vcsn::ambiguous_word(a);
131  return {make_wordset(*a->labelset()), word};
132  }
133  }
134  }
135 
136 
137 
138  /*---------------------.
139  | is_cycle_ambiguous. |
140  `---------------------*/
141 
143  template <Automaton Aut>
144  bool is_cycle_ambiguous(const Aut& aut)
145  {
146  static_assert(labelset_t_of<Aut>::is_free(),
147  "is_cycle_ambiguous: requires free labelset");
148  // Find all strongly connected components.
149  const auto& coms = strong_components(aut,
151  // Check each component if it is cycle-ambiguous.
152  if (coms.size() == 1)
153  return is_cycle_ambiguous_scc(aut);
154  for (const auto &c : coms)
155  {
156  const auto& a = aut_of_component(c, aut);
157  if (is_cycle_ambiguous_scc(a))
158  return true;
159  }
160  return false;
161  }
162 
166  template <Automaton Aut>
167  bool is_cycle_ambiguous_scc(const Aut& aut)
168  {
169  auto conj = conjunction(aut, aut);
170  const auto& coms = strong_components(conj,
172  const auto& origins = conj->origins();
173  // In one SCC of conj = aut & aut, if there exist two states (s0,
174  // s0) (on the diagonal) and (s1, s2) with s1 != s2 (off the
175  // diagonal) then aut has two cycles with the same label:
176  // s0->s1->s0 and s0->s2->s0.
177  for (const auto& c : coms)
178  {
179  bool on = false;
180  bool off = false;
181  for (auto s : c)
182  {
183  auto p = origins.at(s);
184  if (std::get<0>(p) == std::get<1>(p))
185  on = true;
186  else
187  off = true;
188  if (on && off)
189  return true;
190  }
191  }
192  return false;
193  }
194 
195  namespace dyn
196  {
197  namespace detail
198  {
200  template <Automaton Aut>
201  bool
203  {
204  const auto& a = aut->as<Aut>();
206  }
207  }
208  }
209 }
A dyn automaton.
Definition: automaton.hh:17
state_t_of< conjunction_t > witness_
State index in the conjunction of a state that is not on the diagonal.
Definition: is-ambiguous.hh:79
ATTRIBUTE_PURE bool has(const boost::container::flat_set< Key, Compare, Allocator > &s, const Key &e)
Whether e is member of s.
Definition: setalpha.hh:26
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
decltype(conjunction(std::declval< automaton_t >(), std::declval< automaton_t >())) conjunction_t
Definition: is-ambiguous.hh:28
const detail::components_t< Aut > strong_components(const Aut &aut, Tag={})
Find all strongly connected components of aut.
Definition: scc.hh:544
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:577
word_t_of< automaton_t > word_t
Definition: is-ambiguous.hh:29
A dyn Value/ValueSet.
Definition: fwd.hh:29
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
word_t ambiguous_word() const
A witness of ambiguity.
Definition: is-ambiguous.hh:59
bool is_ambiguous(const Aut &aut)
Whether an automaton is ambiguous.
Definition: is-ambiguous.hh:88
Definition: a-star.hh:8
auto conjunction(const Aut &a, const Auts &... as)
Build the (accessible part of the) conjunction.
Definition: conjunction.hh:621
filter_automaton< Aut > coaccessible(const Aut &a)
Coaccessible part of an automaton.
Definition: accessible.hh:146
detail::enumerater< Aut >::polynomial_t shortest(const Aut &aut, boost::optional< unsigned > num={}, boost::optional< unsigned > len={})
The approximated behavior of an automaton.
Definition: shortest.hh:279
Whether an automaton is ambiguous.
Definition: is-ambiguous.hh:21
auto & as()
Extract wrapped typed automaton.
Definition: automaton.hh:37
bool is_cycle_ambiguous(const Aut &aut)
Whether aut is cycle-ambiguous.
bool operator()()
Whether an automaton is ambiguous.
Definition: is-ambiguous.hh:41
states_t< Aut > coaccessible_states(const Aut &a, bool strict=true)
The set of coaccessible states, including post(), and possibly pre().
Definition: accessible.hh:68
bool is_cycle_ambiguous_scc(const Aut &aut)
Whether aut is cycle-ambiguous.
typename labelset_t_of< base_t< ValueSet > >::word_t word_t_of
Definition: traits.hh:90
value_impl< detail::label_tag > label
Definition: fwd.hh:32
is_ambiguous_impl(const automaton_t &aut)
Constructor.
Definition: is-ambiguous.hh:33
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:259
conjunction_t conj_
The self-conjunction of the input automaton.
Definition: is-ambiguous.hh:76
word_t_of< Aut > ambiguous_word(const Aut &aut)
void require(Bool b, Args &&... args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:87
bool is_cycle_ambiguous(const automaton &aut)
Bridge.