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