コード例 #1
0
ファイル: mathematica.py プロジェクト: CETHop/sage
    def _sage_(self, locals={}):
        r"""
        Attempt to return a Sage version of this object.

        This method works successfully when Mathematica returns a result
        or list of results that consist only of:
        - numbers, i.e. integers, floats, complex numbers;
        - functions and named constants also present in Sage, where:
            - Sage knows how to translate the function or constant's name
            from Mathematica's naming scheme, or
            - you provide a translation dictionary `locals`, or
            - the Sage name for the function or constant is simply the
             Mathematica name in lower case;
        - symbolic variables whose names don't pathologically overlap with
          objects already defined in Sage.

        This method will not work when Mathematica's output includes:
        - strings;
        - functions unknown to Sage that are not specified in `locals`;
        - Mathematica functions with different parameters/parameter order to
          the Sage equivalent. In this case, define a function to do the
          parameter conversion, and pass it in via the locals dictionary.

        EXAMPLES:

        Mathematica lists of numbers/constants become Sage lists of
        numbers/constants::

            sage: m = mathematica('{{1., 4}, Pi, 3.2e100, I}')  # optional - mathematica
            sage: s = m.sage(); s       # optional - mathematica
            [[1.0, 4], pi, 3.2*e100, I]
            sage: s[1].n()              # optional - mathematica
            3.14159265358979
            sage: s[3]^2                # optional - mathematica
            -1

        ::

            sage: m = mathematica('x^2 + 5*y')      # optional - mathematica
            sage: m.sage()                          # optional - mathematica
            x^2 + 5*y

        ::

            sage: m = mathematica('Sin[Sqrt[1-x^2]] * (1 - Cos[1/x])^2')  # optional - mathematica
            sage: m.sage()                          # optional - mathematica
            (cos(1/x) - 1)^2*sin(sqrt(-x^2 + 1))

        ::

            sage: m = mathematica('NewFn[x]')       # optional - mathematica
            sage: m._sage_(locals={'NewFn': sin})   # optional - mathematica
            sin(x)

        ::

            sage: var('bla')                        # optional - mathematica
            bla
            sage: m = mathematica('bla^2')          # optional - mathematica
            sage: bla^2 - m.sage()                  # optional - mathematica
            0

        ::

            sage: m = mathematica('bla^2')          # optional - mathematica
            sage: mb = m.sage()                     # optional - mathematica
            sage: var('bla')                        # optional - mathematica
            bla
            sage: bla^2 - mb                        # optional - mathematica
            0


        AUTHORS:

        - Felix Lawrence (2010-11-03): Major rewrite to use ._sage_repr() and
          sage.calculus.calculus.symbolic_expression_from_string() for greater
          compatibility, while still supporting conversion of symbolic
          expressions.
        """
        from sage.symbolic.pynac import symbol_table
        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

        # Get Mathematica's output and perform preliminary formatting
        res = self._sage_repr()
        if '"' in res:
            raise NotImplementedError, "String conversion from Mathematica \
                does not work.  Mathematica's output was: %s" % res

        # Find all the mathematica functions, constants and symbolic variables
        # present in `res`.  Convert MMA functions and constants to their
        # Sage equivalents (if possible), using `locals` and
        # `sage.symbolic.pynac.symbol_table['mathematica']` as translation
        # dictionaries.  If a MMA function or constant is not either
        # dictionary, then we use a variety of tactics listed in `autotrans`.
        # If a MMA variable is not in any dictionary, then create an
        # identically named Sage equivalent.

        # Merge the user-specified locals dictionary and the symbol_table
        # (locals takes priority)
        lsymbols = symbol_table['mathematica'].copy()
        lsymbols.update(locals)

        # Strategies for translating unknown functions/constants:
        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('(?<!\.)[a-zA-Z]\w*')
        for m in p.finditer(res):
            # If the function, variable or constant is already in the
            # translation dictionary, then just move on.
            if m.group() in lsymbols:
                pass
            # Now try to translate all other functions -- try each strategy
            # in `autotrans` and check if the function exists in Sage
            elif m.end() < len(res) and res[m.end()] == '(':
                for t in autotrans:
                    f = find_func(t(m.group()), create_when_missing = False)
                    if f != None:
                        lsymbols[m.group()] = f
                        break
                else:
                    raise NotImplementedError, "Don't know a Sage equivalent \
                        for Mathematica function '%s'.  Please specify one \
                        manually using the 'locals' dictionary" % m.group()
            # Check if Sage has an equivalent constant
            else:
                for t in autotrans:
                    if t(m.group()) in constants:
                        lsymbols[m.group()] = constants[t(m.group())]
                        break
            # If Sage has never heard of the variable, then
            # symbolic_expression_from_string will automatically create it
        try:
            return symbolic_expression_from_string(res, lsymbols,
                accept_sequence=True)
        except StandardError:
            raise NotImplementedError, "Unable to parse Mathematica \
                output: %s" % res
