SymPy 1.13 中文文档(十七)
求解器
本模块文档详细介绍了 sympy.solvers 模块的函数。
内容
-
丢番图方程
-
不等式求解器
-
常微分方程
-
偏微分方程
-
求解器
-
解集
丢番图
注意
对于初学者的指南,重点在解决丢番图方程上,请参阅 代数解丢番图方程。
丢番图方程
“丢番图”一词源自于数学家丢番奴,他大约生活在公元 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² + bxy + cy² + dx + ey + f = 0)
-
齐次三元二次方程:(ax² + by² + cz² + dxy + eyz + fzx = 0)
-
扩展勾股定理方程:(a_{1}x_{1}² + a_{2}x_{2}² + \ldots + a_{n}x_{n}² = a_{n+1}x_{n+1}²)
-
一般平方和:(x_{1}² + x_{2}² + \ldots + x_{n}² = k)
模块结构
这个模块包含 diophantine() 函数及其它辅助函数,用于解决特定的丢番图方程。其结构如下所示。
-
diophantine()-
diop_solve()-
classify_diop() -
diop_linear() -
diop_quadratic() -
diop_ternary_quadratic() -
diop_ternary_quadratic_normal() -
diop_general_pythagorean() -
diop_general_sum_of_squares() -
diop_general_sum_of_even_powers()
-
-
merge_solution()
-
当方程被传递给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 Module”中还有大量其他函数,所有这些函数都列在用户函数和内部函数下。
教程
首先,让我们导入丢番图模块的最高级 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)}
请注意,再往下一级,我们可以通过调用 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² - 4ac) 关于二元二次方程 (ax² + bxy + cy² + 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)² - 418 = -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² + bxy + cy² + dx + ey + f = 0) 的二元二次方程都可以转换成等价形式 (X² - DY² = 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² - 5Y² = 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 矩阵,这样变换
[\begin{split}\begin{bmatrix} X\Y \end{bmatrix} = A \begin{bmatrix} x\y \end{bmatrix} + B\end{split}]
给出方程 (X² -5Y² = 920)。(A) 和 (B) 的值如下。
>>> A
Matrix([
[1/10, 3/10],
[ 0, 1/5]])
>>> B
Matrix([
[ 1/5],
[-11/5]])
我们可以通过将 (D) 和 (N) 传递给 diop_DN() 来解决形如 (X² - DY² = N) 的方程。
>>> diop_DN(5, 920)
[]
不幸的是,我们的方程没有解。
现在让我们转向齐次三元二次方程。这些方程的形式为 (ax² + by² + cz² + 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() first converts the given equation to an equivalent equation of the form (w² = AX² + BY²) and then it uses descent() to solve the latter equation. You can refer to the docs of transformation_to_normal() to find more on this. The equation (w² = AX² + BY²) can be solved more easily by using the Aforementioned descent().
>>> from sympy.solvers.diophantine.diophantine import descent
>>> descent(3, 1) # solves the equation w**2 = 3*Y**2 + Z**2
(1, 0, 1)
Here the solution tuple is in the order (w, Y, Z)
The extended Pythagorean equation, (a_{1}x_{1}² + a_{2}x_{2}² + \ldots + a_{n}x_{n}² = a_{n+1}x_{n+1}²) and the general sum of squares equation, (x_{1}² + x_{2}² + \ldots + x_{n}² = k) can also be solved using the Diophantine module.
>>> 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)}
function diop_general_pythagorean() can also be called directly to solve the same equation. Either you can call diop_general_pythagorean() or use the high level API. For the general sum of squares, this is also true, but one advantage of calling diop_general_sum_of_squares() is that you can control how many solutions are returned.
>>> 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)}
The sum_of_squares() routine will providean iterator that returns solutions and one may control whether the solutions contain zeros or not (and the solutions not containing zeros are returned first):
>>> 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)
Simple Eqyptian fractions can be found with the Diophantine module, too. For example, here are the ways that one might represent 1/2 as a sum of two unit fractions:
>>> from sympy import Eq, S
>>> diophantine(Eq(1/x + 1/y, S(1)/2))
{(-2, 1), (1, -2), (3, 6), (4, 4), (6, 3)}
To get a more thorough understanding of the Diophantine module, please refer to the following blog.
References
User Functions
This functions is imported into the global namespace with from sympy import *:
sympy.solvers.diophantine.diophantine.diophantine(eq, param=t, syms=None, permute=False)
Simplify the solution procedure of diophantine equation eq by converting it into a product of terms which should equal zero.
Explanation
例如,当解决 (x² - y² = 0) 时,这被视为 ((x + y)(x - y) = 0),分别解决 (x + y = 0) 和 (x - y = 0),然后合并。每个术语通过调用 diop_solve() 来解决。(虽然可以直接调用 diop_solve(),但必须小心传递正确形式的方程并正确解释输出;diophantine() 是一般情况下使用的公共函数。)
diophantine() 的输出是一组元组。元组的元素是方程中每个变量的解决方案,并按照变量的字母顺序排列。例如,对于两个变量 (a) 和 (b) 的方程,元组的第一个元素是 (a) 的解,第二个是 (b) 的解。
用法
diophantine(eq, t, syms): 解决丢番图方程 eq。t 是可选的 diop_solve() 使用的参数。syms 是一个可选的符号列表,确定返回元组中元素的顺序。
默认情况下,只返回基本解决方案。如果设置 permute 为 True,则在适用时将返回基本解决方案的排列组合和/或值符号的排列组合。
细节
eq 应为假设为零的表达式。t 是解决方案中使用的参数。
示例
>>> 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 * 导入:
sympy.solvers.diophantine.diophantine.classify_diop(eq, _dict=True)
内部函数
这些函数旨在用于丢番图模块的内部使用。
sympy.solvers.diophantine.diophantine.diop_solve(eq, param=t)
解决丢番图方程 eq。
解释
与 diophantine() 不同,不尝试对 eq 进行因式分解。使用 classify_diop() 确定方程的类型并调用适当的解算函数。
推荐使用 diophantine() 而不是其他辅助函数。diop_solve() 可以根据方程的性质返回集合或元组。
用法
diop_solve(eq, t): 使用 t 作为参数解决丢番图方程 eq。
细节
eq 应为假设为零的表达式。t 是解决方案中使用的参数。
示例
>>> from sympy.solvers.diophantine import diop_solve
>>> from sympy.abc import x, y, z, w
>>> diop_solve(2*x + 3*y - 5)
(3*t_0 - 5, 5 - 2*t_0)
>>> diop_solve(4*x + 3*y - 4*z + 5)
(t_0, 8*t_0 + 4*t_1 + 5, 7*t_0 + 3*t_1 + 5)
>>> diop_solve(x + 3*y - 4*z + w - 6)
(t_0, t_0 + t_1, 6*t_0 + 5*t_1 + 4*t_2 - 6, 5*t_0 + 4*t_1 + 3*t_2 - 6)
>>> diop_solve(x**2 + y**2 - 5)
{(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1)}
另请参阅
丢番图方程
sympy.solvers.diophantine.diophantine.diop_linear(eq, param=t)
解决线性丢番图方程。
线性丢番图方程是形如 (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}) 是整数变量。
用法
diop_linear(eq): 返回一个包含丢番图方程 eq 的解的元组。元组中的值按排序后的变量顺序排列。
详情
eq 是假设为零的线性丢番图方程。param 是解中要使用的参数。
示例
>>> from sympy.solvers.diophantine.diophantine import diop_linear
>>> from sympy.abc import x, y, z
>>> diop_linear(2*x - 3*y - 5) # solves equation 2*x - 3*y - 5 == 0
(3*t_0 - 5, 2*t_0 - 5)
这里 x = -3t_0 - 5,y = -2t_0 - 5
>>> diop_linear(2*x - 3*y - 4*z -3)
(t_0, 2*t_0 + 4*t_1 + 3, -t_0 - 3*t_1 - 3)
另请参见
diop_quadratic, diop_ternary_quadratic, diop_general_pythagorean, diop_general_sum_of_squares
sympy.solvers.diophantine.diophantine.base_solution_linear(c, a, b, t=None)
返回线性方程 (ax + by = c) 的基础解。
解释
由 diop_linear() 使用以找到线性丢番图方程的基础解。如果给定 t,则返回参数化解。
用法
base_solution_linear(c, a, b, t): a, b, c 是 (ax + by = c) 中的系数,t 是解中要使用的参数。
示例
>>> 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.diop_quadratic(eq, param=t)
解决二次丢番图方程。
即形式为 (Ax² + Bxy + Cy² + Dx + Ey + F = 0) 的方程。返回包含元组 ((x, y)) 的集合,包含解。如果没有解,则返回 ((None, None))。
用法
diop_quadratic(eq, param): eq 是二次二元丢番图方程。param 用于指示解中要使用的参数。
详情
eq 应为假设为零的表达式。param 是解中要使用的参数。
示例
>>> from sympy.abc import x, y, t
>>> from sympy.solvers.diophantine.diophantine import diop_quadratic
>>> diop_quadratic(x**2 + y**2 + 2*x + 2*y + 2, t)
{(-1, -1)}
另请参见
diop_linear, diop_ternary_quadratic, diop_general_sum_of_squares, diop_general_pythagorean
参考
[R858]
解决方程 Ax² + Bxy + Cy² + Dx + Ey + F = 0 的方法,[在线],可访问:www.alpertron.com.ar/METHODS.HTM
[R859]
解决方程 ax²+ bxy + cy² + dx + ey + f= 0,[在线],可访问:web.archive.org/web/20160323033111/http://www.jpr2718.org/ax2p.pdf
sympy.solvers.diophantine.diophantine.diop_DN(D, N, t=t)
解决方程 (x² - Dy² = N)。
解释
主要关注(D > 0)且(D)不是完全平方数的情况,这与广义 Pell 方程相同。LMM 算法[R860]用于解决此方程。
对每个解类返回一个解元组((x, y))。可以根据 D 和 N 的值构造该类的其他解。
用法
diop_DN(D, N, t): D 和 N 是方程(x² - Dy² = N)中的整数,t是解的参数。
详情
D和N对应于方程中的 D 和 N。t是解的参数。
示例
>>> from sympy.solvers.diophantine.diophantine import diop_DN
>>> diop_DN(13, -4) # Solves equation x**2 - 13*y**2 = -4
[(3, 1), (393, 109), (36, 10)]
输出可以解释如下:方程(x² - 13y² = -4)有三个基本解,分别为(3, 1),(393, 109)和(36, 10)。每个元组都是形如(x, y)的形式,即解(3, 1)意味着(x = 3)且(y = 1)。
>>> diop_DN(986, 1) # Solves equation x**2 - 986*y**2 = 1
[(49299, 1570)]
参见
find_DN, diop_bf_DN
参考
[R860] (1,2)
解决广义 Pell 方程(x² - D*y² = N),John P. Robertson,2004 年 7 月 31 日,第 16 - 17 页。[在线],可用:web.archive.org/web/20160323033128/http://www.jpr2718.org/pell.pdf
sympy.solvers.diophantine.diophantine.cornacchia(a: int, b: int, m: int) → set[tuple[int, int]]
解决方程(ax² + by² = m),其中(\gcd(a, b) = 1 = gcd(a, m)),且(a, b > 0)。
说明
使用 Cornacchia 算法。该方法仅找到原始解,即满足(\gcd(x, y) = 1)的解。因此,该方法不能用于寻找方程(x² + y² = 20)的解,因为前者的唯一解为((x, y) = (4, 2)),且不是原始解。当(a = b)时,仅找到满足(x \leq y)的解。更多详细信息,请参见参考资料。
示例
>>> 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.utilities.iterables.signed_permutations
参考
[R861]
- Nitaj,“L’algorithme de Cornacchia”
[R862]
通过 Cornacchia 方法解决二次丢番图方程 ax2 + by2 = m,[在线],可用:www.numbertheory.org/php/cornacchia.html
sympy.solvers.diophantine.diophantine.diop_bf_DN(D, N, t=t)
用暴力方法解决方程(x² - Dy² = N)。
说明
主要关注广义 Pell 方程,即当(D > 0)且(D)不是完全平方数的情况。有关此情况的更多信息,请参考[R863]。设((t, u))是方程(x² - Dy² = 1)的最小正解。然后,此方法要求(\sqrt{\frac{\mid N \mid (t \pm 1)}{2D}})要很小。
用法
diop_bf_DN(D, N, t): D和N是方程(x² - Dy² = N)中的系数,t是解的参数。
详情
D和N对应于方程中的 D 和 N。t是解的参数。
示例
>>> from sympy.solvers.diophantine.diophantine import diop_bf_DN
>>> diop_bf_DN(13, -4)
[(3, 1), (-3, 1), (36, 10)]
>>> diop_bf_DN(986, 1)
[(49299, 1570)]
参见
diop_DN
参考文献
[R863] (1,2)
解决广义 Pell 方程 (x² - D*y² = N),John P. Robertson,2004 年 7 月 31 日,第 15 页。web.archive.org/web/20160323033128/http://www.jpr2718.org/pell.pdf
sympy.solvers.diophantine.diophantine.transformation_to_DN(eq)
此函数将一般二次方程 (ax² + bxy + cy² + dx + ey + f = 0) 转换为更易处理的形式 (X² - DY² = N)。
解释
这用于通过转换将一般二次方程解决为后一种形式。更详细的转换信息请参考[R864]。此函数返回一个元组 (A, B),其中 A 是一个 2 X 2 矩阵,B 是一个 2 X 1 矩阵,使得,
Transpose([x y]) = A * Transpose([X Y]) + B
用法
transformation_to_DN(eq): 其中 eq 是要转换的二次方程。
示例
>>> from sympy.abc import x, y
>>> from sympy.solvers.diophantine.diophantine import transformation_to_DN
>>> 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 满足 Transpose((x y)) = A * Transpose((X Y)) + B。将这些值代入 (x) 和 (y) 并进行简化,得到形如 (x² - Dy² = N) 的方程。
>>> from sympy.abc import X, Y
>>> from sympy import Matrix, simplify
>>> 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
接下来,我们将这些公式代入 (x) 和 (y) 并执行 simplify()。
>>> eq = simplify((x**2 - 3*x*y - y**2 - 2*y + 1).subs(zip((x, y), (u, v))))
>>> eq
X**2/676 - Y**2/52 + 17/13
通过适当地乘以分母,我们可以得到标准形式的 Pell 方程。
>>> eq * 676
X**2 - 13*Y**2 + 884
如果只需要最终方程,则可以使用 find_DN()。
另请参阅
find_DN
参考文献
[R864] (1,2)
解方程 (ax² + bxy + cy² + dx + ey + f = 0),John P.Robertson,2003 年 5 月 8 日,第 7 - 11 页。web.archive.org/web/20160323033111/http://www.jpr2718.org/ax2p.pdf
sympy.solvers.diophantine.diophantine.transformation_to_normal(eq)
返回转换矩阵,将一般三元二次方程 eq ((ax² + by² + cz² + dxy + eyz + fxz)) 转换为没有交叉项的形式:(ax² + by² + cz² = 0)。这不用于解决三元二次方程,仅仅是为了完整性而实现的。
sympy.solvers.diophantine.diophantine.find_DN(eq)
此函数返回简化形式的元组 ((D, N)),即 (x² - Dy² = N),对应于一般二次方程 (ax² + bxy + cy² + dx + ey + f = 0)。
解决一般二次方程等效于解决方程 (X² - DY² = N) 并通过使用 transformation_to_DN() 返回的转换矩阵转换解。
用法
find_DN(eq): 其中 eq 是要转换的二次方程。
示例
>>> from sympy.abc import x, y
>>> from sympy.solvers.diophantine.diophantine import find_DN
>>> find_DN(x**2 - 3*x*y - y**2 - 2*y + 1)
(13, -884)
输出的解释是,我们通过使用 transformation_to_DN() 返回的转换来转换 (x² - 3xy - y² - 2y + 1) ,得到 (X² -13Y² = -884)。
另请参阅
transformation_to_DN
参考文献
[R865]
解决方程 (ax² + bxy + cy² + dx + ey + f = 0),John P.Robertson,2003 年 5 月 8 日,第 7 - 11 页。web.archive.org/web/20160323033111/http://www.jpr2718.org/ax2p.pdf
sympy.solvers.diophantine.diophantine.diop_ternary_quadratic(eq, parameterize=False)
解决一般的二次三元形式,(ax² + by² + cz² + fxy + gyz + hxz = 0)。
返回一个元组 ((x, y, z)),它是上述方程的一个基本解。如果没有解,则返回 ((None, None, None))。
用法
diop_ternary_quadratic(eq): 返回一个包含 eq 的基本解的元组。
详情
eq 应该是三个变量中二次齐次表达式,假定其为零。
示例
>>> 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²k, \ 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.ntheory.factor_.core
sympy.solvers.diophantine.diophantine.descent(A, B)
使用拉格朗日下降法和格点约简,返回一个非平凡解((x, y, z)),使得 (x² = Ay² + Bz²)。这里假定 (A) 和 (B) 是使这样的解存在的有效值。
该算法比普通的拉格朗日下降算法更快,因为使用了高斯约简。
示例
>>> 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)
参考文献
[R866]
Cremona, J. E., Rusin, D. (2003). Rational Conics 的有效解法。《计算数学》,72(243),1417-1441。doi.org/10.1090/S0025-5718-02-01480-1
sympy.solvers.diophantine.diophantine.diop_general_pythagorean(eq, param=m)
解决一般的勾股方程,(a_{1}²x_{1}² + a_{2}²x_{2}² + . . . + a_{n}²x_{n}² - a_{n + 1}²x_{n + 1}² = 0)。
返回一个包含按输入变量相同顺序排序的参数化解的元组。
用法
diop_general_pythagorean(eq, param):这里 eq 是一个被假定为零的一般勾股方程,param 是用于构造其他参数的基础参数。
示例
>>> 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}² + x_{2}² + . . . + x_{n}² - k = 0)。
返回最多limit个解。
用法
general_sum_of_squares(eq, limit):这里eq是一个被假定为零的表达式。同时,eq应该是这种形式,(x_{1}² + x_{2}² + . . . + x_{n}² - k = 0)。
详情
当 (n = 3) 时,如果 (k = 4^a(8m + 7)) 对某些 (a, m \in Z) 成立,则没有解。详见[R867]了解更多细节。
示例
>>> 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)}
参考文献
[R867]
代表一个整数作为三个平方和的和,[在线],可参考:www.proofwiki.org/wiki/Integer_as_Sum_of_Three_Squares
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个解。
用法
general_sum_of_even_powers(eq, limit):这里 eq 是一个假设为零的表达式。此外,eq 应该是形如 (x_{1}^e + x_{2}^e + . . . + x_{n}^e - k = 0) 的形式。
示例
>>> 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)}
另请参阅
power_representation
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)。
用法
power_representation(n, p, k, zeros):将非负数 n 表示为 k 个 p 次幂的和。如果 zeros 为 true,则允许解包含零。
示例
>>> 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) 的分区。
解释
(n) 的一个分区是一组加起来等于 (n) 的正整数。例如,3 的分区有 3,1 + 2,1 + 1 + 1。分区以元组的形式返回。如果 k 等于 None,则返回所有可能的分区,而不考虑其大小;否则只返回大小为 k 的分区。如果将 zero 参数设置为 True,则在每个小于 k 大小的分区末尾添加适当数量的零。
zero 参数仅在 k 不为 None 时考虑。当分区结束时,最后的 (next()) 调用将引发 StopIteration 异常,因此应始终在 try-except 块中使用此函数。
细节
partition(n, k):这里 n 是一个正整数,k 是分区的大小,也是正整数。
示例
>>> 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)
返回一个 3-元组 ((a, b, c)),使得 (a² + b² + c² = n) 并且 (a, b, c \geq 0)。
如果 (n = 4^a(8m + 7)) 对于某些 (a, m \in \mathbb{Z}),则返回 None。详细信息请参见 [R868]。
参数:
n :整数
非负整数
返回:
(int, int, int) | None :满足 a**2 + b**2 + c**2 = n 的三元组非负整数 (a, b, c)。
a、b、c 按升序排列。如果没有这样的
(a,b,c),则返回None。
抛出:
数值错误
如果
n是负整数
示例
>>> from sympy.solvers.diophantine.diophantine import sum_of_three_squares
>>> sum_of_three_squares(44542)
(18, 37, 207)
另请参阅
power_representation
sum_of_three_squares(n) 是 power_representation(n, 2, 3, zeros=True) 输出的解之一。
参考
[R868] (1,2)
将一个数表示为三个平方的和,[在线],可用:schorn.ch/lagrange.html
sympy.solvers.diophantine.diophantine.sum_of_four_squares(n)
返回一个 4-元组 ((a, b, c, d)),使得 (a² + b² + c² + d² = n)。这里 (a, b, c, d \geq 0)。
参数:
n :整数
非负整数
返回:
(int, int, int, int):满足 a**2 + b**2 + c**2 + d**2 = n 的 4-元组非负整数 (a, b, c, d)。
a、b、c、d 按升序排列。
引发:
数值错误
如果
n是负整数
示例
>>> 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)
参见
power_representation
sum_of_four_squares(n) 是由 power_representation(n, 2, 4, zeros=True) 输出的解之一
参考文献
[R869]
表示一个数作为四个平方的和,[在线],可访问:schorn.ch/lagrange.html
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)。
用法
power_representation(n, p, k, zeros): 将非负数 n 表示为 k 个 p 次幂的和。如果 zeros 为真,则允许解包含零。
示例
>>> 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 在其因数分解中的每个形式为 4k + 3 的素数具有偶重数时,n 才能被写成两个平方的和。如果 n 是素数,则仅当它为 4k + 1 形式时,才能将其写成两个平方的和。
-
如果 k == 3,则只要 n 不具有 4**m*(8*k + 7) 的形式,n 就可以被写成平方的和。
-
所有整数都可以写成 4 个平方的和。
-
如果 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.utilities.iterables.signed_permutations
sympy.solvers.diophantine.diophantine.merge_solution(var, var_t, solution)
这用于从子方程的解构建完整的解决方案。
解释
例如,当解方程 ((x - y)(x² + y² - z²) = 0) 时,可以分别独立找到方程 (x - y = 0) 和 (x² + y² - z²) 的解。 (x - y = 0) 的解为 ((x, y) = (t, t))。但是在输出原始方程的解时,应为 (x - y = 0) 的解引入一个值为 z 的参数。此函数将 ((t, t)) 转换为 ((t, t, n_{1})),其中 (n_{1}) 是整数参数。
sympy.solvers.diophantine.diophantine.divisible(a, b)
如果 a 能被 b 整除则返回 (True),否则返回 (False)。
sympy.solvers.diophantine.diophantine.PQa(P_0, Q_0, D)
返回解决 Pell 方程所需的有用信息。
Explanation
与 (\frac{P + \sqrt{D}}{Q}) 的连分数表示相关的六个整数序列被定义,即 {(P_{i})}, {(Q_{i})}, {(a_{i})},{(A_{i})}, {(B_{i})}, {(G_{i})}。PQa() 以与上述顺序相同的 6 元组返回这些值。更详细的信息请参见 [R870]。
使用
PQa(P_0, Q_0, D): P_0, Q_0 和 D 是整数,分别对应于连分数 (\frac{P_{0} + \sqrt{D}}{Q_{0}}) 中的 (P_{0}), (Q_{0}) 和 (D)。同时假设 (P_{0}² == D mod(|Q_{0}|)),且 (D) 是无平方因子。
Examples
>>> 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)
References
[R870] (1,2)
解决广义 Pell 方程 (x² - Dy² = N),John P. Robertson, 2004 年 7 月 31 日,第 4 - 8 页。web.archive.org/web/20160323033128/http://www.jpr2718.org/pell.pdf
sympy.solvers.diophantine.diophantine.equivalent(u, v, r, s, D, N)
如果两个解 ((u, v)) 和 ((r, s)) 满足 (x² - Dy² = N) 并属于同一等价类,则返回 True,否则返回 False。
Explanation
对于上述方程的两个解 ((u, v)) 和 ((r, s)),它们属于相同等价类当且仅当 ((ur - Dvs)) 和 ((us - vr)) 都能被 (N) 整除。参见引用 [R871]。不会对是否 ((u, v)) 和 ((r, s)) 实际上是方程的解进行测试。用户应当注意这一点。
Usage
equivalent(u, v, r, s, D, N): ((u, v)) 和 ((r, s)) 是方程 (x² - Dy² = N) 的两个解,涉及的所有参数都是整数。
Examples
>>> from sympy.solvers.diophantine.diophantine import equivalent
>>> equivalent(18, 5, -18, -5, 13, -1)
True
>>> equivalent(3, 1, -18, 393, 109, -4)
False
References
[R871] (1,2)
解决广义 Pell 方程 (x² - D*y² = N),John P. Robertson, 2004 年 7 月 31 日,第 12 页。web.archive.org/web/20160323033128/http://www.jpr2718.org/pell.pdf
sympy.solvers.diophantine.diophantine.parametrize_ternary_quadratic(eq)
返回三元二次方程 eq 的参数化一般解,其形式为 (ax² + by² + cz² + fxy + gyz + hxz = 0)。
Examples
>>> 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)
Notes
考虑前两个参数解中的 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)。
参考文献
[R872]
Diophantine 方程的算法解决,Nigel P. Smart,伦敦数学学会学生文集 41,剑桥大学出版社,剑桥,1998 年。
sympy.solvers.diophantine.diophantine.diop_ternary_quadratic_normal(eq, parameterize=False)
解二次三元丢番图方程 (ax² + by² + cz² = 0)。
解释
这里的系数 (a)、(b) 和 (c) 应为非零。否则方程将成为二次二进制或单变量方程。如果可解,返回满足给定方程的元组 ((x, y, z))。如果方程没有整数解,则返回 ((None, None, None))。
使用方法
diop_ternary_quadratic_normal(eq): 其中eq是形如 (ax² + by² + cz² = 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² = Ax² + By²) 的非平凡解;如果没有这样的解,则返回 None。
参数:
A : 整数
B : 整数
非零整数
返回:
(int, int, int) | None : 一个元组 ((w_0, x_0, y_0)),它是上述方程的解。
示例
>>> from sympy.solvers.diophantine.diophantine import ldescent
>>> ldescent(1, 1) # w² = x² + y²
(1, 1, 0)
>>> ldescent(4, -7) # w² = 4x² - 7y²
(2, -1, 0)
这意味着 (x = -1, y = 0) 和 (w = 2) 是方程 (w² = 4x² - 7y²) 的解。
>>> ldescent(5, -1) # w² = 5x² - y²
(2, 1, -1)
参考资料
[R873]
Diophantine 方程的算法解决,Nigel P. Smart,伦敦数学学会学生文集 41,剑桥大学出版社,剑桥,1998 年。
[R874]
Cremona, J. E., Rusin, D. (2003). Rational Conics 的高效解法。计算数学,72(243),1417-1441。doi.org/10.1090/S0025-5718-02-01480-1
sympy.solvers.diophantine.diophantine.gaussian_reduce(w: int, a: int, b: int) → tuple[int, int]
返回对应模 (b) 的同余方程 (X² - aZ² \equiv 0 \pmod{b}) 的简化解 ((x, z)),使得 (x² + |a|z²) 尽可能小。这里 w 是满足同余方程 (x² \equiv a \pmod{b}) 的解。
此函数仅用于 descent()。
参数:
w : 整数
w满足 (w² \equiv a \pmod{b})
a : 整数
无平方因子的非零整数
b : 整数
无平方因子的非零整数
解释
高斯约简可以找到任何范数的最短向量。因此,我们对向量 (u = (u_1, u_2)) 和 (v = (v_1, v_2)) 定义特殊的范数如下。
[u \cdot v := (wu_1 + bu_2)(wv_1 + bv_2) + |a|u_1v_1]
注意,给定映射 (f: (u_1, u_2) \to (wu_1 + bu_2, u_1)),(f((u_1,u_2))) 是方程 (X² - aZ² \equiv 0 \pmod{b}) 的解。换句话说,找到这个范数中的最短向量将给出一个 (X² + |a|Z²) 较小的解。该算法从基础向量 ((0, 1)) 和 ((1, 0)) 开始(分别对应解 ((b, 0)) 和 ((w, 1))),并找到最短向量。最短向量不一定对应最小的解,但由于 descent() 只需最小可能的解,这已经足够。
示例
>>> 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
参考
[R875]
高斯格点缩减 [在线]. 可访问: web.archive.org/web/20201021115213/http://home.ie.cuhk.edu.hk/~wkshum/wordpress/?p=404
[R876]
Cremona, J. E., Rusin, D. (2003). 有效解决有理圆锥曲线问题. 计算数学, 72(243), 1417-1441. doi.org/10.1090/S0025-5718-02-01480-1
sympy.solvers.diophantine.diophantine.holzer(x, y, z, a, b, c)
简化方程 (ax² + by² = cz²) 的解 ((x, y, z)),其中 (a, b, c > 0) 且 (z² \geq \mid ab \mid),至一个新的减少解 ((x', y', z')),使得 (z'² \leq \mid ab \mid)。
该算法是 Mordell 的缩减的一种解释,如 Cremona 和 Rusin 论文第 8 页所述 [R877],以及 Mordell 在参考文献 [R878] 中的工作。
参考文献
[R877] (1,2)
Cremona, J. E., Rusin, D. (2003). 有效解决有理圆锥曲线问题. 计算数学, 72(243), 1417-1441. doi.org/10.1090/S0025-5718-02-01480-1
[R878] (1,2)
丢番图方程, L. J. Mordell, 第 48 页.
sympy.solvers.diophantine.diophantine.prime_as_sum_of_two_squares(p)
将素数 (p) 表示为两个平方数之和;仅当素数满足 (p \equiv 1 \pmod{4}) 时可行。
参数:
p : 整数
一个满足 (p \equiv 1 \pmod{4}) 的素数
返回:
(int, int) | None : 正整数对 (x, y) 满足 x**2 + y**2 = p。
若
p不满足 (p \equiv 1 \pmod{4}),则返回 None。
抛出:
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)
参考
[R879]
将一个数表示为四个平方数之和 [在线]. 可访问: schorn.ch/lagrange.html
参见
sum_of_squares
sympy.solvers.diophantine.diophantine.sqf_normal(a, b, c, steps=False)
返回 (a', b', c'),即 (ax² + by² + cz² = 0) 的平方自由正则形式的系数,其中 (a', b', c') 是两两素数。如果 steps 为真,则还返回三个元组:(sq),(sqf) 和 ((a', b', c')),在去除 (gcd(a, b, c)) 后包含 (a),(b) 和 (c) 的平方因子。
对于 (ax² + by² + cz² = 0) 的解可以从 (a'x² + b'y² + c'z² = 0) 的解恢复。
示例
>>> from sympy.solvers.diophantine.diophantine import sqf_normal
>>> sqf_normal(2 * 3**2 * 5, 2 * 5 * 11, 2 * 7**2 * 11)
(11, 1, 5)
>>> sqf_normal(2 * 3**2 * 5, 2 * 5 * 11, 2 * 7**2 * 11, True)
((3, 1, 7), (5, 55, 11), (11, 1, 5))
参见
reconstruct
参考
[R880]
Legendre 定理,Lagrange 下降,public.csusm.edu/aitken_html/notes/legendre.pdf
sympy.solvers.diophantine.diophantine.reconstruct(A, B, z)
从等式的平方自由正常形式 (a'*x² + b'*y² + c'*z²) 的解的 (z) 值重建等价解的 (z) 值,其中 (a'), (b') 和 (c') 是平方自由的,且 (gcd(a', b', c') == 1)。
内部类
这些类旨在供丢番图模块内部使用。
class sympy.solvers.diophantine.diophantine.DiophantineSolutionSet(symbols_seq, parameters)
一特定丢番图方程的解集的容器。
基本表示是一组元组,代表每个解的解决方案。
参数:
symbols : 列表
原方程中的自由符号列表。
parameters: list
用于解决方案的参数列表。
示例
添加解决方案:
>>> 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)
特定丢番图方程类型的内部表示。
参数:
equation :
正在解决的丢番图方程。
free_symbols : 列表 (可选)
正在解决的符号。
属性
| total_degree : | 方程中所有项的最大度数 |
|---|---|
| homogeneous : | 方程是否包含度为 0 的项 |
| homogeneous_order : | 方程中是否包含任何符号的系数 |
| dimension : | 正在解决的符号数量 |
matches()
确定给定方程是否可以与特定方程类型匹配。
class sympy.solvers.diophantine.diophantine.Univariate(equation, free_symbols=None)
一元二次丢番图方程的表示。
一元二次丢番图方程是一个形如 (a_{0} + a_{1}x + a_{2}x² + .. + a_{n}x^n = 0) 的方程,其中 (a_{1}, a_{2}, ..a_{n}) 是整数常数,(x) 是整数变量。
示例
>>> 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}) 是整数变量。
示例
>>> 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 = -3t_0 - 5 和 y = -2t_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² + Bxy + Cy² + Dx + Ey + F = 0) 的方程,其中 (A, B, C, D, E, F) 是整数常数,(x) 和 (y) 是整数变量。
示例
>>> 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)}
参考
[R881]
解决 Ax² + Bxy + Cy² + Dx + Ey + F = 0 的方法,[在线],可用:www.alpertron.com.ar/METHODS.HTM
[R882]
解方程(ax²+ bxy + cy² + dx + ey + f= 0),[在线],可参见:web.archive.org/web/20160323033111/http://www.jpr2718.org/ax2p.pdf
class sympy.solvers.diophantine.diophantine.InhomogeneousTernaryQuadratic(equation, free_symbols=None)
表示非均匀三元二次方程。
目前还没有为这种方程类型实现求解器。
class sympy.solvers.diophantine.diophantine.HomogeneousTernaryQuadraticNormal(equation, free_symbols=None)
表示均匀三元二次正规丢番图方程。
示例
>>> 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)
表示均匀三元二次丢番图方程。
示例
>>> 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)
表示非均匀一般二次方程。
目前还没有为这种方程类型实现求解器。
class sympy.solvers.diophantine.diophantine.HomogeneousGeneralQuadratic(equation, free_symbols=None)
表示均匀一般二次方程。
目前还没有为这种方程类型实现求解器。
class sympy.solvers.diophantine.diophantine.GeneralSumOfSquares(equation, free_symbols=None)
表示丢番图方程
(x_{1}² + x_{2}² + . . . + x_{n}² - k = 0).
详情
当(n = 3)时,如果(k = 4^a(8m + 7)),其中(a, m \in Z),则没有解。参考[R883]获取更多详情。
示例
>>> 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)]
参考文献
[R883] (1,2)
将整数表示为三个平方数的和,[在线],可参见:www.proofwiki.org/wiki/Integer_as_Sum_of_Three_Squares
class sympy.solvers.diophantine.diophantine.GeneralPythagorean(equation, free_symbols=None)
表示一般的毕达哥拉斯方程,(a_{1}²x_{1}² + a_{2}²x_{2}² + . . . + a_{n}²x_{n}² - a_{n + 1}²x_{n + 1}² = 0)。
示例
>>> 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)
表示一个三次丢番图方程。
一个三次丢番图方程是一个形式为(f(x, y) = r)的三次多项式,其中(x)和(y)是整数,(r)是有理数。
目前还没有为这种方程类型实现求解器。
示例
>>> 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)是一个偶数整数幂。
示例
>>> 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)}
不等式求解器
对于一般情况应使用reduce_inequalities()。其他函数是专用操作的子类别,将根据需要由reduce_inequalities内部调用。
注意
对于一个以解代数方式减少一个或多个不等式的单变量友好指南,请参阅减少不等式的解数学含义。
注意
以下一些示例使用poly(),它只是将表达式转换为多项式;它不改变表达式的数学含义。
sympy.solvers.inequalities.solve_rational_inequalities(eqs)
用有理系数解有理不等式系统。
示例
>>> from sympy.abc import x
>>> from sympy import solve_rational_inequalities, Poly
>>> solve_rational_inequalities([[
... ((Poly(-x + 1), Poly(1, x)), '>='),
... ((Poly(-x + 1), Poly(1, x)), '<=')]])
{1}
>>> solve_rational_inequalities([[
... ((Poly(x), Poly(1, x)), '!='),
... ((Poly(-x + 1), Poly(1, x)), '>=')]])
Union(Interval.open(-oo, 0), Interval.Lopen(0, 1))
参见
solve_poly_inequality
sympy.solvers.inequalities.solve_poly_inequality(poly, rel)
用有理系数解多项式不等式。
示例
>>> from sympy import solve_poly_inequality, Poly
>>> from sympy.abc import x
>>> solve_poly_inequality(Poly(x, x, domain='ZZ'), '==')
[{0}]
>>> solve_poly_inequality(Poly(x**2 - 1, x, domain='ZZ'), '!=')
[Interval.open(-oo, -1), Interval.open(-1, 1), Interval.open(1, oo)]
>>> solve_poly_inequality(Poly(x**2 - 1, x, domain='ZZ'), '==')
[{-1}, {1}]
参见
solve_poly_inequalities
sympy.solvers.inequalities.solve_poly_inequalities(polys)
用有理系数解多项式不等式。
示例
>>> from sympy import Poly
>>> from sympy.solvers.inequalities import solve_poly_inequalities
>>> from sympy.abc import x
>>> solve_poly_inequalities(((
... Poly(x**2 - 3), ">"), (
... Poly(-x**2 + 1), ">")))
Union(Interval.open(-oo, -sqrt(3)), Interval.open(-1, 1), Interval.open(sqrt(3), oo))
sympy.solvers.inequalities.reduce_rational_inequalities(exprs, gen, relational=True)
用有理系数解有理不等式系统。
示例
>>> from sympy import Symbol
>>> from sympy.solvers.inequalities import reduce_rational_inequalities
>>> x = Symbol('x', real=True)
>>> reduce_rational_inequalities([[x**2 <= 0]], x)
Eq(x, 0)
>>> reduce_rational_inequalities([[x + 2 > 0]], x)
-2 < x
>>> reduce_rational_inequalities([[(x + 2, ">")]], x)
-2 < x
>>> reduce_rational_inequalities([[x + 2]], x)
Eq(x, -2)
此函数找到非无限解集,因此如果未知符号声明为扩展实数而不是实数,则结果可能包括有限性条件:
>>> y = Symbol('y', extended_real=True)
>>> reduce_rational_inequalities([[y + 2 > 0]], y)
(-2 < y) & (y < oo)
sympy.solvers.inequalities.reduce_abs_inequality(expr, rel, gen)
解嵌套绝对值不等式。
示例
>>> from sympy import reduce_abs_inequality, Abs, Symbol
>>> x = Symbol('x', real=True)
>>> reduce_abs_inequality(Abs(x - 5) - 3, '<', x)
(2 < x) & (x < 8)
>>> reduce_abs_inequality(Abs(x + 2)*3 - 13, '<', x)
(-19/3 < x) & (x < 7/3)
参见
reduce_abs_inequalities
sympy.solvers.inequalities.reduce_abs_inequalities(exprs, gen)
解嵌套绝对值不等式系统。
示例
>>> from sympy import reduce_abs_inequalities, Abs, Symbol
>>> x = Symbol('x', extended_real=True)
>>> reduce_abs_inequalities([(Abs(3*x - 5) - 7, '<'),
... (Abs(x + 25) - 13, '>')], x)
(-2/3 < x) & (x < 4) & (((-oo < x) & (x < -38)) | ((-12 < x) & (x < oo)))
>>> reduce_abs_inequalities([(Abs(x - 4) + Abs(3*x - 5) - 7, '<')], x)
(1/2 < x) & (x < 4)
参见
reduce_abs_inequality
sympy.solvers.inequalities.reduce_inequalities(inequalities, symbols=[])
用有理系数解不等式系统。
示例
>>> from sympy.abc import x, y
>>> from sympy import reduce_inequalities
>>> reduce_inequalities(0 <= x + 3, [])
(-3 <= x) & (x < oo)
>>> reduce_inequalities(0 <= x + y*2 - 1, [x])
(x < oo) & (x >= 1 - 2*y)
sympy.solvers.inequalities.solve_univariate_inequality(expr, gen, relational=True, domain=Reals, continuous=False)
解实数单变量不等式。
参数:
表达式:关系型
目标不等式
gen:符号
解不等式的变量
关系型:布尔值
预期输出为关系类型或否
定义域:集合
解方程的定义域
连续: 布尔值
如果已知表达式在给定域上连续(因此不需要调用 continuous_domain()),则返回 True。
异常:
未实现错误
由于
sympy.solvers.solveset.solvify()的限制,无法确定不等式的解。
注释
目前,由于 sympy.solvers.solveset.solvify() 的限制,我们无法解决所有不等式。此外,对于三角不等式返回的解受其周期间隔的限制。
示例
>>> from sympy import solve_univariate_inequality, Symbol, sin, Interval, S
>>> x = Symbol('x')
>>> solve_univariate_inequality(x**2 >= 4, x)
((2 <= x) & (x < oo)) | ((-oo < x) & (x <= -2))
>>> solve_univariate_inequality(x**2 >= 4, x, relational=False)
Union(Interval(-oo, -2), Interval(2, oo))
>>> domain = Interval(0, S.Infinity)
>>> solve_univariate_inequality(x**2 >= 4, x, False, domain)
Interval(2, oo)
>>> solve_univariate_inequality(sin(x) > 0, x, relational=False)
Interval.open(0, pi)
参见
sympy.solvers.solveset.solvify
solver 返回 solveset 解决方案与 solve 的输出 API