sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.38k stars 470 forks source link

#34062 may have introduce new problems with Mathematica handling of locals and some native functions #34457

Open 7822f248-ba56-45f1-ab3d-4de7482bdf9f opened 2 years ago

7822f248-ba56-45f1-ab3d-4de7482bdf9f commented 2 years ago

34602 considerably enhanced the use of many Mathematica functions unknown to Sage :

sage: foo = mathematica("Hypergeometric2F1[a, b, c, d]") ; foo
Hypergeometric2F1[a, b, c, d]
sage: bar = foo.sage() ; bar
Hypergeometric2F1(a, b, c, d)

A new symbolic function was created on the fly, which can be substituted afterwards :

sage: bar.operator()
Hypergeometric2F1
sage: bar.operator().parent()
<class 'sage.symbolic.function_factory.function_factory.<locals>.NewSymbolicFunction'>
sage: bar.substitute_function(bar.operator(), lambda *args:hypergeometric(args[:2], args[2:3], args[3]))
hypergeometric((a, b), (c,), d)

or on the fly :

sage: foo.sage(locals={("Hypergeometric2F1", 4): lambda a, b, c, d:hypergeometric([a, b], [c], d)})
hypergeometric((a, b), (c,), d)

or

sage: foo.sage(locals={("Hypergeometric2F1", 4): lambda *args:hypergeometric(args[:2], args[2:3], args[3])})
hypergeometric((a, b), (c,), d)

Note that the docsting of the ._sage_ method doesn't specify much the composition of locals...

But there are snags : given

sage: gee = mathematica.Gamma(a) ; gee
Gamma[a]

nothing works as expected :

sage: gee.sage()
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
File /usr/local/sage-9/src/sage/interfaces/mathematica.py:913, in MathematicaElement._sage_(self, locals)
    912 try:
--> 913     return symbolic_expression_from_string(res, lsymbols,
    914         accept_sequence=True)
    915 except Exception:

File /usr/local/sage-9/src/sage/calculus/calculus.py:2579, in symbolic_expression_from_string(s, syms, accept_sequence, parser)
   2577 parser._callable_constructor().set_names({k[0]: v for k, v in syms.items()
   2578                                           if _is_function(v)})
-> 2579 return parse_func(s)

File /usr/local/sage-9/src/sage/misc/parser.pyx:575, in sage.misc.parser.Parser.parse_sequence()
    574 
--> 575     cpdef parse_sequence(self, s):
    576         """

File /usr/local/sage-9/src/sage/misc/parser.pyx:591, in sage.misc.parser.Parser.parse_sequence()
    590 cdef Tokenizer tokens = Tokenizer(s)
--> 591 all = self.p_sequence(tokens)
    592 if tokens.next() != EOS:

File /usr/local/sage-9/src/sage/misc/parser.pyx:664, in sage.misc.parser.Parser.p_sequence()
    663 else:
--> 664     obj = self.p_eqn(tokens)
    665 PyList_Append(all, obj)

File /usr/local/sage-9/src/sage/misc/parser.pyx:754, in sage.misc.parser.Parser.p_eqn()
    753 """
--> 754 lhs = self.p_expr(tokens)
    755 cdef int op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:794, in sage.misc.parser.Parser.p_expr()
    793 cdef int op
--> 794 operand1 = self.p_term(tokens)
    795 op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:828, in sage.misc.parser.Parser.p_term()
    827 cdef int op
--> 828 operand1 = self.p_factor(tokens)
    829 op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:871, in sage.misc.parser.Parser.p_factor()
    870 tokens.backtrack()
--> 871 return self.p_power(tokens)
    872 