コード例 #2
0
    def _sage_(self, locals={}):
        r"""
        Attempt to return a Sage version of this object.

        This method works successfully when Mathematica returns a result
        or list of results that consist only of:
        - numbers, i.e. integers, floats, complex numbers;
        - functions and named constants also present in Sage, where:
            - Sage knows how to translate the function or constant's name
            from Mathematica's naming scheme, or
            - you provide a translation dictionary `locals`, or
            - the Sage name for the function or constant is simply the
             Mathematica name in lower case;
        - symbolic variables whose names don't pathologically overlap with
          objects already defined in Sage.

        This method will not work when Mathematica's output includes:
        - strings;
        - functions unknown to Sage that are not specified in `locals`;
        - Mathematica functions with different parameters/parameter order to
          the Sage equivalent. In this case, define a function to do the
          parameter conversion, and pass it in via the locals dictionary.

        EXAMPLES:

        Mathematica lists of numbers/constants become Sage lists of
        numbers/constants::

            sage: m = mathematica('{{1., 4}, Pi, 3.2e100, I}')  # optional - mathematica
            sage: s = m.sage(); s       # optional - mathematica
            [[1.0, 4], pi, 3.2*e100, I]
            sage: s[1].n()              # optional - mathematica
            3.14159265358979
            sage: s[3]^2                # optional - mathematica
            -1

        ::

            sage: m = mathematica('x^2 + 5*y')      # optional - mathematica
            sage: m.sage()                          # optional - mathematica
            x^2 + 5*y

        ::

            sage: m = mathematica('Sin[Sqrt[1-x^2]] * (1 - Cos[1/x])^2')  # optional - mathematica
            sage: m.sage()                          # optional - mathematica
            (cos(1/x) - 1)^2*sin(sqrt(-x^2 + 1))

        ::

            sage: m = mathematica('NewFn[x]')       # optional - mathematica
            sage: m._sage_(locals={'NewFn': sin})   # optional - mathematica
            sin(x)

        ::

            sage: var('bla')                        # optional - mathematica
            bla
            sage: m = mathematica('bla^2')          # optional - mathematica
            sage: bla^2 - m.sage()                  # optional - mathematica
            0

        ::

            sage: m = mathematica('bla^2')          # optional - mathematica
            sage: mb = m.sage()                     # optional - mathematica
            sage: var('bla')                        # optional - mathematica
            bla
            sage: bla^2 - mb                        # optional - mathematica
            0


        AUTHORS:

        - Felix Lawrence (2010-11-03): Major rewrite to use ._sage_repr() and
          sage.calculus.calculus.symbolic_expression_from_string() for greater
          compatibility, while still supporting conversion of symbolic
          expressions.
        """
        from sage.symbolic.pynac import symbol_table
        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

        # Get Mathematica's output and perform preliminary formatting
        res = self._sage_repr()
        if '"' in res:
            raise NotImplementedError("String conversion from Mathematica \
                does not work.  Mathematica's output was: %s" % res)

        # Find all the mathematica functions, constants and symbolic variables
        # present in `res`.  Convert MMA functions and constants to their
        # Sage equivalents (if possible), using `locals` and
        # `sage.symbolic.pynac.symbol_table['mathematica']` as translation
        # dictionaries.  If a MMA function or constant is not either
        # dictionary, then we use a variety of tactics listed in `autotrans`.
        # If a MMA variable is not in any dictionary, then create an
        # identically named Sage equivalent.

        # Merge the user-specified locals dictionary and the symbol_table
        # (locals takes priority)
        lsymbols = symbol_table['mathematica'].copy()
        lsymbols.update(locals)

        # Strategies for translating unknown functions/constants:
        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('(?<!\.)[a-zA-Z]\w*')
        for m in p.finditer(res):
            # If the function, variable or constant is already in the
            # translation dictionary, then just move on.
            if m.group() in lsymbols:
                pass
            # Now try to translate all other functions -- try each strategy
            # in `autotrans` and check if the function exists in Sage
            elif m.end() < len(res) and res[m.end()] == '(':
                for t in autotrans:
                    f = find_func(t(m.group()), create_when_missing=False)
                    if f is not None:
                        lsymbols[m.group()] = f
                        break
                else:
                    raise NotImplementedError("Don't know a Sage equivalent \
                        for Mathematica function '%s'.  Please specify one \
                        manually using the 'locals' dictionary" % m.group())
            # Check if Sage has an equivalent constant
            else:
                for t in autotrans:
                    if t(m.group()) in constants:
                        lsymbols[m.group()] = constants[t(m.group())]
                        break
            # If Sage has never heard of the variable, then
            # symbolic_expression_from_string will automatically create it
        try:
            return symbolic_expression_from_string(res,
                                                   lsymbols,
                                                   accept_sequence=True)
        except Exception:
            raise NotImplementedError("Unable to parse Mathematica \
                output: %s" % res)
