For cosh, it should just be handled by the assumptions system. That
is, cosh should have

def _eval_is_nonnegative(self):
    if self.args[0].is_real:
        return True

(and similar for the new assumptions _eval_refine).

On Mon, Feb 22, 2016 at 9:44 PM, Nolan Dyck <nolan.dyc...@gmail.com> wrote:
> Hi Everyone,
>
> I've been poking around in the sympy source, and I've noticed that the
> `simplify` command does not deal with expressions like the following:
>
>>>> from sympy import *
>>>> from sympy.abc import x
>>>> simplify(abs(cosh(x)))
> Abs(cosh(x))
>
> A simple glance at the graph of cosh(x) reveals that Abs(cosh(x)) ==
> cosh(x). So, in case it's not obvious the above expression should return:
>
> cosh(x)
>
> I'd like to take a stab at implementing this but I need some direction. I
> hope this isn't duplicating something I have stupidly missed (the inequality
> solvers don't seem to identify cases where absolute value brackets are
> unnecessary. There are three key cases (as far as I can see):

To do anything nontrivial in this area the inequality solvers will
definitely need to be improved.

>
> The argument within the abs brackets is non-negative over all combinations
> of all independent variables. Therefore, the absolute value brackets
> redundant / unnecessary and may be removed.
> The argument within the abs brackets is non-positive over all combinations
> of all independent variables. Therefore, the absolute value brackets may be
> removed and the expression may be multiplied by -1 for the same effect.
> The argument within the abs brackets contains both positive and negative
> values depending on the values of the independent variables.
>
> Ok, so to implement the above rules in the general sense it makes sense to
> me to perform the following steps given the expression
> Abs(f(x_1,x_2,...x_n)):
>
> Determine the number of real roots of f(x).
>
> If there are one or more real roots then for each root:
>
> Determine whether the gradient of f(x) is zero:
>
> If non-zero slope at root, then argument expression obtains opposite signed
> value at some point, so return Abs(f(x))
>
> Slope of f(x) at root is 0.
> Determine if the root is an inflection point (need to figure out exactly how
> to test for this over multiple variables in the expression)
>
> If at inflection point then the expression will still become opposite signed
> on either side of the root, so return Abs(f(x))
>
> Any and all roots coincide with extrema values of f(x). Therefore f(x) may
> be represented without absolute value brackets.
>
> If f(x) >= 0 remove the absolute value brackets and return the argument
> expression.
> If f(x) < 0 remove the absolute value brackets, multiply the expression by
> -1 and return it.
>
> There are a few things which I'm not sure how it will work out:

This algorithm only works if the function is real and differentiable
over the given domain.

>
> Imaginary numbers. Does anyone know if I will need to write special code for
> this, or should the above procedure work out anyway?
> The case where a symbol in the expression has been defined with the positive
> flag:
>
>>>> y = Symbol('y')
>>>> simplify(abs(sinh(y)))
> Abs(sinh(y))
>
>>>> y = Symbol('y',positive=True)
>>>> simplify(abs(sinh(y)))
> sinh(y)
>
> Are there sneaky ways of determining in a precise manner whether a function
> which cannot be reduced (e.g. cosh(x)+cos(x)) has real roots, even if
> finding those roots would only be possible numerically? Is there another
> sympy module which can help with this?

solveset aims to give a full set of solutions to an equation over an
equation (compared with solve(), which makes no guarantees about
giving all solutions). It's a difficult problem, though, and so far it
is limited in what it can do.

> What about variables which produce no real roots over a given range? Is
> there a way to handle those? E.g.
>
>>>> y = Symbol('y',range=[0,pi])
>>>> simplify(abs(sin(y)))
> sin(y)

For a continuous function, you only need to check the intervals
between the zeros. You can find all the zeros of sin(y) in the range
[0, pi] (0 and pi), so you only have to check a value between them.

I don't know if this is necessarily the best way to implement this in
SymPy (one needs the ability to determine if a function is continuous,
and to find all its roots). At any rate, Symbol doesn't have a "range"
argument currently. You can use solveset(sin(y), y, domain=Interval(0,
pi)) (note there is a bug with this in master
https://github.com/sympy/sympy/issues/10671).

>
> Redundant absolute value brackets are removed somewhere. Can anyone tell me
> where exactly in the code this happens in the simplify function? I can't
> seem to find it:

It happens in the Abs constructor, i.e., when you create the Abs. Abs
is defined in sympy.functions.elementary.complexes.

>
>>>> from sympy.abc import x
>>>> simplify(abs(abs(x)+1))
> Abs(x) + 1
>>>> simplify(abs(x+1))
> Abs(x + 1)
>
> So, right now I have forked the sympy repo (see here) and set up my own
> little function in sympy.symplify called abssimp.py (just copied combsimp.py
> and started from there), and added an appropriate if-absolute check in the
> main simplify function. Is this the right way to go about adding such a
> feature? Would the code that I write here also be used in solve or
> something?
>
> Any guidance / advice would be appreciated.
>
> Thanks!
> Nolan Dyck
>
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+unsubscr...@googlegroups.com.
> To post to this group, send email to sympy@googlegroups.com.
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/aeb34566-d4b8-46f4-8eb5-f7acabbd12f4%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sympy+unsubscr...@googlegroups.com.
To post to this group, send email to sympy@googlegroups.com.
Visit this group at https://groups.google.com/group/sympy.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/CAKgW%3D6%2BErd7QfBfd4_tQrEcOhpK13AAbWatMP5tgLaaxRpvSXg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to