Vcsn  2.8
Be Rational
derivation.hh
Go to the documentation of this file.
1 #pragma once
2 
4 #include <vcsn/algos/split.hh>
6 #include <vcsn/ctx/fwd.hh>
7 #include <vcsn/dyn/value.hh>
8 #include <vcsn/dyn/value.hh>
9 #include <vcsn/misc/raise.hh>
11 
12 namespace vcsn
13 {
14 
15  /*--------------------------.
16  | derivation(expression). |
17  `--------------------------*/
18 
19  template <typename ExpSet>
20  rat::expression_polynomial_t<ExpSet>
21  derivation(const ExpSet& rs,
22  const typename ExpSet::value_t& e,
23  label_t_of<ExpSet> a,
24  bool breaking = false);
25 
26  namespace rat
27  {
31  template <typename ExpSet>
33  : public ExpSet::const_visitor
34  {
35  public:
36  using expressionset_t = ExpSet;
37  using super_t = typename expressionset_t::const_visitor;
39 
43  using expression_t = typename expressionset_t::value_t;
45  using weight_t = typename weightset_t::value_t;
46 
49 
50  using node_t = typename super_t::node_t;
51 
52  constexpr static const char* me() { return "derivation"; }
53 
55  : rs_(rs)
56  {}
57 
60  {
61  try
62  {
63  variable_ = var;
64  v->accept(*this);
65  return std::move(res_);
66  }
67  catch (const std::runtime_error& e)
68  {
69  raise(e,
70  " while computing derivative of: ", to_string(rs_, v), "\n"
71  " with respect to: ",
72  to_string(*rs_.labelset(), var));
73  }
74  }
75 
76  private:
81 
83  {
84  res_ = ps_.zero();
85  }
86 
88  {
89  res_ = ps_.zero();
90  }
91 
93  {
94  if (e.value() == variable_)
95  res_ = ps_.one();
96  else
97  res_ = ps_.zero();
98  }
99 
101  {
102  super_t::visit(e);
103  }
104 
106  {
107  polynomial_t res = ps_.zero();
108  for (const auto& v: e)
109  {
110  v->accept(*this);
111  ps_.add_here(res, res_);
112  }
113  res_ = std::move(res);
114  }
115 
117  {
118  // We generate a sum.
119  auto res = ps_.zero();
120  // Accumulate the product of the constant terms of the
121  // previous factors.
122  weight_t constant = ws_.one();
123  for (unsigned i = 0, n = e.size(); i < n; ++i)
124  {
125  const auto& v = e[i];
126  v->accept(*this);
127  // See to-expansion.hh, case of mul, for an explanation
128  // of the following line.
129  res_
130  = ps_.rmul_label(res_,
131  prod_(std::next(e.begin(), i+1), std::end(e)));
132  ps_.add_here(res, ps_.lweight(constant, res_));
133  constant = ws_.mul(constant, constant_term(rs_, v));
134  if (ws_.is_zero(constant))
135  break;
136  }
137  res_ = std::move(res);
138  }
139 
145  prod_(typename mul_t::iterator begin,
146  typename mul_t::iterator end) const
147  {
148  using expressions_t = typename mul_t::values_t;
149  if (begin == end)
150  return rs_.one();
151  else if (std::next(begin, 1) == end)
152  return *begin;
153  else
154  return std::make_shared<mul_t>(expressions_t{begin, end});
155  }
156 
157 
159  {
160  // The first polynomial.
161  e.head()->accept(*this);
162  auto res = res_;
163  for (unsigned i = 1, n = e.size(); i < n; ++i)
164  {
165  const auto& v = e[i];
166  v->accept(*this);
167  res = ps_.conjunction(res, res_);
168  }
169  res_ = std::move(res);
170  }
171 
173  {
174  polynomial_t res = ps_.zero();
175  for (unsigned i = 0; i < e.size(); ++i)
176  {
177  e[i]->accept(*this);
178  for (const auto& m: res_)
179  {
180  typename node_t::values_t expressions;
181  for (unsigned j = 0; j < e.size(); ++j)
182  if (i == j)
183  expressions.emplace_back(label_of(m));
184  else
185  expressions.emplace_back(e[j]);
186  // FIXME: we need better n-ary constructors.
187  ps_.add_here(res,
188  std::make_shared<shuffle_t>(expressions),
189  weight_of(m));
190  }
191  }
192  res_ = std::move(res);
193  }
194 
196  {
197  e.sub()->accept(*this);
198  res_ = ps_.complement(res_);
199  }
200 
202  {
203  e.sub()->accept(*this);
204  // We need a copy of e, but without its weights.
205  res_ = ps_.lweight(ws_.star(constant_term(rs_, e.sub())),
206  ps_.rmul_label(res_, e.shared_from_this()));
207  }
208 
210  {
211  e.sub()->accept(*this);
212  res_ = ps_.lweight(e.weight(), res_);
213  }
214 
216  {
217  e.sub()->accept(*this);
218  res_ = ps_.rweight(res_, e.weight());
219  }
220 
221  /*---------.
222  | tuple. |
223  `---------*/
224 
225  using tuple_t = typename super_t::tuple_t;
226  template <bool = context_t::is_lat,
227  typename Dummy = void>
228  struct visit_tuple
229  {
231  template <size_t I>
232  auto work_(const tuple_t& v)
233  {
234  const auto& ps = visitor_.ps_.template project<I>();
235  const auto& rs = visitor_.rs_.template project<I>();
236  if (rs.labelset()->is_one(std::get<I>(visitor_.variable_)))
237  // ∂ε(E) = ⟨c(E)⟩ . 1.
238  return ps.value(rs.one(),
239  constant_term(rs, std::get<I>(v.sub())));
240  else
241  return vcsn::derivation(rs,
242  std::get<I>(v.sub()),
243  std::get<I>(visitor_.variable_));
244  }
245 
247  template <size_t... I>
249  {
250  return visitor_.ps_.tuple(work_<I>(v)...);
251  }
252 
255  {
257  }
258 
259  const self_t& visitor_;
260  };
261 
262  template <typename Dummy>
263  struct visit_tuple<false, Dummy>
264  {
266  {
268  }
269  const self_t& visitor_;
270  };
271 
272  void visit(const tuple_t& v, std::true_type) override
273  {
274  res_ = visit_tuple<>{*this}(v);
275  }
276 
277  private:
280  weightset_t ws_ = *rs_.weightset();
286  };
287  } // rat::
288 
290  template <typename ExpSet>
292  derivation(const ExpSet& rs,
293  const typename ExpSet::value_t& e,
295  bool breaking)
296  {
298  "derivation: requires letterized labelset");
300  auto res = derivation(e, a);
301  if (breaking)
302  res = split(rs, res);
303  return res;
304  }
305 
306 
308  template <typename ExpSet>
310  derivation(const ExpSet& rs,
313  bool breaking = false)
314  {
317  auto res = polynomial_t{};
318  for (const auto& m: p)
319  res = ps.add(res,
320  ps.lweight(weight_of(m),
321  derivation(rs, label_of(m), a, breaking)));
322  return res;
323  }
324 
325 
334  template <typename ExpSet,
335  typename = std::enable_if_t<!std::is_same<word_t_of<ExpSet>,
336  label_t_of<ExpSet>>{}>>
338  derivation(const ExpSet& rs,
339  const typename ExpSet::value_t& e,
340  const word_t_of<ExpSet>& l,
341  bool breaking = false)
342  {
343  auto word = rs.labelset()->letters_of(l);
344  auto i = std::begin(word);
345  auto end = std::end(word);
346  require(i != end, "derivation: word cannot be empty");
347  auto res = derivation(rs, e, *i, breaking);
348  for (++i; i != end; ++i)
349  res = derivation(rs, res, *i, breaking);
350  return res;
351  }
352 
353 
354  namespace dyn
355  {
356  namespace detail
357  {
359  template <typename ExpSet, typename Label, typename Bool>
360  polynomial
361  derivation(const expression& exp, const label& lbl, bool breaking)
362  {
363  const auto& e = exp->as<ExpSet>();
364  const auto& l = lbl->as<Label>().value();
365  const auto& rs = e.valueset();
367  return {ps, vcsn::derivation(rs, e.value(), l, breaking)};
368  }
369  }
370  }
371 } // vcsn::
auto work_(const tuple_t &v)
Work on tape I.
Definition: derivation.hh:232
static constexpr const char * me()
Definition: derivation.hh:52
typename detail::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
Definition: traits.hh:67
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:292
expression_t prod_(typename mul_t::iterator begin, typename mul_t::iterator end) const
Build a product for these expressions.
Definition: derivation.hh:145
typename super_t::node_t node_t
Definition: derivation.hh:50
VCSN_RAT_VISIT(conjunction, e)
Definition: derivation.hh:158
An inner node with multiple children.
Definition: expression.hh:119
typename super_t::tuple_t tuple_t
Definition: derivation.hh:225
auto & as()
Extract wrapped typed value.
Definition: value.hh:55
rat::expression_polynomial_t< ExpSet > split(const ExpSet &rs, const typename ExpSet::value_t &e)
Split an expression.
Definition: split.hh:227
value_impl< detail::polynomial_tag > polynomial
Definition: fwd.hh:33
labelset_t_of< context_t > labelset_t
Definition: derivation.hh:41
polynomial_t operator()(const tuple_t &v)
Entry point.
Definition: derivation.hh:254
An inner node to name the subexpression.
Definition: expression.hh:290
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
typename expression_polynomialset_t< ExpSet >::value_t expression_polynomial_t
Type of polynomials of expressions from the ExpSet type.
Definition: split.hh:26
A dyn Value/ValueSet.
Definition: fwd.hh:29
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
typename weightset_t::value_t weight_t
Definition: derivation.hh:45
polynomial_t res_
The result.
Definition: derivation.hh:283
Definition: a-star.hh:8
context_t_of< expressionset_t > context_t
Definition: derivation.hh:40
typename detail::label_t_of_impl< base_t< ValueSet > >::type label_t_of
Definition: traits.hh:62
typename expressionset_t::value_t expression_t
Definition: derivation.hh:43
void visit(const tuple_t &v, std::true_type) override
Definition: derivation.hh:272
Functor to compute the derivation of an expression.
Definition: derivation.hh:32
std::string to_string(identities i)
Wrapper around operator<<.
Definition: identities.cc:38
An inner node implementing a weight.
Definition: expression.hh:256
A static list of size_t.
Definition: tuple.hh:32
label_t_of< context_t > label_t
Definition: derivation.hh:42
derivation_visitor(const expressionset_t &rs)
Definition: derivation.hh:54
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
The weight of a welement.
Definition: wet.hh:154
return v
Definition: multiply.hh:362
auto label_of(const welement< Label, Weight > &m) -> decltype(m.label())
The label of a welement.
Definition: wet.hh:146
polynomial_t operator()(const expression_t &v, label_t var)
Definition: derivation.hh:59
typename labelset_t_of< base_t< ValueSet > >::word_t word_t_of
Definition: traits.hh:90
value_impl< detail::expression_tag > expression
Definition: fwd.hh:31
weightset_t_of< expressionset_t > weightset_t
Definition: derivation.hh:44
weight_t_of< ExpSet > constant_term(const ExpSet &rs, const typename ExpSet::value_t &e)
The constant term of e.
expression_polynomialset_t< ExpSet > make_expression_polynomialset(const ExpSet &rs)
From a ExpSet to its polynomialset.
Definition: split.hh:31
void require(Bool b, Args &&... args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:87
polynomial_t work_(const tuple_t &v, detail::index_sequence< I... >)
Tuple of derivations of all the tapes.
Definition: derivation.hh:248
#define VCSN_RAT_UNSUPPORTED(Type)
Definition: visitor.hh:75
std::enable_if_t<!is_letterized_t< labelset_t_of< Aut > >{}, bool > is_letterized(const Aut &aut)
Definition: letterize.hh:161
label_t variable_
The derivation variable.
Definition: derivation.hh:285
#define BUILTIN_UNREACHABLE()
Definition: builtins.hh:13
typename polynomialset_t::value_t polynomial_t
Definition: derivation.hh:48
return res
Definition: multiply.hh:399
weightset_t ws_
Shorthand to the weightset.
Definition: derivation.hh:280
typename expressionset_t::const_visitor super_t
Definition: derivation.hh:37