On Tue, Mar 30, 2021 at 2:48 PM 'Bruce Allen' via sympy
<
sy...@googlegroups.com> wrote:
>
> Hi Aaron,
>
> Thanks for your help!
>
> >> def MyAbs(x):
> >> x1=symbols('x1',real=True,positive=True)
> >> x1 = x.evalf(subs={a:0.573})
> >> if x1 < 0.0:
> >> return S(-1)*x
> >> else:
> >> return x
>
> > - Defining x1 as a symbol does nothing in this code, as you
> > immediately overwrite it with x.evalf(...).
>
> OK. I'm still hazy on when Python allocates new storage for an object.
This section of the tutorial may help to clear things up
https://docs.sympy.org/latest/tutorial/gotchas.html. This blog post
also goes into more detail about how variables work in Python
https://nedbatchelder.com/text/names.html.
The important thing is that variable names (what is on the left-hand
side of the =) have no bearing whatsoever on SymPy expressions. So
what you are doing here is
- Defining a SymPy symbol named x1 and assigning it to a Python
variable, also named x1 (these two are unrelated and need not be the
same as one another).
- Creating a number with x.evalf(), and assigning that to the Python
variable x1, overwriting the symbol that was previously assigned to
it.
SymPy objects don't have any side effects when you create them, so the
x1=symbols('x1',real=True,positive=True) is effectively dead code.
>
> > - S(-1) is unnecessary. You can just use -x.
>
> OK.
>
> > - Your code assumes that the expression is a function in the variable
> > a (and only a). But perhaps that assumption is fine for your use-case.
>
> This assumption is correct: all of my expressions are polynomials in a,
> and rational powers of those polynomials. So 'a' is the only variable
> that appears.
>
> > The main gotcha however is that the code is wrong if the abs is
> > positive for that specific value of a but not for the general domain
> > of a.
>
> I only need equations that are valid in an infinitesimal neighborhood
> around a=0.57
If you are confident about these given assumptions, your code seems
fine. You could add guards to check that the argument of the abs
really is what you expect if you want to make it a little more robust,
in case any unrelated absolute values happen to appear at some point.
Oscar's suggestion of swapping a in and out with a custom object that
knows it evaluates to 0.57 should also work. I wouldn't really say one
is better than the other, it's more a question of style. Personally I
like the replace solution better because it's more robust (it doesn't
rely on Abs knowing that it can evaluate itself given the custom
object).
>
> > A more robust way would be to use the maximum() and minimum()
> > functions to get the maximum and minimum values of the abs argument on
> > the interval [0, 1]:
>
> I can test at the endpoints of a small interval, say 0.56 < a < 0.58.
> But the expressions are complicated enough that solving for the extrema
> will be too expensive. Fortunately I do have a consistency test at the
> end which should catch any mistakes.
>
> >>>> maximum(2*a**2 - 1, a, Interval(0, 1))
> > 1
> >>>> minimum(2*a**2 - 1, a, Interval(0, 1))
> > -1
>
> > This tells you that abs(2*a**2 - 1) cannot be simplified like this for
> > a in [0, 1], because it is both positive and negative on that
> > interval. To simplify it, you would need to factor it or write it as a
> > piecewise.
>
> You are correct. Fortunately I only need results that are correct in an
> open set around a specific value of a.
>
> What I might do is to modify MyAbs so that it maintains a global
> dictionary of all arguments it has been called with, adding new
> arguments if they are not found in the dictionary. Later I can check
> that the objects stored in the dictionary have no roots within the small
> interval. Does that seem reasonable?
That sounds fine. You can also use functools.lru_cache to get the same effect.
Aaron Meurer
>
> Cheers,
> Bruce
>
> --
> 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+un...@googlegroups.com.
> To view this discussion on the web visit
https://groups.google.com/d/msgid/sympy/615015dd-29b3-539e-89a4-28fd7c2b879b%40googlemail.com.