ASKSAGE: Sage Q&A Forum - Individual question feedhttp://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Sun, 09 Sep 2012 16:05:49 -0500What is the best way to return only real solutions?http://ask.sagemath.org/question/9307/what-is-the-best-way-to-return-only-real-solutions/I'm trying to write a function that filters out non-real solutions returned by solve. For now, I'm using
def select_real(xs):
return map(lambda eq: eq.lhs() == eq.rhs().real(), filter(lambda eq: not bool(eq.rhs().imag()), xs))
and it works for some simple cases like this
sage: select_real(solve(x^3+8==0, x))
[x == -2]
but this assumes multiple things, like fact that the solve retuns list in the form of actual solutions and imaginary part can be calculated. Generally it is only an ugly hack that I don't like.
I looked at assume(x, 'real') but found out that it does not work ( [Ticket #11941](http://trac.sagemath.org/sage_trac/ticket/11941) ). I also tried to do check using "in RR", but in above case all 3 solutions gave False. Also at first I tried using eq.full_simplify() in map step above, but it turns out that simplifying returns different root than using real/imag:
sage: ((-8)^(1/3)).full_simplify()
-2^(1/3)
sage: ((-8)^(1/3)).real()
1
After all that, I'm out of ideas. What is considered the best way to obtain only real solutions? Thanks in advance.
----------
edit:
I need such functionality because actually I'm preparing materials for high-schoolers who yet do not know about complex numbers, and shouldn't be introduced to them at that moment. My current version (above+extra full_simplify and uniq which are not really part of question) allows me to do for example this:
sage: var('x,a,b,c')
(x, a, b, c)
sage: assume(b^2-4*a*c>0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[x == -1/2*(b - sqrt(-4*a*c + b^2))/a, x == -1/2*(b + sqrt(-4*a*c + b^2))/a]
sage: forget(assumptions())
sage: assume(b^2-4*a*c==0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[x == -1/2*b/a]
sage: forget(assumptions())
sage: assume(b^2-4*a*c<0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[]Sun, 09 Sep 2012 09:23:39 -0500http://ask.sagemath.org/question/9307/what-is-the-best-way-to-return-only-real-solutions/Comment by ebs for <p>I'm trying to write a function that filters out non-real solutions returned by solve. For now, I'm using</p>
<pre><code>def select_real(xs):
return map(lambda eq: eq.lhs() == eq.rhs().real(), filter(lambda eq: not bool(eq.rhs().imag()), xs))
</code></pre>
<p>and it works for some simple cases like this</p>
<pre><code>sage: select_real(solve(x^3+8==0, x))
[x == -2]
</code></pre>
<p>but this assumes multiple things, like fact that the solve retuns list in the form of actual solutions and imaginary part can be calculated. Generally it is only an ugly hack that I don't like.</p>
<p>I looked at assume(x, 'real') but found out that it does not work ( <a href="http://trac.sagemath.org/sage_trac/ticket/11941">Ticket #11941</a> ). I also tried to do check using "in RR", but in above case all 3 solutions gave False. Also at first I tried using eq.full_simplify() in map step above, but it turns out that simplifying returns different root than using real/imag:</p>
<pre><code>sage: ((-8)^(1/3)).full_simplify()
-2^(1/3)
sage: ((-8)^(1/3)).real()
1
</code></pre>
<p>After all that, I'm out of ideas. What is considered the best way to obtain only real solutions? Thanks in advance.</p>
<hr/>
<p>edit:</p>
<p>I need such functionality because actually I'm preparing materials for high-schoolers who yet do not know about complex numbers, and shouldn't be introduced to them at that moment. My current version (above+extra full_simplify and uniq which are not really part of question) allows me to do for example this:</p>
<pre><code>sage: var('x,a,b,c')
(x, a, b, c)
sage: assume(b^2-4*a*c>0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[x == -1/2*(b - sqrt(-4*a*c + b^2))/a, x == -1/2*(b + sqrt(-4*a*c + b^2))/a]
sage: forget(assumptions())
sage: assume(b^2-4*a*c==0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[x == -1/2*b/a]
sage: forget(assumptions())
sage: assume(b^2-4*a*c<0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[]
</code></pre>
http://ask.sagemath.org/question/9307/what-is-the-best-way-to-return-only-real-solutions/?comment=19086#post-id-19086One way I think might work is to convert the output of solve($eqn, $var) into string for example,
str(solve(a*x^2+b*x+c==0, x)) and look for contents between 'sqrt(' and ')' and see if its negative (then you can omit it). you can also look on the left and right side of '^'. First right side to see if its a fractional power and if it is, you can check the expression being raised to the fractional power, if it is negative.(then you can omit it) Sun, 09 Sep 2012 15:45:39 -0500http://ask.sagemath.org/question/9307/what-is-the-best-way-to-return-only-real-solutions/?comment=19086#post-id-19086Answer by calc314 for <p>I'm trying to write a function that filters out non-real solutions returned by solve. For now, I'm using</p>
<pre><code>def select_real(xs):
return map(lambda eq: eq.lhs() == eq.rhs().real(), filter(lambda eq: not bool(eq.rhs().imag()), xs))
</code></pre>
<p>and it works for some simple cases like this</p>
<pre><code>sage: select_real(solve(x^3+8==0, x))
[x == -2]
</code></pre>
<p>but this assumes multiple things, like fact that the solve retuns list in the form of actual solutions and imaginary part can be calculated. Generally it is only an ugly hack that I don't like.</p>
<p>I looked at assume(x, 'real') but found out that it does not work ( <a href="http://trac.sagemath.org/sage_trac/ticket/11941">Ticket #11941</a> ). I also tried to do check using "in RR", but in above case all 3 solutions gave False. Also at first I tried using eq.full_simplify() in map step above, but it turns out that simplifying returns different root than using real/imag:</p>
<pre><code>sage: ((-8)^(1/3)).full_simplify()
-2^(1/3)
sage: ((-8)^(1/3)).real()
1
</code></pre>
<p>After all that, I'm out of ideas. What is considered the best way to obtain only real solutions? Thanks in advance.</p>
<hr/>
<p>edit:</p>
<p>I need such functionality because actually I'm preparing materials for high-schoolers who yet do not know about complex numbers, and shouldn't be introduced to them at that moment. My current version (above+extra full_simplify and uniq which are not really part of question) allows me to do for example this:</p>
<pre><code>sage: var('x,a,b,c')
(x, a, b, c)
sage: assume(b^2-4*a*c>0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[x == -1/2*(b - sqrt(-4*a*c + b^2))/a, x == -1/2*(b + sqrt(-4*a*c + b^2))/a]
sage: forget(assumptions())
sage: assume(b^2-4*a*c==0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[x == -1/2*b/a]
sage: forget(assumptions())
sage: assume(b^2-4*a*c<0)
sage: select_real(solve(a*x^2+b*x+c==0, x))
[]
</code></pre>
http://ask.sagemath.org/question/9307/what-is-the-best-way-to-return-only-real-solutions/?answer=14021#post-id-14021Here is another hack. You can use the solver in `sympy`. For example:
from sympy.solvers import solve
ans=solve(x^3+8, x)
print ans
[a for a in ans if imag(a)==0]
gives the result
[1 + 3**(1/2)*I, -2, 1 - 3**(1/2)*I]
[-2]
This works fine when you have actual values in the equations. There are issues, though, when working completely symbolically. Unfortunately, it won't work with the `assume` command in Sage. There is an `Assume` command in sympy, but I seem to be unable to get it to work in Sage.Sun, 09 Sep 2012 16:03:43 -0500http://ask.sagemath.org/question/9307/what-is-the-best-way-to-return-only-real-solutions/?answer=14021#post-id-14021Comment by calc314 for <p>Here is another hack. You can use the solver in <code>sympy</code>. For example:</p>
<pre><code>from sympy.solvers import solve
ans=solve(x^3+8, x)
print ans
[a for a in ans if imag(a)==0]
</code></pre>
<p>gives the result</p>
<pre><code>[1 + 3**(1/2)*I, -2, 1 - 3**(1/2)*I]
[-2]
</code></pre>
<p>This works fine when you have actual values in the equations. There are issues, though, when working completely symbolically. Unfortunately, it won't work with the <code>assume</code> command in Sage. There is an <code>Assume</code> command in sympy, but I seem to be unable to get it to work in Sage.</p>
http://ask.sagemath.org/question/9307/what-is-the-best-way-to-return-only-real-solutions/?comment=19084#post-id-19084Here is a link to the `sympy` solver documentation: http://docs.sympy.org/dev/modules/solvers/solvers.html#Sun, 09 Sep 2012 16:05:49 -0500http://ask.sagemath.org/question/9307/what-is-the-best-way-to-return-only-real-solutions/?comment=19084#post-id-19084