Vcsn  2.4
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  using automaton_t = Aut;
24  using conjunction_t
25  = decltype(conjunction(std::declval<automaton_t>(),
26  std::declval<automaton_t>()));
28 
32  // FIXME: this product should not take weights into account!
33  : conj_{conjunction(aut, aut)}
34  {}
35 
39  bool operator()()
40  {
41  // Check if there useful states outside of the diagonal.
42  // Since the conjunction is accessible, check only for
43  // coaccessibles states.
45  for (const auto& o: conj_->origins())
46  if (std::get<0>(o.second) != std::get<1>(o.second)
47  && has(coaccessible, o.first))
48  {
49  witness_ = o.first;
50  return true;
51  }
52  return false;
53  }
54 
56  {
57  require(witness_ != conj_->null_state(),
58  "ambiguous_word: automaton is unambiguous, "
59  "or has not been tested, for ambiguity");
60  const auto ls = make_wordset(*conj_->labelset());
61 
62  auto p1 = shortest(conj_, conj_->pre(), witness_);
63  auto p2 = shortest(conj_, witness_, conj_->post());
64 
65  assert(!p1.empty() || !p2.empty()
66  || !"ambiguous_word: did not find an ambiguous word");
67  return ls.mul(p1.empty() ? ls.one() : p1.begin()->first,
68  p2.empty() ? ls.one() : p2.begin()->first);
69 
70  }
71 
76  state_t_of<conjunction_t> witness_ = conj_->null_state();
77  };
78  }
79 
84  template <Automaton Aut>
85  bool is_ambiguous(const Aut& aut)
86  {
88  return is_ambiguous();
89  }
90 
91  namespace dyn
92  {
93  namespace detail
94  {
96  template <Automaton Aut>
97  bool is_ambiguous(const automaton& aut)
98  {
99  return is_ambiguous(aut->as<Aut>());
100  }
101  }
102  }
103 
104 
105  /*-----------------.
106  | ambiguous_word. |
107  `-----------------*/
108 
109  template <Automaton Aut>
111  {
113  require(is_ambiguous(), "ambiguous_word: automaton is unambiguous");
114  return is_ambiguous.ambiguous_word();
115  }
116 
117  namespace dyn
118  {
119  namespace detail
120  {
122  template <Automaton Aut>
123  label
125  {
126  const auto& a = aut->as<Aut>();
127  auto word = vcsn::ambiguous_word(a);
128  return {make_wordset(*a->labelset()), word};
129  }
130  }
131  }
132 
133 
134 
135  /*---------------------.
136  | is_cycle_ambiguous. |
137  `---------------------*/
138 
140  template <Automaton Aut>
141  bool is_cycle_ambiguous(const Aut& aut)
142  {
143  // Find all strongly connected components.
144  const auto& coms = strong_components(aut,
146  // Check each component if it is cycle-ambiguous.
147  if (coms.size() == 1)
148  return is_cycle_ambiguous_scc(aut);
149  for (const auto &c : coms)
150  {
151  const auto& a = aut_of_component(c, aut);
152  if (is_cycle_ambiguous_scc(a))
153  return true;
154  }
155  return false;
156  }
157 
161  template <Automaton Aut>
162  bool is_cycle_ambiguous_scc(const Aut& aut)
163  {
164  auto prod = conjunction(aut, aut);
165  const auto& coms = strong_components(prod,
167  const auto& origins = prod->origins();
168  // In one SCC of prod = aut & aut, if there exist two states (s0,
169  // s0) (on the diagonal) and (s1, s2) with s1 != s2 (off the
170  // diagonal) then aut has two cycles with the same label:
171  // s0->s1->s0 and s0->s2->s0.
172  for (const auto& c : coms)
173  {
174  bool on = false;
175  bool off = false;
176  for (auto s : c)
177  {
178  auto p = origins.at(s);
179  if (std::get<0>(p) == std::get<1>(p))
180  on = true;
181  else
182  off = true;
183  if (on && off)
184  return true;
185  }
186  }
187  return false;
188  }
189 
190  namespace dyn
191  {
192  namespace detail
193  {
195  template <Automaton Aut>
196  bool
198  {
199  const auto& a = aut->as<Aut>();
201  }
202  }
203  }
204 }
bool is_ambiguous(const automaton &aut)
Bridge.
Definition: is-ambiguous.hh:97
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:573
bool is_cycle_ambiguous_scc(const Aut &aut)
Whether aut is cycle-ambiguous.
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
word_t_of< automaton_t > word_t
Definition: is-ambiguous.hh:27
bool is_cycle_ambiguous(const automaton &aut)
Whether the automaton is cycle-ambiguous.
Definition: a-star.hh:8
automaton conjunction(const automaton &lhs, const automaton &rhs, bool lazy=false)
The conjunction (aka synchronized product) of automata.
Definition: others.cc:24
bool is_ambiguous(const Aut &aut)
Whether an automaton is ambiguous.
Definition: is-ambiguous.hh:85
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:276
word_t_of< Aut > ambiguous_word(const Aut &aut)
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:64
typename labelset_t_of< base_t< ValueSet >>::word_t word_t_of
Definition: traits.hh:90
A dyn automaton.
Definition: automaton.hh:17
is_ambiguous_impl(const automaton_t &aut)
Constructor.
Definition: is-ambiguous.hh:31
conjunction_t conj_
The self-conjunction of the input automaton.
Definition: is-ambiguous.hh:73
decltype(conjunction(std::declval< automaton_t >(), std::declval< automaton_t >())) conjunction_t
Definition: is-ambiguous.hh:26
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
filter_automaton< Aut > coaccessible(const Aut &a)
Coaccessible part of an automaton.
Definition: accessible.hh:142
value_impl< detail::label_tag > label
Definition: fwd.hh:26
A dyn Value/ValueSet.
Definition: fwd.hh:23
state_t_of< conjunction_t > witness_
State index in the conjunction of a state that is not on the diagonal.
Definition: is-ambiguous.hh:76
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:25
bool operator()()
Whether an automaton is ambiguous.
Definition: is-ambiguous.hh:39
auto & as()
Extract wrapped typed automaton.
Definition: automaton.hh:37
bool is_cycle_ambiguous(const automaton &aut)
Bridge.
auto conjunction(const Aut &a, const Auts &...as)
Build the (accessible part of the) conjunction.
Definition: conjunction.hh:622
Whether an automaton is ambiguous.
Definition: is-ambiguous.hh:21
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:260
label ambiguous_word(const automaton &aut)
Bridge.
const detail::components_t< Aut > strong_components(const Aut &aut, Tag={})
Find all strongly connected components of aut.
Definition: scc.hh:540