Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Add, Mul, solve, ceiling, floor, sqrt, sympify, Subs, ilcm, Matrix, factor_list, perfect_power, isprime, nextprime, integer_nthroot)
'diop_quadratic', 'diop_DN', 'cornacchia', 'diop_bf_DN', 'transformation_to_DN', 'find_DN', 'diop_ternary_quadratic', 'square_factor', 'descent', 'diop_general_pythagorean', 'diop_general_sum_of_squares', 'partition', 'sum_of_three_squares', 'sum_of_four_squares']
""" Simplify the solution procedure of diophantine equation ``eq`` by converting it into a product of terms which should equal zero.
For example, when solving, `x^2 - y^2 = 0` this is treated as `(x + y)(x - y) = 0` and `x+y = 0` and `x-y = 0` are solved independently and combined. Each term is solved by calling ``diop_solve()``.
Output of ``diophantine()`` is a set of tuples. Each tuple represents a solution of the input equation. In a tuple, solution for each variable is listed according to the alphabetic order of input variables. i.e. if we have an equation with two variables `a` and `b`, first element of the tuple will give the solution for `a` and the second element will give the solution for `b`.
Usage =====
``diophantine(eq, t)``: Solve the diophantine equation ``eq``. ``t`` is the parameter to be used by ``diop_solve()``.
Details =======
``eq`` should be an expression which is assumed to be zero. ``t`` is the parameter to be used in the solution.
Examples ========
>>> from sympy.solvers.diophantine import diophantine >>> from sympy.abc import x, y, z >>> diophantine(x**2 - y**2) set([(-t, -t), (t, -t)])
#>>> diophantine(x*(2*x + 3*y - z)) #set([(0, n1, n2), (3*t - z, -2*t + z, z)]) #>>> diophantine(x**2 + 3*x*y + 4*x) #set([(0, n1), (3*t - 4, -t)])
See Also ========
diop_solve() """ eq = eq.lhs - eq.rhs
""" This is used to construct the full solution from the solutions of sub equations.
For example when solving the equation `(x - y)(x^2 + y^2 - z^2) = 0`, solutions for each of the equations `x-y = 0` and `x^2 + y^2 - z^2` are found independently. Solutions for `x - y = 0` are `(x, y) = (t, t)`. But we should introduce a value for z when we output the solution for the original equation. This function converts `(t, t)` into `(t, t, n_{1})` where `n_{1}` is an integer parameter. """
else:
""" Solves the diophantine equation ``eq``.
Similar to ``diophantine()`` but doesn't try to factor ``eq`` as latter does. Uses ``classify_diop()`` to determine the type of the eqaution and calls the appropriate solver function.
Usage =====
``diop_solve(eq, t)``: Solve diophantine equation, ``eq`` using ``t`` as a parameter if needed.
Details =======
``eq`` should be an expression which is assumed to be zero. ``t`` is a parameter to be used in the solution.
Examples ========
>>> from sympy.solvers.diophantine import diop_solve >>> from sympy.abc import x, y, z, w >>> diop_solve(2*x + 3*y - 5) (3*t - 5, -2*t + 5) >>> diop_solve(4*x + 3*y -4*z + 5) (3*t + 4*z - 5, -4*t - 4*z + 5, z) >>> diop_solve(x + 3*y - 4*z + w -6) (t, -t - 3*y + 4*z + 6, y, z) >>> diop_solve(x**2 + y**2 - 5) set([(-2, -1), (-2, 1), (2, -1), (2, 1)])
See Also ========
diophantine() """
""" Helper routine used by diop_solve() to find the type of the ``eq`` etc.
Returns a tuple containing the type of the diophantine equation along with the variables(free symbols) and their coefficients. Variables are returned as a list and coefficients are returned as a dict with the key being the respective term and the constant term is keyed to Integer(1). Type is an element in the set {"linear", "binary_quadratic", "general_pythagorean", "homogeneous_ternary_quadratic", "univariate", "general_sum_of_squares"}
Usage =====
``classify_diop(eq)``: Return variables, coefficients and type of the ``eq``.
Details =======
``eq`` should be an expression which is assumed to be zero.
Examples ========
>>> from sympy.solvers.diophantine import classify_diop >>> from sympy.abc import x, y, z, w, t >>> classify_diop(4*x + 6*y - 4) ([x, y], {1: -4, x: 4, y: 6}, 'linear') >>> classify_diop(x + 3*y -4*z + 5) ([x, y, z], {1: 5, x: 1, y: 3, z: -4}, 'linear') >>> classify_diop(x**2 + y**2 - x*y + x + 5) ([x, y], {1: 5, x: 1, x**2: 1, y: 0, y**2: 1, x*y: -1}, 'binary_quadratic') """
raise TypeError("Coefficients should be Integers")
else:
diop_type = "inhomogeneous_ternary_quadratic" break else:
diop_type = "inhomogeneous_general_quadratic" break
else: else:
non_square_degree_2_terms = True break break
diop_type = "inhomogeneous_general_quadratic"
break else:
diop_type = "homogeneous_general_quadratic"
else:
break else:
elif Poly(eq).total_degree() == 3 and len(var) == 2:
x, y = var[:2] diop_type = "cubic_thue"
for term in [x**3, x**2*y, x*y**2, y**3, Integer(1)]: if term not in coeff.keys(): coeff[term] == Integer(0)
else: raise NotImplementedError("Still not implemented")
""" Solves linear diophantine equations.
A linear diophantine equation is an equation of the form `a_{1}x_{1} + a_{2}x_{2} + .. + a_{n}x_{n} = 0` where `a_{1}, a_{2}, ..a_{n}` are integer constants and `x_{1}, x_{2}, ..x_{n}` are integer variables.
Usage =====
``diop_linear(eq)``: Returns a tuple containing solutions to the diophantine equation ``eq``. Values in the tuple is arranged in the same order as the sorted variables.
Details =======
``eq`` is a linear diophantine equation which is assumed to be zero. ``param`` is the parameter to be used in the solution.
Examples ========
>>> from sympy.solvers.diophantine import diop_linear >>> from sympy.abc import x, y, z, t >>> from sympy import Integer >>> diop_linear(2*x - 3*y - 5) #solves equation 2*x - 3*y -5 = 0 (-3*t - 5, -2*t - 5)
Here x = -3*t - 5 and y = -2*t - 5
>>> diop_linear(2*x - 3*y - 4*z -3) (-3*t - 4*z - 3, -2*t - 4*z - 3, z)
See Also ========
diop_quadratic(), diop_ternary_quadratic(), diop_general_pythagorean(), diop_general_sum_of_squares() """ var, coeff, diop_type = classify_diop(eq)
if diop_type == "linear": return _diop_linear(var, coeff, param)
else:
else:
""" Return the base solution for a linear diophantine equation with two variables.
Used by ``diop_linear()`` to find the base solution of a linear Diophantine equation. If ``t`` is given then the parametrized solution is returned.
Usage =====
``base_solution_linear(c, a, b, t)``: ``a``, ``b``, ``c`` are coefficients in `ax + by = c` and ``t`` is the parameter to be used in the solution.
Examples ========
>>> from sympy.solvers.diophantine import base_solution_linear >>> from sympy.abc import t >>> base_solution_linear(5, 2, 3) # equation 2*x + 3*y = 5 (-5, 5) >>> base_solution_linear(0, 5, 7) # equation 5*x + 7*y = 0 (0, 0) >>> base_solution_linear(5, 2, 3, t) # equation 2*x + 3*y = 5 (3*t - 5, -2*t + 5) >>> base_solution_linear(0, 5, 7, t) # equation 5*x + 7*y = 0 (7*t, -5*t) """
else: return (S.Zero, S.Zero) else:
else: else:
""" For given ``a``, ``b`` returns a tuple containing integers `x`, `y` and `d` such that `ax + by = d`. Here `d = gcd(a, b)`.
Usage =====
``extended_euclid(a, b)``: returns `x`, `y` and `\gcd(a, b)`.
Details =======
``a`` Any instance of Integer. ``b`` Any instance of Integer.
Examples ========
>>> from sympy.solvers.diophantine import extended_euclid >>> extended_euclid(4, 6) (-1, 1, 2) >>> extended_euclid(3, 5) (2, -1, 1) """
""" Returns `True` if ``a`` is divisible by ``b`` and `False` otherwise. """
""" Solves quadratic diophantine equations.
i.e. equations of the form `Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0`. Returns a set containing the tuples `(x, y)` which contains the solutions. If there are no solutions then `(None, None)` is returned.
Usage =====
``diop_quadratic(eq, param)``: ``eq`` is a quadratic binary diophantine equation. ``param`` is used to indicate the parameter to be used in the solution.
Details =======
``eq`` should be an expression which is assumed to be zero. ``param`` is a parameter to be used in the solution.
Examples ========
>>> from sympy.abc import x, y, t >>> from sympy.solvers.diophantine import diop_quadratic >>> diop_quadratic(x**2 + y**2 + 2*x + 2*y + 2, t) set([(-1, -1)])
References ==========
.. [1] Methods to solve Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0,[online], Available: http://www.alpertron.com.ar/METHODS.HTM .. [2] Solving the equation ax^2+ bxy + cy^2 + dx + ey + f= 0, [online], Available: http://www.jpr2718.org/ax2p.pdf
See Also ========
diop_linear(), diop_ternary_quadratic(), diop_general_sum_of_squares(), diop_general_pythagorean() """ var, coeff, diop_type = classify_diop(eq)
if diop_type == "binary_quadratic": return _diop_quadratic(var, coeff, param)
coeff[term] = Integer(0)
# (1) Linear case: A = B = C = 0 ==> considered under linear diophantine equations
# (2) Simple-Hyperbolic case:A = C = 0, B != 0 # In this case equation can be converted to (Bx + E)(By + D) = DE - BF # We consider two cases; DE - BF = 0 and DE - BF != 0 # More details, http://www.alpertron.com.ar/METHODS.HTM#SHyperb
else:
# (3) Parabolic case: B**2 - 4*A*C = 0 # There are two subcases to be considered in this case. # sqrt(c)D - sqrt(a)E = 0 and sqrt(c)D - sqrt(a)E != 0 # More Details, http://www.alpertron.com.ar/METHODS.HTM#Parabol
else:
- (e*sqrt(c)*g*u**2 + E*u + e*sqrt(c)*F) // (e*sqrt(c)*D - sqrt(a)*E)
+ (sqrt(a)*g*u**2 + D*u + sqrt(a)*F) // (e*sqrt(c)*D - sqrt(a)*E)
# (4) Method used when B**2 - 4*A*C is a square, is descibed in p. 6 of the below paper # by John P. Robertson. # http://www.jpr2718.org/ax2p.pdf
else:
# (5) B**2 - 4*A*C > 0 and B**2 - 4*A*C not a square or B**2 - 4*A*C < 0
else:
else: # In this case equation can be transformed into a Pell equation #n = symbols("n", integer=True)
and isinstance(P[3], Integer) and isinstance(Q[0], Integer) and isinstance(Q[1], Integer)):
else: ilcm(S(P[3]).q, ilcm(S(Q[0]).q, S(Q[1]).q)))))
(X - sqrt(D)*Y)*(T_k - sqrt(D)*U_k)**t)/ 2 (X - sqrt(D)*Y)*(T_k - sqrt(D)*U_k)**t)/ (2*sqrt(D))
""" Check whether `(u, v)` is solution to the quadratic binary diophantine equation with the variable list ``var`` and coefficient dictionary ``coeff``.
Not intended for use by normal users. """
""" Solves the equation `x^2 - Dy^2 = N`.
Mainly concerned in the case `D > 0, D` is not a perfect square, which is the same as generalized Pell equation. To solve the generalized Pell equation this function Uses LMM algorithm. Refer [1]_ for more details on the algorithm. Returns one solution for each class of the solutions. Other solutions of the class can be constructed according to the values of ``D`` and ``N``. Returns a list containing the solution tuples `(x, y)`.
Usage =====
``diop_DN(D, N, t)``: D and N are integers as in `x^2 - Dy^2 = N` and ``t`` is the parameter to be used in the solutions.
Details =======
``D`` and ``N`` correspond to D and N in the equation. ``t`` is the parameter to be used in the solutions.
Examples ========
>>> from sympy.solvers.diophantine import diop_DN >>> diop_DN(13, -4) # Solves equation x**2 - 13*y**2 = -4 [(3, 1), (393, 109), (36, 10)]
The output can be interpreted as follows: There are three fundamental solutions to the equation `x^2 - 13y^2 = -4` given by (3, 1), (393, 109) and (36, 10). Each tuple is in the form (x, y), i. e solution (3, 1) means that `x = 3` and `y = 1`.
>>> diop_DN(986, 1) # Solves equation x**2 - 986*y**2 = 1 [(49299, 1570)]
See Also ========
find_DN(), diop_bf_DN()
References ==========
.. [1] Solving the generalized Pell equation x**2 - D*y**2 = N, John P. Robertson, July 31, 2004, Pages 16 - 17. [online], Available: http://www.jpr2718.org/pell.pdf """
return [(S.Zero, t)]
else: # D > 0
else:
else:
else:
else: else:
else:
""" Solves `ax^2 + by^2 = m` where `\gcd(a, b) = 1 = gcd(a, m)` and `a, b > 0`.
Uses the algorithm due to Cornacchia. The method only finds primitive solutions, i.e. ones with `\gcd(x, y) = 1`. So this method can't be used to find the solutions of `x^2 + y^2 = 20` since the only solution to former is `(x,y) = (4, 2)` and it is not primitive. When ` a = b = 1`, only the solutions with `x \geq y` are found. For more details, see the References.
Examples ========
>>> from sympy.solvers.diophantine import cornacchia >>> cornacchia(2, 3, 35) # equation 2x**2 + 3y**2 = 35 set([(2, 3), (4, 1)]) >>> cornacchia(1, 1, 25) # equation x**2 + y**2 = 25 set([(4, 3)])
References ===========
.. [1] A. Nitaj, "L'algorithme de Cornacchia" .. [2] Solving the diophantine equation ax**2 + by**2 = m by Cornacchia's method, [online], Available: http://www.numbertheory.org/php/cornacchia.html """
return None
v = [v]
""" Returns useful information needed to solve the Pell equation.
There are six sequences of integers defined related to the continued fraction representation of `\\frac{P + \sqrt{D}}{Q}`, namely {`P_{i}`}, {`Q_{i}`}, {`a_{i}`},{`A_{i}`}, {`B_{i}`}, {`G_{i}`}. ``PQa()`` Returns these values as a 6-tuple in the same order as mentioned above. Refer [1]_ for more detailed information.
Usage =====
``PQa(P_0, Q_0, D)``: ``P_0``, ``Q_0`` and ``D`` are integers corresponding to `P_{0}`, `Q_{0}` and `D` in the continued fraction `\\frac{P_{0} + \sqrt{D}}{Q_{0}}`. Also it's assumed that `P_{0}^2 == D mod(|Q_{0}|)` and `D` is square free.
Examples ========
>>> from sympy.solvers.diophantine import PQa >>> pqa = PQa(13, 4, 5) # (13 + sqrt(5))/4 >>> next(pqa) # (P_0, Q_0, a_0, A_0, B_0, G_0) (13, 4, 3, 3, 1, -1) >>> next(pqa) # (P_1, Q_1, a_1, A_1, B_1, G_1) (-1, 1, 1, 4, 1, 3)
References ==========
.. [1] Solving the generalized Pell equation x^2 - Dy^2 = N, John P. Robertson, July 31, 2004, Pages 4 - 8. http://www.jpr2718.org/pell.pdf """
""" Uses brute force to solve the equation, `x^2 - Dy^2 = N`.
Mainly concerned with the generalized Pell equation which is the case when `D > 0, D` is not a perfect square. For more information on the case refer [1]_. Let `(t, u)` be the minimal positive solution of the equation `x^2 - Dy^2 = 1`. Then this method requires `\sqrt{\\frac{\mid N \mid (t \pm 1)}{2D}}` to be small.
Usage =====
``diop_bf_DN(D, N, t)``: ``D`` and ``N`` are coefficients in `x^2 - Dy^2 = N` and ``t`` is the parameter to be used in the solutions.
Details =======
``D`` and ``N`` correspond to D and N in the equation. ``t`` is the parameter to be used in the solutions.
Examples ========
>>> from sympy.solvers.diophantine import diop_bf_DN >>> diop_bf_DN(13, -4) [(3, 1), (-3, 1), (36, 10)] >>> diop_bf_DN(986, 1) [(49299, 1570)]
See Also ========
diop_DN()
References ==========
.. [1] Solving the generalized Pell equation x**2 - D*y**2 = N, John P. Robertson, July 31, 2004, Page 15. http://www.jpr2718.org/pell.pdf """
else: if D < 0: return [(S.Zero, S.Zero)] elif D == 0: return [(S.Zero, t)] else: if isinstance(sqrt(D), Integer): return [(sqrt(D)*t, t), (-sqrt(D)*t, t)] else: return [(S.Zero, S.Zero)]
""" Returns True if two solutions `(u, v)` and `(r, s)` of `x^2 - Dy^2 = N` belongs to the same equivalence class and False otherwise.
Two solutions `(u, v)` and `(r, s)` to the above equation fall to the same equivalence class iff both `(ur - Dvs)` and `(us - vr)` are divisible by `N`. See reference [1]_. No test is performed to test whether `(u, v)` and `(r, s)` are actually solutions to the equation. User should take care of this.
Usage =====
``equivalent(u, v, r, s, D, N)``: `(u, v)` and `(r, s)` are two solutions of the equation `x^2 - Dy^2 = N` and all parameters involved are integers.
Examples ========
>>> from sympy.solvers.diophantine import equivalent >>> equivalent(18, 5, -18, -5, 13, -1) True >>> equivalent(3, 1, -18, 393, 109, -4) False
References ==========
.. [1] Solving the generalized Pell equation x**2 - D*y**2 = N, John P. Robertson, July 31, 2004, Page 12. http://www.jpr2718.org/pell.pdf
"""
""" Returns the (length of aperiodic part + length of periodic part) of continued fraction representation of `\\frac{P + \sqrt{D}}{Q}`.
It is important to remember that this does NOT return the length of the periodic part but the addition of the legths of the two parts as mentioned above.
Usage =====
``length(P, Q, D)``: ``P``, ``Q`` and ``D`` are integers corresponding to the continued fraction `\\frac{P + \sqrt{D}}{Q}`.
Details =======
``P``, ``D`` and ``Q`` corresponds to P, D and Q in the continued fraction, `\\frac{P + \sqrt{D}}{Q}`.
Examples ========
>>> from sympy.solvers.diophantine import length >>> length(-2 , 4, 5) # (-2 + sqrt(5))/4 3 >>> length(-5, 4, 17) # (-5 + sqrt(17))/4 4 """
return len(res)
""" This function transforms general quadratic, `ax^2 + bxy + cy^2 + dx + ey + f = 0` to more easy to deal with `X^2 - DY^2 = N` form.
This is used to solve the general quadratic equation by transforming it to the latter form. Refer [1]_ for more detailed information on the transformation. This function returns a tuple (A, B) where A is a 2 X 2 matrix and B is a 2 X 1 matrix such that,
Transpose([x y]) = A * Transpose([X Y]) + B
Usage =====
``transformation_to_DN(eq)``: where ``eq`` is the quadratic to be transformed.
Examples ========
>>> from sympy.abc import x, y >>> from sympy.solvers.diophantine import transformation_to_DN >>> from sympy.solvers.diophantine import classify_diop >>> A, B = transformation_to_DN(x**2 - 3*x*y - y**2 - 2*y + 1) >>> A Matrix([ [1/26, 3/26], [ 0, 1/13]]) >>> B Matrix([ [-6/13], [-4/13]])
A, B returned are such that Transpose((x y)) = A * Transpose((X Y)) + B. Substituting these values for `x` and `y` and a bit of simplifying work will give an equation of the form `x^2 - Dy^2 = N`.
>>> from sympy.abc import X, Y >>> from sympy import Matrix, simplify, Subs >>> u = (A*Matrix([X, Y]) + B)[0] # Transformation for x >>> u X/26 + 3*Y/26 - 6/13 >>> v = (A*Matrix([X, Y]) + B)[1] # Transformation for y >>> v Y/13 - 4/13
Next we will substitute these formulas for `x` and `y` and do ``simplify()``.
>>> eq = simplify(Subs(x**2 - 3*x*y - y**2 - 2*y + 1, (x, y), (u, v)).doit()) >>> eq X**2/676 - Y**2/52 + 17/13
By multiplying the denominator appropriately, we can get a Pell equation in the standard form.
>>> eq * 676 X**2 - 13*Y**2 + 884
If only the final equation is needed, ``find_DN()`` can be used.
See Also ========
find_DN()
References ==========
.. [1] Solving the equation ax^2 + bxy + cy^2 + dx + ey + f = 0, John P.Robertson, May 8, 2003, Page 7 - 11. http://www.jpr2718.org/ax2p.pdf """
# eq_1 = A*B*X**2 + B*(c*T - A*C**2)*Y**2 + d*T*X + (B*e*T - d*T*C)*Y + f*T*B
else:
# eq_2 = A*X**2 + c*T*Y**2 + e*T*Y + f*T - A*C**2
else:
# eq_3 = a*T*X**2 + A*Y**2 + f*T - A*C**2
else: # TODO: pre-simplification: Not necessary but may simplify # the equation.
""" This function returns a tuple, `(D, N)` of the simplified form, `x^2 - Dy^2 = N`, corresponding to the general quadratic, `ax^2 + bxy + cy^2 + dx + ey + f = 0`.
Solving the general quadratic is then equivalent to solving the equation `X^2 - DY^2 = N` and transforming the solutions by using the transformation matrices returned by ``transformation_to_DN()``.
Usage =====
``find_DN(eq)``: where ``eq`` is the quadratic to be transformed.
Examples ========
>>> from sympy.abc import x, y >>> from sympy.solvers.diophantine import find_DN >>> find_DN(x**2 - 3*x*y - y**2 - 2*y + 1) (13, -884)
Interpretation of the output is that we get `X^2 -13Y^2 = -884` after transforming `x^2 - 3xy - y^2 - 2y + 1` using the transformation returned by ``transformation_to_DN()``.
See Also ========
transformation_to_DN()
References ==========
.. [1] Solving the equation ax^2 + bxy + cy^2 + dx + ey + f = 0, John P.Robertson, May 8, 2003, Page 7 - 11. http://www.jpr2718.org/ax2p.pdf """
""" Check if there is a number modulo ``a`` such that ``x`` and ``y`` are both integers. If exist, then find a parametric representation for ``x`` and ``y``.
Here ``x`` and ``y`` are functions of ``t``. """
isinstance(z_y[p], Integer) and isinstance(z_y[q], Integer)):
if x_param[p] == 0: l1, junk = Poly(y).clear_denoms() else: l1 = 1
if y_param[p] == 0: l2, junk = Poly(x).clear_denoms() else: l2 = 1
return x*ilcm(l1, l2), y*ilcm(l1, l2)
else: return (None, None)
""" Solves the general quadratic ternary form, `ax^2 + by^2 + cz^2 + fxy + gyz + hxz = 0`.
Returns a tuple `(x, y, z)` which is a base solution for the above equation. If there are no solutions, `(None, None, None)` is returned.
Usage =====
``diop_ternary_quadratic(eq)``: Return a tuple containing a basic solution to ``eq``.
Details =======
``eq`` should be an homogeneous expression of degree two in three variables and it is assumed to be zero.
Examples ========
>>> from sympy.abc import x, y, z >>> from sympy.solvers.diophantine import diop_ternary_quadratic >>> diop_ternary_quadratic(x**2 + 3*y**2 - z**2) (1, 0, 1) >>> diop_ternary_quadratic(4*x**2 + 5*y**2 - z**2) (1, 0, 2) >>> diop_ternary_quadratic(45*x**2 - 7*y**2 - 8*x*y - z**2) (28, 45, 105) >>> diop_ternary_quadratic(x**2 - 49*y**2 - z**2 + 13*z*y -8*x*y) (9, 1, 5) """ var, coeff, diop_type = classify_diop(eq)
if diop_type == "homogeneous_ternary_quadratic": return _diop_ternary_quadratic(var, coeff)
# Equations of the form B*x*y + C*z*x + E*y*z = 0 and At least two of the # coefficients A, B, C are non-zero. # There are infinitely many solutions for the equation. # Ex: (0, 0, t), (0, t, 0), (t, 0, 0) # Equation can be re-written as y*(B*x + E*z) = -C*x*z and we can find rather # unobviuos solutions. Set y = -C and B*x + E*z = x*z. The latter can be solved by # using methods for binary quadratic diophantine equations. Let's select the # solution which minimizes |x| + |z|
else: var[0], var[1] = _var[1], _var[0] y_0, x_0, z_0 = _diop_ternary_quadratic(var, coeff)
# If the coefficient of x is zero change the variables
else: var[0], var[1] = _var[1], _var[0] y_0, x_0, z_0 = _diop_ternary_quadratic(var, coeff)
else: # Apply the transformation x --> X - (B*y + C*z)/(2*A)
# Equations of the form A*x**2 + E*yz = 0.
else: # Ax**2 + E*y*z + F*z**2 = 0
else: # A*x**2 + D*y**2 + E*y*z + F*z**2 = 0, C may be zero
else: # Ax**2 + D*y**2 + F*z**2 = 0, C may be zero
""" Returns the transformation Matrix from general ternary quadratic equation `eq` to normal form.
General form of the ternary quadratic equation is `ax^2 + by^2 cz^2 + dxy + eyz + fxz`. This function returns a 3X3 transformation Matrix which transforms the former equation to the form `ax^2 + by^2 + cz^2 = 0`. This is not used in solving ternary quadratics. Only implemented for the sake of completeness. """
# If the coefficient of x is zero change the variables
else:
else: # Apply the transformation x --> X - (B*Y + C*Z)/(2*A)
# Equations of the form A*x**2 + E*yz = 0. # Apply transformation y -> Y + Z ans z -> Y - Z
else: # Ax**2 + E*y*z + F*z**2 = 0 _var[0], _var[2] = var[2], var[0] T = _transformtion_to_normal(_var, coeff) T.row_swap(0, 2) T.col_swap(0, 2) return T
else: # A*x**2 + D*y**2 + E*y*z + F*z**2 = 0, F may be zero
else:
""" Simplify the solution `(x, y, z)`. """
""" Returns the parametrized general solution for the ternary quadratic equation ``eq`` which has the form `ax^2 + by^2 + cz^2 + fxy + gyz + hxz = 0`.
Examples ========
>>> from sympy.abc import x, y, z >>> from sympy.solvers.diophantine import parametrize_ternary_quadratic >>> parametrize_ternary_quadratic(x**2 + y**2 - z**2) (2*p*q, p**2 - q**2, p**2 + q**2)
Here `p` and `q` are two co-prime integers.
>>> parametrize_ternary_quadratic(3*x**2 + 2*y**2 - z**2 - 2*x*y + 5*y*z - 7*y*z) (2*p**2 - 2*p*q - q**2, 2*p**2 + 2*p*q - q**2, 2*p**2 - 2*p*q + 3*q**2) >>> parametrize_ternary_quadratic(124*x**2 - 30*y**2 - 7729*z**2) (-1410*p**2 - 363263*q**2, 2700*p**2 + 30916*p*q - 695610*q**2, -60*p**2 + 5400*p*q + 15458*q**2)
References ==========
.. [1] The algorithmic resolution of Diophantine equations, Nigel P. Smart, London Mathematical Society Student Texts 41, Cambridge University Press, Cambridge, 1998.
""" var, coeff, diop_type = classify_diop(eq)
if diop_type == "homogeneous_ternary_quadratic": x_0, y_0, z_0 = _diop_ternary_quadratic(var, coeff) return _parametrize_ternary_quadratic((x_0, y_0, z_0), var, coeff)
v[0], v[2] = v[2], v[0] z_p, y_p, x_p = _parametrize_ternary_quadratic((z_0, y_0, x_0), v, coeff) return x_p, y_p, z_p else:
""" Solves the quadratic ternary diophantine equation, `ax^2 + by^2 + cz^2 = 0`.
Here the coefficients `a`, `b`, and `c` should be non zero. Otherwise the equation will be a quadratic binary or univariate equation. If solvable, returns a tuple `(x, y, z)` that satisifes the given equation. If the equation does not have integer solutions, `(None, None, None)` is returned.
Usage =====
``diop_ternary_quadratic_normal(eq)``: where ``eq`` is an equation of the form `ax^2 + by^2 + cz^2 = 0`.
Examples ========
>>> from sympy.abc import x, y, z >>> from sympy.solvers.diophantine import diop_ternary_quadratic_normal >>> diop_ternary_quadratic_normal(x**2 + 3*y**2 - z**2) (1, 0, 1) >>> diop_ternary_quadratic_normal(4*x**2 + 5*y**2 - z**2) (1, 0, 2) >>> diop_ternary_quadratic_normal(34*x**2 - 3*y**2 - 301*z**2) (4, 9, 1) """ var, coeff, diop_type = classify_diop(eq)
if diop_type == "homogeneous_ternary_quadratic": return _diop_ternary_quadratic_normal(var, coeff)
raise ValueError("Try factoring out you equation or using diophantine()")
# If following two conditions are satisified then there are no solutions return (None, None, None)
sqrt_mod(-a_2*b_2, c_2) == None):
else: x_0 = x_0*(S(z_0)/c_2).q y_0 = y_0*(S(z_0)/c_2).q z_0 = (S(z_0)/c_2).p
# Holzer reduction else:
""" Returns an integer `c` s.t. `a = c^2k, \ c,k \in Z`. Here `k` is square free.
Examples ========
>>> from sympy.solvers.diophantine import square_factor >>> square_factor(24) 2 >>> square_factor(36) 6 >>> square_factor(1) 1 """
""" Transform `ax^2 + by^2 + cz^2 = 0` into an equivalent equation `a'x^2 + b'y^2 + c'z^2 = 0` where `a', b', c'` are pairwise relatively prime.
Returns a tuple containing `a', b', c'`. `\gcd(a, b, c)` should equal `1` for this to work. The solutions for `ax^2 + by^2 + cz^2 = 0` can be recovered from the solutions of `a'x^2 + b'y^2 + c'z^2 = 0`.
Examples ========
>>> from sympy.solvers.diophantine import pairwise_prime >>> pairwise_prime(6, 15, 10) (5, 2, 3)
See Also ========
make_prime(), reocnstruct() """
""" Transform the equation `ax^2 + by^2 + cz^2 = 0` to an equivalent equation `a'x^2 + b'y^2 + c'z^2 = 0` with `\gcd(a', b') = 1`.
Returns a tuple `(a', b', c')` which satisfies above conditions. Note that in the returned tuple `\gcd(a', c')` and `\gcd(b', c')` can take any value.
Examples ========
>>> from sympy.solvers.diophantine import make_prime >>> make_prime(4, 2, 7) (2, 1, 14)
See Also ========
pairwaise_prime(), reconstruct() """
""" Reconstruct the `z` value of an equivalent solution of `ax^2 + by^2 + cz^2` from the `z` value of a solution of a transformed version of the above equation. """
z = z*p**(e//2) else:
""" Uses Lagrange's method to find a non trivial solution to `w^2 = Ax^2 + By^2`.
Here, `A \\neq 0` and `B \\neq 0` and `A` and `B` are square free. Output a tuple `(w_0, x_0, y_0)` which is a solution to the above equation.
Examples ========
>>> from sympy.solvers.diophantine import ldescent >>> ldescent(1, 1) # w^2 = x^2 + y^2 (1, 1, 0) >>> ldescent(4, -7) # w^2 = 4x^2 - 7y^2 (2, -1, 0)
This means that `x = -1, y = 0` and `w = 2` is a solution to the equation `w^2 = 4x^2 - 7y^2`
>>> ldescent(5, -1) # w^2 = 5x^2 - y^2 (2, 1, -1)
References ==========
.. [1] The algorithmic resolution of Diophantine equations, Nigel P. Smart, London Mathematical Society Student Texts 41, Cambridge University Press, Cambridge, 1998. .. [2] Efficient Solution of Rational Conices, J. E. Cremona and D. Rusin, Mathematics of Computation, Volume 00, Number 0. """
else:
# In this module Descent will always be called with inputs which have solutions.
""" Lagrange's `descent()` with lattice-reduction to find solutions to `x^2 = Ay^2 + Bz^2`.
Here `A` and `B` should be square free and pairwise prime. Always should be called with suitable ``A`` and ``B`` so that the above equation has solutions.
This is more faster than the normal Lagrange's descent algorithm because the gaussian reduction is used.
Examples ========
>>> from sympy.solvers.diophantine import descent >>> descent(3, 1) # x**2 = 3*y**2 + z**2 (1, 0, 1)
`(x, y, z) = (1, 0, 1)` is a solution to the above equation.
>>> descent(41, -113) (-16, -3, 1)
References ==========
.. [1] Efficient Solution of Rational Conices, J. E. Cremona and D. Rusin, Mathematics of Computation, Volume 00, Number 0. """
return (None, None, None) x, z, y = descent(-1, A) return (A*y, z, x)
""" Returns a reduced solution `(x, z)` to the congruence `X^2 - aZ^2 \equiv 0 \ (mod \ b)` so that `x^2 + |a|z^2` is minimal.
Details =======
Here ``w`` is a solution of the congruence `x^2 \equiv a \ (mod \ b)`
References ==========
.. [1] Gaussian lattice Reduction [online]. Available: http://home.ie.cuhk.edu.hk/~wkshum/wordpress/?p=404 .. [2] Efficient Solution of Rational Conices, J. E. Cremona and D. Rusin, Mathematics of Computation, Volume 00, Number 0. """
u, v = v, u
else:
""" Returns a special dot product of the vectors `u = (u_{1}, u_{2})` and `v = (v_{1}, v_{2})` which is defined in order to reduce solution of the congruence equation `X^2 - aZ^2 \equiv 0 \ (mod \ b)`. """
""" Returns the norm of the vector `u = (u_{1}, u_{2})` under the dot product defined by `u \cdot v = (wu_{1} + bu_{2})(w*v_{1} + bv_{2}) + |a|*u_{1}*v_{1}` where `u = (u_{1}, u_{2})` and `v = (v_{1}, v_{2})`. """
""" Simplify the solution `(x_{0}, y_{0}, z_{0})` of the equation `ax^2 + by^2 = cz^2` with `a, b, c > 0` and `z_{0}^2 \geq \mid ab \mid` to a new reduced solution `(x, y, z)` such that `z^2 \leq \mid ab \mid`. """
if c % 2 == 0: k = c // 2 u_0, v_0 = base_solution_linear(k, y_0, -x_0)
else: k = 2*c u_0, v_0 = base_solution_linear(c, y_0, -x_0)
w = -(a*u_0*x_0 + b*v_0*y_0) // (c*z_0)
if c % 2 == 1: if w % 2 != (a*u_0 + b*v_0) % 2: w = w + 1
x = (x_0*(a*u_0**2 + b*v_0**2 + c*w**2) - 2*u_0*(a*u_0*x_0 + b*v_0*y_0 + c*w*z_0)) // k y = (y_0*(a*u_0**2 + b*v_0**2 + c*w**2) - 2*v_0*(a*u_0*x_0 + b*v_0*y_0 + c*w*z_0)) // k z = (z_0*(a*u_0**2 + b*v_0**2 + c*w**2) - 2*w*(a*u_0*x_0 + b*v_0*y_0 + c*w*z_0)) // k
x_0, y_0, z_0 = x, y, z
""" Solves the general pythagorean equation, `a_{1}^2x_{1}^2 + a_{2}^2x_{2}^2 + . . . + a_{n}^2x_{n}^2 - a_{n + 1}^2x_{n + 1}^2 = 0`.
Returns a tuple which contains a parametrized solution to the equation, sorted in the same order as the input variables.
Usage =====
``diop_general_pythagorean(eq, param)``: where ``eq`` is a general pythagorean equation which is assumed to be zero and ``param`` is the base parameter used to construct other parameters by subscripting.
Examples ========
>>> from sympy.solvers.diophantine import diop_general_pythagorean >>> from sympy.abc import a, b, c, d, e >>> diop_general_pythagorean(a**2 + b**2 + c**2 - d**2) (m1**2 + m2**2 - m3**2, 2*m1*m3, 2*m2*m3, m1**2 + m2**2 + m3**2) >>> diop_general_pythagorean(9*a**2 - 4*b**2 + 16*c**2 + 25*d**2 + e**2) (10*m1**2 + 10*m2**2 + 10*m3**2 - 10*m4**2, 15*m1**2 + 15*m2**2 + 15*m3**2 + 15*m4**2, 15*m1*m4, 12*m2*m4, 60*m3*m4) """ var, coeff, diop_type = classify_diop(eq)
if diop_type == "general_pythagorean": return _diop_general_pythagorean(var, coeff, param)
for key in coeff.keys(): coeff[key] = coeff[key] * -1
else:
""" Solves the equation `x_{1}^2 + x_{2}^2 + . . . + x_{n}^2 - k = 0`.
Returns at most ``limit`` number of solutions. Currently there is no way to set ``limit`` using higher level API's like ``diophantine()`` or ``diop_solve()`` but that will be fixed soon.
Usage =====
``general_sum_of_squares(eq, limit)`` : Here ``eq`` is an expression which is assumed to be zero. Also, ``eq`` should be in the form, `x_{1}^2 + x_{2}^2 + . . . + x_{n}^2 - k = 0`. At most ``limit`` number of solutions are returned.
Details =======
When `n = 3` if `k = 4^a(8m + 7)` for some `a, m \in Z` then there will be no solutions. Refer [1]_ for more details.
Examples ========
>>> from sympy.solvers.diophantine import diop_general_sum_of_squares >>> from sympy.abc import a, b, c, d, e, f >>> diop_general_sum_of_squares(a**2 + b**2 + c**2 + d**2 + e**2 - 2345) set([(0, 48, 5, 4, 0)])
Reference =========
.. [1] Representing an Integer as a sum of three squares, [online], Available: http://www.proofwiki.org/wiki/Integer_as_Sum_of_Three_Squares """ var, coeff, diop_type = classify_diop(eq)
if diop_type == "general_sum_of_squares": return _diop_general_sum_of_squares(var, coeff, limit)
return set([])
else:
except StopIteration: break
## Functions below this comment can be more suitably grouped under an Additive number theory module ## rather than the Diophantine equation module.
""" Returns a generator that can be used to generate partitions of an integer `n`.
A partition of `n` is a set of positive integers which add upto `n`. For example, partitions of 3 are 3 , 1 + 2, 1 + 1+ 1. A partition is returned as a tuple. If ``k`` equals None, then all possible partitions are returned irrespective of their size, otherwise only the partitions of size ``k`` are returned. If there are no partions of `n` with size `k` then an empty tuple is returned. If the ``zero`` parameter is set to True then a suitable number of zeros are added at the end of every partition of size less than ``k``.
``zero`` parameter is considered only if ``k`` is not None. When the partitions are over, the last `next()` call throws the ``StopIteration`` exception, so this function should always be used inside a try - except block.
Details =======
``partition(n, k)``: Here ``n`` is a positive integer and ``k`` is the size of the partition which is also positive integer.
Examples ========
>>> from sympy.solvers.diophantine import partition >>> f = partition(5) >>> next(f) (1, 1, 1, 1, 1) >>> next(f) (1, 1, 1, 2) >>> g = partition(5, 3) >>> next(g) (3, 1, 1) >>> next(g) (2, 2, 1)
Reference =========
.. [1] Generating Integer Partitions, [online], Available: http://jeromekelleher.net/partitions.php """
if zeros: for i in range(1, n): for t in partition(n, i): yield (t,) + (0,) * (k - i) else: yield tuple()
else:
for m in range(1, k): for a in partition(n, m): yield tuple(a) + (0,) * (k - m)
else:
""" Represent a prime `p` which is congruent to 1 mod 4, as a sum of two squares.
Examples ========
>>> from sympy.solvers.diophantine import prime_as_sum_of_two_squares >>> prime_as_sum_of_two_squares(5) (2, 1)
Reference =========
.. [1] Representing a number as a sum of four squares, [online], Available: http://www.schorn.ch/howto.html """ else:
""" Returns a 3-tuple `(a, b, c)` such that `a^2 + b^2 + c^2 = n` and `a, b, c \geq 0`.
Returns (None, None, None) if `n = 4^a(8m + 7)` for some `a, m \in Z`. See [1]_ for more details.
Usage =====
``sum_of_three_squares(n)``: Here ``n`` is a non-negative integer.
Examples ========
>>> from sympy.solvers.diophantine import sum_of_three_squares >>> sum_of_three_squares(44542) (207, 37, 18)
References ==========
.. [1] Representing a number as a sum of three squares, [online], Available: http://www.schorn.ch/howto.html """ 85:(6, 7, 0), 130:(3, 11, 0), 214:(3, 6, 13), 226:(8, 9, 9), 370:(8, 9, 15), 526:(6, 7, 21), 706:(15, 15, 16), 730:(1, 27, 0), 1414:(6, 17, 33), 1906:(13, 21, 36), 2986: (21, 32, 39), 9634: (56, 57, 57)}
return (2**v*l, 0, 0)
else:
""" Returns a 4-tuple `(a, b, c, d)` such that `a^2 + b^2 + c^2 + d^2 = n`.
Here `a, b, c, d \geq 0`.
Usage =====
``sum_of_four_squares(n)``: Here ``n`` is a non-negative integer.
Examples ========
>>> from sympy.solvers.diophantine import sum_of_four_squares >>> sum_of_four_squares(3456) (8, 48, 32, 8) >>> sum_of_four_squares(1294585930293) (0, 1137796, 2161, 1234)
References ==========
.. [1] Representing a number as a sum of four squares, [online], Available: http://www.schorn.ch/howto.html """ return (0, 0, 0, 0)
d = 2 n = n - 4 else:
""" Returns a generator for finding k-tuples `(n_{1}, n_{2}, . . . n_{k})` such that `n = n_{1}^p + n_{2}^p + . . . n_{k}^p`.
Here `n` is a non-negative integer. StopIteration exception is raised after all the solutions are generated, so should always be used within a try- catch block.
Usage =====
``power_representation(n, p, k, zeros)``: Represent number ``n`` as a sum of ``k``, ``p``th powers. If ``zeros`` is true, then the solutions will contain zeros.
Examples ========
>>> from sympy.solvers.diophantine import power_representation >>> f = power_representation(1729, 3, 2) # Represent 1729 as a sum of two cubes >>> next(f) (12, 1) >>> next(f) (10, 9) """ raise ValueError("Expected: n > 0 and k >= 1 and p >= 1")
if perfect_power(n): yield (perfect_power(n)[0],) else: yield tuple()
else:
for i in range(2, k): for t in pow_rep_recursive(a, i, n, [], p): yield t + (0,) * (k - i)
else:
|