Esempio n. 1
0
def full_compare(answer, response, vars=[], exclude=[]):
    """ Performs a full symbolic comparison between two expressions.
        This method will perform a full comparison between the two
        expressions passed to it. This will involve fully simplifying each
        and thencomparing to see if the result is the same. A list of the
        variables used must also be passed.

        Optionally a list of excluded expressions can also be passed. If
        the response matches one of the excluded expressions, using the
        simple compare method, then the comparison will return false. This
        is to allow questions such as "expand (x+1)^2" to stop the
        student just entering "(x+1)^2" and have SAGE accept it as a
        match to the correct answer.
        @type answer: string
        @param answer: the answer expression to compare against
        @type response: string
        @param response: the response expression entered by the student
        @type vars: array
        @param vars: an array of variable names used in the expressions
        @type exclude: array
        @param exclude: an array of expressions to exclude as invalid
        @rtype: bool
        @return: true if the expressions are equal, false otherwise
    """
    web.debug(
        "Full compare of '%s' to '%s' with variables '%s' excluding '%s'" %
        (answer, response, ','.join(vars), ';'.join(exclude)))
    try:
        answer = replace_variables(answer, vars)
        response = replace_variables(response, vars)
        answer = algebra.convert_latex(answer)
        response = algebra.convert_latex(response)
        sage.misc.preparser.implicit_multiplication(10)
        web.debug("Answer: " + answer)
        web.debug("Response: " + response)
        web.debug("Level: " +
                  str(sage.misc.preparser.implicit_multiplication()))
        answer = preparse(answer).replace('Integer',
                                          '').replace('RealNumber', '')
        response = preparse(response).replace('Integer',
                                              '').replace('RealNumber', '')
        web.debug("Answer: " + answer)
        web.debug("Response: " + response)
        answer_expr = symbolic_expression_from_string(answer)
        response_expr = symbolic_expression_from_string(response)
    except SyntaxError, e:
        web.debug("Error parsing answer and response expressions: %s" % e)
        f = "Error parsing answer and response expressions: %s" % e
        return f
Esempio n. 2
0
def simple_compare(expr1, expr2, vars=[]):
    """ Performs a simple symbolic comparison between two expressions.
        This method will perform a very simple comparision between two
        algebraic expressions. No expansion or factorization is performed
        hence expressions like "(x+1)^2" and "(1+x)^2" will evaluate as
        the same but expressions like "(x+1)^2" and "x^2+2*x+1" will not.
        @type expr1: string
        @param expr1: the first expression to compare
        @type expr2: string
        @param expr2: the second expression to compare
        @type vars: array
        @param vars: an array of variable names used in the expressions
        @rtype: bool
        @return: true if the expressions are equal, false otherwise
    """
    web.debug("Simple compare of '%s' to '%s' with variables %s" %
              (expr1, expr2, vars))
    expr1 = replace_variables(expr1, vars)
    expr2 = replace_variables(expr2, vars)
    expr1 = algebra.convert_latex(expr1)
    expr2 = algebra.convert_latex(expr2)

    sage.misc.preparser.implicit_multiplication(10)
    web.debug("Expr1: " + expr1)
    web.debug("Expr2: " + expr2)
    web.debug("Level: " + str(sage.misc.preparser.implicit_multiplication()))
    expr1 = preparse(expr1).replace('Integer', '').replace('RealNumber', '')
    expr2 = preparse(expr2).replace('Integer', '').replace('RealNumber', '')
    web.debug("Expr1: " + expr1)
    web.debug("Expr2: " + expr2)
    f = symbolic_expression_from_string("(%s)-(%s)" % (expr1, expr2))
    # Simply check to see if the representation of the expression is
    # a string containing the single character '0'.
    result = {'expr1': expr1, 'expr2': expr2, 'result': (f.__repr__() == '0')}
    return result
Esempio n. 3
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 != 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
Esempio n. 4
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)
    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)
