Build analytic functions
The AnalyticFunction
class allows to build analytic inclusion functions and evaluate them using interval analysis.
Considering a \(n\)-dimensional box \([\mathbf{x}]\) as input, a function \(\mathbf{f}:\mathbb{R}^n\to\mathbb{R}^m\) will output a set which is not necessarily a box. To obtain a reliable enclosure of the image set \(\mathbf{f}([\mathbf{x}])\), we use inclusion functions.
An inclusion function \([\mathbf{f}]:\mathbb{IR}^n\to\mathbb{IR}^m\) outputs an interval set containing all the feasible images \(\mathbf{f}(\mathbf{x})\) for any \(\mathbf{x}\in[\mathbf{x}]\). Hence it must satisfy: \(\forall [\mathbf{x}]\in\mathbb{IR}^n, \mathbf{f}([\mathbf{x}])\subset[\mathbf{f}]([\mathbf{x}])\). The output set \([\mathbf{f}]([\mathbf{x}])\) will also enclose unfeasible values, due to the wrapping effect of intervals, or because the inclusion function may not be minimal. The choice is made to have fast calculation times, rather than minimal enclosures. In all cases, calculations are guaranteed to contain all the images.
The class AnalyticFunction
provides a convenient way to perform calculations on intervals, boxes, and interval matrices. It involves symbolic variables and expressions, and their evaluations rely on interval operators from interval analysis. Real values (reals of \(\mathbb{R}\), vectors, matrices) can also be involved, and will be automatically cast into their interval counterparts.
This page provides an overview of the AnalyticFunction
class, its key features, and practical examples of how to use it.
Note

