使用sympy solve命令时显示一定范围内的解
Displaying solutions within a certain range when using sympy solve command
我可以被认为是 python 和编码的新手,所以请原谅我的无知。
我正在尝试求解 python 中的三角函数系统,我正在使用 sympy 中的 solve
命令来解决这个问题。但是,这种方法 returns 只有有限数量的解决方案,在这种特殊情况下有两个。
我已经通读了文档,似乎要使用 solveset
来代替所有解决方案的表达式。但是,我不想显示所有的解决方案,而是只显示一定范围内的有限数量。
示例如下:
from sympy import *
x, y = symbols('x, y')
eq1 = Eq(y - sin(x), 0)
eq2 = Eq(y - cos(x), 0)
sol = solve([eq1, eq2], [x, y])
print(sol)
只有 returns 正 x 范围内的前两个解。
我该怎么做才能显示x范围[-2pi,2pi]内的所有解?
我希望它们以明确的形式出现,而不是用一些乘数来表示,因为我需要将它们转换成数字形式。
提前致谢。
通过使用 solveset
,您可以使用 domain
参数限制解决方案。要评估数值结果,请使用 .evalf()
或 another similar method。
from sympy import Interval, symbols, solveset, sin, cos, pi
x = symbols('x')
sol = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
print(sol)
print(sol.evalf())
输出
FiniteSet(-7*pi/4, -3*pi/4, pi/4, 5*pi/4)
FiniteSet(-5.49778714378214, -2.35619449019234, 0.785398163397448, 3.92699081698724)
希望对您有所帮助!
多亏了@kampmani 的绝妙建议,才有可能实现预期的结果。
首先,FiniteSet
元素没有索引,无法使用,因此 FiniteSet
必须转换为 list
:
solx_array = []
#
#
#
solx = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
solx_array=list(solx)
下一步是在给定 x 坐标的情况下找到交点的 y 坐标。最终代码看起来应该与此类似:
from sympy import Interval, symbols, solveset, sin, cos, pi
sol_array = []
x = symbols('x')
solx = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
solx_array=list(solx)
for i in range(len(solx_array)):
soly = cos(solx_array[i])
sol_array.append(str(solx_array[i] + soly))
for i in range(len(sol_array)):
print(sol_array[i])
仍然不知道如何将结果转换为数字形式,非常感谢任何想法。
SymPy 真的可以让你陷入困境。我同意 kampmani 的解决方案,前提是您可以自己轻松解决 y
。然而,在更一般的情况下和更高的维度中,他的解决方案不成立。
例如,下面会稍微棘手一些:
eq1 = Eq(z - x*y, 0)
eq2 = Eq(z - cos(x) - sin(y), 0)
eq3 = Eq(z + x*y, 0)
所以我来了;用火箭筒杀死一只苍蝇。问题是人们能够将方程组简化为具有单个变量的单个方程。但是,如果您不能这样做(例如,如果它是一个更大的系统)怎么办?
这种情况下,需要用nonlinsolve
来求解方程组。但这并不直接提供数值解,也没有 domain
参数。
所以下面的代码解压了解决方案。它遍历解决方案集中的每个元组,并为元组中的每个组件找到数值解决方案。然后,为了获得完整列表,您需要每个组件的笛卡尔积。对解决方案集中的每个元组重复此操作。
以下应该适用于任何维度大于 1 的几乎任何方程组。它在边界为 domains
变量的立方体中生成数值解。
from sympy import *
import itertools # used for cartesian product
x, y, z = symbols('x y z', real=True)
domains = [Interval(-10, 10), Interval(-10, 10), Interval(-10, 10)] # The domain for each variable
eq1 = z - x*y
eq2 = z - cos(x) - sin(y)
eq3 = z + x*y
solutions = nonlinsolve([eq1, eq2, eq3], [x, y, z]) # the recommended function for this situation
print("---------Solution set----------")
print(solutions) # make sure the solution set is reasonable. If not, assertion error will occur
_n = Symbol("n", integer=True) # the solution set often seems to contain these symbols
numeric_solutions = []
assert isinstance(solutions, Set) # everything that I had tried resulted in a FiniteSet output
for solution in solutions.args: # loop through the different kinds of solutions
assert isinstance(solution, Tuple) # each solution should be a Tuple if in 2D or higher
list_of_numeric_values = [] # the list of lists of a single numerical value
for i, element in enumerate(solution):
if isinstance(element, Set):
numeric_values = list(element.intersect(domains[i]))
else: # assume it is an Expr
assert isinstance(element, Expr)
if _n.name in [s.name for s in element.free_symbols]: # if n is in the expression
# change our own _n to the solutions _n since they have different hidden
# properties and they cannot be substituted without having the same _n
_n = [s for s in element.free_symbols if s.name == _n.name][0]
numeric_values = [element.subs(_n, n)
for n in range(-10, 10) # just choose a bunch of sample values
if element.subs(_n, n) in domains[i]]
elif len(element.free_symbols) == 0: # we just have a single, numeric number
numeric_values = [element] if element in domains[i] else []
else: # otherwise we just have an Expr that depends on x or y
# we assume this numerical value is in the domain
numeric_values = [element]
# note that we may have duplicates, so we remove them with `set()`
list_of_numeric_values.append(set(numeric_values))
# find the resulting cartesian product of all our numeric_values
numeric_solutions += itertools.product(*list_of_numeric_values)
# remove duplicates again to be safe with `set()` but then retain ordering with `list()`
numeric_solutions = list(set(numeric_solutions))
print("--------`Expr` values----------")
for i in numeric_solutions:
print(list(i)) # turn it into a `list` since the output below is also a `list`.
print("--------`float` values---------")
for i in numeric_solutions:
print([N(j) for j in i]) # could have been converted into a `tuple` instead
特别是,它为新问题生成以下输出:
---------Solution set----------
FiniteSet((0, ImageSet(Lambda(_n, 2*_n*pi + 3*pi/2), Integers), 0))
--------`Expr` values----------
[0, -5*pi/2, 0]
[0, -pi/2, 0]
[0, 3*pi/2, 0]
--------`float` values---------
[0, -7.85398163397448, 0]
[0, -1.57079632679490, 0]
[0, 4.71238898038469, 0]
付出了很多努力,可能不值得,但是哦,好吧。
我可以被认为是 python 和编码的新手,所以请原谅我的无知。
我正在尝试求解 python 中的三角函数系统,我正在使用 sympy 中的 solve
命令来解决这个问题。但是,这种方法 returns 只有有限数量的解决方案,在这种特殊情况下有两个。
我已经通读了文档,似乎要使用 solveset
来代替所有解决方案的表达式。但是,我不想显示所有的解决方案,而是只显示一定范围内的有限数量。
示例如下:
from sympy import *
x, y = symbols('x, y')
eq1 = Eq(y - sin(x), 0)
eq2 = Eq(y - cos(x), 0)
sol = solve([eq1, eq2], [x, y])
print(sol)
只有 returns 正 x 范围内的前两个解。
我该怎么做才能显示x范围[-2pi,2pi]内的所有解?
我希望它们以明确的形式出现,而不是用一些乘数来表示,因为我需要将它们转换成数字形式。
提前致谢。
通过使用 solveset
,您可以使用 domain
参数限制解决方案。要评估数值结果,请使用 .evalf()
或 another similar method。
from sympy import Interval, symbols, solveset, sin, cos, pi
x = symbols('x')
sol = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
print(sol)
print(sol.evalf())
输出
FiniteSet(-7*pi/4, -3*pi/4, pi/4, 5*pi/4)
FiniteSet(-5.49778714378214, -2.35619449019234, 0.785398163397448, 3.92699081698724)
希望对您有所帮助!
多亏了@kampmani 的绝妙建议,才有可能实现预期的结果。
首先,FiniteSet
元素没有索引,无法使用,因此 FiniteSet
必须转换为 list
:
solx_array = []
#
#
#
solx = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
solx_array=list(solx)
下一步是在给定 x 坐标的情况下找到交点的 y 坐标。最终代码看起来应该与此类似:
from sympy import Interval, symbols, solveset, sin, cos, pi
sol_array = []
x = symbols('x')
solx = solveset(cos(x) - sin(x), x, domain=Interval(-2*pi, 2*pi))
solx_array=list(solx)
for i in range(len(solx_array)):
soly = cos(solx_array[i])
sol_array.append(str(solx_array[i] + soly))
for i in range(len(sol_array)):
print(sol_array[i])
仍然不知道如何将结果转换为数字形式,非常感谢任何想法。
SymPy 真的可以让你陷入困境。我同意 kampmani 的解决方案,前提是您可以自己轻松解决 y
。然而,在更一般的情况下和更高的维度中,他的解决方案不成立。
例如,下面会稍微棘手一些:
eq1 = Eq(z - x*y, 0)
eq2 = Eq(z - cos(x) - sin(y), 0)
eq3 = Eq(z + x*y, 0)
所以我来了;用火箭筒杀死一只苍蝇。问题是人们能够将方程组简化为具有单个变量的单个方程。但是,如果您不能这样做(例如,如果它是一个更大的系统)怎么办?
这种情况下,需要用nonlinsolve
来求解方程组。但这并不直接提供数值解,也没有 domain
参数。
所以下面的代码解压了解决方案。它遍历解决方案集中的每个元组,并为元组中的每个组件找到数值解决方案。然后,为了获得完整列表,您需要每个组件的笛卡尔积。对解决方案集中的每个元组重复此操作。
以下应该适用于任何维度大于 1 的几乎任何方程组。它在边界为 domains
变量的立方体中生成数值解。
from sympy import *
import itertools # used for cartesian product
x, y, z = symbols('x y z', real=True)
domains = [Interval(-10, 10), Interval(-10, 10), Interval(-10, 10)] # The domain for each variable
eq1 = z - x*y
eq2 = z - cos(x) - sin(y)
eq3 = z + x*y
solutions = nonlinsolve([eq1, eq2, eq3], [x, y, z]) # the recommended function for this situation
print("---------Solution set----------")
print(solutions) # make sure the solution set is reasonable. If not, assertion error will occur
_n = Symbol("n", integer=True) # the solution set often seems to contain these symbols
numeric_solutions = []
assert isinstance(solutions, Set) # everything that I had tried resulted in a FiniteSet output
for solution in solutions.args: # loop through the different kinds of solutions
assert isinstance(solution, Tuple) # each solution should be a Tuple if in 2D or higher
list_of_numeric_values = [] # the list of lists of a single numerical value
for i, element in enumerate(solution):
if isinstance(element, Set):
numeric_values = list(element.intersect(domains[i]))
else: # assume it is an Expr
assert isinstance(element, Expr)
if _n.name in [s.name for s in element.free_symbols]: # if n is in the expression
# change our own _n to the solutions _n since they have different hidden
# properties and they cannot be substituted without having the same _n
_n = [s for s in element.free_symbols if s.name == _n.name][0]
numeric_values = [element.subs(_n, n)
for n in range(-10, 10) # just choose a bunch of sample values
if element.subs(_n, n) in domains[i]]
elif len(element.free_symbols) == 0: # we just have a single, numeric number
numeric_values = [element] if element in domains[i] else []
else: # otherwise we just have an Expr that depends on x or y
# we assume this numerical value is in the domain
numeric_values = [element]
# note that we may have duplicates, so we remove them with `set()`
list_of_numeric_values.append(set(numeric_values))
# find the resulting cartesian product of all our numeric_values
numeric_solutions += itertools.product(*list_of_numeric_values)
# remove duplicates again to be safe with `set()` but then retain ordering with `list()`
numeric_solutions = list(set(numeric_solutions))
print("--------`Expr` values----------")
for i in numeric_solutions:
print(list(i)) # turn it into a `list` since the output below is also a `list`.
print("--------`float` values---------")
for i in numeric_solutions:
print([N(j) for j in i]) # could have been converted into a `tuple` instead
特别是,它为新问题生成以下输出:
---------Solution set----------
FiniteSet((0, ImageSet(Lambda(_n, 2*_n*pi + 3*pi/2), Integers), 0))
--------`Expr` values----------
[0, -5*pi/2, 0]
[0, -pi/2, 0]
[0, 3*pi/2, 0]
--------`float` values---------
[0, -7.85398163397448, 0]
[0, -1.57079632679490, 0]
[0, 4.71238898038469, 0]
付出了很多努力,可能不值得,但是哦,好吧。