使用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]

付出了很多努力,可能不值得,但是哦,好吧。