carl  24.04
Computer ARithmetic Library
FieldExtensions.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../Evaluation.h"
4 
6 
7 #ifdef USE_COCOA
8 #include <CoCoA/library.H>
9 #endif
10 
11 namespace carl::ran::interval {
12 namespace detail_field_extensions {
13  #ifdef USE_COCOA
14 
15  struct CoCoAConverter {
16 
17  std::map<Variable, CoCoA::RingElem> mSymbolThere;
18  std::map<std::pair<long,std::size_t>, Variable> mSymbolBack;
19 
20  auto buildPolyRing(CoCoA::ring coeff_ring, Variable v) {
21  CoCoA::SparsePolyRing ring = CoCoA::NewPolyRing(coeff_ring, {CoCoA::NewSymbol()});
22  mSymbolThere.emplace(v, CoCoA::indets(ring)[0]);
23  mSymbolBack.emplace(std::make_pair(CoCoA::RingID(ring), 0), v);
24  return ring;
25  }
26 
27  CoCoA::BigRat convert(const mpq_class& n) const {
28  return CoCoA::BigRatFromMPQ(n.get_mpq_t());
29  }
30  template<typename T>
31  T convert(const CoCoA::BigRat& n) const {
32  if constexpr(std::is_same<T,mpq_class>::value) {
33  return mpq_class(CoCoA::mpqref(n));
34  }
35  #ifdef USE_CLN_NUMBERS
36  else if constexpr(std::is_same<T,cln::cl_RA>::value) {
37  std::stringstream ss;
38  ss << n;
39  return T(ss.str().c_str());
40  }
41  #endif
42  else {
43  CARL_LOG_ERROR("carl.ran.interval", "Unsupported number type.");
44  }
45  }
46  #ifdef USE_CLN_NUMBERS
47  CoCoA::BigRat convert(const cln::cl_RA& n) const {
48  std::stringstream ss;
49  ss << n;
50  return CoCoA::BigRatFromString(ss.str());
51  }
52  #endif
53 
54  template<typename Poly>
55  Poly convertMV(const CoCoA::RingElem& p) const {
56  Poly res;
57  for (CoCoA::SparsePolyIter i = CoCoA::BeginIter(p); !CoCoA::IsEnded(i); ++i) {
58  Poly coeff;
59  CoCoA::BigRat numcoeff;
60  if (CoCoA::IsRational(numcoeff, CoCoA::coeff(i))) {
61  coeff = Poly(convert<typename Poly::CoeffType>(numcoeff));
62  } else {
63  coeff = convertMV<Poly>(CoCoA::CanonicalRepr(CoCoA::coeff(i)));
64  }
65  if (CoCoA::IsOne(CoCoA::PP(i))) {
66  res += coeff;
67  } else {
68  std::vector<long> exponents;
69  CoCoA::exponents(exponents, CoCoA::PP(i));
70  Monomial::Content monContent;
71  std::size_t tdeg = 0;
72  for (std::size_t i = 0; i < exponents.size(); ++i) {
73  if (exponents[i] == 0) continue;
74  const auto& ring = CoCoA::owner(p);
75  monContent.emplace_back(mSymbolBack.at(std::make_pair(CoCoA::RingID(ring),i)), exponents[i]);
76  tdeg += std::size_t(exponents[i]);
77  }
78  res += coeff * createMonomial(std::move(monContent), tdeg);
79  }
80  }
81  return res;
82  }
83 
84  template<typename Poly>
85  CoCoA::RingElem convertMV(const Poly& p, const CoCoA::ring& ring) const {
86  CoCoA::RingElem res(ring);
87  for (const auto& t: p) {
88  if (!t.monomial()) {
89  res += convert(t.coeff());
90  continue;
91  }
92  std::vector<long> exponents(mSymbolBack.size());
93  for (const auto& p: *t.monomial()) {
94  auto it = mSymbolThere.find(p.first);
95  assert(it != mSymbolThere.end());
96  long indetIndex;
97  if (CoCoA::IsIndet(indetIndex, it->second)) {
98  exponents[std::size_t(indetIndex)] = long(p.second);
99  } else {
100  assert(false && "The symbol is not an inderminant.");
101  }
102  }
103  res += CoCoA::monomial(ring, convert(t.coeff()), exponents);
104  }
105  return res;
106  }
107 
108  template<typename Poly>
109  CoCoA::RingElem convertUV(const Poly& p, const CoCoA::SparsePolyRing& ring) const {
110  CoCoA::RingElem res(ring);
111  CoCoA::RingElem exp(ring, 1);
112  CoCoA::RingElem var = mSymbolThere.at(p.main_var());
113  for (std::size_t deg = 0; deg <= p.degree(); ++deg) {
114  res += convert(p.coefficients()[deg]) * exp;
115  exp *= var;
116  }
117  return res;
118  }
119  };
120  #endif
121 }
122 
123 /**
124  * This class can be used to construct iterated field extensions from a sequence of real algebraic numbers.
125  * In particular it makes sure that the minimal polynomials are "reduced", i.e. making sure that they are minimal polynomial w.r.t. the current extension field.
126  */
127 template<typename Rational, typename Poly>
129 private:
130  std::map<Variable,IntRepRealAlgebraicNumber<Rational>> mModel;
131 
132  #ifdef USE_COCOA
133  CoCoA::ring mQ = CoCoA::RingQQ();
134  detail_field_extensions::CoCoAConverter cc;
135 
136  auto buildPolyRing(Variable v) {
137  return cc.buildPolyRing(mQ, v);
138  }
139 
140  bool evaluatesToZero(const CoCoA::RingElem& p) const {
141  auto mp = cc.convertMV<Poly>(p);
143  CARL_LOG_DEBUG("carl.ran.interval", "Evaluated " << p << " -> " << mp << " == 0 -> " << res);
144  assert(!indeterminate(res));
145  return (bool)res;
146  }
147 
148  void extendRing(const CoCoA::ring& ring, const CoCoA::RingElem& p) {
149  mQ = CoCoA::NewQuotientRing(ring, CoCoA::ideal(p));
150  }
151  #endif
152 
153 public:
154  /**
155  * Extend the current number field with the field extension defined by r.
156  * The minimal polynomial of r (with is a minimal polynomials in Q[x]) is
157  * embedded into the current number field and the minimal polynomial for r within this number field is computed.
158  * The resulting polynomial is this minimal polynomial over the current number field.
159  *
160  * We may have one of two cases:
161  * - We can eliminate v by substitution with some term
162  * - We create a new field extension and may have to reduce the lifting polynomial
163  *
164  * In the first case, we return true and the term to substitute with.
165  * In the second case, we return false and the new minimal polynomial.
166  */
167  std::pair<bool,Poly> extend(Variable v, const IntRepRealAlgebraicNumber<Rational>& r) {
168  #ifdef USE_COCOA
169  mModel.emplace(v, r);
170  if (r.is_numeric()) {
171  CARL_LOG_DEBUG("carl.ran.interval", "Is numeric: " << v << " -> " << r);
172  return std::make_pair(true, Poly(r.value()));
173  }
174  auto ci = buildPolyRing(v);
175  CoCoA::RingElem p = cc.convertUV(replace_main_variable(r.polynomial(), v), ci);
176  CARL_LOG_DEBUG("carl.ran.interval", "Factorization of " << p << " on " << ci);
177  auto factorization = CoCoA::factor(p);
178  CARL_LOG_DEBUG("carl.ran.interval", "-> " << factorization);
179  for (const auto& f: factorization.myFactors()) {
180  if (evaluatesToZero(f)) {
181  CARL_LOG_DEBUG("carl.ran.interval", "Factor " << f << " is zero in assignment.");
182  if (CoCoA::deg(f) == 1) {
183  auto cf =-(f -CoCoA::LF(f)) / CoCoA::CoeffEmbeddingHom(CoCoA::owner(f))(CoCoA::LC(f));
184  return std::make_pair(true, cc.convertMV<Poly>(cf));
185  } else {
186  extendRing(ci, f);
187  return std::make_pair(false, cc.convertMV<Poly>(f));
188  }
189  }
190  }
191  CARL_LOG_ERROR("carl.ran.interval", "No factor is zero in assignment.");
192  assert(false);
193  return std::make_pair(false, Poly());
194  #else
195  CARL_LOG_ERROR("carl.ran.interval", "CoCoALib is not enabled");
196  assert(false);
197  return std::make_pair(false, Poly());
198  #endif
199  }
200 
201  Poly embed(const Poly& poly) { // TODO not functional yet
202  #ifdef USE_COCOA
203  CARL_LOG_DEBUG("carl.ran.interval", "Embed " << poly << " into " << mQ);
204  auto f = cc.convertMV(poly, mQ);
205  CARL_LOG_DEBUG("carl.ran.interval", "Embedding is " << f);
206  return cc.convertMV<Poly>(f);
207  #else
208  CARL_LOG_ERROR("carl.ran.interval", "CoCoALib is not enabled");
209  assert(false);
210  return Poly();
211  #endif
212  }
213 };
214 
215 }
#define CARL_LOG_ERROR(channel, msg)
Definition: carl-logging.h:40
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
Monomial::Arg createMonomial(T &&... t)
Definition: MonomialPool.h:168
Interval< Number > exp(const Interval< Number > &i)
Definition: Exponential.h:10
bool evaluate(const BasicConstraint< Poly > &c, const Assignment< Number > &m)
Definition: Evaluation.h:10
UnivariatePolynomial< Coeff > replace_main_variable(const UnivariatePolynomial< Coeff > &p, Variable newVar)
Replaces the main variable in a polynomial.
BasicConstraint< ToPoly > convert(const typename ToPoly::ContextType &context, const BasicConstraint< FromPoly > &c)
Definition: Conversion.h:9
Factors< MultivariatePolynomial< C, O, P > > factorization(const MultivariatePolynomial< C, O, P > &p, bool includeConstants=true)
Try to factorize a multivariate polynomial.
Definition: Factorization.h:31
Represent a polynomial (in)equality against zero.
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
std::vector< std::pair< Variable, std::size_t > > Content
Definition: Monomial.h:63
const auto & value() const
Definition: Ran.h:227
const auto & polynomial() const
Definition: Ran.h:218
bool is_numeric() const
Definition: Ran.h:214
This class can be used to construct iterated field extensions from a sequence of real algebraic numbe...
std::map< Variable, IntRepRealAlgebraicNumber< Rational > > mModel
std::pair< bool, Poly > extend(Variable v, const IntRepRealAlgebraicNumber< Rational > &r)
Extend the current number field with the field extension defined by r.