Vcsn  2.1
Be Rational
standard.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <set>
4 
5 #include <vcsn/algos/copy.hh>
9 #include <vcsn/ctx/fwd.hh>
10 #include <vcsn/ctx/traits.hh>
11 #include <vcsn/dyn/automaton.hh>
12 #include <vcsn/dyn/expression.hh>
13 #include <vcsn/misc/memory.hh>
14 #include <vcsn/misc/raise.hh>
15 #include <vcsn/misc/vector.hh> // make_vector
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  inline
53  bool
54  is_standard(const automaton& aut)
55  {
56  const auto& a = aut->as<Aut>();
57  return is_standard(a);
58  }
59 
61  template <typename Aut>
62  inline
63  bool
65  {
66  const auto& a = aut->as<Aut>();
67  return is_costandard(a);
68  }
69  }
70  }
71 
72  /*----------------------.
73  | standard(automaton). |
74  `----------------------*/
75 
79  template <typename Aut>
80  void
81  standard_here(Aut& aut)
82  {
83  if (is_standard(aut))
84  return;
85 
86  const auto& ws = *aut->weightset();
87  const auto& inits = aut->initial_transitions();
88  std::vector<transition_t_of<Aut>> initials{begin(inits), end(inits)};
89 
90  // See TAF-Kit documentation for the implementation details.
91  //
92  // (i.a) Add a new state s...
93  auto ini = aut->new_state();
94  for (auto ti: initials)
95  {
96  // The initial state.
97  auto i = aut->dst_of(ti);
98  auto wi = aut->weight_of(ti);
99  for (auto t: aut->all_out(i))
100  aut->new_transition(ini, aut->dst_of(t), aut->label_of(t),
101  ws.mul(wi, aut->weight_of(t)));
102  aut->del_transition(ti);
103 
104  // (iv) Remove the former initial states of A that are the
105  // destination of no incoming transition.
106  if (aut->all_in(i).empty())
107  aut->del_state(i);
108  }
109  // (i.b) Make [state s] initial, with initial multiplicity equal
110  // to the unit of the multiplicity semiring.
111  aut->set_initial(ini);
112  }
113 
114  template <typename Aut>
115  auto
116  standard(const Aut& aut)
117  -> decltype(copy(aut))
118  {
119  auto res = copy(aut);
120  standard_here(res);
121  return res;
122  }
123 
124  template <typename Aut>
125  auto
126  costandard(const Aut& aut)
127  -> decltype(copy(aut))
128  {
129  return transpose(standard(transpose(aut)));
130  }
131 
132 
133  namespace dyn
134  {
135  namespace detail
136  {
138  template <typename Aut>
139  inline
140  automaton
141  standard(const automaton& aut)
142  {
143  const auto& a = aut->as<Aut>();
144  return make_automaton(::vcsn::standard(a));
145  }
146 
148  template <typename Aut>
149  inline
150  automaton
151  costandard(const automaton& aut)
152  {
153  const auto& a = aut->as<Aut>();
154  return make_automaton(costandard(a));
155  }
156  }
157  }
158 
159 
160  /*------------------------.
161  | standard(expression). |
162  `------------------------*/
163 
164  namespace rat
165  {
170  template <typename Aut,
171  typename ExpSet>
173  : public ExpSet::const_visitor
174  {
175  public:
176  using automaton_t = Aut;
177  using expressionset_t = ExpSet;
181 
182  using super_t = typename expressionset_t::const_visitor;
183 
185  constexpr static const char* me() { return "standard"; }
186 
188  : rs_(rs)
190  {}
191 
193  operator()(const typename expressionset_t::value_t& v)
194  {
195  v->accept(*this);
196  res_->set_initial(initial_);
197  return res_;
198  }
199 
200  private:
207  using tuple_t = typename super_t::tuple_t;
208  virtual void visit(const tuple_t&, std::true_type) override
209  {
210  raise(me(), ": tuple is not supported");
211  }
212 
214  {
215  initial_ = res_->new_state();
216  }
217 
219  {
220  auto i = res_->new_state();
221  initial_ = i;
222  res_->set_final(i);
223  }
224 
226  {
227  auto i = res_->new_state();
228  auto f = res_->new_state();
229  initial_ = i;
230  res_->new_transition(i, f, e.value());
231  res_->set_final(f);
232  }
233 
235  using states_t = std::set<state_t>;
236  states_t
238  {
239  states_t res;
240  for (auto t: res_->final_transitions())
241  res.insert(res_->src_of(t));
242  return res;
243  }
244 
246  {
247  states_t other_finals = finals();
248  e.head()->accept(*this);
249  state_t initial = initial_;
250  for (auto c: e.tail())
251  {
252  c->accept(*this);
253  for (auto t: res_->all_out(initial_))
254  // Not set_transition: for instance 'a*+a*' will make
255  // "initial" go twice to post().
256  res_->add_transition(initial,
257  res_->dst_of(t),
258  res_->label_of(t),
259  res_->weight_of(t));
260  res_->del_state(initial_);
261  }
262  initial_ = initial;
263  }
264 
266  {
267  // The set of the final states that were introduced in pending
268  // parts of the automaton (for instance if we are in the rhs
269  // of "a+bc", recording the final state for "a").
270  states_t other_finals = finals();
271 
272  // Traverse the first part of the product, handle left_weight.
273  e.head()->accept(*this);
274  state_t initial = initial_;
275 
276  // Then the remainder.
277  for (auto c: e.tail())
278  {
279  // The set of the current (left-hand side) final transitions.
280  auto ftr = detail::make_vector(res_->final_transitions());
281 
282  // Visit the next member of the product.
283  c->accept(*this);
284 
285  // Branch all the previously added final transitions to
286  // the successors of the new initial state.
287  for (auto t1: ftr)
288  if (!has(other_finals, res_->src_of(t1)))
289  {
290  // Remove the previous final transition first, as we
291  // might add a final transition for the same state
292  // later.
293  //
294  // For instance on "<2>a+(<3>\e+<5>a)", the final
295  // state s1 of <2>a will be made final thanks to
296  // <3>\e. So if we compute the new transitions from
297  // s1 and then remove t1, we will have removed the
298  // fact that s1 is final thanks to <3>\e.
299  //
300  // Besides, s1 will become final with weight <3>, which
301  // might interfere with <5>a too.
302  auto s1 = res_->src_of(t1);
303  auto w1 = res_->weight_of(t1);
304  res_->del_transition(t1);
305  for (auto t2: res_->all_out(initial_))
306  res_->set_transition(s1,
307  res_->dst_of(t2),
308  res_->label_of(t2),
309  ws_.mul(w1, res_->weight_of(t2)));
310  }
311  res_->del_state(initial_);
312  }
313  initial_ = initial;
314  }
315 
316  // See star_here().
318  {
319  states_t other_finals = finals();
320  e.sub()->accept(*this);
321  // The "final weight of the initial state", starred.
322  weight_t w = ws_.star(res_->get_final_weight(initial_));
323  // Branch all the final states (but initial) to the successors
324  // of initial.
325  for (auto ti: res_->out(initial_))
326  {
327  res_->lmul_weight(ti, w);
328  for (auto tf: res_->final_transitions())
329  if (res_->src_of(tf) != initial_
330  && !has(other_finals, res_->src_of(tf)))
331  // Note that the weight of ti has already been
332  // multiplied, on the left, by w.
333  //
334  // Not set_transition, as for instance with "a**", the
335  // second star modifies many existing transitions.
336  res_->add_transition
337  (res_->src_of(tf),
338  res_->dst_of(ti),
339  res_->label_of(ti),
340  ws_.mul(res_->weight_of(tf), res_->weight_of(ti)));
341  }
342  for (auto tf: res_->final_transitions())
343  res_->rmul_weight(tf, w);
344  res_->set_final(initial_, w);
345  }
346 
348  {
349  e.sub()->accept(*this);
350  for (auto t: res_->all_out(initial_))
351  res_->lmul_weight(t, e.weight());
352  }
353 
355  {
356  states_t other_finals = finals();
357  e.sub()->accept(*this);
358  for (auto t: res_->final_transitions())
359  if (! has(other_finals, res_->src_of(t)))
360  res_->rmul_weight(t, e.weight());
361  }
362 
363  private:
365  const weightset_t& ws_ = *rs_.weightset();
367  state_t initial_ = automaton_t::element_type::null_state();
368  };
369 
370  } // rat::
371 
372 
377  template <typename Aut,
378  typename ExpSet>
379  Aut
380  standard(const ExpSet& rs, const typename ExpSet::value_t& r)
381  {
383  return standard(r);
384  }
385 
386  namespace dyn
387  {
388  namespace detail
389  {
391  template <typename ExpSet>
392  automaton
394  {
395  // FIXME: So far, there is a single implementation of expressions,
396  // but we should actually be parameterized by its type too.
397  using expressionset_t = ExpSet;
398  using automaton_t
400  const auto& e = exp->as<expressionset_t>();
401  return make_automaton(::vcsn::standard<automaton_t>(e.expressionset(),
402  e.expression()));
403  }
404  }
405  }
406 
407 } // vcsn::
STL namespace.
std::vector< typename Cont::value_type > make_vector(const Cont &cont)
The content of cont as a vector.
Definition: vector.hh:20
auto costandard(const Aut &aut) -> decltype(copy(aut))
Definition: standard.hh:126
automaton costandard(const automaton &aut)
Bridge.
Definition: standard.hh:151
const expressionset_t & rs_
Definition: standard.hh:364
automaton standard_expression(const expression &exp)
Bridge (standard).
Definition: standard.hh:393
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:48
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:51
bool is_costandard(const Aut &a)
Whether a is costandard.
Definition: standard.hh:40
typename expressionset_t::const_visitor super_t
Definition: standard.hh:182
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:14
Aut transpose(const transpose_automaton< Aut > &aut)
Definition: transpose.hh:235
automaton standard(const automaton &aut)
Bridge.
Definition: standard.hh:141
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
AutOut copy(const AutIn &input, KeepState keep_state, KeepTrans keep_trans)
A copy of input keeping only its states that are accepted by keep_state.
Definition: copy.hh:254
const weightset_t & ws_
Definition: standard.hh:365
bool is_standard(const Aut &a)
Whether a is standard.
Definition: standard.hh:27
weight_t_of< expressionset_t > weight_t
Definition: standard.hh:179
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
typename super_t::tuple_t tuple_t
Definition: standard.hh:207
auto rs
Definition: lift.hh:151
bool is_costandard(const automaton &aut)
Bridge.
Definition: standard.hh:64
weightset_t_of< expressionset_t > weightset_t
Definition: standard.hh:178
std::set< state_t > states_t
The current set of final states.
Definition: standard.hh:235
automaton_t operator()(const typename expressionset_t::value_t &v)
Definition: standard.hh:193
virtual void visit(const tuple_t &, std::true_type) override
Definition: standard.hh:208
ATTRIBUTE_PURE bool has(const std::deque< T, Allocator > &s, const T &e)
Whether e is member of s.
Definition: deque.hh:13
An inner node implementing a weight.
Definition: expression.hh:264
Build a standard automaton from an expression.
Definition: standard.hh:172
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:78
auto standard(const Aut &aut) -> decltype(copy(aut))
Definition: standard.hh:116
void standard_here(Aut &aut)
Turn aut into a standard automaton.
Definition: standard.hh:81
bool is_standard(const automaton &aut)
Bridge.
Definition: standard.hh:54
state_t_of< automaton_t > state_t
Definition: standard.hh:180
standard_visitor(const expressionset_t &rs)
Definition: standard.hh:187
static constexpr const char * me()
Name of this algorithm, for error messages.
Definition: standard.hh:185
std::shared_ptr< detail::mutable_automaton_impl< Context >> mutable_automaton
Definition: fwd.hh:24
An inner node with multiple children.
Definition: expression.hh:118
#define VCSN_RAT_UNSUPPORTED(Type)
Definition: visitor.hh:68
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:50