Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ordering of roots in solveset #22843

Open
nickme68 opened this issue Jan 12, 2022 · 8 comments
Open

Ordering of roots in solveset #22843

nickme68 opened this issue Jan 12, 2022 · 8 comments
Labels

Comments

@nickme68
Copy link

I am not sure is it bug or feature, but it is not convenient. While solving quadratic equation (for example) solveset gives root in some order, when I convert its output to the tuple (for extracting particular root) the order of roots is changed.

s = solveset(x**2-2, x)
print(s)
print(tuple(s))

Output:

{-sqrt(2), sqrt(2)}
(sqrt(2), -sqrt(2))
@nickme68
Copy link
Author

If roots are integers, then orders are the same:

s = solveset(x**2-4, x)
print(s)
print(tuple(s))

Output:

{-2, 2}
(-2, 2)

@ThePauliPrinciple
Copy link
Contributor

Sets are not supposed to be ordered.
You could use SymPy's ordered to always obtain the same ordering for SymPy objects:

from sympy import *
from sympy.abc import x
s = solveset(x**2-2, x)
tuple(ordered(s))

@nickme68
Copy link
Author

"Sets are not supposed to be ordered" - I understand it! But why two serializations of the same set (for print or display and for converting to the tuple or list) use different orderings? Looks a little bit inconsistently!

@nickme68
Copy link
Author

My use case:

sol = solveset(x**2 - 2, x) # solve given equation
display(sol) # -> {-sqrt(2), sqrt(2)}
# I want to extract positive one
my_root = tuple(sol)[1]
display(my_root) # -> -sqrt(2)

I can fix this problem using print(tuple(sol)) in the second line instead of display, but then I will miss Latex-style of output.

@ThePauliPrinciple
Copy link
Contributor

ThePauliPrinciple commented Jan 12, 2022

I think it is better to simply check for solutions that are positive rather depend on any ordering:

from sympy import *
from sympy.abc import x
s = [a for a in solveset(x**2-2, x) if a.is_positive]
print(s)
s[0]

If you want to display a tuple in LaTeX, you can use SymPy's Tuple (note that it works different from tuple)

Tuple(*solveset(x**2-2, x))

or convert automatically with sympify

sympify(tuple(solveset(x**2-2, x)))

@nickme68
Copy link
Author

OK, my equation has parameters, I want to look at roots and extract particular one (for example with plus sign in front of square root). Solutions you suggest are to complicated for me:

  1. use display to look at solution (set);
  2. if set is finite then use Tuple or tuple to look at ordered list of roots;
  3. choose particular root using its index.

I would like to skip step 2 in this sequence! ;-) And I can't skip step 1 because set may be not finite, then tuple will fail.
Anyway, thank you! Tuple was new command for me.

@oscarbenjamin
Copy link
Contributor

Although a set does not have an a priori defined order Python will iterate over the elements of a set in a particular order for a given set in a particular Python process. The fact that the printer displays the elements of the set in a different order is inconvenient. I have this problem regularly when trying to extract the symbols from an expression in an interactive session:

In [24]: t, x, y, z = expr.free_symbols

In [25]: expr.free_symbols
Out[25]: {t, x, y, z}

In [26]: t, x, y, z = expr.free_symbols

In [27]: [t, x, y, z]
Out[27]: [t, x, z, y]

It would be better if the printer didn't change the order of the elements of a Python set IMO.

@smichr
Copy link
Member

smichr commented Jan 12, 2022

RootOf will give you more control of which root you are selecting:

>>> p = Poly(x**2 -y, x)
>>> RootOf(p, 0)
-sqrt(y)
>>> RotooOf(p, 1)
sqrt(y)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants