Symbolic variables - Symbolic Calculus

Skip to content
Back to top
View this page
Edit this page

# Symbolic variables

sage.calculus.var.clear_vars()

  Delete all 1-letter symbolic variables that are predefined at startup of Sage.

  Any one-letter global variables that are not symbolic variables are not cleared.

  EXAMPLES:

  Sage

      sage: var('x y z')
      (x, y, z)
      sage: (x+y)^z
      (x + y)^z
      sage: k = 15
      sage: clear_vars()
      sage: (x+y)^z
      Traceback (most recent call last):
      ...
      NameError: name 'x' is not defined
      sage: expand((e + i)^2)
      e^2 + 2*I*e - 1
      sage: k
      15

  Python

      >>> from sage.all import *
      >>> var('x y z')
      (x, y, z)
      >>> (x+y)**z
      (x + y)^z
      >>> k = Integer(15)
      >>> clear_vars()
      >>> (x+y)**z
      Traceback (most recent call last):
      ...
      NameError: name 'x' is not defined
      >>> expand((e + i)**Integer(2))
      e^2 + 2*I*e - 1
      >>> k
      15

sage.calculus.var.function(s, **kwds)

  Create a formal symbolic function with the name s.

  INPUT:

  - `nargs=0` – number of arguments the function accepts, defaults to variable number of arguments, or 0

  - `latex_name` – name used when printing in latex mode

  - `conversions` – dictionary specifying names of this function in other systems, this is used by the interfaces internally during conversion

  - `eval_func` – method used for automatic evaluation

  - `evalf_func` – method used for numeric evaluation

  - `evalf_params_first` – boolean to indicate if parameters should be evaluated numerically before calling the custom evalf function

  - `conjugate_func` – method used for complex conjugation

  - `real_part_func` – method used when taking real parts

  - `imag_part_func` – method used when taking imaginary parts

  - `derivative_func` – method to be used for (partial) derivation This method should take a keyword argument deriv_param specifying the index of the argument to differentiate w.r.t

  - `tderivative_func` – method to be used for derivatives

  - `power_func` – method used when taking powers This method should take a keyword argument power_param specifying the exponent

  - `series_func` – method used for series expansion This method should expect keyword arguments - `order` – order for the expansion to be computed - `var` – variable to expand w.r.t. - `at` – expand at this value

  - `print_func` – method for custom printing

  - `print_latex_func` – method for custom printing in latex mode

  Note that custom methods must be instance methods, i.e., expect the instance of the symbolic function as the first argument.

  Note

  The new function is both returned and automatically injected into the global namespace. If you use this function in library code, it is better to use sage.symbolic.function_factory.function, since it will not touch the global namespace.

  EXAMPLES:

  We create a formal function called supersin

  Sage

      sage: function('supersin')
      supersin

  Python

      >>> from sage.all import *
      >>> function('supersin')
      supersin

  We can immediately use supersin in symbolic expressions:

  Sage

      sage: y, z, A = var('y z A')
      sage: supersin(y+z) + A^3
      A^3 + supersin(y + z)

  [Python]

      >>> from sage.all import *
      >>> y, z, A = var('y z A')
      >>> supersin(y+z) + A**Integer(3)
      A^3 + supersin(y + z)

  We can define other functions in terms of supersin:

  Sage

      sage: g(x,y) = supersin(x)^2 + sin(y/2)
      sage: g
      (x, y) |--> supersin(x)^2 + sin(1/2*y)
      sage: g.diff(y)
      (x, y) |--> 1/2*cos(1/2*y)
      sage: k = g.diff(x); k
      (x, y) |--> 2*supersin(x)*diff(supersin(x), x)

  Python

      >>> from sage.all import *
      >>> __tmp__=var("x,y"); g = symbolic_expression(supersin(x)**Integer(2) + sin(y/Integer(2))).function(x,y)
      >>> g
      (x, y) |--> supersin(x)^2 + sin(1/2*y)
      >>> g.diff(y)
      (x, y) |--> 1/2*cos(1/2*y)
      >>> k = g.diff(x); k
      (x, y) |--> 2*supersin(x)*diff(supersin(x), x)

  We create a formal function of one variable, write down an expression that involves first and second derivatives, and extract off coefficients:

  Sage

      sage: r, kappa = var('r,kappa')
      sage: psi = function('psi', nargs=1)(r); psi
      psi(r)
      sage: g = 1/r^2*(2*r*psi.derivative(r,1) + r^2*psi.derivative(r,2)); g
      (r^2*diff(psi(r), r, r) + 2*r*diff(psi(r), r))/r^2
      sage: g.expand()
      2*diff(psi(r), r)/r + diff(psi(r), r, r)
      sage: g.coefficient(psi.derivative(r,2))
      1
      sage: g.coefficient(psi.derivative(r,1))
      2/r

  [Python]

      >>> from sage.all import *
      >>> r, kappa = var('r,kappa')
      >>> psi = function('psi', nargs=Integer(1))(r); psi
      psi(r)
      >>> g = Integer(1)/r**Integer(2)*(Integer(2)*r*psi.derivative(r,Integer(1)) + r**Integer(2)*psi.derivative(r,Integer(2))); g
      (r^2*diff(psi(r), r, r) + 2*r*diff(psi(r), r))/r^2
      >>> g.expand()
      2*diff(psi(r), r)/r + diff(psi(r), r, r)
      >>> g.coefficient(psi.derivative(r,Integer(2)))
      1
      >>> g.coefficient(psi.derivative(r,Integer(1)))
      2/r

  Custom typesetting of symbolic functions in LaTeX, either using latex_name keyword:

  Sage

      sage: function('riemann', latex_name='\\mathcal{R}')
      riemann
      sage: latex(riemann(x))
      \mathcal{R}\left(x\right)

  Python

      >>> from sage.all import *
      >>> function('riemann', latex_name='\\mathcal{R}')
      riemann
      >>> latex(riemann(x))
      \mathcal{R}\left(x\right)

  or passing a custom callable function that returns a latex expression:

  Sage

      sage: mu,nu = var('mu,nu')
      sage: def my_latex_print(self, *args): return "\\psi_{%s}"%(', '.join(map(latex, args)))
      sage: function('psi', print_latex_func=my_latex_print)
      psi
      sage: latex(psi(mu,nu))
      \psi_{\mu, \nu}

  [Python]

      >>> from sage.all import *
      >>> mu,nu = var('mu,nu')
      >>> def my_latex_print(self, *args): return "\\psi_{%s}"%(', '.join(map(latex, args)))
      >>> function('psi', print_latex_func=my_latex_print)
      psi
      >>> latex(psi(mu,nu))
      \psi_{\mu, \nu}

  Defining custom methods for automatic or numeric evaluation, derivation, conjugation, etc. is supported:

  Sage

      sage: def ev(self, x): return 2*x
      sage: foo = function("foo", nargs=1, eval_func=ev)
      sage: foo(x)
      2*x
      sage: foo = function("foo", nargs=1, eval_func=lambda self, x: 5)
      sage: foo(x)
      5
      sage: def ef(self, x): pass
      sage: bar = function("bar", nargs=1, eval_func=ef)
      sage: bar(x)
      bar(x)

      sage: def evalf_f(self, x, parent=None, algorithm=None): return 6
      sage: foo = function("foo", nargs=1, evalf_func=evalf_f)
      sage: foo(x)
      foo(x)
      sage: foo(x).n()
      6

      sage: foo = function("foo", nargs=1, conjugate_func=ev)
      sage: foo(x).conjugate()
      2*x

      sage: def deriv(self, *args, **kwds): print("{} {}".format(args, kwds)); return args[kwds['diff_param']]^2
      sage: foo = function("foo", nargs=2, derivative_func=deriv)
      sage: foo(x,y).derivative(y)
      (x, y) {'diff_param': 1}
      y^2

      sage: def pow(self, x, power_param=None): print("{} {}".format(x, power_param)); return x*power_param
      sage: foo = function("foo", nargs=1, power_func=pow)
      sage: foo(y)^(x+y)
      y x + y
      (x + y)*y

      sage: from pprint import pformat
      sage: def expand(self, *args, **kwds):
      ....:     print("{} {}".format(args, pformat(kwds)))
      ....:     return sum(args[0]^i for i in range(kwds['order']))
      sage: foo = function("foo", nargs=1, series_func=expand)
      sage: foo(y).series(y, 5)
      (y,) {'at': 0, 'options': 0, 'order': 5, 'var': y}
      y^4 + y^3 + y^2 + y + 1

      sage: def my_print(self, *args):
      ....:     return "my args are: " + ', '.join(map(repr, args))
      sage: foo = function('t', nargs=2, print_func=my_print)
      sage: foo(x,y^z)
      my args are: x, y^z

      sage: latex(foo(x,y^z))
      t\left(x, y^{z}\right)
      sage: foo = function('t', nargs=2, print_latex_func=my_print)
      sage: foo(x,y^z)
      t(x, y^z)
      sage: latex(foo(x,y^z))
      my args are: x, y^z
      sage: foo = function('t', nargs=2, latex_name='foo')
      sage: latex(foo(x,y^z))
      foo\left(x, y^{z}\right)

  Python

      >>> from sage.all import *
      >>> def ev(self, x): return Integer(2)*x
      >>> foo = function("foo", nargs=Integer(1), eval_func=ev)
      >>> foo(x)
      2*x
      >>> foo = function("foo", nargs=Integer(1), eval_func=lambda self, x: Integer(5))
      >>> foo(x)
      5
      >>> def ef(self, x): pass
      >>> bar = function("bar", nargs=Integer(1), eval_func=ef)
      >>> bar(x)
      bar(x)

      >>> def evalf_f(self, x, parent=None, algorithm=None): return Integer(6)
      >>> foo = function("foo", nargs=Integer(1), evalf_func=evalf_f)
      >>> foo(x)
      foo(x)
      >>> foo(x).n()
      6

      >>> foo = function("foo", nargs=Integer(1), conjugate_func=ev)
      >>> foo(x).conjugate()
      2*x

      >>> def deriv(self, *args, **kwds): print("{} {}".format(args, kwds)); return args[kwds['diff_param']]**Integer(2)
      >>> foo = function("foo", nargs=Integer(2), derivative_func=deriv)
      >>> foo(x,y).derivative(y)
      (x, y) {'diff_param': 1}
      y^2

      >>> def pow(self, x, power_param=None): print("{} {}".format(x, power_param)); return x*power_param
      >>> foo = function("foo", nargs=Integer(1), power_func=pow)
      >>> foo(y)**(x+y)
      y x + y
      (x + y)*y

      >>> from pprint import pformat
      >>> def expand(self, *args, **kwds):
      ...     print("{} {}".format(args, pformat(kwds)))
      ...     return sum(args[Integer(0)]**i for i in range(kwds['order']))
      >>> foo = function("foo", nargs=Integer(1), series_func=expand)
      >>> foo(y).series(y, Integer(5))
      (y,) {'at': 0, 'options': 0, 'order': 5, 'var': y}
      y^4 + y^3 + y^2 + y + 1

      >>> def my_print(self, *args):
      ...     return "my args are: " + ', '.join(map(repr, args))
      >>> foo = function('t', nargs=Integer(2), print_func=my_print)
      >>> foo(x,y**z)
      my args are: x, y^z

      >>> latex(foo(x,y**z))
      t\left(x, y^{z}\right)
      >>> foo = function('t', nargs=Integer(2), print_latex_func=my_print)
      >>> foo(x,y**z)
      t(x, y^z)
      >>> latex(foo(x,y**z))
      my args are: x, y^z
      >>> foo = function('t', nargs=Integer(2), latex_name='foo')
      >>> latex(foo(x,y**z))
      foo\left(x, y^{z}\right)

  Chain rule:

  Sage

      sage: def print_args(self, *args, **kwds): print("args: {}".format(args)); print("kwds: {}".format(kwds)); return args[0]
      sage: foo = function('t', nargs=2, tderivative_func=print_args)
      sage: foo(x,x).derivative(x)
      args: (x, x)
      kwds: {'diff_param': x}
      x
      sage: foo = function('t', nargs=2, derivative_func=print_args)
      sage: foo(x,x).derivative(x)
      args: (x, x)
      kwds: {'diff_param': 0}
      args: (x, x)
      kwds: {'diff_param': 1}
      2*x

  [Python]

      >>> from sage.all import *
      >>> def print_args(self, *args, **kwds): print("args: {}".format(args)); print("kwds: {}".format(kwds)); return args[Integer(0)]
      >>> foo = function('t', nargs=Integer(2), tderivative_func=print_args)
      >>> foo(x,x).derivative(x)
      args: (x, x)
      kwds: {'diff_param': x}
      x
      >>> foo = function('t', nargs=Integer(2), derivative_func=print_args)
      >>> foo(x,x).derivative(x)
      args: (x, x)
      kwds: {'diff_param': 0}
      args: (x, x)
      kwds: {'diff_param': 1}
      2*x

  Since Sage 4.0, basic arithmetic with unevaluated functions is no longer supported:

  Sage

      sage: x = var('x')
      sage: f = function('f')
      sage: 2*f
      Traceback (most recent call last):
      ...
      TypeError: unsupported operand parent(s) for *: 'Integer Ring' and '<class 'sage.symbolic.function_factory...NewSymbolicFunction'>'

  Python

      >>> from sage.all import *
      >>> x = var('x')
      >>> f = function('f')
      >>> Integer(2)*f
      Traceback (most recent call last):
      ...
      TypeError: unsupported operand parent(s) for *: 'Integer Ring' and '<class 'sage.symbolic.function_factory...NewSymbolicFunction'>'

  You now need to evaluate the function in order to do the arithmetic:

  Sage

      sage: 2*f(x)
      2*f(x)

  [Python]

      >>> from sage.all import *
      >>> Integer(2)*f(x)
      2*f(x)

  Since Sage 4.0, you need to use `substitute_function()` to replace all occurrences of a function with another:

  Sage

      sage: var('a, b')
      (a, b)
      sage: cr = function('cr')
      sage: f = cr(a)
      sage: g = f.diff(a).integral(b)
      sage: g
      b*diff(cr(a), a)
      sage: g.substitute_function(cr, cos)
      -b*sin(a)

      sage: g.substitute_function(cr, (sin(x) + cos(x)).function(x))
      b*(cos(a) - sin(a))

  Python

      >>> from sage.all import *
      >>> var('a, b')
      (a, b)
      >>> cr = function('cr')
      >>> f = cr(a)
      >>> g = f.diff(a).integral(b)
      >>> g
      b*diff(cr(a), a)
      >>> g.substitute_function(cr, cos)
      -b*sin(a)

      >>> g.substitute_function(cr, (sin(x) + cos(x)).function(x))
      b*(cos(a) - sin(a))