For defining a contractor based on an AnalyticFunction
, the CtcInverse
class is available.
It allows to solve constraints under the form \(\mathbf{f}(\mathbf{x})\in[\mathbf{y}]\).
See more.
Variables
Before defining an AnalyticFunction
, you need to define the variables that will be used in the function. The following classes allow to represent arguments:
ScalarVar()
: constructor for a scalar variableVectorVar(n)
: constructor for a \(n\)-d vector variableMatrixVar(r,c)
: constructor for a \(r\times c\) matrix variable
Expressions
An AnalyticFunction
object is built from:
a list of arguments (
ScalarVar
,VectorVar
orMatrixVar
objects), that can be empty;a scalar or vectorial expression involving the arguments, constants, and possibly other functions.
x1 = ScalarVar()
x2 = ScalarVar()
v = VectorVar(3)
# Example of scalar function: from R to R
f1 = AnalyticFunction([x1], x1*cos(x1))
# Example of vectorial function: from R to R²
f2 = AnalyticFunction([x1], [ x1*cos(x1), x1*sin(x1) ])
# Example of vectorial function: from R³ to R²
f3 = AnalyticFunction([v], Interval(-1,1)*v)
# Example of multivariate vectorial function: from R×R to R³
f4 = AnalyticFunction([x1,x2], [ x1+x2, Interval(0,1)*exp(x1), x2^(1+x1) ])
ScalarVar x1, x2;
VectorVar v(3);
// Example of scalar function: from R to R
AnalyticFunction f1({x1}, x1*cos(x1));
// Example of vectorial function: from R to R²
AnalyticFunction f2({x1}, { x1*cos(x1), x1*sin(x1) });
// Example of vectorial function: from R³ to R²
AnalyticFunction f3({v}, Interval(-1,1)*v);
// Example of multivariate vectorial function: from R×R to R³
AnalyticFunction f4({x1,x2}, { x1+x2, Interval(0,1)*exp(x1), x2^(1+x1) });
For VectorVar
and MatrixVar
, as well as for vector or matrix expressions, coefficients can be accessed using the operators [i]
and (i,j)
respectively. For vector elements, the .subvector(i,j)
method allows to get a subvector of the variable or expression.
# Example of function: from R³ to R²
f5 = AnalyticFunction([v], (v[0]*v).subvector(1,2))
# Example of scalar function: from R^(2x2) to R
M = MatrixVar(2,2)
f6 = AnalyticFunction([M], M(0,0)*M(1,1)-M(1,0)*M(0,1))
// Example of function: from R³ to R²
AnalyticFunction f5({v}, (v[0]*v).subvector(1,2));
// Example of scalar function: from R^(2x2) to R
MatrixVar M(2,2);
AnalyticFunction f6({M}, M(0,0)*M(1,1)-M(1,0)*M(0,1));
Variables are temporary objects used only to construct expressions. They can be freed once the function has been instantiated: there is no memory error in using an AnalyticFunction
without its *Var
arguments in the same scope, as in this example:
def create_f():
x = ScalarVar()
return AnalyticFunction([x], x*cos(x))
f = create_f() # x is no longer useful here
auto create_f()
{
ScalarVar x;
return AnalyticFunction({x}, x*cos(x));
}
auto f = create_f(); // x is no longer useful here
Function composition
AnalyticFunction
objects can be easily composed using the ()
operator. For vectorial functions, the []
operator is also available:
f = AnalyticFunction([x1], x1*cos(x1))
g = AnalyticFunction([x1], [ f(2*x1), x1*sin(x1) ])
h = AnalyticFunction([x1], g(x1)[0]) # output is 2*x*cos(2*x)
AnalyticFunction f({x1}, x1*cos(x1));
AnalyticFunction g({x1}, { f(2*x1), x1*sin(x1) });
AnalyticFunction h({x1}, g(x1)[0]); // output is 2*x*cos(2*x)
Evaluations
AnalyticFunction
objects represent interval inclusion functions: their evaluations consist in computing interval output sets, either Interval
or IntervalVector
outputs depending on the definition.
Evaluations can be done by the .eval()
method of AnalyticFunction
.
x1 = ScalarVar() # scalar argument
f1 = AnalyticFunction([x1], x1*cos(x1))
y1 = f1.eval(0.)
y1 = f1.eval(PI)
y1 = f1.eval(Interval(0,1))
x2 = ScalarVar()
f2 = AnalyticFunction([x1,x2], x1^x2) # example of multivariate function
y2 = f2.eval(Interval(2,3), 2)
v = VectorVar(3) # vector arguments
w = VectorVar(3)
f3 = AnalyticFunction([v,w], v-w) # example of vectorial function
y3 = f3.eval(Vector([5,4,3]), IntervalVector([[3,oo],[2],[1,2]]))
ScalarVar x1; // scalar argument
AnalyticFunction f1({x1}, x1*cos(x1));
Interval y1 = f1.eval(0.);
y1 = f1.eval(PI);
y1 = f1.eval(Interval(0,1));
ScalarVar x2;
AnalyticFunction f2({x1,x2}, x1^x2); // example of multivariate function
Interval y2 = f2.eval(Interval(2,3), 2);
VectorVar v(3), w(3); // vector arguments
AnalyticFunction f3({v,w}, v-w); // example of vectorial function
IntervalVector y3 = f3.eval(Vector({5,4,3}), IntervalVector({{3,oo},{2},{1,2}}));
For multivariate functions, it is possible to provide several inputs to the .eval()
method, as in the above example with f2
or f3
. In Codac C++, the arguments may be of different types (any mixed scalar, vector, or matrix types). In Python and Matlab however, the binding does not allow any combination of inputs, but several arguments of same structural types can be provided: a list of scalar values, or a list of vector values (Vector
, IntervalVector
), or a list of matrix values (Matrix
, IntervalMatrix
).
Evaluation modes
The class provides three ways of evaluating functions:
natural evaluations \([\mathbf{f}_n]([\mathbf{x}])\): each operator of the analytic function is evaluated by intervals in a natural way. However, natural evaluations may be pessimistic in case of multiple occurences in the expressions. For instance, the evaluation of \([x]-[x]\) will not be \(0\). This is a classic drawback of interval arithmetic.
centered form evaluations \([\mathbf{f}_c]([\mathbf{x}])\): computations are made using Eq. (1), depicting a centered form expression. Results are significantly improved for small boxes, but will be worse than a natural evaluation for larger boxes.
both natural and centered form evaluations \([\mathbf{f}_n]([\mathbf{x}])\cap[\mathbf{f}_c]([\mathbf{x}])\): the two previous evaluations are carried out simultaneously, and the result is the intersection of the two evaluations. This allows to benefit from the best of both worlds: natural evaluations for large boxes and centered evaluations for small boxes.
By default, the latter mode is used for evaluations. To select a specific mode, the .eval()
method can be configured with the desired evaluation mode prior to the inputs:
f1.eval(EvalMode.NATURAL, Interval(0,1))
f1.eval(EvalMode.CENTERED, Interval(0,1))
f1.eval(EvalMode.NATURAL | EvalMode.CENTERED, Interval(0,1))
# which is equivalent to: f1.eval(Interval(0,1))
f1.eval(EvalMode::NATURAL, Interval(0,1));
f1.eval(EvalMode::CENTERED, Interval(0,1));
f1.eval(EvalMode::NATURAL | EvalMode::CENTERED, Interval(0,1));
// which is equivalent to: f1.eval(Interval(0,1));
Interval automatic differentiation
The class provides a simple and efficient way to compute the set of derivatives of functions through its .diff()
method.
The method computes derivatives with respect to the function’s interval inputs directly, avoiding approximation errors and providing guaranteed results. It works by breaking down complex functions into simpler operations, and then systematically applying the chain rule to compute derivatives of each operation. Symbolic differentiation is not involved in this process.
The output is an IntervalMatrix
corresponding to an enclosure \([\mathbf{J}_{\mathbf{f}}]([\mathbf{x}])\) of the Jacobian \(\mathbf{J}_{\mathbf{f}}([\mathbf{x}])\):
The .diff()
method can be used in the same way as the .eval()
method.
x1 = ScalarVar()
f1 = AnalyticFunction([x1], x1*cos(x1))
J1 = f1.diff(Interval(0,PI/2))
# J1 = intv. matrix 1x1: [[ [-(PI/2),1] ]]
x2 = ScalarVar()
f2 = AnalyticFunction([x1,x2], x1^x2) # example of multivariate function
J2 = f2.diff(2.,Interval(2,3))
# J2 = intv. matrix 1x2: [[ [4,12], [0,0] ]]
v = VectorVar(3)
f3 = AnalyticFunction([v], [ # vectorial function
v[0]-(v[1]^2),
Interval(-1,0)*v[2]
])
J3 = f3.diff(Vector([5,8,10]))
# J3 = intv. matrix 2x3: [[ 1,-16,0 ],[ 0,0,[-1,0] ]]
ScalarVar x1;
AnalyticFunction f1({x1}, x1*cos(x1));
IntervalMatrix J1 = f1.diff(Interval(0,PI/2));
// J1 = intv. matrix 1x1: [[ [-(PI/2),1] ]]
ScalarVar x2;
AnalyticFunction f2({x1,x2}, x1^x2); // example of multivariate function
IntervalMatrix J2 = f2.diff(2.,Interval(2,3));
// J2 = intv. matrix 1x2: [[ [4,12], [0,0] ]]
VectorVar v(3);
AnalyticFunction f3({v}, { // vectorial function
v[0]-(v[1]^2),
Interval(-1,0)*v[2]
});
IntervalMatrix J3 = f3.diff(Vector({5,8,10}));
// J3 = intv. matrix 2x3: [[ 1,-16,0 ],[ 0,0,[-1,0] ]]
Other properties
Let us consider a function \([\mathbf{f}]:\mathbb{IR}^n\to\mathbb{IR}^m\), then the dimensions \(n\) and \(m\) can be accessed by:
n = f.input_size()
m = f.output_size()
int n = f.input_size();
int m = f.output_size();
In the case of multivariate functions, .input_size()
returns the sum of the dimensions of the arguments.
The AnalyticFunction
class supports many mathematical operations, and the full set of operators that can be used is described in the next page.