Esempio n. 6
0
    def _sage_(self, locals={}):
        r"""
        Convert a giac expression back to a Sage expression, if possible.

        NOTES:

        This method works successfully when Giac 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 Giac's naming scheme through the symbols_table, or
            - you provide a translation dictionary ``locals``.

        New conversions can be added using Pynac's ``register_symbol``.
        This is the recommended approach for library code.

        .. WARNING:: List conversion is slow.

        EXAMPLES::

            sage: m = giac('x^2 + 5*y')
            sage: m.sage()
            x^2 + 5*y

        ::

            sage: m = giac('sin(2*sqrt(1-x^2)) * (1 - cos(1/x))^2')
            sage: m.trigexpand().sage()
            2*cos(sqrt(-x^2 + 1))*cos(1/x)^2*sin(sqrt(-x^2 + 1)) - 4*cos(sqrt(-x^2 + 1))*cos(1/x)*sin(sqrt(-x^2 + 1)) + 2*cos(sqrt(-x^2 + 1))*sin(sqrt(-x^2 + 1))

        Converting a custom name using the ``locals`` dictionary::

            sage: ex = giac('myFun(x)')
            sage: ex._sage_({'myFun': sin})
            sin(x)

        Same but by adding a new entry to the ``symbols_table``::

            sage: ex = giac('myFun(x)')
            sage: sage.libs.pynac.pynac.register_symbol(sin, {'giac':'myFun'})
            sage: ex._sage_()
            sin(x)

        Conversion of lists::

            sage: L = giac('solve((2/3)^x-2, x)'); L
            list[ln(2)/(ln(2)-ln(3))]
            sage: L.sage()
            [-ln(2)/(ln(3) - ln(2))]
        """
        from sage.libs.pynac.pynac import symbol_table
        from sage.calculus.calculus import symbolic_expression_from_string

        result = repr(self)  # string representation

        if str(self.type()) not in ['DOM_LIST', 'vector', 'vecteur']:

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

            try:
                return symbolic_expression_from_string(result,
                                                       lsymbols,
                                                       accept_sequence=True)

            except Exception:
                raise NotImplementedError("Unable to parse Giac output: %s" %
                                          result)
        else:
            return [entry.sage() for entry in self]
Esempio n. 7
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)
Esempio n. 8
0
def evaluate_expression(expr):
    f = symbolic_expression_from_string(expr)
    return f.__repr__()
Esempio n. 9
0
     response = preparse(response).replace('Integer',
                                           '').replace('RealNumber', '')
     web.debug("Answer: " + answer)
     web.debug("Response: " + response)
     answer_expr = symbolic_expression_from_string(answer)
     response_expr = symbolic_expression_from_string(response)
 except SyntaxError, e:
     web.debug("Error parsing answer and response expressions: %s" % e)
     f = "Error parsing answer and response expressions: %s" % e
     return f
 # First check for exlcuded responses
 for exc in exclude:
     exc = algebra.convert_latex(exc)
     exc = preparse(exc)
     # Create and expression from the excluded string
     expr = symbolic_expression_from_string(exc)
     # Take a difference between the excluded expression and the
     # response provided by the student
     diff = response_expr - expr
     # See if the difference has a representation of zero. If so it
     # matches with a simple comparison and so should be exlcuded.
     web.debug(diff)
     if diff.__repr__() == '0':
         # Response is excluded so immediately return false
         return {'expr1': answer, 'expr2': response, 'result': False}
 # Create an expression that is the difference of the answer and response
 web.debug('FINAL %s - %s' % (answer_expr, response_expr))
 f = (answer_expr) - (response_expr)
 web.debug('RESULT %s' % f)
 web.debug('RESULT %s' % f.simplify_full())
 # Simply use the 'is_zero' method to determine if the expressions are
Esempio n. 10
0
    def _sage_(self, locals={}):
        r"""
        Convert a giac expression back to a Sage expression, if possible.

        NOTES: 
        
        This method works successfully when Giac 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 Giac's naming scheme through the symbols_table, or
            - you provide a translation dictionary ``locals``.
            
        New conversions can be added using Pynac's ``register_symbol``.
        This is the recommended approach for library code.

        Warning: List conversion is slow.

        EXAMPLES::

        sage: m = giac('x^2 + 5*y')
        sage: m.sage()
        x^2 + 5*y

        ::

        sage: m = giac('sin(2*sqrt(1-x^2)) * (1 - cos(1/x))^2')
        sage: m.trigexpand().sage()
        2*cos(sqrt(-x^2 + 1))*cos(1/x)^2*sin(sqrt(-x^2 + 1)) - 4*cos(sqrt(-x^2 + 1))*cos(1/x)*sin(sqrt(-x^2 + 1)) + 2*cos(sqrt(-x^2 + 1))*sin(sqrt(-x^2 + 1))

        Converting a custom name using the ``locals`` dictionary::
        
        sage: ex = giac('myFun(x)')
        sage: ex._sage_({'myFun': sin})
        sin(x)
        
        Same but by adding a new entry to the ``symbols_table``::
        
        sage: ex = giac('myFun(x)')
        sage: sage.libs.pynac.pynac.register_symbol(sin, {'giac':'myFun'})
        sage: ex._sage_()
        sin(x)
        """
        from sage.libs.pynac.pynac import symbol_table
        from sage.calculus.calculus import symbolic_expression_from_string
        
        result = repr(self) # string representation
        
        if str(self.type()) != 'DOM_LIST' :   
            
            # Merge the user-specified locals dictionary and the symbol_table
            # (locals takes priority)
            lsymbols = symbol_table['giac'].copy()
            lsymbols.update(locals)    
            
            try:
                return symbolic_expression_from_string(result, lsymbols,
                    accept_sequence=True)
                    
            except Exception:
                raise NotImplementedError("Unable to parse Giac output: %s" % result)
        else:
            return [entry.sage() for entry in self]