carl  24.04
Computer ARithmetic Library
CoCoAAdaptor.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <carl-common/config.h>
4 
5 #ifdef USE_COCOA
6 
13 #include <carl-arith/core/Common.h>
14 #include "CoCoAAdaptorStatistics.h"
15 
16 #include <algorithm>
17 #include <cstdlib>
18 #include <iterator>
19 #include <map>
20 
21 //#include "CoCoA/library.H"
22 #include <CoCoA/BigInt.H>
23 #include <CoCoA/BigRat.H>
24 #include <CoCoA/factorization.H>
25 #include <CoCoA/ring.H>
26 #include <CoCoA/RingQQ.H>
27 #include <CoCoA/SparsePolyIter.H>
28 #include <CoCoA/SparsePolyOps-RingElem.H>
29 #include <CoCoA/SparsePolyRing.H>
30 
31 namespace carl {
32 /**
33  * This namespace contains wrapper for all heavy CoCoALib methods.
34  * They are implemented in a separate source file, attempting to reduce the
35  * amount of code included from CoCoALib.
36  */
37 namespace cocoawrapper {
38  /// Calls CoCoA::gcd(p,q).
39  CoCoA::RingElem gcd(const CoCoA::RingElem& p, const CoCoA::RingElem& q);
40  /// Calls CoCoA::factor(p).
41  CoCoA::factorization<CoCoA::RingElem> factor(const CoCoA::RingElem& p);
42  /// Calls CoCoA::ReducedGBasis(CoCoA::ideal(p)).
43  std::vector<CoCoA::RingElem> ReducedGBasis(const std::vector<CoCoA::RingElem>& p);
44  /// Calls CoCoA::SqFreeFactor(p).
45  CoCoA::factorization<CoCoA::RingElem> SqFreeFactor(const CoCoA::RingElem& p);
46 }
47 
48 template<typename Poly>
49 class CoCoAAdaptor {
50 private:
51  std::map<Variable, CoCoA::RingElem> mSymbolThere;
52  std::vector<Variable> mSymbolBack;
53  CoCoA::ring mQ = CoCoA::RingQQ();
54  CoCoA::SparsePolyRing mRing;
55 public:
56  CoCoA::BigInt convert(const mpz_class& n) const {
57  return CoCoA::BigIntFromMPZ(n.get_mpz_t());
58  }
59  mpz_class convert(const CoCoA::BigInt& n) const {
60  return mpz_class(CoCoA::mpzref(n));
61  }
62  CoCoA::BigRat convert(const mpq_class& n) const {
63  return CoCoA::BigRatFromMPQ(n.get_mpq_t());
64  }
65  mpq_class convert(const CoCoA::BigRat& n) const {
66  return mpq_class(CoCoA::mpqref(n));
67  }
68 
69  void convert(mpz_class& res, const CoCoA::RingElem& n) const {
70  CoCoA::BigInt i;
71  CoCoA::IsInteger(i, n);
72  res = convert(i);
73  }
74  void convert(mpq_class& res, const CoCoA::RingElem& n) const {
75  CoCoA::BigRat r;
76  CoCoA::IsRational(r, n);
77  res = convert(r);
78  }
79 
80 #ifdef USE_CLN_NUMBERS
81  CoCoA::BigInt convert(const cln::cl_I& n) const {
82  return convert(carl::convert<cln::cl_I, mpz_class>(n));
83  }
84  CoCoA::BigRat convert(const cln::cl_RA& n) const {
85  return convert(carl::convert<cln::cl_RA, mpq_class>(n));
86  }
87  void convert(cln::cl_I& res, const CoCoA::RingElem& n) const {
88  CoCoA::BigInt i;
89  CoCoA::IsInteger(i, n);
90  res = carl::convert<mpz_class, cln::cl_I>(convert(i));
91  }
92  void convert(cln::cl_RA& res, const CoCoA::RingElem& n) const {
93  CoCoA::BigRat r;
94  CoCoA::IsRational(r, n);
95  res = carl::convert<mpq_class, cln::cl_RA>(convert(r));
96  }
97 #endif
98 
99  static carlVariables variables(const std::vector<Poly>& polys) {
100  carlVariables vars;
101  for (const auto& p: polys) carl::variables(p, vars);
102  return vars;
103  }
104 
105  CoCoA::RingElem convert(const Poly& p) const {
106  CoCoA::RingElem res(mRing);
107  for (const auto& t: p) {
108  if (!t.monomial()) {
109  res += convert(t.coeff());
110  continue;
111  }
112  std::vector<long> exponents(mSymbolBack.size());
113  for (const auto& p: *t.monomial()) {
114  auto it = mSymbolThere.find(p.first);
115  assert(it != mSymbolThere.end());
116  long indetIndex;
117  if (CoCoA::IsIndet(indetIndex, it->second)) {
118  exponents[std::size_t(indetIndex)] = long(p.second);
119  } else {
120  assert(false && "The symbol is not an inderminant.");
121  }
122  }
123  res += CoCoA::monomial(mRing, convert(t.coeff()), exponents);
124  }
125  return res;
126  }
127 
128  Poly convert(const CoCoA::RingElem& p) const {
129  Poly res;
130  for (CoCoA::SparsePolyIter i = CoCoA::BeginIter(p); !CoCoA::IsEnded(i); ++i) {
131  typename Poly::CoeffType coeff;
132  convert(coeff, CoCoA::coeff(i));
133  if (CoCoA::IsOne(CoCoA::PP(i))) {
134  res += coeff;
135  } else {
136  std::vector<long> exponents;
137  CoCoA::exponents(exponents, CoCoA::PP(i));
138  Monomial::Content monContent;
139  std::size_t tdeg = 0;
140  for (std::size_t i = 0; i < exponents.size(); ++i) {
141  if (exponents[i] == 0) continue;
142  monContent.emplace_back(mSymbolBack[i], exponents[i]);
143  tdeg += std::size_t(exponents[i]);
144  }
145  std::sort(monContent.begin(), monContent.end(), [](const std::pair<Variable, exponent>& p1, const std::pair<Variable, exponent>& p2){ return p1.first < p2.first; });
146  res += typename Poly::TermType(std::move(coeff), createMonomial(std::move(monContent), tdeg));
147  }
148  }
149  return res;
150  }
151 
152  std::vector<CoCoA::RingElem> convert(const std::vector<Poly>& p) const {
153  std::vector<CoCoA::RingElem> res;
154  for (const auto& poly: p) res.emplace_back(convert(poly));
155  return res;
156  }
157  std::vector<Poly> convert(const std::vector<CoCoA::RingElem>& p) const {
158  std::vector<Poly> res;
159  for (const auto& poly: p) res.emplace_back(convert(poly));
160  return res;
161  }
162 
163  const auto& variables() const {
164  return mSymbolBack;
165  }
166 
167  auto construct_symbol_back(std::vector<Variable> vars, bool lex_order = false) const {
168  if (!lex_order) {
169  std::sort(vars.begin(), vars.end());
170  }
171  return vars;
172  }
173 
174  auto construct_ring(const std::vector<Variable>& vars, bool lex_order = false) const {
175  std::vector<CoCoA::symbol> indets;
176  for (auto s: vars) {
177  indets.emplace_back(s.safe_name());
178  }
179  if (lex_order) {
180  return CoCoA::NewPolyRing(mQ, indets, CoCoA::lex);
181  } else {
182  return CoCoA::NewPolyRing(mQ, indets);
183  }
184  }
185 
186 public:
187  explicit CoCoAAdaptor(const std::vector<Variable>& vars, bool lex_order = false):
188  mSymbolBack(construct_symbol_back(vars)), mRing(construct_ring(mSymbolBack, lex_order))
189  {
190  auto indets = CoCoA::indets(mRing);
191  for (std::size_t i = 0; i < mSymbolBack.size(); ++i) {
192  mSymbolThere.emplace(mSymbolBack[i], indets[i]);
193  }
194  }
195  CoCoAAdaptor(const std::vector<Poly>& polys):
196  CoCoAAdaptor(variables(polys).as_vector())
197  {}
198  CoCoAAdaptor(const std::initializer_list<Poly>& polys):
199  CoCoAAdaptor(std::vector<Poly>(polys))
200  {}
201 
202  void resetVariableOrdering(const std::vector<Variable>& ordering) {
203  assert(ordering.size() == mSymbolBack.size());
204  assert(ordering.size() == mSymbolThere.size());
205  mSymbolBack = ordering;
206  std::sort(mSymbolBack.begin(), mSymbolBack.end());
207 
208  auto indets = CoCoA::indets(mRing);
209  for (std::size_t i = 0; i < mSymbolBack.size(); ++i) {
210  mSymbolThere[mSymbolBack[i]] = indets[i];
211  }
212  }
213 
214  Poly gcd(const Poly& p1, const Poly& p2) const {
215  CARL_TIME_START(start);
216  auto res = convert(cocoawrapper::gcd(convert(p1), convert(p2)));
217  CARL_TIME_FINISH(cocoa::statistics().gcd, start);
218  return res;
219  }
220 
221  Poly makeCoprimeWith(const Poly& p1, const Poly& p2) const {
222  CoCoA::RingElem res = convert(p1);
223  return convert(res / cocoawrapper::gcd(res, convert(p2)));
224  }
225 
226  /**
227  * Break down a polynomial into its irreducible factors together with
228  * their exponents/multiplicities.
229  * E.g. "x^3 + 4 x^2 + 5 x + 2" factorizes into "(x+1)^2 * (x+2)^1"
230  * where "(x+1)", "(x+2)" are the irreducible factors and "2" and "1" are
231  * their exponents.
232  *
233  * @param includeConstants One of those factors is a constant-polynomial
234  * (degree 0), which is included by default but can be left out by setting
235  * the flag 'includeConstantFlag' to false, e.g., for root computations.
236  *
237  * @return A map whose keys are the irreducible factors and whose values are
238  * the exponents.
239  */
240  Factors<Poly> factorize(const Poly& p, bool includeConstant = true) const {
241  CARL_TIME_START(start);
242  auto finfo = cocoawrapper::factor(convert(p));
243  Factors<Poly> res;
244  if (includeConstant && !CoCoA::IsOne(finfo.myRemainingFactor())) {
245  res.emplace(convert(finfo.myRemainingFactor()), 1);
246  }
247  for (std::size_t i = 0; i < finfo.myFactors().size(); ++i) {
248  res.emplace(convert(finfo.myFactors()[i]), finfo.myMultiplicities()[i]);
249  }
250  CARL_TIME_FINISH(cocoa::statistics().factorize, start);
251  return res;
252  }
253 
254  /**
255  * Break down a polynomial into its unique, irreducible factors
256  * without their exponents/multiplicities.
257  * E.g. "3*x^3 + 12*x^2 + 15*x + 6" has the unique, non-constant, irreducible
258  * factors "(x+1)", "(x+2)", and a constant factor "3" that is included if includeConstant is true.
259  */
260  std::vector<Poly> irreducible_factors(const Poly& p, bool includeConstant = true) const {
261  std::vector<Poly> res;
262  for (auto& f: factorize(p, includeConstant)) {
263  res.emplace_back(std::move(f.first));
264  }
265  return res;
266  }
267 
268  Poly squareFreePart(const Poly& p) const {
269  auto finfo = cocoawrapper::SqFreeFactor(convert(p));
270  Poly res(1);
271  for (const auto& f: finfo.myFactors()) {
272  res *= convert(f);
273  }
274  return res;
275  }
276 
277  auto GBasis(const std::vector<Poly>& p) const {
278  CARL_TIME_START(start);
279  auto res = convert(cocoawrapper::ReducedGBasis(convert(p)));
280  CARL_TIME_FINISH(cocoa::statistics().gbasis, start);
281  return res;
282  }
283 };
284 
285 } // namespace carl
286 
287 #endif
#define CARL_TIME_FINISH(timer, start)
#define CARL_TIME_START(variable)
carl is the main namespace for the library.
MultivariatePolynomial< C, O, P > squareFreePart(const MultivariatePolynomial< C, O, P > &polynomial)
Monomial::Arg createMonomial(T &&... t)
Definition: MonomialPool.h:168
auto irreducible_factors(const ContextPolynomial< Coeff, Ordering, Policies > &p, bool constants=true)
Definition: Functions.h:8
cln::cl_I gcd(const cln::cl_I &a, const cln::cl_I &b)
Calculate the greatest common divisor of two integers.
Definition: operations.h:310
BasicConstraint< ToPoly > convert(const typename ToPoly::ContextType &context, const BasicConstraint< FromPoly > &c)
Definition: Conversion.h:9
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
TermType
Definition: term.h:7
std::vector< std::pair< Variable, std::size_t > > Content
Definition: Monomial.h:63