コード例 #3
0
def symbolic_expression_from_mathematica_string(mexpr):
    r"""
    Translate a mathematica string into a symbolic expression

    INPUT:

    - ``mexpr`` -- string

    OUTPUT:

    symbolic expression

    EXAMPLES::

        sage: from sage.symbolic.integration.external import symbolic_expression_from_mathematica_string
        sage: symbolic_expression_from_mathematica_string(u'-Cos[x]')
        -cos(x)

    """
    import re
    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 = [
        lambda x: x.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'(?<!\.)[a-zA-Z]\w*')

    for m in p.finditer(expr):
        # If the function, variable or constant is already in the
        # translation dictionary, then just move on.
        if m.group() in lsymbols:
            pass
        # Now try to translate all other functions -- try each strategy
        # in `autotrans` and check if the function exists in Sage
        elif m.end() < len(expr) and expr[m.end()] == '(':
            for t in autotrans:
                f = find_func(t(m.group()), create_when_missing=False)
                if f is not None:
                    lsymbols[m.group()] = f
                    break
            else:
                raise NotImplementedError(
                    "Don't know a Sage equivalent for Mathematica function '%s'."
                    % m.group())
        # Check if Sage has an equivalent constant
        else:
            for t in autotrans:
                if t(m.group()) in constants:
                    lsymbols[m.group()] = constants[t(m.group())]
                    break
    return symbolic_expression_from_string(expr,
                                           lsymbols,
                                           accept_sequence=True)
コード例 #4
0
def mma_free_integrator(expression, v, a=None, b=None):
    """
    Integration using Mathematica's online integrator

    EXAMPLES::

        sage: from sage.symbolic.integration.external import mma_free_integrator
        sage: mma_free_integrator(sin(x), x) # optional - internet
        -cos(x)

    TESTS:

    Check that :trac:`18212` is resolved::

        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

        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)
    """
    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("\s", "", page)
    mexpr = re.match(r".*Integrate.*==</em><br/>(.*)</p>", 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('(?<!\.)[a-zA-Z]\w*')

        for m in p.finditer(expr):
            # If the function, variable or constant is already in the
            # translation dictionary, then just move on.
            if m.group() in lsymbols:
                pass
            # Now try to translate all other functions -- try each strategy
            # in `autotrans` and check if the function exists in Sage
            elif m.end() < len(expr) and expr[m.end()] == '(':
                for t in autotrans:
                    f = find_func(t(m.group()), create_when_missing = False)
                    if f is not None:
                        lsymbols[m.group()] = f
                        break
                else:
                    raise NotImplementedError("Don't know a Sage equivalent for Mathematica function '%s'." % m.group())
            # Check if Sage has an equivalent constant
            else:
                for t in autotrans:
                    if t(m.group()) in constants:
                        lsymbols[m.group()] = constants[t(m.group())]
                        break
        ans = symbolic_expression_from_string(expr, lsymbols, accept_sequence=True)
        if repr(v) != 'x':
            ans = ans.subs({x:v}).subs({shadow_x:x})
        return ans
    except TypeError:
        raise ValueError("Unable to parse: %s" % mexpr)