问题
I`m creating a script in Python Sympy library and trying to access the result returned by solveset() and linsolve() functions. My problem is that the object returned by these functions is of type finiteset and I want to select some results automaticaly to re-enter it in other equations. Any body could help me?
An example: I create a list of equations with two unknown variables:
>>> a1, a2 = symbols('a1, a2')
>>> eq2_1 = Eq(-3*a1/10 - 3*a2/20 + 1/12)
>>> eq2_2 = Eq(-3*a1/20 - 13*a2/105 + 1/20)
>>> lista = [eq2_1,eq2_2]
>>> str(lista)
[-3*a1/10 - 3*a2/20 + 1/12, -3*a1/20 - 13*a2/105 + 1/20]
Then a solve it with the linsolve() method.
>>> a = linsolve(lista,a1,a2)
>>> a
{(71/369, 7/41)}
The result is correct, but I'm unable to get these results in to a variable.
O tried dics, lists, tuples, indexing commands, but always return the error. "Finiteset objects has no attribute 'command'"
回答1:
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.
回答2:
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.
回答3:
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.
回答4:
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)
[]
回答5:
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)] )
来源:https://stackoverflow.com/questions/38418205/get-a-value-from-solution-set-returned-as-finiteset-by-sympy