英文:
Sympy solve fails to find nullspace of easy equation
问题
You may be using solve
correctly, but it's possible that the equations you provided are more complex than what sympy
can handle easily. The complexity of equations and their solutions can vary, and sympy
may not always find simplified solutions as you expect. You might consider manually simplifying or manipulating the equations to get the specific solution you desire.
英文:
I am trying to find the nullspace of various function-sets with pythons module sympy
. It managed to find the solution to some sets like
{(x - 1)!, x * (x - 2)!, (x - 2)!}
My code is
from sympy import solve, factorial
from sympy.abc import a, b, c, x
eq = a * factorial(x - 1) + b * x * factorial(x - 2) + c * factorial(x - 2)
print(solve(eq, a, b, c, set=True)) # output: ([a, b, c], {((-b*x + b - c)/x, b, c)})
eq = -b * x + b - c - a * x
print(solve(eq, a, b, c, set=True)) # output: ([a, b], {(-c, c)})
However, it struggled with the set
{upper_gamma(x, -1), upper_gamma(x - 1, -1), x * upper_gamma(x - 1, -1), (-1) ^ x}
Which is fair enough, even wolfram-alpha cannot find the solution. However, I was surprised when it also failed on the simplified problem
{(x - 1) * y - z, y, x * y, z}
My code was again the same
eq = a * (x-1) * y - a * z + b * y + c * x * y + d * z
print(solve(eq, a, b, c, d, set=True)) # output: ([a, b, c, d], {((b*y + c*x*y + d*z)/(-x*y + y + z), b, c, d)})
I expected the solution ([a, b, c], {d, d, -d})
.
Am I using solve
wrongly or is the equation to hard for this solver?
答案1
得分: 4
You are depending on an implicit behaviour of solve
that given a single equation not in a list that is linear in all unknowns it will assume that you are looking for an undetermined coefficients solution which is semantically something quite different from an ordinary solution.
这里涉及到您依赖 solve
的一种隐式行为,即对于一个不在列表中的单一方程,只要它在所有未知数上是线性的,solve
会假定您正在寻找一个待定系数的解决方案,这在语义上与普通解决方案有很大不同。
The difference between these can be seen like:
这两者之间的区别可以如下所示:
Here the first case is returning values of a
and b
that can make the expression identically zero for all possible values of x
and y
. The second case is treating x
and y
as being fixed but unspecified parameters and returning the set of possible values for a
and b
as functions of the symbolic parameters x
and y
that could make the expression zero.
在这里,第一个情况返回了可以使表达式在所有可能的 x
和 y
值上恒等于零的 a
和 b
的值。而第二种情况将 x
和 y
视为已固定但未指定的参数,并返回 a
和 b
的可能值集合,这些值是符号参数 x
和 y
的函数,可以使表达式为零。
Conceptually these are two very different things and it would be better if solve did not mix them up in a single end-user function. The difference that you see is because your equation is being treated like the second case rather than the first. That being said I cannot reproduce the output you report with the most recent version of SymPy (1.11.1):
从概念上讲,这两者是非常不同的,如果 solve
不在单个最终用户函数中混合它们,那将更好。您看到的差异是因为您的方程被视为第二种情况,而不是第一种情况。话虽如此,我无法在最新版本的 SymPy(1.11.1)中复现您报告的输出:
If I pass eq
in a list then I do see it:
如果我将 eq
放在列表中,我会看到它:
In any case it is best not to depend on using solve
this way. I suggest to use solve
only for its primary purpose which is case 2 above and for that it should always be called with a list (even for a single equation).
无论如何,最好不要依赖于以这种方式使用 solve
。我建议仅将 solve
用于其主要目的,即上述的第2种情况,而对于这种情况,它应始终使用列表调用(即使是单个方程也要如此)。
There is instead a function solve_undetermined_coeffs
which is the explicit function for doing what you want to do here:
相反,有一个名为 solve_undetermined_coeffs
的函数,它是执行您在此处想要执行的操作的显式函数:
In [9]: solve_undetermined_coeffs(eq, [a, b, c, d], [x, y, z])
Out[9]: {a: d, b: d, c: -d}
英文:
You are depending on an implicit behaviour of solve
that given a single equation not in a list that is linear in all unknowns it will assume that you are looking for an undetermined coefficients solution which is semantically something quite different from an ordinary solution.
The difference between these can be seen like:
In [5]: solve(a*x + b*y, a, b, set=True)
Out[5]: ([a, b], {(0, 0)})
In [6]: solve([a*x + b*y], a, b, set=True)
Out[6]:
⎛ ⎧⎛-b⋅y ⎞⎫⎞
⎜[a, b], ⎨⎜─────, b⎟⎬⎟
⎝ ⎩⎝ x ⎠⎭⎠
Here the first case is returning values of a
and b
that can make the expression identically zero for all possible values of x
and y
. The second case is treating x
and y
as being fixed but unspecified parameters and returning the set of possible values for a
and b
as functions of the symbolic parameters x
and y
that could make the expression zero.
Conceptually these are two very different things and it would be better if solve did not mix them up in a single end-user function. The difference that you see is because your equation is being treated like the second case rather than the first. That being said I cannot reproduce the output you report with the most recent version of SymPy (1.11.1):
In [1]: a, b, c, d = symbols('a, b, c, d')
In [2]: eq = a * (x-1) * y - a * z + b * y + c * x * y + d * z
...: print(solve(eq, a, b, c, d, set=True)) # output: ([a, b, c, d], {((b*y + c*x*y + d*z)/(-x*y + y
...: + z), b, c, d)})
([a, b, c, d], {(d, d, -d, d)})
If I pass eq
in a list then I do see it:
In [7]: solve([eq], a, b, c, d, set=True)
Out[7]:
⎛ ⎧⎛ b⋅y c⋅x⋅y d⋅z ⎞⎫⎞
⎜[a, b, c, d], ⎨⎜- ─────────── - ─────────── - ───────────, b, c, d⎟⎬⎟
⎝ ⎩⎝ x⋅y - y - z x⋅y - y - z x⋅y - y - z ⎠⎭⎠
In any case it is best not to depend on using solve
this way. I suggest to use solve
only for its primary purpose which is case 2 above and for that it should always be called with a list (even for a single equation).
There is instead a function solve_undetermined_coeffs
which is the explicit function for doing what you want to do here:
In [9]: solve_undetermined_coeffs(eq, [a, b, c, d], [x, y, z])
Out[9]: {a: d, b: d, c: -d}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论