Skip to main content

Symbolic framework

We can define scalar symbolic variables as follows

from gradgen import SX

x = SX.sym("x")

for vectors, use SXVector. For example, to create a vector of dimensions 2 do

from gradgen import SXVector

x = SXVector.sym("x", 2)

If you print x you will see

SXVector(elements=(SX.sym('x_0'), SX.sym('x_1')))
Details

Although SXVectors of length 1 behave like scalar, you can "cast" an SXVector of length 1 as an SX using

x = SXVector.sym("x", 2)
x = x[0]

Lastly, note that x[a:b] returns an SXVector view.

n = 10
x = SXVector.sym("x", n)
x_slice = x[1:4] # <-- this is (x[1], x[2], x[3])

Symbolic expressions

Using scalar and vector symbols we can construct symbolic expressions. For example, to define the function $f(x) = ux/\Vert x \Vert_1$ we can do

f = u * x / x.norm1()

Several operations are supported. Indicatively, we support the operators **; to define the expression $f = 1 + 0.1 z - 4 z^3$ we can write

z = SX.sym("u")

f = 1 + 0.1 * z - 4 * z**3

The operator **, when applied to vectors (SXVector), operates element-wise.

All trigonometric (cos, sin, tan), inverse trigonometric (acos, asin, atan) and hyperbolic operations (cosh, sinh, tanh) and their inverses (acosh, asinh, atanh) are supported.

For vectors, the following scalar-valued operations are available:

  • norm2(): Euclidean norm
  • norm2sq(): squared Euclidean norm
  • norm1(): norm-1
  • norm_inf(): Infinity norm
  • norm_p(p): $p$-norm
  • norm_p_to_p(p): $p$-norm to the power $p$

In optimal control applications we frequently encounter terms of the form $x^\intercal P x$, where $P$ is a symmetric matrix. Such expressions can be constructed with quadform as follows

import gradgen as gg

x = SXVector.sym("x", 2)
P = [[1, 4],
[4, 5]]
f = gg.quadform(P, x, is_symmetric=True)

If is_symmetric=True is used, then a simpler expression is generated, however, an exception is raised if the provided matrix P is not truly symmetric.

One limitation of the current framework is that $P$ needs to be a constant matrix. Quadratic forms with a symbolic matrix will be supported in a future version.

Likewise, we often need to compute dot products. This can be done with dot:

n = 3
x = SXVector.sym("x", n)
q = SXVector.sym("x", n)
f = x.dot(q)