From 11791c54ac7a0227f13f12f5dd256e2c1cab152e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?=
Date: Wed, 12 Dec 2018 23:19:21 +0100
Subject: [PATCH 1/4] 25501: fixing the mma integrator
---
src/sage/symbolic/integration/external.py | 318 +++++++++++++++++-----
src/sage/symbolic/integration/integral.py | 2 +-
2 files changed, 254 insertions(+), 66 deletions(-)
diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py
index d938a29e6ba..6b9fdc046c2 100644
--- a/src/sage/symbolic/integration/external.py
+++ b/src/sage/symbolic/integration/external.py
@@ -65,6 +65,11 @@ def mma_free_integrator(expression, v, a=None, b=None):
sage: mma_free_integrator(sin(x), x) # optional - internet
-cos(x)
+ A definite integral::
+
+ sage: mma_free_integrator(e^(-x), x, a=0, b=oo) # optional - internet
+ 1
+
TESTS:
Check that :trac:`18212` is resolved::
@@ -72,78 +77,261 @@ def mma_free_integrator(expression, v, a=None, b=None):
sage: var('y') # optional - internet
y
sage: integral(sin(y)^2, y, algorithm='mathematica_free') # optional - internet
- -1/2*cos(y)*sin(y) + 1/2*y
+ 1/2*y - 1/4*sin(2*y)
+
+ ::
sage: mma_free_integrator(exp(-x^2)*log(x), x) # optional - internet
1/2*sqrt(pi)*erf(x)*log(x) - x*hypergeometric((1/2, 1/2), (3/2, 3/2), -x^2)
+
+ """
+ math_expr = expression._mathematica_init_()
+ variable = v._mathematica_init_()
+ if a is None and b is None:
+ input = "Integrate[{},{}]".format(math_expr, variable)
+ elif a is not None and b is not None:
+ input = "Integrate[{},{{{},{},{}}}]".format(math_expr, variable,
+ a._mathematica_init_(), b._mathematica_init_())
+ else:
+ raise ValueError('a(={}) and b(={}) should be both None'
+ ' or both defined'.format(a,b))
+ json_page_data = request_wolfram_alpha(input)
+ all_outputs = parse_moutput_from_json(json_page_data)
+ if not all_outputs:
+ raise ValueError("no outputs found in the answer from Wolfram Alpha")
+ first_output = all_outputs[0]
+ return symbolic_expression_from_mathematica_string(first_output)
+
+def request_wolfram_alpha(input, verbose=False):
+ r"""
+ Request Wolfram Alpha website.
+
+ INPUT:
+
+ - ``input`` -- string
+ - ``verbose`` -- bool (default: ``False``)
+
+ OUTPUT:
+
+ json
+
+ EXAMPLES::
+
+ sage: from sage.symbolic.integration.external import request_wolfram_alpha
+ sage: page_data = request_wolfram_alpha('integrate Sin[x]') # optional internet
+ sage: page_data.keys() # optional internet
+ [u'queryresult']
+ sage: page_data['queryresult'].keys() # optional internet
+ [u'sponsorCategories',
+ u'parsetimedout',
+ u'success',
+ u'timedoutpods',
+ u'parsetiming',
+ u'id',
+ u'timedout',
+ u'related',
+ u'numpods',
+ u'host',
+ u'version',
+ u'encryptedParsedExpression',
+ u'encryptedEvaluatedExpression',
+ u'error',
+ u'timing',
+ u'datatypes',
+ u'server',
+ u'pods',
+ u'recalculate']
+
"""
- import re
# import compatible with py2 and py3
- from six.moves.urllib.request import urlopen
from six.moves.urllib.parse import urlencode
- # We need to integrate against x
- vars = [str(x) for x in expression.variables()]
- if any(len(x)>1 for x in vars):
- raise NotImplementedError("Mathematica online integrator can only handle single letter variables.")
- x = SR.var('x')
- if repr(v) != 'x':
- for i in range(ord('a'), ord('z')+1):
- if chr(i) not in vars:
- shadow_x = SR.var(chr(i))
- break
- expression = expression.subs({x:shadow_x}).subs({v: x})
- params = urlencode({'expr': expression._mathematica_init_(), 'random': 'false'})
- page = urlopen("http://integrals.wolfram.com/home.jsp", params).read()
- page = page[page.index('"inputForm"'):page.index('"outputForm"')]
- page = re.sub(r"\s", "", page)
- mexpr = re.match(r".*Integrate.*==
(.*)
", page).groups()[0]
- try:
- from sage.libs.pynac.pynac import symbol_table
- from sage.interfaces.mathematica import _un_camel as un_camel
- from sage.symbolic.constants import constants_name_table as constants
- from sage.calculus.calculus import symbolic_expression_from_string
- from sage.calculus.calculus import _find_func as find_func
-
- expr = mexpr.replace('\n',' ').replace('\r', '')
- expr = expr.replace('[', '(').replace(']', ')')
- expr = expr.replace('{', '[').replace('}', ']')
- lsymbols = symbol_table['mathematica'].copy()
- autotrans = [str.lower, # Try it in lower case
- un_camel, # Convert `CamelCase` to `camel_case`
- lambda x: x # Try the original name
- ]
- # Find the MMA funcs/vars/constants - they start with a letter.
- # Exclude exponents (e.g. 'e8' from 4.e8)
- p = re.compile(r'(?
Date: Thu, 20 Dec 2018 11:11:15 +0100
Subject: [PATCH 2/4] 25501: Python 3 care
---
src/sage/symbolic/integration/external.py | 46 +++++++++++------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py
index 6b9fdc046c2..b0f20373812 100644
--- a/src/sage/symbolic/integration/external.py
+++ b/src/sage/symbolic/integration/external.py
@@ -119,28 +119,28 @@ def request_wolfram_alpha(input, verbose=False):
sage: from sage.symbolic.integration.external import request_wolfram_alpha
sage: page_data = request_wolfram_alpha('integrate Sin[x]') # optional internet
- sage: page_data.keys() # optional internet
- [u'queryresult']
- sage: page_data['queryresult'].keys() # optional internet
- [u'sponsorCategories',
- u'parsetimedout',
- u'success',
- u'timedoutpods',
- u'parsetiming',
- u'id',
- u'timedout',
- u'related',
- u'numpods',
- u'host',
- u'version',
- u'encryptedParsedExpression',
- u'encryptedEvaluatedExpression',
- u'error',
- u'timing',
- u'datatypes',
- u'server',
- u'pods',
- u'recalculate']
+ sage: sorted(page_data.keys()) # optional internet
+ ['queryresult']
+ sage: sorted(page_data['queryresult'].keys()) # optional internet
+ ['datatypes',
+ 'encryptedEvaluatedExpression',
+ 'encryptedParsedExpression',
+ 'error',
+ 'host',
+ 'id',
+ 'numpods',
+ 'parsetimedout',
+ 'parsetiming',
+ 'pods',
+ 'recalculate',
+ 'related',
+ 'server',
+ 'sponsorCategories',
+ 'success',
+ 'timedout',
+ 'timedoutpods',
+ 'timing',
+ 'version']
"""
# import compatible with py2 and py3
@@ -302,7 +302,7 @@ def symbolic_expression_from_mathematica_string(mexpr):
expr = expr.replace('[', '(').replace(']', ')')
expr = expr.replace('{', '[').replace('}', ']')
lsymbols = symbol_table['mathematica'].copy()
- autotrans = [unicode.lower, # Try it in lower case
+ autotrans = [lambda x:x.lower(), # Try it in lower case
un_camel, # Convert `CamelCase` to `camel_case`
lambda x: x # Try the original name
]
From 76ad1cb684c219ce283cbbebe7281655fd18bff7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?=
Date: Thu, 20 Dec 2018 11:30:49 +0100
Subject: [PATCH 3/4] 25501: fix back for Python 2
---
src/sage/symbolic/integration/external.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py
index b0f20373812..5ed6e2135ea 100644
--- a/src/sage/symbolic/integration/external.py
+++ b/src/sage/symbolic/integration/external.py
@@ -118,10 +118,10 @@ def request_wolfram_alpha(input, verbose=False):
EXAMPLES::
sage: from sage.symbolic.integration.external import request_wolfram_alpha
- sage: page_data = request_wolfram_alpha('integrate Sin[x]') # optional internet
- sage: sorted(page_data.keys()) # optional internet
+ sage: page_data = request_wolfram_alpha('integrate Sin[x]') # optional internet
+ sage: [str(a) for a in sorted(page_data.keys())] # optional internet
['queryresult']
- sage: sorted(page_data['queryresult'].keys()) # optional internet
+ sage: [str(a) for a in sorted(page_data['queryresult'].keys())] # optional internet
['datatypes',
'encryptedEvaluatedExpression',
'encryptedParsedExpression',
From f083393998f39847e4cf93a65ee72036c74506f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?=
Date: Mon, 31 Dec 2018 13:32:50 +0100
Subject: [PATCH 4/4] 25501: adding missing optional tags
---
src/sage/symbolic/integration/external.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py
index 5ed6e2135ea..e8fc81f4662 100644
--- a/src/sage/symbolic/integration/external.py
+++ b/src/sage/symbolic/integration/external.py
@@ -237,8 +237,8 @@ def parse_moutput_from_json(page_data, verbose=False):
TESTS::
- sage: page_data = request_wolfram_alpha('Integrate(Sin[z], y)')
- sage: parse_moutput_from_json(page_data)
+ sage: page_data = request_wolfram_alpha('Integrate(Sin[z], y)') # optional internet
+ sage: parse_moutput_from_json(page_data) # optional internet
Traceback (most recent call last):
...
ValueError: asking wolframalpha.com was not successful