Get a value from solution set returned as finiteset by Sympy

Question:

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'”

Answers:

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.

Answered By: user3717023

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.

Answered By: Mike

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 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)] )
Answered By: Stilunke

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)
[]
Answered By: Eric Duminil

FiniteSet has an args attribute that is a tuple (thanks for the correction)

https://github.com/sympy/sympy/issues/19689

Answered By: Ilya

I know this is an old thread, but in the interest of learning if you don’t want to convert the finiteset to a list use the following:

from sympy import *
x, y = symbols('x y')
z = solveset(x-y-1,x).args[0]  # returns 1st element of finiteset
sum = z.subs(y,10)

print(sum)
print(type(sum))

The result is:

11
<class 'sympy.core.numbers.Integer'>
Answered By: Luke Autry
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.