Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
standard.hh
Go to the documentation of this file.
1 #ifndef VCSN_ALGOS_STANDARD_HH
2 # define VCSN_ALGOS_STANDARD_HH
3 
4 # include <set>
5 
6 # include <vcsn/algos/copy.hh>
7 # include <vcsn/algos/transpose.hh>
9 # include <vcsn/core/rat/visitor.hh>
10 # include <vcsn/ctx/fwd.hh>
11 # include <vcsn/ctx/traits.hh>
12 # include <vcsn/dyn/automaton.hh>
13 # include <vcsn/dyn/ratexp.hh>
14 # include <vcsn/misc/memory.hh>
15 # include <vcsn/misc/raise.hh>
16 
17 namespace vcsn
18 {
19 
20  /*-------------------------.
21  | is_standard(automaton). |
22  `-------------------------*/
23 
25  template <typename Aut>
26  bool
27  is_standard(const Aut& a)
28  {
29  auto inis = a->initial_transitions();
30  return
31  inis.size() == 1
32  && a->weightset()->is_one(a->weight_of(inis.front()))
33  // No arrival on the initial state.
34  && a->in(a->dst_of(inis.front())).empty();
35  }
36 
38  template <typename Aut>
39  bool
40  is_costandard(const Aut& a)
41  {
42  return is_standard(transpose(a));
43  }
44 
45 
46  namespace dyn
47  {
48  namespace detail
49  {
51  template <typename Aut>
52  bool
53  is_standard(const automaton& aut)
54  {
55  const auto& a = aut->as<Aut>();
56  return is_standard(a);
57  }
58 
60  (const automaton& e) -> bool);
61 
63  template <typename Aut>
64  bool
66  {
67  const auto& a = aut->as<Aut>();
68  return is_costandard(a);
69  }
70 
72  (const automaton& e) -> bool);
73  }
74  }
75 
76  /*----------------------.
77  | standard(automaton). |
78  `----------------------*/
79 
83  template <typename Aut>
84  void
85  standard_here(Aut& aut)
86  {
87  if (is_standard(aut))
88  return;
89 
90  const auto& ws = *aut->weightset();
91  const auto& inits = aut->initial_transitions();
92  std::vector<transition_t_of<Aut>> initials{begin(inits), end(inits)};
93 
94  // See TAF-Kit documentation for the implementation details.
95  //
96  // (i.a) Add a new state s...
97  auto ini = aut->new_state();
98  for (auto ti: initials)
99  {
100  // The initial state.
101  auto i = aut->dst_of(ti);
102  auto wi = aut->weight_of(ti);
103  for (auto t: aut->all_out(i))
104  aut->new_transition(ini, aut->dst_of(t), aut->label_of(t),
105  ws.mul(wi, aut->weight_of(t)));
106  aut->del_transition(ti);
107 
108  // (iv) Remove the former initial states of A that are the
109  // destination of no incoming transition.
110  if (aut->all_in(i).empty())
111  aut->del_state(i);
112  }
113  // (i.b) Make [state s] initial, with initial multiplicity equal
114  // to the unit of the multiplicity semiring.
115  aut->set_initial(ini);
116  }
117 
118  template <typename Aut>
119  auto
120  standard(const Aut& aut)
121  -> decltype(copy(aut))
122  {
123  auto res = copy(aut);
124  standard_here(res);
125  return res;
126  }
127 
128  template <typename Aut>
129  auto
130  costandard(const Aut& aut)
131  -> decltype(copy(aut))
132  {
133  return transpose(standard(transpose(aut)));
134  }
135 
136 
137  namespace dyn
138  {
139  namespace detail
140  {
142  template <typename Aut>
143  automaton
144  standard(const automaton& aut)
145  {
146  const auto& a = aut->as<Aut>();
147  return make_automaton(::vcsn::standard(a));
148  }
149 
151 
153  template <typename Aut>
154  automaton
155  costandard(const automaton& aut)
156  {
157  const auto& a = aut->as<Aut>();
158  return make_automaton(costandard(a));
159  }
160 
162  }
163  }
164 
165 
166  /*-------------------.
167  | standard(ratexp). |
168  `-------------------*/
169 
170  namespace rat
171  {
176  template <typename Aut,
177  typename RatExpSet>
179  : public RatExpSet::const_visitor
180  {
181  public:
182  using automaton_t = Aut;
183  using ratexpset_t = RatExpSet;
187 
188  using super_t = typename ratexpset_t::const_visitor;
189 
190  constexpr static const char* me() { return "standard"; }
191 
193  : rs_(rs)
195  {}
196 
198  operator()(const typename ratexpset_t::value_t& v)
199  {
200  v->accept(*this);
201  res_->set_initial(initial_);
202  return res_;
203  }
204 
210 
212  {
213  initial_ = res_->new_state();
214  }
215 
217  {
218  auto i = res_->new_state();
219  initial_ = i;
220  res_->set_final(i);
221  }
222 
224  {
225  auto i = res_->new_state();
226  auto f = res_->new_state();
227  initial_ = i;
228  res_->new_transition(i, f, e.value());
229  res_->set_final(f);
230  }
231 
233  using states_t = std::set<state_t>;
234  states_t
236  {
237  states_t res;
238  for (auto t: res_->final_transitions())
239  res.insert(res_->src_of(t));
240  return res;
241  }
242 
244  {
245  states_t other_finals = finals();
246  e.head()->accept(*this);
247  state_t initial = initial_;
248  for (auto c: e.tail())
249  {
250  c->accept(*this);
251  for (auto t: res_->all_out(initial_))
252  // Not set_transition: for instance 'a*+a*' will make
253  // "initial" go twice to post().
254  res_->add_transition(initial,
255  res_->dst_of(t),
256  res_->label_of(t),
257  res_->weight_of(t));
258  res_->del_state(initial_);
259  }
260  initial_ = initial;
261  }
262 
264  {
265  // The set of the final states that were introduced in pending
266  // parts of the automaton (for instance if we are in the rhs
267  // of "a+bc", recording the final state for "a").
268  states_t other_finals = finals();
269 
270  // Traverse the first part of the product, handle left_weight.
271  e.head()->accept(*this);
272  state_t initial = initial_;
273 
274  // Then the remainder.
275  for (auto c: e.tail())
276  {
277  // The set of the current (left-hand side) final transitions.
278  auto ftr_ = res_->final_transitions();
279  // Store transitions by copy.
280  using transs_t = std::vector<transition_t_of<automaton_t>>;
281  transs_t ftr{ begin(ftr_), end(ftr_) };
282 
283  // Visit the next member of the product.
284  c->accept(*this);
285 
286  // Branch all the previously added final transitions to
287  // the successors of the new initial state.
288  for (auto t1: ftr)
289  if (!has(other_finals, res_->src_of(t1)))
290  {
291  // Remove the previous final transition first, as we
292  // might add a final transition for the same state
293  // later.
294  //
295  // For instance on "<2>a+(<3>\e+<5>a)", the final
296  // state s1 of <2>a will be made final thanks to
297  // <3>\e. So if we compute the new transitions from
298  // s1 and then remove t1, we will have removed the
299  // fact that s1 is final thanks to <3>\e.
300  //
301  // Besides, s1 will become final with weight <3>, which
302  // might interfere with <5>a too.
303  auto s1 = res_->src_of(t1);
304  auto w1 = res_->weight_of(t1);
305  res_->del_transition(t1);
306  for (auto t2: res_->all_out(initial_))
307  res_->set_transition(s1,
308  res_->dst_of(t2),
309  res_->label_of(t2),
310  ws_.mul(w1, res_->weight_of(t2)));
311  }
312  res_->del_state(initial_);
313  }
314  initial_ = initial;
315  }
316 
317  // See star_here().
319  {
320  states_t other_finals = finals();
321  e.sub()->accept(*this);
322  // The "final weight of the initial state", starred.
323  weight_t w = ws_.star(res_->get_final_weight(initial_));
324  // Branch all the final states (but initial) to the successors
325  // of initial.
326  for (auto ti: res_->out(initial_))
327  {
328  res_->lmul_weight(ti, w);
329  for (auto tf: res_->final_transitions())
330  if (res_->src_of(tf) != initial_
331  && !has(other_finals, res_->src_of(tf)))
332  // Note that the weight of ti has already been
333  // multiplied, on the left, by w.
334  //
335  // Not set_transition, as for instance with "a**", the
336  // second star modifies many existing transitions.
337  res_->add_transition
338  (res_->src_of(tf),
339  res_->dst_of(ti),
340  res_->label_of(ti),
341  ws_.mul(res_->weight_of(tf), res_->weight_of(ti)));
342  }
343  for (auto tf: res_->final_transitions())
344  res_->rmul_weight(tf, w);
345  res_->set_final(initial_, w);
346  }
347 
349  {
350  e.sub()->accept(*this);
351  for (auto t: res_->all_out(initial_))
352  res_->lmul_weight(t, e.weight());
353  }
354 
356  {
357  states_t other_finals = finals();
358  e.sub()->accept(*this);
359  for (auto t: res_->final_transitions())
360  if (! has(other_finals, res_->src_of(t)))
361  res_->rmul_weight(t, e.weight());
362  }
363 
364  private:
365  const ratexpset_t& rs_;
366  const weightset_t& ws_ = *rs_.weightset();
368  state_t initial_ = automaton_t::element_type::null_state();
369  };
370 
371  } // rat::
372 
373 
378  template <typename Aut,
379  typename RatExpSet>
380  Aut
381  standard(const RatExpSet& rs, const typename RatExpSet::value_t& r)
382  {
384  return standard(r);
385  }
386 
387  namespace dyn
388  {
389  namespace detail
390  {
392  template <typename RatExpSet>
393  automaton
395  {
396  // FIXME: So far, there is a single implementation of ratexps,
397  // but we should actually be parameterized by its type too.
398  using ratexpset_t = RatExpSet;
400  const auto& e = exp->as<ratexpset_t>();
401  return make_automaton(::vcsn::standard<automaton_t>(e.ratexpset(),
402  e.ratexp()));
403  }
404 
406  (const ratexp& e) -> automaton);
407  }
408  }
409 
410 } // vcsn::
411 
412 #endif // !VCSN_ALGOS_STANDARD_HH
bool is_costandard(const automaton &aut)
Bridge.
Definition: standard.hh:65
An inner node with multiple children.
Definition: fwd.hh:123
#define VCSN_RAT_UNSUPPORTED(Type)
Definition: visitor.hh:54
std::set< state_t > states_t
The current set of final states.
Definition: standard.hh:233
automaton standard(const automaton &aut)
Bridge.
Definition: standard.hh:144
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
bool is_standard(const Aut &a)
Whether a is standard.
Definition: standard.hh:27
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:77
std::shared_ptr< detail::mutable_automaton_impl< Context >> mutable_automaton
Definition: fwd.hh:25
std::shared_ptr< detail::ratexp_base > ratexp
Definition: fwd.hh:64
automaton standard_ratexp(const ratexp &exp)
Bridge.
Definition: standard.hh:394
weightset_t_of< ratexpset_t > weightset_t
Definition: standard.hh:184
auto costandard(const Aut &aut) -> decltype(copy(aut))
Definition: standard.hh:130
static constexpr const char * me()
Definition: standard.hh:190
AutOut copy(const AutIn &input, Pred keep_state)
A copy of input keeping only its states that are accepted by keep_state.
Definition: copy.hh:171
typename ratexpset_t::const_visitor super_t
Definition: standard.hh:188
bool is_standard(const automaton &aut)
Bridge.
Definition: standard.hh:53
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:38
auto standard(const Aut &aut) -> decltype(copy(aut))
Definition: standard.hh:120
automaton costandard(const automaton &aut)
Bridge.
Definition: standard.hh:155
const ratexpset_t & rs_
Definition: standard.hh:365
bool is_costandard(const Aut &a)
Whether a is costandard.
Definition: standard.hh:40
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:36
automaton_t operator()(const typename ratexpset_t::value_t &v)
Definition: standard.hh:198
An inner node implementing a weight.
Definition: fwd.hh:145
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:37
Aut transpose(const transpose_automaton< Aut > &aut)
Definition: transpose.hh:230
state_t_of< automaton_t > state_t
Definition: standard.hh:186
weight_t_of< ratexpset_t > weight_t
Definition: standard.hh:185
Build a standard automaton from a ratexp.
Definition: standard.hh:178
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:35
const weightset_t & ws_
Definition: standard.hh:366
SharedPtr make_shared_ptr(Args &&...args)
Same as std::make_shared, but parameterized by the shared_ptr type, not the (pointed to) element_type...
Definition: memory.hh:15
void standard_here(Aut &aut)
Turn aut into a standard automaton.
Definition: standard.hh:85
bool has(const std::map< Key, Value, Compare, Alloc > &s, const Key &e)
Definition: map.hh:35
standard_visitor(const ratexpset_t &rs)
Definition: standard.hh:192