丢番图¶
备注
对于专注于解决丢番图方程的初学者友好指南,请参阅 代数求解丢番图方程。
丢番图方程¶
“丢番图”一词源自于丢番图,一位生活在公元250年左右亚历山大城的数学家。他常被称为“代数之父”,在其著名著作《算术》中提出了150个问题,标志着数论领域的早期开端,该领域研究整数及其性质。丢番图方程在数论中起着核心且重要的作用。
我们将形如 \(f(x_1, x_2, \ldots x_n) = 0\) 的方程称为“丢番图方程”,其中 \(n \geq 2\) 且 \(x_1, x_2, \ldots x_n\) 是整数变量。如果我们能找到 \(n\) 个整数 \(a_1, a_2, \ldots a_n\) 使得 \(x_1 = a_1, x_2 = a_2, \ldots x_n = a_n\) 满足上述方程,我们称该方程是可解的。你可以在 [1] 和 [2] 中阅读更多关于丢番图方程的内容。
目前,可以使用 diophantine()
以及丢番图模块的其他辅助函数来求解以下五种类型的丢番图方程。
线性丢番图方程:\(a_1x_1 + a_2x_2 + \ldots + a_nx_n = b\)。
一般二元二次方程:\(ax^2 + bxy + cy^2 + dx + ey + f = 0\)
齐次三元二次方程:\(ax^2 + by^2 + cz^2 + dxy + eyz + fzx = 0\)
扩展的毕达哥拉斯方程:\(a_{1}x_{1}^2 + a_{2}x_{2}^2 + \ldots + a_{n}x_{n}^2 = a_{n+1}x_{n+1}^2\)
一般平方和:\(x_{1}^2 + x_{2}^2 + \ldots + x_{n}^2 = k\)
模块结构¶
此模块包含 diophantine()
和用于求解某些丢番图方程所需的辅助函数。其结构如下。
-
diop_solve()
当一个方程被传递给 diophantine()
时,它会尝试分解方程(如果可能的话),并通过分别调用 diop_solve()
来求解每个因子给出的方程。然后,所有结果通过 merge_solution()
合并。
diop_solve()
内部使用 classify_diop()
来确定给定方程的类型(以及一些其他细节),然后根据返回的类型调用适当的求解函数。例如,如果 classify_diop()
返回方程类型为“线性”,那么 diop_solve()
将调用 diop_linear()
来求解方程。
每个函数,diop_linear()
、diop_quadratic()
、diop_ternary_quadratic()
、diop_general_pythagorean()
和 diop_general_sum_of_squares()
,都解决了一种特定类型的方程,其类型可以通过函数名称轻松猜测。
除了这些功能之外,“Diophantine 模块”中还有相当多的其他功能,所有这些功能都列在用户功能和内部功能下。
教程¶
首先,让我们导入 Diophantine 模块的最高 API。
>>> from sympy.solvers.diophantine import diophantine
在我们开始解方程之前,我们需要定义变量。
>>> from sympy import symbols
>>> x, y, z = symbols("x, y, z", integer=True)
让我们从解决最简单的丢番图方程类型开始,即线性丢番图方程。让我们解 \(2x + 3y = 5\)。注意,尽管我们在上面以这种形式写出方程,但当我们将其输入到丢番图模块中的任何函数时,它需要以 \(eq = 0\) 的形式输入。
>>> diophantine(2*x + 3*y - 5)
{(3*t_0 - 5, 5 - 2*t_0)}
请注意,在最高API的下一级,我们可以通过调用 diop_solve()
来解决完全相同的方程。
>>> from sympy.solvers.diophantine.diophantine import diop_solve
>>> diop_solve(2*x + 3*y - 5)
(3*t_0 - 5, 5 - 2*t_0)
注意它返回的是一个元组而不是一个集合。diophantine()
总是返回一个元组集合。但是 diop_solve()
可能返回一个单独的元组或一个元组集合,这取决于给定方程的类型。
我们也可以通过调用 diop_linear()
来解决这个方程,这是 diop_solve()
在内部调用的方法。
>>> from sympy.solvers.diophantine.diophantine import diop_linear
>>> diop_linear(2*x + 3*y - 5)
(3*t_0 - 5, 5 - 2*t_0)
如果给定的方程没有解,那么输出将如下所示。
>>> diophantine(2*x + 4*y - 3)
set()
>>> diop_solve(2*x + 4*y - 3)
(None, None)
>>> diop_linear(2*x + 4*y - 3)
(None, None)
请注意,除了最高级别的API外,在没有解决方案的情况下,将返回一个包含 \(None\) 的元组。元组的大小与变量的数量相同。此外,可以通过传递自定义参数来专门设置解决方案中使用的参数。考虑以下示例:
>>> m = symbols("m", integer=True)
>>> diop_solve(2*x + 3*y - 5, m)
(3*m_0 - 5, 5 - 2*m_0)
对于线性丢番图方程,自定义参数是用于解中每个自由变量的前缀。考虑以下示例:
>>> diop_solve(2*x + 3*y - 5*z + 7, m)
(m_0, m_0 + 5*m_1 - 14, m_0 + 3*m_1 - 7)
在上述解决方案中,m_0 和 m_1 是独立的自由变量。
请注意,目前用户只能为线性丢番图方程和二元二次方程设置参数。
让我们尝试解决一个二元二次方程,这是一个具有两个变量且次数为二的方程。在尝试解决这些方程之前,了解与方程相关的各种情况会非常有帮助。请参考 [3] 和 [4] 以获取不同情况和解的性质的详细分析。让我们定义 \(\Delta = b^2 - 4ac\) 相对于二元二次方程 \(ax^2 + bxy + cy^2 + dx + ey + f = 0\)。
当 \(\Delta < 0\) 时,可能没有解或只有有限个解。
>>> diophantine(x**2 - 4*x*y + 8*y**2 - 3*x + 7*y - 5)
{(2, 1), (5, 1)}
在上式中,\(\Delta = (-4)^2 - 4*1*8 = -16\),因此只存在有限个解。
当 \(\Delta = 0\) 时,我们可能既没有解,也可能有参数化解。
>>> diophantine(3*x**2 - 6*x*y + 3*y**2 - 3*x + 7*y - 5)
set()
>>> diophantine(x**2 - 4*x*y + 4*y**2 - 3*x + 7*y - 5)
{(-2*t**2 - 7*t + 10, -t**2 - 3*t + 5)}
>>> diophantine(x**2 + 2*x*y + y**2 - 3*x - 3*y)
{(t_0, -t_0), (t_0, 3 - t_0)}
最有趣的例子是当 \(\Delta > 0\) 且它不是一个完全平方数时。在这种情况下,方程要么没有解,要么有无限多个解。考虑以下 \(\Delta = 8\) 的情况。
>>> diophantine(x**2 - 4*x*y + 2*y**2 - 3*x + 7*y - 5)
set()
>>> from sympy import sqrt
>>> n = symbols("n", integer=True)
>>> s = diophantine(x**2 - 2*y**2 - 2*x - 4*y, n)
>>> x_1, y_1 = s.pop()
>>> x_2, y_2 = s.pop()
>>> x_n = -(-2*sqrt(2) + 3)**n/2 + sqrt(2)*(-2*sqrt(2) + 3)**n/2 - sqrt(2)*(2*sqrt(2) + 3)**n/2 - (2*sqrt(2) + 3)**n/2 + 1
>>> x_1 == x_n or x_2 == x_n
True
>>> y_n = -sqrt(2)*(-2*sqrt(2) + 3)**n/4 + (-2*sqrt(2) + 3)**n/2 + sqrt(2)*(2*sqrt(2) + 3)**n/4 + (2*sqrt(2) + 3)**n/2 - 1
>>> y_1 == y_n or y_2 == y_n
True
这里 \(n\) 是一个整数。尽管 x_n 和 y_n 可能看起来不像整数,但将特定值代入 n(并简化)表明它们确实是。例如,考虑以下示例,我们将 n 设为 9。
>>> from sympy import simplify
>>> simplify(x_n.subs({n: 9}))
-9369318
任何形式的二元二次方程 \(ax^2 + bxy + cy^2 + dx + ey + f = 0\) 都可以被转换为等价形式 \(X^2 - DY^2 = N\)。
>>> from sympy.solvers.diophantine.diophantine import find_DN, diop_DN, transformation_to_DN
>>> find_DN(x**2 - 3*x*y + y**2 - 7*x + 5*y - 3)
(5, 920)
因此,上述方程在经过线性变换后等价于方程 \(X^2 - 5Y^2 = 920\)。如果我们想要找到这个线性变换,我们可以使用 transformation_to_DN()
。
>>> A, B = transformation_to_DN(x**2 - 3*x*y + y**2 - 7*x + 5*y - 3)
这里 A 是一个 2 X 2 的矩阵,B 是一个 2 X 1 的矩阵,使得变换
给出方程 \(X^2 -5Y^2 = 920\)。\(A\) 和 \(B\) 的值如下。
>>> A
Matrix([
[1/10, 3/10],
[ 0, 1/5]])
>>> B
Matrix([
[ 1/5],
[-11/5]])
我们可以通过传递 \(D\) 和 \(N\) 给 diop_DN()
来解形如 \(X^2 - DY^2 = N\) 的方程。
>>> diop_DN(5, 920)
[]
不幸的是,我们的方程没有解。
现在让我们转向齐次三元二次方程。这些方程的形式为 \(ax^2 + by^2 + cz^2 + dxy + eyz + fzx = 0\)。这类方程要么有无限多的解,要么没有解(除了明显的解 (0, 0, 0))
>>> diophantine(3*x**2 + 4*y**2 - 5*z**2 + 4*x*y + 6*y*z + 7*z*x)
{(0, 0, 0)}
>>> diophantine(3*x**2 + 4*y**2 - 5*z**2 + 4*x*y - 7*y*z + 7*z*x)
{(-16*p**2 + 28*p*q + 20*q**2, 3*p**2 + 38*p*q - 25*q**2, 4*p**2 - 24*p*q + 68*q**2)}
如果你只对一个基础解感兴趣,而不是参数化的通解(更准确地说,是通解之一),你可以使用 diop_ternary_quadratic()
。
>>> from sympy.solvers.diophantine.diophantine import diop_ternary_quadratic
>>> diop_ternary_quadratic(3*x**2 + 4*y**2 - 5*z**2 + 4*x*y - 7*y*z + 7*z*x)
(-4, 5, 1)
diop_ternary_quadratic()
首先将给定的方程转换为等价的 \(w^2 = AX^2 + BY^2\) 形式的方程,然后使用 descent()
来求解后者。你可以参考 transformation_to_normal()
的文档来了解更多关于此的内容。通过使用上述的 descent()
,方程 \(w^2 = AX^2 + BY^2\) 可以更容易地求解。
>>> from sympy.solvers.diophantine.diophantine import descent
>>> descent(3, 1) # solves the equation w**2 = 3*Y**2 + Z**2
(1, 0, 1)
这里解决方案元组按顺序为 (w, Y, Z)
扩展的勾股方程,\(a_{1}x_{1}^2 + a_{2}x_{2}^2 + \ldots + a_{n}x_{n}^2 = a_{n+1}x_{n+1}^2\) 和一般的平方和方程,\(x_{1}^2 + x_{2}^2 + \ldots + x_{n}^2 = k\) 也可以使用Diophantine模块来求解。
>>> from sympy.abc import a, b, c, d, e, f
>>> diophantine(9*a**2 + 16*b**2 + c**2 + 49*d**2 + 4*e**2 - 25*f**2)
{(70*t1**2 + 70*t2**2 + 70*t3**2 + 70*t4**2 - 70*t5**2, 105*t1*t5, 420*t2*t5, 60*t3*t5, 210*t4*t5, 42*t1**2 + 42*t2**2 + 42*t3**2 + 42*t4**2 + 42*t5**2)}
函数 diop_general_pythagorean()
也可以直接调用来解决相同的方程。你可以调用 diop_general_pythagorean()
或者使用高级API。对于一般的平方和,这也是成立的,但调用 diop_general_sum_of_squares()
的一个优势是你可以控制返回多少个解。
>>> from sympy.solvers.diophantine.diophantine import diop_general_sum_of_squares
>>> eq = a**2 + b**2 + c**2 + d**2 - 18
>>> diophantine(eq)
{(0, 0, 3, 3), (0, 1, 1, 4), (1, 2, 2, 3)}
>>> diop_general_sum_of_squares(eq, 2)
{(0, 0, 3, 3), (1, 2, 2, 3)}
该 sum_of_squares()
例程将提供一个迭代器,返回解,并且可以控制解是否包含零(不包含零的解首先返回):
>>> from sympy.solvers.diophantine.diophantine import sum_of_squares
>>> sos = sum_of_squares(18, 4, zeros=True)
>>> next(sos)
(1, 2, 2, 3)
>>> next(sos)
(0, 0, 3, 3)
简单的埃及分数也可以通过Diophantine模块找到。例如,以下是可能将1/2表示为两个单位分数之和的方法:
>>> from sympy import Eq, S
>>> diophantine(Eq(1/x + 1/y, S(1)/2))
{(-2, 1), (1, -2), (3, 6), (4, 4), (6, 3)}
要更深入地理解 Diophantine 模块,请参考以下博客。
参考文献¶
用户功能¶
此函数通过 from sympy import *
导入到全局命名空间中:
- sympy.solvers.diophantine.diophantine.diophantine(eq, param=t, syms=None, permute=False)[源代码][源代码]¶
通过将丢番图方程
eq
转换为等于零的项的乘积,简化其求解过程。示例
>>> from sympy import diophantine >>> from sympy.abc import a, b >>> eq = a**4 + b**4 - (2**4 + 3**4) >>> diophantine(eq) {(2, 3)} >>> diophantine(eq, permute=True) {(-3, -2), (-3, 2), (-2, -3), (-2, 3), (2, -3), (2, 3), (3, -2), (3, 2)}
>>> from sympy.abc import x, y, z >>> diophantine(x**2 - y**2) {(t_0, -t_0), (t_0, t_0)}
>>> diophantine(x*(2*x + 3*y - z)) {(0, n1, n2), (t_0, t_1, 2*t_0 + 3*t_1)} >>> diophantine(x**2 + 3*x*y + 4*x) {(0, n1), (-3*t_0 - 4, t_0)}
并且这个函数是通过 from sympy.solvers.diophantine import *
导入的:
内部函数¶
这些函数旨在在 Diophantine 模块中内部使用。
- sympy.solvers.diophantine.diophantine.base_solution_linear(c, a, b, t=None)[源代码][源代码]¶
返回线性方程 \(ax + by = c\) 的基本解。
示例
>>> from sympy.solvers.diophantine.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, 5 - 2*t) >>> base_solution_linear(0, 5, 7, t) # equation 5*x + 7*y = 0 (7*t, -5*t)
- sympy.solvers.diophantine.diophantine.cornacchia(
- a: int,
- b: int,
- m: int,
解决 \(ax^2 + by^2 = m\) 其中 \(\gcd(a, b) = 1 = \gcd(a, m)\) 且 \(a, b > 0\)。
参考文献
[1]Nitaj, “L’algorithme de Cornacchia”
[2]通过Cornacchia方法求解丢番图方程 ax**2 + by**2 = m,[在线],可获取地址: http://www.numbertheory.org/php/cornacchia.html
示例
>>> from sympy.solvers.diophantine.diophantine import cornacchia >>> cornacchia(2, 3, 35) # equation 2x**2 + 3y**2 = 35 {(2, 3), (4, 1)} >>> cornacchia(1, 1, 25) # equation x**2 + y**2 = 25 {(4, 3)}
- sympy.solvers.diophantine.diophantine.transformation_to_normal(eq)[源代码][源代码]¶
返回将一般三元二次方程
eq
(\(ax^2 + by^2 + cz^2 + dxy + eyz + fxz\)) 转换为无交叉项形式 \(ax^2 + by^2 + cz^2 = 0\) 的变换矩阵。这并不用于求解三元二次方程;它仅是为了完整性而实现的。
- sympy.solvers.diophantine.diophantine.diop_ternary_quadratic(eq, parameterize=False)[源代码][源代码]¶
求解一般二次三元形式,\(ax^2 + by^2 + cz^2 + fxy + gyz + hxz = 0\)。
返回一个元组 \((x, y, z)\),这是上述方程的一个基本解。如果没有解,则返回 \((None, None, None)\)。
示例
>>> from sympy.abc import x, y, z >>> from sympy.solvers.diophantine.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)
- sympy.solvers.diophantine.diophantine.square_factor(a)[源代码][源代码]¶
返回一个整数 \(c\),使得 \(a = c^2k, \ c,k \in Z\)。其中 \(k\) 是无平方因子。\(a\) 可以是一个整数或一个因子字典。
示例
>>> from sympy.solvers.diophantine.diophantine import square_factor >>> square_factor(24) 2 >>> square_factor(-36*3) 6 >>> square_factor(1) 1 >>> square_factor({3: 2, 2: 1, -1: 1}) # -18 3
- sympy.solvers.diophantine.diophantine.descent(A, B)[源代码][源代码]¶
使用带有格基约化的拉格朗日下降法返回非平凡解 (x, y, z) 给 \(x^2 = Ay^2 + Bz^2\)。假设 \(A\) 和 \(B\) 对于存在这样的解是有效的。
这比普通的拉格朗日下降算法更快,因为使用了高斯消元法。
参考文献
[1]Cremona, J. E., Rusin, D. (2003). 有理二次曲线的有效解法。计算数学,72(243),1417-1441。https://doi.org/10.1090/S0025-5718-02-01480-1
示例
>>> from sympy.solvers.diophantine.diophantine import descent >>> descent(3, 1) # x**2 = 3*y**2 + z**2 (1, 0, 1)
\((x, y, z) = (1, 0, 1)\) 是上述方程的一个解。
>>> descent(41, -113) (-16, -3, 1)
- sympy.solvers.diophantine.diophantine.diop_general_pythagorean(eq, param=m)[源代码][源代码]¶
解决一般勾股方程,\(a_{1}^2x_{1}^2 + a_{2}^2x_{2}^2 + . . . + a_{n}^2x_{n}^2 - a_{n + 1}^2x_{n + 1}^2 = 0\)。
返回一个元组,其中包含方程的参数化解,按与输入变量相同的顺序排序。
示例
>>> from sympy.solvers.diophantine.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)
- sympy.solvers.diophantine.diophantine.diop_general_sum_of_squares(eq, limit=1)[源代码][源代码]¶
求解方程 \(x_{1}^2 + x_{2}^2 + . . . + x_{n}^2 - k = 0\)。
最多返回
limit
个解决方案。示例
>>> from sympy.solvers.diophantine.diophantine import diop_general_sum_of_squares >>> from sympy.abc import a, b, c, d, e >>> diop_general_sum_of_squares(a**2 + b**2 + c**2 + d**2 + e**2 - 2345) {(15, 22, 22, 24, 24)}
- sympy.solvers.diophantine.diophantine.diop_general_sum_of_even_powers(eq, limit=1)[源代码][源代码]¶
求解方程 \(x_{1}^e + x_{2}^e + . . . + x_{n}^e - k = 0\) 其中 \(e\) 是一个偶数整数次幂。
最多返回
limit
个解决方案。示例
>>> from sympy.solvers.diophantine.diophantine import diop_general_sum_of_even_powers >>> from sympy.abc import a, b >>> diop_general_sum_of_even_powers(a**4 + b**4 - (2**4 + 3**4)) {(2, 3)}
- sympy.solvers.diophantine.diophantine.power_representation(n, p, k, zeros=False)[源代码][源代码]¶
返回一个生成器,用于查找整数的 k-元组 \((n_{1}, n_{2}, . . . n_{k})\),使得 \(n = n_{1}^p + n_{2}^p + . . . n_{k}^p\)。
示例
>>> from sympy.solvers.diophantine.diophantine import power_representation
将 1729 表示为两个立方之和:
>>> f = power_representation(1729, 3, 2) >>> next(f) (9, 10) >>> next(f) (1, 12)
如果标志 \(zeros\) 为 True,解可能包含带有零的元组;任何此类解将在不带零的解之后生成:
>>> list(power_representation(125, 2, 3, zeros=True)) [(5, 6, 8), (3, 4, 10), (0, 5, 10), (0, 2, 11)]
对于偶数 \(p\),可以使用 \(permute_sign\) 函数来获取所有带符号的值:
>>> from sympy.utilities.iterables import permute_signs >>> list(permute_signs((1, 12))) [(1, 12), (-1, 12), (1, -12), (-1, -12)]
所有可能的带符号排列也可以获得:
>>> from sympy.utilities.iterables import signed_permutations >>> list(signed_permutations((1, 12))) [(1, 12), (-1, 12), (1, -12), (-1, -12), (12, 1), (-12, 1), (12, -1), (-12, -1)]
- sympy.solvers.diophantine.diophantine.partition(n, k=None, zeros=False)[源代码][源代码]¶
返回一个生成器,可用于生成整数 \(n\) 的分区。
示例
>>> from sympy.solvers.diophantine.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) (1, 1, 3) >>> next(g) (1, 2, 2) >>> g = partition(5, 3, zeros=True) >>> next(g) (0, 0, 5)
- sympy.solvers.diophantine.diophantine.sum_of_three_squares(n)[源代码][源代码]¶
返回一个三元组 \((a, b, c)\),使得 \(a^2 + b^2 + c^2 = n\) 且 \(a, b, c \geq 0\)。
如果存在 \(a, m \in \mathbb{Z}\) 使得 \(n = 4^a(8m + 7)\),则返回 None。详见 [1]。
- 参数:
- n整数
非负整数
- 返回:
- (int, int, int) | None : 满足
a**2 + b**2 + c**2 = n
的非负整数三元组(a, b, c)
。3-元组非负整数 a,b,c 按升序排列。如果没有这样的
(a,b,c)
,则为None
。
- (int, int, int) | None : 满足
- Raises:
- ValueError
如果
n
是一个负整数
参见
power_representation
sum_of_three_squares(n)
是power_representation(n, 2, 3, zeros=True)
输出的解决方案之一。
参考文献
[1]将一个数表示为三个平方数的和,[在线],可用链接: https://schorn.ch/lagrange.html
示例
>>> from sympy.solvers.diophantine.diophantine import sum_of_three_squares >>> sum_of_three_squares(44542) (18, 37, 207)
- sympy.solvers.diophantine.diophantine.sum_of_four_squares(n)[源代码][源代码]¶
返回一个4元组 \((a, b, c, d)\),使得 \(a^2 + b^2 + c^2 + d^2 = n\)。其中 \(a, b, c, d \geq 0\)。
- 参数:
- n整数
非负整数
- 返回:
- (int, int, int, int) : 4 元组非负整数
(a, b, c, d)
满足a**2 + b**2 + c**2 + d**2 = n
。4元组非负整数 a,b,c,d 按升序排列。
- (int, int, int, int) : 4 元组非负整数
- Raises:
- ValueError
如果
n
是一个负整数
参见
power_representation
sum_of_four_squares(n)
是power_representation(n, 2, 4, zeros=True)
输出的解决方案之一。
参考文献
[1]将一个数表示为四个平方和,[在线],可用:https://schorn.ch/lagrange.html
示例
>>> from sympy.solvers.diophantine.diophantine import sum_of_four_squares >>> sum_of_four_squares(3456) (8, 8, 32, 48) >>> sum_of_four_squares(1294585930293) (0, 1234, 2161, 1137796)
- sympy.solvers.diophantine.diophantine.sum_of_powers(n, p, k, zeros=False)[源代码]¶
返回一个生成器,用于查找整数的 k-元组 \((n_{1}, n_{2}, . . . n_{k})\),使得 \(n = n_{1}^p + n_{2}^p + . . . n_{k}^p\)。
示例
>>> from sympy.solvers.diophantine.diophantine import power_representation
将 1729 表示为两个立方之和:
>>> f = power_representation(1729, 3, 2) >>> next(f) (9, 10) >>> next(f) (1, 12)
如果标志 \(zeros\) 为 True,解可能包含带有零的元组;任何此类解将在不带零的解之后生成:
>>> list(power_representation(125, 2, 3, zeros=True)) [(5, 6, 8), (3, 4, 10), (0, 5, 10), (0, 2, 11)]
对于偶数 \(p\),可以使用 \(permute_sign\) 函数来获取所有带符号的值:
>>> from sympy.utilities.iterables import permute_signs >>> list(permute_signs((1, 12))) [(1, 12), (-1, 12), (1, -12), (-1, -12)]
所有可能的带符号排列也可以获得:
>>> from sympy.utilities.iterables import signed_permutations >>> list(signed_permutations((1, 12))) [(1, 12), (-1, 12), (1, -12), (-1, -12), (12, 1), (-12, 1), (12, -1), (-12, -1)]
- sympy.solvers.diophantine.diophantine.sum_of_squares(n, k, zeros=False)[源代码][源代码]¶
返回一个生成器,该生成器生成非负值的 k-元组,其平方和为 n。如果 zeros 为 False(默认),则解决方案将不包含零。元组中的非负元素按顺序排列。
如果 k == 1 且 n 是平方数,则返回 (n,)。
如果 k == 2,那么 n 只能写成平方和的形式,如果 n 的因数分解中所有形式为 4*k + 3 的素数都有偶数次幂。如果 n 是素数,那么它只能写成两个平方和的形式,如果它是 4*k + 1 的形式。
如果 k == 3,那么 n 可以写成平方和的形式,如果它不具有 4**m*(8*k + 7) 的形式。
所有整数都可以写成四个平方的和。
如果 k > 4,那么 n 可以被划分,并且每个部分可以写成 4 个平方的和;如果 n 不能被 4 整除,那么 n 只能写成平方和,如果可以写成额外的部分的平方和。例如,如果 k = 6,那么 n 被分成两部分,第一部分写成 4 个平方的和,第二部分写成 2 个平方的和——这只有在满足上述 k = 2 的条件时才能做到,因此这将自动拒绝 n 的某些划分。
示例
>>> from sympy.solvers.diophantine.diophantine import sum_of_squares >>> list(sum_of_squares(25, 2)) [(3, 4)] >>> list(sum_of_squares(25, 2, True)) [(3, 4), (0, 5)] >>> list(sum_of_squares(25, 4)) [(1, 2, 2, 4)]
- sympy.solvers.diophantine.diophantine.merge_solution(var, var_t, solution)[源代码][源代码]¶
这用于从子方程的解中构建完整解。
- sympy.solvers.diophantine.diophantine.divisible(a, b)[源代码][源代码]¶
如果
a
能被b
整除则返回 \(True\),否则返回 \(False\)。
- sympy.solvers.diophantine.diophantine.PQa(P_0, Q_0, D)[源代码][源代码]¶
返回解决佩尔方程所需的有用信息。
参考文献
[1]解决广义Pell方程 x^2 - Dy^2 = N,John P. Robertson,2004年7月31日,第4 - 8页。https://web.archive.org/web/20160323033128/http://www.jpr2718.org/pell.pdf
示例
>>> from sympy.solvers.diophantine.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)
- sympy.solvers.diophantine.diophantine.equivalent(u, v, r, s, D, N)[源代码][源代码]¶
如果两个解 \((u, v)\) 和 \((r, s)\) 属于 \(x^2 - Dy^2 = N\) 的同一等价类,则返回 True,否则返回 False。
参考文献
[1]解决广义Pell方程 x**2 - D*y**2 = N,John P. Robertson,2004年7月31日,第12页。https://web.archive.org/web/20160323033128/http://www.jpr2718.org/pell.pdf
示例
>>> from sympy.solvers.diophantine.diophantine import equivalent >>> equivalent(18, 5, -18, -5, 13, -1) True >>> equivalent(3, 1, -18, 393, 109, -4) False
- sympy.solvers.diophantine.diophantine.parametrize_ternary_quadratic(eq)[源代码][源代码]¶
返回三元二次方程
eq
的参数化通解,其形式为 \(ax^2 + by^2 + cz^2 + fxy + gyz + hxz = 0\)。注释
考虑在前面的2参数解决方案中的
p
和q
,并观察到给定的一对参数可以表示多个解决方案。如果 \(p\) 和q
不是互质的,这是显而易见的,因为公因子也将是解值的公因子。但即使p
和q
是互质的,这也可能是真的:>>> sol = Tuple(*_) >>> p, q = ordered(sol.free_symbols) >>> sol.subs([(p, 3), (q, 2)]) (6, 12, 12) >>> sol.subs([(q, 1), (p, 1)]) (-1, 2, 2) >>> sol.subs([(q, 0), (p, 1)]) (2, -4, 4) >>> sol.subs([(q, 1), (p, 0)]) (-3, -6, 6)
除了符号和一个公因子外,这些等价于 (1, 2, 2) 的解。
参考文献
[1]Diophantine方程的算法解法,Nigel P. Smart,伦敦数学学会学生教材41,剑桥大学出版社,剑桥,1998年。
示例
>>> from sympy import Tuple, ordered >>> from sympy.abc import x, y, z >>> from sympy.solvers.diophantine.diophantine import parametrize_ternary_quadratic
参数化解决方案可能返回三个参数:
>>> parametrize_ternary_quadratic(2*x**2 + y**2 - 2*z**2) (p**2 - 2*q**2, -2*p**2 + 4*p*q - 4*p*r - 4*q**2, p**2 - 4*p*q + 2*q**2 - 4*q*r)
也可能只有两个参数:
>>> parametrize_ternary_quadratic(4*x**2 + 2*y**2 - 3*z**2) (2*p**2 - 3*q**2, -4*p**2 + 12*p*q - 6*q**2, 4*p**2 - 8*p*q + 6*q**2)
- sympy.solvers.diophantine.diophantine.diop_ternary_quadratic_normal(
- eq,
- parameterize=False,
求解二次三元丢番图方程,\(ax^2 + by^2 + cz^2 = 0\)。
示例
>>> from sympy.abc import x, y, z >>> from sympy.solvers.diophantine.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)
- sympy.solvers.diophantine.diophantine.ldescent(A, B)[源代码][源代码]¶
使用拉格朗日方法返回 \(w^2 = Ax^2 + By^2\) 的一个非平凡解;如果没有这样的解,则返回 None。
- 参数:
- A整数
- B整数
非零整数
- 返回:
- (int, int, int) | None : 一个元组 \((w_0, x_0, y_0)\),它是上述方程的解。一个元组
参考文献
[1]Diophantine方程的算法解法,Nigel P. Smart,伦敦数学学会学生教材41,剑桥大学出版社,剑桥,1998年。
[2]Cremona, J. E., Rusin, D. (2003). 有理二次曲线的有效解法。计算数学,72(243),1417-1441。https://doi.org/10.1090/S0025-5718-02-01480-1
示例
>>> from sympy.solvers.diophantine.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)
这意味着 \(x = -1, y = 0\) 和 \(w = 2\) 是方程 \(w^2 = 4x^2 - 7y^2\) 的一个解。
>>> ldescent(5, -1) # w^2 = 5x^2 - y^2 (2, 1, -1)
- sympy.solvers.diophantine.diophantine.gaussian_reduce(
- w: int,
- a: int,
- b: int,
返回同余式 \(X^2 - aZ^2 \equiv 0 \pmod{b}\) 的一个简化解 \((x, z)\),使得 \(x^2 + |a|z^2\) 尽可能小。这里
w
是同余式 \(x^2 \equiv a \pmod{b}\) 的一个解。此函数仅用于
descent()
。- 参数:
- w整数
w
使得 \(w^2 \equiv a \pmod{b}\)- a整数
无平方因子的非零整数
- b整数
无平方因子的非零整数
参考文献
[1]高斯格基约化 [在线]。可用链接: https://web.archive.org/web/20201021115213/http://home.ie.cuhk.edu.hk/~wkshum/wordpress/?p=404
[2]Cremona, J. E., Rusin, D. (2003). 有理二次曲线的有效解法。计算数学,72(243),1417-1441。https://doi.org/10.1090/S0025-5718-02-01480-1
示例
>>> from sympy.solvers.diophantine.diophantine import gaussian_reduce >>> from sympy.ntheory.residue_ntheory import sqrt_mod >>> a, b = 19, 101 >>> gaussian_reduce(sqrt_mod(a, b), a, b) # 1**2 - 19*(-4)**2 = -303 (1, -4) >>> a, b = 11, 14 >>> x, z = gaussian_reduce(sqrt_mod(a, b), a, b) >>> (x**2 - a*z**2) % b == 0 True
它并不总是返回最小的解决方案。
>>> a, b = 6, 95 >>> min_x, min_z = 1, 4 >>> x, z = gaussian_reduce(sqrt_mod(a, b), a, b) >>> (x**2 - a*z**2) % b == 0 and (min_x**2 - a*min_z**2) % b == 0 True >>> min_x**2 + abs(a)*min_z**2 < x**2 + abs(a)*z**2 True
- sympy.solvers.diophantine.diophantine.holzer(x, y, z, a, b, c)[源代码][源代码]¶
简化方程 \(ax^2 + by^2 = cz^2\) 的解 \((x, y, z)\),其中 \(a, b, c > 0\) 且 \(z^2 \geq \mid ab \mid\),得到一个新的简化解 \((x', y', z')\),使得 \(z'^2 \leq \mid ab \mid\)。
该算法是对Mordell的简化方法的解释,如Cremona和Rusin的论文[R46b3645dda18-1]_第8页所述,以及参考文献[R46b3645dda18-2]_中Mordell的工作。
参考文献
[1]Cremona, J. E., Rusin, D. (2003). 有理二次曲线的有效解法。计算数学,72(243),1417-1441。https://doi.org/10.1090/S0025-5718-02-01480-1
[2]丢番图方程,L. J. Mordell,第48页。
- sympy.solvers.diophantine.diophantine.prime_as_sum_of_two_squares(p)[源代码][源代码]¶
将一个质数 \(p\) 表示为两个平方的唯一和;这只有在质数同余于 1 mod 4 时才能完成。
- 参数:
- p整数
一个模 4 余 1 的素数
- 返回:
- (int, int) | None : 一对正整数
(x, y)
满足x**2 + y**2 = p
。一对正整数 如果
p
不与 1 模 4 同余,则为 None。
- (int, int) | None : 一对正整数
- Raises:
- ValueError
如果
p
不是质数
示例
>>> from sympy.solvers.diophantine.diophantine import prime_as_sum_of_two_squares >>> prime_as_sum_of_two_squares(7) # can't be done >>> prime_as_sum_of_two_squares(5) (1, 2)
内部类¶
这些类旨在在 Diophantine 模块中内部使用。
- class sympy.solvers.diophantine.diophantine.DiophantineSolutionSet(symbols_seq, parameters)[源代码][源代码]¶
特定丢番图方程的一组解的容器。
基本表示形式是一组元组,每个元组表示一个解决方案。
- 参数:
- 符号列表
原始方程中的自由符号列表。
- 参数: 列表
解决方案中使用的参数列表。
方法
__call__
(*args)add
(solution)clear
从该集合中移除所有元素。
copy
返回集合的浅拷贝。
difference
返回两个或更多集合的差集作为一个新集合。
difference_update
从此集合中移除另一个集合的所有元素。
discard
如果元素是集合的成员,则将其移除。
intersection
返回两个集合的交集作为一个新的集合。
intersection_update
更新一个集合,使其包含自身与另一个集合的交集。
isdisjoint
如果两个集合的交集为空,则返回 True。
issubset
报告另一个集合是否包含此集合。
issuperset
报告此集合是否包含另一个集合。
pop
移除并返回一个任意集合元素。
remove
从集合中移除一个元素;它必须是成员。
symmetric_difference
返回两个集合的对称差作为一个新集合。
symmetric_difference_update
用自身与另一个集合的对称差更新集合。
union
返回集合的并集作为一个新集合。
update
(*solutions)dict_iterator
subs
示例
添加解决方案:
>>> from sympy.solvers.diophantine.diophantine import DiophantineSolutionSet >>> from sympy.abc import x, y, t, u >>> s1 = DiophantineSolutionSet([x, y], [t, u]) >>> s1 set() >>> s1.add((2, 3)) >>> s1.add((-1, u)) >>> s1 {(-1, u), (2, 3)} >>> s2 = DiophantineSolutionSet([x, y], [t, u]) >>> s2.add((3, 4)) >>> s1.update(*s2) >>> s1 {(-1, u), (2, 3), (3, 4)}
将解决方案转换为字典:
>>> list(s1.dict_iterator()) [{x: -1, y: u}, {x: 2, y: 3}, {x: 3, y: 4}]
替换值:
>>> s3 = DiophantineSolutionSet([x, y], [t, u]) >>> s3.add((t**2, t + u)) >>> s3 {(t**2, t + u)} >>> s3.subs({t: 2, u: 3}) {(4, 5)} >>> s3.subs(t, -1) {(1, u - 1)} >>> s3.subs(t, 3) {(9, u + 3)}
在特定值处的评估。位置参数按照与参数相同的顺序给出:
>>> s3(-2, 3) {(4, 1)} >>> s3(5) {(25, u + 5)} >>> s3(None, 2) {(t**2, t + 2)}
- class sympy.solvers.diophantine.diophantine.DiophantineEquationType(
- equation,
- free_symbols=None,
特定丢番图方程类型的内部表示。
- 参数:
- 方程
正在求解的丢番图方程。
- 自由符号列表(可选)
正在求解的符号。
- 属性:
- 总学位
方程中所有项的次数的最大值
- 同质
方程是否包含一个0次项
- homogeneous_order
方程中是否包含任何作为求解符号的系数
- 维度
正在求解的符号数量
方法
matches
()确定给定的方程是否可以匹配到特定的方程类型。
pre_solve
解决
- class sympy.solvers.diophantine.diophantine.Univariate(equation, free_symbols=None)[源代码][源代码]¶
单变量丢番图方程的表示。
单变量丢番图方程是形如 \(a_{0} + a_{1}x + a_{2}x^2 + .. + a_{n}x^n = 0\) 的方程,其中 \(a_{1}, a_{2}, ..a_{n}\) 是整数常数,\(x\) 是整数变量。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
示例
>>> from sympy.solvers.diophantine.diophantine import Univariate >>> from sympy.abc import x >>> Univariate((x - 2)*(x - 3)**2).solve() # solves equation (x - 2)*(x - 3)**2 == 0 {(2,), (3,)}
- class sympy.solvers.diophantine.diophantine.Linear(equation, free_symbols=None)[源代码][源代码]¶
线性丢番图方程的表示。
线性丢番图方程是形如 \(a_{1}x_{1} + a_{2}x_{2} + .. + a_{n}x_{n} = 0\) 的方程,其中 \(a_{1}, a_{2}, ..a_{n}\) 是整数常数,\(x_{1}, x_{2}, ..x_{n}\) 是整数变量。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
示例
>>> from sympy.solvers.diophantine.diophantine import Linear >>> from sympy.abc import x, y, z >>> l1 = Linear(2*x - 3*y - 5) >>> l1.matches() # is this equation linear True >>> l1.solve() # solves equation 2*x - 3*y - 5 == 0 {(3*t_0 - 5, 2*t_0 - 5)}
这里 x = -3*t_0 - 5 且 y = -2*t_0 - 5
>>> Linear(2*x - 3*y - 4*z -3).solve() {(t_0, 2*t_0 + 4*t_1 + 3, -t_0 - 3*t_1 - 3)}
- class sympy.solvers.diophantine.diophantine.BinaryQuadratic(equation, free_symbols=None)[源代码][源代码]¶
二元二次丢番图方程的表示。
二元二次丢番图方程是形如 \(Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0\) 的方程,其中 \(A, B, C, D, E, F\) 是整数常数,\(x\) 和 \(y\) 是整数变量。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
参考文献
[1]解决 Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0 的方法,[在线],可访问:https://www.alpertron.com.ar/METHODS.HTM
[2]求解方程 ax^2+ bxy + cy^2 + dx + ey + f= 0, [在线], 可获取: https://web.archive.org/web/20160323033111/http://www.jpr2718.org/ax2p.pdf
示例
>>> from sympy.abc import x, y >>> from sympy.solvers.diophantine.diophantine import BinaryQuadratic >>> b1 = BinaryQuadratic(x**3 + y**2 + 1) >>> b1.matches() False >>> b2 = BinaryQuadratic(x**2 + y**2 + 2*x + 2*y + 2) >>> b2.matches() True >>> b2.solve() {(-1, -1)}
- class sympy.solvers.diophantine.diophantine.InhomogeneousTernaryQuadratic(
- equation,
- free_symbols=None,
非齐次三元二次型的表示。
目前没有为这种方程类型实现求解器。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
- class sympy.solvers.diophantine.diophantine.HomogeneousTernaryQuadraticNormal(
- equation,
- free_symbols=None,
齐次三元二次正规丢番图方程的表示。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
示例
>>> from sympy.abc import x, y, z >>> from sympy.solvers.diophantine.diophantine import HomogeneousTernaryQuadraticNormal >>> HomogeneousTernaryQuadraticNormal(4*x**2 - 5*y**2 + z**2).solve() {(1, 2, 4)}
- class sympy.solvers.diophantine.diophantine.HomogeneousTernaryQuadratic(
- equation,
- free_symbols=None,
齐次三元二次丢番图方程的表示。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
示例
>>> from sympy.abc import x, y, z >>> from sympy.solvers.diophantine.diophantine import HomogeneousTernaryQuadratic >>> HomogeneousTernaryQuadratic(x**2 + y**2 - 3*z**2 + x*y).solve() {(-1, 2, 1)} >>> HomogeneousTernaryQuadratic(3*x**2 + y**2 - 3*z**2 + 5*x*y + y*z).solve() {(3, 12, 13)}
- class sympy.solvers.diophantine.diophantine.InhomogeneousGeneralQuadratic(
- equation,
- free_symbols=None,
非均匀一般二次型的表示。
目前没有为这种方程类型实现求解器。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
- class sympy.solvers.diophantine.diophantine.HomogeneousGeneralQuadratic(
- equation,
- free_symbols=None,
同质一般二次型的表示。
目前没有为这种方程类型实现求解器。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
- class sympy.solvers.diophantine.diophantine.GeneralSumOfSquares(equation, free_symbols=None)[源代码][源代码]¶
丢番图方程的表示
\(x_{1}^2 + x_{2}^2 + . . . + x_{n}^2 - k = 0\).
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
参考文献
[1]将一个整数表示为三个平方和,[在线],可用:https://www.proofwiki.org/wiki/Integer_as_Sum_of_Three_Squares
示例
>>> from sympy.solvers.diophantine.diophantine import GeneralSumOfSquares >>> from sympy.abc import a, b, c, d, e >>> GeneralSumOfSquares(a**2 + b**2 + c**2 + d**2 + e**2 - 2345).solve() {(15, 22, 22, 24, 24)}
默认情况下只返回1个解决方案。使用 \(limit\) 关键字获取更多:
>>> sorted(GeneralSumOfSquares(a**2 + b**2 + c**2 + d**2 + e**2 - 2345).solve(limit=3)) [(15, 22, 22, 24, 24), (16, 19, 24, 24, 24), (16, 20, 22, 23, 26)]
- class sympy.solvers.diophantine.diophantine.GeneralPythagorean(equation, free_symbols=None)[源代码][源代码]¶
一般勾股方程的表示形式,\(a_{1}^2x_{1}^2 + a_{2}^2x_{2}^2 + . . . + a_{n}^2x_{n}^2 - a_{n + 1}^2x_{n + 1}^2 = 0\)。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
示例
>>> from sympy.solvers.diophantine.diophantine import GeneralPythagorean >>> from sympy.abc import a, b, c, d, e, x, y, z, t >>> GeneralPythagorean(a**2 + b**2 + c**2 - d**2).solve() {(t_0**2 + t_1**2 - t_2**2, 2*t_0*t_2, 2*t_1*t_2, t_0**2 + t_1**2 + t_2**2)} >>> GeneralPythagorean(9*a**2 - 4*b**2 + 16*c**2 + 25*d**2 + e**2).solve(parameters=[x, y, z, t]) {(-10*t**2 + 10*x**2 + 10*y**2 + 10*z**2, 15*t**2 + 15*x**2 + 15*y**2 + 15*z**2, 15*t*x, 12*t*y, 60*t*z)}
- class sympy.solvers.diophantine.diophantine.CubicThue(equation, free_symbols=None)[源代码][源代码]¶
立方 Thue 丢番图方程的表示。
一个三次Thue丢番图方程是一个形如 \(f(x, y) = r\) 的三次多项式,其中 \(x\) 和 \(y\) 是整数,\(r\) 是有理数。
目前没有为这种方程类型实现求解器。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
示例
>>> from sympy.abc import x, y >>> from sympy.solvers.diophantine.diophantine import CubicThue >>> c1 = CubicThue(x**3 + y**2 + 1) >>> c1.matches() True
- class sympy.solvers.diophantine.diophantine.GeneralSumOfEvenPowers(
- equation,
- free_symbols=None,
丢番图方程的表示
\(x_{1}^e + x_{2}^e + . . . + x_{n}^e - k = 0\)
其中 \(e\) 是一个偶数、整数次幂。
- 属性:
- n_parameters
- 参数
方法
matches
()pre_solve
解决
示例
>>> from sympy.solvers.diophantine.diophantine import GeneralSumOfEvenPowers >>> from sympy.abc import a, b >>> GeneralSumOfEvenPowers(a**4 + b**4 - (2**4 + 3**4)).solve() {(2, 3)}