File /usr/local/sage-9/src/sage/misc/parser.pyx:899, in sage.misc.parser.Parser.p_power()
    898 """
--> 899 operand1 = self.p_atom(tokens)
    900 cdef int token = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:958, in sage.misc.parser.Parser.p_atom()
    957         self.parse_error(tokens, "Bad function call")
--> 958     return func(*args, **kwds)
    959 else:

File /usr/local/sage-9/src/sage/functions/gamma.py:726, in _mathematica_gamma3(*args)
    716 r"""
    717 EXAMPLES::
    718 
   (...)
    724     gamma(4/3) - gamma(4/3, 1)
    725 """
--> 726 assert len(args) == 3
    727 return gamma_inc(args[0], args[1]) - gamma_inc(args[0], args[2])

AssertionError: 

During handling of the above exception, another exception occurred:

NotImplementedError                       Traceback (most recent call last)
Input In [581], in <cell line: 1>()
----> 1 gee.sage()

File /usr/local/sage-9/src/sage/interfaces/interface.py:1107, in InterfaceElement.sage(self, *args, **kwds)
   1088 def sage(self, *args, **kwds):
   1089     """
   1090     Attempt to return a Sage version of this object.
   1091 
   (...)
   1105         [0 0]
   1106     """
-> 1107     return self._sage_(*args, **kwds)

File /usr/local/sage-9/src/sage/interfaces/mathematica.py:916, in MathematicaElement._sage_(self, locals)
    913     return symbolic_expression_from_string(res, lsymbols,
    914         accept_sequence=True)
    915 except Exception:
--> 916     raise NotImplementedError("Unable to parse Mathematica \
    917         output: %s" % res)

NotImplementedError: Unable to parse Mathematica                 output: Gamma(a)

This shouldn't happen : gamma and it's Mathematica translation Gamma have been known to Sage at least since Rome foundation (732 BC)...

Neither

sage: gee.sage(locals={"Gamma": gamma}) # Old style locals
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
File /usr/local/sage-9/src/sage/interfaces/mathematica.py:913, in MathematicaElement._sage_(self, locals)
    912 try:
--> 913     return symbolic_expression_from_string(res, lsymbols,
    914         accept_sequence=True)
    915 except Exception:

File /usr/local/sage-9/src/sage/calculus/calculus.py:2579, in symbolic_expression_from_string(s, syms, accept_sequence, parser)
   2577 parser._callable_constructor().set_names({k[0]: v for k, v in syms.items()
   2578                                           if _is_function(v)})
-> 2579 return parse_func(s)

File /usr/local/sage-9/src/sage/misc/parser.pyx:575, in sage.misc.parser.Parser.parse_sequence()
    574 
--> 575     cpdef parse_sequence(self, s):
    576         """

File /usr/local/sage-9/src/sage/misc/parser.pyx:591, in sage.misc.parser.Parser.parse_sequence()
    590 cdef Tokenizer tokens = Tokenizer(s)
--> 591 all = self.p_sequence(tokens)
    592 if tokens.next() != EOS:

File /usr/local/sage-9/src/sage/misc/parser.pyx:664, in sage.misc.parser.Parser.p_sequence()
    663 else:
--> 664     obj = self.p_eqn(tokens)
    665 PyList_Append(all, obj)

File /usr/local/sage-9/src/sage/misc/parser.pyx:754, in sage.misc.parser.Parser.p_eqn()
    753 """
--> 754 lhs = self.p_expr(tokens)
    755 cdef int op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:794, in sage.misc.parser.Parser.p_expr()
    793 cdef int op
--> 794 operand1 = self.p_term(tokens)
    795 op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:828, in sage.misc.parser.Parser.p_term()
    827 cdef int op
--> 828 operand1 = self.p_factor(tokens)
    829 op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:871, in sage.misc.parser.Parser.p_factor()
    870 tokens.backtrack()
--> 871 return self.p_power(tokens)
    872 

File /usr/local/sage-9/src/sage/misc/parser.pyx:899, in sage.misc.parser.Parser.p_power()
    898 """
--> 899 operand1 = self.p_atom(tokens)
    900 cdef int token = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:958, in sage.misc.parser.Parser.p_atom()
    957         self.parse_error(tokens, "Bad function call")
--> 958     return func(*args, **kwds)
    959 else:

