Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
31873: replace giac by libgiac for integration
Browse files Browse the repository at this point in the history
This also fixes a misplaced sig_on() call that otherwise leads to a
doctest failure in interfaces/sympy.py.
  • Loading branch information
mwageringel committed Jun 16, 2021
1 parent 30ee8d6 commit 900ec88
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/sage/libs/giac/giac.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -898,12 +898,12 @@ cdef class Pygen(GiacMethods_base):
# Other types are converted with strings.
else:
sig_on()
if isinstance(s,Expression):
# take account of conversions with key giac in the sage symbol dict
s=SRexpressiontoGiac(s)
if not(isinstance(s,str)): #modif python3
s=s.__str__()
sig_on()
self.gptr = new gen(<string>encstring23(s),context_ptr)
sig_off()
Expand Down
12 changes: 9 additions & 3 deletions src/sage/symbolic/expression.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,9 @@ cdef class Expression(CommutativeRingElement):
EXAMPLES::
sage: i = var('i')
sage: integral(exp(x + x^2)/(x+1), x)._sympy_character_art(False)
sage: f = integral(exp(x + x^2)/(x+1), x)
...
sage: f._sympy_character_art(False)
' / \n | \n | 2 \n | x + x \n | e...'
"""
from sympy import pretty, sympify
Expand Down Expand Up @@ -11272,9 +11274,13 @@ cdef class Expression(CommutativeRingElement):
integrate(f(x) + g(x), x)
sage: integrate(f(x)+g(x),x).distribute()
integrate(f(x), x) + integrate(g(x), x)
sage: integrate(f(x)+g(x),x,a,b)
sage: result = integrate(f(x)+g(x),x,a,b)
...
sage: result
integrate(f(x) + g(x), x, a, b)
sage: integrate(f(x)+g(x),x,a,b).distribute()
sage: result = integrate(f(x)+g(x),x,a,b).distribute()
...
sage: result
integrate(f(x), x, a, b) + integrate(g(x), x, a, b)
sage: sum(X(j)+sum(Y(k)+Z(k),k,1,q),j,1,p)
sum(X(j) + sum(Y(k) + Z(k), k, 1, q), j, 1, p)
Expand Down
45 changes: 45 additions & 0 deletions src/sage/symbolic/integration/external.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,48 @@ def giac_integrator(expression, v, a=None, b=None):
return expression.integrate(v, a, b, hold=True)
else:
return result._sage_()

def libgiac_integrator(expression, v, a=None, b=None):
r"""
Integration using libgiac
EXAMPLES::
sage: import sage.libs.giac
...
sage: from sage.symbolic.integration.external import libgiac_integrator
sage: libgiac_integrator(sin(x), x)
-cos(x)
sage: libgiac_integrator(1/(x^2+6), x, -oo, oo)
No checks were made for singular points of antiderivative...
1/6*sqrt(6)*pi
TESTS::
sage: libgiac_integrator(e^(-x^2)*log(x), x)
integrate(e^(-x^2)*log(x), x)
The following integral fails with the Giac Pexpect interface, but works
with libgiac (:trac:`31873`)::
sage: a, x = var('a,x')
sage: f = sec(2*a*x)
sage: F = libgiac_integrator(f, x)
...
sage: (F.derivative(x) - f).simplify_trig()
0
"""
from sage.libs.giac import libgiac
from sage.libs.giac.giac import Pygen
# We call Pygen on first argument because otherwise some expressions
# involving derivatives result in doctest failures in interfaces/sympy.py
# -- related to the fixme note in sage.libs.giac.giac.GiacFunction.__call__
# regarding conversion of lists.
if a is None:
result = libgiac.integrate(Pygen(expression), v)
else:
result = libgiac.integrate(Pygen(expression), v, a, b)
if 'integrate' in format(result) or 'integration' in format(result):
return expression.integrate(v, a, b, hold=True)
else:
return result.sage()
69 changes: 51 additions & 18 deletions src/sage/symbolic/integration/integral.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
available_integrators['mathematica_free'] = external.mma_free_integrator
available_integrators['fricas'] = external.fricas_integrator
available_integrators['giac'] = external.giac_integrator
available_integrators['libgiac'] = external.libgiac_integrator

######################################################
#
Expand Down Expand Up @@ -71,15 +72,17 @@ def __init__(self):
Check for :trac:`25119`::
sage: integrate(sqrt(x^2)/x,x)
sage: result = integrate(sqrt(x^2)/x,x)
...
sage: result
x*sgn(x)
"""
# The automatic evaluation routine will try these integrators
# in the given order. This is an attribute of the class instead of
# a global variable in this module to enable customization by
# creating a subclasses which define a different set of integrators
self.integrators = [external.maxima_integrator,
external.giac_integrator,
external.libgiac_integrator,
external.sympy_integrator]

