Vcsn  2.8
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>
10 #include <vcsn/ctx/fwd.hh>
11 #include <vcsn/ctx/traits.hh>
12 #include <vcsn/dyn/automaton.hh>
13 #include <vcsn/dyn/value.hh>
14 #include <vcsn/misc/memory.hh>
15 #include <vcsn/misc/raise.hh>
16 #include <vcsn/misc/tuple.hh>
17 #include <vcsn/misc/vector.hh> // make_vector
18 
19 namespace vcsn
20 {
21  /*-------------------------.
22  | is_standard(automaton). |
23  `-------------------------*/
24 
26  template <Automaton Aut>
27  bool
28  is_standard(const Aut& a)
29  {
30  auto inis = initial_transitions(a);
31  return
32  inis.size() == 1
33  && a->weightset()->is_one(a->weight_of(inis.front()))
34  // No arrival on the initial state.
35  && in(a, a->dst_of(inis.front())).empty();
36  }
37 
39  template <Automaton Aut>
40  bool
41  is_costandard(const Aut& a)
42  {
43  return is_standard(transpose(a));
44  }
45 
46 
47  namespace dyn
48  {
49  namespace detail
50  {
52  template <Automaton Aut>
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 <Automaton Aut>
62  bool
64  {
65  const auto& a = aut->as<Aut>();
66  return is_costandard(a);
67  }
68  }
69  }
70 
71  /*----------------------.
72  | standard(automaton). |
73  `----------------------*/
74 
78  template <Automaton Aut>
79  void
80  standard_here(Aut& aut)
81  {
82  if (is_standard(aut))
83  return;
84 
85  const auto& ws = *aut->weightset();
86  const auto& inits = initial_transitions(aut);
87  std::vector<transition_t_of<Aut>> initials{begin(inits), end(inits)};
88 
89  // See Tools documentation for the implementation details.
90  //
91  // (i.a) Add a new state s...
92  auto ini = aut->new_state();
93  for (auto ti: initials)
94  {
95  // The initial state.
96  auto i = aut->dst_of(ti);
97  auto wi = aut->weight_of(ti);
98  for (auto t: all_out(aut, i))
99  // Cannot use new_transition.
100  aut->add_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 (all_in(aut, 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 <Automaton Aut>
115  auto
116  standard(const Aut& aut)
117  {
118  auto res = copy(aut);
120  return res;
121  }
122 
123  template <Automaton Aut>
124  auto
125  costandard(const Aut& aut)
126  -> decltype(copy(aut))
127  {
128  return transpose(standard(transpose(aut)));
129  }
130 
131 
132  namespace dyn
133  {
134  namespace detail
135  {
137  template <Automaton Aut>
138  automaton
139  standard(const automaton& aut)
140  {
141  const auto& a = aut->as<Aut>();
143  }
144 
146  template <Automaton Aut>
147  automaton
148  costandard(const automaton& aut)
149  {
150  const auto& a = aut->as<Aut>();
151  return costandard(a);
152  }
153  }
154  }
155 
156 
157  /*------------------------.
158  | standard(expression). |
159  `------------------------*/
160 
161  namespace rat
162  {
167  template <Automaton Aut,
168  typename ExpSet>
170  : public ExpSet::const_visitor
171  {
172  public:
173  using automaton_t = Aut;
174  using expressionset_t = ExpSet;
175  using expression_t = typename expressionset_t::value_t;
179 
180  using super_t = typename expressionset_t::const_visitor;
181 
183  constexpr static const char* me() { return "standard"; }
184 
186  : rs_(rs)
187  , res_(make_shared_ptr<automaton_t>(rs_.context()))
188  {}
189 
192  {
193  try
194  {
195  v->accept(*this);
196  res_->set_initial(initial_);
197  return std::move(res_);
198  }
199  catch (const std::runtime_error& e)
200  {
201  raise(e,
202  " while computing standard automaton of: ",
203  to_string(rs_, v));
204  }
205  }
206 
207  private:
215  using tuple_t = typename super_t::tuple_t;
216  void visit(const tuple_t&, std::true_type) override
217  {
218  raise(me(), ": tuple is not supported");
219  }
220 
222  {
223  initial_ = res_->new_state();
224  }
225 
227  {
228  auto i = res_->new_state();
229  initial_ = i;
230  res_->set_final(i);
231  }
232 
234  {
235  auto i = res_->new_state();
236  auto f = res_->new_state();
237  initial_ = i;
238  res_->new_transition(i, f, e.value());
239  res_->set_final(f);
240  }
241 
243  {
244  super_t::visit(e);
245  }
246 
248  using states_t = std::set<state_t>;
249  states_t finals() const
250  {
251  states_t res;
252  for (auto t: final_transitions(res_))
253  res.insert(res_->src_of(t));
254  return res;
255  }
256 
258  {
259  states_t other_finals = finals();
260  e.head()->accept(*this);
261  state_t initial = initial_;
262  for (const auto& c: e.tail())
263  {
264  c->accept(*this);
265  for (auto t: all_out(res_, initial_))
266  // Not set_transition: for instance 'a*+a*' will make
267  // "initial" go twice to post().
268  res_->add_transition(initial,
269  res_->dst_of(t),
270  res_->label_of(t),
271  res_->weight_of(t));
272  res_->del_state(initial_);
273  }
274  initial_ = initial;
275  }
276 
278  {
279  // The set of the final states that were introduced in pending
280  // parts of the automaton (for instance if we are in the rhs
281  // of "a+bc", recording the final state for "a").
282  states_t other_finals = finals();
283 
284  // Traverse the first part of the product, handle left_weight.
285  e.head()->accept(*this);
286  state_t initial = initial_;
287 
288  // Then the remainder.
289  for (const auto& c: e.tail())
290  {
291  // The set of the current (left-hand side) final transitions.
292  auto ftr = detail::make_vector(final_transitions(res_));
293 
294  // Visit the next member of the product.
295  c->accept(*this);
296 
297  // Branch all the previously added final transitions to
298  // the successors of the new initial state.
299  for (auto t1: ftr)
300  if (!has(other_finals, res_->src_of(t1)))
301  {
302  // Remove the previous final transition first, as we
303  // might add a final transition for the same state
304  // later.
305  //
306  // For instance on "<2>a+(<3>\e+<5>a)", the final
307  // state s1 of <2>a will be made final thanks to
308  // <3>\e. So if we compute the new transitions from
309  // s1 and then remove t1, we will have removed the
310  // fact that s1 is final thanks to <3>\e.
311  //
312  // Besides, s1 will become final with weight <3>, which
313  // might interfere with <5>a too.
314  auto s1 = res_->src_of(t1);
315  auto w1 = res_->weight_of(t1);
316  res_->del_transition(t1);
317  for (auto t2: all_out(res_, initial_))
318  res_->set_transition(s1,
319  res_->dst_of(t2),
320  res_->label_of(t2),
321  ws_.mul(w1, res_->weight_of(t2)));
322  }
323  res_->del_state(initial_);
324  }
325  initial_ = initial;
326  }
327 
328  // See star_here().
330  {
331  states_t other_finals = finals();
332  e.sub()->accept(*this);
333  // The "final weight of the initial state", starred.
334  weight_t w = ws_.star(res_->get_final_weight(initial_));
335  // Branch all the final states (but initial) to the successors
336  // of initial.
337  for (auto ti: out(res_, initial_))
338  {
339  res_->lweight(ti, w);
340  for (auto tf: final_transitions(res_))
341  if (res_->src_of(tf) != initial_
342  && !has(other_finals, res_->src_of(tf)))
343  // Note that the weight of ti has already been
344  // multiplied, on the left, by w.
345  //
346  // Not set_transition, as for instance with "a**", the
347  // second star modifies many existing transitions.
348  res_->add_transition
349  (res_->src_of(tf),
350  res_->dst_of(ti),
351  res_->label_of(ti),
352  ws_.mul(res_->weight_of(tf), res_->weight_of(ti)));
353  }
354  for (auto tf: final_transitions(res_))
355  res_->rweight(tf, w);
356  res_->set_final(initial_, w);
357  }
358 
360  {
361  e.sub()->accept(*this);
362  for (auto t: all_out(res_, initial_))
363  res_->lweight(t, e.weight());
364  }
365 
367  {
368  states_t other_finals = finals();
369  e.sub()->accept(*this);
370  for (auto t: final_transitions(res_))
371  if (! has(other_finals, res_->src_of(t)))
372  res_->rweight(t, e.weight());
373  }
374 
375  private:
377  const weightset_t& ws_ = *rs_.weightset();
379  state_t initial_ = automaton_t::element_type::null_state();
380  };
381 
382  } // rat::
383 
384 
389  template <Automaton Aut,
390  typename ExpSet>
391  Aut
392  standard(const ExpSet& rs, const typename ExpSet::value_t& r)
393  {
395  return std(r);
396  }
397 
398  namespace dyn
399  {
400  namespace detail
401  {
403  template <typename ExpSet>
404  automaton
406  {
407  // FIXME: So far, there is a single implementation of expressions,
408  // but we should actually be parameterized by its type too.
409  using expressionset_t = ExpSet;
410  using automaton_t
412  const auto& e = exp->as<expressionset_t>();
413  return ::vcsn::standard<automaton_t>(e.valueset(), e.value());
414  }
415  }
416  }
417 
418 } // vcsn::
A dyn automaton.
Definition: automaton.hh:17
std::shared_ptr< detail::mutable_automaton_impl< Context > > mutable_automaton
Definition: fwd.hh:25
Aut transpose(const transpose_automaton< Aut > &aut)
The transpose of a transpose automaton is the original automaton.
Definition: transpose.hh:253
automaton transpose(automaton &aut)
Bridge.
Definition: transpose.hh:273
auto initial_transitions(const Aut &aut) -> decltype(aut->all_out(aut->pre()))
Indexes of transitions to (visible) initial states.
Definition: automaton.hh:167
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::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
Definition: traits.hh:67
static constexpr const char * me()
Name of this algorithm, for error messages.
Definition: standard.hh:183
automaton_t operator()(const expression_t &v)
The standard automaton of v.
Definition: standard.hh:191
std::set< state_t > states_t
The current set of final states.
Definition: standard.hh:248
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
void standard_here(Aut &aut)
Turn aut into a standard automaton.
Definition: standard.hh:80
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:13
An inner node with multiple children.
Definition: expression.hh:119
bool is_standard(const Aut &a)
Whether a is standard.
Definition: standard.hh:28
bool is_standard(const automaton &aut)
Bridge.
Definition: standard.hh:54
std::vector< typename Cont::value_type > make_vector(const Cont &cont)
The content of cont as a vector.
Definition: vector.hh:18
auto final_transitions(const Aut &aut) -> decltype(aut->all_in(aut->post()))
Indexes of transitions from (visible) final states.
Definition: automaton.hh:178
Aut standard(const ExpSet &rs, const typename ExpSet::value_t &r)
Build a standard automaton from an expression.
Definition: standard.hh:392
auto all_in(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions entering state s.
Definition: automaton.hh:116
An inner node to name the subexpression.
Definition: expression.hh:290
typename expressionset_t::value_t expression_t
Definition: standard.hh:175
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
Definition: automaton.hh:67
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
bool is_costandard(const automaton &aut)
Bridge.
Definition: standard.hh:63
automaton standard(const automaton &aut)
Bridge.
Definition: standard.hh:139
weight_t_of< expressionset_t > weight_t
Definition: standard.hh:177
Definition: a-star.hh:8
auto in(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions arriving to state s.
Definition: automaton.hh:135
automaton standard_expression(const expression &exp)
Bridge (standard).
Definition: standard.hh:405
const expressionset_t & rs_
Definition: standard.hh:376
auto & as()
Extract wrapped typed automaton.
Definition: automaton.hh:37
An inner node implementing a weight.
Definition: expression.hh:256
weightset_t_of< expressionset_t > weightset_t
Definition: standard.hh:176
states_t finals() const
Definition: standard.hh:249
standard_visitor(const expressionset_t &rs)
Definition: standard.hh:185
automaton costandard(const automaton &aut)
Bridge.
Definition: standard.hh:148
return v
Definition: multiply.hh:362
Build a standard automaton from an expression.
Definition: standard.hh:169
value_impl< detail::expression_tag > expression
Definition: fwd.hh:31
#define Automaton
Definition: automaton.hh:23
#define VCSN_RAT_UNSUPPORTED(Type)
Definition: visitor.hh:75
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of
Definition: traits.hh:66
typename super_t::tuple_t tuple_t
Definition: standard.hh:215
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7
bool is_costandard(const Aut &a)
Whether a is costandard.
Definition: standard.hh:41
STL namespace.
state_t_of< automaton_t > state_t
Definition: standard.hh:178
typename expressionset_t::const_visitor super_t
Definition: standard.hh:180
automaton copy(const automaton &aut)
Bridge.
Definition: copy.hh:435
return res
Definition: multiply.hh:399
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:86