File /usr/local/sage-9/src/sage/functions/gamma.py:726, in _mathematica_gamma3(*args)
    716 r"""
    717 EXAMPLES::
    718 
   (...)
    724     gamma(4/3) - gamma(4/3, 1)
    725 """
--> 726 assert len(args) == 3
    727 return gamma_inc(args[0], args[1]) - gamma_inc(args[0], args[2])

AssertionError: 

During handling of the above exception, another exception occurred:

NotImplementedError                       Traceback (most recent call last)
Input In [585], in <cell line: 1>()
----> 1 gee.sage(locals={"Gamma": gamma}) # Old style locals

File /usr/local/sage-9/src/sage/interfaces/interface.py:1107, in InterfaceElement.sage(self, *args, **kwds)
   1088 def sage(self, *args, **kwds):
   1089     """
   1090     Attempt to return a Sage version of this object.
   1091 
   (...)
   1105         [0 0]
   1106     """
-> 1107     return self._sage_(*args, **kwds)

File /usr/local/sage-9/src/sage/interfaces/mathematica.py:916, in MathematicaElement._sage_(self, locals)
    913     return symbolic_expression_from_string(res, lsymbols,
    914         accept_sequence=True)
    915 except Exception:
--> 916     raise NotImplementedError("Unable to parse Mathematica \
    917         output: %s" % res)

NotImplementedError: Unable to parse Mathematica                 output: Gamma(a)

Nor :

sage: gee.sage(locals={("Gamma", 1): gamma}) # New style locals
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
File /usr/local/sage-9/src/sage/interfaces/mathematica.py:913, in MathematicaElement._sage_(self, locals)
    912 try:
--> 913     return symbolic_expression_from_string(res, lsymbols,
    914         accept_sequence=True)
    915 except Exception:

File /usr/local/sage-9/src/sage/calculus/calculus.py:2579, in symbolic_expression_from_string(s, syms, accept_sequence, parser)
   2577 parser._callable_constructor().set_names({k[0]: v for k, v in syms.items()
   2578                                           if _is_function(v)})
-> 2579 return parse_func(s)

File /usr/local/sage-9/src/sage/misc/parser.pyx:575, in sage.misc.parser.Parser.parse_sequence()
    574 
--> 575     cpdef parse_sequence(self, s):
    576         """

File /usr/local/sage-9/src/sage/misc/parser.pyx:591, in sage.misc.parser.Parser.parse_sequence()
    590 cdef Tokenizer tokens = Tokenizer(s)
--> 591 all = self.p_sequence(tokens)
    592 if tokens.next() != EOS:

File /usr/local/sage-9/src/sage/misc/parser.pyx:664, in sage.misc.parser.Parser.p_sequence()
    663 else:
--> 664     obj = self.p_eqn(tokens)
    665 PyList_Append(all, obj)

File /usr/local/sage-9/src/sage/misc/parser.pyx:754, in sage.misc.parser.Parser.p_eqn()
    753 """
--> 754 lhs = self.p_expr(tokens)
    755 cdef int op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:794, in sage.misc.parser.Parser.p_expr()
    793 cdef int op
--> 794 operand1 = self.p_term(tokens)
    795 op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:828, in sage.misc.parser.Parser.p_term()
    827 cdef int op
--> 828 operand1 = self.p_factor(tokens)
    829 op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:871, in sage.misc.parser.Parser.p_factor()
    870 tokens.backtrack()
--> 871 return self.p_power(tokens)
    872 

