Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

integrate((x**8+1)**(-1/2),x) raises _CoeffExpValueError #26571

Open
NeilStrickland opened this issue May 7, 2024 · 4 comments · May be fixed by #26573
Open

integrate((x**8+1)**(-1/2),x) raises _CoeffExpValueError #26571

NeilStrickland opened this issue May 7, 2024 · 4 comments · May be fixed by #26573

Comments

@NeilStrickland
Copy link

With sympy version 1.12, this code:

from sympy import symbols, integrate
x = symbols('x')
integrate((x**8+1)**(-1/2), x)

raises a _CoeffExpValueError. The full trace is shown below. Maple gives x*hypergeom([1/8, 1/2], [9/8], -x^8) as the value of this integral.

---------------------------------------------------------------------------
_CoeffExpValueError                       Traceback (most recent call last)
Cell In[1], [line 3](vscode-notebook-cell:?execution_count=1&line=3)
      [1](vscode-notebook-cell:?execution_count=1&line=1) from sympy import symbols, integrate
      [2](vscode-notebook-cell:?execution_count=1&line=2) x = symbols('x')
----> [3](vscode-notebook-cell:?execution_count=1&line=3) integrate((x**8+1)**(-1/2), x)

File c:\Program Files\Python311\Lib\site-packages\sympy\integrals\integrals.py:1567, in integrate(meijerg, conds, risch, heurisch, manual, *args, **kwargs)
   [1564](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1564) integral = Integral(*args, **kwargs)
   [1566](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1566) if isinstance(integral, Integral):
-> [1567](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1567)     return integral.doit(**doit_flags)
   [1568](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1568) else:
   [1569](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1569)     new_args = [a.doit(**doit_flags) if isinstance(a, Integral) else a
   [1570](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1570)         for a in integral.args]

File c:\Program Files\Python311\Lib\site-packages\sympy\integrals\integrals.py:612, in Integral.doit(self, **hints)
    [610](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:610)     antideriv = None
    [611](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:611) else:
--> [612](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:612)     antideriv = self._eval_integral(
    [613](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:613)         function, xab[0], **eval_kwargs)
    [614](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:614)     if antideriv is None and meijerg is True:
    [615](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:615)         ret = try_meijerg(function, xab)

File c:\Program Files\Python311\Lib\site-packages\sympy\integrals\integrals.py:1098, in Integral._eval_integral(self, f, x, meijerg, risch, manual, heurisch, conds, final)
   [1095](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1095) if meijerg is not False and h is None:
   [1096](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1096)     # rewrite using G functions
   [1097](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1097)     try:
-> [1098](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1098)         h = meijerint_indefinite(g, x)
   [1099](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1099)     except NotImplementedError:
   [1100](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/integrals.py:1100)         _debug('NotImplementedError from meijerint_definite')

File c:\Program Files\Python311\Lib\site-packages\sympy\integrals\meijerint.py:1668, in meijerint_indefinite(f, x)
   [1666](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1666) results = []
   [1667](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1667) for a in sorted(_find_splitting_points(f, x) | {S.Zero}, key=default_sort_key):
-> [1668](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1668)     res = _meijerint_indefinite_1(f.subs(x, x + a), x)
   [1669](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1669)     if not res:
   [1670](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1670)         continue

File c:\Program Files\Python311\Lib\site-packages\sympy\integrals\meijerint.py:1694, in _meijerint_indefinite_1(f, x)
   [1691](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1691) _debug('Trying to compute the indefinite integral of', f, 'wrt', x)
   [1692](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1692) from sympy.simplify import hyperexpand, powdenest
-> [1694](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1694) gs = _rewrite1(f, x)
   [1695](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1695) if gs is None:
   [1696](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1696)     # Note: the code that calls us will do expand() and try again
   [1697](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1697)     return None

File c:\Program Files\Python311\Lib\site-packages\sympy\integrals\meijerint.py:1618, in _rewrite1(f, x, recursive)
   [1610](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1610) """
   [1611](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1611) Try to rewrite ``f`` using a (sum of) single G functions with argument a*x**b.
   [1612](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1612) Return fac, po, g such that f = fac*po*g, fac is independent of ``x``.
   (...)
   [1615](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1615) Return None on failure.
   [1616](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1616) """
   [1617](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1617) fac, po, g = _split_mul(f, x)
-> [1618](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1618) g = _rewrite_single(g, x, recursive)
   [1619](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1619) if g:
   [1620](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1620)     return fac, po, g[0], g[1]

File c:\Program Files\Python311\Lib\site-packages\sympy\core\cache.py:72, in __cacheit.<locals>.func_wrapper.<locals>.wrapper(*args, **kwargs)
     [69](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/core/cache.py:69) @wraps(func)
     [70](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/core/cache.py:70) def wrapper(*args, **kwargs):
     [71](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/core/cache.py:71)     try:
---> [72](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/core/cache.py:72)         retval = cfunc(*args, **kwargs)
     [73](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/core/cache.py:73)     except TypeError as e:
     [74](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/core/cache.py:74)         if not e.args or not e.args[0].startswith('unhashable type:'):

File c:\Program Files\Python311\Lib\site-packages\sympy\integrals\meijerint.py:1523, in _rewrite_single(f, x, recursive)
   [1521](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1521) res = []
   [1522](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1522) for fac, g in terms:
-> [1523](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1523)     r1 = _get_coeff_exp(unpolarify(fac.subs(subs).subs(z, x),
   [1524](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1524)                                    exponents_only=True), x)
   [1525](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1525)     try:
   [1526](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:1526)         g = g.subs(subs).subs(z, x)