sage.calculus.var.var(*args, **kwds)

  Create a symbolic variable with the name s.

  INPUT:

  - `args` – a single string `var('x y')`, a list of strings `var(['x','y'])`, or multiple strings `var('x', 'y')`. A single string can be either a single variable name, or a space or comma separated list of variable names. In a list or tuple of strings, each entry is one variable. If multiple arguments are specified, each argument is taken to be one variable. Spaces before or after variable names are ignored.

  - `kwds` – keyword arguments can be given to specify domain and custom latex_name for variables; see EXAMPLES for usage

  Note

  The new variable is both returned and automatically injected into the global namespace. If you need a symbolic variable in library code, you must use either `SR.var()` or `SR.symbol()`.

  OUTPUT:

  If a single symbolic variable was created, the variable itself. Otherwise, a tuple of symbolic variables. The variable names are checked to be valid Python identifiers and a `ValueError` is raised otherwise.

  EXAMPLES:

  Here are the different ways to define three variables `x`, `y`, and `z` in a single line:

  Sage

      sage: var('x y z')
      (x, y, z)
      sage: var('x, y, z')
      (x, y, z)
      sage: var(['x', 'y', 'z'])
      (x, y, z)
      sage: var('x', 'y', 'z')
      (x, y, z)
      sage: var('x'), var('y'), var(z)
      (x, y, z)

  Python

      >>> from sage.all import *
      >>> var('x y z')
      (x, y, z)
      >>> var('x, y, z')
      (x, y, z)
      >>> var(['x', 'y', 'z'])
      (x, y, z)
      >>> var('x', 'y', 'z')
      (x, y, z)
      >>> var('x'), var('y'), var(z)
      (x, y, z)

  We define some symbolic variables:

  Sage

      sage: var('n xx yy zz')
      (n, xx, yy, zz)

  [Python]

      >>> from sage.all import *
      >>> var('n xx yy zz')
      (n, xx, yy, zz)

  Then we make an algebraic expression out of them:

  Sage

      sage: f = xx^n + yy^n + zz^n; f
      xx^n + yy^n + zz^n

  Python

      >>> from sage.all import *
      >>> f = xx**n + yy**n + zz**n; f
      xx^n + yy^n + zz^n

  By default, var returns a complex variable. To define real or positive variables we can specify the domain as:

  Sage

      sage: x = var('x', domain=RR); x; x.conjugate()
      x
      x
      sage: y = var('y', domain='real'); y.conjugate()
      y
      sage: y = var('y', domain='positive'); y.abs()
      y

  [Python]

      >>> from sage.all import *
      >>> x = var('x', domain=RR); x; x.conjugate()
      x
      x
      >>> y = var('y', domain='real'); y.conjugate()
      y
      >>> y = var('y', domain='positive'); y.abs()
      y

  Custom latex expression can be assigned to variable:

  Sage

      sage: x = var('sui', latex_name='s_{u,i}'); x._latex_()
      '{s_{u,i}}'

  Python

      >>> from sage.all import *
      >>> x = var('sui', latex_name='s_{u,i}'); x._latex_()
      '{s_{u,i}}'

  In notebook, we can also colorize latex expression:

  Sage

      sage: x = var('sui', latex_name='\\color{red}{s_{u,i}}'); x._latex_()
      '{\\color{red}{s_{u,i}}}'

  [Python]

      >>> from sage.all import *
      >>> x = var('sui', latex_name='\\color{red}{s_{u,i}}'); x._latex_()
      '{\\color{red}{s_{u,i}}}'

  We can substitute a new variable name for n:

  Sage

      sage: f(n = var('sigma'))
      xx^sigma + yy^sigma + zz^sigma

  Python

      >>> from sage.all import *
      >>> f(n = var('sigma'))
      xx^sigma + yy^sigma + zz^sigma

  If you make an important built-in variable into a symbolic variable, you can get back the original value using restore:

  Sage

      sage: var('QQ RR')
      (QQ, RR)
      sage: QQ
      QQ
      sage: restore('QQ')
      sage: QQ
      Rational Field

  [Python]

      >>> from sage.all import *
      >>> var('QQ RR')
      (QQ, RR)
      >>> QQ
      QQ
      >>> restore('QQ')
      >>> QQ
      Rational Field

  We make two new variables separated by commas:

  Sage

      sage: var('theta, gamma')
      (theta, gamma)
      sage: theta^2 + gamma^3
      gamma^3 + theta^2

  Python

      >>> from sage.all import *
      >>> var('theta, gamma')
      (theta, gamma)
      >>> theta**Integer(2) + gamma**Integer(3)
      gamma^3 + theta^2

  The new variables are of type Expression, and belong to the symbolic expression ring:

  Sage

      sage: type(theta)
      <class 'sage.symbolic.expression.Expression'>
      sage: parent(theta)
      Symbolic Ring

  [Python]

      >>> from sage.all import *
      >>> type(theta)
      <class 'sage.symbolic.expression.Expression'>
      >>> parent(theta)
      Symbolic Ring