carl  24.04
Computer ARithmetic Library
Substitution.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "SqrtEx.h"
4 
5 namespace carl {
6 
7 template<typename Poly>
8 SqrtEx<Poly> substitute( const SqrtEx<Poly>& sqrt_ex, const std::map<Variable, typename SqrtEx<Poly>::Rational>& eval_map ) {
9  using Rational = typename SqrtEx<Poly>::Rational;
10  Poly radicandEvaluated = carl::substitute(sqrt_ex.radicand(), eval_map );
11  Poly factorEvaluated = carl::substitute(sqrt_ex.factor(), eval_map );
12  Poly constantPartEvaluated = carl::substitute(sqrt_ex.constant_part(), eval_map );
13  Poly denomEvaluated = carl::substitute(sqrt_ex.denominator(), eval_map );
14  assert( !denomEvaluated.is_constant() || !carl::is_zero( denomEvaluated.constant_part() ) );
15  Rational sqrtExValue;
16  if( radicandEvaluated.is_constant() && carl::sqrt_exact( radicandEvaluated.constant_part(), sqrtExValue ) )
17  {
18  return SqrtEx<Poly>(Poly(constantPartEvaluated + factorEvaluated * sqrtExValue),
20  std::move(denomEvaluated),
22  }
23  return SqrtEx( std::move(constantPartEvaluated), std::move(factorEvaluated), std::move(denomEvaluated), std::move(radicandEvaluated) );
24 }
25 
26 /**
27  * Substitutes a variable in an expression by a square root expression, which results in a square root expression.
28  * @param _substituteIn The polynomial to substitute in.
29  * @param _varToSubstitute The variable to substitute.
30  * @param _substituteBy The square root expression by which the variable gets substituted.
31  * @return The resulting square root expression.
32  */
33 template<typename Poly>
34 SqrtEx<Poly> substitute( const Poly& _substituteIn, const carl::Variable _varToSubstitute, const SqrtEx<Poly>& _substituteBy )
35 {
36  if( !_substituteIn.has( _varToSubstitute ) )
37  return SqrtEx<Poly>( _substituteIn );
38  /*
39  * We have to calculate the result of the substitution:
40  *
41  * q+r*sqrt{t}
42  * (a_n*x^n+...+a_0)[------------ / x]
43  * s
44  * being:
45  *
46  * sum_{k=0}^n (a_k * (q+r*sqrt{t})^k * s^{n-k})
47  * ----------------------------------------------
48  * s^n
49  */
50  auto varInfo = carl::var_info(_substituteIn, _varToSubstitute, true);
51  const auto& coeffs = varInfo.coeffs();
52  // Calculate the s^k: (0<=k<=n)
53  auto coeff = coeffs.begin();
54  carl::uint lastDegree = varInfo.max_degree();
55  std::vector<Poly> sk;
56  sk.push_back(constant_one<Poly>::get());
57  for( carl::uint i = 1; i <= lastDegree; ++i )
58  {
59  // s^i = s^l * s^{i-l}
60  sk.push_back( sk.back() * _substituteBy.denominator() );
61  }
62  // Calculate the constant part and factor of the square root of (q+r*sqrt{t})^k
63  std::vector<Poly> qk;
64  qk.push_back( _substituteBy.constant_part() );
65  std::vector<Poly> rk;
66  rk.push_back( _substituteBy.factor() );
67  // Let (q+r*sqrt{t})^l be (q'+r'*sqrt{t})
68  // then (q+r*sqrt{t})^l+1 = (q'+r'*sqrt{t}) * (q+r*sqrt{t}) = ( q'*q+r'*r't + (q'*r+r'*q) * sqrt{t} )
69  for( carl::uint i = 1; i < lastDegree; ++i )
70  {
71  // q'*q+r'*r't
72  qk.push_back( qk.back() * _substituteBy.constant_part() + rk.back() * _substituteBy.factor() * _substituteBy.radicand() );
73  // q'*r+r'*q
74  rk.push_back( rk.back() * _substituteBy.constant_part() + qk.at( i - 1 ) * _substituteBy.factor() );
75  }
76  // Calculate the result:
77  Poly resFactor = constant_zero<Poly>::get();
78  Poly resConstantPart = constant_zero<Poly>::get();
79  if( coeff->first == 0 )
80  {
81  resConstantPart += sk.back() * coeff->second;
82  ++coeff;
83  }
84  for( ; coeff != coeffs.end(); ++coeff )
85  {
86  resConstantPart += coeff->second * qk.at( coeff->first - 1 ) * sk.at( lastDegree - coeff->first );
87  resFactor += coeff->second * rk.at( coeff->first - 1 ) * sk.at( lastDegree - coeff->first );
88  }
89  return SqrtEx( resConstantPart, resFactor, sk.back(), _substituteBy.radicand() );
90 }
91 
92 }
mpq_class Rational
Definition: HornerTest.cpp:12
carl is the main namespace for the library.
std::uint64_t uint
Definition: numbers.h:16
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
VarInfo< MultivariatePolynomial< Coeff, Ordering, Policies > > var_info(const MultivariatePolynomial< Coeff, Ordering, Policies > &poly, const Variable var, bool collect_coeff=false)
Definition: VarInfo.h:54
Coeff substitute(const Monomial &m, const std::map< Variable, Coeff > &substitutions)
Applies the given substitutions to a monomial.
Definition: Substitution.h:19
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
static const T & get()
Definition: constants.h:42
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