On Sun, 30 Jun 2013 13:23:50 -0700 (PDT)
Eric Gourgoulhon <egourgoul...@gmail.com> wrote:

> Meanwhile, I've written the following workaround in python:
> basically, it scans all the sqrt's in a given symbolic expression,
> send them to radcan, takes the absolute value of the output and then
> calls simplify(). It is not optimal but it works:
> 
>         sage: assume(x<0)      
>         sage: simplify_sqrt_real( sqrt(x^2) )
>         -x
>         sage: simplify_sqrt_real( sqrt(x^2-2*x+1) )
>         -x + 1
>         sage: simplify_sqrt_real( sqrt(x^2) + sqrt(x^2-2*x+1) )
>         -2*x + 1
> 
> Here is the source code:
> 
> def simplify_sqrt_real(expr):
>     r"""
>     Simplify sqrt in symbolic expressions in the real domain.
>     
>     EXAMPLES:
>     
>     Simplifications of basic expressions::
>     
>         sage: assume(x<0)      
>         sage: simplify_sqrt_real( sqrt(x^2) )
>         -x
>         sage: simplify_sqrt_real( sqrt(x^2-2*x+1) )
>         -x + 1
>         sage: simplify_sqrt_real( sqrt(x^2) + sqrt(x^2-2*x+1) )
>         -2*x + 1
> 
>     """
>     from sage.symbolic.ring import SR
>     from sage.calculus.calculus import maxima
>     # 1/ Search for the sqrt's in expr
>     sexpr = str(expr)
>     if 'sqrt(' not in sexpr:  # no sqrt to simplify
>         return expr
>     pos_sqrts = []   # positions of the sqrt's in sexpr
>     the_sqrts = []   # the sqrt sub-expressions in sexpr
>     for pos in range(len(sexpr)):
>         if sexpr[pos:pos+5] == 'sqrt(':
>             pos_sqrts.append(pos)
>             parenth = 1
>             scan = pos+5
>             while parenth != 0:
>                 if sexpr[scan] == '(': parenth += 1
>                 if sexpr[scan] == ')': parenth -= 1
>                 scan += 1 
>             the_sqrts.append( sexpr[pos:scan] )

Instead of going through strings, you might want to try pattern
matching:

sage: t = sin(x)*sqrt(x^2)*e^(sqrt(x+1))
sage: w = SR.wild()
sage: t.find(w^(1/2))
[sqrt(x + 1), sqrt(x^2)]

Note that this won't catch sqrt() in the denominator. You will need to
specify a negative exponent for that:

sage: u = 1/sqrt(x+1)
sage: u.find(w^(-1/2)) 
[1/sqrt(x + 1)]


>     # 2/ Simplifications of the sqrt's
>     new_expr = ""    # will contain the result
>     pos0 = 0
>     for i, pos in enumerate(pos_sqrts):
>         # radcan is called on each sqrt:
>         x = SR(the_sqrts[i])
>         simpl = SR(x._maxima_().radcan())

This is x.maxima_methods().radcan().

>         # the absolute value of radcan's output is taken, the call to 
> simplify() 
>         # taking into account possible assumptions regarding the sign
> of simpl:
>         new_expr += sexpr[pos0:pos] + '(' +
> str(abs(simpl).simplify()) + ')' pos0 = pos + len(the_sqrts[i])
>     new_expr += sexpr[pos0:]
>     return SR(new_expr)

Putting the new values back can be done with subs().

sage: t
sqrt(x^2)*e^(sqrt(x + 1))*sin(x)
sage: t.subs({sqrt(x^2): x})                           
x*e^(sqrt(x + 1))*sin(x)


Cheers,
Burcin

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To post to this group, send email to sage-devel@googlegroups.com.
Visit this group at http://groups.google.com/group/sage-devel.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to