Skip to content

Commit 005bd03

Browse files
authored
Merge pull request #183 from SimonRohou/codac2_dev
Updates
2 parents 2c20d6e + eb09056 commit 005bd03

File tree

10 files changed

+146
-59
lines changed

10 files changed

+146
-59
lines changed

doc/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mathjax_stmaryrd.js
1111

1212
if(WITH_PYTHON)
1313

14-
find_package(Doxygen 1.0.0)
14+
find_package(Doxygen)
1515

1616
if(NOT DOXYGEN_FOUND)
1717

doc/manual/development/info_dev.rst

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,23 @@ If you simply want to use the latest Codac release in Python, you can download t
3636
1. **Ensure the following prerequisites are met**:
3737

3838
- the prerequisites for the :ref:`C++ installation of Codac <sec-install-cpp-prerequisites>`.
39-
- a recent `Doxygen <https://www.doxygen.nl>`_ version. On Linux systems, Debian packages are available:
39+
- a supported version of Python (>=3.6).
40+
- a recent `Doxygen <https://www.doxygen.nl>`_ version (for instance, release 1.13.0 or newest). On Linux systems, latest releases are not available as Debian packages, so we advice to install Doxygen from the sources:
4041

4142
.. code-block:: bash
4243
43-
sudo apt-get install -y doxygen
44+
cd $HOME
45+
git clone https://github.com/doxygen/doxygen
46+
cd doxygen
47+
git checkout Release_1_13_0 # 1.13.0, or any newer release
48+
mkdir build ; cd build
49+
cmake -DCMAKE_INSTALL_PREFIX=$HOME/doxygen/build_install ..
50+
make ; make install
51+
52+
.. admonition:: About the use of Doxygen
53+
54+
Doxygen software extracts C++ documentation from header files into XML format. We then convert this data into docstring format before embedding it into the binding binaries. In this way, the writing of the documentation is centralized in a single location in the C++ header files.
4455

45-
- a supported version of Python (>=3.6).
4656

4757
2. **Configure IBEX prior to compiling Codac**:
4858

@@ -58,8 +68,7 @@ If you simply want to use the latest Codac release in Python, you can download t
5868
5969
cd $HOME/ibex-lib/build
6070
cmake -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release ..
61-
make
62-
make install
71+
make ; make install
6372
6473
3. **Compile Codac with Python binding**:
6574

@@ -78,7 +87,7 @@ If you simply want to use the latest Codac release in Python, you can download t
7887
git submodule init ; git submodule update
7988
# Configure CMake
8089
cmake -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DWITH_PYTHON=ON -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release ..
81-
make
90+
make ; make install
8291
8392
4. **Configure your Python environment**:
8493

@@ -89,6 +98,12 @@ If you simply want to use the latest Codac release in Python, you can download t
8998
cd $HOME/codac/build/python/python_package
9099
python setup.py develop --user
91100
101+
And update your configuration file (for instance, ``$HOME/.bashrc`` on Linux systems) with:
102+
103+
.. code-block:: bash
104+
105+
export PYTHONPATH="${PYTHONPATH}:$HOME/codac/build/python/python_package/"
106+
92107
5. **Verify the installation** (optional):
93108

94109
To ensure that the installation has worked properly, the unit tests of the library can be run:
@@ -110,11 +125,6 @@ If you simply want to use the latest Codac release in Python, you can download t
110125
You should obtain a graphical output corresponding to a set inversion.
111126

112127

113-
.. admonition:: About the use of Doxygen
114-
115-
Doxygen software extracts C++ documentation from header files into XML format. We then convert this data into docstring format before embedding it into the binding binaries. In this way, the writing of the documentation is centralized in a single location in the C++ header files.
116-
117-
118128
.. admonition:: For admins
119129

120130
The command for uploading the generated wheels on PyPi is:

doc/manual/manual/installation/cpp.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Steps
8888
8989
# Configure IBEX before installation
9090
cd $HOME/ibex-lib
91-
mkdir build && cd build
91+
mkdir build ; cd build
9292
cmake -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release ..
9393
9494
# Building + installing
@@ -113,7 +113,7 @@ Steps
113113
cd $HOME/codac
114114
# Get automatically pybind11 and eigen submodules:
115115
git submodule init ; git submodule update
116-
mkdir build && cd build
116+
mkdir build ; cd build
117117
cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release ..
118118
119119
# Building + installing
@@ -147,7 +147,7 @@ Steps
147147
.. code-block:: bash
148148
149149
cd $HOME/codac/examples/01_batman
150-
mkdir build && cd build
150+
mkdir build ; cd build
151151
cmake ..
152152
make
153153

