Vcsn  2.1
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(const std::string& algo)
39  {
40  static const auto map = std::map<std::string, derived_term_algo>
41  {
42  // { algo, breaking, deterministic }.
43  {"auto", {expansion, false, false}},
44  {"breaking_derivation", {derivation, true, false}},
45  {"breaking_expansion", {expansion, true, false}},
46  {"derivation", {derivation, false, false}},
47  {"derivation,breaking", {derivation, true, false}},
48  {"derivation,deterministic",{derivation, false, true}},
49  {"derivation_breaking", {derivation, true, false}},
50  {"expansion", {expansion, false, false}},
51  {"expansion,breaking", {expansion, true, false}},
52  {"expansion,deterministic", {expansion, false, true}},
53  {"expansion_breaking", {expansion, true, false}},
54  };
55  *this = getargs("derived-term algorithm", map, algo);
56  }
57 
61  bool breaking = false;
65  bool determinize = false;
66  };
67 
68  /*----------------------------.
69  | derived_term(expression). |
70  `----------------------------*/
71 
101  template <typename ExpSet>
103  {
104  using expressionset_t = ExpSet;
105  using expression_t = typename expressionset_t::value_t;
106 
109 
112 
114  : rs_(rs)
115  , algo_(algo)
116  , res_{make_shared_ptr<automaton_t>(rs_)}
117  {}
118 
121  {
123  return via_derivation(expression);
124  else
125  return via_expansion(expression);
126  }
127 
130  {
131  init_(expression);
132 
133  // The alphabet.
134  const auto& ls = rs_.labelset()->genset();
135  while (!res_->todo_.empty())
136  {
137  expression_t src = res_->todo_.top();
138  state_t s = res_->state(src);
139  res_->todo_.pop();
140  res_->set_final(s, constant_term(rs_, src));
141  for (auto l : ls)
142  {
143  auto p = derivation(rs_, src, l, algo_.breaking);
144  if (algo_.determinize)
145  {
146  auto m = ps_.determinize(p);
147  res_->new_transition(s, label_of(m), l, weight_of(m));
148  }
149  else
150  for (const auto& m: p)
151  res_->new_transition(s, label_of(m), l, weight_of(m));
152  }
153  }
154  return res_;
155  }
156 
159  {
160  init_(expression);
161  // Might be needed to determinize.
163 
165  while (!res_->todo_.empty())
166  {
167  expression_t src = res_->todo_.top();
168  res_->todo_.pop();
169  auto s = res_->state(src);
170  auto expansion = to_expansion(src);
171  if (algo_.determinize)
172  expansion = es.determinize(expansion);
173 
174  res_->set_final(s, expansion.constant);
175  for (const auto& p: expansion.polynomials)
176  if (algo_.breaking)
177  for (const auto& m1: p.second)
178  for (const auto& m2: split(rs_, label_of(m1)))
179  res_->new_transition(s, label_of(m2), p.first,
180  ws_.mul(weight_of(m1), weight_of(m2)));
181  else if (algo_.determinize)
182  {
183  auto m = ps_.determinize(p.second);
184  res_->new_transition(s, label_of(m), p.first, weight_of(m));
185  }
186  else
187  for (const auto& m: p.second)
188  res_->new_transition(s, label_of(m), p.first, weight_of(m));
189  }
190  return res_;
191  }
192 
193  private:
195  {
196  if (algo_.breaking)
197  for (const auto& p: split(rs_, expression))
198  res_->set_initial(label_of(p), weight_of(p));
199  else
200  res_->set_initial(expression, ws_.one());
201  }
202 
206  weightset_t ws_ = *rs_.weightset();
214  };
215  }
216 
222  template <typename ExpSet>
223  inline
226  derived_term(const ExpSet& rs,
227  const typename ExpSet::value_t& r,
228  const std::string& algo = "auto")
229  {
230  auto a = detail::derived_term_algo(algo);
231  auto dt = detail::derived_termer<ExpSet>{rs, a};
232  return dt(r);
233  }
234 
240  template <typename ExpSet>
241  inline
243  expression_automaton<mutable_automaton<typename ExpSet::context_t>>>
244  derived_term(const ExpSet& rs,
245  const typename ExpSet::value_t& r,
246  const std::string& algo = "auto")
247  {
248  auto a = detail::derived_term_algo(algo);
250  "derived_term: cannot use derivation on non-free labelsets");
251  // Do not call the operator(), this would trigger the compilation
252  // of via_derivation, which does not compile (on purpose) for non
253  // free labelsets.
254  auto dt = detail::derived_termer<ExpSet>{rs, a};
255  return dt.via_expansion(r);
256  }
257 
258  namespace dyn
259  {
260  namespace detail
261  {
263  template <typename ExpSet, typename String>
264  inline
265  automaton derived_term(const expression& exp, const std::string& algo)
266  {
267  const auto& e = exp->as<ExpSet>();
268  const auto& rs = e.expressionset();
269  const auto& r = e.expression();
270  return make_automaton(::vcsn::derived_term(rs, r, algo));
271  }
272  }
273  }
274 } // vcsn::
bool breaking
Whether to break sums.
Definition: derived-term.hh:61
state_t_of< automaton_t > state_t
void init_(const expression_t &expression)
std::shared_ptr< detail::expression_automaton_impl< Aut >> expression_automaton
An expression automaton as a shared pointer.
Definition: fwd.hh:60
automaton_t via_derivation(const expression_t &expression)
Compute the derived-term automaton via derivation.
auto label_of(const welement< Label, Weight > &m) -> decltype(m.label())
Definition: wet.hh:125
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
weightset_t ws_
Its weightset.
C::mapped_type getargs(const std::string &kind, const C &map, const std::string &key)
Find a correspondance in a map.
Definition: getargs.hh:21
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
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:51
Compute the derived-term automaton from an expression.
vcsn::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.
typename std::enable_if< Cond, T >::type enable_if_t
Definition: type_traits.hh:16
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
std::shared_ptr< const node< Context >> expression
Definition: fwd.hh:182
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
Functor to compute the expansion of an expression.
Definition: to-expansion.hh:40
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
expression_polynomialset_t< ExpSet > make_expression_polynomialset(const ExpSet &rs)
From a ExpSet to its polynomialset.
Definition: split.hh:33
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
std::shared_ptr< const detail::expansion_base > expansion
Definition: expansion.hh:73
rat::expression_polynomial_t< ExpSet > split(const ExpSet &rs, const typename ExpSet::value_t &e)
Split an expression.
Definition: split.hh:264
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
Definition: wet.hh:132
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:75
derived_term_algo(algo_t a, bool b, bool d)
Definition: derived-term.hh:31
weight_t_of< ExpSet > constant_term(const ExpSet &rs, const typename ExpSet::value_t &e)
The constant term of e.
Specify a variety of derived-term construction.
Definition: derived-term.hh:22
auto rs
Definition: lift.hh:151
derived_term_algo(const std::string &algo)
From algo name to algo.
Definition: derived-term.hh:38
automaton_t operator()(const expression_t &expression)
Compute the derived-term automaton.
derived_termer(const expressionset_t &rs, derived_term_algo algo)
automaton_t res_
The resulting automaton.
context_t_of< expressionset_t > context_t
expressionset_t rs_
The expression's set.
weightset_t_of< context_t > weightset_t
expression_automaton< mutable_automaton< context_t >> automaton_t
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:78
bool determinize
Whether to determinize the expansions and produce a deterministic automaton, at the expense of possib...
Definition: derived-term.hh:65
rat::expansionset< ExpSet >::value_t to_expansion(const ExpSet &rs, const typename ExpSet::value_t &e)
First order expansion.
algo_t algo
Core algorithm.
Definition: derived-term.hh:59
typename expressionset_t::value_t expression_t
derived_term_algo algo_
How derived terms are computed.
automaton_t via_expansion(const expression_t &expression)
Compute the derived-term automaton via expansion.