File c:\Program Files\Python311\Lib\site-packages\sympy\integrals\meijerint.py:350, in _get_coeff_exp(expr, x)
    [348](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:348)     return c, S.One
    [349](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:349) else:
--> [350](file:///C:/Program%20Files/Python311/Lib/site-packages/sympy/integrals/meijerint.py:350)     raise _CoeffExpValueError('expr not of form a*x**b: %s' % expr)

_CoeffExpValueError: expr not of form a*x**b: 0.564189583547756
@NeilStrickland
Copy link
Author

I now realise that the error goes away if I change the exponent to Rational(-1,2).

@oscarbenjamin
Copy link
Contributor

It seems to be a bug in as_coeff_mul for floats:

In [12]: S(2.0).as_coeff_mul(x)
Out[12]: (1, (2.0,))

In [13]: S(2).as_coeff_mul(x)
Out[13]: (2, ())

@oscarbenjamin
Copy link
Contributor

diff --git a/sympy/core/numbers.py b/sympy/core/numbers.py
index b497a1bedc..2ff6011536 100644
--- a/sympy/core/numbers.py
+++ b/sympy/core/numbers.py
@@ -537,7 +537,7 @@ def __hash__(self):
     def is_constant(self, *wrt, **flags):
         return True

-    def as_coeff_mul(self, *deps, rational=True, **kwargs):
+    def as_coeff_mul(self, *deps, rational=False, **kwargs):
         # a -> c*t
         if self.is_Rational or not rational:
             return self, ()

@oscarbenjamin
Copy link
Contributor

diff --git a/sympy/core/mul.py b/sympy/core/mul.py
index d93dbde758..23a9ebc5fe 100644
--- a/sympy/core/mul.py
+++ b/sympy/core/mul.py
@@ -2156,8 +2156,12 @@ def _keep_coeff(coeff, factors, clear=True, sign=False):
         return coeff
     if coeff is S.One:
         return factors
-    elif coeff is S.NegativeOne and not sign:
+    elif coeff.is_Float and equal_valued(coeff, S.One):
+        return Add(*[coeff*term for term in Add.make_args(factors)])
+    elif not sign and coeff is S.NegativeOne:
         return -factors
+    elif not sign and coeff.is_Float and equal_valued(coeff, S.NegativeOne):
+        return Add(*[coeff*term for term in Add.make_args(factors)])
     elif factors.is_Add:
         if not clear and coeff.is_Rational and coeff.q != 1:
             args = [i.as_coeff_Mul() for i in factors.args]
@@ -2191,6 +2195,6 @@ def do(e):
     return bottom_up(e, do)


-from .numbers import Rational
+from .numbers import Rational, equal_valued
 from .power import Pow
 from .add import Add, _unevaluated_Add
diff --git a/sympy/core/numbers.py b/sympy/core/numbers.py
index b497a1bedc..2ff6011536 100644
--- a/sympy/core/numbers.py
+++ b/sympy/core/numbers.py
@@ -537,7 +537,7 @@ def __hash__(self):
     def is_constant(self, *wrt, **flags):
         return True

-    def as_coeff_mul(self, *deps, rational=True, **kwargs):
+    def as_coeff_mul(self, *deps, rational=False, **kwargs):
         # a -> c*t
         if self.is_Rational or not rational:
             return self, ()
diff --git a/sympy/core/tests/test_expr.py b/sympy/core/tests/test_expr.py
index 8299ca312c..e52da8caf3 100644
--- a/sympy/core/tests/test_expr.py
+++ b/sympy/core/tests/test_expr.py
@@ -1250,9 +1250,10 @@ def test_as_coeff_add():

 def test_as_coeff_mul():
     assert S(2).as_coeff_mul() == (2, ())
-    assert S(3.0).as_coeff_mul() == (1, (S(3.0),))
-    assert S(-3.0).as_coeff_mul() == (-1, (S(3.0),))
+    assert S(3.0).as_coeff_mul() == (S(3.0), ())
+    assert S(-3.0).as_coeff_mul() == (S(-3.0), ())
     assert S(-3.0).as_coeff_mul(rational=False) == (-S(3.0), ())
+    assert S(-3.0).as_coeff_mul(rational=True) == (-1, (S(3.0),))
     assert x.as_coeff_mul() == (1, (x,))
     assert (-x).as_coeff_mul() == (-1, (x,))
     assert (2*x).as_coeff_mul() == (2, (x,))
diff --git a/sympy/holonomic/tests/test_holonomic.py b/sympy/holonomic/tests/test_holonomic.py
index e5069c89a8..991d2c3d85 100644
--- a/sympy/holonomic/tests/test_holonomic.py
+++ b/sympy/holonomic/tests/test_holonomic.py
@@ -624,7 +624,7 @@ def test_to_expr():
     q = 1.4*a*x**2
     assert p == q
     p = (expr_to_holonomic(1.4*x)+expr_to_holonomic(a*x, x)).to_expr()
-    q = x*(a + 1.4)
+    q = x*(1.0*a + 1.4)
     assert p == q
     p = (expr_to_holonomic(1.4*x)+expr_to_holonomic(x)).to_expr()
     assert p == 2.4*x

@oscarbenjamin oscarbenjamin added Easy to Fix This is a good issue for new contributors. Feel free to work on this if no one else has already. core integrals.meijerg and removed Easy to Fix This is a good issue for new contributors. Feel free to work on this if no one else has already. labels May 7, 2024
oscarbenjamin added a commit to oscarbenjamin/sympy that referenced this issue May 7, 2024
integrate((x**8+1)**(-1/2), x)
skirpichev added a commit to skirpichev/diofant that referenced this issue May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants