Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
lebarsfa committed Jan 14, 2024
2 parents 9d99334 + d7e18aa commit 4cbae00
Show file tree
Hide file tree
Showing 21 changed files with 261 additions and 53 deletions.
11 changes: 11 additions & 0 deletions doc/doc/_static/custom-sphinx.css
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,17 @@
}


/* Right alignment + gray color (for right-align notes) */

.right-aligned-note
{
margin-right: 10px;
display: block;
float: right;
color: gray;
}


/* */

.wy-table-responsive table td
Expand Down
2 changes: 2 additions & 0 deletions doc/doc/conf.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ breathe_projects = {
rst_prolog = """
.. role:: underline
:class: underline
.. role:: right-aligned-note
:class: right-aligned-note
"""

# GitHub repo
Expand Down
2 changes: 1 addition & 1 deletion doc/doc/dev/info_dev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ This configuration generates header files containing docstrings for Python, base
the content of XML files made by Doxygen. The documentation of any C++/Python function
is then located in the C++ header files of the :file:`/src` directory.

Note that you also have to configure IBEX with the ``-DCMAKE_CXX_FLAGS="-fPIC"`` flag.
Note that you also have to configure IBEX with the ``-DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC"`` flag.

Finally, after the compilation of Codac (and IBEX):

Expand Down
29 changes: 17 additions & 12 deletions doc/doc/tutorial/01-basics/index.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
.. _sec-tuto-01:

.. # define a hard line break for HTML
.. |br| raw:: html

<br />

Lesson A: Getting started with intervals and contractors
========================================================

Expand Down Expand Up @@ -169,21 +174,21 @@ Codac is using C++/Python objects to represent intervals and boxes [#f1]_:

For full details about ``Interval`` and ``IntervalVector`` objects, please read the :ref:`sec-manual-intervals` page of the user manual.


.. admonition:: Exercise

**A.1.** Let us consider two intervals :math:`[x]=[8,10]` and :math:`[y]=[1,2]`. Without coding the operation, what would be the result of :math:`[x]/[y]` (:math:`[x]` divided by :math:`[y]`)? Remember that the result of this interval-division is also an interval enclosing all feasible divisions.

**A.2.** In your new project, compute and print the following simple operations on intervals:
**A.2.** In your new project, compute and print the following simple operations on intervals: |br|
:right-aligned-note:`Solutions are given below` |br|

* :math:`[-2,4]\cdot[1,3]`
* :math:`[8,10]/[-1,0]`
* :math:`[-2,4]\sqcup[6,7]` with operator ``|``
* :math:`\max([2,7],[1,9])`
* :math:`\max(\varnothing,[1,2])`
* :math:`\cos([-\infty,\infty])`
* :math:`[-1,4]^2` with function ``sqr()``
* :math:`([1,2]\cdot[-1,3]) + \max([1,3]\cap[6,7],[1,2])`
* :math:`[-2,4]\cdot[1,3]` :right-aligned-note:`[-6,12]`
* :math:`[8,10]/[-1,0]` :right-aligned-note:`[-∞,-8]`
* :math:`[-2,4]\sqcup[6,7]` with operator ``|`` :right-aligned-note:`[-2,7]`
* :math:`\max([2,7],[1,9])` :right-aligned-note:`[2,9]`
* :math:`\max(\varnothing,[1,2])` :right-aligned-note:``
* :math:`\cos([-\infty,\infty])` :right-aligned-note:`[-1,1]`
* :math:`[-1,4]^2` with function ``sqr()`` :right-aligned-note:`[0,16]`
* :math:`([1,2]\cdot[-1,3]) + \max([1,6]\cap[5,7],[1,2])` :right-aligned-note:`[3,12]`

| Note that :math:`\sqcup` is the hull union (``|``), *i.e.*, :math:`[x]\sqcup[y] = [[x]\cup[y]]`.
| *For instance:* :math:`[-1,2]\sqcup[4,6]=[-1,6]`
Expand Down Expand Up @@ -299,11 +304,11 @@ The graphical tool `VIBes <http://enstabretagnerobotics.github.io/VIBES/>`_ has

| **A.6.** Before the ``.show()`` method, draw the boxes :math:`[\mathbf{x}]` and :math:`[\mathbf{b}]` with the ``fig.draw_box(..)`` method. The computed interval range :math:`[d]` can be displayed as a ring centered on :math:`\mathbf{x}=(0,0)`. The ring will contain the set of all positions that are :math:`d`-distant from :math:`\mathbf{x}=(0,0)`, with :math:`d\in[d]`.
To display each bound of the ring, you can use ``fig.draw_circle(x, y, rad)`` where ``x``, ``y``, ``rad`` are *double* values.
To display each bound of the ring, you can use ``fig.draw_circle(x, y, rad)`` where ``x``, ``y``, ``rad`` are real values.

.. hint::

To access *double* bounds of an interval object ``x``, you can use the ``x.lb()``/``x.ub()`` methods for lower and upper bounds.
To access real bounds of an ``Interval`` object ``x``, you can use the ``x.lb()``/``x.ub()`` methods for lower and upper bounds. This also works with ``IntervalVector``, returning vector items.

| **A.7.** Now, repeat the operation with :math:`[\mathbf{x}]=[-0.1,0.1]\times[-0.1,0.1]`. You can for instance use the ``.inflate(0.1)`` method on ``x``.
| Is the result reliable, according to the sets :math:`[\mathbf{x}]` and :math:`[\mathbf{b}]`? You may display the box :math:`([\mathbf{x}]+[\mathbf{b}])` to understand how the reliable interval distance is computed.
Expand Down
2 changes: 1 addition & 1 deletion examples/codac2/01/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

# Compilation

add_executable(${PROJECT_NAME} main_test_sample.cpp)
add_executable(${PROJECT_NAME} main.cpp)
target_compile_options(${PROJECT_NAME} PUBLIC ${CODAC_CXX_FLAGS})
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CODAC_INCLUDE_DIRS} ${EIGEN3_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex ${CODAC_LIBRARIES} Ibex::ibex)
20 changes: 10 additions & 10 deletions examples/codac2/01/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ using namespace codac;

int main()
{
codac2::TDomain tdomain(Interval(0,10), 0.01, true); // last argument creates "gates" (degenerated slices at scalar timesteps)
codac2::Tube<IntervalVector> x(2, tdomain,
auto tdomain = codac2::create_tdomain(Interval(0,10), 0.01, true); // last argument creates "gates" (degenerated slices at scalar timesteps)
codac2::Tube<IntervalVector> x(tdomain,
TFunction("(sin(sqrt(t)+((t-5)^2)*[-0.01,0.01]) ; cos(t)+sin(t/0.2)*[-0.1,0.1])"));
codac2::Tube<IntervalVector> u(2, tdomain);

TFunction tf("x[2]", "u[2]", "(sin(x[1]) ; -sin(x[0]))");
codac2::CtcDiffInclusion ctc_diffincl(tf);
ctc_diffincl.contract(x,u);
codac2::Tube<IntervalVector> u(tdomain);

// If you want to iterate each slice (including gates = degenerate slices)
for(auto& sx : x)
{
//cout << sx << endl;
}

vibes::beginDrawing();

codac::TubeVector x_codac1 = x.to_codac1(); // may take time
codac::Tube xi_codac1 = x[1].to_codac1(); // may take time
codac::TubeVector x_codac1 = codac2::to_codac1(x); // may take time

VIBesFigTube fig("Tube");
fig.set_properties(100, 100, 600, 300);
fig.add_tube(&xi_codac1, "x");
fig.add_tube(&x_codac1[1], "x");
fig.show(true);

vibes::endDrawing();
Expand Down
6 changes: 3 additions & 3 deletions examples/codac2/01/main_test_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ using namespace codac;
int main()
{
{
codac2::TDomain tdomain(Interval(0,10), 1., false);
codac2::Tube<IntervalVector> x(2, tdomain);
auto tdomain = codac2::create_tdomain(Interval(0,10), 1., false);
codac2::Tube<IntervalVector> x(tdomain, IntervalVector(2));

for(auto& sx : x)
{
if(sx.t0_tf().contains(5.2))
{
cout << "sample" << endl;
tdomain.sample(5.2);
tdomain->sample(5.2);
}
cout << sx << endl;
}
Expand Down
1 change: 1 addition & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
src/core/cn/codac_py_Variable.cpp

src/core/contractors/static/codac_py_Ctc.cpp
src/core/contractors/static/codac_py_Ctc3BCid.cpp
src/core/contractors/static/codac_py_CtcBox.cpp
src/core/contractors/static/codac_py_CtcCN.cpp
src/core/contractors/static/codac_py_CtcCartProd.cpp
Expand Down
56 changes: 56 additions & 0 deletions python/codac/tests/test_numpy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python

# Codac tests
# ---------------------------------------------------------------------------
# \date 2023
# \author Simon Rohou
# \copyright Copyright 2023 Codac Team
# \license This program is distributed under the terms of
# the GNU Lesser General Public License (LGPL).

import unittest
import numpy as np
from codac import *

class TestNumpyMatrices(unittest.TestCase):

def test_numpytocodac(self):

cdA=IntervalMatrix(2,6)
cdA[0][0]=Interval(1)
cdA[0][1]=Interval(3)
cdA[0][2]=Interval(5)
cdA[0][3]=Interval(7)
cdA[0][4]=Interval(9)
cdA[0][5]=Interval(11)
cdA[1][0]=Interval(2)
cdA[1][1]=Interval(4)
cdA[1][2]=Interval(6)
cdA[1][3]=Interval(8)
cdA[1][4]=Interval(10)
cdA[1][5]=Interval(12)

npA=np.array([[1.,3.,5.,7.,9.,11.],[2.,4.,6.,8.,10.,12.]])
self.assertEqual(IntervalMatrix(npA), cdA)

def test_numpytocodac_withtranspose(self):

cdA=IntervalMatrix(2,6)
cdA[0][0]=Interval(1)
cdA[0][1]=Interval(3)
cdA[0][2]=Interval(5)
cdA[0][3]=Interval(7)
cdA[0][4]=Interval(9)
cdA[0][5]=Interval(11)
cdA[1][0]=Interval(2)
cdA[1][1]=Interval(4)
cdA[1][2]=Interval(6)
cdA[1][3]=Interval(8)
cdA[1][4]=Interval(10)
cdA[1][5]=Interval(12)

npA=np.array([[1.,2.],[3.,4.],[5.,6.],[7.,8.],[9.,10.],[11.,12.]]).T
self.assertEqual(IntervalMatrix(npA), cdA)

if __name__ == '__main__':
unittest.main()
2 changes: 2 additions & 0 deletions python/codac_py_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void export_IntervalVar(py::module& m);
void export_IntervalVectorVar(py::module& m);

py::class_<Ctc,pyCtc> export_Ctc(py::module& m);
void export_Ctc3BCid(py::module& m, py::class_<Ctc, pyCtc>& ctc);
void export_CtcBox(py::module& m, py::class_<Ctc, pyCtc>& ctc);
void export_CtcCN(py::module& m, py::class_<Ctc, pyCtc>& ctc);
void export_CtcCartProd(py::module& m, py::class_<Ctc, pyCtc>& ctc);
Expand Down Expand Up @@ -100,6 +101,7 @@ PYBIND11_MODULE(core, m)
export_IntervalVectorVar(m);

py::class_<Ctc, pyCtc> ctc = export_Ctc(m);
export_Ctc3BCid(m, ctc);
export_CtcBox(m, ctc);
export_CtcCN(m, ctc);
export_CtcCartProd(m, ctc);
Expand Down
45 changes: 45 additions & 0 deletions python/src/core/contractors/static/codac_py_Ctc3BCid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* \file
* Ctc3BCid Python binding
* ----------------------------------------------------------------------------
* \date 2023
* \author Simon Rohou, Benoît Desrochers
* \copyright Copyright 2023 Codac Team
* \license This program is distributed under the terms of
* the GNU Lesser General Public License (LGPL).
*/

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/operators.h>
#include <pybind11/functional.h>
#include "codac_type_caster.h"

#include "codac_py_Ctc.h"
#include "codac_Ctc.h"
#include "ibex_Ctc3BCid.h"
// Generated file from Doxygen XML (doxygen2docstring.py):
//#include "codac_py_Ctc3BCid_docs.h"

using namespace std;
using namespace codac;
namespace py = pybind11;
using namespace pybind11::literals;


void export_Ctc3BCid(py::module& m, py::class_<Ctc, pyCtc>& ctc)
{
py::class_<ibex::Ctc3BCid> ctc_3bcid(m, "Ctc3BCid", ctc, "todo");
ctc_3bcid

.def(py::init<Ctc&,int,int,int,double>(),
py::keep_alive<1,2>(),
"ctc"_a.noconvert(),
"s3b"_a.noconvert()=ibex::Ctc3BCid::default_s3b,
"scid"_a.noconvert()=ibex::Ctc3BCid::default_scid,
"vhandled"_a.noconvert()=-1,
"var_min_width"_a.noconvert()=ibex::Ctc3BCid::default_var_min_width)

.def("contract", (void (Ctc::*) (IntervalVector&)) &ibex::Ctc3BCid::contract, "todo")
;
}
36 changes: 30 additions & 6 deletions python/src/core/domains/interval/codac_py_IntervalMatrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ string to_string(const IntervalMatrix& x)
return ss.str();
}

// Inspired by Numpy documentation
// See: https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html

#include "codac2_IntervalMatrix.h"
/* Bind MatrixXd (or some other Eigen type) to Python */
typedef Eigen::MatrixXd Matrix;

//typedef Eigen::Matrix::Scalar Scalar;
constexpr bool rowMajor = !true;//Eigen::Matrix::Flags & Eigen::RowMajorBit;

void export_IntervalMatrix(py::module& m)
{
py::class_<IntervalMatrix> interval_matrix(m, "IntervalMatrix");
Expand All @@ -79,20 +89,34 @@ void export_IntervalMatrix(py::module& m)
.def(py::init<const IntervalMatrix&>())
.def(py::init(&create_from_list))

.def(py::init([](py::buffer b) // create for instance an IntervalMatrix from a NumPy matrix
.def(py::init([](py::buffer b)
{
// Inspired by Numpy documentation
// See: https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html

// Note: use raw data does not work because of strides,
// see for instance transpose operations on numpy matrices

typedef Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic> Strides;

// Request a buffer descriptor from Python
py::buffer_info info = b.request();

// Some sanity checks...
// Some basic validation checks...
if(info.format != py::format_descriptor<double>::format())
throw std::runtime_error("Incompatible format: expected a double array");
throw std::runtime_error("Incompatible format: expected a double array!");

if(info.ndim != 2)
throw std::runtime_error("Incompatible buffer dimension");
throw std::runtime_error("Incompatible buffer dimension!");

auto strides = Strides(
info.strides[rowMajor ? 0 : 1] / (py::ssize_t)sizeof(double),
info.strides[rowMajor ? 1 : 0] / (py::ssize_t)sizeof(double));

auto map = Eigen::Map<Eigen::MatrixXd, 0, Strides>(
static_cast<double*>(info.ptr), info.shape[0], info.shape[1], strides);

ibex::Matrix m((int)info.shape[0], (int)info.shape[1], static_cast<double*>(info.ptr));
return IntervalMatrix(m);
return codac2::to_codac1(codac2::Matrix(map));
}))

.def("__getitem__", [](IntervalMatrix& s, size_t index) -> IntervalVector&
Expand Down
6 changes: 6 additions & 0 deletions python/src/core/graphics/codac_py_ColorMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,11 @@ void export_ColorMap(py::module& m)

.def("is_opaque", &ColorMap::is_opaque,
COLORMAP_BOOL_IS_OPAQUE)

.def_property_readonly_static("HAXBY", [](py::object) { return ColorMap::HAXBY; })
.def_property_readonly_static("DEFAULT", [](py::object) { return ColorMap::DEFAULT; })
.def_property_readonly_static("BLUE_TUBE", [](py::object) { return ColorMap::BLUE_TUBE; })
.def_property_readonly_static("RED_TUBE", [](py::object) { return ColorMap::RED_TUBE; })
.def_property_readonly_static("RAINBOW", [](py::object) { return ColorMap::RAINBOW; })
;
}
8 changes: 6 additions & 2 deletions src/core/2/actions/codac2_Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ namespace codac2
return (a > 0) ? 1 : ((a < 0) ? -1 : 0);
}

OctaSym::OctaSym(const std::vector<int>& s) : std::vector<int>(s)
OctaSym::OctaSym(const vector<int>& s) : vector<int>(s)
{
for(const auto& i : s)
{
assert((size_t)abs(i) > 0 && (size_t)abs(i) <= size());
}
}

OctaSym::OctaSym(initializer_list<int> s)
: OctaSym(vector<int>(s))
{ }

IntervalVector OctaSym::operator()(const IntervalVector& x) const
{
assert((size_t)x.size() == size());
Expand Down Expand Up @@ -64,7 +68,7 @@ namespace codac2
return s3;
}

std::ostream& operator<<(std::ostream& str, const OctaSym& s)
ostream& operator<<(ostream& str, const OctaSym& s)
{
str << "(";
for(size_t i = 0 ; i < s.size() ; i++)
Expand Down
1 change: 1 addition & 0 deletions src/core/2/actions/codac2_Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace codac2
{
public:

OctaSym(std::initializer_list<int> s);
OctaSym(const std::vector<int>& s);
CtcAction operator()(codac::Ctc& ctc) const;
codac::IntervalVector operator()(const codac::IntervalVector& x) const;
Expand Down
Loading

0 comments on commit 4cbae00

Please sign in to comment.