carl  24.04
Computer ARithmetic Library
Evaluation.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "SqrtEx.h"
4 
5 namespace carl {
6 
7 /**
8  * @brief Evaluates the square root expression. Might be not exact when a square root is rounded.
9  *
10  * @tparam Poly
11  * @param sqrt_ex The square root expression to be evaluated.
12  * @param eval_map Assignments for all variables.
13  * @param rounding -1 if square root should be rounded downwards, 1 if the square root should be rounded upwards, 0 if double precision is fine.
14  * @return std::pair<SqrtEx<Poly>::Rational, bool> The first component is the evaluation result, the second indicates whether the result is exact (true) or rounded (false).
15  */
16 template<typename Poly>
17 std::pair<typename SqrtEx<Poly>::Rational, bool> evaluate(const SqrtEx<Poly>& sqrt_ex, const std::map<Variable, typename SqrtEx<Poly>::Rational>& eval_map, int rounding) {
18  using Rational = typename SqrtEx<Poly>::Rational;
19 
20  Poly radicandEvaluated = carl::substitute(sqrt_ex.radicand(), eval_map );
21  assert( radicandEvaluated.is_constant() );
22  Rational radicandValue = radicandEvaluated.constant_part();
23  assert( radicandValue >= 0 );
24  Poly factorEvaluated = carl::substitute(sqrt_ex.factor(), eval_map );
25  assert( factorEvaluated.is_constant() );
26  Rational factorValue = factorEvaluated.constant_part();
27  Poly constantPartEvaluated = carl::substitute(sqrt_ex.constant_part(), eval_map );
28  assert( constantPartEvaluated.is_constant() );
29  Rational constantPartValue = constantPartEvaluated.constant_part();
30  Poly denomEvaluated = carl::substitute(sqrt_ex.denominator(), eval_map );
31  assert( denomEvaluated.is_constant() );
32  Rational denomValue = denomEvaluated.constant_part();
33  assert( !carl::is_zero( denomValue ) );
34  // Check whether the resulting assignment is integer.
35  bool exact = true;
36  Rational sqrtExValue;
37  if( !carl::sqrt_exact( radicandValue, sqrtExValue ) )
38  {
39  assert( rounding != 0 );
40  exact = false;
41  assert( factorValue != 0 );
42  double dbSqrt = sqrt( carl::to_double( radicandValue ) );
43  sqrtExValue = carl::rationalize<Rational>( dbSqrt ) ;
44  // As there is no rational number representing the resulting square root we have to round.
45  if( rounding < 0 ) // If the result should round down in this case.
46  {
47  if( factorValue > 0 && (sqrtExValue*sqrtExValue) > radicandValue )
48  {
49  // The factor of the resulting square root is positive, hence force rounding down.
50  dbSqrt = std::nextafter( dbSqrt, -INFINITY );
51  sqrtExValue = carl::rationalize<Rational>( dbSqrt );
52  assert( !((sqrtExValue*sqrtExValue) > radicandValue) );
53  }
54  else if( factorValue < 0 && (sqrtExValue*sqrtExValue) < radicandValue )
55  {
56  // The factor of the resulting square root is negative, hence force rounding up.
57  dbSqrt = std::nextafter( dbSqrt, INFINITY );
58  sqrtExValue = carl::rationalize<Rational>( dbSqrt );
59  assert( !((sqrtExValue*sqrtExValue) < radicandValue) );
60  }
61  }
62  else if( rounding > 0 ) // If the result should round up in this case.
63  {
64  if( factorValue < 0 && (sqrtExValue*sqrtExValue) > radicandValue )
65  {
66  // The factor of the resulting square root is negative, hence force rounding down.
67  dbSqrt = std::nextafter( dbSqrt, -INFINITY );
68  sqrtExValue = carl::rationalize<Rational>( dbSqrt );
69  assert( !((sqrtExValue*sqrtExValue) > radicandValue) );
70  }
71  else if( factorValue > 0 && (sqrtExValue*sqrtExValue) < radicandValue )
72  {
73  // The factor of the resulting square root is positive, hence force rounding up.
74  dbSqrt = std::nextafter( dbSqrt, INFINITY );
75  sqrtExValue = carl::rationalize<Rational>( dbSqrt );
76  assert( !((sqrtExValue*sqrtExValue) < radicandValue) );
77  }
78  }
79  }
80  return std::make_pair(((constantPartValue + factorValue * sqrtExValue) / denomValue), exact);
81 }
82 
83 }
mpq_class Rational
Definition: HornerTest.cpp:12
carl is the main namespace for the library.
bool sqrt_exact(const cln::cl_RA &a, cln::cl_RA &b)
Calculate the square root of a fraction if possible.
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
bool evaluate(const BasicConstraint< Poly > &c, const Assignment< Number > &m)
Definition: Evaluation.h:10
Interval< Number > sqrt(const Interval< Number > &i)
Definition: Power.h:51
Coeff substitute(const Monomial &m, const std::map< Variable, Coeff > &substitutions)
Applies the given substitutions to a monomial.
Definition: Substitution.h:19
double to_double(const cln::cl_RA &n)
Converts the given fraction to a double.
Definition: operations.h:113
Bitset exact(SetCover &sc)
Exact "heuristic": Computes a minimum set cover.
Definition: exact.cpp:35
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
const Poly & radicand() const
Definition: SqrtEx.h:93
const Poly & constant_part() const
Definition: SqrtEx.h:69
const Poly & denominator() const
Definition: SqrtEx.h:85
typename UnderlyingNumberType< Poly >::type Rational
Definition: SqrtEx.h:23
const Poly & factor() const
Definition: SqrtEx.h:77