Get a value from solution set returned as finiteset by Sympy

泪湿孤枕 提交于 2019-11-30 17:24:14

I found the sympy library way in this link http://docs.sympy.org/latest/tutorial/manipulation.html

Use .args atribute in the function or result object. If I have a function:

>>>func = Eq(u(x),−x+sin(x)) 
>>>func
u(x) = -x + sin(x)
>>>func.args[0] 
u(x)
>>>func.args[1]
-x+sin(x)

The same applies for a result that is a finite set type.

You can use iter to get an iterator based on the set, and then next to return one element of that set (if you only need one element).

Example:

from sympy import *
var('x y')
sol = linsolve([x+y-2, 2*x-3*y], x, y)
(x0, y0) = next(iter(sol))

Now x0 is 6/5 and y0 is 4/5.

Weird. There's no description anywhere how to use the results of linsolve.

Even the specs only test the result set as a whole, without checking the elements separately.

Sequence unpacking

If you know that the system of equation admits at least one solution, you can use sequence unpacking with a trailing comma before the assignment :

>>> from sympy import linsolve, symbols, solve, Rational
>>> a1, a2 = symbols('a1 a2')
>>> equations = [-3*a1/10 - 3*a2/20 + Rational(1, 12), -3*a1/20 - 13*a2/105 + Rational(1, 20)]
>>> equations
[-3*a1/10 - 3*a2/20 + 1/12, -3*a1/20 - 13*a2/105 + 1/20]
>>> linsolve(equations, a1, a2)
{(71/369, 7/41)}
>>> solution, = linsolve(equations, a1, a2)
>>> solution
(71/369, 7/41)

This syntax will also work if there is an infinity of solution:

>>> solution, = linsolve([a1, a1], a1, a2)
>>> solution
(0, a2)

But it will fail if there are no solution:

>>> solution, = linsolve([a1 - 1, a1 - 2], a1, a2)
ValueError: not enough values to unpack (expected 1, got 0)

which might be the desired behaviour.

Iterate over the solutions:

Another possibility is to simply iterate over the solutions:

>>> for solution in linsolve(equations, a1, a2):
...     print(solution)
... 
(71/369, 7/41)

Nothing happens if there's no solution:

>>> for solution in linsolve([a1 - 1, a1 - 2], a1, a2):
...     print(solution)
... 

solve instead of linsolve

You could also use solve instead of linsolve, even though it's not recommended by the project because it can output different types:

>>> solve(equations, a1, a2)
{a1: 71/369, a2: 7/41}
>>> solve([a1 - 1, a1 - 2], a1, a2)
[]

A slightly more general solution is to simply convert the FiniteSet into a standard python list

>>> a=list(linsolve(lista,a1,a2))
>>> a
[(71/369, 7/41)]

Then you can extract elements using standard indexing — in this case a[0]. But then if you get multiple solutions, you can just pull out the one you want.

You can use tuple in combination with argument unpacking:

var('x y z')
eqs = [ x + y + z - 1, x + y + 2*z - 3 ]
sol = linsolve( eqs, x, y, z )
(x0, y0, z0) = tuple(*sol)

Now you can check the solution with:

eqs[0].subs( [(x, x0), (y, y0), (z, z0)] )
eqs[1].subs( [(x, x0), (y, y0), (z, z0)] )
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!