doc/manual/manual/installation/python.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
Python installation
44
===================
55

6+
.. error::
7+
8+
The following instructions are not valid at the moment: Codac v2 is not yet available on PyPi. To get Codac v2 in Python, please :ref:`compile your own binaries locally on your machine <sec-dev-info-binding>`.
9+
610
In case you want to use Codac only with Python, then the installation procedure is simply:
711

812
1. **Dependencies**: Ensure you have a supported version of Python (>=3.6).

python/src/core/codac2_py_cast.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#pragma once
1212

1313
#include <pybind11/pybind11.h>
14+
#include <codac2_AnalyticTraj.h>
1415

1516
namespace py = pybind11;
1617
using namespace pybind11::literals;
@@ -33,6 +34,25 @@ namespace codac2
3334
return x.cast<const T&>();
3435
}
3536

37+
// Casting to trajectory types
38+
39+
template<typename T>
40+
requires std::is_same_v<T,AnalyticTraj<VectorType>>
41+
bool is_instance(const py::object& x)
42+
{
43+
const py::object& x_traj = x.attr("traj");
44+
return x_traj && py::isinstance<T>(x_traj);
45+
}
46+
47+
template<typename T>
48+
requires std::is_same_v<T,AnalyticTraj<VectorType>>
49+
const T& cast(const py::object& x)
50+
{
51+
assert(is_instance<T>(x));
52+
const py::object& x_traj = x.attr("traj");
53+
return x_traj.cast<const T&>();
54+
}
55+
3656
// Casting to function/expression types
3757

3858
template<typename T>

python/src/core/functions/analytic/codac2_py_AnalyticFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ using namespace pybind11::literals;
9090
\
9191
; \
9292

