Vcsn  2.1
Be Rational
zpc.hh
Go to the documentation of this file.
1 #pragma once
2 
6 #include <vcsn/ctx/fwd.hh>
7 #include <vcsn/ctx/traits.hh>
8 #include <vcsn/dyn/automaton.hh>
9 #include <vcsn/dyn/expression.hh>
10 #include <vcsn/labelset/labelset.hh> // make_nullableset_context
11 #include <vcsn/misc/raise.hh>
12 
13 namespace vcsn
14 {
15  namespace rat
16  {
21  template <typename Aut,
22  typename ExpSet>
24  : public ExpSet::const_visitor
25  {
26  public:
27  using automaton_t = Aut;
28  using expressionset_t = ExpSet;
33 
34  using super_t = typename expressionset_t::const_visitor;
35 
36  static_assert(labelset_t_of<Aut>::has_one(),
37  "zpc: requires nullable labels");
38 
40  constexpr static const char* me() { return "zpc"; }
41 
44  const expressionset_t& rs,
45  bool compact)
46  : rs_(rs)
48  , compact_(compact)
49  {}
50 
51  zpc_visitor(const expressionset_t& rs, bool compact)
52  : zpc_visitor(rs.context(), rs, compact)
53  {}
54 
56  operator()(const typename expressionset_t::value_t& v)
57  {
58  v->accept(*this);
59  res_->set_initial(initial_);
60  res_->set_final(final_);
61 
62  for (auto t: res_->all_in(res_->post()))
63  res_->set_weight(t, ws_.mul(res_->weight_of(t), final_weight_));
64 
65  return std::move(res_);
66  }
67 
68  private:
75  using tuple_t = typename super_t::tuple_t;
76  virtual void visit(const tuple_t&, std::true_type) override
77  {
78  raise(me(), ": tuple is not supported");
79  }
80 
82  {
83  initial_ = res_->new_state();
84  final_ = res_->new_state();
85  }
86 
88  {
89  initial_ = res_->new_state();
90  final_ = res_->new_state();
91 
92  res_->set_final(initial_);
93  }
94 
96  {
97  initial_ = res_->new_state();
98  final_ = res_->new_state();
99  // The automaton and the expression might have different
100  // labelsets.
101  res_->new_transition(initial_, final_,
102  res_->labelset()->conv(*rs_.labelset(),
103  e.value()));
104  }
105 
107  {
108  if (compact_)
109  sum_compact(e);
110  else
111  sum_regular(e);
112  }
113 
115  {
116  if (compact_)
117  prod_compact(e);
118  else
119  prod_regular(e);
120  }
121 
123  {
124  state_t initial = res_->new_state();
125 
126  e.sub()->accept(*this);
127 
128  state_t final = res_->new_state();
129 
130  auto cst = ws_.star(res_->get_final_weight(initial_));
131  res_->unset_final(initial_);
132 
133  res_->new_transition(initial, initial_, epsilon_, cst);
134  res_->new_transition(final_, final, epsilon_, cst);
135  res_->new_transition(final_, initial_, epsilon_, cst);
136 
137  initial_ = initial;
138  final_ = final;
139 
140  res_->set_final(initial_, cst);
141  }
142 
144  {
145  e.sub()->accept(*this);
146 
147  const weight_t& w = e.weight();
148  for (auto t: res_->all_out(initial_))
149  res_->set_weight(t, ws_.mul(w, res_->weight_of(t)));
150  }
151 
153  {
154  e.sub()->accept(*this);
155 
156  final_weight_ = ws_.mul(e.weight(), final_weight_);
157  }
158 
159  void sum_regular(const sum_t& e)
160  {
161  state_t initial = res_->new_state();
162 
163  weight_t cst = ws_.zero();
164  std::vector<state_t> finals_;
165 
166  for (auto c: e)
167  {
168  c->accept(*this);
169  res_->new_transition(initial, initial_, epsilon_);
170  finals_.push_back(final_);
171 
172  cst = ws_.add(cst, res_->get_final_weight(initial_));
173  res_->unset_final(initial_);
174  }
175 
176  state_t final = res_->new_state();
177 
178  for (auto s: finals_)
179  res_->new_transition(s, final, epsilon_);
180 
181  initial_ = initial;
182  final_ = final;
183 
184  // Constant term weight.
185  res_->set_final(initial_, cst);
186  }
187 
188  void prod_regular(const prod_t& e)
189  {
190  std::vector<state_t> state_stack;
191 
192  // Number of 'initial' states to create.
193  for (auto i = 0; i < e.size() - 1; ++i)
194  state_stack.push_back(res_->new_state());
195 
196  e.head()->accept(*this);
197 
198  // In each methods prod_regular, prod_compact and sum_compact,
199  // sometimes it's necessary to create simultaneously
200  // two sub-automaton, the first one's states are postfixes by _e and
201  // the next one (creation order) by _f.
202  state_t initial_e = initial_;
203  state_t final_e = final_;
204 
205  // Default value of initial for the compact form.
206  state_t initial = initial_e;
207  state_t final = automaton_t::element_type::null_state();
208 
209  initial = state_stack.back();
210  state_stack.pop_back();
211  res_->new_transition(initial, initial_e, epsilon_);
212 
213  for (auto t: e.tail())
214  {
215  t->accept(*this);
216 
217  final = res_->new_state();
218  res_->new_transition(final_, final, epsilon_);
219 
220  auto cst_e = res_->get_final_weight(initial_e);
221  auto cst_f = res_->get_final_weight(initial_);
222 
223  res_->new_transition(initial, initial_, epsilon_, cst_e);
224  res_->unset_final(initial_e);
225  res_->new_transition(final_e, final, epsilon_, cst_f);
226  res_->unset_final(initial_);
227 
228  res_->set_final(initial, ws_.mul(cst_e, cst_f));
229 
230  res_->new_transition(final_e, initial_, epsilon_);
231 
232  initial_e = initial;
233  final_e = final;
234 
235  if (!state_stack.empty())
236  {
237  initial = state_stack.back();
238  state_stack.pop_back();
239 
240  res_->new_transition(initial, initial_e, epsilon_);
241  }
242  }
243 
244  initial_ = initial;
245  final_ = final;
246  }
247 
248  void sum_compact(const sum_t& e)
249  {
250  e.head()->accept(*this);
251 
252  weight_t cst = res_->get_final_weight(initial_);
253  res_->unset_final(initial_);
254 
255  state_t initial = initial_;
256  state_t initial_e = initial;
257  state_t final_e = final_;
258 
259  for (auto c: e.tail())
260  {
261  c->accept(*this);
262  cst = ws_.add(cst, res_->get_final_weight(initial_));
263  res_->unset_final(initial_);
264 
265  res_->new_transition(initial_e, initial_, epsilon_);
266  res_->new_transition(final_e, final_, epsilon_);
267 
268  initial_e = initial_;
269  final_e = final_;
270  }
271 
272  initial_ = initial;
273 
274  res_->set_final(initial_, cst);
275  }
276 
277  void prod_compact(const prod_t& e)
278  {
279  e.head()->accept(*this);
280 
281  state_t initial_e = initial_;
282  state_t final_e = final_;
283 
284  // Default value of initial for the compact form.
285  state_t initial = initial_e;
286  state_t final;
287 
288  for (auto t: e.tail())
289  {
290  t->accept(*this);
291  final = final_;
292 
293  auto cst_e = res_->get_final_weight(initial_e);
294  auto cst_f = res_->get_final_weight(initial_);
295 
296  res_->new_transition(initial, initial_, epsilon_, cst_e);
297  res_->unset_final(initial_e);
298  res_->new_transition(final_e, final, epsilon_, cst_f);
299  res_->unset_final(initial_);
300 
301  res_->set_final(initial, ws_.mul(cst_e, cst_f));
302 
303  res_->new_transition(final_e, initial_, epsilon_);
304 
305  initial_e = initial;
306  final_e = final;
307  }
308 
309  initial_ = initial;
310  final_ = final;
311  }
312 
313  private:
315  const weightset_t& ws_ = *rs_.weightset();
318  const label_t epsilon_ = res_->labelset()->one();
319  state_t initial_ = automaton_t::element_type::null_state();
320  state_t final_ = automaton_t::element_type::null_state();
321  weight_t final_weight_ = ws_.one();
323  const bool compact_;
324  };
325 
326  } // rat::
327 
332  template <typename Aut, typename ExpSet>
333  inline
334  Aut
336  const ExpSet& rs,
337  const typename ExpSet::value_t& r,
338  const std::string& algo = "auto")
339  {
340  require(algo == "auto" || algo == "regular" || algo == "compact",
341  "zpc: expects \"auto\", \"regular\", \"compact\" or nothing");
342  rat::zpc_visitor<Aut, ExpSet> zpc{ctx, rs, algo == "compact"};
343  return zpc(r);
344  }
345 
346  namespace dyn
347  {
348  namespace detail
349  {
350  /*-----------------.
351  | dyn::zpc(exp). |
352  `-----------------*/
353 
355  template <typename ExpSet, typename String>
356  inline
357  automaton
358  zpc(const expression& exp, const std::string& algo)
359  {
360  // FIXME: So far, there is a single implementation of expressions,
361  // but we should actually be parameterized by its type too.
362  using expressionset_t = ExpSet;
363  const auto& e = exp->as<expressionset_t>();
364  auto ctx
365  = vcsn::detail::make_nullableset_context(e.expressionset().context());
366  using ctx_t = decltype(ctx);
367  using automaton_t = mutable_automaton<ctx_t>;
368  return make_automaton(::vcsn::zpc<automaton_t>(ctx,
369  e.expressionset(),
370  e.expression(),
371  algo));
372  }
373  }
374  }
375 
376 } // vcsn::
STL namespace.
VCSN_RAT_VISIT(zero,)
Definition: zpc.hh:81
VCSN_RAT_VISIT(rweight, e)
Definition: zpc.hh:152
const label_t epsilon_
Definition: zpc.hh:318
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:46
zpc_visitor(const expressionset_t &rs, bool compact)
Definition: zpc.hh:51
nullableset_context_t< context< LabelSet, WeightSet > > make_nullableset_context(const context< LabelSet, WeightSet > &ctx)
The nullableset context of a context.
Definition: labelset.hh:166
VCSN_RAT_VISIT(star, e)
Definition: zpc.hh:122
typename expressionset_t::const_visitor super_t
Definition: zpc.hh:34
weight_t_of< expressionset_t > weight_t
Definition: zpc.hh:31
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:48
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:45
context_t_of< automaton_t > context_t
Definition: zpc.hh:29
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:51
const weightset_t & ws_
Definition: zpc.hh:315
typename super_t::tuple_t tuple_t
Definition: zpc.hh:75
weight_t final_weight_
Definition: zpc.hh:321
automaton_t operator()(const typename expressionset_t::value_t &v)
Definition: zpc.hh:56
state_t initial_
Definition: zpc.hh:319
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
ExpSet expressionset_t
Definition: zpc.hh:28
const expressionset_t & rs_
Definition: zpc.hh:314
VCSN_RAT_VISIT(prod, e)
Definition: zpc.hh:114
virtual void visit(const tuple_t &, std::true_type) override
Definition: zpc.hh:76
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:80
automaton_t res_
Definition: zpc.hh:316
const bool compact_
Whether to build the "compact" version of the ZPC automaton.
Definition: zpc.hh:323
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
Aut zpc(const context_t_of< Aut > &ctx, const ExpSet &rs, const typename ExpSet::value_t &r, const std::string &algo="auto")
Build a ZPC automaton from an expression.
Definition: zpc.hh:335
static constexpr const char * me()
Name of this algorithm, for error messages.
Definition: zpc.hh:40
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:47
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:75
automaton zpc(const expression &exp, const std::string &algo)
Bridge.
Definition: zpc.hh:358
VCSN_RAT_VISIT(sum, e)
Definition: zpc.hh:106
void prod_regular(const prod_t &e)
Definition: zpc.hh:188
auto rs
Definition: lift.hh:151
Build a ZPC automaton from an expression.
Definition: zpc.hh:23
label_t_of< automaton_t > label_t
Definition: zpc.hh:317
state_t_of< automaton_t > state_t
Definition: zpc.hh:32
zpc_visitor(const context_t &ctx, const expressionset_t &rs, bool compact)
Build an automaton of context ctx.
Definition: zpc.hh:43
VCSN_RAT_VISIT(one,)
Definition: zpc.hh:87
VCSN_RAT_VISIT(atom, e)
Definition: zpc.hh:95
An inner node implementing a weight.
Definition: expression.hh:264
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:78
VCSN_RAT_VISIT(lweight, e)
Definition: zpc.hh:143
void sum_regular(const sum_t &e)
Definition: zpc.hh:159
weightset_t_of< expressionset_t > weightset_t
Definition: zpc.hh:30
void prod_compact(const prod_t &e)
Definition: zpc.hh:277
std::shared_ptr< detail::mutable_automaton_impl< Context >> mutable_automaton
Definition: fwd.hh:24
void sum_compact(const sum_t &e)
Definition: zpc.hh:248
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