Skip to content

Commit

Permalink
Trac #28913: integrate(..., algorithm="giac"): Incorrect conversion t…
Browse files Browse the repository at this point in the history
…o Sage

Seen in [https://ask.sagemath.org/question/49192/possible-bug-in-sage-
giac-integration-interface-needs-confirmation/ this ask.sagemath
question]:

{{{
sage: Ex=(1-2*x^(1/3))^(3/4)/x
sage: integrate(Ex, x, algorithm="giac")
------------------------------------------------------------------------
---
SyntaxError                               Traceback (most recent call
last)
/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/interfaces/giac.py in _sage_(self, locals)
   1100                 return symbolic_expression_from_string(result,
lsymbols,
-> 1101                     accept_sequence=True)
   1102

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/calculus/calculus.py in symbolic_expression_from_string(s,
syms, accept_sequence)
   2384             _augmented_syms = syms
-> 2385             return parse_func(s)
   2386         finally:

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/misc/parser.pyx in sage.misc.parser.Parser.parse_sequence
(build/cythonized/sage/misc/parser.c:5479)()
    538
--> 539     cpdef parse_sequence(self, s):
    540         """

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/misc/parser.pyx in sage.misc.parser.Parser.parse_sequence
(build/cythonized/sage/misc/parser.c:5369)()
    556         if tokens.next() != EOS:
--> 557             self.parse_error(tokens)
    558         if len(all) == 1 and isinstance(all, list):

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/misc/parser.pyx in sage.misc.parser.Parser.parse_error
(build/cythonized/sage/misc/parser.c:9742)()
   1007     cdef parse_error(self, Tokenizer tokens, msg="Malformed
expression"):
-> 1008         raise SyntaxError(msg, tokens.s, tokens.pos)
   1009

SyntaxError: Malformed expression

During handling of the above exception, another exception occurred:

NotImplementedError                       Traceback (most recent call
last)
<ipython-input-22-617e71e52902> in <module>()
----> 1 integrate(Ex, x, algorithm="giac")

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/misc/functional.py in integral(x, *args, **kwds)
    751     """
    752     if hasattr(x, 'integral'):
--> 753         return x.integral(*args, **kwds)
    754     else:
    755         from sage.symbolic.ring import SR

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/symbolic/expression.pyx in
sage.symbolic.expression.Expression.integral
(build/cythonized/sage/symbolic/expression.cpp:64575)()
  12389                     R = ring.SR
  12390             return R(integral(f, v, a, b, **kwds))
> 12391         return integral(self, *args, **kwds)
  12392
  12393     integrate = integral

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/symbolic/integration/integral.py in integrate(expression,
v, a, b, algorithm, hold)
    925         if not integrator:
    926             raise ValueError("Unknown algorithm: %s" %
algorithm)
--> 927         return integrator(expression, v, a, b)
    928     if a is None:
    929         return indefinite_integral(expression, v, hold=hold)

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/symbolic/integration/external.py in
giac_integrator(expression, v, a, b)
    430         return expression.integrate(v, a, b, hold=True)
    431     else:
--> 432         return result._sage_()

/usr/local/sage-P3-2/local/lib/python3.7/site-
packages/sage/interfaces/giac.py in _sage_(self, locals)
   1102
   1103             except Exception:
-> 1104                 raise NotImplementedError("Unable to parse Giac
output: %s" % result)
   1105         else:
   1106             return [entry.sage() for entry in self]

NotImplementedError: Unable to parse Giac output: Evaluation time: 2.82
12*(1/4*ln(abs((-2*x^(1/3)+1)^(1/4)-1))-1/4*ln((-2*x^(1/3)+1)^(1/4)+1)+1
/2*atan((-2*x^(1/3)+1)^(1/4))+1/3*((-2*x^(1/3)+1)^(1/4))^3)
}}}

However, the following workaround works:

{{{
sage: from giacpy_sage import *
// Giac share root-directory:/usr/local/sage-P3-2/local/share/giac/
// Giac share root-directory:/usr/local/sage-P3-2/local/share/giac/
Help file /usr/local/sage-P3-2/local/share/giac/doc/fr/aide_cas not
found
Added 0 synonyms
sage: libgiac.integrate(Ex,x).sage()
4*(-2*x^(1/3) + 1)^(3/4) + 6*arctan((-2*x^(1/3) + 1)^(1/4)) -
3*log((-2*x^(1/3) + 1)^(1/4) + 1) + 3*log(abs((-2*x^(1/3) + 1)^(1/4) -
1))
}}}

This seems to point to the (unwelcome) timing information added by Giac
//before// its results... It's probably more of a booboo than a
(real|hard) bug, but might defeat a whole problem if this error is
raised before other algorithms has had a chance to report their results.

I'm not sure that this should be reported upstream (it should if there
is no way to cleanly suppress the timing information).

