Repository: sympy/sympy
Pull request: printing unevaluated Integrals
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g.  See
https://github.com/blog/1506-closing-issues-via-pull-requests .-->
Fixes #15716


#### Brief description of what is fixed or changed
```
>>> from sympy import *
>>> x = Symbol('x')
>>> e = -3**x*exp(-3)*log(3**x*exp(-3)/factorial(x))/factorial(x)
>>> i = integrate(e, [x, -oo, oo])
>>> i
During this definite integral an exception is raised which is "ValueError" so i just add "ValueError" .
```

  

#### Other comments

 


#### Release Notes

<!-- Write the release notes for this release below. See
https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more information
on how to write release notes. The bot will check your release notes
automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
- printing
  - catch ValueError from unevaluated integrals
<!-- END RELEASE NOTES -->



Problem statement:
Definite integral of -3**x*exp(-3)*log(3**x*exp(-3)/factorial(x))/factorial(x) returns an object that cannot be printed
```
>>> from sympy import *
>>> x = Symbol('x')
>>> e = -3**x*exp(-3)*log(3**x*exp(-3)/factorial(x))/factorial(x)
>>> i = integrate(e, [x, -oo, oo])
>>> i
Traceback (most recent call last):
  File "/home/e/se/sympy/core/evalf.py", line 1306, in evalf
    rf = evalf_table[x.func]
KeyError: factorial

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/e/se/sympy/core/evalf.py", line 1306, in evalf
    rf = evalf_table[x.func]
KeyError: factorial

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/e/se/sympy/core/basic.py", line 407, in __repr__
    return sstr(self, order=None)
  File "/home/e/se/sympy/printing/str.py", line 843, in sstr
    s = p.doprint(expr)
  File "/home/e/se/sympy/printing/printer.py", line 249, in doprint
    return self._str(self._print(expr))
  File "/home/e/se/sympy/printing/printer.py", line 287, in _print
    return getattr(self, printmethod)(expr, **kwargs)
  File "/home/e/se/sympy/printing/str.py", line 287, in _print_Mul
    args = expr.as_ordered_factors()
  File "/home/e/se/sympy/core/mul.py", line 1706, in as_ordered_factors
    cpart.sort(key=lambda expr: expr.sort_key(order=order))
  File "/home/e/se/sympy/core/mul.py", line 1706, in <lambda>
    cpart.sort(key=lambda expr: expr.sort_key(order=order))
  File "/home/e/se/sympy/core/cache.py", line 94, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/home/e/se/sympy/core/expr.py", line 89, in sort_key
    args = expr.as_ordered_terms(order=order)
  File "/home/e/se/sympy/core/expr.py", line 1021, in as_ordered_terms
    terms, gens = self.as_terms()
  File "/home/e/se/sympy/core/expr.py", line 1060, in as_terms
    coeff *= complex(factor)
  File "/home/e/se/sympy/core/expr.py", line 283, in __complex__
    result = self.evalf()
  File "/home/e/se/sympy/core/evalf.py", line 1437, in evalf
    result = evalf(self, prec + 4, options)
  File "/home/e/se/sympy/core/evalf.py", line 1307, in evalf
    r = rf(x, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 1037, in evalf_integral
    result = do_integral(expr, workprec, options)
  File "/home/e/se/sympy/core/evalf.py", line 996, in do_integral
    result, quadrature_error = quadts(f, [xlow, xhigh], error=1)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 786, in quadts
    return ctx.quad(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 743, in quad
    v, err = rule.summation(f, points[0], prec, epsilon, m, verbose)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 232, in summation
    results.append(self.sum_next(f, nodes, degree, prec, results, verbose))
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 304, in sum_next
    S += self.ctx.fdot((w,f(x)) for (x,w) in nodes)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/ctx_mp_python.py", line 925, in fdot
    for a, b in A:
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 304, in <genexpr>
    S += self.ctx.fdot((w,f(x)) for (x,w) in nodes)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 224, in <lambda>
    f = lambda x: _f(-x) + _f(x)
  File "/home/e/se/sympy/core/evalf.py", line 969, in f
    re, im, re_acc, im_acc = evalf(func, mp.prec, {'subs': {x: t}})
  File "/home/e/se/sympy/core/evalf.py", line 1307, in evalf
    r = rf(x, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 559, in evalf_mul
    arg = evalf(arg, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 1307, in evalf
    r = rf(x, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 676, in evalf_pow
    re, im, re_acc, im_acc = evalf(base, prec + 5, options)
  File "/home/e/se/sympy/core/evalf.py", line 1312, in evalf
    x = x.subs(evalf_subs(prec, options['subs']))
  File "/home/e/se/sympy/core/basic.py", line 997, in subs
    rv = rv._subs(old, new, **kwargs)
  File "/home/e/se/sympy/core/cache.py", line 94, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/home/e/se/sympy/core/basic.py", line 1111, in _subs
    rv = fallback(self, old, new)
  File "/home/e/se/sympy/core/basic.py", line 1088, in fallback
    rv = self.func(*args)
  File "/home/e/se/sympy/core/cache.py", line 94, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/home/e/se/sympy/core/function.py", line 454, in __new__
    result = result.evalf(mlib.libmpf.prec_to_dps(pr))
  File "/home/e/se/sympy/core/evalf.py", line 1437, in evalf
    result = evalf(self, prec + 4, options)
  File "/home/e/se/sympy/core/evalf.py", line 1313, in evalf
    xe = x._eval_evalf(prec)
  File "/home/e/se/sympy/core/function.py", line 567, in _eval_evalf
    v = func(*args)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/ctx_mp_python.py", line 993, in f
    return ctx.make_mpf(mpf_f(x._mpf_, prec, rounding))
  File "/usr/local/lib/python3.6/dist-packages/mpmath/libmp/gammazeta.py", line 2353, in mpf_factorial
    return mpf_gamma(x, prec, rnd, 1)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/libmp/gammazeta.py", line 1950, in mpf_gamma
    raise ValueError("gamma function pole")
ValueError: gamma function pole
>>> N(i)
Traceback (most recent call last):
  File "/home/e/se/sympy/core/evalf.py", line 1306, in evalf
    rf = evalf_table[x.func]
KeyError: factorial

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/e/se/sympy/core/evalf.py", line 1306, in evalf
    rf = evalf_table[x.func]
KeyError: factorial

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/e/se/sympy/core/evalf.py", line 1532, in N
    return sympify(x).evalf(n, **options)
  File "/home/e/se/sympy/core/evalf.py", line 1437, in evalf
    result = evalf(self, prec + 4, options)
  File "/home/e/se/sympy/core/evalf.py", line 1307, in evalf
    r = rf(x, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 559, in evalf_mul
    arg = evalf(arg, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 1307, in evalf
    r = rf(x, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 519, in evalf_add
    terms = [evalf(arg, prec + 10, options) for arg in v.args]
  File "/home/e/se/sympy/core/evalf.py", line 519, in <listcomp>
    terms = [evalf(arg, prec + 10, options) for arg in v.args]
  File "/home/e/se/sympy/core/evalf.py", line 1307, in evalf
    r = rf(x, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 1037, in evalf_integral
    result = do_integral(expr, workprec, options)
  File "/home/e/se/sympy/core/evalf.py", line 996, in do_integral
    result, quadrature_error = quadts(f, [xlow, xhigh], error=1)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 786, in quadts
    return ctx.quad(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 743, in quad
    v, err = rule.summation(f, points[0], prec, epsilon, m, verbose)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 232, in summation
    results.append(self.sum_next(f, nodes, degree, prec, results, verbose))
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 304, in sum_next
    S += self.ctx.fdot((w,f(x)) for (x,w) in nodes)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/ctx_mp_python.py", line 925, in fdot
    for a, b in A:
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 304, in <genexpr>
    S += self.ctx.fdot((w,f(x)) for (x,w) in nodes)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/calculus/quadrature.py", line 224, in <lambda>
    f = lambda x: _f(-x) + _f(x)
  File "/home/e/se/sympy/core/evalf.py", line 969, in f
    re, im, re_acc, im_acc = evalf(func, mp.prec, {'subs': {x: t}})
  File "/home/e/se/sympy/core/evalf.py", line 1307, in evalf
    r = rf(x, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 559, in evalf_mul
    arg = evalf(arg, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 1307, in evalf
    r = rf(x, prec, options)
  File "/home/e/se/sympy/core/evalf.py", line 676, in evalf_pow
    re, im, re_acc, im_acc = evalf(base, prec + 5, options)
  File "/home/e/se/sympy/core/evalf.py", line 1312, in evalf
    x = x.subs(evalf_subs(prec, options['subs']))
  File "/home/e/se/sympy/core/basic.py", line 997, in subs
    rv = rv._subs(old, new, **kwargs)
  File "/home/e/se/sympy/core/cache.py", line 94, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/home/e/se/sympy/core/basic.py", line 1111, in _subs
    rv = fallback(self, old, new)
  File "/home/e/se/sympy/core/basic.py", line 1088, in fallback
    rv = self.func(*args)
  File "/home/e/se/sympy/core/cache.py", line 94, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/home/e/se/sympy/core/function.py", line 454, in __new__
    result = result.evalf(mlib.libmpf.prec_to_dps(pr))
  File "/home/e/se/sympy/core/evalf.py", line 1437, in evalf
    result = evalf(self, prec + 4, options)
  File "/home/e/se/sympy/core/evalf.py", line 1313, in evalf
    xe = x._eval_evalf(prec)
  File "/home/e/se/sympy/core/function.py", line 567, in _eval_evalf
    v = func(*args)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/ctx_mp_python.py", line 993, in f
    return ctx.make_mpf(mpf_f(x._mpf_, prec, rounding))
  File "/usr/local/lib/python3.6/dist-packages/mpmath/libmp/gammazeta.py", line 2353, in mpf_factorial
    return mpf_gamma(x, prec, rnd, 1)
  File "/usr/local/lib/python3.6/dist-packages/mpmath/libmp/gammazeta.py", line 1950, in mpf_gamma
    raise ValueError("gamma function pole")
ValueError: gamma function pole
```