File /usr/local/sage-9/src/sage/misc/parser.pyx:899, in sage.misc.parser.Parser.p_power()
    898 """
--> 899 operand1 = self.p_atom(tokens)
    900 cdef int token = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:958, in sage.misc.parser.Parser.p_atom()
    957         self.parse_error(tokens, "Bad function call")
--> 958     return func(*args, **kwds)
    959 else:

File /usr/local/sage-9/src/sage/functions/gamma.py:726, in _mathematica_gamma3(*args)
    716 r"""
    717 EXAMPLES::
    718 
   (...)
    724     gamma(4/3) - gamma(4/3, 1)
    725 """
--> 726 assert len(args) == 3
    727 return gamma_inc(args[0], args[1]) - gamma_inc(args[0], args[2])

AssertionError: 

During handling of the above exception, another exception occurred:

NotImplementedError                       Traceback (most recent call last)
Input In [587], in <cell line: 1>()
----> 1 gee.sage(locals={("Gamma", Integer(1)): gamma}) # New style locals

File /usr/local/sage-9/src/sage/interfaces/interface.py:1107, in InterfaceElement.sage(self, *args, **kwds)
   1088 def sage(self, *args, **kwds):
   1089     """
   1090     Attempt to return a Sage version of this object.
   1091 
   (...)
   1105         [0 0]
   1106     """
-> 1107     return self._sage_(*args, **kwds)

File /usr/local/sage-9/src/sage/interfaces/mathematica.py:916, in MathematicaElement._sage_(self, locals)
    913     return symbolic_expression_from_string(res, lsymbols,
    914         accept_sequence=True)
    915 except Exception:
--> 916     raise NotImplementedError("Unable to parse Mathematica \
    917         output: %s" % res)

NotImplementedError: Unable to parse Mathematica                 output: Gamma(a)

work.

Priority set to critical since Sage stopped previously-known results.

CC: @fchapoton

Component: interfaces

Keywords: mathematica symbol_table interface gamma

Branch/Commit: public/mathica_fixtry @ 29b0cee

Issue created by migration from https://trac.sagemath.org/ticket/34457

7822f248-ba56-45f1-ab3d-4de7482bdf9f commented 2 years ago

Changed keywords from mathematica symbol_table interface to mathematica symbol_table interface gamma

7822f248-ba56-45f1-ab3d-4de7482bdf9f commented 2 years ago
comment:1

In all failures reported above, the error is triggered on the assert len(args) == 3 error. This my be an error specific to gamma.

Some specific, systematic testing may be in order...

fchapoton commented 2 years ago
comment:2

Je peux pas faire grand chose sans avoir acces a m....ca

Voici une branche avec une tentative à l'aveugle.

Not critical, as this concerns an optional interface.


New commits:

29b0ceemathematica interface
fchapoton commented 2 years ago

Commit: 29b0cee

fchapoton commented 2 years ago

Branch: public/mathica_fixtry

7822f248-ba56-45f1-ab3d-4de7482bdf9f commented 2 years ago
comment:3

Replying to @fchapoton:

Je peux pas faire grand chose sans avoir acces a m....ca

Selon print(mathematica._install_hints()) :

(1) You might have to buy Mathematica (https://www.wolfram.com/), or install a currently (Feb 2022) free for personal use Wolfram Engine (https://www.wolfram.com/engine/).

J'ai testé (installation secondaire de Sage dans une machine virtuelle tournant "Doze, nécessaire dans les mines de sel administratives...). Çà marche, et çà semble remarquablement peu intrusif.

Voici une branche avec une tentative à l'aveugle.

Je regarde çà d'ici 2 heures...

Not critical, as this concerns an optional interface.

Hmmm... mathematica.py fait partie du corps de Sage (pas même un module standard), et interface à un logiciel (trop) connu et désormais gratis (mais loin d'être libre...) ==> risque de devenir une part de facto standard d'une installation "par défaut".

7822f248-ba56-45f1-ab3d-4de7482bdf9f commented 2 years ago
comment:4

Replying to @fchapoton:

Je peux pas faire grand chose sans avoir acces a m....ca

Voici une branche avec une tentative à l'aveugle.

Nope. On top of 9.7.beta0 :

sage: mathematica.Gamma(x).sage()
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
File /usr/local/sage-9/src/sage/interfaces/mathematica.py:913, in MathematicaElement._sage_(self, locals)
    912 try:
--> 913     return symbolic_expression_from_string(res, lsymbols,
    914         accept_sequence=True)
    915 except Exception:

File /usr/local/sage-9/src/sage/calculus/calculus.py:2579, in symbolic_expression_from_string(s, syms, accept_sequence, parser)
   2577 parser._callable_constructor().set_names({k[0]: v for k, v in syms.items()
   2578                                           if _is_function(v)})
-> 2579 return parse_func(s)

File /usr/local/sage-9/src/sage/misc/parser.pyx:575, in sage.misc.parser.Parser.parse_sequence()
    574 
--> 575     cpdef parse_sequence(self, s):
    576         """

