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.