BuiltinFunction.__init__(self, "integrate", nargs=2, conversions={'sympy': 'Integral',
Expand Down Expand Up @@ -189,7 +192,7 @@ def __init__(self):
# a global variable in this module to enable customization by
# creating a subclasses which define a different set of integrators
self.integrators = [external.maxima_integrator,
external.giac_integrator,
external.libgiac_integrator,
external.sympy_integrator]

BuiltinFunction.__init__(self, "integrate", nargs=4, conversions={'sympy': 'Integral',
Expand Down Expand Up @@ -268,6 +271,7 @@ def _tderivative_(self, f, x, a, b, diff_param=None):
sage: from sage.symbolic.integration.integral import definite_integral
sage: f = function('f'); a,b=var('a,b')
sage: h = definite_integral(f(x), x,a,b)
...
sage: h.diff(x) # indirect doctest
0
sage: h.diff(a)
Expand Down Expand Up @@ -425,9 +429,9 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False):
- ``b`` - (optional) upper endpoint of definite integral
- ``algorithm`` - (default: 'maxima') one of
- ``algorithm`` - (default: 'maxima', 'libgiac' and 'sympy') one of
- 'maxima' - use maxima (the default)
- 'maxima' - use maxima
- 'sympy' - use sympy (also in Sage)
Expand All @@ -437,6 +441,8 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False):
- 'giac' - use Giac
- 'libgiac' - use libgiac
To prevent automatic evaluation use the ``hold`` argument.
.. SEEALSO::
Expand Down Expand Up @@ -623,7 +629,9 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False):
where the default integrator obtains another answer::
sage: integrate(f(x), x)
sage: result = integrate(f(x), x)
...
sage: result
1/8*sqrt(x)*gamma(1/4)*gamma(-1/4)^2*hypergeometric((-1/4, -1/4, 1/4), (1/2, 3/4), -1/x^2)/(pi*gamma(3/4))
The following definite integral is not found by maxima::
Expand All @@ -648,7 +656,9 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False):
sage: integrate(abs(cos(x)), x, 0, 2*pi, algorithm='giac')
4
sage: integrate(abs(cos(x)), x, 0, 2*pi)
sage: result = integrate(abs(cos(x)), x, 0, 2*pi)
...
sage: result
4
ALIASES: integral() and integrate() are the same.
Expand Down Expand Up @@ -795,7 +805,9 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False):
the previous (wrong) answer of zero. See :trac:`10914`::
sage: f = abs(sin(x))
sage: integrate(f, x, 0, 2*pi)
sage: result = integrate(f, x, 0, 2*pi)
...
sage: result
4
Another incorrect integral fixed upstream in Maxima, from
Expand Down Expand Up @@ -891,42 +903,63 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False):
Some integrals are now working (:trac:`27958`, using giac or sympy)::
sage: integrate(1/(1 + abs(x)), x)
sage: result = integrate(1/(1 + abs(x)), x)
...
sage: result
log(abs(x*sgn(x) + 1))/sgn(x)
sage: integrate(cos(x + abs(x)), x)
sage: result = integrate(cos(x + abs(x)), x)
...
sage: result
sin(x*sgn(x) + x)/(sgn(x) + 1)
sage: integrate(abs(x^2 - 1), x, -2, 2)
sage: result = integrate(abs(x^2 - 1), x, -2, 2)
...
sage: result
4
sage: f = sqrt(x + 1/x^2)
sage: actual = integrate(f, x)
...
sage: expected = (1/3*(2*sqrt(x^3 + 1) - log(sqrt(x^3 + 1) + 1)
....: + log(abs(sqrt(x^3 + 1) - 1)))*sgn(x))
sage: bool(actual == expected)
True
sage: g = abs(sin(x)*cos(x))
sage: g.integrate(x, 0, 2*pi)
sage: result = g.integrate(x, 0, 2*pi)
...
sage: result
2
sage: integrate(1/sqrt(abs(x)), x)
sage: result = integrate(1/sqrt(abs(x)), x)
...
sage: result
2*sqrt(x*sgn(x))/sgn(x)
sage: integrate(sgn(x) - sgn(1-x), x)
sage: result = integrate(sgn(x) - sgn(1-x), x)
...
sage: result
x*(sgn(x) - sgn(-x + 1)) + sgn(-x + 1)
sage: integrate(1 / (1 + abs(x-5)), x, -5, 6)
sage: result = integrate(1 / (1 + abs(x-5)), x, -5, 6)
...
sage: result
log(11) + log(2)
sage: integrate(1/(1 + abs(x)), x)
sage: result = integrate(1/(1 + abs(x)), x)
...
sage: result
log(abs(x*sgn(x) + 1))/sgn(x)
sage: integrate(cos(x + abs(x)), x)
sage: result = integrate(cos(x + abs(x)), x)
...
sage: result
sin(x*sgn(x) + x)/(sgn(x) + 1)
sage: integrate(abs(x^2 - 1), x, -2, 2)
sage: result = integrate(abs(x^2 - 1), x, -2, 2)
...
sage: result
4
Some tests for :trac:`17468`::
Expand Down

0 comments on commit 900ec88

Please sign in to comment.