93-
FunctionArgsList create_FunctionArgsList(const std::vector<py::object>& l)
93+
inline FunctionArgsList create_FunctionArgsList(const std::vector<py::object>& l)
9494
{
9595
FunctionArgsList args {};
9696
Index i = 0;

python/src/core/paver/codac2_py_pave.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,20 @@ using namespace pybind11::literals;
2121

2222
void export_pave(py::module& m)
2323
{
24-
m.def("pave", (PavingOut (*)(const IntervalVector&,const CtcBase<IntervalVector>&,double))&codac2::pave,
25-
PAVINGOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_CTCBASE_INTERVALVECTOR_REF_DOUBLE,
26-
"x"_a, "c"_a, "eps"_a);
24+
m.def("pave", (PavingOut (*)(const IntervalVector&,const CtcBase<IntervalVector>&,double,bool))&codac2::pave,
25+
PAVINGOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_CTCBASE_INTERVALVECTOR_REF_DOUBLE_BOOL,
26+
"x"_a, "c"_a, "eps"_a, "verbose"_a=false);
2727

28-
m.def("pave", (PavingInOut (*)(const IntervalVector&,const SepBase&,double))&codac2::pave,
29-
PAVINGINOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_SEPBASE_REF_DOUBLE,
30-
"x"_a, "s"_a, "eps"_a);
28+
m.def("pave", (PavingInOut (*)(const IntervalVector&,const SepBase&,double,bool))&codac2::pave,
29+
PAVINGINOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_SEPBASE_REF_DOUBLE_BOOL,
30+
"x"_a, "s"_a, "eps"_a, "verbose"_a=false);
3131

3232
m.def("sivia",
3333
[](const IntervalVector& x, const py::object& f, const py::object& y, double eps, bool verbose)
3434
{
3535
if(!is_instance<AnalyticFunction<ScalarType>>(f)
3636
&& !is_instance<AnalyticFunction<VectorType>>(f)
37-
&& !is_instance<AnalyticFunction<VectorType>>(f))
38-
{
37+
&& !is_instance<AnalyticFunction<VectorType>>(f)) {
3938
assert_release("sivia: invalid function type");
4039
}
4140

python/src/graphics/figures/codac2_py_Figure2D.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
#include <pybind11/pybind11.h>
1111
#include <pybind11/operators.h>
1212
#include <pybind11/stl.h>
13+
#include <codac2_Paving.h>
1314
#include <codac2_Figure2D.h>
1415
#include "codac2_py_Figure2D_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py):
1516
#include "codac2_py_matlab.h"
1617
#include "codac2_py_cast.h"
17-
#include <codac2_Paving.h>
1818

1919
using namespace std;
2020
using namespace codac2;
@@ -135,22 +135,36 @@ void export_Figure2D(py::module& m)
135135
VOID_FIGURE2D_DRAW_ELLIPSE_CONST_VECTOR_REF_CONST_VECTOR_REF_DOUBLE_CONST_STYLEPROPERTIES_REF,
136136
"c"_a, "ab"_a, "theta"_a, "s"_a=StyleProperties())
137137

138-
.def("draw_trajectory", (void(Figure2D::*)(const AnalyticTraj<VectorType>&,const StyleProperties&))&Figure2D::draw_trajectory,
139-
VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF,
140-
"x"_a, "s"_a=StyleProperties())
141-
142138
.def("draw_trajectory", (void(Figure2D::*)(const SampledTraj<Vector>&,const StyleProperties&))&Figure2D::draw_trajectory,
143139
VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_STYLEPROPERTIES_REF,
144140
"x"_a, "s"_a=StyleProperties())
145141

146-
.def("draw_trajectory", (void(Figure2D::*)(const AnalyticTraj<VectorType>&,const ColorMap&))&Figure2D::draw_trajectory,
147-
VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF,
148-
"x"_a, "cmap"_a)
142+
.def("draw_trajectory", [](Figure2D& fig, const py::object& x, const StyleProperties& s)
143+
{
144+
if(!is_instance<AnalyticTraj<VectorType>>(x)) {
145+
assert_release("draw_trajectory: invalid function type");
146+
}
147+
148+
fig.draw_trajectory(cast<AnalyticTraj<VectorType>>(x), s);
149+
},
150+
VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF,
151+
"x"_a, "s"_a=StyleProperties())
149152

150153
.def("draw_trajectory", (void(Figure2D::*)(const SampledTraj<Vector>&,const ColorMap&))&Figure2D::draw_trajectory,
151154
VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_COLORMAP_REF,
152155
"x"_a, "cmap"_a)
153156

157+
.def("draw_trajectory", [](Figure2D& fig, const py::object& x, const ColorMap& cmap)
158+
{
159+
if(!is_instance<AnalyticTraj<VectorType>>(x)) {
160+
assert_release("draw_trajectory: invalid function type");
161+
}
162+
163+
fig.draw_trajectory(cast<AnalyticTraj<VectorType>>(x), cmap);
164+
},
165+
VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF,
166+
"x"_a, "cmap"_a)
167+
154168
// Robots
155169

156170
.def("draw_tank", &Figure2D::draw_tank,
@@ -230,22 +244,36 @@ void export_Figure2D(py::module& m)
230244
STATIC_VOID_DEFAULTVIEW_DRAW_PIE_CONST_VECTOR_REF_CONST_INTERVAL_REF_CONST_INTERVAL_REF_CONST_STYLEPROPERTIES_REF,
231245
"c"_a, "r"_a, "theta"_a, "s"_a=StyleProperties())
232246

233-
.def_static("draw_trajectory", (void(*)(const AnalyticTraj<VectorType>&,const StyleProperties&))&DefaultView::draw_trajectory,
234-
STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF,
235-
"x"_a, "s"_a=StyleProperties())
236-
237247
.def_static("draw_trajectory", (void(*)(const SampledTraj<Vector>&,const StyleProperties&))&DefaultView::draw_trajectory,
238248
STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_STYLEPROPERTIES_REF,
239249
"x"_a, "s"_a=StyleProperties())
240250

241-
.def_static("draw_trajectory", (void(*)(const AnalyticTraj<VectorType>&,const ColorMap&))&DefaultView::draw_trajectory,
242-
STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF,
243-
"x"_a, "cmap"_a)
251+
.def_static("draw_trajectory", [](const py::object& x, const StyleProperties& s)
252+
{
253+
if(!is_instance<AnalyticTraj<VectorType>>(x)) {
254+
assert_release("draw_trajectory: invalid function type");
255+
}
256+
257+
DefaultView::draw_trajectory(cast<AnalyticTraj<VectorType>>(x), s);
258+
},
259+
STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF,
260+
"x"_a, "s"_a=StyleProperties())
244261

245262
.def_static("draw_trajectory", (void(*)(const SampledTraj<Vector>&,const ColorMap&))&DefaultView::draw_trajectory,
246263
STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_COLORMAP_REF,
247264
"x"_a, "cmap"_a)
248265

266+
.def_static("draw_trajectory", [](const py::object& x, const ColorMap& cmap)
267+
{
268+
if(!is_instance<AnalyticTraj<VectorType>>(x)) {
269+
assert_release("draw_trajectory: invalid function type");
270+
}
271+
272+
DefaultView::draw_trajectory(cast<AnalyticTraj<VectorType>>(x), cmap);
273+
},
274+
STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF,
275+
"x"_a, "cmap"_a)
276+
249277
// Robots
250278

251279
.def_static("draw_tank", &DefaultView::draw_tank,

src/core/paver/codac2_pave.cpp

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,20 @@ using namespace codac2;
1414

1515
namespace codac2
1616
{
17-
PavingOut pave(const IntervalVector& x, std::shared_ptr<const CtcBase<IntervalVector>> c, double eps)
17+
PavingOut pave(const IntervalVector& x, std::shared_ptr<const CtcBase<IntervalVector>> c, double eps, bool verbose)
1818
{
19-
return pave(x, *c, eps);
19+
return pave(x, *c, eps, verbose);
2020
}
2121

22-
PavingOut pave(const IntervalVector& x, const CtcBase<IntervalVector>& c, double eps)
22+
PavingOut pave(const IntervalVector& x, const CtcBase<IntervalVector>& c, double eps, bool verbose)
2323
{
2424
assert_release(eps > 0.);
2525
assert_release(!x.is_empty());
2626
assert_release(c.size() >= 2 && "cannot reveal 1d contractors");
2727

28+
clock_t t_start = clock();
29+
Index n_boundary = 0;
30+
2831
PavingOut p(x);
2932
// In order to be able to reconstruct the initial box, the first level represents the
3033
// initial domain x (the left node is x, the right one is an empty box).
@@ -42,28 +45,40 @@ namespace codac2
4245

4346
c.contract(get<0>(n->boxes()));
4447

45-
if(!get<0>(n->boxes()).is_empty() && get<0>(n->boxes()).max_diam() > eps)
48+
if(!get<0>(n->boxes()).is_empty())
4649
{
47-
n->bisect();
48-
l.push_back(n->left());
49-
l.push_back(n->right());
50+
if(get<0>(n->boxes()).max_diam() > eps)
51+
{
52+
n->bisect();
53+
l.push_back(n->left());
54+
l.push_back(n->right());
55+
}
56+
57+
else if(verbose)
58+
n_boundary++;
5059
}
51-
}
60+
}
5261

62+
if(verbose)
63+
printf("Computation time: %.4fs, %ld boxes\n",
64+
(double)(clock()-t_start)/CLOCKS_PER_SEC, n_boundary);
5365
return p;
5466
}
5567

56-
PavingInOut pave(const IntervalVector& x, std::shared_ptr<const SepBase> s, double eps)
68+
PavingInOut pave(const IntervalVector& x, std::shared_ptr<const SepBase> s, double eps, bool verbose)
5769
{
58-
return pave(x, *s, eps);
70+
return pave(x, *s, eps, verbose);
5971
}
6072

61-
PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps)
73+
PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps, bool verbose)
6274
{
6375
assert_release(eps > 0.);
6476
assert_release(!x.is_empty());
6577
assert_release(s.size() >= 2 && "cannot reveal 1d separators");
6678

79+
clock_t t_start = clock();
80+
Index n_boundary = 0;
81+
6782
PavingInOut p(x);
6883
std::shared_ptr<PavingInOut_Node> n;
6984
list<std::shared_ptr<PavingInOut_Node>> l { p.tree() };
@@ -77,14 +92,23 @@ namespace codac2
7792
auto boundary = (xs.inner & xs.outer);
7893
n->boxes() = { xs.outer, xs.inner };
7994

80-
if(!boundary.is_empty() && boundary.max_diam() > eps)
95+
if(!boundary.is_empty())
8196
{
82-
n->bisect();
83-
l.push_back(n->left());
84-
l.push_back(n->right());
97+
if(boundary.max_diam() > eps)
98+
{
99+
n->bisect();
100+
l.push_back(n->left());
101+
l.push_back(n->right());
102+
}
103+
104+
else
105+
n_boundary++;
85106
}
86107
}
87108

109+
if(verbose)
110+
printf("Computation time: %.4fs, %ld boundary boxes\n",
111+
(double)(clock()-t_start)/CLOCKS_PER_SEC, n_boundary);
88112
return p;
89113
}
90114
}

0 commit comments

Comments
 (0)