Analytic operators
Main authors: Simon Rohou, Damien Massé
Codac provides a list of operators for calculating intervals, defining expressions and constructing contractors.
Operators currently available
- The following table lists the mathematical operators currently available. The availability is indicated for four operations:
Natural forward evaluation
Centered-form forward evaluation
Differentiation
Backward (reverse) evaluation
When operators are available for operations 2–3, then an AnalyticFunction can be built upon them and the .eval(EvalMode.CENTERED, ...) and .diff(...) methods can be successfully called. When operators are available for operation 4, then analytic contractors such as CtcInverse will work.
Only the ✓ operators are supported at the moment. If you notice any mathematical operators missing from the list below, feel free to contribute to the library. You can submit your suggestions or pull requests on the GitHub repository of Codac.
operators folder:Operator |
Syntax |
Struct |
Operands type |
Fwd eval. |
Bwd. eval. |
||
|---|---|---|---|---|---|---|---|
Natur. |
Centr. |
Diff. |
|||||
Unary operations |
|||||||
\(|x|\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\arccos(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\arcsin(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\arctan(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\lceil x \rceil\) |
|
|
✓ |
✗ |
✗ |
✓ |
|
\(\cos(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\cosh(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\det(\mathbf{A})\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\exp(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\lfloor x \rfloor\) |
|
|
✓ |
✗ |
✗ |
✓ |
|
\(\log(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathrm{sgn}(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\sin(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\sinh(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(x^2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\sqrt{x}\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\tan(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\tanh(x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathrm{flatten}(\mathbf{X})\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{X}^\intercal\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
Binary operations |
|||||||
\(x_1+x_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{x}_1+\mathbf{x}_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{X}_1+\mathbf{X}_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(x_1-x_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{x}_1-\mathbf{x}_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{X}_1-\mathbf{X}_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(x_1\cdot x_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(x_1\cdot\mathbf{x}_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{x}_1\cdot x_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(x_1\cdot\mathbf{X}_2\) |
|
|
✓ |
✓ |
✓ |
✗ |
|
\(\mathbf{x}_1\cdot\mathbf{x}_2\) |
|
|
✓ |
✗ |
✗ |
✓ |
|
\(\mathbf{X}_1\cdot\mathbf{x}_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{X}_1\cdot\mathbf{X}_2\) |
|
|
✓ |
✓ |
✓ |
✗ |
|
\(x_1/x_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{x}_1/x_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{X}_1/x_2\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{x}_1\times\mathbf{x}_2\) |
|
|
✓ |
✓ |
✓ |
✗ |
|
\(\max(x_1,x_2)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\min(x_1,x_2)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(x_1\mod p\) |
|
|
✓ |
✗ |
✗ |
✓ |
|
\((x_1)^{x_2}\) |
pow(x1,x2)x1**x2 (py) |
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathrm{arctan2}(y,x)\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\begin{split}f(x) \textrm{ if } x \in D_f,\\ g(x) \textrm{ otherwise}\end{split}\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
Ternary operations |
|||||||
\(\begin{split}\chi(x_1,x_2,x_3) =\\ \begin{cases}x_2 & \text{if } x_1 \leqslant 0, \\x_3 & \text{if } x_1>0.\end{cases}\end{split}\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
Vectorial / matricial operations |
|||||||
\(x_i\) (vector coeff) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(X_{ij}\) (mat. coeff) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\mathbf{x}_{i:j}\) (subvector) |
|
x: vector expressioni, j: scalar |
✓ |
✓ |
✓ |
✓ |
|
\([x_1,x_2,\dots]^\intercal\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
\(\left(\mathbf{x}_1,\mathbf{x}_2,\dots\right)\) |
|
|
✓ |
✓ |
✓ |
✗ |
|
\(\sigma(\mathbf{x})\) |
|
|
✓ |
✓ |
✓ |
✓ |
|
Temporal operations |
|||||||
\(\mathbf{x}(t)\) |
|
|
✓ |
✗ |
✗ |
✗ |
|
\([\mathbf{x}](t)\) |
|
|
✓ |
✗ |
✗ |
✗ |
|
Why ^ is disabled in Codac
The ^ syntax is intentionally disabled in Codac for powers. Although this operator can be overloaded, its precedence remains the one of the bitwise XOR operator, both in Python and in C++. Overloading an operator does not change the precedence rules of the host language.
As a consequence, an expression such as x^2 + sin(x) is parsed as x^(2 + sin(x)), not as (x^2) + sin(x). This kind of ambiguity is easy to overlook and may silently produce an expression different from the one intended by the user.
To avoid such error-prone expressions, Codac does not provide ^ as a power syntax. Use:
pow(x1,x2)for generic powers;x1**x2in Python when exponentiation syntax is preferred;sqr(x1)for squares when applicable (it is equivalent topow(x1,2)).
Examples:
x = ScalarVar()
f = AnalyticFunction([x], x**2 + sin(x))
g = AnalyticFunction([x], pow(x,2) + sin(x))
ScalarVar x;
AnalyticFunction f({x}, pow(x,2) + sin(x));
AnalyticFunction g({x}, sqr(x) + sin(x));
Expressions involving a non-supported centered-form operation
If an operator, for which the centered form is not defined, is involved in an expression, then this expression cannot be evaluated using the centered form (calculation is disabled for the entire operation). A simple natural evaluation will then be computed.
Expressions involving a temporal operator
Temporal operations for involving trajectories or tubes in analytic expressions require an intermediate operation:
x = # some sampled trajectory...
g = x.as_function() # intermediate operation
t = ScalarVar()
h = AnalyticFunction(
[t], g(t)
)
x = // some sampled trajectory...
g = x.as_function(); // intermediate operation
ScalarVar t;
AnalyticFunction h(
{t}, g(t)
);
Direct use of operators
Operators can be used directly without building an AnalyticFunction. They are organized in structures named <OperatorCode>Op and each structure provides .fwd() and .bwd() methods.
For example, the operator cos is proposed with:
class CosOp:
@staticmethod
def fwd(x1):
# Default natural forward evaluation
# ...
@staticmethod
def bwd(y, x1):
# Backward evaluation
# ...
struct CosOp
{
// Default natural forward evaluation
static Interval fwd(const Interval& x1);
// Backward evaluation
static void bwd(const Interval& y, Interval& x1);
};
CosOp is given below:# Forward evaluation
y = CosOp.fwd([0,PI/2]) # y = [0,1]
# Backward evaluation
x = Interval(0,PI) # prior value of [x]
CosOp.bwd([0,0.5], x) # [x] is contracted to [PI/3,PI/2]
// Forward evaluation
Interval y = CosOp::fwd({0,PI/2}); // y = [0,1]
// Backward evaluation
Interval x(0,PI); // prior value of [x]
CosOp::bwd({0,0.5}, x); // [x] is contracted to [PI/3,PI/2]
% Forward evaluation
y = CosOp().fwd(Interval(0,PI/2)); % y = [0,1]
% Backward evaluation
x = Interval(0,PI); % prior value of [x]
CosOp().bwd(Interval(0,0.5), x); % [x] is contracted to [PI/3,PI/2]