3

I'm trying to determine the range of a function, in this case a polynomial. My program already uses a lot of SymPy functions so I thought I could use the function_range function from the sympy.calculus.util module. For the polynomial 1/2*x**4-2*x**2-1/4*x over the domain R doesn't work, and outputs this error:

>>> from sympy import S
>>> from sympy.abc import x
>>> expr = S(1)/2*x**4-2*x**2-S(1)/4*x
>>> function_range(expr, x, S.Reals)
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/base/data/home/apps/s~sympy-live-hrd/66.426491309333028408/sympy/sympy/calculus/util.py", line 223, in function_range
    for critical_point in critical_points:
  File "/base/data/home/apps/s~sympy-live-hrd/66.426491309333028408/sympy/sympy/sets/sets.py", line 1375, in __iter__
    "The computation had not completed because of the "
TypeError: The computation had not completed because of the undecidable set membership is found in every candidates.

Considering that this function is perfectly continuous and not very complex, I really don't understand why SymPy can't determine the Range, as it's a rather simple one. Am I doing something wrong with the input? Are there alternatives to SymPy for doing this?

[edited to use Rationals instead of Floats]

smichr
  • 16,948
  • 2
  • 27
  • 34
DeepQuantum
  • 273
  • 3
  • 14
  • 1
    Works for me. What version of SymPy are you using? – Oscar Benjamin Jan 01 '22 at 03:27
  • What is your definition of `x`? Please provide [a minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Yuri Ginsburg Jan 01 '22 at 03:58
  • When `x` is defined as `x = Symbol('x')` result is `Interval(-2.35737693115205, oo)`. So SymPy works. – Yuri Ginsburg Jan 01 '22 at 04:01
  • @YuriGinsburg The example above was done in [SymPy live](https://live.sympy.org/). My code as well as SymPy use the standard definition of `x`, `x = Symbol('x')`. – DeepQuantum Jan 01 '22 at 06:07
  • @OscarBenjamin The test above is just copy pasted from SymPy live, but both that and my personal code produce the same error. SymPy version is 1.9. – DeepQuantum Jan 01 '22 at 06:10
  • 1
    Alright so I tested it a bit more. When I just run this code in a basic python shell locally, it works, and gives the same interval as @YuriGinsburg mentioned. However, in my own personal code AND on the SymPy live shell, it doesn't work. SymPy live and my code both parse the input, turning `expr` into `x**4/2 - 2*x**2 - x/4`. Meanwhile, the python shell parses the input into `0.5*x**4 - 2*x**2 - 0.25*x`. When I input the expr as the shell puts it, the function works. – DeepQuantum Jan 01 '22 at 06:48
  • 1
    I can reproduce this with `expr = S(1)/2*x**4-2*x**2-S(1)/4*x`. I think maybe that's something that Live does automatically. Looks like a bug that should be reported to github: https://github.com/sympy/sympy/issues – Oscar Benjamin Jan 01 '22 at 17:28
  • cf https://github.com/sympy/sympy/issues/22793 – smichr Jan 04 '22 at 19:54

1 Answers1

0

The exact solution of the cubic equation needed to find the max/min of the quartic expression does not lend itself well to making comparisons needed to find which extremum is the lowest. You can calculate the value on your own by telling solve not to use exact cubic solutions like this:

>>> maxmin = FiniteSet(*[eq.subs(x,i) for i in solve(eq.diff(), cubics=False)])

The limits of the quartic are both positive and infinite at +/-oo

>>> limit(eq,x,-oo)
oo
>>> limit(eq,x,oo)  # must also be oo since function is even
oo

The minimum value the function attains is

>>> maxmin.inf
-2*CRootOf(8*x**3 - 16*x - 1, 2)**2 - CRootOf(8*x**3 - 16*x - 1, 2)/4 +
CRootOf(8*x**3 - 16*x - 1, 2)**4/2
>>> _.n()
-2.35737693115205
smichr
  • 16,948
  • 2
  • 27
  • 34