Hints from issue discussion:
I am working on this and i think that problem is with limits.
I think problem is with limits because of factorial it can't be negative.
It seems that ValueError should be handled [here](https://github.com/sympy/sympy/blob/master/sympy/core/expr.py#L1061) in addition to TypeError.
@jksuom  I think it is working  ,there should be ValueError.

Commit message: test case added

Patch to review:
diff --git a/sympy/core/expr.py b/sympy/core/expr.py
index 0e0b59d392d9..5ff2a69402ab 100644
--- a/sympy/core/expr.py
+++ b/sympy/core/expr.py
@@ -1058,7 +1058,7 @@ def as_terms(self):
                     if factor.is_number:
                         try:
                             coeff *= complex(factor)
-                        except TypeError:
+                        except (TypeError, ValueError):
                             pass
                         else:
                             continue
diff --git a/sympy/integrals/tests/test_integrals.py b/sympy/integrals/tests/test_integrals.py
index 61f53f9cf29b..39cb6c39b6f1 100644
--- a/sympy/integrals/tests/test_integrals.py
+++ b/sympy/integrals/tests/test_integrals.py
@@ -15,6 +15,7 @@
 from sympy.utilities.pytest import XFAIL, raises, slow, skip, ON_TRAVIS
 from sympy.utilities.randtest import verify_numerically
 from sympy.integrals.integrals import Integral
+from sympy import factorial
 
 x, y, a, t, x_1, x_2, z, s = symbols('x y a t x_1 x_2 z s')
 n = Symbol('n', integer=True)
diff --git a/sympy/printing/tests/test_str.py b/sympy/printing/tests/test_str.py
index 5c7b753bde84..7c00a4544442 100644
--- a/sympy/printing/tests/test_str.py
+++ b/sympy/printing/tests/test_str.py
@@ -16,6 +16,7 @@
 from sympy.printing import sstr, sstrrepr, StrPrinter
 from sympy.core.trace import Tr
 from sympy import MatrixSymbol
+from sympy import factorial, log, integrate
 
 x, y, z, w, t = symbols('x,y,z,w,t')
 d = Dummy('d')
@@ -809,3 +810,9 @@ def test_MatrixSymbol_printing():
 def test_Subs_printing():
     assert str(Subs(x, (x,), (1,))) == 'Subs(x, x, 1)'
     assert str(Subs(x + y, (x, y), (1, 2))) == 'Subs(x + y, (x, y), (1, 2))'
+
+def test_issue_15716():
+    x = Symbol('x')
+    e = -3**x*exp(-3)*log(3**x*exp(-3)/factorial(x))/factorial(x)
+    definite = integrate(e, [x, -oo, oo])
+    assert str(Integral(e, (x, -oo, oo)).doit()) == str(definite)


Code review comments:
diff_hunk: @@ -809,3 +810,9 @@ def test_MatrixSymbol_printing():
 def test_Subs_printing():
     assert str(Subs(x, (x,), (1,))) == 'Subs(x, x, 1)'
     assert str(Subs(x + y, (x, y), (1, 2))) == 'Subs(x + y, (x, y), (1, 2))'
+
+def test_issue_15716():
+    x = Symbol('x')
+    e = -3**x*exp(-3)*log(3**x*exp(-3)/factorial(x))/factorial(x)
+    definite = integrate(e, [x, -oo, oo])
+    assert str(Integral(e, (x, -oo, oo)).doit()) == str(definite)
path: sympy/printing/tests/test_str.py
text: @user1:
The integral should be computed only once to save time. `Integral(e, (x, -oo, oo)).doit()` will only repeat what `integrate` does on the previous line. Perhaps it would be possible to write something like

    assert str(integrate(e, (x, -oo, oo))) == "..."

where the string on the right hand side is precomputed to save time.

@author:
okk