carl  24.04
Computer ARithmetic Library
EZGCD.h
Go to the documentation of this file.
1 /**
2  * @file EZGCD.h
3  * @ingroup gcd
4  * @ingroup multirp
5  * @author Sebastian Junges
6  */
7 
8 #pragma once
9 #include "../MultivariatePolynomial.h"
10 #include "../../numbers/PrimeFactory.h"
11 #include "GCD.h"
12 
13 namespace carl
14 {
15 /**
16  * Extended Zassenhaus algorithm for multivariate GCD calculation.
17  * @ingroup gcd
18  * @ingroup multirp
19  */
20 template<typename Coeff, typename Ordering= GrLexOrdering, typename Policies = StdMultivariatePolynomialPolicies<>>
21 class EZGCD
22 {
23 
25  typedef GCDResult<Coeff,Ordering,Policies> Result;
26  typedef typename Polynomial::TermType Term;
30 
31  const Polynomial& mp1;
32  const Polynomial& mp2;
34 
35 
36  public:
38  : mp1(p1), mp2(p2)
39  {
40 
41  }
42 
43  /**
44  *
45  * @param approx
46  * @return
47  */
48  Result calculate(bool approx=true)
49  {
50  assert(approx);
51 
52  // We start with some trivial cases.
53  if(mp1 == (Coeff)1 || mp2 == (Coeff)1) return {Polynomial((Coeff)1), Polynomial((Coeff)1), Polynomial((Coeff)1)};
54  if(mp1.nr_terms() == 1 && mp2.nr_terms() == 1)
55  {
56  //return Polynomial(Term::gcd(*mp1.lterm(), *mp2.lterm()));
57  }
58 
59  // And we do some simplifications for the input.
60  // In order to do so, we gather some information about the polynomials, as we most certainly need them later on.
61 
62  // We check for mutual trivial factorizations.
63 
64  // And we check for linearly appearing variables. Notice that ay + b is irreducible and thus,
65  // gcd(p, ay + b) is either ay + b or 1.
66 
67  // Here, we follow notation from @cite GCL92. We also add the notation from MY73.
68  Variable x = getMainVar(mp1, mp2);
69  UnivReprPol A = mp1.toUnivariatePolynomial(x);
70  UnivReprPol B = mp2.toUnivariatePolynomial(x);
71  Polynomial a;// = A.cont(); // In MY73, fbar
72  Polynomial b;// = B.cont(); // In MY73, gbar.
73  A /= a; // In MY73, F
74  B /= b; // IN MY73, G.
75  Polynomial g = gcd(a,b); // In MY72, dbar
76  a = a.divideBy(g).quotient;
77  b = b.divideBy(g).quotient;
78 
79  Integer p = getPrime(A,B);
80  std::map<Variable, Integer> eval_b = findEval(A,B,p); // bold b in @cite GCL92.
81  UnivPol A_I = A.evaluateCoefficient(eval_b).mod(p); // F_b
82  UnivPol B_I = B.evaluateCoefficient(eval_b).mod(p); // G_b
83  UnivPol C_I = UnivPol::gcd(A_I, B_I); // In MY73, D_b
84  unsigned d = C_I.degree(); // In MY72, delta.
85  if(d == 0)
86  {
87  // In MY73 step A3.
88  return {Polynomial(a * A), Polynomial(b * B), g};
89  }
90  while(true)
91  {
92  Integer p_prime = getPrime(A,B);
93  std::map<Variable, Integer> eval_c = findEval(A,B,p_prime); // bold c in book.
94  UnivPol A_I_prime = A.evaluateCoefficient(eval_c).mod(p_prime);
95  UnivPol B_I_prime = B.evaluateCoefficient(eval_c).mod(p_prime);
96  UnivPol C_I_prime = UnivPol::gcd(A_I, B_I);
97  unsigned d_I_prime = C_I_prime.degree();
98  if(d_I_prime < d)
99  {
100  // Previous evaluation was bad.
101  A_I = A_I_prime;
102  B_I = B_I_prime;
103  C_I = C_I_prime;
104  d = d_I_prime;
105  eval_b = eval_c;
106  continue;
107  }
108  else if (d < d_I_prime)
109  {
110  // This evaluation was bad.
111  continue;
112  }
113  assert(d == d_I_prime);
114 
115  // Test for special cases.
116  if(d == 0)
117  {
118  return {Polynomial(a * A), Polynomial(b * B), g};
119  }
120  if(d == B.degree())
121  {
122  if(A.divides(B))
123  {
124  return {Polynomial(a*(A.divideBy(B).quotient)), b, Polynomial(B*g)};
125  }
126  else
127  {
128  d--;
129  continue;
130  }
131  }
132  // Check for relatively prime cofactors
133  // In MY73, step A6.
134  UnivReprPol U_I(x);
135  UnivPol H_I(x);
136  Polynomial c;
137  if(UnivPol::gcd(B_I, C_I).is_one())
138  {
139  U_I = B; // B = G.
140  H_I = B_I.divideBy(C_I).quotient; // B_o[hat] = G_b / D_b
141  c = b; // Could not find in MY73
142  }
143  else if(UnivPol::gcd(A_I, C_I).is_one())
144  {
145  U_I = A; // B = F.
146  H_I = A_I.divideBy(C_I).quotient; //B_o[hat] = F_b / D_b
147  c = a; // Could not find in MY73
148  }
149  else
150  {
151  // Special gcd.
153  }
154 
155  // Lifting step.
156  //
157  U_I = c*U_I;
158  Coeff c_I = mod(c.evaluate(eval_b),p);
159  C_I = c_I * C_I;
160  //MultivariateH
162  std::vector<Polynomial> CE; //= EZ_LIFT(U_I, C_I, H_i, b, c_I) // EZ_LIFT(U_I, C_I, H_i, b, p, c)
163  assert(CE.size() == 2);
164  if(U_I == CE.front()*CE.back())
165  {
166  continue;
167  }
168  Polynomial C;// = CE.front().primitivePart();
169  if(C.divides(mp2) && C.divides(mp1))
170  {
171  return {a*mp1/C, b*mp2/C, g*C};
172  }
173  else
174  {
175  continue;
176  }
177  }
178  }
179 
180  private:
181  /**
182  * Given the two polynomials, find a suitable main variable for gcd.
183  * @param p1
184  * @param p2
185  * @return NoVariable if intersection is empty, otherwise some variable v which is in p1 and p2.
186  */
187  Variable getMainVar(const Polynomial p1, const Polynomial p2) const
188  {
189  // TODO find good heuristic.
190  std::vector<Variable> common;
191  auto v1 = carl::variables(p1).as_vector();
192  auto v2 = carl::variables(p2).as_vector();
193 
194  std::set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),
195  std::inserter(common,common.begin()));
196  if(common.empty())
197  {
198  return Variable::NO_VARIABLE;
199  }
200  else
201  {
202  return *common.begin();
203  }
204 
205  }
206 
208  {
209  Integer p;
210  do
211  {
213  } while( carl::is_zero(!A.lcoeff().mod(p)) || carl::is_zero(!A.lcoeff().mod(p)));
214  return p;
215 
216  }
217 
218  /**
219  * Find a valid evaluation point b = (b_1, ... , b_k)
220  * with 0 <= b_i < p and b_i = 0 for as many i as possible.
221  * @param A Polynomial in Z[x, y_1,...,y_k]
222  * @param B Polynomial in Z[x, y_1,...,y_k]
223  * @param p Prime number
224  * @return the evaluation point.
225  */
226  std::map<Variable, Integer> findEval( const UnivReprPol& A, const UnivReprPol& B, Integer p ) const
227  {
228  std::map<Variable, Integer> result;
229 
230  //assert(A.evaluateCoefficient(result).;
231  return result;
232  }
233 
234 
235 };
236 
237 }
#define CARL_LOG_NOTIMPLEMENTED()
Definition: carl-logging.h:48
carl is the main namespace for the library.
cln::cl_I mod(const cln::cl_I &a, const cln::cl_I &b)
Calculate the remainder of the integer division.
Definition: operations.h:445
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
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
typename UnderlyingNumberType< P >::type Coeff
Interval< Number > set_intersection(const Interval< Number > &lhs, const Interval< Number > &rhs)
Intersects two intervals in a set-theoretic manner.
Definition: SetTheory.h:99
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
bool is_one(const Interval< Number > &i)
Check if this interval is a point-interval containing 1.
Definition: Interval.h:1462
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
static const Variable NO_VARIABLE
Instance of an invalid variable.
Definition: Variable.h:203
const T & next_prime()
Computed the next prime and returns it.
Definition: PrimeFactory.h:74
This class represents a univariate polynomial with coefficients of an arbitrary type.
UnivariatePolynomial< Coefficient > evaluateCoefficient(const std::map< Variable, SubstitutionType > &) const
uint degree() const
Get the maximal exponent of the main variable.
The general-purpose multivariate polynomial class.
bool divides(const MultivariatePolynomial &b) const
std::size_t nr_terms() const
Calculate the number of terms.
Extended Zassenhaus algorithm for multivariate GCD calculation.
Definition: EZGCD.h:22
const Polynomial & mp2
Definition: EZGCD.h:32
IntegralType< Coeff >::type Integer
Definition: EZGCD.h:27
UnivariatePolynomial< Coeff > UnivPol
Definition: EZGCD.h:29
Polynomial::TermType Term
Definition: EZGCD.h:26
Result calculate(bool approx=true)
Definition: EZGCD.h:48
UnivariatePolynomial< MultivariatePolynomial< Coeff, Ordering, Policies > > UnivReprPol
Definition: EZGCD.h:28
std::map< Variable, Integer > findEval(const UnivReprPol &A, const UnivReprPol &B, Integer p) const
Find a valid evaluation point b = (b_1, ...
Definition: EZGCD.h:226
MultivariatePolynomial< Coeff, Ordering, Policies > Polynomial
Definition: EZGCD.h:24
const Polynomial & mp1
Definition: EZGCD.h:31
GCDResult< Coeff, Ordering, Policies > Result
Definition: EZGCD.h:25
EZGCD(const MultivariatePolynomial< Coeff, Ordering, Policies > &p1, const MultivariatePolynomial< Coeff, Ordering, Policies > &p2)
Definition: EZGCD.h:37
PrimeFactory< Integer > mPrimeFactory
Definition: EZGCD.h:33
Variable getMainVar(const Polynomial p1, const Polynomial p2) const
Given the two polynomials, find a suitable main variable for gcd.
Definition: EZGCD.h:187
Integer getPrime(const UnivReprPol &A, const UnivReprPol &B)
Definition: EZGCD.h:207