Skip to content

Commit 0fd3585

Browse files
authored
Merge pull request #337 from godardma/parallelization
Parallelization for PEIBOS
2 parents 38072cd + b125268 commit 0fd3585

29 files changed

Lines changed: 835 additions & 91 deletions

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@
144144
endif()
145145
# Adds Eigen3::Eigen
146146

147+
################################################################################
148+
# Looking for Threads
149+
################################################################################
150+
151+
find_package(Threads REQUIRED)
147152

148153
################################################################################
149154
# Looking for CAPD (if needed)
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
.. _sec-extensions-capd-capd:
2+
3+
CAPD (rigorous numerics in dynamical systems)
4+
=============================================
5+
6+
Main author: `Maël Godard <https://godardma.github.io>`_
7+
8+
This page describes how to use the CAPD library with Codac. CAPD is a C++ library for rigorous numerics in dynamical systems.
9+
10+
To use CAPD with Codac, you first need to install the CAPD library. You can find the installation instructions on the `CAPD website <http://capd.ii.uj.edu.pl/html/capd_compilation.html>`_.
11+
12+
Note that as CAPD is a C++ only library, the content present in this page is **only available in C++**.
13+
14+
15+
.. _subsec-extensions-capd-capd-install:
16+
Installing the ``codac-capd`` extension
17+
---------------------------------------
18+
19+
To install the ``codac-capd`` extension, you need to install the Codac library from its sources. This can be done :ref:`by using CMake <sec-install-cpp>` with the option ``WITH_CAPD=ON``. For example:
20+
21+
.. code-block:: bash
22+
23+
cmake -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release -DWITH_CAPD=ON ..
24+
25+
We highly recommend to test the installation of the library with the provided tests. To do so, you can use the following command:
26+
27+
.. code-block:: bash
28+
29+
make test
30+
31+
32+
Content
33+
-------
34+
35+
The ``codac-capd`` extension provides functions to convert CAPD objects to Codac objects and vice versa.
36+
37+
The functions are ``to_capd`` and ``to_codac``. They can be used to convert the following objects:
38+
39+
- ``capd::Interval`` :math:`\leftrightarrow` ``codac2::Interval``
40+
- ``capd::IVector`` :math:`\leftrightarrow` ``codac2::IntervalVector``
41+
- ``capd::IMatrix`` :math:`\leftrightarrow` ``codac2::IntervalMatrix``
42+
- ``capd::ITimeMap::SolutionCurve`` :math:`\rightarrow` ``codac2::SlicedTube<codac2::IntervalVector>``
43+
44+
45+
How to use
46+
----------
47+
48+
The header of the ``codac-capd`` extension is not included by default. You need to include it manually in your code, together with the CAPD library:
49+
50+
.. code-block:: c++
51+
52+
#include <codac-capd.h>
53+
#include <capd/capdlib.h>
54+
55+
You can use the functions ``to_capd`` and ``to_codac`` to convert between CAPD and Codac objects as follows:
56+
57+
.. tabs::
58+
59+
.. code-tab:: c++
60+
61+
codac2::Interval codac_interval(0,2); // Codac interval [0, 2]
62+
capd::Interval capd_interval = to_capd(codac_interval); // convert to CAPD interval
63+
codac2::Interval codac_interval2 = to_codac(capd_interval); // convert back to Codac interval
64+
65+
66+
Example
67+
-------
68+
69+
.. image:: img/pendulum.png
70+
:alt: State variables of the pendulum
71+
:align: right
72+
:width: 130px
73+
74+
For this example we will consider the pendulum with friction.
75+
76+
The state variables of the pendulum are its angle :math:`\theta` and its angular velocity :math:`\omega`. The pendulum follows the following dynamic:
77+
78+
.. math::
79+
80+
\left(\begin{array}{c}
81+
\dot{\theta}\\
82+
\dot{\omega}
83+
\end{array}\right)=\left(\begin{array}{c}
84+
\omega\\
85+
-\sin(\theta)\cdot\frac{g}{l}-0.5\omega
86+
\end{array}\right),
87+
88+
89+
where :math:`g` is the gravity constant and :math:`l` is the length of the pendulum.
90+
91+
This equation can be passed to the CAPD library as follows:
92+
93+
.. tabs::
94+
95+
.. group-tab:: C++
96+
97+
.. literalinclude:: src.cpp
98+
:language: c++
99+
:start-after: [codac-capd-2-beg]
100+
:end-before: [codac-capd-2-end]
101+
:dedent: 2
102+
103+
To solve this ODE, an ``IOdeSolver`` object is necessary.
104+
105+
.. tabs::
106+
107+
.. group-tab:: C++
108+
109+
.. literalinclude:: src.cpp
110+
:language: c++
111+
:start-after: [codac-capd-3-beg]
112+
:end-before: [codac-capd-3-end]
113+
:dedent: 2
114+
115+
CAPD then uses an ``ITimeMap`` to make the link between a time step and the solution of the ODE at this time. The ``I`` here stands for ``Interval`` as the solution is an interval guaranteed to enclose the solution. Here we will integrate the ODE between :math:`t_0=0s` and :math:`t_f=20s`.
116+
117+
.. tabs::
118+
119+
.. group-tab:: C++
120+
121+
.. literalinclude:: src.cpp
122+
:language: c++
123+
:start-after: [codac-capd-4-beg]
124+
:end-before: [codac-capd-4-end]
125+
:dedent: 2
126+
127+
To completly define the ODE, we need to define the initial conditions. Here we will set the initial angle to :math:`\theta_0=-\frac{\pi}{2}` and the
128+
initial angular velocity to :math:`\omega_0=0`. For the purpose of this example, we will add a small uncertainty to the initial conditions. The initial conditions are then defined as follows:
129+
130+
.. tabs::
131+
132+
.. group-tab:: C++
133+
134+
.. literalinclude:: src.cpp
135+
:language: c++
136+
:start-after: [codac-capd-5-beg]
137+
:end-before: [codac-capd-5-end]
138+
:dedent: 2
139+
140+
There are then two ways to get the result of the integration depending on the use case.
141+
142+
If the desired result is the solution of the ODE at a given time (here say :math:`T=1s`), we can do as follows:
143+
144+
.. tabs::
145+
146+
.. group-tab:: C++
147+
148+
.. literalinclude:: src.cpp
149+
:language: c++
150+
:start-after: [codac-capd-6-beg]
151+
:end-before: [codac-capd-6-end]
152+
:dedent: 2
153+
154+
**Be careful, this method modifies the initial set** ``s`` **in place**.
155+
156+
If the desired result is the solution curve (or tube) of the ODE on the time domain :math:`[t_0,t_f]`, we can do as follows:
157+
158+
.. tabs::
159+
160+
.. group-tab:: C++
161+
162+
.. literalinclude:: src.cpp
163+
:language: c++
164+
:start-after: [codac-capd-7-beg]
165+
:end-before: [codac-capd-7-end]
166+
:dedent: 2
167+
168+
The variable ``solution`` is the desired solution curve (or tube). The operator ``solution(t)`` gives the solution at time :math:`t`.
169+
It can be converted into a Codac ``SlicedTube<IntervalVector>`` with the function ``to_codac``. This functions takes two arguments:
170+
171+
- the ``capd::ITimeMap::SolutionCurve`` to convert.
172+
- a ``codac2::TDomain`` object defining the temporal domain of the tube.
173+
174+
The resulting ``SlicedTube`` will have the same time domain as the one given in argument, completed with the CAPD gates. An example of conversion is :
175+
176+
.. tabs::
177+
178+
.. group-tab:: C++
179+
180+
.. literalinclude:: src.cpp
181+
:language: c++
182+
:start-after: [codac-capd-8-beg]
183+
:end-before: [codac-capd-8-end]
184+
:dedent: 2
185+
186+
A full display can be done with the following code:
187+
188+
.. tabs::
189+
190+
.. group-tab:: C++
191+
192+
.. literalinclude:: src.cpp
193+
:language: c++
194+
:start-after: [codac-capd-9-beg]
195+
:end-before: [codac-capd-9-end]
196+
:dedent: 4
197+
198+
The result is the following figure, with in green the initial set (:math:`t=0s`) and in red the final set (:math:`t=20s`). The ``SlicedTube`` is displayed in blue with a black edge for better visibility. The orange rectangles correspond to the gates (degenerate slices).
199+
200+
.. figure:: img/pendulum_result.png
201+
:width: 500px
202+
203+
Result of the CAPD integration of the pendulum, enclosed in a Codac tube.
1.18 MB
Loading
80.6 KB
Loading
93.9 KB
Loading
137 KB
Loading
28 KB
Loading
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
.. _sec-extensions-capd-peibos:
2+
3+
PEIBOS-CAPD
4+
===========
5+
6+
When compiling CODAC with the codac-capd extension (see :ref:`here <subsec-extensions-capd-capd-install>`), the CAPD version of the PEIBOS library is also compiled.
7+
8+
Let us consider an initial set :math:`\mathbb{X}_0 \subset \mathbb{R}^n` with its boundary :math:`\partial \mathbb{X}_0`.
9+
Considering a dynamical system :math:`\dot{\mathbf{x}}=\gamma(\mathbf{x})`, the PEIBOS tool allows to compute the reach set :math:`\mathbf{X}_t=\left\{ \mathbf{x}(t) \mid \mathbf{x} \in \partial \mathbb{X}_0 \right\}`.
10+
11+
Gnomonic atlas
12+
--------------
13+
14+
To handle the boundary of the initial set :math:`\mathbb{X}_0`, the PEIBOS tool relies on a gnomonic atlas. See :ref:`subsec-functions-peibos-gnomonic-atals`.
15+
16+
Use
17+
---
18+
19+
The computation of the reach set is decomposed into two separate functions.
20+
21+
PEIBOS
22+
~~~~~~
23+
24+
The PEIBOS function takes at least six arguments :
25+
26+
- The CAPD IMap representing :math:`\gamma`.
27+
- The final time for the integration of the ODE.
28+
- A timestep to get intermediate states.
29+
- The inverse chart for the gnomonic atlas (an analytic function).
30+
- The list of symmetries for the gnomonic atlas. Note that each symmetry is represented as a hyperoctahedral symmetry, see :ref:`sec-actions-octasym`.
31+
- A resolution :math:`\epsilon`. The initial box :math:`\left[-1,1\right]^m` will initiallly be splitted in boxes with a diameter smaller than :math:`\epsilon`.
32+
- Eventually an offset vector can be specified if the initial set is not centered around the origin.
33+
- Eventually a flag can be set to True to get the verbose.
34+
35+
For each of the small box :math:`\left[\mathbf{x}(0)\right]`, this function computes a box containing :math:`\bar{\mathbf{x}}(t)` and an interval matrix enclosing the Jacobian matrix :math:`D\mathbf{\left[x\right]}(t)`.
36+
37+
It returns a map where the keys are the time steps. For each time step, the value is a vector of tuple, where each tuple contains:
38+
39+
- A `PEIBOS_CAPD_Key` representing the symmetry and the initial box used (plus an eventual offset), i.e. :math:`\mathbf{x}(0)= \sigma(\psi_0(\mathbf{\text{box}})) + \text{offset}`
40+
- A box enclosing :math:`\bar{\mathbf{x}}(t)`
41+
- An interval matrix enclosing the Jacobian matrix :math:`D\mathbf{\left[x\right]}(t)`
42+
43+
Each tuple can then be used to build a Parallelepiped enclosing :math:`\mathbf{x}(t)` using the parallelepiped inclusion. This is done in the `reach_set` function.
44+
45+
The full signature of the function is :
46+
47+
.. doxygenfunction:: codac2::PEIBOS(const capd::IMap&, double, double, const AnalyticFunction<VectorType>&, const std::vector<OctaSym>&, double, const Vector&, bool);
48+
:project: codac
49+
50+
reach_set
51+
~~~~~~~~~
52+
53+
The reach_set function takes only one argument : the map returned by the PEIBOS function.
54+
55+
It returns a map where the keys are the time steps. For each time step, the value is a vector of :ref:`subsec-zonotope-parallelepiped`. Their union is an outer approximation of :math:`\mathbf{X}_t`.
56+
57+
This function is then simply :
58+
59+
.. tabs::
60+
61+
.. group-tab:: C++
62+
63+
.. literalinclude:: src.cpp
64+
:language: c++
65+
:start-after: [peibos-capd-1-beg]
66+
:end-before: [peibos-capd-1-end]
67+
:dedent: 0
68+
69+
The `parallelepiped_inclusion` is the one described in `this article <https://www.sciencedirect.com/science/article/pii/S0888613X25002154?via%3Dihub>`_.
70+
71+
.. tabs::
72+
73+
.. group-tab:: C++
74+
75+
.. literalinclude:: src.cpp
76+
:language: c++
77+
:start-after: [peibos-capd-2-beg]
78+
:end-before: [peibos-capd-2-end]
79+
:dedent: 0
80+
81+
Examples
82+
--------
83+
84+
2D : Pendulum
85+
~~~~~~~~~~~~~
86+
87+
Say that we want to integrate the state of the pendulum starting from the an initial box. It is defined by
88+
89+
.. math::
90+
\dot{x}=\gamma(x) = \begin{pmatrix}
91+
x_2 \\
92+
-5\cdot\sin (x_1) - 0.5\cdot x_2
93+
\end{pmatrix}
94+
95+
The corresponding code is:
96+
97+
.. tabs::
98+
99+
.. group-tab:: C++
100+
101+
.. literalinclude:: src.cpp
102+
:language: c++
103+
:start-after: [peibos-capd-3-beg]
104+
:end-before: [peibos-capd-3-end]
105+
:dedent: 4
106+
107+
The result is
108+
109+
.. image:: img/pendulum_peibos.png
110+
:alt: 20 seconds of integration of the pendulum
111+
:align: center
112+
:width: 400px
113+
114+
3D : Lorenz system
115+
~~~~~~~~~~~~~~~~~~
116+
117+
Say that we want to integrate the state of the pendulum starting from the an initial sphere. It is defined by
118+
119+
.. math::
120+
\dot{x}=\gamma(x) = \begin{pmatrix}
121+
\sigma (x_2 - x_1) \\
122+
x_1 (\rho - x_3) - x_2 \\
123+
x_1 x_2 - \beta x_3
124+
\end{pmatrix}
125+
126+
The corresponding code is:
127+
128+
.. tabs::
129+
130+
.. group-tab:: C++
131+
132+
.. literalinclude:: src.cpp
133+
:language: c++
134+
:start-after: [peibos-capd-4-beg]
135+
:end-before: [peibos-capd-4-end]
136+
:dedent: 4
137+
138+
The result is
139+
140+
.. image:: img/lorenz.png
141+
:alt: Integration of the Lorenz system
142+
:align: center
143+
:width: 500px
144+
145+
Related work
146+
------------
147+
148+
This method comes from `this article <https://www.sciencedirect.com/science/article/pii/S0888613X25002154?via%3Dihub>`_.

0 commit comments

Comments
 (0)