2  * @file DiophantineEquation.tpp
 
    3  * @author Tobias Winkler
 
    9 #include "DiophantineEquation.h"
 
   14 std::vector<T> solveDiophantine(MultivariatePolynomial<T>& p) {
 
   15     static_assert(carl::is_integer_type<T>::value, "Diophantine equations are build from integral coefficients only!");
 
   17         res = std::vector<T>();
 
   19         // use an algorithm for linear equations only
 
   21             res = solveLinearDiophantine(p);  
 
   24             CARL_LOG_NOTIMPLEMENTED();
 
   30 // Finds a single solution of a linear diophantine Equation
 
   32 std::vector<T> solveLinearDiophantine(MultivariatePolynomial<T>& equation) {
 
   33     assert(equation.is_linear());
 
   34     //assert(!equation.is_constant());
 
   35     //assert(equation.hatConstantTerm()); // change this later
 
   39     // if there is no constant part return the trivial solution
 
   40     if(!equation.has_constant_term()){
 
   41         res = std::vector<T>(carl::variables(equation).size(), 0);
 
   45     T const_part = equation.constant_part();
 
   47     // initialize coefficient vector
 
   48     std::vector<carl::Term<T>> terms = equation.terms();
 
   49     std::vector<T> coeffs = std::vector<T>();
 
   50     for(std::size_t i = 1; i < terms.size(); i++ ) { // terms[0] is the constant part
 
   51         coeffs.push_back(terms[i].coeff());
 
   55     std::vector<T> fromExtendedGcd = std::vector<T>(1, 1);
 
   56     T currGcd = coeffs[0];
 
   58     if(carl::mod(const_part, coeffs[0]) == 0) {
 
   59         res = std::vector<T>(coeffs.size(), 0);
 
   60         res[0] = -carl::div(const_part, coeffs[0]);
 
   63     for(std::size_t i = 1; i < coeffs.size(); i++) {
 
   66         currGcd = extended_gcd_integer(currGcd, coeffs[i], s, t);
 
   67         for(auto& r : fromExtendedGcd) {
 
   70         fromExtendedGcd.push_back(t);
 
   71         if(carl::mod(const_part, currGcd) == 0) {
 
   72             T factor = -carl::div(const_part, currGcd);
 
   73             for(auto& r : fromExtendedGcd) {
 
   76             std::size_t diff = coeffs.size() - fromExtendedGcd.size();
 
   77             for(std::size_t j = 0; j < diff; j++) {
 
   78                 fromExtendedGcd.push_back(0);
 
   80             assert(fromExtendedGcd.size() == coeffs.size());
 
   81             return fromExtendedGcd;
 
   85     CARL_LOG_NOTIMPLEMENTED(); 
 
   86     return std::vector<T>(coeffs.size(), 0);
 
   90 // implementation of extended euklid for integers
 
   92 T extended_gcd_integer(T a, T b, T& s, T& t) {
 
   93     static_assert(carl::is_integer_type<T>::value, "extended gcd algorithmn is for integral types only!");
 
   96     if(a == 0 && b == 0) {
 
  112         quotient = carl::quotient(old_r, r);
 
  115         r = old_r - quotient * r;
 
  119         s = old_s - quotient * s;
 
  123         t = old_t - quotient * t;
 
  126     // normalize so that the gcd is always positive