Vcsn  2.3
Be Rational
derived-term.hh
Go to the documentation of this file.
1 #pragma once
2 
5 #include <vcsn/algos/split.hh>
7 #include <vcsn/core/automaton.hh> // all_out
10 #include <vcsn/ctx/fwd.hh>
11 #include <vcsn/dyn/automaton.hh>
12 #include <vcsn/dyn/value.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  {
174  try
175  {
177  return via_derivation(exp);
178  else
179  return via_expansion(exp);
180  }
181  catch (const std::runtime_error& e)
182  {
183  raise(e, " while computing derived-term of: ", to_string(rs_, exp));
184  }
185  }
186 
189  {
190  init_(exp);
191  while (!aut_->todo_.empty())
192  {
193  auto p = std::move(aut_->todo_.top());
194  aut_->todo_.pop();
195  complete_via_derivation_(p.first, p.second);
196  }
197  return aut_;
198  }
199 
202  {
203  init_(exp);
204  while (!aut_->todo_.empty())
205  {
206  auto p = std::move(aut_->todo_.top());
207  aut_->todo_.pop();
208  complete_via_expansion_(p.first, p.second);
209  }
210  return aut_;
211  }
212 
213  // private:
215  using super_t::aut_;
216 
218  void init_(const expression_t& exp)
219  {
220  if (algo_.breaking)
221  for (const auto& p: split(rs_, exp))
222  aut_->set_initial(label_of(p), weight_of(p));
223  else
224  aut_->set_initial(exp, ws_.one());
225  }
226 
228  void complete_(state_t s) const
229  {
230  const auto& orig = aut_->origins();
231  auto sn = orig.at(s);
232  const_cast<self_t&>(*this).complete_via_expansion_(s, sn);
233  }
234 
236  auto all_out(state_t s) const
237  -> decltype(vcsn::detail::all_out(aut_, s))
238  {
239  if (this->is_lazy(s))
240  complete_(s);
241  return vcsn::detail::all_out(aut_, s);
242  }
243 
245  template <typename ES = expressionset_t,
246  typename = std::enable_if<labelset_t_of<ES>::is_free()>>
248  {
249  aut_->set_lazy(s, false);
250  aut_->set_final(s, constant_term(rs_, src));
251  for (auto l : members_.gens)
252  {
253  auto p = derivation(rs_, src, l, algo_.breaking);
254  if (algo_.determinize)
255  {
256  auto m = ps_.determinize(p);
257  aut_->new_transition(s, label_of(m), l, weight_of(m));
258  }
259  else
260  for (const auto& m: p)
261  aut_->new_transition(s, label_of(m), l, weight_of(m));
262  }
263  }
264 
267  {
268  aut_->set_lazy(s, false);
269  auto expansion = to_expansion_(src);
270  if (algo_.determinize)
272 
273  aut_->set_final(s, expansion.constant);
274  for (const auto& p: expansion.polynomials)
275  if (algo_.breaking)
276  for (const auto& m1: p.second)
277  for (const auto& m2: split(rs_, label_of(m1)))
278  aut_->new_transition(s, label_of(m2), p.first,
279  ws_.mul(weight_of(m1), weight_of(m2)));
280  else if (algo_.determinize)
281  {
282  auto m = ps_.determinize(p.second);
283  aut_->new_transition(s, label_of(m), p.first, weight_of(m));
284  }
285  else
286  for (const auto& m: p.second)
287  aut_->new_transition(s, label_of(m), p.first, weight_of(m));
288  }
289 
293  weightset_t ws_ = *rs_.weightset();
299 
308  };
309  }
310 
312  template <typename ExpSet>
314  = std::shared_ptr<detail::derived_term_automaton_impl<ExpSet>>;
315 
316  template <typename ExpSet>
317  auto
318  make_derived_term_automaton(const ExpSet& rs,
319  const detail::derived_term_algo& algo)
321  {
322  using res_t = derived_term_automaton<ExpSet>;
323  return make_shared_ptr<res_t>(rs, algo);
324  }
325 
331  template <typename ExpSet>
332  std::enable_if_t<labelset_t_of<ExpSet>::is_free(),
333  expression_automaton<mutable_automaton<typename ExpSet::context_t>>>
334  derived_term(const ExpSet& rs,
335  const typename ExpSet::value_t& r,
336  const std::string& algo = "auto")
337  {
338  auto a = detail::derived_term_algo(algo);
339  auto dt = make_derived_term_automaton(rs, a);
340  return dt->operator()(r);
341  }
342 
348  template <typename ExpSet>
349  std::enable_if_t<!labelset_t_of<ExpSet>::is_free(),
350  expression_automaton<mutable_automaton<typename ExpSet::context_t>>>
351  derived_term(const ExpSet& rs,
352  const typename ExpSet::value_t& r,
353  const std::string& algo = "auto")
354  {
355  auto a = detail::derived_term_algo(algo);
357  "derived_term: cannot use derivation on non-free labelsets");
358  // Do not call the operator(), this would trigger the compilation
359  // of via_derivation, which does not compile (on purpose) for non
360  // free labelsets.
361  auto dt = make_derived_term_automaton(rs, a);
362  return dt->via_expansion(r);
363  }
364 
365  namespace dyn
366  {
367  namespace detail
368  {
370  template <typename ExpSet, typename String>
371  automaton derived_term(const expression& exp, const std::string& algo)
372  {
373  const auto& e = exp->as<ExpSet>();
374  const auto& rs = e.valueset();
375  const auto& r = e.value();
376  if (boost::starts_with(algo, "lazy,"))
377  {
378  auto a = vcsn::detail::derived_term_algo(algo);
380  "derived_term: laziness works only with expansions");
381  // Do not call the operator(), this would trigger the compilation
382  // of via_derivation, which does not compile (on purpose) for non
383  // free labelsets.
384  auto res = make_derived_term_automaton(rs, a);
385  res->init_(r);
386  return res;
387  }
388  else
389  return ::vcsn::derived_term(rs, r, algo);
390  }
391  }
392  }
393 } // vcsn::
automaton_t via_derivation(const expression_t &exp)
Compute the derived-term automaton via derivation.
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
std::shared_ptr< detail::expression_automaton_impl< Aut >> expression_automaton
An expression automaton as a shared pointer.
Definition: fwd.hh:61
automaton derived_term(const expression &exp, const std::string &algo)
Bridge.
void complete_via_derivation_(state_t s, const expression_t &src)
Compute the outgoing transitions of src.
Additional members when the labelset is free.
Definition: derived-term.hh:81
symbol sname()
Definition: name.hh:65
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:63
derived_term_algo algo_
How derived terms are computed.
Aggregate an automaton, and forward calls to it.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:61
weightset_t_of< context_t > weightset_t
bool breaking
Whether to break sums.
Definition: derived-term.hh:67
typename labelset_t_of< ExpSet >::genset_t genset_t
The alphabet.
Definition: derived-term.hh:88
auto all_out(state_t s) const -> decltype(vcsn::detail::all_out(aut_, s))
All the outgoing transitions.
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
bool determinize
Whether to determinize the expansions and produce a deterministic automaton, at the expense of possib...
Definition: derived-term.hh:71
derived_term_automaton_impl(const expressionset_t &rs, derived_term_algo algo)
expression_automaton< mutable_automaton< context_t >> automaton_t
The type of the (strict) automaton we build.
auto is_lazy(Args &&...args) const -> decltype(aut_-> is_lazy(std::forward< Args >(args)...))
automaton_t via_expansion(const expression_t &exp)
Compute the derived-term automaton via expansion.
Compute the derived-term automaton from an expression.
return res
Definition: multiply.hh:398
std::shared_ptr< detail::derived_term_automaton_impl< ExpSet >> derived_term_automaton
A derived-term automaton as a shared pointer.
auto weight_of(Args &&...args) const -> decltype(aut_-> weight_of(std::forward< Args >(args)...))
auto label_of(Args &&...args) const -> decltype(aut_-> label_of(std::forward< Args >(args)...))
void complete_(state_t s) const
Complete a state: find its outgoing transitions.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:64
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:277
auto rs
Definition: lift.hh:152
void complete_via_expansion_(state_t s, const expression_t &src)
Compute the outgoing transitions of src.
expressionset_t rs_
The expression's set.
Definition: a-star.hh:8
auto make_derived_term_automaton(const ExpSet &rs, const detail::derived_term_algo &algo) -> derived_term_automaton< ExpSet >
A dyn automaton.
Definition: automaton.hh:17
An input/output format for valuesets.
Definition: format.hh:13
void init_(const expression_t &exp)
Initialize the computation: build the initial states.
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:177
value_impl< detail::expansion_tag > expansion
Definition: fwd.hh:24
derived_term_algo(std::string algo)
From algo name to algo.
Definition: derived-term.hh:38
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7
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.
rat::expression_polynomial_t< ExpSet > split(const ExpSet &rs, const typename ExpSet::value_t &e)
Split an expression.
Definition: split.hh:262
typename expressionset_t::value_t expression_t
Our state names: expressions.
Specify a variety of derived-term construction.
Definition: derived-term.hh:22
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
derived_term_automaton_members< expressionset_t > members_
Possibly the generators.
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:67
automaton_t operator()(const expression_t &exp)
Compute the derived-term automaton.
expression_polynomialset_t< ExpSet > make_expression_polynomialset(const ExpSet &rs)
From a ExpSet to its polynomialset.
Definition: split.hh:31
A mapping from strings to Values.
Definition: getargs.hh:33
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
Definition: automaton.hh:45
std::ostream & print_set(std::ostream &o, format fmt={}) const
value_t determinize(const value_t &v) const
Turn the polynomials into (normalized) monomials.
weight_t_of< ExpSet > constant_term(const ExpSet &rs, const typename ExpSet::value_t &e)
The constant term of e.
value_impl< detail::expression_tag > expression
Definition: fwd.hh:25
context_t_of< expressionset_t > context_t
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54