.. _getting-started:
Getting Started
=====================
This chapter provides a high-level overview of how to begin using
**ChenFliessSeries.jl**. It introduces the core workflow, explains the
main concepts, and walks through the essential steps for computing
Chen–Fliess expansions in practice.
The goal is to give you a clear mental model first, and then guide you
through concrete examples.
Contents
--------
- :ref:`installation`
- :ref:`basic-usage`
- :ref:`iterated-integrals`
- :ref:`vector-fields`
- :ref:`lie-derivatives`
- :ref:`truncated-series`
- :ref:`ode-comparison`
- :ref:`pitfalls`
- :ref:`more-examples`
.. _installation:
Installation
-----------------
To install the **ChenFliessSeries.jl** package, run the following command
in your terminal.
Using the Julia REPL's Pkg mode:
.. code-block:: bash
:linenos:
julia> ]
pkg> add ChenFliessSeries
Or using the Pkg module in the standard REPL:
.. code-block:: bash
:linenos:
julia> using Pkg
julia> Pkg.add("ChenFliessSeries")
This will download and install the package along with its dependencies.
Make sure you have Julia 1.12.3 or higher installed on your system.
Quick sanity check:
.. code-block:: julia
:linenos:
using ChenFliessSeries
@info "ChenFliessSeries.jl loaded successfully!"
.. _basic-usage:
Basic Usage (High-Level Overview)
-------------------------------------
Once installed, **ChenFliessSeries.jl** enables you to compute the
building blocks of the Chen–Fliess expansion:
1. **Iterated integrals** of the input
2. **Lie derivatives** of the output along the vector fields
3. **Chen–Fliess coefficients** :math:`(c,\eta)`
4. **Truncated Chen–Fliess series** :math:`F_c^{N}[u](t)`
5. **Comparison with the true system output**
A typical workflow looks like this:
.. mermaid::
flowchart TD
classDef step fill:#f2f2f2,stroke:#333,stroke-width:1px,rx:6px,ry:6px,color:black;
U["Inputs
$$\ u(t)$$"]:::step
E["Iterated integrals
$$\ E^N_\eta[u](t)$$"]:::step
G["Vector fields
$$\ g_i$$"]:::step
L["Lie derivatives
$$\ L_\eta h$$"]:::step
F["Chen–Fliess series
$$\ F_c^N[u](t)$$"]:::step
O["Output of the system
$$\ h(t)$$"]:::step
G --> L --> F
O --> L
U --> E --> F
The sections below walk through each step in detail.
.. _iterated-integrals:
Computing iterated integrals
-------------------------------------
To compute the iterated integrals :math:`E_\eta[u](t)`,
you must define:
- time interval :math:`[0,t_f]`,
- input function :math:`u(t)`,
- the integration step :math:`dt`.
- truncation length :math:`N`
.. code-block:: julia
:linenos:
using ChenFliessSeries
dt = 0.001
t = 0:dt:0.1
u0 = one.(t)
u1 = sin.(t)
u2 = cos.(t)
utemp = vcat(u0', u1', u2') # shape: (m+1, length(t))
Ntrunc = 4
E = iter_int(utemp, dt, Ntrunc)
This computes all iterated integrals :math:`E_\eta[u](t)` for
:math:`|\eta| \le N`.
The algorithm of the `iter_int` function is based on Chen's identity
which translates numerically to
.. math::
:label: eq:cfs
\begin{aligned}
E_{X^k}[u](t)=\int _0^t u(t)\otimes E_{X^{k-1}}[u](t) d\tau .
\end{aligned}
where :math:`u(t)` is the matrix of inputs stacked horizontally,
:math:`E_{X^k}[u](t)` is the matrix that stacks horizontally the iterated integrals
and the tensor symbol :math:`\otimes` represents
the `column-wise Kronecker product `_ .
The outline of the calculation of the algorithm follows the workflow:
.. mermaid::
flowchart TD
classDef step fill:#f2f2f2,stroke:#333,stroke-width:1px,rx:6px,ry:6px,color:black;
classDef calc fill:#e8f0ff,stroke:#333,stroke-width:1px,rx:6px,ry:6px,color:black;
classDef loop fill:#fff4d6,stroke:#333,stroke-width:1px,rx:6px,ry:6px,color:black;
A["Start
$$\ ( u_{\text{temp}}, dt, N_{\text{trunc}})$$"]:::step
H["Compute first-order integrals: $$\ E_{X^1}[u](t) $$"]:::calc
I{"Loop i = 1 to Ntrunc-1"}:::loop
K[" $$\ \text{Etemp} = u(t)\otimes E_{X^{i}}[u](t) $$"]:::calc
M["Compute: $$\ E_{X^{i+1}}[u](t) = \int _0^t \text{Etemp} d\tau $$"]:::calc
N["Store $$\ E_{X^{i+1}}[u](t) $$"]:::step
O["Return the integral block"]:::step
%% Connections
A --> H --> I
I --> K --> M
M --> N --> I
I --> O
.. _vector-fields:
Defining vector fields and outputs
-------------------------------------
To compute Chen–Fliess coefficients :math:`(c,\eta) = L_\eta h`,
you must define:
- the drift vector field :math:`g_0(z)`,
- the controlled vector fields :math:`g_i(z)`,
- the output function :math:`h(z)`.
Example:
.. code-block:: julia
:linenos:
using Symbolics
@variables x[1:6]
z_vec = x
Ntrunc = 4
h = x[1]
# parameters
gg = 9.81 # Gravitational acceleration (m/s^2)
m = 0.18 # Mass (kg)
Ixx = 0.00025 # Mass moment of inertia (kg*m^2)
L = 0.086 # Arm length (m)
g = hcat(
[x[4], x[5], x[6], 0, -gg, 0],
[0, 0, 0, 1/m*sin(x[3]), 1/m*cos(x[3]), -L/Ixx],
[0, 0, 0, 1/m*sin(x[3]), 1/m*cos(x[3]), L/Ixx]
)
.. _lie-derivatives:
Computing Lie derivatives
-------------------------------------
Lie derivatives encode the geometric structure of the system.
.. code-block:: julia
:linenos:
x_val = [0.5, 0.0, 0.1, 0.0, 0.0, 0.0] # make it Float64 to avoid promotion issues
# initial evaluator for Ntrunc = 4
f_L = build_lie_evaluator(h, g, x_vec, Ntrunc)
L_eval = f_L(x_val) # Vector{Float64}, no Symbolics anywhere
Similarly to the iterated integrals, the outline of the calculation of the algorithm follows the workflow:
.. mermaid::
flowchart TD
classDef step fill:#f2f2f2,stroke:#333,stroke-width:1px,rx:6px,ry:6px,color:black;
classDef calc fill:#e8f0ff,stroke:#333,stroke-width:1px,rx:6px,ry:6px,color:black;
classDef loop fill:#fff4d6,stroke:#333,stroke-width:1px,rx:6px,ry:6px,color:black;
A["Start
$$\ ( g_i(z), h(z), N_{\text{trunc}})$$"]:::step
H["Compute first-order Lie derivatives: $$\ L_{X^1}h(z) $$"]:::calc
I{"Loop i = 1 to Ntrunc-1"}:::loop
K[" $$\ \text{Ltemp} = \frac{\partial}{\partial z}L_{X^i}h(z) $$"]:::calc
M["Compute: $$\ g\otimes \text{Ltemp} $$"]:::calc
N["Store $$\ L_{X^{i+1}}h(z) $$"]:::step
O["Return the Lie derivative block"]:::step
%% Connections
A --> H --> I
I --> K --> M
M --> N --> I
I --> O
.. _truncated-series:
Computing truncated Chen–Fliess series
-----------------------------------------
Once iterated integrals and Lie derivatives are available, you can
assemble the truncated Chen–Fliess series:
.. code-block:: julia
:linenos:
Fc = z_val[1] .+ vec(L_eval' * E)
This returns a numerical approximation of
.. math::
F_c^{N}[u](t) = \sum_{|\eta| \le N} (c, \eta)\, E_\eta[u](t).
.. _ode-comparison:
Comparing with ODE simulation
-------------------------------------
To validate the approximation, compare it with the true system output.
.. code-block:: julia
:linenos:
using DifferentialEquations
function twodquad!(dx, x, p, t)
# input u1(t)
u1 = sin(t) # scalar, t is a Float64 here
u2 = cos(t)
# same dynamics as symbolic g, but numeric
dx[1] = x[4]
dx[2] = x[5]
dx[3] = x[6]
dx[4] = 1/m*sin(x[3])*(u1+u2)
dx[5] = -gg + (1/m*cos(x[3]))*(u1+u2)
dx[6] = (L/Ixx)*(u2-u1)
end
x0 = [0.0, 0.0, 0.1, 0.0, 0.0, 0.0]
tspan = (0.0, 0.1)
prob = ODEProblem(twodquad!, x0, tspan)
sol = solve(prob, Tsit5(), saveat = t)
x1_ode = sol[1, :] # extract x₂(t), since h = x₂
y_true = x1_ode
y_cfs = Fc
.. _pitfalls:
Common pitfalls
------------------
- **Mismatched dimensions**: Inputs must have shape `(m+1, length(t))`.
- **Transpose required**: Use `vcat(u0', u1', ...)`.
- **Large truncation depth**: Word count grows combinatorially.
- **Vector fields should be symbolic** for compliance.
- **Indexing inside ODE solvers** must match the time grid.
.. _more-examples:
More examples
-----------------
For more detailed examples and advanced usage,
see the `examples `_ section of the documentation.