carl  24.04
Computer ARithmetic Library
RationalFunction.h
Go to the documentation of this file.
1 /**
2  * @file: RationalFunction.h
3  * @author: Sebastian Junges
4  * @author: Florian Corzilius
5  */
6 
7 #pragma once
10 #include "FactorizedPolynomial.h"
13 
14 #include "evaluation.h"
15 
16 #include <optional>
17 
18 namespace carl {
19 
20 template<typename Pol, bool AutoSimplify = false>
22 public:
23  using PolyType = Pol;
24  using CoeffType = typename Pol::CoeffType;
25  using NumberType = typename Pol::NumberType;
26 
27 private:
28  std::optional<std::pair<Pol, Pol>> mPolynomialQuotient;
31 
32 public:
34  : mNumberQuotient(0),
35  mIsSimplified(true) {}
36 
37  explicit RationalFunction(int v)
38  : mNumberQuotient(v),
39  mIsSimplified(true) {}
40 
41  explicit RationalFunction(const CoeffType& c)
42  : mNumberQuotient(c),
43  mIsSimplified(true) {}
44 
45  template<typename P = Pol, DisableIf<needs_cache_type<P>> = dummy>
47  : mPolynomialQuotient(std::pair<Pol, Pol>(std::move(P(v)), std::move(Pol(1)))),
49  mIsSimplified(true) {}
50 
51  explicit RationalFunction(const Pol& p)
52  : mNumberQuotient(),
53  mIsSimplified(true) {
54  if (p.is_constant())
55  mNumberQuotient = p.constant_part();
56  else
57  mPolynomialQuotient = std::pair<Pol, Pol>(p, std::move(Pol(1)));
58  }
59 
60  explicit RationalFunction(Pol&& p)
61  : mNumberQuotient(),
62  mIsSimplified(true) {
63  if (p.is_constant())
64  mNumberQuotient = p.constant_part();
65  else
66  mPolynomialQuotient = std::pair<Pol, Pol>(std::move(p), std::move(Pol(1)));
67  }
68 
69  explicit RationalFunction(const Pol& nom, const Pol& denom)
70  : mNumberQuotient(),
71  mIsSimplified(false) {
72  if (nom.is_constant() && denom.is_constant()) {
73  mNumberQuotient = nom.constant_part() / denom.constant_part();
74  mIsSimplified = true;
75  } else {
76  mPolynomialQuotient = std::pair<Pol, Pol>(nom, denom);
77  eliminateCommonFactor(!AutoSimplify);
79  }
80  }
81 
82  explicit RationalFunction(Pol&& nom, Pol&& denom)
83  : mPolynomialQuotient(std::pair<Pol, Pol>(std::move(nom), std::move(denom))),
85  mIsSimplified(false) {
86  eliminateCommonFactor(!AutoSimplify);
88  }
89 
90  explicit RationalFunction(std::optional<std::pair<Pol, Pol>>&& quotient, const CoeffType& num, bool simplified)
91  : mPolynomialQuotient(std::move(quotient)),
92  mNumberQuotient(num),
93  mIsSimplified(simplified) {}
94 
95  RationalFunction(const RationalFunction& _rf) = default;
96 
98 
99  ~RationalFunction() noexcept = default;
100 
101  RationalFunction& operator=(const RationalFunction& _rf) = default;
102 
103  RationalFunction& operator=(RationalFunction&& _rf) = default;
104 
105  /**
106  * @return The nominator
107  */
108  Pol nominator() const {
109  if (is_constant())
111  else
112  return mPolynomialQuotient->first;
113  }
114 
115  /**
116  * @return The denominator
117  */
118  Pol denominator() const {
119  if (is_constant())
121  return mPolynomialQuotient->second;
122  }
123 
124  /**
125  * @return The nominator as a polynomial.
126  */
127  const Pol& nominatorAsPolynomial() const {
128  assert(!is_constant());
129  return mPolynomialQuotient->first;
130  }
131 
132  /**
133  * @return The denominator as a polynomial.
134  */
135  const Pol& denominatorAsPolynomial() const {
136  assert(!is_constant());
137  return mPolynomialQuotient->second;
138  }
139 
140  /**
141  * @return The nominator as a polynomial.
142  */
144  assert(is_constant());
146  }
147 
148  /**
149  * @return The denominator as a polynomial.
150  */
152  assert(is_constant());
154  }
155 
156  /**
157  * Checks if this rational function has been simplified since it's last modification.
158  * Note that if AutoSimplify is true, this should always return true.
159  * @return If this is simplified.
160  */
161  bool isSimplified() const {
162  return mIsSimplified;
163  }
164 
165  void simplify() {
166  if (AutoSimplify) {
167  CARL_LOG_WARN("carl.core", "Calling simplify on rational function with AutoSimplify");
168  }
169  eliminateCommonFactor(false);
170  }
171 
172  /**
173  * Returns the inverse of this rational function.
174  * @return Inverse of this.
175  */
177  assert(!this->is_zero());
178  if (is_constant()) {
179  return RationalFunction(std::nullopt, 1 / mNumberQuotient, mIsSimplified);
180  } else {
181  return RationalFunction(std::optional<std::pair<Pol, Pol>>(std::pair<Pol, Pol>(mPolynomialQuotient->second, mPolynomialQuotient->first)), carl::constant_zero<CoeffType>().get(), mIsSimplified);
182  }
183  }
184 
185  /**
186  * Check whether the rational function is zero
187  * @return true if it is
188  */
189  bool is_zero() const {
190  if (is_constant())
194  }
195 
196  bool is_one() const {
197  if (is_constant())
201  }
202 
203  bool is_constant() const {
204  return !mPolynomialQuotient;
205  }
206 
208  if (is_constant())
209  return mNumberQuotient;
210  return nominatorAsPolynomial().constant_part() / denominatorAsPolynomial().constant_part();
211  }
212 
213  /**
214  * Collect all occurring variables
215  * @return All occcurring variables
216  */
217  std::set<Variable> gatherVariables() const {
218  std::set<Variable> vars;
219  gatherVariables(vars);
220  return vars;
221  }
222 
223  /**
224  * Add all occurring variables to the set vars
225  * @param vars
226  */
227  void gatherVariables(std::set<Variable>& vars) const {
228  if (is_constant())
229  return;
230  nominatorAsPolynomial().gatherVariables(vars);
231  denominatorAsPolynomial().gatherVariables(vars);
232  }
233 
234  /**
235  * Evaluate the polynomial at the point described by substitutions.
236  * @param substitutions A mapping from variable to constant values.
237  * @return The result of the substitution
238  */
239  CoeffType evaluate(const std::map<Variable, CoeffType>& substitutions) const {
240  if (is_constant()) {
241  return mNumberQuotient;
242  } else {
243  return carl::evaluate(nominatorAsPolynomial(), substitutions) / carl::evaluate(denominatorAsPolynomial(), substitutions);
244  }
245  }
246 
247  RationalFunction substitute(const std::map<Variable, CoeffType>& substitutions) const {
248  if (is_constant())
249  return *this;
250  else {
252  }
253  }
254 
255  /**
256  * Derivative of the rational function with respect to variable x
257  * @param x the main variable
258  * @param nth which derivative one should take
259  * @return
260  *
261  * @todo Currently only nth = 1 is supported
262  * @todo Curretnly only factorized polynomials are supported
263  */
264  RationalFunction derivative(const Variable& x, unsigned nth = 1) const;
265 
266  std::string toString(bool infix = true, bool friendlyNames = true) const;
267 
268 private:
269  /**
270  * Helper function for simplify which eliminates the common factor.
271  * @param _justNormalize
272  */
273  void eliminateCommonFactor(bool _justNormalize);
274 
275  template<bool byInverse = false>
277 
278  template<bool byInverse = false>
279  RationalFunction& add(const Pol& rhs);
280 
281  template<bool byInverse = false, typename P = Pol, DisableIf<needs_cache_type<P>> = dummy>
283 
284  template<bool byInverse = false>
286 
287 public:
288  /// @name In-place addition operators
289  /// @{
290  /**
291  * Add something to this rational function and return the changed rational function.
292  * @param rhs Right hand side.
293  * @return Changed rational function.
294  */
296  return this->template add<false>(rhs);
297  }
298 
300  return this->template add<false>(rhs);
301  }
302 
304  auto tmp = Pol(rhs);
305  return this->template add<false>(tmp);
306  }
307 
309  auto tmp = Pol(rhs);
310  return this->template add<false>(tmp);
311  }
312 
313  template<typename P = Pol, DisableIf<needs_cache_type<P>> = dummy>
315  return this->template add<false>(rhs);
316  }
317 
319  return this->template add<false>(rhs);
320  }
321  /// @}
322 
323  /// @name In-place subtraction operators
324  /// @{
325  /**
326  * Subtract something from this rational function and return the changed rational function.
327  * @param rhs Right hand side.
328  * @return Changed rational function.
329  */
331  return this->template add<true>(rhs);
332  }
333 
335  return this->template add<true>(rhs);
336  }
337 
339  return (*this -= Pol(rhs));
340  }
341 
343  return (*this -= Pol(rhs));
344  }
345 
346  template<typename P = Pol, DisableIf<needs_cache_type<P>> = dummy>
348  return this->template add<true>(rhs);
349  }
350 
352  return this->template add<true>(rhs);
353  }
354  /// @}
355 
356  /// @name In-place multiplication operators
357  /// @{
358  /**
359  * Multiply something with this rational function and return the changed rational function.
360  * @param rhs Right hand side.
361  * @return Changed rational function.
362  */
366  return (*this *= Pol(rhs));
367  }
369  return (*this *= Pol(rhs));
370  }
371  template<typename P = Pol, DisableIf<needs_cache_type<P>> = dummy>
375  /// @}
376 
377  /// @name In-place division operators
378  /// @{
379  /**
380  * Divide this rational function by something and return the changed rational function.
381  * @param rhs Right hand side.
382  * @return Changed rational function.
383  */
387  return (*this /= Pol(rhs));
388  }
390  return (*this /= Pol(rhs));
391  }
392  template<typename P = Pol, DisableIf<needs_cache_type<P>> = dummy>
395  RationalFunction& operator/=(unsigned long rhs);
396  /// @}
397 
398  template<typename PolA, bool ASA>
400 
401  template<typename PolA, bool ASA>
403 
404  template<typename PolA, bool ASA>
405  friend std::ostream& operator<<(std::ostream& os, const RationalFunction<PolA, ASA>& rhs);
406 };
407 
408 template<typename Pol, bool AS>
410  return RationalFunction<Pol, AS>(lhs) += rhs;
411 }
412 
413 template<typename Pol, bool AS>
415  return RationalFunction<Pol, AS>(lhs) += rhs;
416 }
417 
418 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
420  return RationalFunction<Pol, AS>(lhs) += rhs;
421 }
422 
423 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
425  return RationalFunction<Pol, AS>(lhs) += rhs;
426 }
427 
428 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
430  return RationalFunction<Pol, AS>(lhs) += rhs;
431 }
432 
433 template<typename Pol, bool AS>
434 RationalFunction<Pol, AS> operator+(const RationalFunction<Pol, AS>& lhs, const typename Pol::CoeffType& rhs) {
435  return RationalFunction<Pol, AS>(lhs) += rhs;
436 }
437 
438 template<typename Pol, bool AS>
440  return RationalFunction<Pol, AS>(lhs) *= typename Pol::CoeffType(-1);
441 }
442 
443 template<typename Pol, bool AS>
445  return RationalFunction<Pol, AS>(lhs) -= rhs;
446 }
447 
448 template<typename Pol, bool AS>
450  return RationalFunction<Pol, AS>(lhs) -= rhs;
451 }
452 
453 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
455  return RationalFunction<Pol, AS>(lhs) -= rhs;
456 }
457 
458 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
460  return RationalFunction<Pol, AS>(lhs) -= rhs;
461 }
462 
463 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
465  return RationalFunction<Pol, AS>(lhs) -= rhs;
466 }
467 
468 template<typename Pol, bool AS>
469 RationalFunction<Pol, AS> operator-(const RationalFunction<Pol, AS>& lhs, const typename Pol::CoeffType& rhs) {
470  return RationalFunction<Pol, AS>(lhs) -= rhs;
471 }
472 
473 template<typename Pol, bool AS>
475  return RationalFunction<Pol, AS>(lhs) *= rhs;
476 }
477 
478 template<typename Pol, bool AS>
480  return RationalFunction<Pol, AS>(lhs) *= rhs;
481 }
482 
483 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
485  return RationalFunction<Pol, AS>(lhs) *= rhs;
486 }
487 
488 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
490  return RationalFunction<Pol, AS>(lhs) *= rhs;
491 }
492 
493 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
495  return RationalFunction<Pol, AS>(lhs) *= rhs;
496 }
497 
498 template<typename Pol, bool AS>
499 RationalFunction<Pol, AS> operator*(const RationalFunction<Pol, AS>& lhs, const typename Pol::CoeffType& rhs) {
500  return RationalFunction<Pol, AS>(lhs) *= rhs;
501 }
502 
503 template<typename Pol, bool AS>
504 RationalFunction<Pol, AS> operator*(const typename Pol::CoeffType& lhs, const RationalFunction<Pol, AS>& rhs) {
505  return RationalFunction<Pol, AS>(rhs) *= lhs;
506 }
507 
508 template<typename Pol, bool AS>
510  return RationalFunction<Pol, AS>(lhs) *= rhs;
511 }
512 
513 template<typename Pol, bool AS>
515  return RationalFunction<Pol, AS>(rhs) *= lhs;
516 }
517 
518 template<typename Pol, bool AS>
520  return RationalFunction<Pol, AS>(lhs) /= rhs;
521 }
522 
523 template<typename Pol, bool AS>
525  return RationalFunction<Pol, AS>(lhs) /= rhs;
526 }
527 
528 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
530  return RationalFunction<Pol, AS>(lhs) /= rhs;
531 }
532 
533 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
535  return RationalFunction<Pol, AS>(lhs) /= rhs;
536 }
537 
538 template<typename Pol, bool AS, DisableIf<needs_cache_type<Pol>> = dummy>
540  return RationalFunction<Pol, AS>(lhs) /= rhs;
541 }
542 
543 template<typename Pol, bool AS>
544 RationalFunction<Pol, AS> operator/(const RationalFunction<Pol, AS>& lhs, const typename Pol::CoeffType& rhs) {
545  return RationalFunction<Pol, AS>(lhs) /= rhs;
546 }
547 
548 template<typename Pol, bool AS>
550  return RationalFunction<Pol, AS>(lhs) /= rhs;
551 }
552 
553 // TODO: Make more efficient :).
554 template<typename Pol, bool AS>
556  static_assert(!std::is_same<Pol, Pol>::value, "Use carl::pow(rf, exp) instead. ");
558  for (unsigned i = exp; i > 0; --i) {
559  res *= rf;
560  }
561  return res;
562 }
563 
564 template<typename Pol, bool AS>
566  return !(lhs == rhs);
567 }
568 
569 } // namespace carl
570 
571 namespace std {
572 template<typename Pol, bool AS>
573 struct hash<carl::RationalFunction<Pol, AS>> {
574  std::size_t operator()(const carl::RationalFunction<Pol, AS>& r) const {
575  if (r.is_constant())
577  else
579  }
580 };
581 } // namespace std
582 
583 #include "RationalFunction.tpp"
#define CARL_LOG_WARN(channel, msg)
Definition: carl-logging.h:41
MultivariatePolynomial< Rational > Pol
Definition: HornerTest.cpp:17
carl is the main namespace for the library.
Interval< Number > operator/(const Interval< Number > &lhs, const Number &rhs)
Operator for the division of an interval and a number.
Definition: operators.h:453
Interval< Number > operator+(const Interval< Number > &lhs, const Interval< Number > &rhs)
Operator for the addition of two intervals.
Definition: operators.h:261
Interval< Number > quotient(const Interval< Number > &_lhs, const Interval< Number > &_rhs)
Implements the division with remainder.
Definition: Interval.h:1488
Interval< Number > exp(const Interval< Number > &i)
Definition: Exponential.h:10
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
Interval< Number > operator*(const Interval< Number > &lhs, const Interval< Number > &rhs)
Operator for the multiplication of two intervals.
Definition: operators.h:386
bool evaluate(const BasicConstraint< Poly > &c, const Assignment< Number > &m)
Definition: Evaluation.h:10
cln::cl_I get_num(const cln::cl_RA &n)
Extract the numerator from a fraction.
Definition: operations.h:60
Coeff substitute(const Monomial &m, const std::map< Variable, Coeff > &substitutions)
Applies the given substitutions to a monomial.
Definition: Substitution.h:19
Interval< Number > operator-(const Interval< Number > &rhs)
Unary minus.
Definition: operators.h:318
bool operator!=(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
cln::cl_I get_denom(const cln::cl_RA &n)
Extract the denominator from a fraction.
Definition: operations.h:69
std::int64_t sint
Definition: numbers.h:17
std::size_t hash_all(Args &&... args)
Hashes an arbitrary number of values.
Definition: hash.h:71
Interval< Number > pow(const Interval< Number > &i, Integer exp)
Definition: Power.h:11
bool is_one(const Interval< Number > &i)
Check if this interval is a point-interval containing 1.
Definition: Interval.h:1462
auto & get(const std::string &name)
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
static const T & get()
Definition: constants.h:42
std::shared_ptr< const Monomial > Arg
Definition: Monomial.h:62
Represents a single term, that is a numeric coefficient and a monomial.
Definition: Term.h:23
RationalFunction & operator-=(const CoeffType &rhs)
Subtract something from this rational function and return the changed rational function.
void eliminateCommonFactor(bool _justNormalize)
Helper function for simplify which eliminates the common factor.
CoeffType evaluate(const std::map< Variable, CoeffType > &substitutions) const
Evaluate the polynomial at the point described by substitutions.
RationalFunction & operator+=(const Monomial::Arg &rhs)
Add something to this rational function and return the changed rational function.
const Pol & nominatorAsPolynomial() const
friend std::ostream & operator<<(std::ostream &os, const RationalFunction< PolA, ASA > &rhs)
RationalFunction & operator*=(const Pol &rhs)
Multiply something with this rational function and return the changed rational function.
RationalFunction & operator*=(const CoeffType &rhs)
Multiply something with this rational function and return the changed rational function.
RationalFunction(std::optional< std::pair< Pol, Pol >> &&quotient, const CoeffType &num, bool simplified)
RationalFunction & operator/=(const Monomial::Arg &rhs)
Divide this rational function by something and return the changed rational function.
RationalFunction & operator-=(const RationalFunction &rhs)
Subtract something from this rational function and return the changed rational function.
RationalFunction & operator-=(const Monomial::Arg &rhs)
Subtract something from this rational function and return the changed rational function.
RationalFunction(const RationalFunction &_rf)=default
typename Pol::CoeffType CoeffType
RationalFunction & operator/=(const CoeffType &rhs)
Divide this rational function by something and return the changed rational function.
RationalFunction(Pol &&nom, Pol &&denom)
RationalFunction & operator/=(const Term< CoeffType > &rhs)
Divide this rational function by something and return the changed rational function.
CoeffType constant_part() const
std::set< Variable > gatherVariables() const
Collect all occurring variables.
RationalFunction & add(const RationalFunction &rhs)
RationalFunction & operator*=(carl::sint rhs)
Multiply something with this rational function and return the changed rational function.
RationalFunction derivative(const Variable &x, unsigned nth=1) const
Derivative of the rational function with respect to variable x.
RationalFunction & operator+=(const Term< CoeffType > &rhs)
Add something to this rational function and return the changed rational function.
bool isSimplified() const
Checks if this rational function has been simplified since it's last modification.
RationalFunction & add(const CoeffType &rhs)
std::optional< std::pair< Pol, Pol > > mPolynomialQuotient
typename Pol::NumberType NumberType
friend bool operator<(const RationalFunction< PolA, ASA > &lhs, const RationalFunction< PolA, ASA > &rhs)
RationalFunction & operator*=(const Monomial::Arg &rhs)
Multiply something with this rational function and return the changed rational function.
RationalFunction(const Pol &nom, const Pol &denom)
RationalFunction inverse() const
Returns the inverse of this rational function.
RationalFunction(RationalFunction &&_rf)=default
RationalFunction & operator-=(Variable rhs)
Subtract something from this rational function and return the changed rational function.
friend bool operator==(const RationalFunction< PolA, ASA > &lhs, const RationalFunction< PolA, ASA > &rhs)
RationalFunction & operator*=(Variable rhs)
Multiply something with this rational function and return the changed rational function.
RationalFunction & operator/=(unsigned long rhs)
Divide this rational function by something and return the changed rational function.
RationalFunction & operator*=(const Term< CoeffType > &rhs)
Multiply something with this rational function and return the changed rational function.
RationalFunction & operator-=(const Term< CoeffType > &rhs)
Subtract something from this rational function and return the changed rational function.
RationalFunction & add(Variable rhs)
RationalFunction & operator-=(const Pol &rhs)
Subtract something from this rational function and return the changed rational function.
void gatherVariables(std::set< Variable > &vars) const
Add all occurring variables to the set vars.
RationalFunction & operator/=(const Pol &rhs)
Divide this rational function by something and return the changed rational function.
RationalFunction & add(const Pol &rhs)
RationalFunction & operator+=(const RationalFunction &rhs)
Add something to this rational function and return the changed rational function.
RationalFunction & operator+=(Variable rhs)
Add something to this rational function and return the changed rational function.
RationalFunction(const CoeffType &c)
RationalFunction & operator/=(Variable rhs)
Divide this rational function by something and return the changed rational function.
bool is_zero() const
Check whether the rational function is zero.
RationalFunction & operator+=(const CoeffType &rhs)
Add something to this rational function and return the changed rational function.
RationalFunction & operator+=(const Pol &rhs)
Add something to this rational function and return the changed rational function.
RationalFunction(const Pol &p)
const Pol & denominatorAsPolynomial() const
CoeffType nominatorAsNumber() const
RationalFunction substitute(const std::map< Variable, CoeffType > &substitutions) const
RationalFunction & operator/=(const RationalFunction &rhs)
Divide this rational function by something and return the changed rational function.
~RationalFunction() noexcept=default
CoeffType denominatorAsNumber() const
std::string toString(bool infix=true, bool friendlyNames=true) const
RationalFunction & operator*=(const RationalFunction &rhs)
Multiply something with this rational function and return the changed rational function.
std::size_t operator()(const carl::RationalFunction< Pol, AS > &r) const