Vcsn  2.2
Be Rational
derived-term.hh
Go to the documentation of this file.
1 #pragma once
2 
5 #include <vcsn/algos/split.hh>
9 #include <vcsn/ctx/fwd.hh>
10 #include <vcsn/dyn/automaton.hh>
11 #include <vcsn/dyn/expression.hh>
12 #include <vcsn/dyn/polynomial.hh>
13 #include <vcsn/misc/getargs.hh>
14 #include <vcsn/misc/raise.hh>
16 
17 namespace vcsn
18 {
19  namespace detail
20  {
23  {
25  enum algo_t
26  {
29  };
30 
31  derived_term_algo(algo_t a, bool b, bool d)
32  : algo(a)
33  , breaking(b)
34  , determinize(d)
35  {}
36 
38  derived_term_algo(std::string algo)
39  {
40  using dta = derived_term_algo;
41  static const auto map = getarg<derived_term_algo>
42  {
43  "derived-term algorithm",
44  {
45  // { algo, breaking, deterministic }.
46  {"auto", dta{expansion, false, false}},
47  {"breaking_derivation", "derivation,breaking"},
48  {"breaking_expansion", "expansion,breaking"},
49  {"derivation", dta{derivation, false, false}},
50  {"derivation,breaking", dta{derivation, true, false}},
51  {"derivation,deterministic",dta{derivation, false, true}},
52  {"derivation_breaking", "derivation,breaking"},
53  {"expansion", dta{expansion, false, false}},
54  {"expansion,breaking", dta{expansion, true, false}},
55  {"expansion,deterministic", dta{expansion, false, true}},
56  {"expansion_breaking", "expansion,breaking"},
57  }
58  };
59  if (boost::starts_with(algo, "lazy,"))
60  algo = algo.substr(5);
61  *this = map[algo];
62  }
63 
67  bool breaking = false;
71  bool determinize = false;
72  };
73 
74  /*--------------------------.
75  | derived_term_automaton. |
76  `--------------------------*/
77 
79  template <typename ExpSet,
82  {
84  : gens{rs.labelset()->generators()}
85  {}
86 
90  };
91 
93  template <typename ExpSet>
94  struct derived_term_automaton_members<ExpSet, false>
95  {
97  };
98 
128  template <typename ExpSet>
130  : public automaton_decorator<expression_automaton<mutable_automaton<context_t_of<ExpSet>>>>
131  {
132  public:
133  using expressionset_t = ExpSet;
135  using expression_t = typename expressionset_t::value_t;
136 
139 
143 
148 
149  static symbol sname()
150  {
151  static auto res = symbol{"derived_term_automaton<"
153  + ">"};
154  return res;
155  }
156 
157  std::ostream& print_set(std::ostream& o, format fmt = {}) const
158  {
159  o << "derived_term_automaton<";
160  return rs_.print_set(o, fmt) << '>';
161  }
162 
164  derived_term_algo algo)
165  : super_t{make_shared_ptr<automaton_t>(rs)}
166  , rs_{rs}
167  , algo_{algo}
168  , members_{rs}
169  {}
170 
173  {
175  return via_derivation(expression);
176  else
177  return via_expansion(expression);
178  }
179 
182  {
183  init_(expression);
184  while (!aut_->todo_.empty())
185  {
186  auto p = std::move(aut_->todo_.top());
187  aut_->todo_.pop();
188  complete_via_derivation_(p.first, p.second);
189  }
190  return aut_;
191  }
192 
195  {
196  init_(expression);
197  while (!aut_->todo_.empty())
198  {
199  auto p = std::move(aut_->todo_.top());
200  aut_->todo_.pop();
201  complete_via_expansion_(p.first, p.second);
202  }
203  return aut_;
204  }
205 
206  // private:
208  using super_t::aut_;
209 
212  {
213  if (algo_.breaking)
214  for (const auto& p: split(rs_, expression))
215  aut_->set_initial(label_of(p), weight_of(p));
216  else
217  aut_->set_initial(expression, ws_.one());
218  }
219 
221  void complete_(state_t s) const
222  {
223  const auto& orig = aut_->origins();
224  auto sn = orig.at(s);
225  const_cast<self_t&>(*this).complete_via_expansion_(s, sn);
226  }
227 
229  auto all_out(state_t s) const
230  -> decltype(vcsn::detail::all_out(aut_, s))
231  {
232  if (this->is_lazy(s))
233  complete_(s);
234  return vcsn::detail::all_out(aut_, s);
235  }
236 
238  template <typename ES = expressionset_t,
239  typename = std::enable_if<labelset_t_of<ES>::is_free()>>
241  {
242  aut_->set_lazy(s, false);
243  aut_->set_final(s, constant_term(rs_, src));
244  for (auto l : members_.gens)
245  {
246  auto p = derivation(rs_, src, l, algo_.breaking);
247  if (algo_.determinize)
248  {
249  auto m = ps_.determinize(p);
250  aut_->new_transition(s, label_of(m), l, weight_of(m));
251  }
252  else
253  for (const auto& m: p)
254  aut_->new_transition(s, label_of(m), l, weight_of(m));
255  }
256  }
257 
260  {
261  aut_->set_lazy(s, false);
262  auto expansion = to_expansion_(src);
263  if (algo_.determinize)
265 
266  aut_->set_final(s, expansion.constant);
267  for (const auto& p: expansion.polynomials)
268  if (algo_.breaking)
269  for (const auto& m1: p.second)
270  for (const auto& m2: split(rs_, label_of(m1)))
271  aut_->new_transition(s, label_of(m2), p.first,
272  ws_.mul(weight_of(m1), weight_of(m2)));
273  else if (algo_.determinize)
274  {
275  auto m = ps_.determinize(p.second);
276  aut_->new_transition(s, label_of(m), p.first, weight_of(m));
277  }
278  else
279  for (const auto& m: p.second)
280  aut_->new_transition(s, label_of(m), p.first, weight_of(m));
281  }
282 
286  weightset_t ws_ = *rs_.weightset();
292 
301  };
302  }
303 
305  template <typename ExpSet>
307  = std::shared_ptr<detail::derived_term_automaton_impl<ExpSet>>;
308 
309  template <typename ExpSet>
310  auto
311  make_derived_term_automaton(const ExpSet& rs,
312  const detail::derived_term_algo& algo)
314  {
315  using res_t = derived_term_automaton<ExpSet>;
316  return make_shared_ptr<res_t>(rs, algo);
317  }
318 
324  template <typename ExpSet>
325  std::enable_if_t<labelset_t_of<ExpSet>::is_free(),
326  expression_automaton<mutable_automaton<typename ExpSet::context_t>>>
327  derived_term(const ExpSet& rs,
328  const typename ExpSet::value_t& r,
329  const std::string& algo = "auto")
330  {
331  auto a = detail::derived_term_algo(algo);
332  auto dt = make_derived_term_automaton(rs, a);
333  return dt->operator()(r);
334  }
335 
341  template <typename ExpSet>
342  std::enable_if_t<!labelset_t_of<ExpSet>::is_free(),
343  expression_automaton<mutable_automaton<typename ExpSet::context_t>>>
344  derived_term(const ExpSet& rs,
345  const typename ExpSet::value_t& r,
346  const std::string& algo = "auto")
347  {
348  auto a = detail::derived_term_algo(algo);
350  "derived_term: cannot use derivation on non-free labelsets");
351  // Do not call the operator(), this would trigger the compilation
352  // of via_derivation, which does not compile (on purpose) for non
353  // free labelsets.
354  auto dt = make_derived_term_automaton(rs, a);
355  return dt->via_expansion(r);
356  }
357 
358  namespace dyn
359  {
360  namespace detail
361  {
363  template <typename ExpSet, typename String>
364  automaton derived_term(const expression& exp, const std::string& algo)
365  {
366  const auto& e = exp->as<ExpSet>();
367  const auto& rs = e.expressionset();
368  const auto& r = e.expression();
369  if (boost::starts_with(algo, "lazy"))
370  {
371  auto a = vcsn::detail::derived_term_algo(algo);
373  "derived_term: laziness works only with expansions");
374  // Do not call the operator(), this would trigger the compilation
375  // of via_derivation, which does not compile (on purpose) for non
376  // free labelsets.
377  auto res = make_derived_term_automaton(rs, a);
378  res->init_(r);
379  return make_automaton(res);
380  }
381  else
382  return make_automaton(::vcsn::derived_term(rs, r, algo));
383  }
384  }
385  }
386 } // vcsn::
typename expressionset_t::value_t expression_t
Our state names: expressions.
std::ostream & print_set(std::ostream &o, format fmt={}) const
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
Definition: automaton.hh:37
auto map(const std::tuple< Ts... > &ts, Fun f) -> decltype(map_tuple_(f, ts, make_index_sequence< sizeof...(Ts)>()))
Map a function on a tuple, return tuple of the results.
Definition: tuple.hh:160
Specify a variety of derived-term construction.
Definition: derived-term.hh:22
bool determinize
Whether to determinize the expansions and produce a deterministic automaton, at the expense of possib...
Definition: derived-term.hh:71
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:59
derived_term_algo(std::string algo)
From algo name to algo.
Definition: derived-term.hh:38
auto weight_of(Args &&...args) const -> decltype(aut_-> weight_of(std::forward< Args >(args)...))
std::shared_ptr< detail::expression_automaton_impl< Aut >> expression_automaton
An expression automaton as a shared pointer.
Definition: fwd.hh:61
automaton_t operator()(const expression_t &expression)
Compute the derived-term automaton.
automaton_t via_derivation(const expression_t &expression)
Compute the derived-term automaton via derivation.
expressionset_t rs_
The expression's set.
auto make_derived_term_automaton(const ExpSet &rs, const detail::derived_term_algo &algo) -> derived_term_automaton< ExpSet >
void complete_via_derivation_(state_t s, const expression_t &src)
Compute the outgoing transitions of src.
Definition: a-star.hh:8
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:78
std::enable_if_t< labelset_t_of< ExpSet >::is_free(), expression_automaton< mutable_automaton< typename ExpSet::context_t > > > derived_term(const ExpSet &rs, const typename ExpSet::value_t &r, const std::string &algo="auto")
The derived-term automaton, for free labelsets.
context_t_of< expressionset_t > context_t
std::shared_ptr< const detail::expansion_base > expansion
Definition: expansion.hh:73
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:55
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
An input/output format for valuesets.
Definition: format.hh:11
value_t determinize(const value_t &v) const
Turn the polynomials into (normalized) monomials.
Additional members when the labelset is free.
Definition: derived-term.hh:81
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
weight_t_of< ExpSet > constant_term(const ExpSet &rs, const typename ExpSet::value_t &e)
The constant term of e.
expression_automaton< mutable_automaton< context_t >> automaton_t
The type of the (strict) automaton we build.
weightset_t_of< context_t > weightset_t
derived_term_automaton_members< expressionset_t > members_
Possibly the generators.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:56
void complete_via_expansion_(state_t s, const expression_t &src)
Compute the outgoing transitions of src.
A mapping from strings to Values.
Definition: getargs.hh:33
std::shared_ptr< detail::derived_term_automaton_impl< ExpSet >> derived_term_automaton
A derived-term automaton as a shared pointer.
auto is_lazy(Args &&...args) const -> decltype(aut_-> is_lazy(std::forward< Args >(args)...))
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
Aggregate an automaton, and forward calls to it.
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
auto rs
Definition: lift.hh:151
void init_(const expression_t &expression)
Initialize the computation: build the initial states.
symbol sname()
Definition: name.hh:67
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:53
std::shared_ptr< const node< Context >> expression
Definition: fwd.hh:182
Compute the derived-term automaton from an expression.
auto all_out(state_t s) const -> decltype(vcsn::detail::all_out(aut_, s))
All the outgoing transitions.
derived_term_automaton_impl(const expressionset_t &rs, derived_term_algo algo)
algo_t algo
Core algorithm.
Definition: derived-term.hh:65
derived_term_algo(algo_t a, bool b, bool d)
Definition: derived-term.hh:31
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:92
rat::expression_polynomial_t< ExpSet > derivation(const ExpSet &rs, const typename ExpSet::value_t &e, label_t_of< ExpSet > a, bool breaking=false)
Derive an expression wrt to a letter.
Definition: derivation.hh:267
expression_polynomialset_t< ExpSet > make_expression_polynomialset(const ExpSet &rs)
From a ExpSet to its polynomialset.
Definition: split.hh:33
bool breaking
Whether to break sums.
Definition: derived-term.hh:67
void complete_(state_t s) const
Complete a state: find its outgoing transitions.
derived_term_algo algo_
How derived terms are computed.
typename labelset_t_of< ExpSet >::genset_t genset_t
The alphabet.
Definition: derived-term.hh:88
automaton_t via_expansion(const expression_t &expression)
Compute the derived-term automaton via expansion.
auto label_of(Args &&...args) const -> decltype(aut_-> label_of(std::forward< Args >(args)...))
rat::expression_polynomial_t< ExpSet > split(const ExpSet &rs, const typename ExpSet::value_t &e)
Split an expression.
Definition: split.hh:264