File /usr/local/sage-9/src/sage/misc/parser.pyx:591, in sage.misc.parser.Parser.parse_sequence()
    590 cdef Tokenizer tokens = Tokenizer(s)
--> 591 all = self.p_sequence(tokens)
    592 if tokens.next() != EOS:

File /usr/local/sage-9/src/sage/misc/parser.pyx:664, in sage.misc.parser.Parser.p_sequence()
    663 else:
--> 664     obj = self.p_eqn(tokens)
    665 PyList_Append(all, obj)

File /usr/local/sage-9/src/sage/misc/parser.pyx:754, in sage.misc.parser.Parser.p_eqn()
    753 """
--> 754 lhs = self.p_expr(tokens)
    755 cdef int op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:794, in sage.misc.parser.Parser.p_expr()
    793 cdef int op
--> 794 operand1 = self.p_term(tokens)
    795 op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:828, in sage.misc.parser.Parser.p_term()
    827 cdef int op
--> 828 operand1 = self.p_factor(tokens)
    829 op = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:871, in sage.misc.parser.Parser.p_factor()
    870 tokens.backtrack()
--> 871 return self.p_power(tokens)
    872 

File /usr/local/sage-9/src/sage/misc/parser.pyx:899, in sage.misc.parser.Parser.p_power()
    898 """
--> 899 operand1 = self.p_atom(tokens)
    900 cdef int token = tokens.next()

File /usr/local/sage-9/src/sage/misc/parser.pyx:958, in sage.misc.parser.Parser.p_atom()
    957         self.parse_error(tokens, "Bad function call")
--> 958     return func(*args, **kwds)
    959 else:

File /usr/local/sage-9/src/sage/functions/gamma.py:726, in _mathematica_gamma3(*args)
    716 r"""
    717 EXAMPLES::
    718 
   (...)
    724     gamma(4/3) - gamma(4/3, 1)
    725 """
--> 726 assert len(args) == 3
    727 return gamma_inc(args[0], args[1]) - gamma_inc(args[0], args[2])

AssertionError: 

During handling of the above exception, another exception occurred:

NotImplementedError                       Traceback (most recent call last)
Input In [5], in <cell line: 1>()
----> 1 mathematica.Gamma(x).sage()

File /usr/local/sage-9/src/sage/interfaces/interface.py:1107, in InterfaceElement.sage(self, *args, **kwds)
   1088 def sage(self, *args, **kwds):
   1089     """
   1090     Attempt to return a Sage version of this object.
   1091 
   (...)
   1105         [0 0]
   1106     """
-> 1107     return self._sage_(*args, **kwds)

File /usr/local/sage-9/src/sage/interfaces/mathematica.py:916, in MathematicaElement._sage_(self, locals)
    913     return symbolic_expression_from_string(res, lsymbols,
    914         accept_sequence=True)
    915 except Exception:
--> 916     raise NotImplementedError("Unable to parse Mathematica \
    917         output: %s" % res)

NotImplementedError: Unable to parse Mathematica                 output: Gamma(x)

Again, the initial stumble is in _mathematica_gamma3...

Same results (not shown) with :

On the other hand :

sage: mathematica.Sqrt(x).sage()
sqrt(x)
sage: type(mathematica.Sqrt(x).sage().operator())
<class 'builtin_function_or_method'>
sage: mathematica.Sin(x).sage()
sin(x)
sage: type(mathematica.Sin(x).sage().operator())
<class 'sage.functions.trig.Function_sin'>

This looks more and more as a gamma-specific problem. Any ideas for a systematic, exhaustive test set ?