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