Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

The problem is reproducible in Sympy :

>>> from sympy import *
>>> x=symbols("x")
>>> Ex=Piecewise((3*x+1, (x > -2) | (x < -2)), (2, Eq(x, -2)))
>>> Ex.subs({x:-2})
2
>>> limit(Ex, x, -2)
2
>>> f=Lambda((x), Ex)
>>> limit(f(x), x, -2)
2

You may yelp on the Sympy Google group...

BTW,

  • Giac gets it right :

    sage: f(x).limit(x=-2, algorithm="giac") -5

So does the Wolfram engine :

sage: %%mathematica
....: f[x_]:=Piecewise[{{3*x+1, x<-2}, {3*x+1, x>-2}, {2,x==-2}}]
....: f[-2]
....: Limit[f[x], x->-2]
....: 
....: 
        2
Out[7]= -5

Sage is worse :

sage: f(x).limit(x=-2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [200], line 1
----> 1 f(x).limit(x=-Integer(2))

File /usr/local/sage-10/src/sage/symbolic/expression.pyx:13332, in sage.symbolic.expression.Expression.limit()
  13330     """
  13331     from sage.calculus.calculus import limit
> 13332     return limit(self, *args, **kwds)
  13333 
  13334 def laplace(self, t, s):

File /usr/local/sage-10/src/sage/calculus/calculus.py:1429, in limit(ex, dir, taylor, algorithm, **argv)
   1427 if algorithm == 'maxima':
   1428     if dir is None:
-> 1429         l = maxima.sr_limit(ex, v, a)
   1430     elif dir in dir_plus:
   1431         l = maxima.sr_limit(ex, v, a, 'plus')

File /usr/local/sage-10/src/sage/interfaces/maxima_lib.py:1006, in MaximaLib.sr_limit(self, expr, v, a, dir)
   1004     elif dir == "minus":
   1005         L.append(max_minus)
-> 1006     return max_to_sr(maxima_eval(([max_limit], L)))
   1007 except RuntimeError as error:
   1008     s = str(error)

File /usr/local/sage-10/src/sage/interfaces/maxima_lib.py:1728, in max_to_sr(expr)
   1724     op = max_to_pynac_table[op_max_str]
   1725 else:
   1726     # This could be unsafe if the conversion to SR
   1727     # changes the structure of expr
-> 1728     sage_expr = SR(maxima(expr))
   1729     op = sage_expr.operator()
   1730 if op in sage_op_dict:

File /usr/local/sage-10/src/sage/structure/parent.pyx:901, in sage.structure.parent.Parent.__call__()
    899 if mor is not None:
    900     if no_extra_args:
--> 901         return mor._call_(x)
    902     else:
    903         return mor._call_with_args(x, args, kwds)

File /usr/local/sage-10/src/sage/structure/coerce_maps.pyx:163, in sage.structure.coerce_maps.DefaultConvertMap_unique._call_()
    161             print(type(C), C)
    162             print(type(C._element_constructor), C._element_constructor)
--> 163         raise
    164 
    165 cpdef Element _call_with_args(self, x, args=(), kwds={}):

File /usr/local/sage-10/src/sage/structure/coerce_maps.pyx:158, in sage.structure.coerce_maps.DefaultConvertMap_unique._call_()
    156 cdef Parent C = self._codomain
    157 try:
--> 158     return C._element_constructor(x)
    159 except Exception:
    160     if print_warnings:

File /usr/local/sage-10/src/sage/symbolic/ring.pyx:376, in sage.symbolic.ring.SymbolicRing._element_constructor_()
    374         TypeError: Malformed expression: λ + * !!!  1
    375     """
--> 376     return new_Expression(self, x)
    377 
    378 def _force_pyobject(self, x, bint force=False, bint recursive=True):

File /usr/local/sage-10/src/sage/symbolic/expression.pyx:13773, in sage.symbolic.expression.new_Expression()
  13771     return new_Expression_from_GEx(parent, (<Expression>x)._gobj)
  13772 if hasattr(x, '_symbolic_'):
> 13773     return x._symbolic_(parent)
  13774 elif isinstance(x, str):
  13775     try:

File /usr/local/sage-10/src/sage/interfaces/maxima_abstract.py:1280, in MaximaAbstractElement._symbolic_(self, R)
   1257 def _symbolic_(self, R):
   1258     """
   1259     Return a symbolic expression equivalent to this Maxima object.
   1260 
   (...)
   1278         sqrt(2)
   1279     """
-> 1280     return R(self._sage_())

File /usr/local/sage-10/src/sage/interfaces/maxima_abstract.py:1254, in MaximaAbstractElement._sage_(self)
   1199 """
   1200 Attempt to make a native Sage object out of this Maxima object.
   1201 This is useful for automatic coercions in addition to other
   (...)
   1251     (True, False)
   1252 """
   1253 import sage.calculus.calculus as calculus
-> 1254 return calculus.symbolic_expression_from_maxima_string(self.name(),
   1255         maxima=self.parent())

File /usr/local/sage-10/src/sage/calculus/calculus.py:2403, in symbolic_expression_from_maxima_string(x, equals_sub, maxima)
   2401     SRM_parser._variable_constructor().set_names(var_syms)
   2402     SRM_parser._callable_constructor().set_names(function_syms)
-> 2403     return SRM_parser.parse_sequence(s)
   2404 except SyntaxError:
   2405     raise TypeError("unable to make sense of Maxima expression '%s' in Sage" % s)

File /usr/local/sage-10/src/sage/misc/parser.pyx:571, in sage.misc.parser.Parser.parse_sequence()
    569     return expr
    570 
--> 571 cpdef parse_sequence(self, s):
    572     """
    573     Parse a (possibly nested) set of lists and tuples.

File /usr/local/sage-10/src/sage/misc/parser.pyx:587, in sage.misc.parser.Parser.parse_sequence()
    585 """
    586 cdef Tokenizer tokens = Tokenizer(s)
--> 587 all = self.p_sequence(tokens)
    588 if tokens.next() != EOS:
    589     self.parse_error(tokens)

File /usr/local/sage-10/src/sage/misc/parser.pyx:660, in sage.misc.parser.Parser.p_sequence()
    658     return all
    659 else:
--> 660     obj = self.p_eqn(tokens)
    661 PyList_Append(all, obj)
    662 token = tokens.next()

File /usr/local/sage-10/src/sage/misc/parser.pyx:750, in sage.misc.parser.Parser.p_eqn()
    748     a != b
    749 """
--> 750 lhs = self.p_expr(tokens)
    751 cdef int op = tokens.next()
    752 if op == c'=':

File /usr/local/sage-10/src/sage/misc/parser.pyx:790, in sage.misc.parser.Parser.p_expr()
    788 # Note: this is left-recursive, so we can't just recurse
    789 cdef int op
--> 790 operand1 = self.p_term(tokens)
    791 op = tokens.next()
    792 while op == c'+' or op == c'-':

File /usr/local/sage-10/src/sage/misc/parser.pyx:824, in sage.misc.parser.Parser.p_term()
    822 # Note: this is left-recursive, so we can't just recurse
    823 cdef int op
--> 824 operand1 = self.p_factor(tokens)
    825 op = tokens.next()
    826 if op == NAME and self.implicit_multiplication:

File /usr/local/sage-10/src/sage/misc/parser.pyx:867, in sage.misc.parser.Parser.p_factor()
    865         else:
    866             tokens.backtrack()
--> 867             return self.p_power(tokens)
    868 
    869 # power ::=  (atom | atom!) ^ factor | atom | atom!

File /usr/local/sage-10/src/sage/misc/parser.pyx:895, in sage.misc.parser.Parser.p_power()
    893 
    894         """
--> 895         operand1 = self.p_atom(tokens)
    896         cdef int token = tokens.next()
    897         if token == c'^':

File /usr/local/sage-10/src/sage/misc/parser.pyx:950, in sage.misc.parser.Parser.p_atom()
    948 if token == c'(':
    949     func = self.callable_constructor(name)
--> 950     args, kwds = self.p_args(tokens)
    951     token = tokens.next()
    952     if token != c')':

File /usr/local/sage-10/src/sage/misc/parser.pyx:987, in sage.misc.parser.Parser.p_args()
    985 cdef int token = c','
    986 while token == c',':
--> 987     arg = self.p_arg(tokens)
    988     if isinstance(arg, tuple):
    989         name, value = arg

File /usr/local/sage-10/src/sage/misc/parser.pyx:1037, in sage.misc.parser.Parser.p_arg()
   1035     else:
   1036         tokens.backtrack()
-> 1037         return self.p_expr(tokens)
   1038 
   1039 cdef parse_error(self, Tokenizer tokens, msg="Malformed expression"):

File /usr/local/sage-10/src/sage/misc/parser.pyx:790, in sage.misc.parser.Parser.p_expr()
    788 # Note: this is left-recursive, so we can't just recurse
    789 cdef int op
--> 790 operand1 = self.p_term(tokens)
    791 op = tokens.next()
    792 while op == c'+' or op == c'-':

File /usr/local/sage-10/src/sage/misc/parser.pyx:824, in sage.misc.parser.Parser.p_term()
    822 # Note: this is left-recursive, so we can't just recurse
    823 cdef int op
--> 824 operand1 = self.p_factor(tokens)
    825 op = tokens.next()
    826 if op == NAME and self.implicit_multiplication:

File /usr/local/sage-10/src/sage/misc/parser.pyx:867, in sage.misc.parser.Parser.p_factor()
    865         else:
    866             tokens.backtrack()
--> 867             return self.p_power(tokens)
    868 
    869 # power ::=  (atom | atom!) ^ factor | atom | atom!

File /usr/local/sage-10/src/sage/misc/parser.pyx:895, in sage.misc.parser.Parser.p_power()
    893 
    894         """
--> 895         operand1 = self.p_atom(tokens)
    896         cdef int token = tokens.next()
    897         if token == c'^':

File /usr/local/sage-10/src/sage/misc/parser.pyx:954, in sage.misc.parser.Parser.p_atom()
    952     if token != c')':
    953         self.parse_error(tokens, "Bad function call")
--> 954     return func(*args, **kwds)
    955 else:
    956     tokens.backtrack()

TypeError: PiecewiseFunction.__call__() takes 2 positional arguments but 3 were given

This is now #35883.

HTH,