{{{Cc}}}ing the participants to #27958, which introduced this particular
wolf in the general Sage integration sheepshed...

URL: https://trac.sagemath.org/28913
Reported by: charpent
Ticket author(s): Frédéric Chapoton
Reviewer(s): Thierry Monteil
  • Loading branch information
Release Manager committed May 26, 2020
2 parents df2bc13 + 297033a commit 58f004f
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 11 deletions.
16 changes: 11 additions & 5 deletions src/sage/interfaces/giac.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,24 +580,30 @@ def cputime(self, t=None):
else:
return float(self('time() - %s'%float(t)))


def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if_needed=False):
"""
EXAMPLES::
sage: giac._eval_line('2+2')
'4'
sage: A=matrix([range(280)])
sage: GA=giac(A)
sage: A = matrix([range(280)])
sage: GA = giac(A)
TESTS::
sage: h='int(1/x*((-2*x^(1/3)+1)^(1/4))^3,x)'
sage: giac(h)
12*(...)
"""
with gc_disabled():
z = Expect._eval_line(self, line, allow_use_file=allow_use_file,
wait_for_prompt=wait_for_prompt)
if z.lower().find("error") != -1:
raise RuntimeError("An error occurred running a Giac command:\nINPUT:\n%s\nOUTPUT:\n%s"%(line, z))
return z

lines = (line for line in z.splitlines()
if not line.startswith('Evaluation time:'))
return "\n".join(lines)

def eval(self, code, strip=True, **kwds):
r"""
Expand Down
21 changes: 15 additions & 6 deletions src/sage/symbolic/integration/integral.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ def __init__(self):
sage: indefinite_integral(exp(x), 2*x)
2*e^x
TESTS:
Check for :trac:`28913`::
sage: Ex = (1-2*x^(1/3))^(3/4)/x
sage: integrate(Ex, x, algorithm="giac") # long time
4*(-2*x^(1/3) + 1)^(3/4) + 6*arctan((-2*x^(1/3) + 1)^(1/4)) - 3*log((-2*x^(1/3) + 1)^(1/4) + 1) + 3*log(abs((-2*x^(1/3) + 1)^(1/4) - 1))
"""
# The automatic evaluation routine will try these integrators
# in the given order. This is an attribute of the class instead of
Expand Down Expand Up @@ -179,7 +186,7 @@ def __init__(self):

def _eval_(self, f, x, a, b):
"""
Return the results of symbolic evaluation of the integral
Return the results of symbolic evaluation of the integral.
EXAMPLES::
Expand Down Expand Up @@ -217,12 +224,13 @@ def _eval_(self, f, x, a, b):

def _evalf_(self, f, x, a, b, parent=None, algorithm=None):
"""
Return a numerical approximation of the integral
Return a numerical approximation of the integral.
EXAMPLES::
sage: from sage.symbolic.integration.integral import definite_integral
sage: h = definite_integral(sin(x)*log(x)/x^2, x, 1, 2); h
sage: f = sin(x)*log(x)/x^2
sage: h = definite_integral(f, x, 1, 2, hold=True); h
integrate(log(x)*sin(x)/x^2, x, 1, 2)
sage: h.n() # indirect doctest
0.14839875208053...
Expand All @@ -241,7 +249,7 @@ def _evalf_(self, f, x, a, b, parent=None, algorithm=None):

def _tderivative_(self, f, x, a, b, diff_param=None):
"""
Return the derivative of symbolic integration
Return the derivative of symbolic integration.
EXAMPLES::
Expand All @@ -260,8 +268,9 @@ def _tderivative_(self, f, x, a, b, diff_param=None):
ans = definite_integral(f.diff(diff_param), x, a, b)
else:
ans = SR.zero()
return (ans + f.subs(x == b) * b.diff(diff_param)
- f.subs(x == a) * a.diff(diff_param))
return (ans
+ f.subs(x == b) * b.diff(diff_param)
- f.subs(x == a) * a.diff(diff_param))

def _print_latex_(self, f, x, a, b):
r"""
Expand Down

0 comments on commit 58f004f

Please sign in to comment.