carl  24.04
Computer ARithmetic Library
Derivative.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../MultivariatePolynomial.h"
4 #include "../UnivariatePolynomial.h"
5 
6 #include <algorithm>
7 #include <iterator>
8 
9 namespace carl {
10 namespace detail_derivative {
11  /// Returns n * (n-1) * ... * (n-k+1)
12  constexpr inline std::size_t multiply(std::size_t n, std::size_t k) {
13  std::size_t res = 1;
14  for (; k > 0; --k) res *= n - k + 1;
15  return res;
16  }
17 }
18 
19 /**
20  * Computes the n'th derivative of a number, which is either the number itself (for n = 0) or zero.
21  */
22 template<typename T, EnableIf<is_number_type<T>> = dummy>
23 const T& derivative(const T& t, Variable, std::size_t n = 1) {
24  if (n == 0) return t;
25  return constant_zero<T>::get();
26 }
27 
28 /**
29  * Computes the (partial) n'th derivative of this monomial with respect to the given variable.
30  * @param m Monomial to derive.
31  * @param v Variable.
32  * @param n n.
33  * @return Partial n'th derivative, consisting of constant factor and the remaining monomial.
34  */
35 inline std::pair<std::size_t,Monomial::Arg> derivative(const Monomial::Arg& m, Variable v, std::size_t n = 1) {
36  if (n == 0) return std::make_pair(1, m);
37  auto it = std::find_if(m->begin(), m->end(),
38  [v](const auto& e){ return e.first == v; }
39  );
40  if ((it == m->end()) || (it->second < n)) {
41  CARL_LOG_DEBUG("carl.core", "derivative(" << m << ", " << v << ", " << n << ") = 0");
42  return std::make_pair(0, nullptr);
43  } else if (it->second == n) {
44  std::size_t factor = detail_derivative::multiply(it->second, n);
45  if (m->exponents().size() == 1) {
46  CARL_LOG_DEBUG("carl.core", "derivative(" << m << ", " << v << ", " << n << ") = " << factor);
47  return std::make_pair(factor, nullptr);
48  } else {
49  Monomial::Content newExps;
50  for (const auto& e: *m) {
51  if (e.first == v) continue;
52  newExps.emplace_back(e);
53  }
54  auto res = createMonomial(std::move(newExps), m->tdeg()-n);
55  CARL_LOG_DEBUG("carl.core", "derivative(" << m << ", " << v << ", " << n << ") = " << factor << "*" << res);
56  return std::make_pair(factor, res);
57  }
58  } else {
59  std::size_t factor = detail_derivative::multiply(it->second, n);
60  Monomial::Content newExps = m->exponents();
61  newExps[static_cast<std::size_t>(std::distance(m->begin(), it))].second -= n;
62  auto res = createMonomial(std::move(newExps), m->tdeg()-n);
63  CARL_LOG_DEBUG("carl.core", "derivative(" << m << ", " << v << ", " << n << ") = " << factor << "*" << res);
64  return std::make_pair(factor, res);
65  }
66 }
67 
68 /**
69  * Computes the n'th derivative of t with respect to v.
70  */
71 template<typename C>
72 Term<C> derivative(const Term<C>& t, Variable v, std::size_t n = 1) {
73  if (n == 0) return t;
74  if (t.monomial()) {
75  auto newm = carl::derivative(t.monomial(), v, n);
76  return Term<C>(t.coeff() * newm.first, newm.second);
77  } else {
78  return Term<C>();
79  }
80 }
81 
82 /**
83  * Computes the n'th derivative of p with respect to v.
84  */
85 template<typename C, typename O, typename P>
87 {
88  // Check for trivial cases.
89  if (n == 0) return p;
91 
93  for (const auto& t: p) {
94  newTerms.emplace_back(derivative(t, v, n));
95  if (is_zero(newTerms.back())) newTerms.pop_back();
96  }
97  return MultivariatePolynomial<C,O,P>(std::move(newTerms));
98 }
99 
100 /**
101  * Computes the n'th derivative of p with respect to the main variable of p.
102  */
103 template<typename C>
105  if (n == 0) return p;
106  if (is_zero(p)) return p;
107  if (p.degree() < n) {
108  CARL_LOG_DEBUG("carl.core", "derivative(" << p << ", " << n << ") = 0");
109  return UnivariatePolynomial<C>(p.main_var());
110  }
111 
112  std::vector<C> newCoeffs;
113  for (std::size_t i = 0; i < p.degree() + 1 - n; ++i) {
114  std::size_t factor = detail_derivative::multiply(n + i, n);
115  newCoeffs.emplace_back(static_cast<C>(factor) * p.coefficients()[i + n]);
116  }
117  CARL_LOG_DEBUG("carl.core", "derivative(" << p << ", " << n << ") = " << UnivariatePolynomial<C>(p.main_var(), newCoeffs));
118  return UnivariatePolynomial<C>(p.main_var(), std::move(newCoeffs));
119 }
120 
121 /**
122  * Computes the n'th derivative of p with respect to v.
123  */
124 template<typename C>
126  if (n == 0) return p;
127  if (is_zero(p)) return p;
128  if (v == p.main_var()) return derivative(p, n);
129 
130  std::vector<C> newCoeffs;
131  std::transform(p.coefficients().begin(), p.coefficients().end(), std::back_inserter(newCoeffs),
132  [v,n](const auto& c) { return derivative(c, v, n); }
133  );
134  CARL_LOG_DEBUG("carl.core", "derivative(" << p << ", " << n << ") = " << UnivariatePolynomial<C>(p.main_var(), newCoeffs));
135  return UnivariatePolynomial<C>(p.main_var(), std::move(newCoeffs));
136 }
137 
138 
139 }
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
carl is the main namespace for the library.
Monomial::Arg createMonomial(T &&... t)
Definition: MonomialPool.h:168
const T & derivative(const T &t, Variable, std::size_t n=1)
Computes the n'th derivative of a number, which is either the number itself (for n = 0) or zero.
Definition: Derivative.h:23
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
constexpr std::size_t multiply(std::size_t n, std::size_t k)
Returns n * (n-1) * ... * (n-k+1)
Definition: Derivative.h:12
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
static const T & get()
Definition: constants.h:42
This class represents a univariate polynomial with coefficients of an arbitrary type.
const std::vector< Coefficient > & coefficients() const &
Retrieves the coefficients defining this polynomial.
Variable main_var() const
Retrieves the main variable of this polynomial.
uint degree() const
Get the maximal exponent of the main variable.
The general-purpose multivariate polynomial class.
bool is_constant() const
Check if the polynomial is constant.
std::vector< Term< Coeff > > TermsType
Type our terms vector.f.
std::shared_ptr< const Monomial > Arg
Definition: Monomial.h:62
std::vector< std::pair< Variable, std::size_t > > Content
Definition: Monomial.h:63
Represents a single term, that is a numeric coefficient and a monomial.
Definition: Term.h:23
Coefficient & coeff()
Get the coefficient.
Definition: Term.h:80
Monomial::Arg & monomial()
Get the monomial.
Definition: Term.h:91