Classes for symbolic functions¶
To enable their usage as part of symbolic expressions, symbolic function
classes are derived from one of the subclasses of Function
:
BuiltinFunction
: the code of these functions is written in Python; many special functions are of this type
GinacFunction
: the code of these functions is written in C++ and part of the Pynac support library; most elementary functions are of this type
SymbolicFunction
: symbolic functions defined on the Sage command line are of this type
Sage uses BuiltinFunction
and GinacFunction
for its symbolic builtin
functions. Users can define any other additional SymbolicFunction
through
the function()
factory, see Factory for symbolic functions
Several parameters are supported by the superclass’ __init__()
method.
Examples follow below.
nargs
: the number of arguments
name
: the string that is printed on the CLI; the name of the member functions that are attempted for evaluation of Sage element arguments; also the name of the Pynac function that is associated with aGinacFunction
alt_name
: the second name of the member functions that are attempted for evaluation of Sage element arguments
latex_name
: what is printed whenlatex(f(...))
is called
conversions
: a dict containing the function’s name in other CAS
evalf_params_first
: ifFalse
, when floating-point evaluating the expression do not evaluate function arguments before calling the_evalf_()
member of the function
preserved_arg
: if nonzero, the index (starting with1
) of the function argument that determines the return type. Note that, e.g,atan2()
uses both arguments to determine return type, through a different mechanism
Function classes can define the following Python member functions:
_eval_(*args)
: the only mandatory member function, evaluating the argument and returning the result; ifNone
is returned the expression stays unevaluated
_eval_numpy_(*args)
: evaluation off(args)
with arguments of numpy type
_evalf_(*args, **kwds)
: called when the expression is floating-point evaluated; may receive aparent
keyword specifying the expected parent of the result. If not defined an attempt is made to convert the result of_eval_()
.
_conjugate_(*args)
,_real_part_(*args)
,_imag_part_(*args)
: return conjugate, real part, imaginary part of the expressionf(args)
_derivative_(*args, index)
: return derivative with respect to the parameter indexed byindex
(starting with 0) off(args)
_tderivative_()
: same as_derivative_()
but don’t apply chain rule; only one of the two functions may be defined
_power_(*args, expo)
: returnf(args)^expo
_series_(*args, **kwds)
: return the power series atat
up toorder
with respect tovar
off(args)
; these three values are received inkwds
. If not defined the series is attempted to be computed by differentiation.
print(*args)
: return what should be printed on the CLI withf(args)
print_latex(*args)
: return what should be output withlatex(f(args))
The following examples are intended for Sage developers. Users can define
functions interactively through the function()
factory, see
Factory for symbolic functions.
EXAMPLES:
The simplest example is a function returning nothing, it practically behaves
like a symbol. Setting nargs=0
allows any number of arguments:
sage: from sage.symbolic.function import BuiltinFunction
sage: class Test1(BuiltinFunction):
....: def __init__(self):
....: BuiltinFunction.__init__(self, 'test', nargs=0)
....: def _eval_(self, *args):
....: pass
sage: f = Test1()
sage: f() # needs sage.symbolic
test()
sage: f(1,2,3)*f(1,2,3) # needs sage.symbolic
test(1, 2, 3)^2
>>> from sage.all import *
>>> from sage.symbolic.function import BuiltinFunction
>>> class Test1(BuiltinFunction):
... def __init__(self):
... BuiltinFunction.__init__(self, 'test', nargs=Integer(0))
... def _eval_(self, *args):
... pass
>>> f = Test1()
>>> f() # needs sage.symbolic
test()
>>> f(Integer(1),Integer(2),Integer(3))*f(Integer(1),Integer(2),Integer(3)) # needs sage.symbolic
test(1, 2, 3)^2
from sage.symbolic.function import BuiltinFunction class Test1(BuiltinFunction): def __init__(self): BuiltinFunction.__init__(self, 'test', nargs=0) def _eval_(self, *args): pass f = Test1() f() # needs sage.symbolic f(1,2,3)*f(1,2,3) # needs sage.symbolic
In the following the sin
function of CBF(0)
is called because with
floating point arguments the CBF
element’s my_sin()
member function
is attempted, and after that sin()
which succeeds:
sage: class Test2(BuiltinFunction):
....: def __init__(self):
....: BuiltinFunction.__init__(self, 'my_sin', alt_name='sin',
....: latex_name=r'\SIN', nargs=1)
....: def _eval_(self, x):
....: return 5
....: def _evalf_(self, x, **kwds):
....: return 3.5
sage: f = Test2()
sage: f(0)
5
sage: f(0, hold=True) # needs sage.symbolic
my_sin(0)
sage: f(0, hold=True).n() # needs sage.rings.real_mpfr
3.50000000000000
sage: f(CBF(0)) # needs sage.libs.flint
0
sage: latex(f(0, hold=True)) # needs sage.symbolic
\SIN\left(0\right)
sage: f(1,2)
Traceback (most recent call last):
...
TypeError: Symbolic function my_sin takes exactly 1 arguments (2 given)
>>> from sage.all import *
>>> class Test2(BuiltinFunction):
... def __init__(self):
... BuiltinFunction.__init__(self, 'my_sin', alt_name='sin',
... latex_name=r'\SIN', nargs=Integer(1))
... def _eval_(self, x):
... return Integer(5)
... def _evalf_(self, x, **kwds):
... return RealNumber('3.5')
>>> f = Test2()
>>> f(Integer(0))
5
>>> f(Integer(0), hold=True) # needs sage.symbolic
my_sin(0)
>>> f(Integer(0), hold=True).n() # needs sage.rings.real_mpfr
3.50000000000000
>>> f(CBF(Integer(0))) # needs sage.libs.flint
0
>>> latex(f(Integer(0), hold=True)) # needs sage.symbolic
\SIN\left(0\right)
>>> f(Integer(1),Integer(2))
Traceback (most recent call last):
...
TypeError: Symbolic function my_sin takes exactly 1 arguments (2 given)
class Test2(BuiltinFunction): def __init__(self): BuiltinFunction.__init__(self, 'my_sin', alt_name='sin', latex_name=r'\SIN', nargs=1) def _eval_(self, x): return 5 def _evalf_(self, x, **kwds): return 3.5 f = Test2() f(0) f(0, hold=True) # needs sage.symbolic f(0, hold=True).n() # needs sage.rings.real_mpfr f(CBF(0)) # needs sage.libs.flint latex(f(0, hold=True)) # needs sage.symbolic f(1,2)
- class sage.symbolic.function.BuiltinFunction[source]¶
Bases:
Function
This is the base class for symbolic functions defined in Sage.
If a function is provided by the Sage library, we don’t need to pickle the custom methods, since we can just initialize the same library function again. This allows us to use Cython for custom methods.
We assume that each subclass of this class will define one symbolic function. Make sure you use subclasses and not just call the initializer of this class.
- class sage.symbolic.function.Function[source]¶
Bases:
SageObject
Base class for symbolic functions defined through Pynac in Sage.
This is an abstract base class, with generic code for the interfaces and a
__call__()
method. Subclasses should implement the_is_registered()
and_register_function()
methods.This class is not intended for direct use, instead use one of the subclasses
BuiltinFunction
orSymbolicFunction
.- default_variable()[source]¶
Return a default variable.
EXAMPLES:
sage: sin.default_variable() # needs sage.symbolic x
>>> from sage.all import * >>> sin.default_variable() # needs sage.symbolic x
sin.default_variable() # needs sage.symbolic
- name()[source]¶
Return the name of this function.
EXAMPLES:
sage: foo = function("foo", nargs=2) # needs sage.symbolic sage: foo.name() # needs sage.symbolic 'foo'
>>> from sage.all import * >>> foo = function("foo", nargs=Integer(2)) # needs sage.symbolic >>> foo.name() # needs sage.symbolic 'foo'
foo = function("foo", nargs=2) # needs sage.symbolic foo.name() # needs sage.symbolic
- number_of_arguments()[source]¶
Return the number of arguments that this function takes.
EXAMPLES:
sage: # needs sage.symbolic sage: foo = function("foo", nargs=2) sage: foo.number_of_arguments() 2 sage: foo(x, x) foo(x, x) sage: foo(x) Traceback (most recent call last): ... TypeError: Symbolic function foo takes exactly 2 arguments (1 given)
>>> from sage.all import * >>> # needs sage.symbolic >>> foo = function("foo", nargs=Integer(2)) >>> foo.number_of_arguments() 2 >>> foo(x, x) foo(x, x) >>> foo(x) Traceback (most recent call last): ... TypeError: Symbolic function foo takes exactly 2 arguments (1 given)
# needs sage.symbolic foo = function("foo", nargs=2) foo.number_of_arguments() foo(x, x) foo(x)
- class sage.symbolic.function.GinacFunction[source]¶
Bases:
BuiltinFunction
This class provides a wrapper around symbolic functions already defined in Pynac/GiNaC.
GiNaC provides custom methods for these functions defined at the C++ level. It is still possible to define new custom functionality or override those already defined.
There is also no need to register these functions.
- class sage.symbolic.function.SymbolicFunction[source]¶
Bases:
Function
This is the basis for user defined symbolic functions. We try to pickle or hash the custom methods, so subclasses must be defined in Python not Cython.
- sage.symbolic.function.pickle_wrapper(f)[source]¶
Return a pickled version of the function
f
.If
f
isNone
, just returnNone
.This is a wrapper around
pickle_function()
.EXAMPLES:
sage: from sage.symbolic.function import pickle_wrapper sage: def f(x): return x*x sage: isinstance(pickle_wrapper(f), bytes) True sage: pickle_wrapper(None) is None True
>>> from sage.all import * >>> from sage.symbolic.function import pickle_wrapper >>> def f(x): return x*x >>> isinstance(pickle_wrapper(f), bytes) True >>> pickle_wrapper(None) is None True
from sage.symbolic.function import pickle_wrapper def f(x): return x*x isinstance(pickle_wrapper(f), bytes) pickle_wrapper(None) is None
- sage.symbolic.function.unpickle_wrapper(p)[source]¶
Return a unpickled version of the function defined by
p
.If
p
isNone
, just returnNone
.This is a wrapper around
unpickle_function()
.EXAMPLES:
sage: from sage.symbolic.function import pickle_wrapper, unpickle_wrapper sage: def f(x): return x*x sage: s = pickle_wrapper(f) sage: g = unpickle_wrapper(s) sage: g(2) 4 sage: unpickle_wrapper(None) is None True
>>> from sage.all import * >>> from sage.symbolic.function import pickle_wrapper, unpickle_wrapper >>> def f(x): return x*x >>> s = pickle_wrapper(f) >>> g = unpickle_wrapper(s) >>> g(Integer(2)) 4 >>> unpickle_wrapper(None) is None True
from sage.symbolic.function import pickle_wrapper, unpickle_wrapper def f(x): return x*x s = pickle_wrapper(f) g = unpickle_wrapper(s) g(2) unpickle_wrapper(None) is None