From 15fe23a98cc5189945c53c0aa49db4d287002b74 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 18 Sep 2024 14:16:35 +0200 Subject: [PATCH 001/126] [domains] introducing ellipsoids --- src/core/CMakeLists.txt | 2 + .../domains/ellipsoid/codac2_Ellipsoid.cpp | 187 ++++++++++++++++++ src/core/domains/ellipsoid/codac2_Ellipsoid.h | 34 ++++ 3 files changed, 223 insertions(+) create mode 100644 src/core/domains/ellipsoid/codac2_Ellipsoid.cpp create mode 100644 src/core/domains/ellipsoid/codac2_Ellipsoid.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 35a03d586..306ba2bdd 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -39,6 +39,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/domains/codac2_BoolInterval.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/codac2_Domain.h + ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval.cpp ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval_operations.cpp diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp new file mode 100644 index 000000000..536d5a97c --- /dev/null +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -0,0 +1,187 @@ +/** + * codac2_Ellipsoid.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include "codac2_Ellipsoid.h" +#include "codac2_assert.h" + +using namespace std; +using namespace codac2; + +namespace codac2 +{ + Ellipsoid::Ellipsoid(size_t n) + : mu(Vector(n)), Q(Matrix(n,n)) + { + assert_release(n > 0); + } + + Ellipsoid::Ellipsoid(const Vector& mu_, const Matrix& Q_) + : mu(mu_), Q(Q_) + { + assert_release(mu_.size() == Q_.nb_cols() && mu_.size() == Q_.nb_rows()); + } + + size_t Ellipsoid::size() const + { + return mu.size(); + } + + Ellipsoid operator+(const Ellipsoid& e1, const Ellipsoid& e2) + { + assert_release(e1.size() == e2.size()); + + //if(e1.is_unbounded() || e2.is_unbounded()) + // return Ellipsoid(e1.size()); + + //if(e1.is_empty() || e2.is_empty()) + // return Ellipsoid::empty(e1.size()); + + auto G1 = e1.Q._e*e1.Q._e.transpose(); + auto G2 = e2.Q._e*e2.Q._e.transpose(); + + double beta = std::sqrt(G1.trace()/G2.trace()); + return Ellipsoid( + e1.mu._e + e2.mu._e, + ((1.+(1./beta))*G1 + (1.+beta)*G2).sqrt() + ); + } + + // Old implementations: + + #if 0 + void draw_ellipse(const Ellipsoid& x, const std::string& color) + { + if(x.is_unbounded()) + cout << "Unbounded ellipse" << endl; + + else if(x.is_empty()) + cout << "Empty ellipse" << endl; + + else + { + Matrix Qmod = x.Q*x.Q.transpose(); + + Eigen::EigenSolver eig(Qmod); + Vector D_ = eig.eigenvalues().real().cwiseSqrt(); + const Matrix& V = eig.eigenvectors().real(); + + vector vx, vy; + + double dr = 0.2; + for(double t = -M_PI ; t < M_PI+dr ; t+=dr) + { + if(t > M_PI) t = M_PI; + Vector p = x.mu+V*Vector({std::cos(t),std::sin(t)}).cwiseProduct(D_); + vx.push_back(p[0]); vy.push_back(p[1]); + + /*if(!((Q.determinant() == 0 || // if Q is not invertible, no check + fabs(1. - (p-mu).transpose()*Q.inverse()*(p-mu)) < 1e-10))) + cout << Q.determinant() << " " << (p-mu).transpose()*Q.inverse()*(p-mu) << endl; + assert((Q.determinant() == 0 || // if Q is not invertible, no check + fabs(1. - (p-mu).transpose()*Q.inverse()*(p-mu)) < 1e-10) + && "the ellipse equation is not valid");*/ + } + + //vibes::drawPolygon(vx,vy,color); + //vibes::drawCircle(x.mu[0], x.mu[1], 0.005, "blue"); + } + } + + Ellipsoid update(const Ellipsoid& e1, const Vector& mu, const Matrix& Q_m, const Matrix_<1,2>& C) + { + if(e1.is_empty()) + return Ellipsoid::empty(e1.size()); + + if(e1.is_unbounded()) + return Ellipsoid::all_reals(); + + const Vector& mu_kp1 = e1.mu; + const Vector& mu_mkp1 = mu; + Matrix Q_kp1 = e1.Q*e1.Q.transpose(); + + Matrix Pp_m = C.transpose()*C*Q_m.inverse(); + + Matrix_<2,1> L_kp1 = Q_kp1*C.transpose()*((C*Q_kp1*C.transpose()+(C*Q_m*C.transpose())).inverse()); + Vector mu_kp1_tld = mu_kp1 + L_kp1*C*(mu_mkp1-mu_kp1); + + double xi_kp1 = 1. + (Q_kp1.pow(-.5)*(mu_kp1_tld-mu_kp1)).norm(); + double xi_mkp1 = 1. + (Pp_m.pow(.5)*(mu_kp1_tld-mu_mkp1)).norm(); + + Matrix Qp_kp1 = 4.*(2.*((std::pow(xi_kp1,2)*Q_kp1).inverse()+std::pow(xi_mkp1,-2)*Pp_m)).inverse(); + + return Ellipsoid(mu_kp1_tld, Qp_kp1); + } + + Ellipsoid Ellipsoid::operator&(const Ellipsoid& e2) const + { + assert_release(this->size() == e2.size()); + + const Ellipsoid& e1 = *this; + + if(e1.is_unbounded()) + return e2; + + if(e2.is_unbounded()) + return e1; + + if(e1.is_empty() || e2.is_empty()) + return Ellipsoid::empty(e1.size()); + + Matrix_<3,3> Q1_mu_inv, Q2_mu_inv; + + Q1_mu_inv.block<2,2>(0,0) = e1.Q.inverse(); + Q1_mu_inv.block<2,1>(0,2) = -e1.Q.inverse()*e1.mu; + Q1_mu_inv.block<1,2>(2,0) = -e1.mu.transpose()*e1.Q.inverse(); + Q1_mu_inv.block<1,1>(2,2) = e1.mu.transpose()*e1.Q.inverse()*e1.mu; + + Q2_mu_inv.block<2,2>(0,0) = e2.Q.inverse(); + Q2_mu_inv.block<2,1>(0,2) = -e2.Q.inverse()*e2.mu; + Q2_mu_inv.block<1,2>(2,0) = -e2.mu.transpose()*e2.Q.inverse(); + Q2_mu_inv.block<1,1>(2,2) = e2.mu.transpose()*e2.Q.inverse()*e2.mu; + + Vector mu_kf; + + if(sel == 1) + mu_kf = e1.mu; + else if(sel == 2) + mu_kf = e2.mu; + else + { + Matrix L_KF = e1.Q*(e1.Q+e2.Q).inverse(); + mu_kf = e1.mu + L_KF*(e2.mu-e1.mu); + } + + Matrix_<3,3> PD_inv = (2.*(Q1_mu_inv+Q2_mu_inv)); + + Matrix Q_n = PD_inv.block<2,2>(0,0).inverse(); + Matrix_<2,1> mu_n = -Q_n*PD_inv.block<2,1>(0,2); + + double P_22_inv = PD_inv(2,2); + double scal = (1.+mu_n.transpose()*Q_n.inverse()*mu_n-P_22_inv); + Q_n /= fabs(scal); + + Eigen::ColPivHouseholderQR dec1(e1.Q.sqrt()); + Vector yy1 = dec1.solve(mu_kf-e1.mu); + + Eigen::ColPivHouseholderQR dec2(e2.Q.sqrt()); + Vector yy2 = dec2.solve(mu_kf-e2.mu); + + Matrix Qa1 = std::pow(1. + yy1.norm(), 2)*e1.Q; + Matrix Qa2 = std::pow(1. + yy2.norm(), 2)*e2.Q; + + return Ellipsoid( + mu_kf, + 4.*(2.*(Qa1.inverse()+Qa2.inverse())).inverse() + ); + + return *this; + } + #endif +} \ No newline at end of file diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h new file mode 100644 index 000000000..f8d0ed01e --- /dev/null +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -0,0 +1,34 @@ +/** + * \file codac2_Ellipsoid.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_Matrix.h" +#include "codac2_Vector.h" + +namespace codac2 +{ + class Ellipsoid + { + public: + + Ellipsoid(size_t n); + Ellipsoid(const Vector& mu_, const Matrix& Q_); + + size_t size() const; + + public: + + Vector mu; + Matrix Q; + }; + + + Ellipsoid operator+(const Ellipsoid& e1, const Ellipsoid& e2); +} \ No newline at end of file From 7147cf26f7caacabf318664827a6c535c9fd41d1 Mon Sep 17 00:00:00 2001 From: MLouedec Date: Fri, 27 Sep 2024 10:56:36 +0200 Subject: [PATCH 002/126] new ellipsoidal function, not working yet --- examples/ellipsoid_example/CMakeLists.txt | 44 ++ examples/ellipsoid_example/main.cpp | 28 ++ .../domains/ellipsoid/codac2_Ellipsoid.cpp | 384 +++++++++++------- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 40 +- 4 files changed, 345 insertions(+), 151 deletions(-) create mode 100644 examples/ellipsoid_example/CMakeLists.txt create mode 100644 examples/ellipsoid_example/main.cpp diff --git a/examples/ellipsoid_example/CMakeLists.txt b/examples/ellipsoid_example/CMakeLists.txt new file mode 100644 index 000000000..0f71d4b97 --- /dev/null +++ b/examples/ellipsoid_example/CMakeLists.txt @@ -0,0 +1,44 @@ +# ================================================================== +# codac / ellipsoid example - cmake configuration file +# ================================================================== + + cmake_minimum_required(VERSION 3.0.2) + project(codac_example LANGUAGES CXX) + + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Adding IBEX + + # In case you installed IBEX in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option. + # set(CMAKE_PREFIX_PATH "~/ibex-lib/build_install") + + find_package(IBEX REQUIRED) + ibex_init_common() # IBEX should have installed this function + message(STATUS "Found IBEX version ${IBEX_VERSION}") + +# Adding Eigen3 + + # In case you installed Eigen3 in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option, e.g. + # set(CMAKE_PREFIX_PATH "~/eigen/build_install") + + find_package(Eigen3 3.4 REQUIRED NO_MODULE) + message(STATUS "Found Eigen3 version ${Eigen3_VERSION}") + +# Adding Codac + + # In case you installed Codac in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option. + set(CMAKE_PREFIX_PATH "~/Documents/Code_these/codac/build_install") + + find_package(CODAC REQUIRED) + message(STATUS "Found Codac version ${CODAC_VERSION}") + +# Compilation + + 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}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex Eigen3::Eigen) diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp new file mode 100644 index 000000000..10687a749 --- /dev/null +++ b/examples/ellipsoid_example/main.cpp @@ -0,0 +1,28 @@ +#include + +using namespace std; +using namespace codac2; + +int main() +{ + Vector mu({1.3,2.7}); + Matrix G({{2.3,0.5},{0.5,1.7}}); + Ellipsoid e1(mu, G); + + Matrix A({{0.,0.5},{-0.5,0.9}}); + Vector b({1.3,2.1}); + + Ellipsoid e2 = linear_mapping(e1, A, b); + + cout << "Linear Mapping" << endl; + cout << "Initial ellipsoid e1:" << endl; + cout << e1 << endl; + + cout << "Image ellipsoid e2:" << endl; + cout << e2 << endl; + + cout << "non Linear Mapping" << endl; + AnalyticFunction h { + {x,y}, vec(x[0]+0.5*sin(x[1]),-0.5*sin(x[0])+0.9)}; + Ellipsoid e3 = nonlinear_mapping(e1, f); +} diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 536d5a97c..602e9de0e 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -9,179 +9,283 @@ #include #include "codac2_Ellipsoid.h" -#include "codac2_assert.h" +#include "codac2_template_tools.h" using namespace std; using namespace codac2; -namespace codac2 -{ - Ellipsoid::Ellipsoid(size_t n) - : mu(Vector(n)), Q(Matrix(n,n)) - { - assert_release(n > 0); - } - - Ellipsoid::Ellipsoid(const Vector& mu_, const Matrix& Q_) - : mu(mu_), Q(Q_) - { - assert_release(mu_.size() == Q_.nb_cols() && mu_.size() == Q_.nb_rows()); - } - - size_t Ellipsoid::size() const - { - return mu.size(); - } - - Ellipsoid operator+(const Ellipsoid& e1, const Ellipsoid& e2) - { - assert_release(e1.size() == e2.size()); - - //if(e1.is_unbounded() || e2.is_unbounded()) - // return Ellipsoid(e1.size()); - - //if(e1.is_empty() || e2.is_empty()) - // return Ellipsoid::empty(e1.size()); - - auto G1 = e1.Q._e*e1.Q._e.transpose(); - auto G2 = e2.Q._e*e2.Q._e.transpose(); - - double beta = std::sqrt(G1.trace()/G2.trace()); - return Ellipsoid( - e1.mu._e + e2.mu._e, - ((1.+(1./beta))*G1 + (1.+beta)*G2).sqrt() - ); - } - - // Old implementations: - - #if 0 - void draw_ellipse(const Ellipsoid& x, const std::string& color) - { - if(x.is_unbounded()) - cout << "Unbounded ellipse" << endl; - - else if(x.is_empty()) - cout << "Empty ellipse" << endl; - - else - { - Matrix Qmod = x.Q*x.Q.transpose(); +namespace codac2 { + Ellipsoid::Ellipsoid(size_t n) + : mu(Vector(n)), G(Matrix(n, n)) { + assert_release(n > 0); + } - Eigen::EigenSolver eig(Qmod); - Vector D_ = eig.eigenvalues().real().cwiseSqrt(); - const Matrix& V = eig.eigenvectors().real(); + Ellipsoid::Ellipsoid(const Vector &mu_, const Matrix &G_) + : mu(mu_), G(G_) { + assert_release(mu_.size() == G_.nb_cols() && mu_.size() == G_.nb_rows()); + } - vector vx, vy; + size_t Ellipsoid::size() const { + return mu.size(); + } - double dr = 0.2; - for(double t = -M_PI ; t < M_PI+dr ; t+=dr) - { - if(t > M_PI) t = M_PI; - Vector p = x.mu+V*Vector({std::cos(t),std::sin(t)}).cwiseProduct(D_); - vx.push_back(p[0]); vy.push_back(p[1]); - - /*if(!((Q.determinant() == 0 || // if Q is not invertible, no check - fabs(1. - (p-mu).transpose()*Q.inverse()*(p-mu)) < 1e-10))) - cout << Q.determinant() << " " << (p-mu).transpose()*Q.inverse()*(p-mu) << endl; - assert((Q.determinant() == 0 || // if Q is not invertible, no check - fabs(1. - (p-mu).transpose()*Q.inverse()*(p-mu)) < 1e-10) - && "the ellipse equation is not valid");*/ - } + Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2) { + assert_release(e1.size() == e2.size()); - //vibes::drawPolygon(vx,vy,color); - //vibes::drawCircle(x.mu[0], x.mu[1], 0.005, "blue"); + //if(e1.is_unbounded() || e2.is_unbounded()) + // return Ellipsoid(e1.size()); + + //if(e1.is_empty() || e2.is_empty()) + // return Ellipsoid::empty(e1.size()); + + auto Q1 = e1.G._e * e1.G._e.transpose(); + auto Q2 = e2.G._e * e2.G._e.transpose(); + + double beta = std::sqrt(Q1.trace() / Q2.trace()); + return Ellipsoid( + e1.mu._e + e2.mu._e, + ((1. + (1. / beta)) * Q1 + (1. + beta) * Q2).sqrt() + ); } - } - Ellipsoid update(const Ellipsoid& e1, const Vector& mu, const Matrix& Q_m, const Matrix_<1,2>& C) - { - if(e1.is_empty()) - return Ellipsoid::empty(e1.size()); + Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b) { + // compute A*e+b + Vector mu_res = A._e * e.mu._e + b._e; + Matrix G_res = A._e * e.G._e; + Ellipsoid res(mu_res, G_res); + return res; + } - if(e1.is_unbounded()) - return Ellipsoid::all_reals(); + Ellipsoid linear_mapping_guaranteed(const Ellipsoid &e, const Matrix &A, const Vector &b) { + // TODO à refaire avec la méthode d'andreas + // compute A*e+b considering rounding error + Ellipsoid e_ = linear_mapping(e, A, b); + + // compute rounding error as a small box + IntervalVector mu_(e.mu); + IntervalMatrix G_(e.G); + IntervalMatrix A_(A); + IntervalVector b_(b); + IntervalVector mu_res_ = A_ * mu_ + b_; // TODO multiplication IntervalMatrix*IntervalVector + IntervalMatrix G_res_ = A_ * G_; + IntervalVector unit_box_(mu_.size(), Interval(-1, 1)); + IntervalMatrix error_box_ = mu_res_ - mu_res_ + (A_ * G_ - G_res_) * unit_box_; + + // compute the max radius of error_box + double rho = error_box_.norm_2().upper(); // TODO norm 2 d'une boite + + Ellipsoid elli_error(mu_res_, Eigen::Identity(mu_.size()) * rho); // = rho*unit_ball + return e_ + elli_error; + } - const Vector& mu_kp1 = e1.mu; - const Vector& mu_mkp1 = mu; - Matrix Q_kp1 = e1.Q*e1.Q.transpose(); + Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box) { + Matrix E_out = J * G; + IntervalMatrix JE = IntervalMatrix(E_out); + IntervalMatrix JE_inv = JE.inverse(); // TODO inverse of interval matrix + // TODO this is the rigorous version, but one could compute JE_inv = E_out.inv() - Matrix Pp_m = C.transpose()*C*Q_m.inverse(); + // compute b_box + IntervalVector unit_box(G.nb_rows(), Interval(-1, 1)); + IntervalMatrix I_ = IntervalMatrix(Eigen::Identity(e.size())); + IntervalVector b_box = (JE_inv * J_box * IntervalMatrix(e.G) - I_) * unit_box; - Matrix_<2,1> L_kp1 = Q_kp1*C.transpose()*((C*Q_kp1*C.transpose()+(C*Q_m*C.transpose())).inverse()); - Vector mu_kp1_tld = mu_kp1 + L_kp1*C*(mu_mkp1-mu_kp1); + // get max radius of b_box + double rho = b_box.norm_2().upper(); // TODO norm 2 d'une boite + return (1 + rho) * E_out; + } - double xi_kp1 = 1. + (Q_kp1.pow(-.5)*(mu_kp1_tld-mu_kp1)).norm(); - double xi_mkp1 = 1. + (Pp_m.pow(.5)*(mu_kp1_tld-mu_mkp1)).norm(); + Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction::Domain>& f) { + // compute the image of the center + Vector mu_res = f.centered_eval(e.mu); - Matrix Qp_kp1 = 4.*(2.*((std::pow(xi_kp1,2)*Q_kp1).inverse()+std::pow(xi_mkp1,-2)*Pp_m)).inverse(); + // compute the Jacobian of f at the center + Matrix J = f.diff(e.mu); - return Ellipsoid(mu_kp1_tld, Qp_kp1); - } + // compute the Jacoiban of f over a box enclosing the ellipsoid + IntervalVector enclosing_box = enclose_elli_by_box(e); // TODO import this function - Ellipsoid Ellipsoid::operator&(const Ellipsoid& e2) const - { - assert_release(this->size() == e2.size()); + IntervalMatrix J_box = f.diff(enclosing_box); - const Ellipsoid& e1 = *this; + Matrix E_out = nonlinear_mapping_base(e.G, J, J_box); + return Ellipsoid(mu_res, E_out); + } + + std::ostream &operator<<(std::ostream &os, const Ellipsoid &e) { + return os << "mu : " << e.mu << "\n" << "G :\n" << e.G; + } - if(e1.is_unbounded()) - return e2; + bool stability_analysis(const AnalyticFunction::Domain> &f, int alpha_max) + { + // get the Jacobian of f at the origin + Vector origin(Eigen::zeros(f.domain().size())); + Matrix J = f.diff(origin); + + // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J + Matrix P; //TODO + Matrix G0 = sqrt(P.inv()); + int alpha = 0; + bool res = false; + + while alpha < alpha_max + { + Ellipsoid e(origin,pow(10,-alpha) * G0); + Ellipsoid e_out = nonlinear_mapping(e,f); + + res = inclusion_test(e,e_out); + if(res) + { + cout << "The system is stable" << endl; + cout << "Domain of attraction :\n" << e_out << endl; + return true; + } + alpha++; + } + cout << "The method is not able to conclude on the stability" << endl; + return false; + } - if(e2.is_unbounded()) - return e1; - - if(e1.is_empty() || e2.is_empty()) - return Ellipsoid::empty(e1.size()); + bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2){ + // check if e1 included in e2 - Matrix_<3,3> Q1_mu_inv, Q2_mu_inv; + // Identity matrix with the same size as Y + IntervalMatrix I(Eigen::Idendity(e2.G.nb_rows())); + IntervalMatrix G2_inv = e2.G.inverse(); // TODO pas garantie + IntervalVector D = I - e1.G.transpose()*G2_inv.transpose()*G2_inv*e1.G; - Q1_mu_inv.block<2,2>(0,0) = e1.Q.inverse(); - Q1_mu_inv.block<2,1>(0,2) = -e1.Q.inverse()*e1.mu; - Q1_mu_inv.block<1,2>(2,0) = -e1.mu.transpose()*e1.Q.inverse(); - Q1_mu_inv.block<1,1>(2,2) = e1.mu.transpose()*e1.Q.inverse()*e1.mu; - - Q2_mu_inv.block<2,2>(0,0) = e2.Q.inverse(); - Q2_mu_inv.block<2,1>(0,2) = -e2.Q.inverse()*e2.mu; - Q2_mu_inv.block<1,2>(2,0) = -e2.mu.transpose()*e2.Q.inverse(); - Q2_mu_inv.block<1,1>(2,2) = e2.mu.transpose()*e2.Q.inverse()*e2.mu; + // cholesky decomposition of D + //TODO - Vector mu_kf; + return res; + } + // Old implementations: + +#if 0 + void draw_ellipse(const Ellipsoid& x, const std::string& color) + { + if(x.is_unbounded()) + cout << "Unbounded ellipse" << endl; + + else if(x.is_empty()) + cout << "Empty ellipse" << endl; + + else + { + Matrix Qmod = x.Q*x.Q.transpose(); + + Eigen::EigenSolver eig(Qmod); + Vector D_ = eig.eigenvalues().real().cwiseSqrt(); + const Matrix& V = eig.eigenvectors().real(); + + vector vx, vy; + + double dr = 0.2; + for(double t = -M_PI ; t < M_PI+dr ; t+=dr) + { + if(t > M_PI) t = M_PI; + Vector p = x.mu+V*Vector({std::cos(t),std::sin(t)}).cwiseProduct(D_); + vx.push_back(p[0]); vy.push_back(p[1]); + + /*if(!((Q.determinant() == 0 || // if Q is not invertible, no check + fabs(1. - (p-mu).transpose()*Q.inverse()*(p-mu)) < 1e-10))) + cout << Q.determinant() << " " << (p-mu).transpose()*Q.inverse()*(p-mu) << endl; + assert((Q.determinant() == 0 || // if Q is not invertible, no check + fabs(1. - (p-mu).transpose()*Q.inverse()*(p-mu)) < 1e-10) + && "the ellipse equation is not valid");*/ + } + + //vibes::drawPolygon(vx,vy,color); + //vibes::drawCircle(x.mu[0], x.mu[1], 0.005, "blue"); + } + } - if(sel == 1) - mu_kf = e1.mu; - else if(sel == 2) - mu_kf = e2.mu; - else + Ellipsoid update(const Ellipsoid& e1, const Vector& mu, const Matrix& Q_m, const Matrix_<1,2>& C) { - Matrix L_KF = e1.Q*(e1.Q+e2.Q).inverse(); - mu_kf = e1.mu + L_KF*(e2.mu-e1.mu); + if(e1.is_empty()) + return Ellipsoid::empty(e1.size()); + + if(e1.is_unbounded()) + return Ellipsoid::all_reals(); + + const Vector& mu_kp1 = e1.mu; + const Vector& mu_mkp1 = mu; + Matrix Q_kp1 = e1.Q*e1.Q.transpose(); + + Matrix Pp_m = C.transpose()*C*Q_m.inverse(); + + Matrix_<2,1> L_kp1 = Q_kp1*C.transpose()*((C*Q_kp1*C.transpose()+(C*Q_m*C.transpose())).inverse()); + Vector mu_kp1_tld = mu_kp1 + L_kp1*C*(mu_mkp1-mu_kp1); + + double xi_kp1 = 1. + (Q_kp1.pow(-.5)*(mu_kp1_tld-mu_kp1)).norm(); + double xi_mkp1 = 1. + (Pp_m.pow(.5)*(mu_kp1_tld-mu_mkp1)).norm(); + + Matrix Qp_kp1 = 4.*(2.*((std::pow(xi_kp1,2)*Q_kp1).inverse()+std::pow(xi_mkp1,-2)*Pp_m)).inverse(); + + return Ellipsoid(mu_kp1_tld, Qp_kp1); } - Matrix_<3,3> PD_inv = (2.*(Q1_mu_inv+Q2_mu_inv)); + Ellipsoid Ellipsoid::operator&(const Ellipsoid& e2) const + { + assert_release(this->size() == e2.size()); + + const Ellipsoid& e1 = *this; + + if(e1.is_unbounded()) + return e2; - Matrix Q_n = PD_inv.block<2,2>(0,0).inverse(); - Matrix_<2,1> mu_n = -Q_n*PD_inv.block<2,1>(0,2); + if(e2.is_unbounded()) + return e1; - double P_22_inv = PD_inv(2,2); - double scal = (1.+mu_n.transpose()*Q_n.inverse()*mu_n-P_22_inv); - Q_n /= fabs(scal); + if(e1.is_empty() || e2.is_empty()) + return Ellipsoid::empty(e1.size()); - Eigen::ColPivHouseholderQR dec1(e1.Q.sqrt()); - Vector yy1 = dec1.solve(mu_kf-e1.mu); + Matrix_<3,3> Q1_mu_inv, Q2_mu_inv; - Eigen::ColPivHouseholderQR dec2(e2.Q.sqrt()); - Vector yy2 = dec2.solve(mu_kf-e2.mu); + Q1_mu_inv.block<2,2>(0,0) = e1.Q.inverse(); + Q1_mu_inv.block<2,1>(0,2) = -e1.Q.inverse()*e1.mu; + Q1_mu_inv.block<1,2>(2,0) = -e1.mu.transpose()*e1.Q.inverse(); + Q1_mu_inv.block<1,1>(2,2) = e1.mu.transpose()*e1.Q.inverse()*e1.mu; - Matrix Qa1 = std::pow(1. + yy1.norm(), 2)*e1.Q; - Matrix Qa2 = std::pow(1. + yy2.norm(), 2)*e2.Q; + Q2_mu_inv.block<2,2>(0,0) = e2.Q.inverse(); + Q2_mu_inv.block<2,1>(0,2) = -e2.Q.inverse()*e2.mu; + Q2_mu_inv.block<1,2>(2,0) = -e2.mu.transpose()*e2.Q.inverse(); + Q2_mu_inv.block<1,1>(2,2) = e2.mu.transpose()*e2.Q.inverse()*e2.mu; - return Ellipsoid( - mu_kf, - 4.*(2.*(Qa1.inverse()+Qa2.inverse())).inverse() - ); + Vector mu_kf; - return *this; - } - #endif + if(sel == 1) + mu_kf = e1.mu; + else if(sel == 2) + mu_kf = e2.mu; + else + { + Matrix L_KF = e1.Q*(e1.Q+e2.Q).inverse(); + mu_kf = e1.mu + L_KF*(e2.mu-e1.mu); + } + + Matrix_<3,3> PD_inv = (2.*(Q1_mu_inv+Q2_mu_inv)); + + Matrix Q_n = PD_inv.block<2,2>(0,0).inverse(); + Matrix_<2,1> mu_n = -Q_n*PD_inv.block<2,1>(0,2); + + double P_22_inv = PD_inv(2,2); + double scal = (1.+mu_n.transpose()*Q_n.inverse()*mu_n-P_22_inv); + Q_n /= fabs(scal); + + Eigen::ColPivHouseholderQR dec1(e1.Q.sqrt()); + Vector yy1 = dec1.solve(mu_kf-e1.mu); + + Eigen::ColPivHouseholderQR dec2(e2.Q.sqrt()); + Vector yy2 = dec2.solve(mu_kf-e2.mu); + + Matrix Qa1 = std::pow(1. + yy1.norm(), 2)*e1.Q; + Matrix Qa2 = std::pow(1. + yy2.norm(), 2)*e2.Q; + + return Ellipsoid( + mu_kf, + 4.*(2.*(Qa1.inverse()+Qa2.inverse())).inverse() + ); + + return *this; + } +#endif } \ No newline at end of file diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index f8d0ed01e..cbe481385 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -11,24 +11,42 @@ #include "codac2_Matrix.h" #include "codac2_Vector.h" +#include "codac2_AnalyticFunction.h" -namespace codac2 -{ - class Ellipsoid - { +namespace codac2 { + class Ellipsoid { public: - Ellipsoid(size_t n); - Ellipsoid(const Vector& mu_, const Matrix& Q_); + Ellipsoid(size_t n); - size_t size() const; + Ellipsoid(const Vector &mu_, const Matrix &G_); + + size_t size() const; public: - Vector mu; - Matrix Q; - }; + Vector mu; + Matrix G; + }; + + + Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2); + + Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b); + + Ellipsoid linear_mapping_guaranteed(const Ellipsoid &e, const Matrix &A, const Vector &b); + + Ellipsoid nonlinear_mapping_base(const Ellipsoid &e, const Matrix &J, const IntervalMatrix &J_box); + + template + requires std::is_base_of_v + Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction::Domain> &f); + + std::ostream &operator<<(std::ostream &os, const Ellipsoid &e); + template + requires std::is_base_of_v + bool stability_analysis(const AnalyticFunction::Domain> &f, int alpha_max); - Ellipsoid operator+(const Ellipsoid& e1, const Ellipsoid& e2); + bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); } \ No newline at end of file From 59a270444b0d0cea484e7e3aa92899c43b11cba5 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 27 Sep 2024 13:08:30 +0200 Subject: [PATCH 003/126] [fig] preparing draw_ellipsoid... --- src/core/CMakeLists.txt | 1 + src/graphics/3rd/ipe/codac2_Figure2D_IPE.h | 1 + src/graphics/figures/codac2_Figure2D.cpp | 17 +++++++++++++++++ src/graphics/figures/codac2_Figure2D.h | 7 +++++++ src/graphics/figures/codac2_Figure2DInterface.h | 1 + 5 files changed, 27 insertions(+) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 306ba2bdd..91ea29986 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -148,6 +148,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/actions ${CMAKE_CURRENT_SOURCE_DIR}/contractors ${CMAKE_CURRENT_SOURCE_DIR}/domains + ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval ${CMAKE_CURRENT_SOURCE_DIR}/domains/paving ${CMAKE_CURRENT_SOURCE_DIR}/functions diff --git a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h index a882a3d98..3b6e1a3a7 100644 --- a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h +++ b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.h @@ -15,6 +15,7 @@ #include "codac2_OutputFigure2D.h" #include "codac2_Vector.h" #include "codac2_IntervalVector.h" +#include "codac2_Ellipsoid.h" #include "vibes.h" namespace codac2 diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 0469ce4c9..ea22a85f3 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -191,6 +191,23 @@ void Figure2D::draw_ellipse(const Vector& c, const Vector& ab, double theta, con output_fig->draw_ellipse(c,ab,theta,s); } +void Figure2D::draw_ellipsoid(const Ellipsoid& e, const StyleProperties& s) +{ + assert_release(this->size() <= e.size()); + + // <===== ici, définir le code de projection d'ellipsoide en 2d + + // La figure 2d est définie comme une projection d'un espace de grande dimension, + // les dimensions de la figure sont données par: + // output_fig->i() // (dimension 1) + // output_fig->j() // (dimension 2) + + // ... + + //for(const auto& output_fig : _output_figures) + // output_fig->draw_ellipse( ... ,s); // utiliser draw_ellipse à la place, une fois les paramètres estimés +} + void Figure2D::draw_tank(const Vector& x, float size, const StyleProperties& s) { assert_release(this->size() <= x.size()+1); diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index da7b28cf9..03671bd72 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -88,6 +88,7 @@ namespace codac2 void draw_polygone(const std::vector& x, const StyleProperties& s = StyleProperties()); void draw_pie(const Vector& c, const Interval& r, const Interval& theta, const StyleProperties& s = StyleProperties()); void draw_ellipse(const Vector& c, const Vector& ab, double theta, const StyleProperties& s = StyleProperties()); + void draw_ellipsoid(const Ellipsoid& e, const StyleProperties& s = StyleProperties()); // Robots void draw_tank(const Vector& x, float size, const StyleProperties& s = StyleProperties()); @@ -203,6 +204,12 @@ namespace codac2 selected_fig()->draw_ellipse(c,ab,theta,s); } + static void draw_ellipsoid(const Ellipsoid& e, const StyleProperties& s = StyleProperties()) + { + auto_init(); + selected_fig()->draw_ellipsoid(e,s); + } + // Robots static void draw_tank(const Vector& x, float size, const StyleProperties& s = StyleProperties()) diff --git a/src/graphics/figures/codac2_Figure2DInterface.h b/src/graphics/figures/codac2_Figure2DInterface.h index 52132435a..996d37c49 100644 --- a/src/graphics/figures/codac2_Figure2DInterface.h +++ b/src/graphics/figures/codac2_Figure2DInterface.h @@ -14,6 +14,7 @@ #include "codac2_Vector.h" #include "codac2_IntervalVector.h" #include "codac2_StyleProperties.h" +#include "codac2_Ellipsoid.h" namespace codac2 { From 1d19e4170650e28cf738c6fc94c86b160bc936c0 Mon Sep 17 00:00:00 2001 From: MLouedec Date: Fri, 27 Sep 2024 13:23:39 +0200 Subject: [PATCH 004/126] still working on the ellipsoid functions --- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 71 +++++++++++-------- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 14 ++-- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 602e9de0e..0ebac3d45 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -57,49 +57,48 @@ namespace codac2 { } Ellipsoid linear_mapping_guaranteed(const Ellipsoid &e, const Matrix &A, const Vector &b) { - // TODO à refaire avec la méthode d'andreas // compute A*e+b considering rounding error - Ellipsoid e_ = linear_mapping(e, A, b); + Ellipsoid e_res = linear_mapping(e, A, b); // compute rounding error as a small box IntervalVector mu_(e.mu); IntervalMatrix G_(e.G); IntervalMatrix A_(A); IntervalVector b_(b); - IntervalVector mu_res_ = A_ * mu_ + b_; // TODO multiplication IntervalMatrix*IntervalVector - IntervalMatrix G_res_ = A_ * G_; + IntervalVector mu_res_(A_._e * mu_._e + b_._e); // TODO multiplication IntervalMatrix*IntervalVector IntervalVector unit_box_(mu_.size(), Interval(-1, 1)); - IntervalMatrix error_box_ = mu_res_ - mu_res_ + (A_ * G_ - G_res_) * unit_box_; + IntervalMatrix error_box_ = mu_res_ - IntervalVector(e_res.mu._e) + + (A_ * G_ - IntervalMatrix(e_res.G._e)) * unit_box_; // compute the max radius of error_box - double rho = error_box_.norm_2().upper(); // TODO norm 2 d'une boite - - Ellipsoid elli_error(mu_res_, Eigen::Identity(mu_.size()) * rho); // = rho*unit_ball - return e_ + elli_error; + double rho = Interval(error_box_._e.norm()).ub(); // TODO norm 2 d'une boite + Ellipsoid elli_error(e.mu, Eigen::MatrixXd::Identity(e.size(),e.size()) * rho); // = rho*unit_ball + return e_res + elli_error; } Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box) { Matrix E_out = J * G; IntervalMatrix JE = IntervalMatrix(E_out); - IntervalMatrix JE_inv = JE.inverse(); // TODO inverse of interval matrix + IntervalMatrix JE_inv = JE._e.inverse(); // TODO inverse of interval matrix // TODO this is the rigorous version, but one could compute JE_inv = E_out.inv() // compute b_box IntervalVector unit_box(G.nb_rows(), Interval(-1, 1)); - IntervalMatrix I_ = IntervalMatrix(Eigen::Identity(e.size())); - IntervalVector b_box = (JE_inv * J_box * IntervalMatrix(e.G) - I_) * unit_box; + IntervalMatrix I_ = IntervalMatrix(Eigen::MatrixXd::Identity(G.nb_rows(),G.nb_cols())); + IntervalVector b_box = (JE_inv * J_box * IntervalMatrix(G) - I_) * unit_box; // get max radius of b_box - double rho = b_box.norm_2().upper(); // TODO norm 2 d'une boite +// double rho = b_box.norm_2().upper(); // TODO norm 2 d'une boite + double rho = Interval(b_box._e.norm()).ub(); return (1 + rho) * E_out; } - Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction::Domain>& f) { + Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f) { // compute the image of the center - Vector mu_res = f.centered_eval(e.mu); + Vector mu_res = f.eval(e.mu).mid(); // compute the Jacobian of f at the center - Matrix J = f.diff(e.mu); + Matrix J = f.diff(e.mu).mid(); // compute the Jacoiban of f over a box enclosing the ellipsoid IntervalVector enclosing_box = enclose_elli_by_box(e); // TODO import this function @@ -114,21 +113,22 @@ namespace codac2 { return os << "mu : " << e.mu << "\n" << "G :\n" << e.G; } - bool stability_analysis(const AnalyticFunction::Domain> &f, int alpha_max) + bool stability_analysis(const AnalyticFunction &f, int alpha_max) { // get the Jacobian of f at the origin - Vector origin(Eigen::zeros(f.domain().size())); - Matrix J = f.diff(origin); + int n = f.args().size(); + IntervalVector origin(Eigen::MatrixXd::Zero(n,n)); + IntervalMatrix J = f.diff(IntervalVector(origin)); // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J - Matrix P; //TODO - Matrix G0 = sqrt(P.inv()); + IntervalMatrix P(n,n); //TODO + IntervalMatrix G0 = (P._e.inverse()).sqrt(); int alpha = 0; bool res = false; - while alpha < alpha_max + while(alpha <= alpha_max) { - Ellipsoid e(origin,pow(10,-alpha) * G0); + Ellipsoid e(origin.mid(),(pow(10,-alpha) * G0).mid()); Ellipsoid e_out = nonlinear_mapping(e,f); res = inclusion_test(e,e_out); @@ -146,17 +146,32 @@ namespace codac2 { bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2){ // check if e1 included in e2 - - // Identity matrix with the same size as Y - IntervalMatrix I(Eigen::Idendity(e2.G.nb_rows())); - IntervalMatrix G2_inv = e2.G.inverse(); // TODO pas garantie - IntervalVector D = I - e1.G.transpose()*G2_inv.transpose()*G2_inv*e1.G; + IntervalMatrix G1(e1.G._e); + IntervalMatrix G2(e2.G._e); + IntervalMatrix G2_inv = G2._e.inverse(); + IntervalMatrix I(Eigen::MatrixXd::Identity(e2.G.nb_rows(),e2.G.nb_cols())); + IntervalMatrix D(I._e - G1._e.transpose()*G2_inv._e.transpose()*G2_inv._e*G1._e); // cholesky decomposition of D //TODO + return false; + } + + IntervalVector enclose_elli_by_box(const Ellipsoid& e) + { + // |xi|<||Gamma_i| (i_th column bcs symetric) + // xi = Gamma_i*y with |y|<1, y = Gamma_inv*x in the unit circle + IntervalVector res(e.size()); + for(int i=0; i - requires std::is_base_of_v - Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction::Domain> &f); +// template +// requires std::is_base_of_v + Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction &f); std::ostream &operator<<(std::ostream &os, const Ellipsoid &e); - template - requires std::is_base_of_v - bool stability_analysis(const AnalyticFunction::Domain> &f, int alpha_max); +// template +// requires std::is_base_of_v + bool stability_analysis(const AnalyticFunction &f, int alpha_max); bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); + + IntervalVector enclose_elli_by_box(const Ellipsoid& e); } \ No newline at end of file From 576db058508c99c5e2aef8a4b6afbc38c2999a98 Mon Sep 17 00:00:00 2001 From: MLouedec Date: Mon, 30 Sep 2024 14:21:51 +0200 Subject: [PATCH 005/126] 30septok --- examples/ellipsoid_example/main.cpp | 5 +- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 122 +++++++++--------- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 4 +- 3 files changed, 68 insertions(+), 63 deletions(-) diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index 10687a749..7e2de1c83 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -22,7 +22,8 @@ int main() cout << e2 << endl; cout << "non Linear Mapping" << endl; + VectorVar x(2); AnalyticFunction h { - {x,y}, vec(x[0]+0.5*sin(x[1]),-0.5*sin(x[0])+0.9)}; - Ellipsoid e3 = nonlinear_mapping(e1, f); + {x}, vec(x[0]+0.5*sin(x[1]),-0.5*sin(x[0])+0.9)}; + Ellipsoid e3 = nonlinear_mapping(e1, h); } diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 0ebac3d45..359da0a80 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -50,8 +50,8 @@ namespace codac2 { Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b) { // compute A*e+b - Vector mu_res = A._e * e.mu._e + b._e; - Matrix G_res = A._e * e.G._e; + auto mu_res = A._e * e.mu._e + b._e; + auto G_res = A._e * e.G._e; Ellipsoid res(mu_res, G_res); return res; } @@ -62,35 +62,39 @@ namespace codac2 { // compute rounding error as a small box IntervalVector mu_(e.mu); + IntervalVector mu_res_(e_res.mu); IntervalMatrix G_(e.G); + IntervalMatrix G_res_(e_res.G); + IntervalMatrix A_(A); IntervalVector b_(b); - IntervalVector mu_res_(A_._e * mu_._e + b_._e); // TODO multiplication IntervalMatrix*IntervalVector IntervalVector unit_box_(mu_.size(), Interval(-1, 1)); - IntervalMatrix error_box_ = mu_res_ - IntervalVector(e_res.mu._e) + - (A_ * G_ - IntervalMatrix(e_res.G._e)) * unit_box_; + auto mu_res_guaranteed = A_._e * mu_._e + b_._e; + auto G_res_guaranteed = A_._e * G_._e; + auto error_box_ = mu_res_guaranteed - mu_res_._e + + (G_res_guaranteed - G_res_._e) * unit_box_._e; // compute the max radius of error_box - double rho = Interval(error_box_._e.norm()).ub(); // TODO norm 2 d'une boite + double rho = Interval(error_box_.norm()).ub(); // TODO norm 2 d'une boite à verifier Ellipsoid elli_error(e.mu, Eigen::MatrixXd::Identity(e.size(),e.size()) * rho); // = rho*unit_ball return e_res + elli_error; } Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box) { - Matrix E_out = J * G; - IntervalMatrix JE = IntervalMatrix(E_out); - IntervalMatrix JE_inv = JE._e.inverse(); // TODO inverse of interval matrix - // TODO this is the rigorous version, but one could compute JE_inv = E_out.inv() + Matrix JG = J * G; + IntervalMatrix G_(G); + IntervalMatrix JG_ = IntervalMatrix(JG); + // IntervalMatrix JG_inv_ = JE._e.inverse(); // not working with eigen + IntervalMatrix JG_inv_(JG._e.inverse()); // nonrigourous inversion // compute b_box IntervalVector unit_box(G.nb_rows(), Interval(-1, 1)); IntervalMatrix I_ = IntervalMatrix(Eigen::MatrixXd::Identity(G.nb_rows(),G.nb_cols())); - IntervalVector b_box = (JE_inv * J_box * IntervalMatrix(G) - I_) * unit_box; + auto b_box = (JG_inv_._e * J_box._e * G_._e - I_._e) * unit_box._e; // get max radius of b_box -// double rho = b_box.norm_2().upper(); // TODO norm 2 d'une boite - double rho = Interval(b_box._e.norm()).ub(); - return (1 + rho) * E_out; + double rho = Interval(b_box.norm()).ub(); // TODO norm 2 d'une boite à verifier + return (1 + rho) * JG; } Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f) { @@ -113,51 +117,51 @@ namespace codac2 { return os << "mu : " << e.mu << "\n" << "G :\n" << e.G; } - bool stability_analysis(const AnalyticFunction &f, int alpha_max) - { - // get the Jacobian of f at the origin - int n = f.args().size(); - IntervalVector origin(Eigen::MatrixXd::Zero(n,n)); - IntervalMatrix J = f.diff(IntervalVector(origin)); - - // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J - IntervalMatrix P(n,n); //TODO - IntervalMatrix G0 = (P._e.inverse()).sqrt(); - int alpha = 0; - bool res = false; - - while(alpha <= alpha_max) - { - Ellipsoid e(origin.mid(),(pow(10,-alpha) * G0).mid()); - Ellipsoid e_out = nonlinear_mapping(e,f); - - res = inclusion_test(e,e_out); - if(res) - { - cout << "The system is stable" << endl; - cout << "Domain of attraction :\n" << e_out << endl; - return true; - } - alpha++; - } - cout << "The method is not able to conclude on the stability" << endl; - return false; - } - - bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2){ - // check if e1 included in e2 - IntervalMatrix G1(e1.G._e); - IntervalMatrix G2(e2.G._e); - IntervalMatrix G2_inv = G2._e.inverse(); - IntervalMatrix I(Eigen::MatrixXd::Identity(e2.G.nb_rows(),e2.G.nb_cols())); - IntervalMatrix D(I._e - G1._e.transpose()*G2_inv._e.transpose()*G2_inv._e*G1._e); - - // cholesky decomposition of D - //TODO - - return false; - } - +// bool stability_analysis(const AnalyticFunction &f, int alpha_max) +// { +// // get the Jacobian of f at the origin +// int n = f.args().size(); +// IntervalVector origin(Eigen::MatrixXd::Zero(n,n)); +// IntervalMatrix J = f.diff(IntervalVector(origin)); +// +// // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J +// IntervalMatrix P(n,n); //TODO +// IntervalMatrix G0 = (P._e.inverse()).sqrt(); +// int alpha = 0; +// bool res = false; +// +// while(alpha <= alpha_max) +// { +// Ellipsoid e(origin.mid(),(pow(10,-alpha) * G0).mid()); +// Ellipsoid e_out = nonlinear_mapping(e,f); +// +// res = inclusion_test(e,e_out); +// if(res) +// { +// cout << "The system is stable" << endl; +// cout << "Domain of attraction :\n" << e_out << endl; +// return true; +// } +// alpha++; +// } +// cout << "The method is not able to conclude on the stability" << endl; +// return false; +// } +// +// bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2){ +// // check if e1 included in e2 +// IntervalMatrix G1(e1.G._e); +// IntervalMatrix G2(e2.G._e); +// IntervalMatrix G2_inv = G2._e.inverse(); +// IntervalMatrix I(Eigen::MatrixXd::Identity(e2.G.nb_rows(),e2.G.nb_cols())); +// IntervalMatrix D(I._e - G1._e.transpose()*G2_inv._e.transpose()*G2_inv._e*G1._e); +// +// // cholesky decomposition of D +// //TODO +// +// return false; +// } +// IntervalVector enclose_elli_by_box(const Ellipsoid& e) { // |xi|<||Gamma_i| (i_th column bcs symetric) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index 7564ca61d..579d42e14 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -46,9 +46,9 @@ namespace codac2 { // template // requires std::is_base_of_v - bool stability_analysis(const AnalyticFunction &f, int alpha_max); +// bool stability_analysis(const AnalyticFunction &f, int alpha_max); - bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); +// bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); IntervalVector enclose_elli_by_box(const Ellipsoid& e); } \ No newline at end of file From 0d0b956ca249bc66a3c8fdbde956f103b022a7a5 Mon Sep 17 00:00:00 2001 From: MLouedec Date: Mon, 30 Sep 2024 17:08:03 +0200 Subject: [PATCH 006/126] exemple ellipse avec linear et nonlinear mapping = OK --- examples/ellipsoid_example/main.cpp | 45 ++++++++++++++-------- src/graphics/figures/codac2_Figure2D.cpp | 48 +++++++++++++++++------- 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index 7e2de1c83..d1f5be4d0 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -5,25 +5,40 @@ using namespace codac2; int main() { - Vector mu({1.3,2.7}); - Matrix G({{2.3,0.5},{0.5,1.7}}); - Ellipsoid e1(mu, G); - - Matrix A({{0.,0.5},{-0.5,0.9}}); - Vector b({1.3,2.1}); + Figure2D fig1("Ellipsoid example", GraphicOutput::VIBES); + fig1.set_axes(FigureAxis(0,{0,1.5}), FigureAxis(1,{-1.,0.5})); + fig1.set_window_properties({250,250},{500,500}); - Ellipsoid e2 = linear_mapping(e1, A, b); - - cout << "Linear Mapping" << endl; + // initial ellipsoid + Vector mu({1.,0.}); + Matrix G({{0.05,0.0},{0.,0.05}}); + Ellipsoid e1(mu, G); + fig1.draw_ellipsoid(e1, {Color::red(),Color::red(0.3)}); cout << "Initial ellipsoid e1:" << endl; cout << e1 << endl; - cout << "Image ellipsoid e2:" << endl; - cout << e2 << endl; - - cout << "non Linear Mapping" << endl; + // discrete nonlinear pendulum system VectorVar x(2); AnalyticFunction h { - {x}, vec(x[0]+0.5*sin(x[1]),-0.5*sin(x[0])+0.9)}; - Ellipsoid e3 = nonlinear_mapping(e1, h); + {x}, vec(x[0]+0.1*x[1],-0.2*sin(x[0])+0.9*x[1])}; + + // linear mapping + int N = 10; + Ellipsoid e2 = Ellipsoid(e1); + for(int i =0; idraw_ellipse(c,ab,theta,s); } -void Figure2D::draw_ellipsoid(const Ellipsoid& e, const StyleProperties& s) -{ - assert_release(this->size() <= e.size()); - - // <===== ici, définir le code de projection d'ellipsoide en 2d +void Figure2D::draw_ellipsoid(const Ellipsoid &e, const StyleProperties &s) { + assert_release(this->size() <= e.size()); + for (const auto &output_fig: _output_figures) { + Matrix G_draw(2, 2); + Vector mu_draw(2); + // 2d projection of the ellipsoid + if (e.size() > 2) { + // affine space of the projection + Vector d(Eigen::VectorXd::Zero(e.mu.nb_rows())); + Matrix T(Eigen::MatrixXd::Zero(e.G.nb_rows(), 2)); + T(output_fig->i(), 0) = 1; + T(output_fig->j(), 1) = 1; + + // project ellipsoid E(mu,Q) = {x in R^n | (x-mu).T*G.{-T}*G^{-1}*(x-mu)<1} + // on the affine plan A = {x|x=d+Tt} [Pope -2008] + // reduce the dimensions of mu and Q + + auto TTG = T._e.transpose() * e.G._e; + Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); + Matrix U(bdcsvd.matrixU()); + Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); + G_draw = U._e * E._e; + mu_draw = T._e.transpose() * (d._e + T._e * T._e.transpose() * (e.mu._e - d._e)); + } else { + G_draw = e.G; + mu_draw = e.mu; + } - // La figure 2d est définie comme une projection d'un espace de grande dimension, - // les dimensions de la figure sont données par: - // output_fig->i() // (dimension 1) - // output_fig->j() // (dimension 2) + // draw the 2d ellipsoid + Eigen::JacobiSVD jsvd(G_draw._e, Eigen::ComputeThinU); + Matrix U(jsvd.matrixU()); + Vector ab(jsvd.singularValues()); - // ... + double theta = atan2(U(1, 0), U(0, 0)).mid(); - //for(const auto& output_fig : _output_figures) - // output_fig->draw_ellipse( ... ,s); // utiliser draw_ellipse à la place, une fois les paramètres estimés + output_fig->draw_ellipse(mu_draw, ab, theta, s); + } } void Figure2D::draw_tank(const Vector& x, float size, const StyleProperties& s) @@ -280,7 +302,7 @@ void Figure2D::draw_paving(const PavingInOut& p, const StyleProperties& boundary for(const auto& bi : hull.diff(outer)) output_fig->draw_box(bi, outside_style); - + if(n->is_leaf()) output_fig->draw_box(inner & outer, boundary_style); From 9369f224f877410e5d7ae73130b4b724c429eb7e Mon Sep 17 00:00:00 2001 From: MLouedec Date: Mon, 30 Sep 2024 17:45:20 +0200 Subject: [PATCH 007/126] inclusion test = OK --- examples/ellipsoid_example/main.cpp | 61 ++++++++++++++++++- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 57 ++++++++++++----- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 2 +- 3 files changed, 102 insertions(+), 18 deletions(-) diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index d1f5be4d0..0b116a71a 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -5,7 +5,11 @@ using namespace codac2; int main() { - Figure2D fig1("Ellipsoid example", GraphicOutput::VIBES); + // ---------------------------------------------------------- + // linear and nonlinear mappings + // ---------------------------------------------------------- + + Figure2D fig1("Linear and nonlinear mappings", GraphicOutput::VIBES); fig1.set_axes(FigureAxis(0,{0,1.5}), FigureAxis(1,{-1.,0.5})); fig1.set_window_properties({250,250},{500,500}); @@ -41,4 +45,59 @@ int main() } cout << "\nNon Linear Mapping - Image ellipsoid e3:" << endl; cout << e3 << endl; + + // ---------------------------------------------------------- + // ellipsoid projections + // ---------------------------------------------------------- + + Vector mu4({1.,0.,0.}); + Matrix G4({{1.,0.5,0.},{0.5,2.,0.2},{0.,0.2,3.}}); + Ellipsoid e4(mu4, G4); + + Matrix G5 = 0.7*G4; + Ellipsoid e5(mu4, G5); + + Matrix G6({{2.,0.,0.5},{0.,1.,0.2},{0.,0.2,3.}}); + Ellipsoid e6(mu4, G6); + + Figure2D fig2("Projected ellipsoid xy", GraphicOutput::VIBES); + Figure2D fig3("Projected ellipsoid yz", GraphicOutput::VIBES); + Figure2D fig4("Projected ellipsoid xz", GraphicOutput::VIBES); + + fig2.set_window_properties({250,250},{500,500}); + fig3.set_window_properties({250,250},{500,500}); + fig4.set_window_properties({250,250},{500,500}); + + fig2.set_axes(FigureAxis(0,{-3,3}), FigureAxis(1,{-3,3})); + fig3.set_axes(FigureAxis(1,{-3,3}), FigureAxis(2,{-3,3})); + fig4.set_axes(FigureAxis(0,{-3,3}), FigureAxis(2,{-3,3})); + + fig2.draw_ellipsoid(e4, {Color::blue(),Color::blue(0.3)}); + fig3.draw_ellipsoid(e4, {Color::blue(),Color::blue(0.3)}); + fig4.draw_ellipsoid(e4, {Color::blue(),Color::blue(0.3)}); + + fig2.draw_ellipsoid(e5, {Color::red(),Color::red(0.3)}); + fig3.draw_ellipsoid(e5, {Color::red(),Color::red(0.3)}); + fig4.draw_ellipsoid(e5, {Color::red(),Color::red(0.3)}); + + fig2.draw_ellipsoid(e6, {Color::green(),Color::green(0.3)}); + fig3.draw_ellipsoid(e6, {Color::green(),Color::green(0.3)}); + fig4.draw_ellipsoid(e6, {Color::green(),Color::green(0.3)}); + + // ---------------------------------------------------------- + // inclusion tests + // ---------------------------------------------------------- + + bool res1 = concentric_inclusion_test(e5, e4); + cout << "\nInclusion test e5 in e4: " << res1 << endl; + + bool res2 = concentric_inclusion_test(e4, e5); + cout << "Inclusion test e4 in e5: " << res2 << endl; + + bool res3 = concentric_inclusion_test(e6, e4); + cout << "Inclusion test e4 in e6: " << res3 << endl; + + bool res4 = concentric_inclusion_test(e5, e6); + cout << "Inclusion test e5 in e6: " << res4 << endl; + } diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 359da0a80..55cb15fe1 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -147,21 +147,47 @@ namespace codac2 { // cout << "The method is not able to conclude on the stability" << endl; // return false; // } -// -// bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2){ -// // check if e1 included in e2 -// IntervalMatrix G1(e1.G._e); -// IntervalMatrix G2(e2.G._e); -// IntervalMatrix G2_inv = G2._e.inverse(); -// IntervalMatrix I(Eigen::MatrixXd::Identity(e2.G.nb_rows(),e2.G.nb_cols())); -// IntervalMatrix D(I._e - G1._e.transpose()*G2_inv._e.transpose()*G2_inv._e*G1._e); -// -// // cholesky decomposition of D -// //TODO -// -// return false; -// } -// + + bool concentric_inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2) { + assert(e1.size() == e2.size()); + assert((e1.mu._e - e2.mu._e).norm() < 1e-10); // check if the centers are the same + + // check if e1 included in e2 + auto G2_inv = e2.G._e.inverse(); + Matrix I(Eigen::MatrixXd::Identity(e2.G.nb_rows(), e2.G.nb_cols())); + IntervalMatrix D(I._e - e1.G._e.transpose() * G2_inv.transpose() * G2_inv * e1.G._e); + + // cholesky decomposition of D + IntervalMatrix L(e1.size(), e1.size()); // matrix of the Cholesky decomposition + + Interval S(0, 0); + Interval U(0, 0); + + for (int j = 0; j < L.nb_cols(); j++) // for every column + { + S = Interval(0, 0); + for (int k = 0; k < j; k++) + S += L(j, k) * L(j, k); + U = D(j, j) - S; + if (U.lb() < 0) { + return false; + } + L(j,j) = sqrt(U); + + // now the rest of the column + for (int i = j + 1; i // bool stability_analysis(const AnalyticFunction &f, int alpha_max); -// bool inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); + bool concentric_inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); IntervalVector enclose_elli_by_box(const Ellipsoid& e); } \ No newline at end of file From a4eb4c28af2ce967f1784cf71674b1dd85dddef6 Mon Sep 17 00:00:00 2001 From: MLouedec Date: Mon, 30 Sep 2024 18:01:49 +0200 Subject: [PATCH 008/126] 30sept --- examples/ellipsoid_example/main.cpp | 18 ++++++++++++++++++ .../domains/ellipsoid/codac2_Ellipsoid.cpp | 4 ++-- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 4 ---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index 0b116a71a..f912b36d2 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -100,4 +100,22 @@ int main() bool res4 = concentric_inclusion_test(e5, e6); cout << "Inclusion test e5 in e6: " << res4 << endl; + // ---------------------------------------------------------- + // guaranteed and non guaranteed linear mappings + // ---------------------------------------------------------- + Matrix A({{0.9,0.5},{-.5,1.1}}); + Vector b({0.1,0.2}); + + Ellipsoid e7 = linear_mapping(e1, A, b); + Ellipsoid e8 = linear_mapping_guaranteed(e1, A, b); + + cout << "\nLinear Mapping - Image ellipsoid e7:" << endl; + cout << e7 << endl; + + cout << "\nLinear Mapping Guaranteed - Image ellipsoid e8:" << endl; + cout << e8 << endl; + + cout << "\nDifference between e7 and e8:" << endl; + cout << "mu diff norm is " << (e7.mu._e - e8.mu._e).norm() << endl; + cout << "G diff norm is " << (e7.G._e - e8.G._e).norm() << endl; } diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 55cb15fe1..a980fca52 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -76,7 +76,7 @@ namespace codac2 { // compute the max radius of error_box double rho = Interval(error_box_.norm()).ub(); // TODO norm 2 d'une boite à verifier - Ellipsoid elli_error(e.mu, Eigen::MatrixXd::Identity(e.size(),e.size()) * rho); // = rho*unit_ball + Ellipsoid elli_error(Vector(e.size()), Eigen::MatrixXd::Identity(e.size(),e.size()) * rho); // = rho*unit_ball return e_res + elli_error; } @@ -125,7 +125,7 @@ namespace codac2 { // IntervalMatrix J = f.diff(IntervalVector(origin)); // // // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J -// IntervalMatrix P(n,n); //TODO +// IntervalMatrix P(n,n); // TODO solve the Lyapunov equation !!! // IntervalMatrix G0 = (P._e.inverse()).sqrt(); // int alpha = 0; // bool res = false; diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index 01e0e6d6e..3036122ef 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -38,14 +38,10 @@ namespace codac2 { Ellipsoid nonlinear_mapping_base(const Ellipsoid &e, const Matrix &J, const IntervalMatrix &J_box); -// template -// requires std::is_base_of_v Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction &f); std::ostream &operator<<(std::ostream &os, const Ellipsoid &e); -// template -// requires std::is_base_of_v // bool stability_analysis(const AnalyticFunction &f, int alpha_max); bool concentric_inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); From 5ac6a85453738bb9b1f79fbb8d0bf4b45c52078e Mon Sep 17 00:00:00 2001 From: MLouedec Date: Tue, 1 Oct 2024 20:12:07 +0200 Subject: [PATCH 009/126] need to fix the degenerated case --- examples/ellipsoid_example/main.cpp | 146 +++++++++++++----- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 105 ++++++++++--- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 13 +- tests/CMakeLists.txt | 1 + .../ellipsoid/codac2_tests_Ellipsoid.cpp | 93 +++++++++++ 5 files changed, 293 insertions(+), 65 deletions(-) create mode 100644 tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index f912b36d2..ff90d1d6e 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -3,86 +3,111 @@ using namespace std; using namespace codac2; -int main() -{ +int main() { // ---------------------------------------------------------- // linear and nonlinear mappings // ---------------------------------------------------------- Figure2D fig1("Linear and nonlinear mappings", GraphicOutput::VIBES); - fig1.set_axes(FigureAxis(0,{0,1.5}), FigureAxis(1,{-1.,0.5})); - fig1.set_window_properties({250,250},{500,500}); + fig1.set_axes(FigureAxis(0, {0, 1.5}), FigureAxis(1, {-1., 0.5})); + fig1.set_window_properties({0, 100}, {500, 500}); // initial ellipsoid - Vector mu({1.,0.}); - Matrix G({{0.05,0.0},{0.,0.05}}); + Vector mu({1., 0.}); + Matrix G({{0.05, 0.0}, + {0., 0.05}}); Ellipsoid e1(mu, G); - fig1.draw_ellipsoid(e1, {Color::red(),Color::red(0.3)}); + fig1.draw_ellipsoid(e1, {Color::red(), Color::red(0.3)}); cout << "Initial ellipsoid e1:" << endl; cout << e1 << endl; // discrete nonlinear pendulum system VectorVar x(2); - AnalyticFunction h { - {x}, vec(x[0]+0.1*x[1],-0.2*sin(x[0])+0.9*x[1])}; + AnalyticFunction h{ + {x}, vec(x[0] + 0.1 * x[1], -0.2 * sin(x[0]) + 0.9 * x[1])}; // linear mapping int N = 10; Ellipsoid e2 = Ellipsoid(e1); - for(int i =0; isize())); + double rand_norm = ((double) rand() / (RAND_MAX)); + return this->mu._e + this->G._e * xi._e / xi._e.norm() * rand_norm; + } + Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2) { assert_release(e1.size() == e2.size()); @@ -49,7 +55,7 @@ namespace codac2 { } Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b) { - // compute A*e+b + // return A*e+b | non-rigorous operations auto mu_res = A._e * e.mu._e + b._e; auto G_res = A._e * e.G._e; Ellipsoid res(mu_res, G_res); @@ -57,7 +63,7 @@ namespace codac2 { } Ellipsoid linear_mapping_guaranteed(const Ellipsoid &e, const Matrix &A, const Vector &b) { - // compute A*e+b considering rounding error + // compute en outer enclosure of A*e+b, considering the rounding error Ellipsoid e_res = linear_mapping(e, A, b); // compute rounding error as a small box @@ -65,51 +71,100 @@ namespace codac2 { IntervalVector mu_res_(e_res.mu); IntervalMatrix G_(e.G); IntervalMatrix G_res_(e_res.G); - IntervalMatrix A_(A); IntervalVector b_(b); IntervalVector unit_box_(mu_.size(), Interval(-1, 1)); + auto mu_res_guaranteed = A_._e * mu_._e + b_._e; auto G_res_guaranteed = A_._e * G_._e; auto error_box_ = mu_res_guaranteed - mu_res_._e + (G_res_guaranteed - G_res_._e) * unit_box_._e; - // compute the max radius of error_box - double rho = Interval(error_box_.norm()).ub(); // TODO norm 2 d'une boite à verifier - Ellipsoid elli_error(Vector(e.size()), Eigen::MatrixXd::Identity(e.size(),e.size()) * rho); // = rho*unit_ball + + double rho = Interval(error_box_.norm()).ub(); // max radius of error_box + Ellipsoid elli_error(Vector(e.size()), + Eigen::MatrixXd::Identity(e.size(),e.size()) * rho); // = rho*unit_ball return e_res + elli_error; } - Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box) { + Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box, const Vector& trig, const Vector& q) { + /* nonsingular main case from + * Rauh, A., & Jaulin, L. (2021). + * "A computationally inexpensive algorithm for determining outer + * and inner enclosures of nonlinear mappings of ellipsoidal domains. + * International Journal of Applied Mathematics and Computer Science, 31(3).*/ + Matrix JG = J * G; IntervalMatrix G_(G); IntervalMatrix JG_ = IntervalMatrix(JG); - // IntervalMatrix JG_inv_ = JE._e.inverse(); // not working with eigen - IntervalMatrix JG_inv_(JG._e.inverse()); // nonrigourous inversion - - // compute b_box IntervalVector unit_box(G.nb_rows(), Interval(-1, 1)); + + // normal case IntervalMatrix I_ = IntervalMatrix(Eigen::MatrixXd::Identity(G.nb_rows(),G.nb_cols())); - auto b_box = (JG_inv_._e * J_box._e * G_._e - I_._e) * unit_box._e; + IntervalMatrix JG_inv_(JG._e.inverse()); // non rigourous inversion + Matrix M(JG); + auto W = JG_inv_._e; + auto Z = I_._e; + + // check for singularities + if(std::abs(JG._e.determinant()) < trig[1]) + { + /* degenerated case from + * Louedec, M., Jaulin, L., & Viel, C. (2024). + * "Outer enclosures of nonlinear mapping with degenerate ellipsoids." + * IFAC ACNDC June 2024*/ + assert(trig.size() == 2); + assert(q.size() == G.nb_rows()); + + // SVD decomposition of JG = U*E*V.T + Eigen::BDCSVD bdcsvd(JG._e,Eigen::ComputeFullU); + IntervalMatrix U_(bdcsvd.matrixU()); // which is also the right part + Vector Sv(bdcsvd.singularValues()); // vectors of singular values + + // select new singular values + int dim = G.nb_rows(); + IntervalVector s_box(U_._e.transpose()*J_box._e*G_._e*unit_box._e); + IntervalMatrix S_(Eigen::MatrixXd::Zero(dim,dim)); // diagonal matrix of the new singular value + IntervalMatrix S_pinv_(Eigen::MatrixXd::Zero(dim,dim)); // pseudo inverse of S + for(int i=0;itrig[2]){ // normal size singular values + S_(i,i) = Interval(Sv[i]); + S_pinv_(i,i) = 1/S_(i,i); + }else{ // for very small singular values (0 included) use s_box + double val = s_box[i].ub(); + S_(i,i) = Interval(q[i]*val); + S_pinv_(i,i)=1/S_(i,i); + } + } + M = (U_*S_).mid(); + W = S_pinv_._e*U_._e.transpose(); + Z = W*JG_._e; + } - // get max radius of b_box - double rho = Interval(b_box.norm()).ub(); // TODO norm 2 d'une boite à verifier - return (1 + rho) * JG; +// auto b_box = (JG_inv_._e * J_box._e * G_._e - I_._e) * unit_box._e; + auto b_box = (W * J_box._e * G_._e - Z) * unit_box._e; + double rho = Interval(b_box.norm()).ub(); // max radius of b_box + return (1 + rho) * M; } - Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f) { - // compute the image of the center - Vector mu_res = f.eval(e.mu).mid(); + Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f) + { + return nonlinear_mapping(e,f,Vector({1e-10,1e-9}),Vector(Eigen::VectorXd::Ones(e.size()))); + } - // compute the Jacobian of f at the center - Matrix J = f.diff(e.mu).mid(); + Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f,const Vector& trig, const Vector& q) { + assert(e.size() == f.input_size()); + assert(trig.size() == 2); + assert(q.size() == e.size()); - // compute the Jacoiban of f over a box enclosing the ellipsoid - IntervalVector enclosing_box = enclose_elli_by_box(e); // TODO import this function + Vector mu_res = f.eval(e.mu).mid(); // compute the image of the center + Matrix J = f.diff(e.mu).mid(); // compute the Jacobian of f at the center + // compute the Jacobian of f over a box enclosing the ellipsoid + IntervalVector enclosing_box = enclose_elli_by_box(e); IntervalMatrix J_box = f.diff(enclosing_box); - Matrix E_out = nonlinear_mapping_base(e.G, J, J_box); + Matrix E_out = nonlinear_mapping_base(e.G, J, J_box,trig,q); return Ellipsoid(mu_res, E_out); } @@ -163,7 +218,7 @@ namespace codac2 { Interval S(0, 0); Interval U(0, 0); - for (int j = 0; j < L.nb_cols(); j++) // for every column + for (int j = 0; j < (int)e1.size(); j++) // for every column { S = Interval(0, 0); for (int k = 0; k < j; k++) @@ -175,7 +230,7 @@ namespace codac2 { L(j,j) = sqrt(U); // now the rest of the column - for (int i = j + 1; i &f); + Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction &f, + const Vector& trig,const Vector& q); + + std::ostream &operator<<(std::ostream &os, const Ellipsoid &e); @@ -47,4 +57,5 @@ namespace codac2 { bool concentric_inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); IntervalVector enclose_elli_by_box(const Ellipsoid& e); + } \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4956a9361..bb62a20ff 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -40,6 +40,7 @@ list(APPEND SRC_TESTS # listing files without extension core/domains/interval/codac2_tests_Interval_operations core/domains/interval/codac2_tests_IntervalMatrix core/domains/interval/codac2_tests_IntervalVector + core/domains/ellipsoid/codac2_tests_Ellipsoid core/functions/analytic/codac2_tests_AnalyticFunction diff --git a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp new file mode 100644 index 000000000..b86722ae7 --- /dev/null +++ b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp @@ -0,0 +1,93 @@ +/** + * Codac tests + * + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Morgan Louedec, (Simon Rohou) + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include + +using namespace std; +using namespace codac2; + +Ellipsoid e1() { + return Ellipsoid(Vector({1., 0.}), Matrix({{0.05, 0.0}, + {0., 0.05}})); +} + +Ellipsoid e4() { + return Ellipsoid(Vector({1., 0., 0.}), + Matrix({{1., 0.5, 0.}, + {0.5, 2., 0.2}, + {0., 0.2, 3.}})); +} + +Ellipsoid e5() { + return Ellipsoid(Vector({1., 0., 0.}), + Matrix({{0.7, 0.35, 0.}, + {0.35, 1.4, 0.14}, + {0., 0.14, 2.1}})); +} + +Ellipsoid e6(){ + return Ellipsoid(Vector({1., 0., 0.}), + Matrix({{2., 0., 0.5}, + {0., 1., 0.2}, + {0., 0.2, 3.}})); +} + +TEST_CASE("Ellipsoids") +{ + Ellipsoid e = e1(); + CHECK(e.size() == 2); + CHECK(e.mu == Vector({1., 0.})); + CHECK(e.G == Matrix({{0.05, 0.0}, + {0., 0.05}})); + + VectorVar x(2); + AnalyticFunction h { + {x}, vec(x[0]+0.1*x[1],-0.2*sin(x[0])+0.9*x[1])}; + + Matrix A = h.diff(e.mu).mid(); + Vector b(h.eval(e.mu).mid()._e - A._e*e.mu._e); + Ellipsoid e2 = linear_mapping(e, A, b); + Vector mu2({1 , -0.168294}); + Matrix G2({{0.0500001 , 0.00500001},{-0.00540302 , 0.0450001}}); + CHECK(e2.size() == 2); + CHECK((e2.mu._e-mu2._e).norm() < 1e-6); + CHECK((e2.G._e-G2._e).norm() < 1e-6); + + Ellipsoid e3 = nonlinear_mapping(e, h); + Vector mu3({1. , -0.168294}); + Matrix G3({{0.0550724 , 0.00550724},{-0.00595114 , 0.0495651}}); + CHECK(e3.size() == 2); + CHECK((e3.mu._e-mu3._e).norm() < 1e-6); + CHECK((e3.G._e-G3._e).norm() < 1e-6); + + Ellipsoid e4_ = e4(); + Ellipsoid e5_ = e5(); + Ellipsoid e6_ = e6(); + + bool res1 = concentric_inclusion_test(e5_, e4_); + bool res2 = concentric_inclusion_test(e4_, e5_); + bool res3 = concentric_inclusion_test(e6_, e4_); + bool res4 = concentric_inclusion_test(e5_, e6_); + CHECK(res1 == true); + CHECK(res2 == false); + CHECK(res3 == false); + CHECK(res4 == false); + + Matrix A2({{0.9,0.5},{-.5,1.1}}); + Vector b2({0.1,0.2}); + + Ellipsoid e7 = linear_mapping(e, A2, b2); + Ellipsoid e8 = linear_mapping_guaranteed(e, A2, b2); + CHECK((e7.mu._e - e8.mu._e).norm()<1e-6); + CHECK((e7.G._e - e8.G._e).norm()<0.04); + + +} \ No newline at end of file From 016ae73f506b0d7a1538c9566d6c3158aa36972f Mon Sep 17 00:00:00 2001 From: MLouedec Date: Wed, 2 Oct 2024 14:32:02 +0200 Subject: [PATCH 010/126] degenerate and stability analysis OK --- examples/ellipsoid_example/main.cpp | 69 ++++++++++-- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 100 +++++++++++------- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 4 +- 3 files changed, 124 insertions(+), 49 deletions(-) diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index ff90d1d6e..b92c99f4e 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -18,7 +18,7 @@ int main() { {0., 0.05}}); Ellipsoid e1(mu, G); fig1.draw_ellipsoid(e1, {Color::red(), Color::red(0.3)}); - cout << "Initial ellipsoid e1:" << endl; + cout << "Initial ellipsoid e1 (red):" << endl; cout << e1 << endl; // discrete nonlinear pendulum system @@ -35,7 +35,7 @@ int main() { e2 = linear_mapping(e2, A, b); fig1.draw_ellipsoid(e2, {Color::green(), Color::green(0.3)}); } - cout << "\nLinear Mapping - Image ellipsoid e2:" << endl; + cout << "\nLinear Mapping - Image ellipsoid e2 (green):" << endl; cout << e2 << endl; // nonlinear mapping @@ -44,7 +44,7 @@ int main() { e3 = nonlinear_mapping(e3, h); fig1.draw_ellipsoid(e3, {Color::blue(), Color::blue(0.3)}); } - cout << "\nNon Linear Mapping - Image ellipsoid e3:" << endl; + cout << "\nNon Linear Mapping - Image ellipsoid e3 (blue):" << endl; cout << e3 << endl; // particle cloud (draw the evolution of 200 points in the ellipsoid) @@ -100,7 +100,7 @@ int main() { fig3.draw_ellipsoid(e6, {Color::green(), Color::green(0.3)}); fig4.draw_ellipsoid(e6, {Color::green(), Color::green(0.3)}); - // particle cloud (draw the evolution of 200 points in the ellipsoid) + // particle cloud (draw the evolution of 200 points in the ellipsoid e5) for (int i = 0; i < Np; i++) { IntervalVector x5(e5.sample()); x5.inflate(0.001); @@ -150,7 +150,7 @@ int main() { // ---------------------------------------------------------- Figure2D fig5("singular mappings and degenerated ellipsoids", GraphicOutput::VIBES); - fig5.set_axes(FigureAxis(0, {-5, 5}), FigureAxis(1, {-5., 5})); + fig5.set_axes(FigureAxis(0, {-0.5, 2}), FigureAxis(1, {-1.5, 1.})); fig5.set_window_properties({700, 600}, {500, 500}); Ellipsoid e9(Vector({0., 0.5}), Matrix({{0.25, 0.}, @@ -162,18 +162,21 @@ int main() { fig5.draw_ellipsoid(e10, {Color::red(), Color::red(0.3)}); AnalyticFunction h2{ - {x}, vec(x[0] + 0.5 * x[1] + 1., -0.5 * sin(x[0]) + 0.9 * x[1])}; + {x}, vec(x[0] + 0.5 * x[1] + 0.75, -0.5 * sin(x[0]) + 0.9 * x[1] + 0.1*0.5)}; AnalyticFunction h3{ - {x}, vec(x[0] + 0.5 * x[1] + 1., x[0] + 0.5 * x[1])}; + {x}, vec(x[0] + 0.5 * x[1] + 1.25, x[0] + 0.5 * x[1]-0.25)}; - Vector q(0); - cout << "q size is " << q.size() << endl; Ellipsoid e11 = nonlinear_mapping(e9, h2); Ellipsoid e12 = nonlinear_mapping(e10, h3); fig5.draw_ellipsoid(e11, {Color::green(), Color::green(0.3)}); fig5.draw_ellipsoid(e12, {Color::green(), Color::green(0.3)}); + cout << "\nDegenerate ellipsoid e9 (blue):\n" << e9 << endl; + cout << "\nImage of degenerated ellipsoid e11 (green):\n" << e11 << endl; + cout << "\nNon-degenerate ellipsoid e10 (red):\n" << e10 << endl; + cout << "\nImage of singular mapping e12 (green):\n" << e12 << endl; + // particle cloud (draw the evolution of 200 points in the ellipsoid) for (int i = 0; i < Np; i++) { Vector x0 = e9.sample(); @@ -186,4 +189,52 @@ int main() { x0 = h3.eval(x0).mid(); fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); } + + // ---------------------------------------------------------- + // stability analysis + // ---------------------------------------------------------- + + // pendulum example + AnalyticFunction h4{ + {x}, vec(x[0] + 0.5 * x[1] , x[1] + 0.5 * (-x[1]-sin(x[0])))}; + Ellipsoid e13(Vector(2), Matrix(2,2)); + Ellipsoid e13_out(Vector(2), Matrix(2,2)); + int alpha_max = 1; + bool res = stability_analysis(h4,alpha_max, e13, e13_out); + if(res) + { + cout << "\nStability analysis: the system is stable" << endl; + cout << "Ellipsoidal domain of attraction e13 (red):" << endl; + cout << e13 << endl; + cout << "Outter enclosure e13_out of the Image of e13 by h4 (green):" << endl; + cout << e13_out << endl; + } + else + { + cout << "\nStability analysis: the method is not able to conclude" << endl; + } + Figure2D fig6("Stability analysis - pendulum example", GraphicOutput::VIBES); + fig6.set_axes(FigureAxis(0, {-0.1, 0.1}), FigureAxis(1, {-0.1, 0.1})); + fig6.set_window_properties({1200, 600}, {500, 500}); + fig6.draw_ellipsoid(e13, {Color::red(), Color::red(0.3)}); + fig6.draw_ellipsoid(e13_out, {Color::green(), Color::green(0.3)}); + +// // high dimensional rov example +// VectorVar m(6); +// double T = 0.1; +// double s = 10; +// double kpd = 0.1; +// double kdd = 0.1; +// double kpp = 0.2; +// double kdp = 0.7; +// double dd = 5; +// +// AnalyticFunction h5{ +// {m}, vec(m[0] + T * m[3] , +// m[1] + T * m[4] , +// m[2] + T* (m[6]-m[5]), +// m[3] + T*s*atan(-kpd*m[0]-kdd*m[3]), +// m[4] + T*s*atan(-kpd*m[1]-kdd*m[4]), +// m[5] + T*s*atan(kpp/2*m[2]-kdp*m[5])/(m[0]+dd), +// m[6] + T*s*atan(-kpp/2*m[2]-kdp*m[6])/(m[1]+dd))}; } diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index ce97a420b..544fd3c7f 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -8,6 +8,7 @@ */ #include +#include #include "codac2_Ellipsoid.h" #include "codac2_template_tools.h" @@ -30,6 +31,7 @@ namespace codac2 { } Vector Ellipsoid::sample() const{ + // chose a ramdom point in the ellipsoid Vector xi(Eigen::VectorXd::Random(this->size())); double rand_norm = ((double) rand() / (RAND_MAX)); return this->mu._e + this->G._e * xi._e / xi._e.norm() * rand_norm; @@ -63,7 +65,7 @@ namespace codac2 { } Ellipsoid linear_mapping_guaranteed(const Ellipsoid &e, const Matrix &A, const Vector &b) { - // compute en outer enclosure of A*e+b, considering the rounding error + // compute en outer enclosure of A*e+b, considering the rounding error with pessimism Ellipsoid e_res = linear_mapping(e, A, b); // compute rounding error as a small box @@ -80,7 +82,6 @@ namespace codac2 { auto error_box_ = mu_res_guaranteed - mu_res_._e + (G_res_guaranteed - G_res_._e) * unit_box_._e; - double rho = Interval(error_box_.norm()).ub(); // max radius of error_box Ellipsoid elli_error(Vector(e.size()), Eigen::MatrixXd::Identity(e.size(),e.size()) * rho); // = rho*unit_ball @@ -107,7 +108,7 @@ namespace codac2 { auto Z = I_._e; // check for singularities - if(std::abs(JG._e.determinant()) < trig[1]) + if(std::abs(JG._e.determinant()) < trig[0]) { /* degenerated case from * Louedec, M., Jaulin, L., & Viel, C. (2024). @@ -127,7 +128,7 @@ namespace codac2 { IntervalMatrix S_(Eigen::MatrixXd::Zero(dim,dim)); // diagonal matrix of the new singular value IntervalMatrix S_pinv_(Eigen::MatrixXd::Zero(dim,dim)); // pseudo inverse of S for(int i=0;itrig[2]){ // normal size singular values + if (Sv[i]>trig[1]){ // normal size singular values S_(i,i) = Interval(Sv[i]); S_pinv_(i,i) = 1/S_(i,i); }else{ // for very small singular values (0 included) use s_box @@ -141,7 +142,6 @@ namespace codac2 { Z = W*JG_._e; } -// auto b_box = (JG_inv_._e * J_box._e * G_._e - I_._e) * unit_box._e; auto b_box = (W * J_box._e * G_._e - Z) * unit_box._e; double rho = Interval(b_box.norm()).ub(); // max radius of b_box return (1 + rho) * M; @@ -153,6 +153,8 @@ namespace codac2 { } Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f,const Vector& trig, const Vector& q) { + // compute an outer ellipsoidal enclosure of f(e) + assert(e.size() == f.input_size()); assert(trig.size() == 2); assert(q.size() == e.size()); @@ -172,47 +174,50 @@ namespace codac2 { return os << "mu : " << e.mu << "\n" << "G :\n" << e.G; } -// bool stability_analysis(const AnalyticFunction &f, int alpha_max) -// { -// // get the Jacobian of f at the origin -// int n = f.args().size(); -// IntervalVector origin(Eigen::MatrixXd::Zero(n,n)); -// IntervalMatrix J = f.diff(IntervalVector(origin)); -// -// // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J -// IntervalMatrix P(n,n); // TODO solve the Lyapunov equation !!! -// IntervalMatrix G0 = (P._e.inverse()).sqrt(); -// int alpha = 0; -// bool res = false; -// -// while(alpha <= alpha_max) -// { -// Ellipsoid e(origin.mid(),(pow(10,-alpha) * G0).mid()); -// Ellipsoid e_out = nonlinear_mapping(e,f); -// -// res = inclusion_test(e,e_out); -// if(res) -// { -// cout << "The system is stable" << endl; -// cout << "Domain of attraction :\n" << e_out << endl; -// return true; -// } -// alpha++; -// } -// cout << "The method is not able to conclude on the stability" << endl; -// return false; -// } + bool stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out) + { + // get the Jacobian of f at the origin + int n = f.input_size(); + Vector origin(Eigen::VectorXd::Zero(n)); + Matrix J = f.diff(IntervalVector(origin)).mid(); + + // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J + Matrix P = solve_discrete_lyapunov(J.transpose(),J.transpose()*J); // TODO solve the Lyapunov equation !!! + Matrix G0((P._e.inverse()).sqrt()); + int alpha = 0; + bool res = false; + + while(alpha <= alpha_max) + { + e = Ellipsoid(origin, std::pow(10,-alpha) * G0); + e_out = nonlinear_mapping(e,f); + cout << "\nwith alpha = " << alpha << endl; + cout << "e is\n" << e << endl; + cout << "e_out is\n" << e_out << endl; + + res = concentric_inclusion_test(e_out,e); + if(res) + { + cout << "The system is stable" << endl; + cout << "Domain of attraction :\n" << e_out << endl; + return true; + } + alpha++; + } + cout << "The method is not able to conclude on the stability" << endl; + return false; + } bool concentric_inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2) { + // check if e1 included in e2, assuming that the centers are the same assert(e1.size() == e2.size()); assert((e1.mu._e - e2.mu._e).norm() < 1e-10); // check if the centers are the same - // check if e1 included in e2 auto G2_inv = e2.G._e.inverse(); Matrix I(Eigen::MatrixXd::Identity(e2.G.nb_rows(), e2.G.nb_cols())); IntervalMatrix D(I._e - e1.G._e.transpose() * G2_inv.transpose() * G2_inv * e1.G._e); - // cholesky decomposition of D + // cholesky decomposition of D = L*L^T IntervalMatrix L(e1.size(), e1.size()); // matrix of the Cholesky decomposition Interval S(0, 0); @@ -220,16 +225,17 @@ namespace codac2 { for (int j = 0; j < (int)e1.size(); j++) // for every column { + // diagonal element S = Interval(0, 0); for (int k = 0; k < j; k++) S += L(j, k) * L(j, k); U = D(j, j) - S; if (U.lb() < 0) { - return false; + return false; // cannot guarantee that D is positive definite } L(j,j) = sqrt(U); - // now the rest of the column + // then the rest of the column for (int i = j + 1; i<(int)e1.size(); i++) { @@ -245,6 +251,7 @@ namespace codac2 { IntervalVector enclose_elli_by_box(const Ellipsoid& e) { + // compute the tightest axis aligned box containing e // |xi|<||Gamma_i| (i_th column bcs symetric) // xi = Gamma_i*y with |y|<1, y = Gamma_inv*x in the unit circle IntervalVector res(e.size()); @@ -255,6 +262,21 @@ namespace codac2 { return res; } + Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q) + { + // implementation of the scipy solver for the discrete lyapunov equation (real matrix only) + // works well under dimension 10 + // https://github.com/scipy/scipy/blob/v1.14.1/scipy/linalg/_solvers.py#L235-L323 + // Solves the discrete Lyapunov equation :math:`AXA^H - X + Q = 0` + assert(a.nb_rows() == a.nb_cols()); + assert(a.nb_rows() == q.nb_rows()); + assert(a.nb_cols() == q.nb_cols()); + + Eigen::MatrixXd lhs = Eigen::KroneckerProduct(a._e, a._e); + lhs = Eigen::MatrixXd::Identity(lhs.rows(),lhs.cols()) - lhs; + Eigen::MatrixXd x = lhs.colPivHouseholderQr().solve((Eigen::VectorXd)q._e.reshaped()); + return Matrix(x.reshaped(q.nb_rows(),q.nb_cols())); + } // Old implementations: diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index 24892951a..2341ed006 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -52,10 +52,12 @@ namespace codac2 { std::ostream &operator<<(std::ostream &os, const Ellipsoid &e); -// bool stability_analysis(const AnalyticFunction &f, int alpha_max); + bool stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out); bool concentric_inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); IntervalVector enclose_elli_by_box(const Ellipsoid& e); + Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q); + } \ No newline at end of file From b7396941a02def23b2b5bb8ec172ef5a0bb1ea51 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 18 Oct 2024 10:19:10 +0200 Subject: [PATCH 011/126] [ellips] added rand/random methods on domains --- examples/ellipsoid_example/main.cpp | 8 ++--- .../src/core/matrices/codac2_py_MatrixBase.h | 10 +++++- .../src/core/matrices/codac2_py_VectorBase.h | 8 +++++ .../domains/ellipsoid/codac2_Ellipsoid.cpp | 10 +++--- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 31 ++++++++++++------- src/core/matrices/codac2_MatrixBase.h | 8 +++++ src/core/matrices/codac2_VectorBase.h | 14 +++++++++ tests/CMakeLists.txt | 2 +- .../ellipsoid/codac2_tests_Ellipsoid.cpp | 1 - .../ellipsoid/codac2_tests_Ellipsoid.py | 20 ++++++++++++ 10 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.py diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index b92c99f4e..f95302b49 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -50,7 +50,7 @@ int main() { // particle cloud (draw the evolution of 200 points in the ellipsoid) int Np = 200; for (int i = 0; i < Np; i++) { - Vector x0 = e1.sample(); + Vector x0 = e1.rand(); fig1.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); for (int j = 0; j < N; j++) { x0 = h.eval(x0).mid(); @@ -102,7 +102,7 @@ int main() { // particle cloud (draw the evolution of 200 points in the ellipsoid e5) for (int i = 0; i < Np; i++) { - IntervalVector x5(e5.sample()); + IntervalVector x5(e5.rand()); x5.inflate(0.001); fig2.draw_box(x5, {Color::black(), Color::black(0.3)}); fig3.draw_box(x5, {Color::black(), Color::black(0.3)}); @@ -179,12 +179,12 @@ int main() { // particle cloud (draw the evolution of 200 points in the ellipsoid) for (int i = 0; i < Np; i++) { - Vector x0 = e9.sample(); + Vector x0 = e9.rand(); fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); x0 = h2.eval(x0).mid(); fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); - x0 = e10.sample(); + x0 = e10.rand(); fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); x0 = h3.eval(x0).mid(); fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); diff --git a/python/src/core/matrices/codac2_py_MatrixBase.h b/python/src/core/matrices/codac2_py_MatrixBase.h index eeacc5d4f..4a647c503 100644 --- a/python/src/core/matrices/codac2_py_MatrixBase.h +++ b/python/src/core/matrices/codac2_py_MatrixBase.h @@ -195,10 +195,18 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) .def_static("eye", [](size_t_type r, size_t_type c) { matlab::test_integer(r,c); - return S::ones(r,c); + return S::eye(r,c); }, STATIC_S_MATRIXBASE_ST_EYE_SIZET_SIZET, "r"_a, "c"_a) + + .def_static("random", [](size_t_type r, size_t_type c) + { + matlab::test_integer(r,c); + return S::random(r,c); + }, + STATIC_S_MATRIXBASE_ST_RANDOM_SIZET_SIZET, + "r"_a, "c"_a) ; } diff --git a/python/src/core/matrices/codac2_py_VectorBase.h b/python/src/core/matrices/codac2_py_VectorBase.h index 4d2cfadaf..bfe85c570 100644 --- a/python/src/core/matrices/codac2_py_VectorBase.h +++ b/python/src/core/matrices/codac2_py_VectorBase.h @@ -90,6 +90,14 @@ void export_VectorBase(py::module& m, py::class_& pyclass) }, STATIC_S_VECTORBASE_SMT_ONES_SIZET, "n"_a) + + .def_static("random", [](size_t_type n) + { + matlab::test_integer(n); + return S::random(n); + }, + STATIC_S_VECTORBASE_SMT_RANDOM_SIZET, + "n"_a) .def("__repr__", [](const S& x) { diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 544fd3c7f..409dfbc57 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -2,7 +2,7 @@ * codac2_Ellipsoid.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author + * \author Morgan Louedec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -30,10 +30,10 @@ namespace codac2 { return mu.size(); } - Vector Ellipsoid::sample() const{ - // chose a ramdom point in the ellipsoid - Vector xi(Eigen::VectorXd::Random(this->size())); - double rand_norm = ((double) rand() / (RAND_MAX)); + Vector Ellipsoid::rand() const + { + auto xi = Vector::random(this->size()); + double rand_norm = ((double) std::rand() / (RAND_MAX)); return this->mu._e + this->G._e * xi._e / xi._e.norm() * rand_norm; } diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index 2341ed006..5f4ffa324 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -2,7 +2,7 @@ * \file codac2_Ellipsoid.h * ---------------------------------------------------------------------------- * \date 2024 - * \author + * \author Morgan Louedec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -13,24 +13,33 @@ #include "codac2_Vector.h" #include "codac2_AnalyticFunction.h" -namespace codac2 { - - class Ellipsoid { +namespace codac2 +{ + class Ellipsoid + { public: - Ellipsoid(size_t n); + Ellipsoid(size_t n); - Ellipsoid(const Vector &mu_, const Matrix &G_); + Ellipsoid(const Vector &mu_, const Matrix &G_); - size_t size() const; + size_t size() const; - Vector sample() const; + /** + * \brief Returns a random vector inside the ellipsoid + * + * \note The seed of the pseudo-random number generator is + * voluntarily initialized outside this function, on demand. + * + * \return random value + */ + Vector rand() const; public: - Vector mu; - Matrix G; - }; + Vector mu; + Matrix G; + }; Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2); diff --git a/src/core/matrices/codac2_MatrixBase.h b/src/core/matrices/codac2_MatrixBase.h index b719df52d..c757547f0 100644 --- a/src/core/matrices/codac2_MatrixBase.h +++ b/src/core/matrices/codac2_MatrixBase.h @@ -270,6 +270,14 @@ namespace codac2 return EigenMatrix::Identity(r,c); } + // Note that this static function is not called "rand" + // because of ambiguity with the member function "rand" + static S random(size_t r, size_t c) + { + assert_release(r >= 0 && c >= 0); + return EigenMatrix::Random(r,c); + } + template friend std::ostream& operator<<(std::ostream& os, const MatrixBase& x); diff --git a/src/core/matrices/codac2_VectorBase.h b/src/core/matrices/codac2_VectorBase.h index 7340421ce..c918aab5a 100644 --- a/src/core/matrices/codac2_VectorBase.h +++ b/src/core/matrices/codac2_VectorBase.h @@ -93,18 +93,32 @@ namespace codac2 return diag; } + static S zeros(size_t r, size_t c) = delete; + static S zeros(size_t n) { assert_release(n >= 0); return EigenMatrix::Zero(n,1); } + static S ones(size_t r, size_t c) = delete; + static S ones(size_t n) { assert_release(n >= 0); return EigenMatrix::Ones(n,1); } + static S random(size_t r, size_t c) = delete; + + // Note that this static function is not called "rand" + // because of ambiguity with the member function "rand" + static S random(size_t n) + { + assert_release(n >= 0); + return EigenMatrix::Random(n,1); + } + }; template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3fe308dec..4bd8f43dd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -36,12 +36,12 @@ list(APPEND SRC_TESTS # listing files without extension core/contractors/codac2_tests_linear_ctc core/domains/codac2_tests_BoolInterval + core/domains/ellipsoid/codac2_tests_Ellipsoid core/domains/interval/codac2_tests_Interval core/domains/interval/codac2_tests_Interval_bwd core/domains/interval/codac2_tests_Interval_operations core/domains/interval/codac2_tests_IntervalMatrix core/domains/interval/codac2_tests_IntervalVector - core/domains/ellipsoid/codac2_tests_Ellipsoid core/functions/analytic/codac2_tests_AnalyticFunction diff --git a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp index b86722ae7..660fa45ca 100644 --- a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp +++ b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp @@ -1,6 +1,5 @@ /** * Codac tests - * * ---------------------------------------------------------------------------- * \date 2024 * \author Morgan Louedec, (Simon Rohou) diff --git a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.py b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.py new file mode 100644 index 000000000..5306df9e2 --- /dev/null +++ b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +# Codac tests +# ---------------------------------------------------------------------------- +# \date 2024 +# \author Morgan Louedec, (Simon Rohou) +# \copyright Copyright 2024 Codac Team +# \license GNU Lesser General Public License (LGPL) + +import unittest +from codac import * + +class TestEllipsoid(unittest.TestCase): + + def tests_Ellipsoid(self): + + self.assertTrue(True) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From 94539e95237bebfc3e341bb402c7927440e058e6 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 18 Oct 2024 10:34:50 +0200 Subject: [PATCH 012/126] [ellips] enclose_elli_by_box() -> hull_box() --- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 26 ++++++++----------- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 10 +++++-- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 409dfbc57..a4ba1ea47 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -37,6 +37,16 @@ namespace codac2 { return this->mu._e + this->G._e * xi._e / xi._e.norm() * rand_norm; } + IntervalVector Ellipsoid::hull_box() const + { + IntervalVector hull(size()); + for(size_t i=0; i< size(); i++){ + double m = G._e.col(i).norm(); + hull[i] = Interval(-m, m); + } + return hull; + } + Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2) { assert_release(e1.size() == e2.size()); @@ -163,8 +173,7 @@ namespace codac2 { Matrix J = f.diff(e.mu).mid(); // compute the Jacobian of f at the center // compute the Jacobian of f over a box enclosing the ellipsoid - IntervalVector enclosing_box = enclose_elli_by_box(e); - IntervalMatrix J_box = f.diff(enclosing_box); + IntervalMatrix J_box = f.diff(e.hull_box()); Matrix E_out = nonlinear_mapping_base(e.G, J, J_box,trig,q); return Ellipsoid(mu_res, E_out); @@ -249,19 +258,6 @@ namespace codac2 { return true; } - IntervalVector enclose_elli_by_box(const Ellipsoid& e) - { - // compute the tightest axis aligned box containing e - // |xi|<||Gamma_i| (i_th column bcs symetric) - // xi = Gamma_i*y with |y|<1, y = Gamma_inv*x in the unit circle - IntervalVector res(e.size()); - for(int i=0; i Date: Fri, 18 Oct 2024 11:20:00 +0200 Subject: [PATCH 013/126] [ellips] concentric_inclusion_test() -> is_concentric_subset() --- examples/ellipsoid_example/main.cpp | 16 ++- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 100 +++++++++--------- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 16 ++- .../ellipsoid/codac2_tests_Ellipsoid.cpp | 12 +-- 4 files changed, 70 insertions(+), 74 deletions(-) diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index f95302b49..39ed15421 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -113,17 +113,13 @@ int main() { // inclusion tests // ---------------------------------------------------------- - bool res1 = concentric_inclusion_test(e5, e4); - cout << "\nInclusion test e5 in e4: " << res1 << endl; + cout << "\nInclusion test e5 in e4: " << e5.is_concentric_subset(e4) << endl; - bool res2 = concentric_inclusion_test(e4, e5); - cout << "Inclusion test e4 in e5: " << res2 << endl; + cout << "Inclusion test e4 in e5: " << e4.is_concentric_subset(e5) << endl; - bool res3 = concentric_inclusion_test(e6, e4); - cout << "Inclusion test e4 in e6: " << res3 << endl; + cout << "Inclusion test e4 in e6: " << e6.is_concentric_subset(e4) << endl; - bool res4 = concentric_inclusion_test(e5, e6); - cout << "Inclusion test e5 in e6: " << res4 << endl; + cout << "Inclusion test e5 in e6: " << e5.is_concentric_subset(e6) << endl; // ---------------------------------------------------------- // guaranteed and non guaranteed linear mappings @@ -200,8 +196,8 @@ int main() { Ellipsoid e13(Vector(2), Matrix(2,2)); Ellipsoid e13_out(Vector(2), Matrix(2,2)); int alpha_max = 1; - bool res = stability_analysis(h4,alpha_max, e13, e13_out); - if(res) + + if(stability_analysis(h4,alpha_max, e13, e13_out) == BoolInterval::TRUE) { cout << "\nStability analysis: the system is stable" << endl; cout << "Ellipsoidal domain of attraction e13 (red):" << endl; diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index a4ba1ea47..975576f18 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -47,6 +47,46 @@ namespace codac2 { return hull; } + BoolInterval Ellipsoid::is_concentric_subset(const Ellipsoid& e) const + { + assert_release(size() == e.size()); + + if((mu._e - e.mu._e).norm() > 1e-10) + return BoolInterval::FALSE; // check if the centers are the same + + auto I = Matrix::eye(size(),size()); + auto G2_inv = e.G._e.inverse(); + IntervalMatrix D(I._e - G._e.transpose() * G2_inv.transpose() * G2_inv * G._e); + + // cholesky decomposition of D = L*L^T + IntervalMatrix L(size(),size()); // matrix of the Cholesky decomposition + + for (size_t j = 0; j < size(); j++) // for every column + { + // diagonal element + Interval s = 0.; + for (size_t k = 0; k < j; k++) + s += L(j, k) * L(j, k); + Interval u = D(j, j) - s; + if (u.lb() < 0) { + return BoolInterval::UNKNOWN; // cannot guarantee that D is positive definite + } + L(j,j) = sqrt(u); + + // then the rest of the column + for (size_t i = j + 1; i& f,const Vector& trig, const Vector& q) { // compute an outer ellipsoidal enclosure of f(e) - assert(e.size() == f.input_size()); - assert(trig.size() == 2); - assert(q.size() == e.size()); + assert_release(e.size() == f.input_size()); + assert_release(trig.size() == 2); + assert_release(q.size() == e.size()); Vector mu_res = f.eval(e.mu).mid(); // compute the image of the center Matrix J = f.diff(e.mu).mid(); // compute the Jacobian of f at the center @@ -175,15 +215,14 @@ namespace codac2 { // compute the Jacobian of f over a box enclosing the ellipsoid IntervalMatrix J_box = f.diff(e.hull_box()); - Matrix E_out = nonlinear_mapping_base(e.G, J, J_box,trig,q); - return Ellipsoid(mu_res, E_out); + return Ellipsoid(mu_res, nonlinear_mapping_base(e.G, J, J_box,trig,q)); } std::ostream &operator<<(std::ostream &os, const Ellipsoid &e) { return os << "mu : " << e.mu << "\n" << "G :\n" << e.G; } - bool stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out) + BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out) { // get the Jacobian of f at the origin int n = f.input_size(); @@ -194,7 +233,6 @@ namespace codac2 { Matrix P = solve_discrete_lyapunov(J.transpose(),J.transpose()*J); // TODO solve the Lyapunov equation !!! Matrix G0((P._e.inverse()).sqrt()); int alpha = 0; - bool res = false; while(alpha <= alpha_max) { @@ -204,58 +242,16 @@ namespace codac2 { cout << "e is\n" << e << endl; cout << "e_out is\n" << e_out << endl; - res = concentric_inclusion_test(e_out,e); - if(res) + if(e_out.is_concentric_subset(e) == BoolInterval::TRUE) { cout << "The system is stable" << endl; cout << "Domain of attraction :\n" << e_out << endl; - return true; + return BoolInterval::TRUE; } alpha++; } cout << "The method is not able to conclude on the stability" << endl; - return false; - } - - bool concentric_inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2) { - // check if e1 included in e2, assuming that the centers are the same - assert(e1.size() == e2.size()); - assert((e1.mu._e - e2.mu._e).norm() < 1e-10); // check if the centers are the same - - auto G2_inv = e2.G._e.inverse(); - Matrix I(Eigen::MatrixXd::Identity(e2.G.nb_rows(), e2.G.nb_cols())); - IntervalMatrix D(I._e - e1.G._e.transpose() * G2_inv.transpose() * G2_inv * e1.G._e); - - // cholesky decomposition of D = L*L^T - IntervalMatrix L(e1.size(), e1.size()); // matrix of the Cholesky decomposition - - Interval S(0, 0); - Interval U(0, 0); - - for (int j = 0; j < (int)e1.size(); j++) // for every column - { - // diagonal element - S = Interval(0, 0); - for (int k = 0; k < j; k++) - S += L(j, k) * L(j, k); - U = D(j, j) - S; - if (U.lb() < 0) { - return false; // cannot guarantee that D is positive definite - } - L(j,j) = sqrt(U); - - // then the rest of the column - for (int i = j + 1; i<(int)e1.size(); - i++) - { - S = Interval(0, 0); - for (int k = 0; k < j; k++) - S += L(j,k) * L(i,k); - L(i,j) = (D(i,j) - S) / L(j,j); - L(j,i) = Interval(0, 0); - } - } - return true; + return BoolInterval::UNKNOWN; } Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index 23bbe75af..a94ca380d 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -12,6 +12,7 @@ #include "codac2_Matrix.h" #include "codac2_Vector.h" #include "codac2_AnalyticFunction.h" +#include "codac2_BoolInterval.h" namespace codac2 { @@ -42,6 +43,16 @@ namespace codac2 */ IntervalVector hull_box() const; + + /** + * \brief Compute if the provided ellipsoid is a subset of this ellipsoid, + * provided that the two ellipsoids share the same center + * + * \param e the second ellipsoid of same dimension + * \return a BoolInterval + */ + BoolInterval is_concentric_subset(const Ellipsoid& e) const; + public: Vector mu; @@ -68,10 +79,7 @@ namespace codac2 std::ostream &operator<<(std::ostream &os, const Ellipsoid &e); - bool stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out); - - bool concentric_inclusion_test(const Ellipsoid &e1, const Ellipsoid &e2); - + BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out); Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q); diff --git a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp index 660fa45ca..d26626a03 100644 --- a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp +++ b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp @@ -71,14 +71,10 @@ TEST_CASE("Ellipsoids") Ellipsoid e5_ = e5(); Ellipsoid e6_ = e6(); - bool res1 = concentric_inclusion_test(e5_, e4_); - bool res2 = concentric_inclusion_test(e4_, e5_); - bool res3 = concentric_inclusion_test(e6_, e4_); - bool res4 = concentric_inclusion_test(e5_, e6_); - CHECK(res1 == true); - CHECK(res2 == false); - CHECK(res3 == false); - CHECK(res4 == false); + CHECK(e5_.is_concentric_subset(e4_) == BoolInterval::TRUE); + CHECK(e4_.is_concentric_subset(e5_) == BoolInterval::UNKNOWN); + CHECK(e6_.is_concentric_subset(e4_) == BoolInterval::UNKNOWN); + CHECK(e5_.is_concentric_subset(e6_) == BoolInterval::UNKNOWN); Matrix A2({{0.9,0.5},{-.5,1.1}}); Vector b2({0.1,0.2}); From be5c04552b36deeb8d4335c9c2d7f1114d7e51df Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 18 Oct 2024 12:55:54 +0200 Subject: [PATCH 014/126] [ellips] linear_mapping_guaranteed() vs unreliable_linear_mapping() --- src/core/domains/ellipsoid/codac2_Ellipsoid.cpp | 9 ++++++--- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 975576f18..84c529b5d 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -106,7 +106,7 @@ namespace codac2 { ); } - Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b) { + Ellipsoid unreliable_linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b) { // return A*e+b | non-rigorous operations auto mu_res = A._e * e.mu._e + b._e; auto G_res = A._e * e.G._e; @@ -114,9 +114,9 @@ namespace codac2 { return res; } - Ellipsoid linear_mapping_guaranteed(const Ellipsoid &e, const Matrix &A, const Vector &b) { + Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b) { // compute en outer enclosure of A*e+b, considering the rounding error with pessimism - Ellipsoid e_res = linear_mapping(e, A, b); + Ellipsoid e_res = unreliable_linear_mapping(e, A, b); // compute rounding error as a small box IntervalVector mu_(e.mu); @@ -205,6 +205,7 @@ namespace codac2 { Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f,const Vector& trig, const Vector& q) { // compute an outer ellipsoidal enclosure of f(e) + assert_release(f.args().size() == 1 && "f must have only one arg"); assert_release(e.size() == f.input_size()); assert_release(trig.size() == 2); assert_release(q.size() == e.size()); @@ -224,6 +225,8 @@ namespace codac2 { BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out) { + assert_release(f.args().size() == 1 && "f must have only one arg"); + // get the Jacobian of f at the origin int n = f.input_size(); Vector origin(Eigen::VectorXd::Zero(n)); diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index a94ca380d..beb35f339 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -62,9 +62,9 @@ namespace codac2 Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2); - Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b); + Ellipsoid unreliable_linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b); - Ellipsoid linear_mapping_guaranteed(const Ellipsoid &e, const Matrix &A, const Vector &b); + Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b); Ellipsoid nonlinear_mapping_base(const Ellipsoid &e, const Matrix &J, const IntervalMatrix &J_box, From 3b929d082d667c125fd87553a0bfb1543f1d7031 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 18 Oct 2024 15:39:19 +0200 Subject: [PATCH 015/126] [ellips] optimizing computations (casts, etc.) --- examples/ellipsoid_example/main.cpp | 6 +- src/core/CMakeLists.txt | 2 + .../domains/ellipsoid/codac2_Ellipsoid.cpp | 144 ++++++------------ src/core/domains/ellipsoid/codac2_Ellipsoid.h | 13 +- .../ellipsoid/codac2_Ellipsoid_utils.cpp | 68 +++++++++ .../ellipsoid/codac2_Ellipsoid_utils.h | 19 +++ .../ellipsoid/codac2_tests_Ellipsoid.cpp | 6 +- 7 files changed, 153 insertions(+), 105 deletions(-) create mode 100644 src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp create mode 100644 src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index 39ed15421..b6b9ed8c9 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -32,7 +32,7 @@ int main() { for (int i = 0; i < N; i++) { Matrix A = h.diff(e2.mu).mid(); Vector b(h.eval(e2.mu).mid()._e - A._e * e2.mu._e); - e2 = linear_mapping(e2, A, b); + e2 = unreliable_linear_mapping(e2, A, b); fig1.draw_ellipsoid(e2, {Color::green(), Color::green(0.3)}); } cout << "\nLinear Mapping - Image ellipsoid e2 (green):" << endl; @@ -128,8 +128,8 @@ int main() { {-.5, 1.1}}); Vector b({0.1, 0.2}); - Ellipsoid e7 = linear_mapping(e1, A, b); - Ellipsoid e8 = linear_mapping_guaranteed(e1, A, b); + Ellipsoid e7 = unreliable_linear_mapping(e1, A, b); + Ellipsoid e8 = linear_mapping(e1, A, b); cout << "\nLinear Mapping - Image ellipsoid e7:" << endl; cout << e7 << endl; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 958af6e42..4d06ccf7c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -43,6 +43,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/domains/codac2_Domain.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid.h + ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid_utils.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/domains/ellipsoid/codac2_Ellipsoid_utils.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval.cpp ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval.h ${CMAKE_CURRENT_SOURCE_DIR}/domains/interval/codac2_Interval_operations.cpp diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 84c529b5d..f583fc2d0 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -8,7 +8,6 @@ */ #include -#include #include "codac2_Ellipsoid.h" #include "codac2_template_tools.h" @@ -23,7 +22,7 @@ namespace codac2 { Ellipsoid::Ellipsoid(const Vector &mu_, const Matrix &G_) : mu(mu_), G(G_) { - assert_release(mu_.size() == G_.nb_cols() && mu_.size() == G_.nb_rows()); + assert_release(mu_.size() == G_.nb_cols() && G_.is_squared()); } size_t Ellipsoid::size() const { @@ -49,19 +48,21 @@ namespace codac2 { BoolInterval Ellipsoid::is_concentric_subset(const Ellipsoid& e) const { - assert_release(size() == e.size()); + size_t n = size(); + assert_release(n == e.size()); + - if((mu._e - e.mu._e).norm() > 1e-10) - return BoolInterval::FALSE; // check if the centers are the same + if((mu._e - e.mu._e).norm() > 1e-10) // check if the centers are the same + return BoolInterval::FALSE; // not concentric - auto I = Matrix::eye(size(),size()); + auto I = Matrix::eye(n,n); auto G2_inv = e.G._e.inverse(); IntervalMatrix D(I._e - G._e.transpose() * G2_inv.transpose() * G2_inv * G._e); // cholesky decomposition of D = L*L^T - IntervalMatrix L(size(),size()); // matrix of the Cholesky decomposition + IntervalMatrix L(n,n); // matrix of the Cholesky decomposition - for (size_t j = 0; j < size(); j++) // for every column + for (size_t j = 0; j < n; j++) // for every column { // diagonal element Interval s = 0.; @@ -74,7 +75,7 @@ namespace codac2 { L(j,j) = sqrt(u); // then the rest of the column - for (size_t i = j + 1; i(); + auto e_res_mu_ = e_res.mu._e.template cast(); + auto e_res_G_ = e_res.G._e.template cast(); + auto e_G_ = e.G._e.template cast(); + auto A_ = A._e.template cast(); + auto b_ = b._e.template cast(); + IntervalVector unit_box_(n, {-1,1}); + // compute rounding error as a small box - IntervalVector mu_(e.mu); - IntervalVector mu_res_(e_res.mu); - IntervalMatrix G_(e.G); - IntervalMatrix G_res_(e_res.G); - IntervalMatrix A_(A); - IntervalVector b_(b); - IntervalVector unit_box_(mu_.size(), Interval(-1, 1)); - - auto mu_res_guaranteed = A_._e * mu_._e + b_._e; - auto G_res_guaranteed = A_._e * G_._e; - auto error_box_ = mu_res_guaranteed - mu_res_._e + - (G_res_guaranteed - G_res_._e) * unit_box_._e; - - double rho = Interval(error_box_.norm()).ub(); // max radius of error_box - Ellipsoid elli_error(Vector(e.size()), - Eigen::MatrixXd::Identity(e.size(),e.size()) * rho); // = rho*unit_ball + auto mu_res_guaranteed = A_ * e_mu_ + b_; + auto G_res_guaranteed = A_ * e_G_; + auto error_box_ = mu_res_guaranteed - e_res_mu_ + + (G_res_guaranteed - e_res_G_) * unit_box_._e; + + double rho = error_box_.norm().ub(); // max radius of error_box + Ellipsoid elli_error(Vector::zeros(n), + Matrix::eye(n,n) * rho); // = rho*unit_ball return e_res + elli_error; } Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box, const Vector& trig, const Vector& q) { - /* nonsingular main case from - * Rauh, A., & Jaulin, L. (2021). - * "A computationally inexpensive algorithm for determining outer - * and inner enclosures of nonlinear mappings of ellipsoidal domains. - * International Journal of Applied Mathematics and Computer Science, 31(3).*/ Matrix JG = J * G; IntervalMatrix G_(G); @@ -193,86 +196,37 @@ namespace codac2 { } auto b_box = (W * J_box._e * G_._e - Z) * unit_box._e; - double rho = Interval(b_box.norm()).ub(); // max radius of b_box + double rho = b_box.norm().ub(); // max radius of b_box return (1 + rho) * M; } Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f) { - return nonlinear_mapping(e,f,Vector({1e-10,1e-9}),Vector(Eigen::VectorXd::Ones(e.size()))); + return nonlinear_mapping(e,f,Vector({1e-10,1e-9}),Vector::ones(e.size())); } Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction& f,const Vector& trig, const Vector& q) { - // compute an outer ellipsoidal enclosure of f(e) assert_release(f.args().size() == 1 && "f must have only one arg"); assert_release(e.size() == f.input_size()); assert_release(trig.size() == 2); assert_release(q.size() == e.size()); - Vector mu_res = f.eval(e.mu).mid(); // compute the image of the center Matrix J = f.diff(e.mu).mid(); // compute the Jacobian of f at the center // compute the Jacobian of f over a box enclosing the ellipsoid IntervalMatrix J_box = f.diff(e.hull_box()); - return Ellipsoid(mu_res, nonlinear_mapping_base(e.G, J, J_box,trig,q)); + return { + f.eval(e.mu).mid(), // mu: compute the image of the center + nonlinear_mapping_base(e.G, J, J_box,trig,q) // G + }; } std::ostream &operator<<(std::ostream &os, const Ellipsoid &e) { return os << "mu : " << e.mu << "\n" << "G :\n" << e.G; } - BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out) - { - assert_release(f.args().size() == 1 && "f must have only one arg"); - - // get the Jacobian of f at the origin - int n = f.input_size(); - Vector origin(Eigen::VectorXd::Zero(n)); - Matrix J = f.diff(IntervalVector(origin)).mid(); - - // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J - Matrix P = solve_discrete_lyapunov(J.transpose(),J.transpose()*J); // TODO solve the Lyapunov equation !!! - Matrix G0((P._e.inverse()).sqrt()); - int alpha = 0; - - while(alpha <= alpha_max) - { - e = Ellipsoid(origin, std::pow(10,-alpha) * G0); - e_out = nonlinear_mapping(e,f); - cout << "\nwith alpha = " << alpha << endl; - cout << "e is\n" << e << endl; - cout << "e_out is\n" << e_out << endl; - - if(e_out.is_concentric_subset(e) == BoolInterval::TRUE) - { - cout << "The system is stable" << endl; - cout << "Domain of attraction :\n" << e_out << endl; - return BoolInterval::TRUE; - } - alpha++; - } - cout << "The method is not able to conclude on the stability" << endl; - return BoolInterval::UNKNOWN; - } - - Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q) - { - // implementation of the scipy solver for the discrete lyapunov equation (real matrix only) - // works well under dimension 10 - // https://github.com/scipy/scipy/blob/v1.14.1/scipy/linalg/_solvers.py#L235-L323 - // Solves the discrete Lyapunov equation :math:`AXA^H - X + Q = 0` - assert(a.nb_rows() == a.nb_cols()); - assert(a.nb_rows() == q.nb_rows()); - assert(a.nb_cols() == q.nb_cols()); - - Eigen::MatrixXd lhs = Eigen::KroneckerProduct(a._e, a._e); - lhs = Eigen::MatrixXd::Identity(lhs.rows(),lhs.cols()) - lhs; - Eigen::MatrixXd x = lhs.colPivHouseholderQr().solve((Eigen::VectorXd)q._e.reshaped()); - return Matrix(x.reshaped(q.nb_rows(),q.nb_cols())); - } - // Old implementations: #if 0 diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index beb35f339..170ca50a3 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -62,16 +62,25 @@ namespace codac2 Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2); + // return A*e+b | non-rigorous operations Ellipsoid unreliable_linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b); + // compute en outer enclosure of A*e+b, considering the rounding error with pessimism Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b); + /* nonsingular main case from + * Rauh, A., & Jaulin, L. (2021). + * "A computationally inexpensive algorithm for determining outer + * and inner enclosures of nonlinear mappings of ellipsoidal domains. + * International Journal of Applied Mathematics and Computer Science, 31(3).*/ Ellipsoid nonlinear_mapping_base(const Ellipsoid &e, const Matrix &J, const IntervalMatrix &J_box, const Vector& trig1, const Vector& q); Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction &f); + + // compute an outer ellipsoidal enclosure of f(e) Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction &f, const Vector& trig,const Vector& q); @@ -79,8 +88,4 @@ namespace codac2 std::ostream &operator<<(std::ostream &os, const Ellipsoid &e); - BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out); - - Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q); - } \ No newline at end of file diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp new file mode 100644 index 000000000..675779152 --- /dev/null +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp @@ -0,0 +1,68 @@ +/** + * codac2_Ellipsoid.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Morgan Louedec + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include "codac2_Ellipsoid_utils.h" + +using namespace std; +using namespace codac2; + +namespace codac2 +{ + Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q) + { + // implementation of the scipy solver for the discrete lyapunov equation (real matrix only) + // works well under dimension 10 + // https://github.com/scipy/scipy/blob/v1.14.1/scipy/linalg/_solvers.py#L235-L323 + // Solves the discrete Lyapunov equation :math:`AXA^H - X + Q = 0` + assert(a.nb_rows() == a.nb_cols()); + assert(a.nb_rows() == q.nb_rows()); + assert(a.nb_cols() == q.nb_cols()); + + Eigen::MatrixXd lhs = Eigen::KroneckerProduct(a._e, a._e); + lhs = Eigen::MatrixXd::Identity(lhs.rows(),lhs.cols()) - lhs; + Eigen::MatrixXd x = lhs.colPivHouseholderQr().solve((Eigen::VectorXd)q._e.reshaped()); + return Matrix(x.reshaped(q.nb_rows(),q.nb_cols())); + } + + BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out) + { + assert_release(f.args().size() == 1 && "f must have only one arg"); + + // get the Jacobian of f at the origin + int n = f.input_size(); + Vector origin(Eigen::VectorXd::Zero(n)); + Matrix J = f.diff(IntervalVector(origin)).mid(); + + // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J + Matrix P = solve_discrete_lyapunov(J.transpose(),J.transpose()*J); // TODO solve the Lyapunov equation !!! + Matrix G0((P._e.inverse()).sqrt()); + int alpha = 0; + + while(alpha <= alpha_max) + { + e = Ellipsoid(origin, std::pow(10,-alpha) * G0); + e_out = nonlinear_mapping(e,f); + cout << "\nwith alpha = " << alpha << endl; + cout << "e is\n" << e << endl; + cout << "e_out is\n" << e_out << endl; + + if(e_out.is_concentric_subset(e) == BoolInterval::TRUE) + { + cout << "The system is stable" << endl; + cout << "Domain of attraction :\n" << e_out << endl; + return BoolInterval::TRUE; + } + alpha++; + } + cout << "The method is not able to conclude on the stability" << endl; + return BoolInterval::UNKNOWN; + } +} \ No newline at end of file diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h new file mode 100644 index 000000000..f12e0831d --- /dev/null +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h @@ -0,0 +1,19 @@ +/** + * \file codac2_Ellipsoid_utils.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Morgan Louedec + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_Ellipsoid.h" + +namespace codac2 +{ + BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out); + + Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q); +} \ No newline at end of file diff --git a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp index d26626a03..d252b5ecb 100644 --- a/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp +++ b/tests/core/domains/ellipsoid/codac2_tests_Ellipsoid.cpp @@ -53,7 +53,7 @@ TEST_CASE("Ellipsoids") Matrix A = h.diff(e.mu).mid(); Vector b(h.eval(e.mu).mid()._e - A._e*e.mu._e); - Ellipsoid e2 = linear_mapping(e, A, b); + Ellipsoid e2 = unreliable_linear_mapping(e, A, b); Vector mu2({1 , -0.168294}); Matrix G2({{0.0500001 , 0.00500001},{-0.00540302 , 0.0450001}}); CHECK(e2.size() == 2); @@ -79,8 +79,8 @@ TEST_CASE("Ellipsoids") Matrix A2({{0.9,0.5},{-.5,1.1}}); Vector b2({0.1,0.2}); - Ellipsoid e7 = linear_mapping(e, A2, b2); - Ellipsoid e8 = linear_mapping_guaranteed(e, A2, b2); + Ellipsoid e7 = unreliable_linear_mapping(e, A2, b2); + Ellipsoid e8 = linear_mapping(e, A2, b2); CHECK((e7.mu._e - e8.mu._e).norm()<1e-6); CHECK((e7.G._e - e8.G._e).norm()<0.04); From b7de09381a8ef274b33c9df99a36dde65b9f5f89 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 18 Oct 2024 16:20:06 +0200 Subject: [PATCH 016/126] [ellips] asserts and documentation --- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 19 ++- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 159 +++++++++++++----- .../ellipsoid/codac2_Ellipsoid_utils.cpp | 2 +- .../ellipsoid/codac2_Ellipsoid_utils.h | 22 ++- 4 files changed, 155 insertions(+), 47 deletions(-) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index f583fc2d0..1cf112472 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -2,7 +2,7 @@ * codac2_Ellipsoid.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author Morgan Louedec + * \author Morgan Louédec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -148,7 +148,12 @@ namespace codac2 { Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box, const Vector& trig, const Vector& q) { - Matrix JG = J * G; + size_t n = G.nb_cols(); + + assert(G.is_squared() && J.is_squared() && J_box.is_squared()); + assert(n == J.nb_cols() && n == J_box.nb_cols() && n == q.size()); + + Matrix JG = J * G; // note: reliability may be lost here! IntervalMatrix G_(G); IntervalMatrix JG_ = IntervalMatrix(JG); IntervalVector unit_box(G.nb_rows(), Interval(-1, 1)); @@ -223,9 +228,13 @@ namespace codac2 { }; } - std::ostream &operator<<(std::ostream &os, const Ellipsoid &e) { - return os << "mu : " << e.mu << "\n" << "G :\n" << e.G; - } + ostream& operator<<(ostream& os, const Ellipsoid& e) + { + os << "Ellipsoid:\n" + << " mu=" << e.mu << "\n" + << " G=\n" << e.G; + return os; + } // Old implementations: diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index 170ca50a3..80ced6cf1 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -2,7 +2,7 @@ * \file codac2_Ellipsoid.h * ---------------------------------------------------------------------------- * \date 2024 - * \author Morgan Louedec + * \author Morgan Louédec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -16,26 +16,64 @@ namespace codac2 { + /** + * \brief Ellipsoid representation + * + * References: + * + * Concentric subset test and degenerate computations are inspired by the + * work of Morgan Louedec. Concepts and algorithms are provided in: + * + * Stability analysis of the formation control of a group of + * underwater robots, with ellipsoidal enclosure. + * Morgan Louédec, 2024 + * PhD thesis, Université de Bretagne Occidentale, Brest, France. + * https://morgan-louedec.fr/thesis-of-morgan-louedec + * + * Non-linear mapping of the nonsingular main case is inspired by: + * + * A computationally inexpensive algorithm for determining outer + * and inner enclosures of nonlinear mappings of ellipsoidal domains. + * Andreas Rauh, Luc Jaulin + * 2021, International Journal of Applied Mathematics and Computer Science, + * doi: https://doi.org/10.34768/amcs-2021-0027 + */ class Ellipsoid { public: + /** + * \brief Create a n-dimensional ellipsoid + * + * \param n number of dimensions + */ Ellipsoid(size_t n); - Ellipsoid(const Vector &mu_, const Matrix &G_); + /** + * \brief Create an ellipsoid from a center and a shape matrix + * + * \param mu midpoint vector + * \param G shape matrix + */ + Ellipsoid(const Vector& mu, const Matrix& G); + /** + * \brief Return the dimension of the ellipsoid + * + * \return number of dimensions + */ size_t size() const; /** - * \brief Returns a random vector inside this ellipsoid + * \brief Return a random vector inside this ellipsoid * * \note The seed of the pseudo-random number generator is * voluntarily initialized outside this function, on demand. * - * \return random value + * \return random vector value */ Vector rand() const; - + /** * \brief Compute the tightest axis-aligned box containing this ellipsoid * @@ -43,9 +81,8 @@ namespace codac2 */ IntervalVector hull_box() const; - /** - * \brief Compute if the provided ellipsoid is a subset of this ellipsoid, + * \brief Test if the provided ellipsoid is a subset of this ellipsoid, * provided that the two ellipsoids share the same center * * \param e the second ellipsoid of same dimension @@ -55,37 +92,83 @@ namespace codac2 public: - Vector mu; - Matrix G; + Vector mu; ///< midpoint vector + Matrix G; ///< shape matrix }; - - Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2); - - // return A*e+b | non-rigorous operations - Ellipsoid unreliable_linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b); - - // compute en outer enclosure of A*e+b, considering the rounding error with pessimism - Ellipsoid linear_mapping(const Ellipsoid &e, const Matrix &A, const Vector &b); - - /* nonsingular main case from - * Rauh, A., & Jaulin, L. (2021). - * "A computationally inexpensive algorithm for determining outer - * and inner enclosures of nonlinear mappings of ellipsoidal domains. - * International Journal of Applied Mathematics and Computer Science, 31(3).*/ - - Ellipsoid nonlinear_mapping_base(const Ellipsoid &e, const Matrix &J, const IntervalMatrix &J_box, - const Vector& trig1, - const Vector& q); - - Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction &f); - - // compute an outer ellipsoidal enclosure of f(e) - Ellipsoid nonlinear_mapping(const Ellipsoid &e, const AnalyticFunction &f, - const Vector& trig,const Vector& q); - - - - std::ostream &operator<<(std::ostream &os, const Ellipsoid &e); - + /** + * \brief Compute the Minkowski sum of two ellipsoids + * + * \param e1 first ellipsoid + * \param e2 second ellipsoid + * \return the Minkowski sum + */ + Ellipsoid operator+(const Ellipsoid& e1, const Ellipsoid& e2); + + /** + * \brief Guaranteed linear evaluation A*e+b, + * considering the rounding errors + * + * \param e input ellipsoid + * \param A matrix + * \param b vector + * \return a rigorous outer enclosure of the linear mapping + */ + Ellipsoid linear_mapping(const Ellipsoid& e, const Matrix& A, const Vector& b); + + /** + * \brief Nonrigorous linear evaluation A*e+b + * + * \note This function is used in linear_mapping() and provides + * a faster output than its guaranteed counterpart. + * + * \param e input ellipsoid + * \param A matrix + * \param b vector + * \return a nonrigorous approximation of the linear mapping + */ + Ellipsoid unreliable_linear_mapping(const Ellipsoid& e, const Matrix& A, const Vector& b); + + /** + * \brief (Rigorous?) non-linear evaluation f(e) + * + * \param e input ellipsoid + * \param f non-linear analytical function + * \return a (rigorous?) outer enclosure of the non-linear mapping + */ + Ellipsoid nonlinear_mapping(const Ellipsoid& e, const AnalyticFunction& f); + + /** + * \brief (Rigorous?) non-linear evaluation f(e), with parameters + * + * \param e input ellipsoid + * \param f non-linear analytical function + * \param trig (?) + * \param q (?) + * \return a (rigorous?) outer enclosure of the non-linear mapping + */ + Ellipsoid nonlinear_mapping(const Ellipsoid& e, const AnalyticFunction& f, + const Vector& trig, const Vector& q); + + /** + * \brief (Rigorous?) non-linear evaluation f(e), from Jacobian information + * + * \param e input ellipsoid + * \param J approximated Jacobian matrix of f + * \param J_box reliable enclosure of the Jacobian matrix of f + * \param trig (?) + * \param q (?) + * \return a (rigorous?) outer enclosure of the non-linear mapping + */ + Ellipsoid nonlinear_mapping_base(const Ellipsoid& e, const Matrix& J, const IntervalMatrix& J_box, + const Vector& trig, const Vector& q); + + /** + * \brief Streams out an Ellipsoid + * + * \param os the stream to be updated + * \param x the ellipsoid stream out + * \return a reference to the updated stream + */ + std::ostream& operator<<(std::ostream& os, const Ellipsoid& e); } \ No newline at end of file diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp index 675779152..85eca7354 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp @@ -2,7 +2,7 @@ * codac2_Ellipsoid.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author Morgan Louedec + * \author Morgan Louédec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h index f12e0831d..48265836b 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h @@ -2,7 +2,7 @@ * \file codac2_Ellipsoid_utils.h * ---------------------------------------------------------------------------- * \date 2024 - * \author Morgan Louedec + * \author Morgan Louédec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -13,7 +13,23 @@ namespace codac2 { - BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out); + /** + * \brief ... + * + * \param f ... + * \param alpha_max ... + * \param e ... + * \param e_out ... + * \return ... + */ + BoolInterval stability_analysis(const AnalyticFunction& f, int alpha_max, Ellipsoid& e, Ellipsoid& e_out); - Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q); + /** + * \brief ... + * + * \param a ... + * \param q ... + * \return ... + */ + Matrix solve_discrete_lyapunov(const Matrix& a, const Matrix& q); } \ No newline at end of file From f568bdd715d9b9465f91d371c1edeb842f344769 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 18 Oct 2024 17:15:44 +0200 Subject: [PATCH 017/126] [mat] added norm, squared_norm --- python/src/core/matrices/codac2_py_MatrixBase.h | 12 ++++++++++++ src/core/matrices/codac2_MatrixBase.h | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/python/src/core/matrices/codac2_py_MatrixBase.h b/python/src/core/matrices/codac2_py_MatrixBase.h index 4a647c503..407bfb025 100644 --- a/python/src/core/matrices/codac2_py_MatrixBase.h +++ b/python/src/core/matrices/codac2_py_MatrixBase.h @@ -65,6 +65,18 @@ void export_MatrixBase(py::module& m, py::class_& pyclass) }, T_MATRIXBASE_ST_MAX_COEFF_CONST) + .def("norm", [](const S& x) + { + return x.norm(); + }, + T_MATRIXBASE_ST_NORM_CONST) + + .def("squared_norm", [](const S& x) + { + return x.squared_norm(); + }, + T_MATRIXBASE_ST_SQUARED_NORM_CONST) + ; if constexpr(!VECTOR_INHERITANCE) diff --git a/src/core/matrices/codac2_MatrixBase.h b/src/core/matrices/codac2_MatrixBase.h index c757547f0..a675dcad1 100644 --- a/src/core/matrices/codac2_MatrixBase.h +++ b/src/core/matrices/codac2_MatrixBase.h @@ -161,6 +161,16 @@ namespace codac2 minmax_item(max); } + T norm() const + { + return _e.norm(); + } + + T squared_norm() const + { + return _e.squaredNorm(); + } + friend bool operator==(const MatrixBase& x1, const MatrixBase& x2) { if(x1.nb_rows() != x2.nb_rows() || x1.nb_cols() != x2.nb_cols()) From cfcb2c84d3e488a7c02249c37714642fedd17354 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 18 Oct 2024 17:16:07 +0200 Subject: [PATCH 018/126] [ellips] Python binding --- examples/ellipsoid_example/main.cpp | 12 +- examples/ellipsoid_example/main.py | 215 ++++++++++++++++++ python/codac/core/__init__.py | 11 +- python/src/core/CMakeLists.txt | 1 + python/src/core/codac2_py_core.cpp | 2 + .../domains/ellipsoid/codac2_py_Ellipsoid.cpp | 91 ++++++++ .../graphics/figures/codac2_py_Figure2D.cpp | 14 +- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 8 +- 8 files changed, 342 insertions(+), 12 deletions(-) create mode 100644 examples/ellipsoid_example/main.py create mode 100644 python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index b6b9ed8c9..dff50e734 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -9,7 +9,7 @@ int main() { // ---------------------------------------------------------- Figure2D fig1("Linear and nonlinear mappings", GraphicOutput::VIBES); - fig1.set_axes(FigureAxis(0, {0, 1.5}), FigureAxis(1, {-1., 0.5})); + fig1.set_axes(axis(0, {0, 1.5}), axis(1, {-1., 0.5})); fig1.set_window_properties({0, 100}, {500, 500}); // initial ellipsoid @@ -84,9 +84,9 @@ int main() { fig3.set_window_properties({1200, 100}, {500, 500}); fig4.set_window_properties({0, 600}, {500, 500}); - fig2.set_axes(FigureAxis(0, {-3, 3}), FigureAxis(1, {-3, 3})); - fig3.set_axes(FigureAxis(1, {-3, 3}), FigureAxis(2, {-3, 3})); - fig4.set_axes(FigureAxis(0, {-3, 3}), FigureAxis(2, {-3, 3})); + fig2.set_axes(axis(0, {-3, 3}), axis(1, {-3, 3})); + fig3.set_axes(axis(1, {-3, 3}), axis(2, {-3, 3})); + fig4.set_axes(axis(0, {-3, 3}), axis(2, {-3, 3})); fig2.draw_ellipsoid(e4, {Color::blue(), Color::blue(0.3)}); fig3.draw_ellipsoid(e4, {Color::blue(), Color::blue(0.3)}); @@ -146,7 +146,7 @@ int main() { // ---------------------------------------------------------- Figure2D fig5("singular mappings and degenerated ellipsoids", GraphicOutput::VIBES); - fig5.set_axes(FigureAxis(0, {-0.5, 2}), FigureAxis(1, {-1.5, 1.})); + fig5.set_axes(axis(0, {-0.5, 2}), axis(1, {-1.5, 1.})); fig5.set_window_properties({700, 600}, {500, 500}); Ellipsoid e9(Vector({0., 0.5}), Matrix({{0.25, 0.}, @@ -210,7 +210,7 @@ int main() { cout << "\nStability analysis: the method is not able to conclude" << endl; } Figure2D fig6("Stability analysis - pendulum example", GraphicOutput::VIBES); - fig6.set_axes(FigureAxis(0, {-0.1, 0.1}), FigureAxis(1, {-0.1, 0.1})); + fig6.set_axes(axis(0, {-0.1, 0.1}), axis(1, {-0.1, 0.1})); fig6.set_window_properties({1200, 600}, {500, 500}); fig6.draw_ellipsoid(e13, {Color::red(), Color::red(0.3)}); fig6.draw_ellipsoid(e13_out, {Color::green(), Color::green(0.3)}); diff --git a/examples/ellipsoid_example/main.py b/examples/ellipsoid_example/main.py new file mode 100644 index 000000000..e0d28ce2f --- /dev/null +++ b/examples/ellipsoid_example/main.py @@ -0,0 +1,215 @@ +from codac import * + +# ---------------------------------------------------------- +# linear and nonlinear mappings +# ---------------------------------------------------------- + +fig1 = Figure2D('Linear and nonlinear mappings', GraphicOutput.VIBES) +fig1.set_axes(axis(0, [0, 1.5]), axis(1, [-1., 0.5])) +fig1.set_window_properties([0, 100], [500, 500]) + +# initial ellipsoid +mu = Vector([1., 0.]) +G = Matrix([[0.05, 0.0], + [0., 0.05]]) +e1 = Ellipsoid(mu, G) +fig1.draw_ellipsoid(e1, [Color.red(), Color.red(0.3)]) +print('Initial ellipsoid e1 (red):', e1) + +# discrete nonlinear pendulum system +x = VectorVar(2) +h = AnalyticFunction ([x], vec(x[0] + 0.1 * x[1], -0.2 * sin(x[0]) + 0.9 * x[1])) + +# linear mapping +N = 10 +e2 = Ellipsoid(e1) +for i in range(0,N): + A = h.diff(e2.mu).mid() + b = Vector(h.eval(e2.mu).mid() - A * e2.mu) + e2 = unreliable_linear_mapping(e2, A, b) + fig1.draw_ellipsoid(e2, [Color.green(), Color.green(0.3)]) + +print('\nLinear Mapping - Image ellipsoid e2 (green):', e2) + +# nonlinear mapping +e3 = Ellipsoid(e1) +for i in range(0,N): + e3 = nonlinear_mapping(e3, h) + fig1.draw_ellipsoid(e3, [Color.blue(), Color.blue(0.3)]) + +print('\nNon Linear Mapping - Image ellipsoid e3 (blue):', e3) + +# particle cloud (draw the evolution of 200 points in the ellipsoid) +Np = 200 +for i in range(0,Np): + x0 = e1.rand() + fig1.draw_box(IntervalVector(x0).inflate(0.0001), [Color.black(), Color.black(0.3)]) + for j in range(0,N): + x0 = h.eval(x0).mid() + fig1.draw_box(IntervalVector(x0).inflate(0.0001), [Color.black(), Color.black(0.3)]) + + +# ---------------------------------------------------------- +# ellipsoid projections +# ---------------------------------------------------------- + +mu4 = Vector([1., 0., 0.]) +G4 = Matrix([[1., 0.5, 0.], + [0.5, 2., 0.2], + [0., 0.2, 3.]]) +e4 = Ellipsoid(mu4, G4) + +G5 = 0.7 * G4 +e5 = Ellipsoid(mu4, G5) + +G6 = Matrix([[2., 0., 0.5], + [0., 1., 0.2], + [0., 0.2, 3.]]) +e6 = Ellipsoid(mu4, G6) + +fig2 = Figure2D('Projected ellipsoid xy', GraphicOutput.VIBES) +fig3 = Figure2D('Projected ellipsoid yz', GraphicOutput.VIBES) +fig4 = Figure2D('Projected ellipsoid xz', GraphicOutput.VIBES) + +fig2.set_window_properties([700, 100], [500, 500]) +fig3.set_window_properties([1200, 100], [500, 500]) +fig4.set_window_properties([0, 600], [500, 500]) + +fig2.set_axes(axis(0, [-3, 3]), axis(1, [-3, 3])) +fig3.set_axes(axis(1, [-3, 3]), axis(2, [-3, 3])) +fig4.set_axes(axis(0, [-3, 3]), axis(2, [-3, 3])) + +fig2.draw_ellipsoid(e4, [Color.blue(), Color.blue(0.3)]) +fig3.draw_ellipsoid(e4, [Color.blue(), Color.blue(0.3)]) +fig4.draw_ellipsoid(e4, [Color.blue(), Color.blue(0.3)]) + +fig2.draw_ellipsoid(e5, [Color.red(), Color.red(0.3)]) +fig3.draw_ellipsoid(e5, [Color.red(), Color.red(0.3)]) +fig4.draw_ellipsoid(e5, [Color.red(), Color.red(0.3)]) + +fig2.draw_ellipsoid(e6, [Color.green(), Color.green(0.3)]) +fig3.draw_ellipsoid(e6, [Color.green(), Color.green(0.3)]) +fig4.draw_ellipsoid(e6, [Color.green(), Color.green(0.3)]) + +# particle cloud (draw the evolution of 200 points in the ellipsoid e5) +for i in range(0,Np): + x5 = IntervalVector(e5.rand()) + x5.inflate(0.001) + fig2.draw_box(x5, [Color.black(), Color.black(0.3)]) + fig3.draw_box(x5, [Color.black(), Color.black(0.3)]) + fig4.draw_box(x5, [Color.black(), Color.black(0.3)]) + +# ---------------------------------------------------------- +# inclusion tests +# ---------------------------------------------------------- + +print('\nInclusion test e5 in e4: ', e5.is_concentric_subset(e4)) + +print('\nclusion test e4 in e5: ', e4.is_concentric_subset(e5)) + +print('\nclusion test e4 in e6: ', e6.is_concentric_subset(e4)) + +print('\nclusion test e5 in e6: ', e5.is_concentric_subset(e6)) + +# ---------------------------------------------------------- +# guaranteed and non guaranteed linear mappings +# ---------------------------------------------------------- +A = Matrix([[0.9, 0.5], + [-.5, 1.1]]) +b = Vector([0.1, 0.2]) + +e7 = unreliable_linear_mapping(e1, A, b) +e8 = linear_mapping(e1, A, b) + +print('\nLinear Mapping - Image ellipsoid e7:', e7) + +print('\nLinear Mapping Guaranteed - Image ellipsoid e8:', e8) + +print('\nDifference between e7 and e8:', 'mu diff norm is ', (e7.mu - e8.mu).norm(), 'G diff norm is ', (e7.G - e8.G).norm()) + +# ---------------------------------------------------------- +# singular case for nonlinear mapping +# ---------------------------------------------------------- + +fig5 = Figure2D('singular mappings and degenerated ellipsoids', GraphicOutput.VIBES) +fig5.set_axes(axis(0, [-0.5, 2]), axis(1, [-1.5, 1.])) +fig5.set_window_properties([700, 600], [500, 500]) + +e9 = Ellipsoid(Vector([0., 0.5]), Matrix([[0.25, 0.], + [0., 0.]])) +e10 = Ellipsoid(Vector([0., -0.5]), Matrix([[0.25, 0.], + [0., 0.25]])) + +fig5.draw_ellipsoid(e9, [Color.blue(), Color.red(0.3)]) +fig5.draw_ellipsoid(e10, [Color.red(), Color.red(0.3)]) + +h2 = AnalyticFunction([x], vec(x[0] + 0.5 * x[1] + 0.75, -0.5 * sin(x[0]) + 0.9 * x[1] + 0.1*0.5)) +h3 = AnalyticFunction([x], vec(x[0] + 0.5 * x[1] + 1.25, x[0] + 0.5 * x[1]-0.25)) + +e11 = nonlinear_mapping(e9, h2) +e12 = nonlinear_mapping(e10, h3) + +fig5.draw_ellipsoid(e11, [Color.green(), Color.green(0.3)]) +fig5.draw_ellipsoid(e12, [Color.green(), Color.green(0.3)]) + +print('\nDegenerate ellipsoid e9 (blue):\n', e9) +print('\nImage of degenerated ellipsoid e11 (green):\n', e11) +print('\nNon-degenerate ellipsoid e10 (red):\n', e10) +print('\nImage of singular mapping e12 (green):\n', e12) + +# particle cloud (draw the evolution of 200 points in the ellipsoid) +for i in range(0,Np): + x0 = e9.rand() + fig5.draw_box(IntervalVector(x0).inflate(0.0001), [Color.black(), Color.black(0.3)]) + x0 = h2.eval(x0).mid() + fig5.draw_box(IntervalVector(x0).inflate(0.0001), [Color.black(), Color.black(0.3)]) + + x0 = e10.rand() + fig5.draw_box(IntervalVector(x0).inflate(0.0001), [Color.black(), Color.black(0.3)]) + x0 = h3.eval(x0).mid() + fig5.draw_box(IntervalVector(x0).inflate(0.0001), [Color.black(), Color.black(0.3)]) + +# ---------------------------------------------------------- +# stability analysis +# ---------------------------------------------------------- + +# pendulum example +h4 = AnalyticFunction([x], vec(x[0] + 0.5 * x[1] , x[1] + 0.5 * (-x[1]-sin(x[0])))) +e13 = Ellipsoid(Vector(2), Matrix(2,2)) +e13_out = Ellipsoid(Vector(2), Matrix(2,2)) +alpha_max = 1 + +# todo if stability_analysis(h4,alpha_max, e13, e13_out) == BoolInterval.TRUE: +# todo print('\nStability analysis: the system is stable') +# todo print('Ellipsoidal domain of attraction e13 (red):') +# todo print(e13) +# todo print('Outter enclosure e13_out of the Image of e13 by h4 (green):') +# todo print(e13_out) +# todo +# todo else: +# todo print('\nStability analysis: the method is not able to conclude') +# todo +# todo fig6 = Figure2D('Stability analysis - pendulum example', GraphicOutput.VIBES) +# todo fig6.set_axes(axis(0, [-0.1, 0.1]), axis(1, [-0.1, 0.1])) +# todo fig6.set_window_properties([1200, 600], [500, 500]) +# todo fig6.draw_ellipsoid(e13, [Color.red(), Color.red(0.3)]) +# todo fig6.draw_ellipsoid(e13_out, [Color.green(), Color.green(0.3)]) + +# # high dimensional rov example +# VectorVar m(6) +# double T = 0.1 +# double s = 10 +# double kpd = 0.1 +# double kdd = 0.1 +# double kpp = 0.2 +# double kdp = 0.7 +# double dd = 5 +# +# AnalyticFunction h5[ +# [m], vec(m[0] + T * m[3] , +# m[1] + T * m[4] , +# m[2] + T* (m[6]-m[5]), +# m[3] + T*s*atan(-kpd*m[0]-kdd*m[3]), +# m[4] + T*s*atan(-kpd*m[1]-kdd*m[4]), +# m[5] + T*s*atan(kpp/2*m[2]-kdp*m[5])/(m[0]+dd), +# m[6] + T*s*atan(-kpp/2*m[2]-kdp*m[6])/(m[1]+dd))] \ No newline at end of file diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index 33f38f013..e0dab7f8b 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -224,4 +224,13 @@ def sivia(x,f,y,eps): return sivia_(x, f.f, IntervalVector(y), eps) else: - codac_error("sivia: can only compute sivia from scalar or vector functions") \ No newline at end of file + codac_error("sivia: can only compute sivia from scalar or vector functions") + + +def nonlinear_mapping(e,f): + + if isinstance(f.f, AnalyticFunction_Vector): + return nonlinear_mapping_(e, f.f) + + else: + codac_error("nonlinear_mapping: can only compute from vector functions") \ No newline at end of file diff --git a/python/src/core/CMakeLists.txt b/python/src/core/CMakeLists.txt index e4d01d4d3..c936609bc 100644 --- a/python/src/core/CMakeLists.txt +++ b/python/src/core/CMakeLists.txt @@ -27,6 +27,7 @@ contractors/codac2_py_directed_ctc.cpp contractors/codac2_py_linear_ctc.cpp + domains/ellipsoid/codac2_py_Ellipsoid.cpp domains/interval/codac2_py_Interval.cpp domains/interval/codac2_py_Interval_operations.cpp domains/interval/codac2_py_IntervalMatrix.cpp diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index 888acc85e..5085aedba 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -45,6 +45,7 @@ void export_linear_ctc(py::module& m); // domains void export_BoolInterval(py::module& m); +void export_Ellipsoid(py::module& m); py::class_ export_Interval(py::module& m); void export_Interval_operations(py::module& m, py::class_& py_Interval); py::class_ export_IntervalVector(py::module& m); @@ -143,6 +144,7 @@ PYBIND11_MODULE(_core, m) // domains export_BoolInterval(m); + export_Ellipsoid(m); auto py_Interval = export_Interval(m); export_Interval_operations(m, py_Interval); auto py_IV = export_IntervalVector(m); diff --git a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp new file mode 100644 index 000000000..a65e7f85f --- /dev/null +++ b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp @@ -0,0 +1,91 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include "codac2_py_Ellipsoid_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_Ellipsoid(py::module& m) +{ + py::class_ exported_ellipsoid_class(m, "Ellipsoid", ELLIPSOID_MAIN); + exported_ellipsoid_class + + .def_readwrite("mu", &Ellipsoid::mu, + VECTOR_ELLIPSOID_MU) + .def_readwrite("G", &Ellipsoid::G, + MATRIX_ELLIPSOID_G) + + .def(py::init(), + ELLIPSOID_ELLIPSOID_SIZET, + "n"_a) + + .def(py::init(), + ELLIPSOID_ELLIPSOID_CONST_VECTOR_REF_CONST_MATRIX_REF, + "mu"_a, "G"_a) + + .def(py::init(), + "e"_a) + + .def("__repr__", [](const Ellipsoid& e) { + std::ostringstream s; + s << e; + return string(s.str()); + }, + OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_ELLIPSOID_REF) + + .def("size", &Ellipsoid::size, + SIZET_ELLIPSOID_SIZE_CONST) + + .def("rand", &Ellipsoid::rand, + VECTOR_ELLIPSOID_RAND_CONST) + + .def("hull_box", &Ellipsoid::hull_box, + INTERVALVECTOR_ELLIPSOID_HULL_BOX_CONST) + + .def("is_concentric_subset", &Ellipsoid::is_concentric_subset, + BOOLINTERVAL_ELLIPSOID_IS_CONCENTRIC_SUBSET_CONST_ELLIPSOID_REF_CONST, + "e"_a) + + .def(py::self + py::self, + ELLIPSOID_OPERATORPLUS_CONST_ELLIPSOID_REF_CONST_ELLIPSOID_REF) + + ; + + m + + .def("linear_mapping", &codac2::linear_mapping, + ELLIPSOID_LINEAR_MAPPING_CONST_ELLIPSOID_REF_CONST_MATRIX_REF_CONST_VECTOR_REF, + "e"_a, "A"_a, "b"_a) + + .def("unreliable_linear_mapping", &codac2::unreliable_linear_mapping, + ELLIPSOID_UNRELIABLE_LINEAR_MAPPING_CONST_ELLIPSOID_REF_CONST_MATRIX_REF_CONST_VECTOR_REF, + "e"_a, "A"_a, "b"_a) + + .def("nonlinear_mapping_", (Ellipsoid (*)(const Ellipsoid&,const AnalyticFunction&))&codac2::nonlinear_mapping, + ELLIPSOID_NONLINEAR_MAPPING_CONST_ELLIPSOID_REF_CONST_ANALYTICFUNCTION_VECTOROPVALUE_REF, + "e"_a, "f"_a) + + .def("nonlinear_mapping_", (Ellipsoid (*)(const Ellipsoid&,const AnalyticFunction&,const Vector&,const Vector&))&codac2::nonlinear_mapping, + ELLIPSOID_NONLINEAR_MAPPING_CONST_ELLIPSOID_REF_CONST_ANALYTICFUNCTION_VECTOROPVALUE_REF_CONST_VECTOR_REF_CONST_VECTOR_REF, + "e"_a, "f"_a, "trig"_a, "q"_a) + + .def("nonlinear_mapping_base", &codac2::nonlinear_mapping_base, + MATRIX_NONLINEAR_MAPPING_BASE_CONST_MATRIX_REF_CONST_MATRIX_REF_CONST_INTERVALMATRIX_REF_CONST_VECTOR_REF_CONST_VECTOR_REF, + "G"_a, "J"_a, "J_box"_a, "trig"_a, "q"_a) + + ; +} \ No newline at end of file diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index d06f588e1..f35947aab 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -123,9 +123,13 @@ void export_Figure2D(py::module& m) "c"_a, "r"_a, "theta"_a, "s"_a=StyleProperties()) .def("draw_ellipse", &Figure2D::draw_ellipse, - STATIC_VOID_DEFAULTVIEW_DRAW_ELLIPSE_CONST_VECTOR_REF_CONST_VECTOR_REF_DOUBLE_CONST_STYLEPROPERTIES_REF, + VOID_FIGURE2D_DRAW_ELLIPSE_CONST_VECTOR_REF_CONST_VECTOR_REF_DOUBLE_CONST_STYLEPROPERTIES_REF, "c"_a, "ab"_a, "theta"_a, "s"_a=StyleProperties()) + .def("draw_ellipsoid", &Figure2D::draw_ellipsoid, + VOID_FIGURE2D_DRAW_ELLIPSOID_CONST_ELLIPSOID_REF_CONST_STYLEPROPERTIES_REF, + "e"_a, "s"_a=StyleProperties()) + // Robots .def("draw_tank", &Figure2D::draw_tank, @@ -187,6 +191,14 @@ void export_Figure2D(py::module& m) STATIC_VOID_DEFAULTVIEW_DRAW_PIE_CONST_VECTOR_REF_CONST_INTERVAL_REF_CONST_INTERVAL_REF_CONST_STYLEPROPERTIES_REF, "c"_a, "r"_a, "theta"_a, "s"_a=StyleProperties()) + .def_static("draw_ellipse", &DefaultView::draw_ellipse, + STATIC_VOID_DEFAULTVIEW_DRAW_ELLIPSE_CONST_VECTOR_REF_CONST_VECTOR_REF_DOUBLE_CONST_STYLEPROPERTIES_REF, + "c"_a, "ab"_a, "theta"_a, "s"_a=StyleProperties()) + + .def_static("draw_ellipsoid", &DefaultView::draw_ellipsoid, + STATIC_VOID_DEFAULTVIEW_DRAW_ELLIPSOID_CONST_ELLIPSOID_REF_CONST_STYLEPROPERTIES_REF, + "e"_a, "s"_a=StyleProperties()) + // Robots .def_static("draw_tank", &DefaultView::draw_tank, diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index 80ced6cf1..d839b8b5c 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -153,21 +153,21 @@ namespace codac2 /** * \brief (Rigorous?) non-linear evaluation f(e), from Jacobian information * - * \param e input ellipsoid + * \param G (?) * \param J approximated Jacobian matrix of f * \param J_box reliable enclosure of the Jacobian matrix of f * \param trig (?) * \param q (?) * \return a (rigorous?) outer enclosure of the non-linear mapping */ - Ellipsoid nonlinear_mapping_base(const Ellipsoid& e, const Matrix& J, const IntervalMatrix& J_box, - const Vector& trig, const Vector& q); + Matrix nonlinear_mapping_base(const Matrix& G, const Matrix& J, const IntervalMatrix& J_box, + const Vector& trig, const Vector& q); /** * \brief Streams out an Ellipsoid * * \param os the stream to be updated - * \param x the ellipsoid stream out + * \param e the ellipsoid stream out * \return a reference to the updated stream */ std::ostream& operator<<(std::ostream& os, const Ellipsoid& e); From 1da8202f638197660794d8645baa9b537478d53c Mon Sep 17 00:00:00 2001 From: MLouedec Date: Tue, 22 Oct 2024 13:36:04 +0200 Subject: [PATCH 019/126] generalisation of ellipsoidal 2Dprojection as a class function --- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 22 ++++++++++ src/core/domains/ellipsoid/codac2_Ellipsoid.h | 8 ++++ src/graphics/figures/codac2_Figure2D.cpp | 41 +++++++++++-------- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 1cf112472..04d0afe75 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -88,6 +88,28 @@ namespace codac2 { return BoolInterval::TRUE; } + void Ellipsoid::projection2D(const Vector& d, const Vector& v, const Vector& u) + { + // from [Pope S. B. - Algorithms for Ellipsoids - 2008] + assert( d.size() == v.size()); + assert( d.size() == u.size()); + assert( d.size() == this->size()); + assert( (v._e.transpose()*u._e).norm() == 0); // u & v orthogonal + + // Normalized Projection matrix + // the plane (d,u,v) is also the affine plan {x|x=d+Tt} with T = [u,v] + Matrix T = Matrix(this->size(),2); + T.col(0) = v/v.norm(); + T.col(1) = u/u.norm(); + + auto TTG = T._e.transpose() * this->G._e; + Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); + Matrix U(bdcsvd.matrixU()); + Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); + this->G = U._e * E._e; + this->mu = T._e.transpose() * (d._e + T._e * T._e.transpose() * (this->mu._e - d._e)); + } + Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2) { assert_release(e1.size() == e2.size()); diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index d839b8b5c..f2003619d 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -90,6 +90,14 @@ namespace codac2 */ BoolInterval is_concentric_subset(const Ellipsoid& e) const; + /** + * \brief Project the ellipsoid on the 2d plane (d,v,u) + * \param d a point on the plane + * \param v a vector of the plane + * \param u a other vector of the plane, orthogonal to v + */ + void projection2D(const Vector& d, const Vector& v, const Vector& u); + public: Vector mu; ///< midpoint vector diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 3df8eafaf..c9c78181a 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -203,22 +203,31 @@ void Figure2D::draw_ellipsoid(const Ellipsoid &e, const StyleProperties &s) { Vector mu_draw(2); // 2d projection of the ellipsoid if (e.size() > 2) { - // affine space of the projection - Vector d(Eigen::VectorXd::Zero(e.mu.nb_rows())); - Matrix T(Eigen::MatrixXd::Zero(e.G.nb_rows(), 2)); - T(output_fig->i(), 0) = 1; - T(output_fig->j(), 1) = 1; - - // project ellipsoid E(mu,Q) = {x in R^n | (x-mu).T*G.{-T}*G^{-1}*(x-mu)<1} - // on the affine plan A = {x|x=d+Tt} [Pope -2008] - // reduce the dimensions of mu and Q - - auto TTG = T._e.transpose() * e.G._e; - Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); - Matrix U(bdcsvd.matrixU()); - Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); - G_draw = U._e * E._e; - mu_draw = T._e.transpose() * (d._e + T._e * T._e.transpose() * (e.mu._e - d._e)); + Ellipsoid ep(e); + Vector v = Eigen::VectorXd::Zero(e.size()); + v[output_fig->i()] = 1; + Vector u = Eigen::VectorXd::Zero(e.size()); + u[output_fig->j()] = 1; + ep.projection2D(Eigen::VectorXd::Zero(e.size()),v,u); + G_draw = ep.G; + mu_draw = ep.mu; + +// // affine space of the projection +// Vector d(Eigen::VectorXd::Zero(e.mu.nb_rows())); +// Matrix T(Eigen::MatrixXd::Zero(e.G.nb_rows(), 2)); +// T(output_fig->i(), 0) = 1; +// T(output_fig->j(), 1) = 1; +// +// // project ellipsoid E(mu,Q) = {x in R^n | (x-mu).T*G.{-T}*G^{-1}*(x-mu)<1} +// // on the affine plan A = {x|x=d+Tt} [Pope -2008] +// // reduce the dimensions of mu and Q +// +// auto TTG = T._e.transpose() * e.G._e; +// Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); +// Matrix U(bdcsvd.matrixU()); +// Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); +// G_draw = U._e * E._e; +// mu_draw = T._e.transpose() * (d._e + T._e * T._e.transpose() * (e.mu._e - d._e)); } else { G_draw = e.G; mu_draw = e.mu; From 62078ed35a8df454fe0731d0da862f44a6a4807c Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 21 Nov 2024 16:56:21 +0100 Subject: [PATCH 020/126] [ellips] updates with new matrices implementation --- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 88 +++++++++---------- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 4 +- src/graphics/figures/codac2_Figure2D.cpp | 12 +-- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 1cf112472..dc09379ca 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -15,17 +15,17 @@ using namespace std; using namespace codac2; namespace codac2 { - Ellipsoid::Ellipsoid(size_t n) + Ellipsoid::Ellipsoid(Index n) : mu(Vector(n)), G(Matrix(n, n)) { assert_release(n > 0); } Ellipsoid::Ellipsoid(const Vector &mu_, const Matrix &G_) : mu(mu_), G(G_) { - assert_release(mu_.size() == G_.nb_cols() && G_.is_squared()); + assert_release(mu_.size() == G_.cols() && G_.is_squared()); } - size_t Ellipsoid::size() const { + Index Ellipsoid::size() const { return mu.size(); } @@ -33,14 +33,14 @@ namespace codac2 { { auto xi = Vector::random(this->size()); double rand_norm = ((double) std::rand() / (RAND_MAX)); - return this->mu._e + this->G._e * xi._e / xi._e.norm() * rand_norm; + return this->mu + this->G * xi / xi.norm() * rand_norm; } IntervalVector Ellipsoid::hull_box() const { IntervalVector hull(size()); - for(size_t i=0; i< size(); i++){ - double m = G._e.col(i).norm(); + for(Index i=0; i< size(); i++){ + double m = G.col(i).norm(); hull[i] = Interval(-m, m); } return hull; @@ -48,21 +48,21 @@ namespace codac2 { BoolInterval Ellipsoid::is_concentric_subset(const Ellipsoid& e) const { - size_t n = size(); + Index n = size(); assert_release(n == e.size()); - if((mu._e - e.mu._e).norm() > 1e-10) // check if the centers are the same + if((mu - e.mu).norm() > 1e-10) // check if the centers are the same return BoolInterval::FALSE; // not concentric auto I = Matrix::eye(n,n); - auto G2_inv = e.G._e.inverse(); - IntervalMatrix D(I._e - G._e.transpose() * G2_inv.transpose() * G2_inv * G._e); + auto G2_inv = e.G.inverse(); + IntervalMatrix D(I - G.transpose() * G2_inv.transpose() * G2_inv * G); // cholesky decomposition of D = L*L^T IntervalMatrix L(n,n); // matrix of the Cholesky decomposition - for (size_t j = 0; j < n; j++) // for every column + for (Index j = 0; j < n; j++) // for every column { // diagonal element Interval s = 0.; @@ -75,11 +75,11 @@ namespace codac2 { L(j,j) = sqrt(u); // then the rest of the column - for (size_t i = j + 1; i(); - auto e_res_mu_ = e_res.mu._e.template cast(); - auto e_res_G_ = e_res.G._e.template cast(); - auto e_G_ = e.G._e.template cast(); - auto A_ = A._e.template cast(); - auto b_ = b._e.template cast(); + auto e_mu_ = e.mu.template cast(); + auto e_res_mu_ = e_res.mu.template cast(); + auto e_res_G_ = e_res.G.template cast(); + auto e_G_ = e.G.template cast(); + auto A_ = A.template cast(); + auto b_ = b.template cast(); IntervalVector unit_box_(n, {-1,1}); // compute rounding error as a small box auto mu_res_guaranteed = A_ * e_mu_ + b_; auto G_res_guaranteed = A_ * e_G_; auto error_box_ = mu_res_guaranteed - e_res_mu_ + - (G_res_guaranteed - e_res_G_) * unit_box_._e; + (G_res_guaranteed - e_res_G_) * unit_box_; double rho = error_box_.norm().ub(); // max radius of error_box Ellipsoid elli_error(Vector::zeros(n), @@ -148,41 +148,41 @@ namespace codac2 { Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box, const Vector& trig, const Vector& q) { - size_t n = G.nb_cols(); + Index n = G.cols(); assert(G.is_squared() && J.is_squared() && J_box.is_squared()); - assert(n == J.nb_cols() && n == J_box.nb_cols() && n == q.size()); + assert(n == J.cols() && n == J_box.cols() && n == q.size()); Matrix JG = J * G; // note: reliability may be lost here! IntervalMatrix G_(G); IntervalMatrix JG_ = IntervalMatrix(JG); - IntervalVector unit_box(G.nb_rows(), Interval(-1, 1)); + IntervalVector unit_box(G.rows(), Interval(-1, 1)); // normal case - IntervalMatrix I_ = IntervalMatrix(Eigen::MatrixXd::Identity(G.nb_rows(),G.nb_cols())); - IntervalMatrix JG_inv_(JG._e.inverse()); // non rigourous inversion + IntervalMatrix I_ = IntervalMatrix(Eigen::MatrixXd::Identity(G.rows(),G.cols())); + IntervalMatrix JG_inv_(JG.inverse()); // non rigourous inversion Matrix M(JG); - auto W = JG_inv_._e; - auto Z = I_._e; + auto W = JG_inv_; + auto Z = I_; // check for singularities - if(std::abs(JG._e.determinant()) < trig[0]) + if(std::abs(JG.determinant()) < trig[0]) { /* degenerated case from * Louedec, M., Jaulin, L., & Viel, C. (2024). * "Outer enclosures of nonlinear mapping with degenerate ellipsoids." * IFAC ACNDC June 2024*/ assert(trig.size() == 2); - assert(q.size() == G.nb_rows()); + assert(q.size() == G.rows()); // SVD decomposition of JG = U*E*V.T - Eigen::BDCSVD bdcsvd(JG._e,Eigen::ComputeFullU); + Eigen::BDCSVD bdcsvd(JG,Eigen::ComputeFullU); IntervalMatrix U_(bdcsvd.matrixU()); // which is also the right part Vector Sv(bdcsvd.singularValues()); // vectors of singular values // select new singular values - int dim = G.nb_rows(); - IntervalVector s_box(U_._e.transpose()*J_box._e*G_._e*unit_box._e); + int dim = G.rows(); + IntervalVector s_box(U_.transpose()*J_box*G_*unit_box); IntervalMatrix S_(Eigen::MatrixXd::Zero(dim,dim)); // diagonal matrix of the new singular value IntervalMatrix S_pinv_(Eigen::MatrixXd::Zero(dim,dim)); // pseudo inverse of S for(int i=0;i 2) { // affine space of the projection - Vector d(Eigen::VectorXd::Zero(e.mu.nb_rows())); - Matrix T(Eigen::MatrixXd::Zero(e.G.nb_rows(), 2)); + Vector d(Eigen::VectorXd::Zero(e.mu.rows())); + Matrix T(Eigen::MatrixXd::Zero(e.G.rows(), 2)); T(output_fig->i(), 0) = 1; T(output_fig->j(), 1) = 1; @@ -214,19 +214,19 @@ void Figure2D::draw_ellipsoid(const Ellipsoid &e, const StyleProperties &s) { // on the affine plan A = {x|x=d+Tt} [Pope -2008] // reduce the dimensions of mu and Q - auto TTG = T._e.transpose() * e.G._e; + auto TTG = T.transpose() * e.G; Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); Matrix U(bdcsvd.matrixU()); Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); - G_draw = U._e * E._e; - mu_draw = T._e.transpose() * (d._e + T._e * T._e.transpose() * (e.mu._e - d._e)); + G_draw = U * E; + mu_draw = T.transpose() * (d + T * T.transpose() * (e.mu - d)); } else { G_draw = e.G; mu_draw = e.mu; } // draw the 2d ellipsoid - Eigen::JacobiSVD jsvd(G_draw._e, Eigen::ComputeThinU); + Eigen::JacobiSVD jsvd(G_draw, Eigen::ComputeThinU); Matrix U(jsvd.matrixU()); Vector ab(jsvd.singularValues()); From 53b156bbe9657c82ff18411add6320c81d6d9eaf Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 26 Nov 2024 22:27:45 +0100 Subject: [PATCH 021/126] [ellips] updates following new matrices implementation --- .../domains/ellipsoid/codac2_Ellipsoid.cpp | 6 +- .../ellipsoid/codac2_Ellipsoid_utils.cpp | 4 +- src/graphics/CMakeLists.txt | 1 + src/graphics/figures/codac2_Figure2D.cpp | 41 +------------- .../figures/codac2_Figure2D_ellipsoid.cpp | 56 +++++++++++++++++++ 5 files changed, 65 insertions(+), 43 deletions(-) create mode 100644 src/graphics/figures/codac2_Figure2D_ellipsoid.cpp diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 893fac3b6..aff80c982 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -12,7 +12,7 @@ #include using namespace std; -using namespace codac2; +using codac2::Vector; namespace codac2 { Ellipsoid::Ellipsoid(Index n) @@ -132,7 +132,7 @@ namespace codac2 { auto e_G_ = e.G.template cast(); auto A_ = A.template cast(); auto b_ = b.template cast(); - IntervalVector unit_box_(n, {-1,1}); + IntervalVector unit_box_ = IntervalVector::constant(n, {-1,1}); // compute rounding error as a small box auto mu_res_guaranteed = A_ * e_mu_ + b_; @@ -141,7 +141,7 @@ namespace codac2 { (G_res_guaranteed - e_res_G_) * unit_box_; double rho = error_box_.norm().ub(); // max radius of error_box - Ellipsoid elli_error(Vector::zeros(n), + Ellipsoid elli_error(Vector::zero(n), Matrix::eye(n,n) * rho); // = rho*unit_ball return e_res + elli_error; } diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp index a05020497..2416c9491 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp @@ -12,7 +12,9 @@ #include using namespace std; -using namespace codac2; +using codac2::Matrix; +using codac2::Vector; +using codac2::BoolInterval; namespace codac2 { diff --git a/src/graphics/CMakeLists.txt b/src/graphics/CMakeLists.txt index 7b38751b6..9da2bb33c 100644 --- a/src/graphics/CMakeLists.txt +++ b/src/graphics/CMakeLists.txt @@ -12,6 +12,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/3rd/vibes/vibes.h ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2D.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2D_ellipsoid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2D.h ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2DInterface.h ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_OutputFigure2D.cpp diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 972ecd3b5..b3af3ef92 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -13,6 +13,8 @@ #include "codac2_Figure2D_IPE.h" #include "codac2_math.h" #include "codac2_pave.h" +#include "codac2_matrices.h" +#include "codac2_Matrix.h" using namespace std; using namespace codac2; @@ -197,45 +199,6 @@ void Figure2D::draw_ellipse(const Vector& c, const Vector& ab, double theta, con output_fig->draw_ellipse(c,ab,theta,s); } -void Figure2D::draw_ellipsoid(const Ellipsoid &e, const StyleProperties &s) { - assert_release(this->size() <= e.size()); - for (const auto &output_fig: _output_figures) { - Matrix G_draw(2, 2); - Vector mu_draw(2); - // 2d projection of the ellipsoid - if (e.size() > 2) { - // affine space of the projection - Vector d(Eigen::VectorXd::Zero(e.mu.rows())); - Matrix T(Eigen::MatrixXd::Zero(e.G.rows(), 2)); - T(output_fig->i(), 0) = 1; - T(output_fig->j(), 1) = 1; - - // project ellipsoid E(mu,Q) = {x in R^n | (x-mu).T*G.{-T}*G^{-1}*(x-mu)<1} - // on the affine plan A = {x|x=d+Tt} [Pope -2008] - // reduce the dimensions of mu and Q - - auto TTG = T.transpose() * e.G; - Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); - Matrix U(bdcsvd.matrixU()); - Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); - G_draw = U * E; - mu_draw = T.transpose() * (d + T * T.transpose() * (e.mu - d)); - } else { - G_draw = e.G; - mu_draw = e.mu; - } - - // draw the 2d ellipsoid - Eigen::JacobiSVD jsvd(G_draw, Eigen::ComputeThinU); - Matrix U(jsvd.matrixU()); - Vector ab(jsvd.singularValues()); - - double theta = atan2(U(1, 0), U(0, 0)).mid(); - - output_fig->draw_ellipse(mu_draw, ab, theta, s); - } -} - void Figure2D::draw_tank(const Vector& x, float size, const StyleProperties& s) { assert_release(this->size() <= x.size()+1); diff --git a/src/graphics/figures/codac2_Figure2D_ellipsoid.cpp b/src/graphics/figures/codac2_Figure2D_ellipsoid.cpp new file mode 100644 index 000000000..4d1c83738 --- /dev/null +++ b/src/graphics/figures/codac2_Figure2D_ellipsoid.cpp @@ -0,0 +1,56 @@ +/** + * codac2_Figure2D.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Morgan Louédec + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_Index.h" +#include "codac2_Figure2D.h" +#include "codac2_matrices.h" +#include "codac2_Matrix.h" + +using namespace std; +using codac2::Vector; +using codac2::Matrix; + +void codac2::Figure2D::draw_ellipsoid(const codac2::Ellipsoid &e, const codac2::StyleProperties &s) { + //assert_release(this->size() <= e.size()); + for (const auto &output_fig: _output_figures) { + Matrix G_draw(2, 2); + Vector mu_draw(2); + // 2d projection of the ellipsoid + if (e.size() > 2) { + // affine space of the projection + Vector d(Eigen::VectorXd::Zero(e.mu.rows())); + Matrix T(Eigen::MatrixXd::Zero(e.G.rows(), 2)); + T(output_fig->i(), 0) = 1; + T(output_fig->j(), 1) = 1; + + // project ellipsoid E(mu,Q) = {x in R^n | (x-mu).T*G.{-T}*G^{-1}*(x-mu)<1} + // on the affine plan A = {x|x=d+Tt} [Pope -2008] + // reduce the dimensions of mu and Q + + auto TTG = T.transpose().eval() * e.G; + Eigen::BDCSVD bdcsvd(Matrix(TTG.eval()), Eigen::ComputeFullU); + Matrix U(bdcsvd.matrixU()); + Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); + G_draw = U * E; + mu_draw = T.transpose() * (d + T * T.transpose() * (e.mu - d)); + } else { + G_draw = e.G; + mu_draw = e.mu; + } + + // draw the 2d ellipsoid + Eigen::JacobiSVD jsvd(G_draw, Eigen::ComputeThinU); + Matrix U(jsvd.matrixU()); + Vector ab(jsvd.singularValues()); + + double theta = atan2(U(1, 0), U(0, 0)).mid(); + + output_fig->draw_ellipse(mu_draw, ab, theta, s); + } +} \ No newline at end of file From d7de9677988d289be1510d4f5c0b947d75edb665 Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sun, 1 Dec 2024 15:11:07 +0100 Subject: [PATCH 022/126] /MP flag for Visual Studio may allow more parallelization possibilities --- .github/workflows/unixmatrix.yml | 12 ++++++------ .github/workflows/vcmatrix.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/unixmatrix.yml b/.github/workflows/unixmatrix.yml index 41c66beaf..5f7155325 100644 --- a/.github/workflows/unixmatrix.yml +++ b/.github/workflows/unixmatrix.yml @@ -28,13 +28,13 @@ jobs: fail-fast: false matrix: cfg: - - { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2022 x64' } - - { os: windows-2022, shell: cmd, arch: x86, bitness: 32, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2022 x86' } + - { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A x64', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2022 x64' } + - { os: windows-2022, shell: cmd, arch: x86, bitness: 32, runtime: vc17, cmake_params: '-G "Visual Studio 17" -T v143 -A Win32', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2022 x86' } # Problems related to C++20? - #- { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2019 x64' } - #- { os: windows-2022, shell: cmd, arch: x86, bitness: 32, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2019 x86' } - #- { os: windows-2019, shell: cmd, arch: x64, bitness: 64, runtime: vc15, cmake_params: '-G "Visual Studio 16" -T v141 -A x64', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2017 x64' } - #- { os: windows-2019, shell: cmd, arch: x86, bitness: 32, runtime: vc15, cmake_params: '-G "Visual Studio 16" -T v141 -A Win32', cmake_flags: ' /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2017 x86' } + #- { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A x64', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2019 x64' } + #- { os: windows-2022, shell: cmd, arch: x86, bitness: 32, runtime: vc16, cmake_params: '-G "Visual Studio 17" -T v142 -A Win32', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2019 x86' } + #- { os: windows-2019, shell: cmd, arch: x64, bitness: 64, runtime: vc15, cmake_params: '-G "Visual Studio 16" -T v141 -A x64', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', desc: 'Windows Visual Studio 2017 x64' } + #- { os: windows-2019, shell: cmd, arch: x86, bitness: 32, runtime: vc15, cmake_params: '-G "Visual Studio 16" -T v141 -A Win32', cmake_flags: ' /MP4 /wd4267 /wd4244 /wd4305 /wd4996', test_config: 'Release/', choco_flags: '--x86', desc: 'Windows Visual Studio 2017 x86' } - { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: mingw13, cmake_params: '-G "MinGW Makefiles"', cmake_flags: '-fPIC', desc: 'Windows MinGW 13.2.0 x64' } - { os: windows-2022, shell: cmd, arch: x86, bitness: 32, runtime: mingw13, cmake_params: '-G "MinGW Makefiles"', cmake_flags: '-fPIC', choco_flags: '--x86', desc: 'Windows MinGW 13.2.0 x86' } - { os: windows-2022, shell: cmd, arch: x64, bitness: 64, runtime: mingw12, cmake_params: '-G "MinGW Makefiles"', cmake_flags: '-fPIC', desc: 'Windows MinGW 12.2.0 x64' } diff --git a/.github/workflows/vcmatrix.yml b/.github/workflows/vcmatrix.yml index f22699776..ffdfb2ec5 100644 --- a/.github/workflows/vcmatrix.yml +++ b/.github/workflows/vcmatrix.yml @@ -68,7 +68,7 @@ jobs: del /f /q ibex.2.8.9.20241117.nupkg - run: | mkdir build ; cd build - cmake -E env CXXFLAGS=" /wd4267 /wd4244 /wd4305 /wd4996" CFLAGS=" /wd4267 /wd4244 /wd4305 /wd4996" cmake ${{ matrix.cfg.cmake_params }} -D CMAKE_INSTALL_PREFIX="../codac" -D BUILD_TESTS=ON -D WITH_CAPD=OFF -D WITH_PYTHON=ON .. + cmake -E env CXXFLAGS=" /MP4 /wd4267 /wd4244 /wd4305 /wd4996" CFLAGS=" /MP4 /wd4267 /wd4244 /wd4305 /wd4996" cmake ${{ matrix.cfg.cmake_params }} -D CMAKE_INSTALL_PREFIX="../codac" -D BUILD_TESTS=ON -D WITH_CAPD=OFF -D WITH_PYTHON=ON .. cmake --build . -j 4 --config Release --target install cmake --build . --config Release --target pip_package ; cp `ls *.whl` ../`ls *.whl | sed "s/py3-none-any/cp${{ matrix.cfg.py_v_maj }}${{ matrix.cfg.py_v_min }}-cp${{ matrix.cfg.py_v_maj }}${{ matrix.cfg.py_v_min }}${{ matrix.cfg.cpcfg }}/"` cd .. From 8e7acd8950efd5e45d37cfc9b358f055515947b3 Mon Sep 17 00:00:00 2001 From: MLouedec Date: Tue, 10 Dec 2024 15:42:31 +0100 Subject: [PATCH 023/126] adding uncommited updates --- examples/ellipsoid_dev/CMakeLists.txt | 44 +++++++++ examples/ellipsoid_dev/main.cpp | 123 ++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 examples/ellipsoid_dev/CMakeLists.txt create mode 100644 examples/ellipsoid_dev/main.cpp diff --git a/examples/ellipsoid_dev/CMakeLists.txt b/examples/ellipsoid_dev/CMakeLists.txt new file mode 100644 index 000000000..a9eeab778 --- /dev/null +++ b/examples/ellipsoid_dev/CMakeLists.txt @@ -0,0 +1,44 @@ +# ================================================================== +# codac / ellipsoid example - cmake configuration file +# ================================================================== + + cmake_minimum_required(VERSION 3.0.2) + project(ellipsoid_dev LANGUAGES CXX) + + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Adding IBEX + + # In case you installed IBEX in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option. + # set(CMAKE_PREFIX_PATH "~/ibex-lib/build_install") + + find_package(IBEX REQUIRED) + ibex_init_common() # IBEX should have installed this function + message(STATUS "Found IBEX version ${IBEX_VERSION}") + +# Adding Eigen3 + + # In case you installed Eigen3 in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option, e.g. + # set(CMAKE_PREFIX_PATH "~/eigen/build_install") + + find_package(Eigen3 3.4 REQUIRED NO_MODULE) + message(STATUS "Found Eigen3 version ${Eigen3_VERSION}") + +# Adding Codac + + # In case you installed Codac in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option. + set(CMAKE_PREFIX_PATH "~/Documents/Code_these/codac/build_install") + + find_package(CODAC REQUIRED) + message(STATUS "Found Codac version ${CODAC_VERSION}") + +# Compilation + + 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}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex Eigen3::Eigen) diff --git a/examples/ellipsoid_dev/main.cpp b/examples/ellipsoid_dev/main.cpp new file mode 100644 index 000000000..f85548931 --- /dev/null +++ b/examples/ellipsoid_dev/main.cpp @@ -0,0 +1,123 @@ +#include + +using namespace std; +using namespace codac2; + +int main() { + // ---------------------------------------------------------- + // ellipsoid projections + // ---------------------------------------------------------- + + Vector mu4({1., 0., 0.}); + Matrix G4({{1., 0.5, 0.}, + {0.5, 2., 0.2}, + {0., 0.2, 3.}}); + Ellipsoid e4(mu4, G4); + + Matrix G5 = 0.7 * G4; + Ellipsoid e5(mu4, G5); + + Matrix G6({{2., 0., 0.5}, + {0., 1., 0.2}, + {0., 0.2, 3.}}); + Ellipsoid e6(mu4, G6); + + Figure2D fig2("Projected ellipsoid xy", GraphicOutput::VIBES); + Figure2D fig3("Projected ellipsoid yz", GraphicOutput::VIBES); + Figure2D fig4("Projected ellipsoid xz", GraphicOutput::VIBES); + + fig2.set_window_properties({700, 100}, {500, 500}); + fig3.set_window_properties({1200, 100}, {500, 500}); + fig4.set_window_properties({0, 100}, {500, 500}); + + fig2.set_axes(axis(0, {-3, 3}), axis(1, {-3, 3})); + fig3.set_axes(axis(1, {-3, 3}), axis(2, {-3, 3})); + fig4.set_axes(axis(0, {-3, 3}), axis(2, {-3, 3})); + + fig2.draw_ellipsoid(e4, {Color::blue(), Color::blue(0.3)}); + fig3.draw_ellipsoid(e4, {Color::blue(), Color::blue(0.3)}); + fig4.draw_ellipsoid(e4, {Color::blue(), Color::blue(0.3)}); + + fig2.draw_ellipsoid(e5, {Color::red(), Color::red(0.3)}); + fig3.draw_ellipsoid(e5, {Color::red(), Color::red(0.3)}); + fig4.draw_ellipsoid(e5, {Color::red(), Color::red(0.3)}); + + fig2.draw_ellipsoid(e6, {Color::green(), Color::green(0.3)}); + fig3.draw_ellipsoid(e6, {Color::green(), Color::green(0.3)}); + fig4.draw_ellipsoid(e6, {Color::green(), Color::green(0.3)}); + + // ---------------------------------------------------------- + // inclusion tests + // ---------------------------------------------------------- + + cout << "\nInclusion test e5 in e4: " << e5.is_concentric_subset(e4) << endl; + + cout << "Inclusion test e4 in e5: " << e4.is_concentric_subset(e5) << endl; + + cout << "Inclusion test e4 in e6: " << e6.is_concentric_subset(e4) << endl; + + cout << "Inclusion test e5 in e6: " << e5.is_concentric_subset(e6) << endl; + + // ---------------------------------------------------------- + // test the non inclusion (e4 in e6) + // ---------------------------------------------------------- + + // step 1 identify the direction of non inclusion + Eigen::MatrixXd X = e4.G._e; + Eigen::MatrixXd Y = e6.G._e; + Eigen::MatrixXd Y_inv = Y.inverse(); + Eigen::MatrixXd D = Eigen::MatrixXd::Identity(3,3)- X.transpose()*Y_inv.transpose()*Y_inv*X; + cout << "D = " << D << endl; + + Eigen::SelfAdjointEigenSolver es(D); + Eigen::VectorXd eigenvalues = es.eigenvalues(); + + Eigen::VectorXd v; + double min_eigenvalue = MAXFLOAT; + for (int i = 0; i < eigenvalues.size(); i++){ + if (eigenvalues(i) < min_eigenvalue){ + min_eigenvalue = eigenvalues(i); + v = es.eigenvectors().col(i); // the vector associated to the smallest eigenvalue + } + } + cout << " the min eigenvalue of D is " << min_eigenvalue << endl; + cout << " the vector associated to the min eigenvalue is " << v << endl; + + // select the less included point and draw it on the figures + Eigen::VectorXd x = e4.mu._e+e4.G._e*v; + cout << "the point " << x << " is the less included point" << endl; + fig2.draw_point(x, {Color::black()}); + fig3.draw_point(x, {Color::black()}); + fig4.draw_point(x, {Color::black()}); + +// IntervalVector x6(x); +// x6.inflate(0.001); +// fig2.draw_box(x6, {Color::black(), Color::black()}); + + // now let us prove by intervals that x is out of e6 + // by proving (x-mu6).T@G6^(-T)@G6^(-1)@(x-mu6) > 1 + + IntervalVector w(x); + w -= IntervalVector(e6.mu); + + IntervalMatrix Q(Y_inv); + Q = Q.transpose()*Q; + + IntervalMatrix res = w.transpose()*Q*w; + cout << "the result of the inclusion test is " << res << endl; + + if(res(0,0).lb() > 1.) { + cout << "the point is out of the ellipsoid" << endl; + cout << "the non inclusion is guaranteed" << endl; + } + + // can we also prove that x is in e4? -> we should take the point not on the boundary or + // have guaranteed operations previously + Eigen::MatrixXd X_inv = X.inverse(); + IntervalMatrix Qx(X_inv); + Qx = Qx.transpose()*Qx; + + IntervalMatrix res2 = w.transpose()*Qx*w; + cout << "the result of the inclusion test in e4 is " << res2 << endl; + +} From a81e68d6e2de229280836bb18d85375a10fa2c92 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sun, 15 Dec 2024 11:45:05 +0100 Subject: [PATCH 024/126] [ellips] updates (homogenization + Eigen optimizations) --- examples/ellipsoid_example/main.cpp | 87 +++++++++++-------- python/src/core/CMakeLists.txt | 1 + python/src/core/codac2_py_core.cpp | 2 + .../domains/ellipsoid/codac2_py_Ellipsoid.cpp | 23 +++-- .../ellipsoid/codac2_py_Ellipsoid_utils.cpp | 35 ++++++++ .../graphics/figures/codac2_py_Figure2D.cpp | 6 ++ .../domains/ellipsoid/codac2_Ellipsoid.cpp | 69 +++++++-------- src/core/domains/ellipsoid/codac2_Ellipsoid.h | 3 +- .../ellipsoid/codac2_Ellipsoid_utils.cpp | 53 ++++++----- .../ellipsoid/codac2_Ellipsoid_utils.h | 9 +- src/graphics/CMakeLists.txt | 1 - src/graphics/figures/codac2_Figure2D.cpp | 41 ++++++++- src/graphics/figures/codac2_Figure2D.h | 3 + .../figures/codac2_Figure2D_ellipsoid.cpp | 56 ------------ .../figures/codac2_OutputFigure2D.cpp | 4 +- 15 files changed, 226 insertions(+), 167 deletions(-) create mode 100644 python/src/core/domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp delete mode 100644 src/graphics/figures/codac2_Figure2D_ellipsoid.cpp diff --git a/examples/ellipsoid_example/main.cpp b/examples/ellipsoid_example/main.cpp index 1c328c8ea..c3cb37538 100644 --- a/examples/ellipsoid_example/main.cpp +++ b/examples/ellipsoid_example/main.cpp @@ -13,10 +13,11 @@ int main() { fig1.set_window_properties({0, 100}, {500, 500}); // initial ellipsoid - Vector mu({1., 0.}); - Matrix G({{0.05, 0.0}, - {0., 0.05}}); - Ellipsoid e1(mu, G); + Ellipsoid e1( + {1., 0.}, // mu + {{0.05, 0.0}, // G + {0., 0.05}} + ); fig1.draw_ellipsoid(e1, {Color::red(), Color::red(0.3)}); cout << "Initial ellipsoid e1 (red):" << endl; cout << e1 << endl; @@ -51,10 +52,10 @@ int main() { int Np = 200; for (int i = 0; i < Np; i++) { Vector x0 = e1.rand(); - fig1.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); + fig1.draw_point(x0, {Color::black(), Color::black(0.3)}); for (int j = 0; j < N; j++) { x0 = h.eval(x0).mid(); - fig1.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); + fig1.draw_point(x0, {Color::black(), Color::black(0.3)}); } } @@ -62,19 +63,24 @@ int main() { // ellipsoid projections // ---------------------------------------------------------- - Vector mu4({1., 0., 0.}); - Matrix G4({{1., 0.5, 0.}, - {0.5, 2., 0.2}, - {0., 0.2, 3.}}); - Ellipsoid e4(mu4, G4); - - Matrix G5 = 0.7 * G4; - Ellipsoid e5(mu4, G5); - - Matrix G6({{2., 0., 0.5}, - {0., 1., 0.2}, - {0., 0.2, 3.}}); - Ellipsoid e6(mu4, G6); + Ellipsoid e4 { + {1., 0., 0.}, // mu + {{1., 0.5, 0.}, // G + {0.5, 2., 0.2}, + {0., 0.2, 3.}} + }; + + Ellipsoid e5 { + e4.mu, // mu + 0.7 * e4.G // G + }; + + Ellipsoid e6 { + e4.mu, // mu + {{2., 0., 0.5}, // G + {0., 1., 0.2}, + {0., 0.2, 3.}} + }; Figure2D fig2("Projected ellipsoid xy", GraphicOutput::VIBES); Figure2D fig3("Projected ellipsoid yz", GraphicOutput::VIBES); @@ -102,11 +108,10 @@ int main() { // particle cloud (draw the evolution of 200 points in the ellipsoid e5) for (int i = 0; i < Np; i++) { - IntervalVector x5(e5.rand()); - x5.inflate(0.001); - fig2.draw_box(x5, {Color::black(), Color::black(0.3)}); - fig3.draw_box(x5, {Color::black(), Color::black(0.3)}); - fig4.draw_box(x5, {Color::black(), Color::black(0.3)}); + Vector x5 = e5.rand(); + fig2.draw_point(x5, {Color::black(), Color::black(0.3)}); + fig3.draw_point(x5, {Color::black(), Color::black(0.3)}); + fig4.draw_point(x5, {Color::black(), Color::black(0.3)}); } // ---------------------------------------------------------- @@ -149,10 +154,16 @@ int main() { fig5.set_axes(axis(0, {-0.5, 2}), axis(1, {-1.5, 1.})); fig5.set_window_properties({700, 600}, {500, 500}); - Ellipsoid e9(Vector({0., 0.5}), Matrix({{0.25, 0.}, - {0., 0.}})); - Ellipsoid e10(Vector({0., -0.5}), Matrix({{0.25, 0.}, - {0., 0.25}})); + Ellipsoid e9 { + {0., 0.5}, // mu + {{0.25, 0.}, // G + {0., 0.}} + }; + Ellipsoid e10 { + {0., -0.5}, // mu + {{0.25, 0.}, // G + {0., 0.25}} + }; fig5.draw_ellipsoid(e9, {Color::blue(), Color::red(0.3)}); fig5.draw_ellipsoid(e10, {Color::red(), Color::red(0.3)}); @@ -176,14 +187,12 @@ int main() { // particle cloud (draw the evolution of 200 points in the ellipsoid) for (int i = 0; i < Np; i++) { Vector x0 = e9.rand(); - fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); - x0 = h2.eval(x0).mid(); - fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); + fig5.draw_point(x0, {Color::black(), Color::black(0.3)}); + fig5.draw_point(h2.eval(x0).mid(), {Color::black(), Color::black(0.3)}); x0 = e10.rand(); - fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); - x0 = h3.eval(x0).mid(); - fig5.draw_box(IntervalVector(x0).inflate(0.0001), {Color::black(), Color::black(0.3)}); + fig5.draw_point(x0, {Color::black(), Color::black(0.3)}); + fig5.draw_point(h3.eval(x0).mid(), {Color::black(), Color::black(0.3)}); } // ---------------------------------------------------------- @@ -193,8 +202,14 @@ int main() { // pendulum example AnalyticFunction h4{ {x}, vec(x[0] + 0.5 * x[1] , x[1] + 0.5 * (-x[1]-sin(x[0])))}; - Ellipsoid e13(Vector(2), Matrix(2,2)); - Ellipsoid e13_out(Vector(2), Matrix(2,2)); + Ellipsoid e13 { + Vector::zero(2), // mu + Matrix::zero(2,2) // G + }; + Ellipsoid e13_out { + Vector::zero(2), // mu + Matrix::zero(2,2) // G + }; int alpha_max = 1; if(stability_analysis(h4,alpha_max, e13, e13_out) == BoolInterval::TRUE) diff --git a/python/src/core/CMakeLists.txt b/python/src/core/CMakeLists.txt index c2d7a483a..0bc86a5a8 100644 --- a/python/src/core/CMakeLists.txt +++ b/python/src/core/CMakeLists.txt @@ -33,6 +33,7 @@ contractors/codac2_py_linear_ctc.cpp domains/ellipsoid/codac2_py_Ellipsoid.cpp + domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp domains/interval/codac2_py_Interval.cpp domains/interval/codac2_py_Interval_operations.cpp domains/interval/codac2_py_IntervalMatrix.cpp diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index dbe2355c2..89c071a9f 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -53,6 +53,7 @@ void export_linear_ctc(py::module& m); // domains void export_BoolInterval(py::module& m); void export_Ellipsoid(py::module& m); +void export_Ellipsoid_utils(py::module& m); py::class_ export_Interval(py::module& m); void export_Interval_operations(py::module& m, py::class_& py_Interval); py::class_ export_IntervalRow(py::module& m); @@ -164,6 +165,7 @@ PYBIND11_MODULE(_core, m) // domains export_BoolInterval(m); export_Ellipsoid(m); + export_Ellipsoid_utils(m); auto py_Interval = export_Interval(m); export_Interval_operations(m, py_Interval); auto py_IR = export_IntervalRow(m); diff --git a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp index a411561ea..e1784a10a 100644 --- a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp +++ b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp @@ -29,7 +29,7 @@ void export_Ellipsoid(py::module& m) .def_readwrite("G", &Ellipsoid::G, MATRIX_ELLIPSOID_G) - .def(py::init(), + .def(py::init(), ELLIPSOID_ELLIPSOID_INDEX, "n"_a) @@ -40,13 +40,6 @@ void export_Ellipsoid(py::module& m) .def(py::init(), "e"_a) - .def("__repr__", [](const Ellipsoid& e) { - std::ostringstream s; - s << e; - return string(s.str()); - }, - OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_ELLIPSOID_REF) - .def("size", &Ellipsoid::size, INDEX_ELLIPSOID_SIZE_CONST) @@ -60,8 +53,20 @@ void export_Ellipsoid(py::module& m) BOOLINTERVAL_ELLIPSOID_IS_CONCENTRIC_SUBSET_CONST_ELLIPSOID_REF_CONST, "e"_a) + .def("proj_2d", &Ellipsoid::proj_2d, + ELLIPSOID_ELLIPSOID_PROJ_2D_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST, + "d"_a, "v"_a, "u"_a) + + .def("__repr__", [](const Ellipsoid& e) { + std::ostringstream s; + s << e; + return string(s.str()); + }, + OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_ELLIPSOID_REF) + .def(py::self + py::self, - ELLIPSOID_OPERATORPLUS_CONST_ELLIPSOID_REF_CONST_ELLIPSOID_REF) + ELLIPSOID_OPERATORPLUS_CONST_ELLIPSOID_REF_CONST_ELLIPSOID_REF, + py::is_operator()) ; diff --git a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp new file mode 100644 index 000000000..1fd51de17 --- /dev/null +++ b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid_utils.cpp @@ -0,0 +1,35 @@ +/** + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include "codac2_py_Ellipsoid_utils_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_Ellipsoid_utils(py::module& m) +{ + m + + .def("stability_analysis", &codac2::stability_analysis, + BOOLINTERVAL_STABILITY_ANALYSIS_CONST_ANALYTICFUNCTION_VECTOROPVALUE_REF_UNSIGNED_INT_ELLIPSOID_REF_ELLIPSOID_REF_BOOL, + "f"_a, "alpha_max"_a, "e"_a, "e_out"_a, "verbose"_a=false) + + .def("solve_discrete_lyapunov", &codac2::solve_discrete_lyapunov, + MATRIX_SOLVE_DISCRETE_LYAPUNOV_CONST_MATRIX_REF_CONST_MATRIX_REF, + "A"_a, "Q"_a) + + ; +} \ No newline at end of file diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index 4a3e18d11..4c9e143fe 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -65,6 +65,12 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_SET_AXES_CONST_FIGUREAXIS_REF_CONST_FIGUREAXIS_REF, "axis1"_a, "axis2"_a) + .def("i", &Figure2D::i, + CONST_INDEX_REF_FIGURE2D_I_CONST) + + .def("j", &Figure2D::j, + CONST_INDEX_REF_FIGURE2D_J_CONST) + .def("pos", &Figure2D::pos, CONST_VECTOR_REF_FIGURE2D_POS_CONST) diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index 8dd67f454..f7102e3ac 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -17,7 +17,7 @@ using codac2::Vector; namespace codac2 { Ellipsoid::Ellipsoid(Index n) - : mu(Vector(n)), G(Matrix(n, n)) { + : mu(Vector::zero(n)), G(Matrix::zero(n, n)) { assert_release(n > 0); } @@ -27,6 +27,7 @@ namespace codac2 { } Index Ellipsoid::size() const { + assert(mu.size() == G.cols() && G.is_squared()); return mu.size(); } @@ -89,13 +90,13 @@ namespace codac2 { return BoolInterval::TRUE; } - void Ellipsoid::projection2D(const Vector& d, const Vector& v, const Vector& u) + Ellipsoid Ellipsoid::proj_2d(const Vector& d, const Vector& v, const Vector& u) const { // from [Pope S. B. - Algorithms for Ellipsoids - 2008] - assert( d.size() == v.size()); - assert( d.size() == u.size()); - assert( d.size() == this->size()); - assert( (v.transpose()*u).norm() == 0); // u & v orthogonal + assert_release( d.size() == v.size()); + assert_release( d.size() == u.size()); + assert_release( d.size() == this->size()); + assert_release( (v.transpose()*u).norm() == 0); // u & v orthogonal // Normalized Projection matrix // the plane (d,u,v) is also the affine plan {x|x=d+Tt} with T = [u,v] @@ -104,22 +105,19 @@ namespace codac2 { T.col(1) = u/u.norm(); auto TTG = T.transpose() * this->G; - Eigen::BDCSVD bdcsvd(TTG, Eigen::ComputeFullU); - Matrix U(bdcsvd.matrixU()); - Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); - this->G = U * E; - this->mu = T.transpose() * (d + T * T.transpose() * (this->mu - d)); + Eigen::BDCSVD bdcsvd(TTG); + auto U = bdcsvd.matrixU(); + auto E = bdcsvd.singularValues().asDiagonal(); + + return { + T.transpose() * (d + T * T.transpose() * (this->mu - d)), + U * E + }; } Ellipsoid operator+(const Ellipsoid &e1, const Ellipsoid &e2) { assert_release(e1.size() == e2.size()); - //if(e1.is_unbounded() || e2.is_unbounded()) - // return Ellipsoid(e1.size()); - - //if(e1.is_empty() || e2.is_empty()) - // return Ellipsoid::empty(e1.size()); - auto Q1 = e1.G * e1.G.transpose(); auto Q2 = e2.G * e2.G.transpose(); @@ -176,14 +174,13 @@ namespace codac2 { assert(G.is_squared() && J.is_squared() && J_box.is_squared()); assert(n == J.cols() && n == J_box.cols() && n == q.size()); - Matrix JG = J * G; // note: reliability may be lost here! - IntervalMatrix G_(G); - IntervalMatrix JG_ = IntervalMatrix(JG); - IntervalVector unit_box(G.rows()); unit_box.init(Interval(-1,1)); + auto JG = J * G; // note: reliability may be lost here! + auto G_ = G.template cast(); + IntervalVector unit_box = IntervalVector::constant(G.rows(), {-1,1}); // normal case - IntervalMatrix I_ = IntervalMatrix(Eigen::MatrixXd::Identity(G.rows(),G.cols())); - IntervalMatrix JG_inv_(inverse_enclosure(JG)); // non rigourous inversion + IntervalMatrix I_ = IntervalMatrix::eye(G.rows(),G.cols()); + IntervalMatrix JG_inv_ = inverse_enclosure(JG); // rigourous inversion Matrix M(JG); auto W = JG_inv_; auto Z = I_; @@ -199,28 +196,26 @@ namespace codac2 { assert(q.size() == G.rows()); // SVD decomposition of JG = U*E*V.T - Eigen::BDCSVD bdcsvd(JG,Eigen::ComputeFullU); - IntervalMatrix U_(bdcsvd.matrixU()); // which is also the right part - Vector Sv(bdcsvd.singularValues()); // vectors of singular values + Eigen::BDCSVD bdcsvd(JG); + auto U_ = bdcsvd.matrixU().template cast(); // which is also the right part + auto Sv = bdcsvd.singularValues(); // vectors of singular values // select new singular values - int dim = G.rows(); - IntervalVector s_box(U_.transpose()*J_box*G_*unit_box); - IntervalMatrix S_(Eigen::MatrixXd::Zero(dim,dim)); // diagonal matrix of the new singular value - IntervalMatrix S_pinv_(Eigen::MatrixXd::Zero(dim,dim)); // pseudo inverse of S - for(int i=0;itrig[1]){ // normal size singular values S_(i,i) = Interval(Sv[i]); - S_pinv_(i,i) = 1/S_(i,i); }else{ // for very small singular values (0 included) use s_box - double val = s_box[i].ub(); - S_(i,i) = Interval(q[i]*val); - S_pinv_(i,i)=1/S_(i,i); + S_(i,i) = Interval(q[i])*s_box[i].ub(); } + S_pinv_(i,i) = 1./S_(i,i); } M = (U_*S_).mid(); W = S_pinv_*U_.transpose(); - Z = W*JG_; + Z = W*JG.template cast(); } auto b_box = (W * J_box * G_ - Z) * unit_box; @@ -253,7 +248,7 @@ namespace codac2 { ostream& operator<<(ostream& os, const Ellipsoid& e) { - os << "Ellipsoid:\n" + os << "Ellipsoid " << e.size() << "d:\n" << " mu=" << e.mu << "\n" << " G=\n" << e.G; return os; diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.h b/src/core/domains/ellipsoid/codac2_Ellipsoid.h index 9202861b9..a7ac9b3a5 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.h @@ -96,8 +96,9 @@ namespace codac2 * \param d a point on the plane * \param v a vector of the plane * \param u a other vector of the plane, orthogonal to v + * \return the projected 2d ellipsoid */ - void projection2D(const Vector& d, const Vector& v, const Vector& u); + Ellipsoid proj_2d(const Vector& d, const Vector& v, const Vector& u) const; public: diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp index 2416c9491..f14d3f2c2 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.cpp @@ -18,53 +18,66 @@ using codac2::BoolInterval; namespace codac2 { - Matrix solve_discrete_lyapunov(const Matrix& a,const Matrix& q) + Matrix solve_discrete_lyapunov(const Matrix& A, const Matrix& Q) { // implementation of the scipy solver for the discrete lyapunov equation (real matrix only) // works well under dimension 10 // https://github.com/scipy/scipy/blob/v1.14.1/scipy/linalg/_solvers.py#L235-L323 // Solves the discrete Lyapunov equation :math:`AXA^H - X + Q = 0` - assert(a.rows() == a.cols()); - assert(a.rows() == q.rows()); - assert(a.cols() == q.cols()); + assert(A.is_squared() && Q.is_squared()); + assert(A.size() == Q.size()); - Eigen::MatrixXd lhs = Eigen::KroneckerProduct(a, a); - lhs = Eigen::MatrixXd::Identity(lhs.rows(),lhs.cols()) - lhs; - Eigen::MatrixXd x = lhs.colPivHouseholderQr().solve((Eigen::VectorXd)q.reshaped()); - return Matrix(x.reshaped(q.rows(),q.cols())); + Matrix lhs = Eigen::KroneckerProduct(A,A); + lhs = Matrix::eye(lhs.rows(),lhs.cols()) - lhs; + Matrix x = lhs.colPivHouseholderQr().solve((Vector)Q.reshaped()); + return Matrix(x.reshaped(Q.rows(),Q.cols())); } - BoolInterval stability_analysis(const AnalyticFunction &f, int alpha_max, Ellipsoid &e, Ellipsoid &e_out) + BoolInterval stability_analysis(const AnalyticFunction &f, unsigned int alpha_max, Ellipsoid &e, Ellipsoid &e_out, bool verbose) { assert_release(f.args().size() == 1 && "f must have only one arg"); // get the Jacobian of f at the origin - int n = f.input_size(); + Index n = f.input_size(); Vector origin(Eigen::VectorXd::Zero(n)); Matrix J = f.diff(IntervalVector(origin)).mid(); // solve the axis aligned discrete lyapunov equation J.T * P * J − P = −J.T * J - Matrix P = solve_discrete_lyapunov(J.transpose(),J.transpose()*J); // TODO solve the Lyapunov equation !!! - Matrix G0((P.inverse()).sqrt()); - int alpha = 0; + auto P = solve_discrete_lyapunov(J.transpose(),J.transpose()*J); // TODO solve the Lyapunov equation !!! + auto G0 = P.inverse().sqrt(); + unsigned int alpha = 0; + + if(verbose) + cout << "Stability analysis:" << endl; while(alpha <= alpha_max) { - e = Ellipsoid(origin, std::pow(10,-alpha) * G0); + e = Ellipsoid(origin, std::pow(10.,-(int)alpha) * G0); e_out = nonlinear_mapping(e,f); - cout << "\nwith alpha = " << alpha << endl; - cout << "e is\n" << e << endl; - cout << "e_out is\n" << e_out << endl; + + if(verbose) + { + cout << "\t with alpha = " << alpha << endl; + cout << "\t e is\n" << e << endl; + cout << "\t e_out is\n" << e_out << endl; + } if(e_out.is_concentric_subset(e) == BoolInterval::TRUE) { - cout << "The system is stable" << endl; - cout << "Domain of attraction :\n" << e_out << endl; + if(verbose) + { + cout << "\t The system is stable" << endl; + cout << "\t Domain of attraction :\n" << e_out << endl; + } return BoolInterval::TRUE; } + alpha++; } - cout << "The method is not able to conclude on the stability" << endl; + + if(verbose) + cout << "\t The method is not able to conclude on the stability" << endl; + return BoolInterval::UNKNOWN; } } \ No newline at end of file diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h index 48265836b..452594236 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid_utils.h @@ -20,16 +20,17 @@ namespace codac2 * \param alpha_max ... * \param e ... * \param e_out ... + * \param verbose ... * \return ... */ - BoolInterval stability_analysis(const AnalyticFunction& f, int alpha_max, Ellipsoid& e, Ellipsoid& e_out); + BoolInterval stability_analysis(const AnalyticFunction& f, unsigned int alpha_max, Ellipsoid& e, Ellipsoid& e_out, bool verbose = false); /** * \brief ... * - * \param a ... - * \param q ... + * \param A ... + * \param Q ... * \return ... */ - Matrix solve_discrete_lyapunov(const Matrix& a, const Matrix& q); + Matrix solve_discrete_lyapunov(const Matrix& A, const Matrix& Q); } \ No newline at end of file diff --git a/src/graphics/CMakeLists.txt b/src/graphics/CMakeLists.txt index ca7d530ed..c18ba4b8c 100644 --- a/src/graphics/CMakeLists.txt +++ b/src/graphics/CMakeLists.txt @@ -12,7 +12,6 @@ ${CMAKE_CURRENT_SOURCE_DIR}/3rd/vibes/vibes.h ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2D.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2D_ellipsoid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2D.h ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2DInterface.h ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_OutputFigure2D.cpp diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index b3af3ef92..9f9d210d1 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -2,7 +2,7 @@ * codac2_Figure2D.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Morgan Louédec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -55,6 +55,16 @@ void Figure2D::set_axes(const FigureAxis& axis1, const FigureAxis& axis2) output_fig->update_axes(); } +const Index& Figure2D::i() const +{ + return axes()[0].dim_id; +} + +const Index& Figure2D::j() const +{ + return axes()[1].dim_id; +} + const Vector& Figure2D::pos() const { return _pos; @@ -199,6 +209,35 @@ void Figure2D::draw_ellipse(const Vector& c, const Vector& ab, double theta, con output_fig->draw_ellipse(c,ab,theta,s); } +void Figure2D::draw_ellipsoid(const Ellipsoid &e, const StyleProperties &s) { + // Author: Morgan Louédec + assert_release(this->size() <= e.size()); + + Index n = e.size(); + Ellipsoid proj_e(2); + + // 2d projection of the ellipsoid + if (n > 2) { + Vector v = Vector::zero(n); + v[i()] = 1; + Vector u = Vector::zero(n); + u[j()] = 1; + proj_e = e.proj_2d(Vector::zero(n), v, u); + } else { + proj_e = e; + } + + // draw the 2d ellipsoid + Eigen::JacobiSVD jsvd(proj_e.G, Eigen::ComputeThinU); + Matrix U(jsvd.matrixU()); + Vector ab(jsvd.singularValues()); + + double theta = std::atan2(U(1, 0), U(0, 0)); + + for(const auto& output_fig : _output_figures) + output_fig->draw_ellipse(proj_e.mu, ab, theta, s); +} + void Figure2D::draw_tank(const Vector& x, float size, const StyleProperties& s) { assert_release(this->size() <= x.size()+1); diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 7ed01306a..81e58764c 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -70,6 +70,9 @@ namespace codac2 const std::vector& axes() const; void set_axes(const FigureAxis& axis1, const FigureAxis& axis2); + const Index& i() const; + const Index& j() const; + const Vector& pos() const; const Vector& window_size() const; void set_window_properties(const Vector& pos, const Vector& size); diff --git a/src/graphics/figures/codac2_Figure2D_ellipsoid.cpp b/src/graphics/figures/codac2_Figure2D_ellipsoid.cpp deleted file mode 100644 index 4d1c83738..000000000 --- a/src/graphics/figures/codac2_Figure2D_ellipsoid.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/** - * codac2_Figure2D.cpp - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Morgan Louédec - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include "codac2_Index.h" -#include "codac2_Figure2D.h" -#include "codac2_matrices.h" -#include "codac2_Matrix.h" - -using namespace std; -using codac2::Vector; -using codac2::Matrix; - -void codac2::Figure2D::draw_ellipsoid(const codac2::Ellipsoid &e, const codac2::StyleProperties &s) { - //assert_release(this->size() <= e.size()); - for (const auto &output_fig: _output_figures) { - Matrix G_draw(2, 2); - Vector mu_draw(2); - // 2d projection of the ellipsoid - if (e.size() > 2) { - // affine space of the projection - Vector d(Eigen::VectorXd::Zero(e.mu.rows())); - Matrix T(Eigen::MatrixXd::Zero(e.G.rows(), 2)); - T(output_fig->i(), 0) = 1; - T(output_fig->j(), 1) = 1; - - // project ellipsoid E(mu,Q) = {x in R^n | (x-mu).T*G.{-T}*G^{-1}*(x-mu)<1} - // on the affine plan A = {x|x=d+Tt} [Pope -2008] - // reduce the dimensions of mu and Q - - auto TTG = T.transpose().eval() * e.G; - Eigen::BDCSVD bdcsvd(Matrix(TTG.eval()), Eigen::ComputeFullU); - Matrix U(bdcsvd.matrixU()); - Matrix E((Eigen::MatrixXd) bdcsvd.singularValues().asDiagonal()); - G_draw = U * E; - mu_draw = T.transpose() * (d + T * T.transpose() * (e.mu - d)); - } else { - G_draw = e.G; - mu_draw = e.mu; - } - - // draw the 2d ellipsoid - Eigen::JacobiSVD jsvd(G_draw, Eigen::ComputeThinU); - Matrix U(jsvd.matrixU()); - Vector ab(jsvd.singularValues()); - - double theta = atan2(U(1, 0), U(0, 0)).mid(); - - output_fig->draw_ellipse(mu_draw, ab, theta, s); - } -} \ No newline at end of file diff --git a/src/graphics/figures/codac2_OutputFigure2D.cpp b/src/graphics/figures/codac2_OutputFigure2D.cpp index 56d37b263..32afc150d 100644 --- a/src/graphics/figures/codac2_OutputFigure2D.cpp +++ b/src/graphics/figures/codac2_OutputFigure2D.cpp @@ -16,10 +16,10 @@ using namespace codac2; const Index& OutputFigure2D::i() const { - return _fig.axes()[0].dim_id; + return _fig.i(); } const Index& OutputFigure2D::j() const { - return _fig.axes()[1].dim_id; + return _fig.j(); } \ No newline at end of file From 49b972d21727540c9f332610f4f8ed16ed5115ca Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sun, 15 Dec 2024 12:22:32 +0100 Subject: [PATCH 025/126] [git.actions] removed '-j4' build option (difficulty to compile Eigen templates?) --- .github/workflows/unixmatrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unixmatrix.yml b/.github/workflows/unixmatrix.yml index 41c66beaf..e5367d6c1 100644 --- a/.github/workflows/unixmatrix.yml +++ b/.github/workflows/unixmatrix.yml @@ -147,7 +147,7 @@ jobs: if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi mkdir build ; cd build cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D CMAKE_INSTALL_PREFIX="../codac" .. - cmake --build . -j 4 --config Debug --target install + cmake --build . --config Debug --target install cd .. sed_param=s/PATH_SUFFIXES\ /PATHS\ \$\{CMAKE_CURRENT_LIST_FILE\}\\/..\\/..\\/..\\/..\\/\ PATH_SUFFIXES\ / if [ ${{ runner.os }} = Windows ]; then sed -i "$sed_param" codac/share/codac/cmake/*.cmake ; fi From 100f61fc82e0f12cf7a05c8c5f4e4610234cf2ac Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Mon, 16 Dec 2024 20:05:18 +0100 Subject: [PATCH 026/126] [ellips] py binding: C++ cast of AnalyticFunction py objects --- .../domains/ellipsoid/codac2_py_Ellipsoid.cpp | 11 +++++++++-- .../analytic/codac2_py_AnalyticFunction.h | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp index e1784a10a..404f20343 100644 --- a/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp +++ b/python/src/core/domains/ellipsoid/codac2_py_Ellipsoid.cpp @@ -13,6 +13,7 @@ #include #include #include "codac2_py_Ellipsoid_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_AnalyticFunction.h" using namespace std; using namespace codac2; @@ -80,11 +81,17 @@ void export_Ellipsoid(py::module& m) ELLIPSOID_UNRELIABLE_LINEAR_MAPPING_CONST_ELLIPSOID_REF_CONST_MATRIX_REF_CONST_VECTOR_REF, "e"_a, "A"_a, "b"_a) - .def("nonlinear_mapping_", (Ellipsoid (*)(const Ellipsoid&,const AnalyticFunction&))&codac2::nonlinear_mapping, + .def("nonlinear_mapping", [](const Ellipsoid& e, py::object f) + { + return nonlinear_mapping(e, pyobject_to_AnalyticFunction(f)); + }, ELLIPSOID_NONLINEAR_MAPPING_CONST_ELLIPSOID_REF_CONST_ANALYTICFUNCTION_VECTOROPVALUE_REF, "e"_a, "f"_a) - .def("nonlinear_mapping_", (Ellipsoid (*)(const Ellipsoid&,const AnalyticFunction&,const Vector&,const Vector&))&codac2::nonlinear_mapping, + .def("nonlinear_mapping", [](const Ellipsoid& e, py::object f, const Vector &trig, const Vector &q) + { + return nonlinear_mapping(e, pyobject_to_AnalyticFunction(f), trig, q); + }, ELLIPSOID_NONLINEAR_MAPPING_CONST_ELLIPSOID_REF_CONST_ANALYTICFUNCTION_VECTOROPVALUE_REF_CONST_VECTOR_REF_CONST_VECTOR_REF, "e"_a, "f"_a, "trig"_a, "q"_a) diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index 9dd8c75b1..9647582bf 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -25,6 +25,22 @@ using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; +inline AnalyticFunction pyobject_to_AnalyticFunction(py::object f) +{ + if(py::isinstance>(f)) + return f.cast>(); + + else + { + // Trying to extract an AnalyticFunction + // from the python wrapper 'AnalyticFunction' + py::object f_ = f.attr("f"); + if(!py::isinstance>(f_)) + assert_release("invalid argument: AnalyticFunction expected"); + return f_.cast>(); + } +} + #define bind_(exported, op_name, op, doc) \ \ exported \ From af0e27c100e2f9bed08bf7157200d64a5b24d4fb Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 17 Dec 2024 17:09:54 +0100 Subject: [PATCH 027/126] [fnc] updated AnalyticFunction (EvalMode, real_eval()) --- python/codac/core/__init__.py | 12 +-- python/src/core/codac2_py_core.cpp | 7 ++ .../analytic/codac2_py_AnalyticFunction.h | 36 ++++++- src/core/contractors/codac2_CtcProj.h | 1 + .../analytic/codac2_AnalyticFunction.h | 95 ++++++++++--------- src/core/separators/codac2_SepProj.h | 1 + .../trajectory/codac2_AnalyticTrajectory.h | 2 +- .../trajectory/codac2_SampledTrajectory.h | 13 ++- .../codac2_tests_AnalyticFunction.cpp | 32 +++---- .../analytic/codac2_tests_AnalyticFunction.py | 16 ++-- .../codac2_tests_AnalyticTrajectory.cpp | 2 +- .../codac2_tests_AnalyticTrajectory.py | 2 +- 12 files changed, 134 insertions(+), 85 deletions(-) diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index 4eeab90eb..1c9cd2207 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -28,14 +28,14 @@ def __init__(self, args, e): def input_size(self): return self.f.input_size() - def eval(self,*args): - return self.f.eval(*args) + def real_eval(self,*args): + return self.f.real_eval(*args) - def natural_eval(self,*args): - return self.f.natural_eval(*args) + def eval(self,m,*args): + return self.f.eval(m,*args) - def centered_eval(self,*args): - return self.f.centered_eval(*args) + def eval(self,*args): + return self.f.eval(*args) def diff(self,*args): return self.f.diff(*args) diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index 5176b48d3..04a1a0f73 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -185,6 +185,13 @@ PYBIND11_MODULE(_core, m) export_Subpaving(m); // function + py::enum_(m, "EvalMode") + .value("NATURAL", EvalMode::NATURAL) + .value("CENTERED", EvalMode::CENTERED) + .value("DEFAULT", EvalMode::DEFAULT) + .def(py::self | py::self, EVALMODE_OPERATOROR_EVALMODE_EVALMODE) + ; + export_ExprWrapperBase(m); export_ScalarExpr(m); export_VectorExpr(m); diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index 9dd8c75b1..dc4e57000 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -25,6 +25,38 @@ using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; +#define bind_mode_(exported, op_name, op, doc) \ + \ + exported \ + \ + /* Several cases of scalar inputs */ \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m) { return f.op(m); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1) { return f.op(m,x1); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2) { return f.op(m,x1,x2); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2, I x3) { return f.op(m,x1,x2,x3); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2, I x3, I x4) { return f.op(m,x1,x2,x3,x4); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2, I x3, I x4, I x5) { return f.op(m,x1,x2,x3,x4,x5); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2, I x3, I x4, I x5, I x6) { return f.op(m,x1,x2,x3,x4,x5,x6); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2, I x3, I x4, I x5, I x6, I x7) { return f.op(m,x1,x2,x3,x4,x5,x6,x7); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2, I x3, I x4, I x5, I x6, I x7, I x8) { return f.op(m,x1,x2,x3,x4,x5,x6,x7,x8); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2, I x3, I x4, I x5, I x6, I x7, I x8, I x9) { return f.op(m,x1,x2,x3,x4,x5,x6,x7,x8,x9); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, I x1, I x2, I x3, I x4, I x5, I x6, I x7, I x8, I x9, I x10) { return f.op(m,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10); }, doc) \ + \ + /* Several cases of vector inputs */ \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m) { return f.op(m); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1) { return f.op(m,x1); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2) { return f.op(m,x1,x2); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2, IV x3) { return f.op(m,x1,x2,x3); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2, IV x3, IV x4) { return f.op(m,x1,x2,x3,x4); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2, IV x3, IV x4, IV x5) { return f.op(m,x1,x2,x3,x4,x5); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2, IV x3, IV x4, IV x5, IV x6) { return f.op(m,x1,x2,x3,x4,x5,x6); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2, IV x3, IV x4, IV x5, IV x6, IV x7) { return f.op(m,x1,x2,x3,x4,x5,x6,x7); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2, IV x3, IV x4, IV x5, IV x6, IV x7, IV x8) { return f.op(m,x1,x2,x3,x4,x5,x6,x7,x8); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2, IV x3, IV x4, IV x5, IV x6, IV x7, IV x8, IV x9) { return f.op(m,x1,x2,x3,x4,x5,x6,x7,x8,x9); }, doc) \ + .def(op_name, [](AnalyticFunction& f, const EvalMode& m, IV x1, IV x2, IV x3, IV x4, IV x5, IV x6, IV x7, IV x8, IV x9, IV x10) { return f.op(m,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10); }, doc) \ + \ + ; \ + #define bind_(exported, op_name, op, doc) \ \ exported \ @@ -103,9 +135,9 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) using I = const Interval&; using IV = const IntervalVector&; + bind_(exported, "real_eval", real_eval, AUTO_ANALYTICFUNCTION_T_REAL_EVAL_CONST_ARGS_REF_VARIADIC_CONST); + bind_mode_(exported, "eval", eval, T_DOMAIN_ANALYTICFUNCTION_T_EVAL_CONST_ARGS_REF_VARIADIC_CONST); bind_(exported, "eval", eval, T_DOMAIN_ANALYTICFUNCTION_T_EVAL_CONST_ARGS_REF_VARIADIC_CONST); - bind_(exported, "natural_eval", natural_eval, T_DOMAIN_ANALYTICFUNCTION_T_NATURAL_EVAL_CONST_ARGS_REF_VARIADIC_CONST); - bind_(exported, "centered_eval", centered_eval, T_DOMAIN_ANALYTICFUNCTION_T_CENTERED_EVAL_CONST_ARGS_REF_VARIADIC_CONST); bind_(exported, "diff", diff, AUTO_ANALYTICFUNCTION_T_DIFF_CONST_ARGS_REF_VARIADIC_CONST); exported diff --git a/src/core/contractors/codac2_CtcProj.h b/src/core/contractors/codac2_CtcProj.h index 00dff8a38..1515d10e2 100644 --- a/src/core/contractors/codac2_CtcProj.h +++ b/src/core/contractors/codac2_CtcProj.h @@ -35,6 +35,7 @@ namespace codac2 assert_release(*min_element(_xi.begin(),_xi.end()) >= 0); assert_release(*max_element(_xi.begin(),_xi.end()) < size_of(c)); assert_release(size_of(c) >= (Index)_xi.size() && "cannot compute a projection of a set into a superset"); + assert_release(y.is_bisectable()); assert_release(default_eps > 0.); } diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index 23a4aae59..31099e435 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -19,17 +19,18 @@ namespace codac2 { - enum class EvaluationMode + enum class EvalMode { NATURAL = 0x01, - CENTERED = 0x02 + CENTERED = 0x02, + DEFAULT = 0x03 // corresponds to (NATURAL|CENTERED) }; - inline EvaluationMode operator&(EvaluationMode a, EvaluationMode b) - { return static_cast(static_cast(a) & static_cast(b)); } + inline EvalMode operator&(EvalMode a, EvalMode b) + { return static_cast(static_cast(a) & static_cast(b)); } - inline EvaluationMode operator|(EvaluationMode a, EvaluationMode b) - { return static_cast(static_cast(a) | static_cast(b)); } + inline EvalMode operator|(EvalMode a, EvalMode b) + { return static_cast(static_cast(a) | static_cast(b)); } template requires std::is_base_of_v @@ -53,56 +54,60 @@ namespace codac2 { } template - typename T::Domain eval(const EvaluationMode& m, const Args&... x) const + auto real_eval(const Args&... x) const { - switch(m) - { - case EvaluationMode::NATURAL: - return natural_eval(x...); - - case EvaluationMode::CENTERED: - return centered_eval(x...); - - default: - return eval(x...); - } + return eval(x...).mid(); } template - typename T::Domain eval(const Args&... x) const + typename T::Domain eval(const EvalMode& m, const Args&... x) const { check_valid_inputs(x...); auto x_ = eval_(x...); - if(x_.da.size() == 0) // if the centered form is not available for this expression - return natural_eval(x...); - - auto flatten_x = cart_prod(x...); - - if constexpr(std::is_same_v) - return x_.a & (x_.m + (x_.da*(flatten_x-flatten_x.mid()))[0]); - else - return x_.a & (x_.m + (x_.da*(flatten_x-flatten_x.mid())).col(0)); - } - - template - typename T::Domain natural_eval(const Args&... x) const - { - check_valid_inputs(x...); - return eval_(x...).a; + switch(m) + { + case EvalMode::NATURAL: + { + return x_.a; + } + + case EvalMode::CENTERED: + { + auto flatten_x = cart_prod(x...); + assert(x_.da.rows() == x_.a.size() && x_.da.cols() == flatten_x.size()); + + if constexpr(std::is_same_v) + return x_.m + (x_.da*(flatten_x-flatten_x.mid()))[0]; + else + return x_.m + (x_.da*(flatten_x-flatten_x.mid())).col(0); + } + + case EvalMode::DEFAULT: + default: + { + if(x_.da.size() == 0) // if the centered form is not available for this expression + return eval(EvalMode::NATURAL, x...); + + else + { + auto flatten_x = cart_prod(x...); + if constexpr(std::is_same_v) + return x_.a & (x_.m + (x_.da*(flatten_x-flatten_x.mid()))[0]); + else + { + assert(x_.da.rows() == x_.a.size() && x_.da.cols() == flatten_x.size()); + return x_.a & (x_.m + (x_.da*(flatten_x-flatten_x.mid())).col(0)); + } + } + } + } } template - typename T::Domain centered_eval(const Args&... x) const + typename T::Domain eval(const Args&... x) const { - check_valid_inputs(x...); - auto x_ = eval_(x...); - auto flatten_x = cart_prod(x...); - - if constexpr(std::is_same_v) - return x_.m + (x_.da*(flatten_x-flatten_x.mid()))[0]; - else - return x_.m + (x_.da*(flatten_x-flatten_x.mid())).col(0); + return eval(EvalMode::NATURAL | EvalMode::CENTERED, x...); } template @@ -122,7 +127,7 @@ namespace codac2 // A dump evaluation is performed to estimate the dimension // of the image of this function. A natural evaluation is assumed // to be faster. - return natural_eval(IntervalVector(this->input_size())).size(); + return eval(EvalMode::NATURAL, IntervalVector(this->input_size())).size(); } else diff --git a/src/core/separators/codac2_SepProj.h b/src/core/separators/codac2_SepProj.h index c7dfa3599..33bef8430 100644 --- a/src/core/separators/codac2_SepProj.h +++ b/src/core/separators/codac2_SepProj.h @@ -36,6 +36,7 @@ namespace codac2 assert_release(*min_element(_xi.begin(),_xi.end()) >= 0); assert_release(*max_element(_xi.begin(),_xi.end()) < size_of(s)); assert_release(size_of(s) >= (Index)_xi.size() && "cannot compute a projection of a set into a superset"); + assert_release(y.is_bisectable()); assert_release(default_eps > 0.); } diff --git a/src/core/trajectory/codac2_AnalyticTrajectory.h b/src/core/trajectory/codac2_AnalyticTrajectory.h index 126107df4..b0b8f5ad8 100644 --- a/src/core/trajectory/codac2_AnalyticTrajectory.h +++ b/src/core/trajectory/codac2_AnalyticTrajectory.h @@ -56,7 +56,7 @@ namespace codac2 { if(!this->tdomain().contains(t)) return this->nan_value(); - return AnalyticFunction::eval(t).mid(); + return AnalyticFunction::real_eval(t); } virtual typename Wrapper::Domain operator()(const Interval& t) const diff --git a/src/core/trajectory/codac2_SampledTrajectory.h b/src/core/trajectory/codac2_SampledTrajectory.h index 52c5b8070..f39ab82d9 100644 --- a/src/core/trajectory/codac2_SampledTrajectory.h +++ b/src/core/trajectory/codac2_SampledTrajectory.h @@ -115,11 +115,14 @@ namespace codac2 if(!this->tdomain().is_superset(t)) return hull.init(Interval(-oo,oo)); - hull.set_empty(); - for(auto it = this->lower_bound(t.lb()) ; it != this->upper_bound(t.ub()) ; it++) - hull |= it->second; - hull |= (*this)(t.ub()); - return hull; + else + { + hull = (*this)(t.lb()); + for(auto it = this->lower_bound(t.lb()) ; it != this->upper_bound(t.ub()) ; it++) + hull |= it->second; + hull |= (*this)(t.ub()); + return hull; + } } virtual SampledTrajectory sampled(double dt) const diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp index cc09983c2..8fabf900b 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp @@ -18,10 +18,10 @@ using namespace codac2; TEST_CASE("AnalyticFunction") { - std::array modes { - EvaluationMode::NATURAL, - EvaluationMode::CENTERED, - EvaluationMode::NATURAL | EvaluationMode::NATURAL + std::array modes { + EvalMode::NATURAL, + EvalMode::CENTERED, + EvalMode::NATURAL | EvalMode::NATURAL }; for(const auto& m : modes) // try all available evaluation modes @@ -114,7 +114,7 @@ TEST_CASE("AnalyticFunction") // .def("__mul__", {}(const ScalarVar& e1, const VectorVar& e2); CHECK(AnalyticFunction({v1,v2}, v1[0]*v2).eval(m, Vector({5.,10.}),IntervalVector({3,3})) == Vector({15,15})); // .def("__mul__", {}(const ScalarVar& e1, const IntervalVector& e2); - CHECK(AnalyticFunction({x1}, x1*IntervalVector({{-2,3},{0,1}})).centered_eval(5.) == IntervalVector({{-10,15},{0,5}})); + CHECK(AnalyticFunction({x1}, x1*IntervalVector({{-2,3},{0,1}})).eval(EvalMode::CENTERED,5.) == IntervalVector({{-10,15},{0,5}})); // .def("__truediv__", {}(const ScalarVar& e1, const ScalarVar& e2); CHECK(Approx(AnalyticFunction({x1,x2}, x1/x2).eval(m, 1.,10.)) == 0.1); // .def("__truediv__", {}(const ScalarVar& e1, const Interval& e2); @@ -195,19 +195,19 @@ TEST_CASE("AnalyticFunction") //.def("__pos__", {}(const VectorExpr& e1); CHECK(Approx(AnalyticFunction({v1}, +(v1+v1)).eval(m, IntervalVector({{0.},{-oo,5}}))) == - (m == EvaluationMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-oo,10}}))); + (m == EvalMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-oo,10}}))); //.def(py::self + py::self); CHECK(Approx(AnalyticFunction({v1}, v1+v1).eval(m, IntervalVector({{0.},{-oo,5}}))) == - (m == EvaluationMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-oo,10}}))); + (m == EvalMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-oo,10}}))); //.def("__radd__", {}(const VectorExpr& e1, const VectorVar& e2); CHECK(Approx(AnalyticFunction({v1}, (v1+v1)+v1).eval(m, IntervalVector({{0.},{-oo,5}}))) == - (m == EvaluationMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-oo,15}}))); + (m == EvalMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-oo,15}}))); //.def("__radd__", {}(const VectorExpr& e1, const IntervalVector& e2); CHECK(Approx(AnalyticFunction({v1}, v1+(v1+v1)).eval(m, IntervalVector({{0.},{-oo,5}}))) == - (m == EvaluationMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-oo,15}}))); + (m == EvalMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-oo,15}}))); //.def(- py::self); CHECK(Approx(AnalyticFunction({v1}, -(v1+v1)).eval(m, IntervalVector({{0.},{-oo,5}}))) == - (m == EvaluationMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-10,oo}}))); + (m == EvalMode::CENTERED ? IntervalVector({{0.},{-oo,oo}}) : IntervalVector({{0.},{-10,oo}}))); //.def(py::self - py::self); CHECK(Approx(AnalyticFunction({v1,v2}, (v1-v2)).eval(m, IntervalVector({2,3}),Vector({1,5}))) == IntervalVector({1,-2})); //.def("__sub__", {}(const VectorExpr& e1, const VectorVar& e2); @@ -256,8 +256,8 @@ TEST_CASE("AnalyticFunction") { ScalarVar x; AnalyticFunction f({x}, x-x); - CHECK(f.natural_eval(Interval(-1,1)) == Interval(-2,2)); - CHECK(f.centered_eval(Interval(-1,1)) == Interval(0)); + CHECK(f.eval(EvalMode::NATURAL,Interval(-1,1)) == Interval(-2,2)); + CHECK(f.eval(EvalMode::CENTERED,Interval(-1,1)) == Interval(0)); CHECK(f.eval(Interval(-1,1)) == Interval(0)); } @@ -271,13 +271,13 @@ TEST_CASE("AnalyticFunction") IntervalVector a(4); a = IntervalVector({1,2,3,4}); - CHECK(g.natural_eval(a) == 14); - CHECK(g.centered_eval(a) == 14); + CHECK(g.eval(EvalMode::NATURAL,a) == 14); + CHECK(g.eval(EvalMode::CENTERED,a) == 14); CHECK(g.eval(a) == 14); a = IntervalVector({0,2,5,4}); - CHECK(g.natural_eval(a) == 20); - CHECK(g.centered_eval(a) == 20); + CHECK(g.eval(EvalMode::NATURAL,a) == 20); + CHECK(g.eval(EvalMode::CENTERED,a) == 20); CHECK(g.eval(a) == 20); } } \ No newline at end of file diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py index 2dc923371..e27da09bd 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py @@ -34,10 +34,10 @@ def invalid_function(): def test_eval(f,*args): if(i == 0): # natural - return f.natural_eval(*args) + return f.eval(EvalMode.NATURAL,*args) elif(i == 1): # centered - return f.centered_eval(*args) + return f.eval(EvalMode.CENTERED,*args) else: # centered and natural return f.eval(*args) @@ -232,8 +232,8 @@ def test_eval(f,*args): # Evaluation modes x = ScalarVar() f = AnalyticFunction([x], x-x) - self.assertTrue(f.natural_eval(Interval(-1,1)) == Interval(-2,2)) - self.assertTrue(f.centered_eval(Interval(-1,1)) == Interval(0)) + self.assertTrue(f.eval(EvalMode.NATURAL,Interval(-1,1)) == Interval(-2,2)) + self.assertTrue(f.eval(EvalMode.CENTERED,Interval(-1,1)) == Interval(0)) self.assertTrue(f.eval(Interval(-1,1)) == Interval(0)) # Subvector on variables @@ -245,13 +245,13 @@ def test_eval(f,*args): a = IntervalVector(4) a = IntervalVector([[1],[2],[3],[4]]) - self.assertTrue(g.natural_eval(a) == 14) - self.assertTrue(g.centered_eval(a) == 14) + self.assertTrue(g.eval(EvalMode.NATURAL,a) == 14) + self.assertTrue(g.eval(EvalMode.CENTERED,a) == 14) self.assertTrue(g.eval(a) == 14) a = IntervalVector([[0],[2],[5],[4]]) - self.assertTrue(g.natural_eval(a) == 20) - self.assertTrue(g.centered_eval(a) == 20) + self.assertTrue(g.eval(EvalMode.NATURAL,a) == 20) + self.assertTrue(g.eval(EvalMode.CENTERED,a) == 20) self.assertTrue(g.eval(a) == 20) if __name__ == '__main__': diff --git a/tests/core/trajectory/codac2_tests_AnalyticTrajectory.cpp b/tests/core/trajectory/codac2_tests_AnalyticTrajectory.cpp index 2fcf8b0f2..2853c2abc 100644 --- a/tests/core/trajectory/codac2_tests_AnalyticTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_AnalyticTrajectory.cpp @@ -50,7 +50,7 @@ TEST_CASE("AnalyticTrajectory") CHECK(Approx(sampled_traj(9.),1e-2) == 81.); // Testing primitive computation from analytic trajectory - double x0 = f.eval(-1).mid(); // == 1. + double x0 = f.real_eval(-1); // == 1. auto sampled_prim_traj = traj.primitive(x0,0.01); CHECK(sampled_prim_traj.tdomain() == Interval(-1,10)); CHECK(Approx(sampled_prim_traj.codomain(),4e-1) == Interval(prim_value(0),prim_value(10.))); diff --git a/tests/core/trajectory/codac2_tests_AnalyticTrajectory.py b/tests/core/trajectory/codac2_tests_AnalyticTrajectory.py index c4d76672e..2e1583a71 100644 --- a/tests/core/trajectory/codac2_tests_AnalyticTrajectory.py +++ b/tests/core/trajectory/codac2_tests_AnalyticTrajectory.py @@ -48,7 +48,7 @@ def tests_AnalyticTrajectory(self): self.assertTrue(Approx(sampled_traj(9.),1e-2) == 81.) # Testing primitive computation from analytic trajectory - x0 = f.eval(-1).mid() # == 1. + x0 = f.real_eval(-1) # == 1. sampled_prim_traj = traj.primitive(x0,0.01) self.assertTrue(sampled_prim_traj.tdomain() == Interval(-1,10)) self.assertTrue(Approx(sampled_prim_traj.codomain(),4e-1) == Interval(prim_value(0),prim_value(10.))) From 2953acabce6ee30366051a8f0bcca28ceb174a3d Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Tue, 17 Dec 2024 19:17:21 +0100 Subject: [PATCH 028/126] Attempt to solve error: number of sections exceeded object file format limit --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a39db1a1..f88dbbc10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,13 @@ add_compile_options(-Wall -Wextra -Wpedantic) endif() + # Temporary fix in case of error: number of sections exceeded object file format limit. + if(MSVC) + add_compile_options(/bigobj) + elseif(MINGW) + add_compile_options(-Wa,-mbig-obj) + endif() + # # Check that the compiler supports c++20 # include(CheckCXXCompilerFlag) # check_cxx_compiler_flag("-std=c++2a" COMPILER_SUPPORTS_CXX20) From a1321dbaed4d67d1e3583a73188c999a09f34482 Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Tue, 17 Dec 2024 19:51:48 +0100 Subject: [PATCH 029/126] Revert "[git.actions] removed '-j4' build option (difficulty to compile Eigen templates?)" This reverts commit 49b972d21727540c9f332610f4f8ed16ed5115ca. --- .github/workflows/unixmatrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unixmatrix.yml b/.github/workflows/unixmatrix.yml index e5367d6c1..41c66beaf 100644 --- a/.github/workflows/unixmatrix.yml +++ b/.github/workflows/unixmatrix.yml @@ -147,7 +147,7 @@ jobs: if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi mkdir build ; cd build cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D CMAKE_INSTALL_PREFIX="../codac" .. - cmake --build . --config Debug --target install + cmake --build . -j 4 --config Debug --target install cd .. sed_param=s/PATH_SUFFIXES\ /PATHS\ \$\{CMAKE_CURRENT_LIST_FILE\}\\/..\\/..\\/..\\/..\\/\ PATH_SUFFIXES\ / if [ ${{ runner.os }} = Windows ]; then sed -i "$sed_param" codac/share/codac/cmake/*.cmake ; fi From d88420b90a6805f4b2b2c5b7e1cf2b789c1f5a67 Mon Sep 17 00:00:00 2001 From: godardma Date: Wed, 18 Dec 2024 17:21:31 +0100 Subject: [PATCH 030/126] [graphics] colormaps for trajectories --- .../graphics/figures/codac2_py_Figure2D.cpp | 50 +++++++++++++++++++ src/graphics/figures/codac2_Figure2D.cpp | 30 +++++++++++ src/graphics/figures/codac2_Figure2D.h | 17 +++++++ 3 files changed, 97 insertions(+) diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index f976cca23..71d7fac4b 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -151,6 +151,31 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTOROPVALUE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) + .def("draw_trajectory", [](Figure2D& fig, py::object x, const ColorMap& cmap) + { + py::object x_traj = x.attr("traj"); + + if(x_traj) + { + if(py::isinstance>(x_traj)) + { + fig.draw_trajectory(x_traj.cast>(),cmap); + return; + } + + else if(py::isinstance>(x_traj)) + { + fig.draw_trajectory(x_traj.cast>(),cmap); + return; + } + } + + assert_release(false && + "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); + }, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTOROPVALUE_REF_CONST_STYLEPROPERTIES_REF, + "x"_a, "cmap"_a) + // Robots .def("draw_tank", &Figure2D::draw_tank, @@ -247,6 +272,31 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTOROPVALUE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) + .def_static("draw_trajectory", [](py::object x, const ColorMap& cmap) + { + py::object x_traj = x.attr("traj"); + + if(x_traj) + { + if(py::isinstance>(x_traj)) + { + DefaultView::draw_trajectory(x_traj.cast>(),cmap); + return; + } + + else if(py::isinstance>(x_traj)) + { + DefaultView::draw_trajectory(x_traj.cast>(),cmap); + return; + } + } + + assert_release(false && + "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); + }, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTOROPVALUE_REF_CONST_STYLEPROPERTIES_REF, + "x"_a, "cmap"_a) + // Robots .def_static("draw_tank", &DefaultView::draw_tank, diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 608da895f..d285aff21 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -138,6 +138,16 @@ void Figure2D::draw_ring(const Vector& c, const Interval& r, const StyleProperti output_fig->draw_ring(c,r,s); } +void Figure2D::draw_line(const Vector& x, const Vector& y, const StyleProperties& s) +{ + assert_release(x.size() == y.size()); + assert_release(x.size() == 2); + vector points = {x,y}; + + for(const auto& output_fig : _output_figures) + output_fig->draw_polyline(points,1e-3*scaled_unit(),s); +} + void Figure2D::draw_polyline(const vector& x, const StyleProperties& s) { draw_polyline(x, 1e-3*scaled_unit(), s); @@ -212,6 +222,26 @@ void Figure2D::draw_trajectory(const AnalyticTrajectory& x, const draw_trajectory(x.sampled(x.tdomain().diam()/1e4), s); } +void Figure2D::draw_trajectory(const SampledTrajectory& x, const ColorMap& cmap) +{ + assert_release(this->size() <= x.size()); + + std::vector values(2); + values[0] = x.begin()->second; + for (auto it = std::next(x.begin()); it != x.end(); ++it) + { + values[1] = it->second; + Color color = cmap.color((it->first - x.begin()->first) / (x.rbegin()->first - x.begin()->first)); + draw_polyline(values, color); + values[0] = values[1]; + } +} + +void Figure2D::draw_trajectory(const AnalyticTrajectory& x, const ColorMap& cmap) +{ + draw_trajectory(x.sampled(x.tdomain().diam()/1e4), cmap); +} + void Figure2D::draw_tank(const Vector& x, float size, const StyleProperties& s) { assert_release(this->size() <= x.size()+1); diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 0f2bf9a7e..41c494d7a 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -16,6 +16,7 @@ #include "codac2_Figure2DInterface.h" #include "codac2_OutputFigure2D.h" #include "codac2_Paving.h" +#include "codac2_ColorMap.h" #define DEFAULT_FIG_NAME "Codac - default view" @@ -85,6 +86,7 @@ namespace codac2 void draw_box(const IntervalVector& x, const StyleProperties& s = StyleProperties()); void draw_circle(const Vector& c, double r, const StyleProperties& s = StyleProperties()); void draw_ring(const Vector& c, const Interval& r, const StyleProperties& s = StyleProperties()); + void draw_line(const Vector& x1, const Vector& x2, const StyleProperties& s = StyleProperties()); void draw_polyline(const std::vector& x, const StyleProperties& s = StyleProperties()); void draw_polyline(const std::vector& x, float tip_length, const StyleProperties& s = StyleProperties()); void draw_polygone(const std::vector& x, const StyleProperties& s = StyleProperties()); @@ -92,6 +94,9 @@ namespace codac2 void draw_ellipse(const Vector& c, const Vector& ab, double theta, const StyleProperties& s = StyleProperties()); void draw_trajectory(const SampledTrajectory& x, const StyleProperties& s = StyleProperties()); void draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s = StyleProperties()); + void draw_trajectory(const SampledTrajectory& x, const ColorMap& cmap); + void draw_trajectory(const AnalyticTrajectory& x, const ColorMap& cmap); + // Robots void draw_tank(const Vector& x, float size, const StyleProperties& s = StyleProperties()); void draw_AUV(const Vector& x, float size, const StyleProperties& s = StyleProperties()); @@ -218,6 +223,18 @@ namespace codac2 selected_fig()->draw_trajectory(x,s); } + static void draw_trajectory(const SampledTrajectory& x, const ColorMap& cmap) + { + auto_init(); + selected_fig()->draw_trajectory(x,cmap); + } + + static void draw_trajectory(const AnalyticTrajectory& x, const ColorMap& cmap) + { + auto_init(); + selected_fig()->draw_trajectory(x,cmap); + } + // Robots static void draw_tank(const Vector& x, float size, const StyleProperties& s = StyleProperties()) From ffebe251ac1ac0aad9b69cfd9a026764696aec86 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 19 Dec 2024 08:21:08 +0100 Subject: [PATCH 031/126] [fnc] (Sampled)Trajectory can now be involved in analytic expressions --- src/core/CMakeLists.txt | 2 + .../analytic/codac2_analytic_operations.h | 6 ++ .../trajectory/codac2_AnalyticTrajectory.h | 5 ++ .../trajectory/codac2_SampledTrajectory.h | 10 +++ src/core/trajectory/codac2_TrajectoryBase.h | 3 + .../trajectory/codac2_Trajectory_operator.cpp | 39 ++++++++++ .../trajectory/codac2_Trajectory_operator.h | 71 +++++++++++++++++++ 7 files changed, 136 insertions(+) create mode 100644 src/core/trajectory/codac2_Trajectory_operator.cpp create mode 100644 src/core/trajectory/codac2_Trajectory_operator.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 494c16146..8eff65584 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -159,6 +159,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_AnalyticTrajectory.h ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_SampledTrajectory.h + ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_Trajectory_operator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_Trajectory_operator.h ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_TrajectoryBase.h ) diff --git a/src/core/functions/analytic/codac2_analytic_operations.h b/src/core/functions/analytic/codac2_analytic_operations.h index e04692f52..a1a2b0eb5 100644 --- a/src/core/functions/analytic/codac2_analytic_operations.h +++ b/src/core/functions/analytic/codac2_analytic_operations.h @@ -547,6 +547,12 @@ namespace codac2 return std::make_shared>(x...); } + inline ScalarExpr_ptr + ind(Index i, const VectorExpr_ptr& x1) + { + return std::make_shared>(x1,i); + } + template inline MatrixExpr_ptr mat(const std::shared_ptr>&... x) diff --git a/src/core/trajectory/codac2_AnalyticTrajectory.h b/src/core/trajectory/codac2_AnalyticTrajectory.h index b0b8f5ad8..c0699356d 100644 --- a/src/core/trajectory/codac2_AnalyticTrajectory.h +++ b/src/core/trajectory/codac2_AnalyticTrajectory.h @@ -67,6 +67,11 @@ namespace codac2 return AnalyticFunction::eval(t); } + /*virtual AnalyticFunction as_function() const + { + return *this; + }*/ + protected: Interval _tdomain; diff --git a/src/core/trajectory/codac2_SampledTrajectory.h b/src/core/trajectory/codac2_SampledTrajectory.h index f39ab82d9..1440f287d 100644 --- a/src/core/trajectory/codac2_SampledTrajectory.h +++ b/src/core/trajectory/codac2_SampledTrajectory.h @@ -11,9 +11,12 @@ #include #include "codac2_TrajectoryBase.h" +#include "codac2_analytic_variables.h" namespace codac2 { + struct TrajectoryOp; + template class SampledTrajectory : public TrajectoryBase, public std::map { @@ -146,5 +149,12 @@ namespace codac2 return straj; } + + auto as_function() const + { + ScalarVar t; + return AnalyticFunction({t}, + std::make_shared>(*this,t)); + } }; } \ No newline at end of file diff --git a/src/core/trajectory/codac2_TrajectoryBase.h b/src/core/trajectory/codac2_TrajectoryBase.h index fd3da2638..610c8808b 100644 --- a/src/core/trajectory/codac2_TrajectoryBase.h +++ b/src/core/trajectory/codac2_TrajectoryBase.h @@ -11,6 +11,7 @@ #include "codac2_Interval.h" #include "codac2_Wrapper.h" +#include "codac2_AnalyticFunction.h" namespace codac2 { @@ -82,5 +83,7 @@ namespace codac2 return p; } + + //virtual AnalyticFunction::Domain> as_function() const = 0; }; } \ No newline at end of file diff --git a/src/core/trajectory/codac2_Trajectory_operator.cpp b/src/core/trajectory/codac2_Trajectory_operator.cpp new file mode 100644 index 000000000..7bfa26a87 --- /dev/null +++ b/src/core/trajectory/codac2_Trajectory_operator.cpp @@ -0,0 +1,39 @@ +/** + * codac2_Trajectory_operator.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou, Luc Jaulin + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_Trajectory_operator.h" + +using namespace std; +using namespace codac2; + + +IntervalVector TrajectoryOp::fwd(const SampledTrajectory& x1, const Interval& x2) +{ + return x1(x2); +} + +VectorOpValue TrajectoryOp::fwd(const SampledTrajectory& x1, const ScalarOpValue& x2) +{ + IntervalMatrix d(x1.size(),x2.da.cols()); + + return { + fwd(x1,x2.m), + fwd(x1,x2.a), + d, + x2.def_domain + }; +} + +void TrajectoryOp::bwd( + [[maybe_unused]] const SampledTrajectory& x1, + [[maybe_unused]] const IntervalVector& y, + [[maybe_unused]] Interval& x2) +{ + // todo +} \ No newline at end of file diff --git a/src/core/trajectory/codac2_Trajectory_operator.h b/src/core/trajectory/codac2_Trajectory_operator.h new file mode 100644 index 000000000..9798b9789 --- /dev/null +++ b/src/core/trajectory/codac2_Trajectory_operator.h @@ -0,0 +1,71 @@ +/** + * \file codac2_Trajectory_operator.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_analytic_operations.h" +#include "codac2_SampledTrajectory.h" + +namespace codac2 +{ + struct TrajectoryOp + { + static IntervalVector fwd(const SampledTrajectory& x1, const Interval& x2); + static VectorOpValue fwd(const SampledTrajectory& x1, const ScalarOpValue& x2); + static void bwd(const SampledTrajectory& x1, const IntervalVector& y, Interval& x2); + }; + + + template<> + class AnalyticOperationExpr + : public AnalyticExpr, public OperationExprBase> + { + public: + + AnalyticOperationExpr(const SampledTrajectory& x1, const std::shared_ptr>& x2) + : OperationExprBase>(x2), _x1(x1) + { } + + AnalyticOperationExpr(const AnalyticOperationExpr& e) + : OperationExprBase>(e), _x1(e._x1) + { } + + std::shared_ptr copy() const + { + return std::make_shared>(*this); + } + + void replace_expr(const ExprID& old_expr_id, const std::shared_ptr& new_expr) + { + return OperationExprBase>::replace_expr(old_expr_id, new_expr); + } + + VectorOpValue fwd_eval(ValuesMap& v, Index total_input_size) const + { + return AnalyticExpr::init_value( + v, TrajectoryOp::fwd(_x1, std::get<0>(this->_x)->fwd_eval(v, total_input_size))); + } + + void bwd_eval(ValuesMap& v) const + { + TrajectoryOp::bwd(_x1, AnalyticExpr::value(v).a, std::get<0>(this->_x)->value(v).a); + std::get<0>(this->_x)->bwd_eval(v); + } + + virtual bool belongs_to_args_list(const FunctionArgsList& args) const + { + return std::get<0>(this->_x)->belongs_to_args_list(args); + } + + protected: + + const SampledTrajectory _x1; + }; + +} \ No newline at end of file From 529d43541b85157cc985034c2fadea28709a6ac8 Mon Sep 17 00:00:00 2001 From: godardma Date: Thu, 19 Dec 2024 11:29:02 +0100 Subject: [PATCH 032/126] [graphics] added draw_line binding --- examples/00_graphics/graphic_examples.py | 1 + python/src/graphics/figures/codac2_py_Figure2D.cpp | 8 ++++++++ src/graphics/figures/codac2_Figure2D.h | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/examples/00_graphics/graphic_examples.py b/examples/00_graphics/graphic_examples.py index b40898016..135f80acc 100644 --- a/examples/00_graphics/graphic_examples.py +++ b/examples/00_graphics/graphic_examples.py @@ -44,6 +44,7 @@ fig2.draw_polygone([[2,4.5],[4,4.5],[4.2,3.5],[3.5,3]], [Color.none(),Color.green(0.5)]) fig2.draw_polyline([[-0.8,0],[0,1.5]], 0.2, [Color.red(),Color.black(0.3)]) fig2.draw_ellipse([1,1],[0.5,2], 0.2, [Color.blue(),Color.blue(0.3)]) +fig2.draw_line([1,1],[3,3], [Color.blue(),Color.blue(0.3)]) # Colors # predefined colors without and with opacity diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index 71d7fac4b..208419b86 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -106,6 +106,10 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_DRAW_RING_CONST_VECTOR_REF_CONST_INTERVAL_REF_CONST_STYLEPROPERTIES_REF, "c"_a, "r"_a, "s"_a=StyleProperties()) + .def("draw_line", &Figure2D::draw_line, + VOID_FIGURE2D_DRAW_LINE_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_STYLEPROPERTIES_REF, + "c1"_a, "c2"_a, "s"_a=StyleProperties()) + .def("draw_polyline", (void(Figure2D::*)(const std::vector&,const StyleProperties&))&Figure2D::draw_polyline, VOID_FIGURE2D_DRAW_POLYLINE_CONST_VECTOR_VECTOR_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) @@ -231,6 +235,10 @@ void export_Figure2D(py::module& m) STATIC_VOID_DEFAULTVIEW_DRAW_RING_CONST_VECTOR_REF_CONST_INTERVAL_REF_CONST_STYLEPROPERTIES_REF, "c"_a, "r"_a, "s"_a=StyleProperties()) + .def_static("draw_line", &DefaultView::draw_line, + STATIC_VOID_DEFAULTVIEW_DRAW_LINE_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_STYLEPROPERTIES_REF, + "c1"_a, "c2"_a, "s"_a=StyleProperties()) + .def_static("draw_polyline", (void(*)(const std::vector&,const StyleProperties&))&DefaultView::draw_polyline, STATIC_VOID_DEFAULTVIEW_DRAW_POLYLINE_CONST_VECTOR_VECTOR_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 41c494d7a..f867ce8b0 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -181,6 +181,12 @@ namespace codac2 selected_fig()->draw_ring(c,r,s); } + static void draw_line(const Vector& x1, const Vector& x2, const StyleProperties& s = StyleProperties()) + { + auto_init(); + selected_fig()->draw_line(x1,x2,s); + } + static void draw_polyline(const std::vector& x, const StyleProperties& s = StyleProperties()) { auto_init(); From 534ee5c7206e5660407e635bebfce78d68d72c5d Mon Sep 17 00:00:00 2001 From: godardma Date: Thu, 19 Dec 2024 11:39:30 +0100 Subject: [PATCH 033/126] [graphics] added draw_arrow --- examples/00_graphics/graphic_examples.py | 3 ++- python/src/graphics/figures/codac2_py_Figure2D.cpp | 8 ++++++++ src/graphics/figures/codac2_Figure2D.cpp | 14 ++++++++++++-- src/graphics/figures/codac2_Figure2D.h | 7 +++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/examples/00_graphics/graphic_examples.py b/examples/00_graphics/graphic_examples.py index 135f80acc..2f2e6919c 100644 --- a/examples/00_graphics/graphic_examples.py +++ b/examples/00_graphics/graphic_examples.py @@ -44,7 +44,8 @@ fig2.draw_polygone([[2,4.5],[4,4.5],[4.2,3.5],[3.5,3]], [Color.none(),Color.green(0.5)]) fig2.draw_polyline([[-0.8,0],[0,1.5]], 0.2, [Color.red(),Color.black(0.3)]) fig2.draw_ellipse([1,1],[0.5,2], 0.2, [Color.blue(),Color.blue(0.3)]) -fig2.draw_line([1,1],[3,3], [Color.blue(),Color.blue(0.3)]) +fig2.draw_line([1,1],[3,3], Color.blue()) +fig2.draw_arrow([3,1],[2.2,2], 0.2, [Color.red(),Color.black(0.3)]) # Colors # predefined colors without and with opacity diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index 208419b86..772c0e371 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -110,6 +110,10 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_DRAW_LINE_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_STYLEPROPERTIES_REF, "c1"_a, "c2"_a, "s"_a=StyleProperties()) + .def("draw_arrow", &Figure2D::draw_arrow, + VOID_FIGURE2D_DRAW_ARROW_CONST_VECTOR_REF_CONST_VECTOR_REF_FLOAT_CONST_STYLEPROPERTIES_REF, + "c1"_a, "c2"_a, "tip_length"_a, "s"_a=StyleProperties()) + .def("draw_polyline", (void(Figure2D::*)(const std::vector&,const StyleProperties&))&Figure2D::draw_polyline, VOID_FIGURE2D_DRAW_POLYLINE_CONST_VECTOR_VECTOR_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) @@ -239,6 +243,10 @@ void export_Figure2D(py::module& m) STATIC_VOID_DEFAULTVIEW_DRAW_LINE_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_STYLEPROPERTIES_REF, "c1"_a, "c2"_a, "s"_a=StyleProperties()) + .def_static("draw_arrow", &DefaultView::draw_arrow, + STATIC_VOID_DEFAULTVIEW_DRAW_ARROW_CONST_VECTOR_REF_CONST_VECTOR_REF_FLOAT_CONST_STYLEPROPERTIES_REF, + "c1"_a, "c2"_a, "tip_length"_a, "s"_a=StyleProperties()) + .def_static("draw_polyline", (void(*)(const std::vector&,const StyleProperties&))&DefaultView::draw_polyline, STATIC_VOID_DEFAULTVIEW_DRAW_POLYLINE_CONST_VECTOR_VECTOR_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index d285aff21..63cae3cd3 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -142,10 +142,20 @@ void Figure2D::draw_line(const Vector& x, const Vector& y, const StyleProperties { assert_release(x.size() == y.size()); assert_release(x.size() == 2); - vector points = {x,y}; + vector values = {x,y}; for(const auto& output_fig : _output_figures) - output_fig->draw_polyline(points,1e-3*scaled_unit(),s); + output_fig->draw_polyline(values,1e-3*scaled_unit(),s); +} + +void Figure2D::draw_arrow(const Vector& x, const Vector& y, float tip_length, const StyleProperties& s) +{ + assert_release(x.size() == y.size()); + assert_release(x.size() == 2); + vector values = {x,y}; + + for(const auto& output_fig : _output_figures) + output_fig->draw_polyline(values,tip_length,s); } void Figure2D::draw_polyline(const vector& x, const StyleProperties& s) diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index f867ce8b0..209ab7d16 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -87,6 +87,7 @@ namespace codac2 void draw_circle(const Vector& c, double r, const StyleProperties& s = StyleProperties()); void draw_ring(const Vector& c, const Interval& r, const StyleProperties& s = StyleProperties()); void draw_line(const Vector& x1, const Vector& x2, const StyleProperties& s = StyleProperties()); + void draw_arrow(const Vector& x1, const Vector& x2, float tip_length, const StyleProperties& s = StyleProperties()); void draw_polyline(const std::vector& x, const StyleProperties& s = StyleProperties()); void draw_polyline(const std::vector& x, float tip_length, const StyleProperties& s = StyleProperties()); void draw_polygone(const std::vector& x, const StyleProperties& s = StyleProperties()); @@ -187,6 +188,12 @@ namespace codac2 selected_fig()->draw_line(x1,x2,s); } + static void draw_arrow(const Vector& x1, const Vector& x2, float tip_length, const StyleProperties& s = StyleProperties()) + { + auto_init(); + selected_fig()->draw_arrow(x1,x2,tip_length,s); + } + static void draw_polyline(const std::vector& x, const StyleProperties& s = StyleProperties()) { auto_init(); From ea04e2e9c2a573f22aea84e8ae3f39dc8589adac Mon Sep 17 00:00:00 2001 From: godardma Date: Thu, 19 Dec 2024 15:25:35 +0100 Subject: [PATCH 034/126] [graphics] minor update (thanks to Simon's advice) --- .../graphics/figures/codac2_py_Figure2D.cpp | 8 ++--- src/graphics/figures/codac2_Figure2D.cpp | 35 +++++++++---------- src/graphics/figures/codac2_Figure2D.h | 4 +-- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index 772c0e371..be0401835 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -108,11 +108,11 @@ void export_Figure2D(py::module& m) .def("draw_line", &Figure2D::draw_line, VOID_FIGURE2D_DRAW_LINE_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_STYLEPROPERTIES_REF, - "c1"_a, "c2"_a, "s"_a=StyleProperties()) + "a"_a, "b"_a, "s"_a=StyleProperties()) .def("draw_arrow", &Figure2D::draw_arrow, VOID_FIGURE2D_DRAW_ARROW_CONST_VECTOR_REF_CONST_VECTOR_REF_FLOAT_CONST_STYLEPROPERTIES_REF, - "c1"_a, "c2"_a, "tip_length"_a, "s"_a=StyleProperties()) + "a"_a, "b"_a, "tip_length"_a, "s"_a=StyleProperties()) .def("draw_polyline", (void(Figure2D::*)(const std::vector&,const StyleProperties&))&Figure2D::draw_polyline, VOID_FIGURE2D_DRAW_POLYLINE_CONST_VECTOR_VECTOR_REF_CONST_STYLEPROPERTIES_REF, @@ -241,11 +241,11 @@ void export_Figure2D(py::module& m) .def_static("draw_line", &DefaultView::draw_line, STATIC_VOID_DEFAULTVIEW_DRAW_LINE_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_STYLEPROPERTIES_REF, - "c1"_a, "c2"_a, "s"_a=StyleProperties()) + "a"_a, "b"_a, "s"_a=StyleProperties()) .def_static("draw_arrow", &DefaultView::draw_arrow, STATIC_VOID_DEFAULTVIEW_DRAW_ARROW_CONST_VECTOR_REF_CONST_VECTOR_REF_FLOAT_CONST_STYLEPROPERTIES_REF, - "c1"_a, "c2"_a, "tip_length"_a, "s"_a=StyleProperties()) + "a"_a, "b"_a, "tip_length"_a, "s"_a=StyleProperties()) .def_static("draw_polyline", (void(*)(const std::vector&,const StyleProperties&))&DefaultView::draw_polyline, STATIC_VOID_DEFAULTVIEW_DRAW_POLYLINE_CONST_VECTOR_VECTOR_REF_CONST_STYLEPROPERTIES_REF, diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 63cae3cd3..f97470fd2 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -138,24 +138,22 @@ void Figure2D::draw_ring(const Vector& c, const Interval& r, const StyleProperti output_fig->draw_ring(c,r,s); } -void Figure2D::draw_line(const Vector& x, const Vector& y, const StyleProperties& s) +void Figure2D::draw_line(const Vector& a, const Vector& b, const StyleProperties& s) { - assert_release(x.size() == y.size()); - assert_release(x.size() == 2); - vector values = {x,y}; + assert_release(a.size() == b.size()); + assert_release(a.size() == 2); + vector values = {a,b}; - for(const auto& output_fig : _output_figures) - output_fig->draw_polyline(values,1e-3*scaled_unit(),s); + draw_polyline(values,s); } -void Figure2D::draw_arrow(const Vector& x, const Vector& y, float tip_length, const StyleProperties& s) +void Figure2D::draw_arrow(const Vector& a, const Vector& b, float tip_length, const StyleProperties& s) { - assert_release(x.size() == y.size()); - assert_release(x.size() == 2); - vector values = {x,y}; + assert_release(a.size() == b.size()); + assert_release(a.size() == 2); + vector values = {a,b}; - for(const auto& output_fig : _output_figures) - output_fig->draw_polyline(values,tip_length,s); + draw_polyline(values,tip_length,s); } void Figure2D::draw_polyline(const vector& x, const StyleProperties& s) @@ -236,14 +234,13 @@ void Figure2D::draw_trajectory(const SampledTrajectory& x, const ColorMa { assert_release(this->size() <= x.size()); - std::vector values(2); - values[0] = x.begin()->second; - for (auto it = std::next(x.begin()); it != x.end(); ++it) + double range = x.rbegin()->first - x.begin()->first; + + for(auto it = x.begin(); std::next(it) != x.end(); ++it) { - values[1] = it->second; - Color color = cmap.color((it->first - x.begin()->first) / (x.rbegin()->first - x.begin()->first)); - draw_polyline(values, color); - values[0] = values[1]; + draw_polyline( + { it->second, std::next(it)->second }, + cmap.color((it->first - x.begin()->first) / range)); } } diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 209ab7d16..02386426e 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -86,8 +86,8 @@ namespace codac2 void draw_box(const IntervalVector& x, const StyleProperties& s = StyleProperties()); void draw_circle(const Vector& c, double r, const StyleProperties& s = StyleProperties()); void draw_ring(const Vector& c, const Interval& r, const StyleProperties& s = StyleProperties()); - void draw_line(const Vector& x1, const Vector& x2, const StyleProperties& s = StyleProperties()); - void draw_arrow(const Vector& x1, const Vector& x2, float tip_length, const StyleProperties& s = StyleProperties()); + void draw_line(const Vector& a, const Vector& b, const StyleProperties& s = StyleProperties()); + void draw_arrow(const Vector& a, const Vector& b, float tip_length, const StyleProperties& s = StyleProperties()); void draw_polyline(const std::vector& x, const StyleProperties& s = StyleProperties()); void draw_polyline(const std::vector& x, float tip_length, const StyleProperties& s = StyleProperties()); void draw_polygone(const std::vector& x, const StyleProperties& s = StyleProperties()); From 32ab1be07fee0e5ead0679c991d5b18286c057f5 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 19 Dec 2024 16:11:31 +0100 Subject: [PATCH 035/126] [fnc] TrajectoryBase::as_function + tests --- src/core/CMakeLists.txt | 1 - .../trajectory/codac2_AnalyticTrajectory.h | 5 -- .../trajectory/codac2_SampledTrajectory.h | 9 --- src/core/trajectory/codac2_TrajectoryBase.h | 2 +- .../trajectory/codac2_Trajectory_operator.cpp | 39 ------------ .../trajectory/codac2_Trajectory_operator.h | 62 ++++++++++++++----- .../codac2_tests_SampledTrajectory.cpp | 36 +++++++++++ 7 files changed, 85 insertions(+), 69 deletions(-) delete mode 100644 src/core/trajectory/codac2_Trajectory_operator.cpp diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8eff65584..ba1d3fa9a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -159,7 +159,6 @@ ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_AnalyticTrajectory.h ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_SampledTrajectory.h - ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_Trajectory_operator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_Trajectory_operator.h ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_TrajectoryBase.h ) diff --git a/src/core/trajectory/codac2_AnalyticTrajectory.h b/src/core/trajectory/codac2_AnalyticTrajectory.h index c0699356d..b0b8f5ad8 100644 --- a/src/core/trajectory/codac2_AnalyticTrajectory.h +++ b/src/core/trajectory/codac2_AnalyticTrajectory.h @@ -67,11 +67,6 @@ namespace codac2 return AnalyticFunction::eval(t); } - /*virtual AnalyticFunction as_function() const - { - return *this; - }*/ - protected: Interval _tdomain; diff --git a/src/core/trajectory/codac2_SampledTrajectory.h b/src/core/trajectory/codac2_SampledTrajectory.h index 1440f287d..004802ee7 100644 --- a/src/core/trajectory/codac2_SampledTrajectory.h +++ b/src/core/trajectory/codac2_SampledTrajectory.h @@ -15,8 +15,6 @@ namespace codac2 { - struct TrajectoryOp; - template class SampledTrajectory : public TrajectoryBase, public std::map { @@ -149,12 +147,5 @@ namespace codac2 return straj; } - - auto as_function() const - { - ScalarVar t; - return AnalyticFunction({t}, - std::make_shared>(*this,t)); - } }; } \ No newline at end of file diff --git a/src/core/trajectory/codac2_TrajectoryBase.h b/src/core/trajectory/codac2_TrajectoryBase.h index 610c8808b..a7f766cc9 100644 --- a/src/core/trajectory/codac2_TrajectoryBase.h +++ b/src/core/trajectory/codac2_TrajectoryBase.h @@ -84,6 +84,6 @@ namespace codac2 return p; } - //virtual AnalyticFunction::Domain> as_function() const = 0; + AnalyticFunction::Domain> as_function() const; }; } \ No newline at end of file diff --git a/src/core/trajectory/codac2_Trajectory_operator.cpp b/src/core/trajectory/codac2_Trajectory_operator.cpp deleted file mode 100644 index 7bfa26a87..000000000 --- a/src/core/trajectory/codac2_Trajectory_operator.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/** - * codac2_Trajectory_operator.cpp - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou, Luc Jaulin - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include "codac2_Trajectory_operator.h" - -using namespace std; -using namespace codac2; - - -IntervalVector TrajectoryOp::fwd(const SampledTrajectory& x1, const Interval& x2) -{ - return x1(x2); -} - -VectorOpValue TrajectoryOp::fwd(const SampledTrajectory& x1, const ScalarOpValue& x2) -{ - IntervalMatrix d(x1.size(),x2.da.cols()); - - return { - fwd(x1,x2.m), - fwd(x1,x2.a), - d, - x2.def_domain - }; -} - -void TrajectoryOp::bwd( - [[maybe_unused]] const SampledTrajectory& x1, - [[maybe_unused]] const IntervalVector& y, - [[maybe_unused]] Interval& x2) -{ - // todo -} \ No newline at end of file diff --git a/src/core/trajectory/codac2_Trajectory_operator.h b/src/core/trajectory/codac2_Trajectory_operator.h index 9798b9789..dc71aa5f8 100644 --- a/src/core/trajectory/codac2_Trajectory_operator.h +++ b/src/core/trajectory/codac2_Trajectory_operator.h @@ -14,21 +14,45 @@ namespace codac2 { + template::Domain> + requires (std::is_same_v || std::is_same_v) struct TrajectoryOp { - static IntervalVector fwd(const SampledTrajectory& x1, const Interval& x2); - static VectorOpValue fwd(const SampledTrajectory& x1, const ScalarOpValue& x2); - static void bwd(const SampledTrajectory& x1, const IntervalVector& y, Interval& x2); - }; + static D fwd(const TrajectoryBase& x1, const Interval& x2) + { + return x1(x2); + } + + static typename ArgWrapper::Domain fwd(const TrajectoryBase& x1, const ScalarOpValue& x2) + { + IntervalMatrix d(x1.size(),x2.da.cols()); + + return { + fwd(x1,x2.m), + fwd(x1,x2.a), + d, + x2.def_domain && x1.tdomain().is_superset(x2.m) + }; + } + static void bwd( + [[maybe_unused]] const TrajectoryBase& x1, + [[maybe_unused]] const D& y, + [[maybe_unused]] Interval& x2) + { + // todo + } + }; - template<> - class AnalyticOperationExpr - : public AnalyticExpr, public OperationExprBase> + template + class AnalyticOperationExpr,typename ArgWrapper::Domain,ScalarOpValue> + : public AnalyticExpr::Domain>, public OperationExprBase> { public: - AnalyticOperationExpr(const SampledTrajectory& x1, const std::shared_ptr>& x2) + using O = typename ArgWrapper::Domain; + + AnalyticOperationExpr(const TrajectoryBase& x1, const std::shared_ptr>& x2) : OperationExprBase>(x2), _x1(x1) { } @@ -38,7 +62,7 @@ namespace codac2 std::shared_ptr copy() const { - return std::make_shared>(*this); + return std::make_shared,O,ScalarOpValue>>(*this); } void replace_expr(const ExprID& old_expr_id, const std::shared_ptr& new_expr) @@ -46,15 +70,15 @@ namespace codac2 return OperationExprBase>::replace_expr(old_expr_id, new_expr); } - VectorOpValue fwd_eval(ValuesMap& v, Index total_input_size) const + O fwd_eval(ValuesMap& v, Index total_input_size) const { - return AnalyticExpr::init_value( - v, TrajectoryOp::fwd(_x1, std::get<0>(this->_x)->fwd_eval(v, total_input_size))); + return AnalyticExpr::init_value( + v, TrajectoryOp::fwd(_x1, std::get<0>(this->_x)->fwd_eval(v, total_input_size))); } void bwd_eval(ValuesMap& v) const { - TrajectoryOp::bwd(_x1, AnalyticExpr::value(v).a, std::get<0>(this->_x)->value(v).a); + TrajectoryOp::bwd(_x1, AnalyticExpr::value(v).a, std::get<0>(this->_x)->value(v).a); std::get<0>(this->_x)->bwd_eval(v); } @@ -65,7 +89,17 @@ namespace codac2 protected: - const SampledTrajectory _x1; + const TrajectoryBase& _x1; }; + template + AnalyticFunction::Domain> TrajectoryBase::as_function() const + { + ScalarVar t; + return {{t}, + std::make_shared< + AnalyticOperationExpr + , typename ArgWrapper::Domain, ScalarOpValue>>(*this,t) + }; + } } \ No newline at end of file diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp index 002e1d230..7fdbb1477 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -59,4 +60,39 @@ TEST_CASE("SampledTrajectory") //DefaultView::set_window_properties({75,75},{700,700}); //DefaultView::draw_trajectory(x, Color::blue()); //DefaultView::draw_trajectory(x_sampled, Color::red()); +} + +TEST_CASE("SampledTrajectory as operator (1d case)") +{ + ScalarVar t; + AnalyticFunction f { {t}, cos(t) }; + AnalyticTrajectory analytic_traj(f, {-M_PI,M_PI}); + auto sampled_traj = analytic_traj.sampled(1e-2); + auto g = sampled_traj.as_function(); + + AnalyticFunction h { {t}, g(t) }; + + for(double t = -M_PI ; t < M_PI ; t+=1e-2) + CHECK(Approx(h.real_eval(t)) == cos(t)); +} + +TEST_CASE("SampledTrajectory as operator (nd case)") +{ + ScalarVar t; + AnalyticFunction f { + {t}, + vec(2*cos(t),sin(2*t)) + }; + + auto analytic_traj = AnalyticTrajectory(f, {0,5}); + auto sampled_traj = analytic_traj.sampled(1e-2); + auto g = sampled_traj.as_function(); + + AnalyticFunction h { + {t}, + vec(1.*ind(0,g(t)),1.*ind(1,g(t))) + }; + + for(double t = 0 ; t < 5 ; t+=1e-2) + CHECK(Approx(h.real_eval(t)) == Vector({2*cos(t),sin(2*t)})); } \ No newline at end of file From c2a964a44b22862f6122c3ef05931ebccb2753ca Mon Sep 17 00:00:00 2001 From: godardma Date: Fri, 20 Dec 2024 13:41:16 +0100 Subject: [PATCH 036/126] [capd] added capd tools --- CMakeLists.txt | 17 +++++--- include/codac-capd.h | 8 ++++ include/codac2-capd.h | 8 ++++ include/codac2_capd.h | 75 ++++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 10 +++-- src/capd/CMakeLists.txt | 61 ++++++++++++++++++++++++++++ src/capd/codac2_capd.cpp | 78 ++++++++++++++++++++++++++++++++++++ src/capd/codac2_capd.h | 68 +++++++++++++++++++++++++++++++ src/core/3rd/codac2_ibex.cpp | 2 +- 9 files changed, 317 insertions(+), 10 deletions(-) create mode 100644 include/codac-capd.h create mode 100644 include/codac2-capd.h create mode 100644 include/codac2_capd.h create mode 100644 src/capd/CMakeLists.txt create mode 100644 src/capd/codac2_capd.cpp create mode 100644 src/capd/codac2_capd.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a39db1a1..9f72bd430 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,12 +102,17 @@ option(WITH_CAPD "Using CAPD for accurate integration of ODEs" OFF) if(WITH_CAPD) - # This looks for capd.pc file - include(FindPkgConfig) - pkg_search_module(PKG_CAPD REQUIRED capd capd-gui mpcapd mpcapd-gui) - include_directories(${PKG_CAPD_INCLUDE_DIRS}) - #message(STATUS "[capd2codac] PKG_CAPD_INCLUDE_DIRS = ${PKG_CAPD_INCLUDE_DIRS}") - #message(STATUS "[capd2codac] PKG_CAPD_LDFLAGS = ${PKG_CAPD_LDFLAGS}") + execute_process(COMMAND capd-config --cflags OUTPUT_VARIABLE CAPD_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND capd-config --libs OUTPUT_VARIABLE CAPD_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE) + + separate_arguments(CAPD_CFLAGS) + separate_arguments(CAPD_LIBS) + + message(STATUS "CAPD_CFLAGS: ${CAPD_CFLAGS}") + message(STATUS "CAPD_LIBS: ${CAPD_LIBS}") + + add_compile_options(${CAPD_CFLAGS}) + link_libraries(${CAPD_LIBS}) endif() diff --git a/include/codac-capd.h b/include/codac-capd.h new file mode 100644 index 000000000..0f703eef8 --- /dev/null +++ b/include/codac-capd.h @@ -0,0 +1,8 @@ +/* This file is generated by CMake */ + +#ifndef __CODAC2_3RD_CAPD_H__ +#define __CODAC2_3RD_CAPD_H__ + +#include + +#endif diff --git a/include/codac2-capd.h b/include/codac2-capd.h new file mode 100644 index 000000000..0f703eef8 --- /dev/null +++ b/include/codac2-capd.h @@ -0,0 +1,8 @@ +/* This file is generated by CMake */ + +#ifndef __CODAC2_3RD_CAPD_H__ +#define __CODAC2_3RD_CAPD_H__ + +#include + +#endif diff --git a/include/codac2_capd.h b/include/codac2_capd.h new file mode 100644 index 000000000..9056f95c6 --- /dev/null +++ b/include/codac2_capd.h @@ -0,0 +1,75 @@ +/** + * \file codac2_capd.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "capd/capdlib.h" +#include "codac2_IntervalVector.h" +#include "codac2_Matrix.h" +#include "codac2_IntervalMatrix.h" + +namespace codac2 +{ + /** + * \brief Casts a reference to a Codac Interval object into a reference to an CAPD Interval object + * + * \param x Codac type Interval + * \return CAPD type Interval + */ + capd::Interval& to_capd(codac2::Interval& x); + + /** + * \brief Casts a Codac Interval object into an CAPD Interval object + * + * \param x const Codac type Interval + * \return const CAPD type Interval + */ + const capd::Interval& to_capd(const codac2::Interval& x); + + /** + * \brief Casts an CAPD Interval object into a Codac Interval object + * + * \param x const CAPD type Interval + * \return Codac type Interval + */ + codac2::Interval to_codac(const capd::Interval& x); + + /** + * \brief Casts a Codac IntervalVector object into an CAPD IntervalVector object + * + * \param x const Codac type IntervalVector + * \return CAPD type IntervalVector + */ + capd::IVector to_capd(const codac2::IntervalVector& x); + + /** + * \brief Casts an CAPD IntervalVector object into a Codac IntervalVector object + * + * \param x const CAPD type IntervalVector + * \return Codac type IntervalVector + */ + codac2::IntervalVector to_codac(const capd::IVector& x); + + /** + * \brief Casts a Codac IntervalMatrix object into an CAPD IntervalMatrix object + * + * \param x const Codac type IntervalMatrix + * \return CAPD type IntervalMatrix + */ + capd::IMatrix to_capd(const codac2::IntervalMatrix& x); + + /** + * \brief Casts an CAPD IntervalMatrix object into a Codac IntervalMatrix object + * + * \param x const CAPD type IntervalMatrix + * \return Codac type IntervalMatrix + */ + codac2::IntervalMatrix to_codac(const capd::IMatrix& x); + +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a3f79a44..577b6cfad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,10 @@ #if(WITH_PYTHON) # add_subdirectory(sympy) #endif() + + if(WITH_CAPD) + add_subdirectory(capd) + endif() # Generating PKG file @@ -97,11 +101,11 @@ # Optional 3rd party: - find_path(CODAC_CAPD_INCLUDE_DIR ${PROJECT_NAME}-sympy.h - PATH_SUFFIXES include/${PROJECT_NAME}-sympy) + find_path(CODAC_CAPD_INCLUDE_DIR ${PROJECT_NAME}-capd.h + PATH_SUFFIXES include/${PROJECT_NAME}-capd) set(CODAC_INCLUDE_DIRS \${CODAC_INCLUDE_DIRS} \${CODAC_CAPD_INCLUDE_DIR}) - find_library(CODAC_CAPD_LIBRARY NAMES ${PROJECT_NAME}-sympy + find_library(CODAC_CAPD_LIBRARY NAMES ${PROJECT_NAME}-capd PATH_SUFFIXES lib) set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY}) ") diff --git a/src/capd/CMakeLists.txt b/src/capd/CMakeLists.txt new file mode 100644 index 000000000..d0e838316 --- /dev/null +++ b/src/capd/CMakeLists.txt @@ -0,0 +1,61 @@ +# ================================================================== +# Codac - cmake configuration file +# ================================================================== + +list(APPEND CODAC_CAPD_SRC + + ${CMAKE_CURRENT_SOURCE_DIR}/codac2_capd.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/codac2_capd.h +) + +################################################################################ +# Create the target for libcodac-capd +################################################################################ + + #if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + #endif() + + add_library(${PROJECT_NAME}-capd ${CODAC_CAPD_SRC}) + target_link_libraries(${PROJECT_NAME}-capd PUBLIC ${PROJECT_NAME}-core Ibex::ibex Eigen3::Eigen) + + + ################################################################################ + # For the generation of the PKG file + ################################################################################ + + set(CODAC_PKG_CONFIG_CFLAGS "${CODAC_PKG_CONFIG_CFLAGS} -I\${includedir}/${PROJECT_NAME}-capd" PARENT_SCOPE) + set(CODAC_PKG_CONFIG_LIBS "${CODAC_PKG_CONFIG_LIBS} -l${PROJECT_NAME}-capd" PARENT_SCOPE) + + + ################################################################################ + # Installation of libcodac-capd files + ################################################################################ + + # Getting header files from sources + + foreach(srcfile ${CODAC_CAPD_SRC}) + if(srcfile MATCHES "\\.h$" OR srcfile MATCHES "\\.hpp$") + list(APPEND CODAC_CAPD_HDR ${srcfile}) + file(COPY ${srcfile} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../include) + endif() + endforeach() + + # Generating the file codac-capd.h + + set(CODAC_CAPD_MAIN_HEADER ${CMAKE_CURRENT_BINARY_DIR}/codac-capd.h) + set(CODAC_MAIN_SUBHEADERS ${CODAC_MAIN_SUBHEADERS} "codac-capd.h" PARENT_SCOPE) + file(WRITE ${CODAC_CAPD_MAIN_HEADER} "/* This file is generated by CMake */\n\n") + file(APPEND ${CODAC_CAPD_MAIN_HEADER} "#pragma once\n\n") + foreach(header_path ${CODAC_CAPD_HDR}) + get_filename_component(header_name ${header_path} NAME) + file(APPEND ${CODAC_CAPD_MAIN_HEADER} "#include <${header_name}>\n") + endforeach() + file(COPY ${CODAC_CAPD_MAIN_HEADER} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../include) + + # Install files in system directories + + install(TARGETS ${PROJECT_NAME}-capd DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(FILES ${CODAC_CAPD_HDR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-capd) + install(FILES ${CODAC_CAPD_MAIN_HEADER} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-capd) \ No newline at end of file diff --git a/src/capd/codac2_capd.cpp b/src/capd/codac2_capd.cpp new file mode 100644 index 000000000..62de19aee --- /dev/null +++ b/src/capd/codac2_capd.cpp @@ -0,0 +1,78 @@ +/** + * codac2_capd.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include "codac2_capd.h" + +using namespace std; + +#include + +namespace codac2 +{ + capd::Interval to_capd(const Interval &x) + { + capd::Interval y(x.lb(), x.ub()); + return y; + } + + Interval to_codac(const capd::Interval &x) + { + Interval y(x.leftBound(), x.rightBound()); + return y; + } + + capd::IVector to_capd(const IntervalVector &x) + { + capd::IVector y(x.size()); + for (Index i = 0; i < (Index)x.size(); i++) + { + y[i] = to_capd(x[i]); + } + return y; + } + + IntervalVector to_codac(const capd::IVector &x) + { + IntervalVector y(x.dimension()); + for (Index i = 0; i < (Index)x.dimension(); i++) + { + y[i] = to_codac(x[i]); + } + return y; + } + + capd::IMatrix to_capd(const IntervalMatrix &x) + { + capd::IMatrix y(x.rows(), x.cols()); + for (Index i = 0; i < (Index)x.rows(); i++) + { + for (Index j = 0; j < (Index)x.cols(); j++) + { + y[i][j] = to_capd(x(i, j)); + } + } + return y; + } + + IntervalMatrix to_codac(const capd::IMatrix &x) + { + IntervalMatrix y(x.numberOfRows(), x.numberOfColumns()); + for (Index i = 0; i < (Index)x.numberOfRows(); i++) + { + for (Index j = 0; j < (Index)x.numberOfColumns(); j++) + { + y(i, j) = to_codac(x[i][j]); + } + } + return y; + } + + +} diff --git a/src/capd/codac2_capd.h b/src/capd/codac2_capd.h new file mode 100644 index 000000000..659bfff9b --- /dev/null +++ b/src/capd/codac2_capd.h @@ -0,0 +1,68 @@ +/** + * \file codac2_capd.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "capd/capdlib.h" +#include "codac2_IntervalVector.h" +#include "codac2_Matrix.h" +#include "codac2_IntervalMatrix.h" + +namespace codac2 +{ + + /** + * \brief Casts a Codac Interval object into an CAPD Interval object + * + * \param x const Codac type Interval + * \return CAPD type Interval + */ + capd::Interval to_capd(const codac2::Interval& x); + + /** + * \brief Casts an CAPD Interval object into a Codac Interval object + * + * \param x const CAPD type Interval + * \return Codac type Interval + */ + codac2::Interval to_codac(const capd::Interval& x); + + /** + * \brief Casts a Codac IntervalVector object into an CAPD IntervalVector object + * + * \param x const Codac type IntervalVector + * \return CAPD type IntervalVector + */ + capd::IVector to_capd(const codac2::IntervalVector& x); + + /** + * \brief Casts an CAPD IntervalVector object into a Codac IntervalVector object + * + * \param x const CAPD type IntervalVector + * \return Codac type IntervalVector + */ + codac2::IntervalVector to_codac(const capd::IVector& x); + + /** + * \brief Casts a Codac IntervalMatrix object into an CAPD IntervalMatrix object + * + * \param x const Codac type IntervalMatrix + * \return CAPD type IntervalMatrix + */ + capd::IMatrix to_capd(const codac2::IntervalMatrix& x); + + /** + * \brief Casts an CAPD IntervalMatrix object into a Codac IntervalMatrix object + * + * \param x const CAPD type IntervalMatrix + * \return Codac type IntervalMatrix + */ + codac2::IntervalMatrix to_codac(const capd::IMatrix& x); + +} \ No newline at end of file diff --git a/src/core/3rd/codac2_ibex.cpp b/src/core/3rd/codac2_ibex.cpp index 338b5fa55..b2c79aec5 100644 --- a/src/core/3rd/codac2_ibex.cpp +++ b/src/core/3rd/codac2_ibex.cpp @@ -1,5 +1,5 @@ /** - * codac2_ibex.h + * codac2_ibex.cpp * ---------------------------------------------------------------------------- * \date 2024 * \author Gilles Chabert, (Simon Rohou) From fa311e01d897d6702ca17767c4a00da2390360e9 Mon Sep 17 00:00:00 2001 From: godardma Date: Fri, 20 Dec 2024 15:03:38 +0100 Subject: [PATCH 037/126] [capd] changed CMakeLists to include capd --- CMakeLists.txt | 12 +----------- examples/01_batman/CMakeLists.txt | 10 +++++++++- examples/02_centered_form/CMakeLists.txt | 10 +++++++++- examples/03_sivia/CMakeLists.txt | 10 +++++++++- src/capd/CMakeLists.txt | 2 +- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f72bd430..9e5f63782 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,17 +102,7 @@ option(WITH_CAPD "Using CAPD for accurate integration of ODEs" OFF) if(WITH_CAPD) - execute_process(COMMAND capd-config --cflags OUTPUT_VARIABLE CAPD_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND capd-config --libs OUTPUT_VARIABLE CAPD_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE) - - separate_arguments(CAPD_CFLAGS) - separate_arguments(CAPD_LIBS) - - message(STATUS "CAPD_CFLAGS: ${CAPD_CFLAGS}") - message(STATUS "CAPD_LIBS: ${CAPD_LIBS}") - - add_compile_options(${CAPD_CFLAGS}) - link_libraries(${CAPD_LIBS}) + find_package(CAPD REQUIRED) endif() diff --git a/examples/01_batman/CMakeLists.txt b/examples/01_batman/CMakeLists.txt index 314b49ffc..9e88ae6b0 100644 --- a/examples/01_batman/CMakeLists.txt +++ b/examples/01_batman/CMakeLists.txt @@ -27,6 +27,11 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") +# Adding CAPD + + # In case Codac was compiled with CAPD, you need to find it. + # find_package(CAPD REQUIRED) + # Compilation if(FAST_RELEASE) @@ -37,4 +42,7 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) + + # Link with CAPD if needed + # target_link_libraries(${PROJECT_NAME} PUBLIC capd::capd) \ No newline at end of file diff --git a/examples/02_centered_form/CMakeLists.txt b/examples/02_centered_form/CMakeLists.txt index 314b49ffc..d46334add 100644 --- a/examples/02_centered_form/CMakeLists.txt +++ b/examples/02_centered_form/CMakeLists.txt @@ -27,6 +27,11 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") +# Adding CAPD + + # In case Codac was compiled with CAPD, you need to find it. + # find_package(CAPD REQUIRED) + # Compilation if(FAST_RELEASE) @@ -37,4 +42,7 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) + + # Link with CAPD if needed + # target_link_libraries(${PROJECT_NAME} PUBLIC capd::capd) \ No newline at end of file diff --git a/examples/03_sivia/CMakeLists.txt b/examples/03_sivia/CMakeLists.txt index 314b49ffc..d46334add 100644 --- a/examples/03_sivia/CMakeLists.txt +++ b/examples/03_sivia/CMakeLists.txt @@ -27,6 +27,11 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") +# Adding CAPD + + # In case Codac was compiled with CAPD, you need to find it. + # find_package(CAPD REQUIRED) + # Compilation if(FAST_RELEASE) @@ -37,4 +42,7 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) + + # Link with CAPD if needed + # target_link_libraries(${PROJECT_NAME} PUBLIC capd::capd) \ No newline at end of file diff --git a/src/capd/CMakeLists.txt b/src/capd/CMakeLists.txt index d0e838316..8a4fe56d5 100644 --- a/src/capd/CMakeLists.txt +++ b/src/capd/CMakeLists.txt @@ -18,7 +18,7 @@ list(APPEND CODAC_CAPD_SRC #endif() add_library(${PROJECT_NAME}-capd ${CODAC_CAPD_SRC}) - target_link_libraries(${PROJECT_NAME}-capd PUBLIC ${PROJECT_NAME}-core Ibex::ibex Eigen3::Eigen) + target_link_libraries(${PROJECT_NAME}-capd PUBLIC ${PROJECT_NAME}-core Ibex::ibex Eigen3::Eigen capd::capd) ################################################################################ From 27753351caa469b063bb1d6b072ec641b0ee1bac Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sun, 22 Dec 2024 10:31:24 +0100 Subject: [PATCH 038/126] [fnc] operator[] on analytic expressions --- src/core/CMakeLists.txt | 1 + .../analytic/codac2_AnalyticExprWrapper.h | 33 +++++++++++++++++++ .../analytic/codac2_AnalyticFunction.h | 7 ++++ 3 files changed, 41 insertions(+) create mode 100644 src/core/functions/analytic/codac2_AnalyticExprWrapper.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ba1d3fa9a..7eb3dd314 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -72,6 +72,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_values.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_variables.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticExpr.h + ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticExprWrapper.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticFunction.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/set/codac2_set_operations.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/set/codac2_set_operators.h diff --git a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h new file mode 100644 index 000000000..f2ecc381a --- /dev/null +++ b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h @@ -0,0 +1,33 @@ +/** + * \file codac2_AnalyticExprWrapper.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_analytic_operations.h" +#include "codac2_analytic_variables.h" +#include "codac2_AnalyticExpr.h" +#include "codac2_AnalyticFunction.h" + +namespace codac2 +{ + template + struct AnalyticExprWrapper : public std::shared_ptr> + { + AnalyticExprWrapper(const std::shared_ptr>& e) + : std::shared_ptr>(std::dynamic_pointer_cast>(e->copy())) + { } + + template + requires std::is_same_v + inline ScalarExpr_ptr operator[](Index i) + { + return std::make_shared>(*this,i); + } + }; +} \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index 31099e435..e30e01c07 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -16,6 +16,7 @@ #include "codac2_FunctionBase.h" #include "codac2_template_tools.h" #include "codac2_analytic_operations.h" +#include "codac2_AnalyticExprWrapper.h" namespace codac2 { @@ -53,6 +54,12 @@ namespace codac2 : FunctionBase>(f) { } + template + AnalyticExprWrapper test(const X&... x) const + { + return { this->FunctionBase>::operator()(x...) }; + } + template auto real_eval(const Args&... x) const { From 32f2562f1503268c0b2347e902fdd439919d4c33 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sun, 22 Dec 2024 14:21:32 +0100 Subject: [PATCH 039/126] [fnc] vec(...) operator can now be replaced by { ... } --- examples/01_batman/main.cpp | 16 +- examples/02_centered_form/main.cpp | 10 +- examples/02_centered_form/main_evans.cpp | 14 +- examples/02_centered_form/main_parabolas.cpp | 2 +- src/core/CMakeLists.txt | 1 + .../analytic/codac2_AnalyticExprWrapper.h | 9 +- .../analytic/codac2_AnalyticFunction.h | 22 +- .../analytic/codac2_analytic_constants.h | 4 +- .../analytic/codac2_analytic_operations.h | 419 +++++++++--------- .../analytic/codac2_analytic_variables.cpp | 86 ++++ .../analytic/codac2_analytic_variables.h | 82 +--- src/core/functions/codac2_FunctionBase.h | 9 + .../trajectory/codac2_Trajectory_operator.h | 6 +- 13 files changed, 386 insertions(+), 294 deletions(-) create mode 100644 src/core/functions/analytic/codac2_analytic_variables.cpp diff --git a/examples/01_batman/main.cpp b/examples/01_batman/main.cpp index 53fb9a171..c8c620193 100644 --- a/examples/01_batman/main.cpp +++ b/examples/01_batman/main.cpp @@ -8,13 +8,21 @@ int main() VectorVar x(2); AnalyticFunction f_half_wing { - {x}, vec(x[0],sqr(x[0]/7.)+sqr(x[1]/3.)) }; + {x}, + { x[0],sqr(x[0]/7.)+sqr(x[1]/3.) } + }; AnalyticFunction f_half_head { - {x}, vec(0.75+3*x[0]-x[1]) }; + {x}, + { 0.75+3*x[0]-x[1] } + }; AnalyticFunction f_half_neck { - {x}, vec(9-8*x[0]-x[1], (6.*sqrt(10.)/7.)+(1.5-0.5*x[0])-(6.*sqrt(10.)/14.)*sqrt(4-sqr(x[0]-1))-x[1]) }; + {x}, + { 9-8*x[0]-x[1], (6.*sqrt(10.)/7.)+(1.5-0.5*x[0])-(6.*sqrt(10.)/14.)*sqrt(4-sqr(x[0]-1))-x[1] } + }; AnalyticFunction f_half_legs { - {x}, vec(((x[0]/2)-((3*sqrt(33)-7)/112)*sqr(x[0]))-3+sqrt(1-sqr(abs(x[0]-2)-1))-x[1]) }; + {x}, + { ((x[0]/2)-((3*sqrt(33)-7)/112)*sqr(x[0]))-3+sqrt(1-sqr(abs(x[0]-2)-1))-x[1] } + }; SetFunction half_bat { { /* no arguments */ }, diff --git a/examples/02_centered_form/main.cpp b/examples/02_centered_form/main.cpp index 1755095f3..749eae0d2 100644 --- a/examples/02_centered_form/main.cpp +++ b/examples/02_centered_form/main.cpp @@ -9,10 +9,12 @@ using namespace codac2; int main() { VectorVar x(3); - AnalyticFunction f({x}, vec( - -sqr(x[2])+2*x[2]*sin(x[2]*x[0])+cos(x[2]*x[1]), - 2*x[2]*cos(x[2]*x[0])-sin(x[2]*x[1]) - )); + AnalyticFunction f { {x}, + { + -sqr(x[2])+2*x[2]*sin(x[2]*x[0])+cos(x[2]*x[1]), + 2*x[2]*cos(x[2]*x[0])-sin(x[2]*x[1]) + } + }; CtcInverse_ ctc(f, IntervalVector::zero(2)); draw_while_paving({{0,2},{2,4},{0,10}}, ctc, 0.004); diff --git a/examples/02_centered_form/main_evans.cpp b/examples/02_centered_form/main_evans.cpp index 1e7351b9f..0311d0c5b 100644 --- a/examples/02_centered_form/main_evans.cpp +++ b/examples/02_centered_form/main_evans.cpp @@ -6,12 +6,16 @@ using namespace codac2; int main() { VectorVar x(4); - AnalyticFunction f({x}, vec( - sqr(x[0])-sqr(x[1])+2*exp(-x[0]*x[2])*(x[1]*sin(x[1]*x[2])+x[0]*cos(x[1]*x[2]))+exp(-x[0]*x[3])*cos(x[1]*x[3]), - 2*x[0]*x[1]+2*exp(-x[0]*x[2])*(x[1]*cos(x[1]*x[2])-x[0]*sin(x[1]*x[2]))-exp(-x[0]*x[3])*sin(x[1]*x[3]) - )); + AnalyticFunction f { {x}, + { + sqr(x[0])-sqr(x[1])+2*exp(-x[0]*x[2])*(x[1]*sin(x[1]*x[2]) + +x[0]*cos(x[1]*x[2]))+exp(-x[0]*x[3])*cos(x[1]*x[3]), + 2*x[0]*x[1]+2*exp(-x[0]*x[2])*(x[1]*cos(x[1]*x[2]) + -x[0]*sin(x[1]*x[2]))-exp(-x[0]*x[3])*sin(x[1]*x[3]) + } + }; - CtcInverse_ ctc(f, {0.,0.}); + CtcInverse_ ctc(f, IntervalVector::zero(2)); IntervalVector x0({{-10,10},{0,20},{1,1},{2,2}}); shared_ptr g = make_shared("Evans", GraphicOutput::VIBES); diff --git a/examples/02_centered_form/main_parabolas.cpp b/examples/02_centered_form/main_parabolas.cpp index 6902f3891..7a11615cd 100644 --- a/examples/02_centered_form/main_parabolas.cpp +++ b/examples/02_centered_form/main_parabolas.cpp @@ -22,7 +22,7 @@ int main() ); AnalyticFunction h({a}, fa(a[0],a[1])-fb(a[2],a[3])); - CtcInverse_ ctc(h, {0.,0.,0.}); + CtcInverse_ ctc(h, IntervalVector::zero(3)); IntervalVector x0({{0,1},{0,1},{0,1},{0,1}}); draw_while_paving(x0, ctc, 0.001); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7eb3dd314..6ff50980e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -70,6 +70,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_constants.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_operations.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_values.h + ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_variables.cpp ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_variables.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticExpr.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticExprWrapper.h diff --git a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h index f2ecc381a..e6e40a977 100644 --- a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h +++ b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h @@ -9,10 +9,7 @@ #pragma once -#include "codac2_analytic_operations.h" -#include "codac2_analytic_variables.h" #include "codac2_AnalyticExpr.h" -#include "codac2_AnalyticFunction.h" namespace codac2 { @@ -20,14 +17,14 @@ namespace codac2 struct AnalyticExprWrapper : public std::shared_ptr> { AnalyticExprWrapper(const std::shared_ptr>& e) - : std::shared_ptr>(std::dynamic_pointer_cast>(e->copy())) + : std::shared_ptr>(e) { } template requires std::is_same_v - inline ScalarExpr_ptr operator[](Index i) + inline AnalyticExprWrapper operator[](Index i) { - return std::make_shared>(*this,i); + return { std::make_shared>(*this,i) }; } }; } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index e30e01c07..18cb2e9fc 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -32,6 +32,16 @@ namespace codac2 inline EvalMode operator|(EvalMode a, EvalMode b) { return static_cast(static_cast(a) | static_cast(b)); } + + class ScalarExprList : public AnalyticExprWrapper + { + public: + + template + ScalarExprList(const S&... y) + : AnalyticExprWrapper(vec(y...)) + { } + }; template requires std::is_base_of_v @@ -39,6 +49,13 @@ namespace codac2 { public: + AnalyticFunction(const FunctionArgsList& args, const ScalarExprList& y) + : FunctionBase>(args, y) + { + assert_release(y->belongs_to_args_list(this->args()) && + "Invalid argument: variable not present in input arguments"); + } + AnalyticFunction(const FunctionArgsList& args, const std::shared_ptr>& y) : FunctionBase>(args, y) { @@ -55,7 +72,7 @@ namespace codac2 { } template - AnalyticExprWrapper test(const X&... x) const + AnalyticExprWrapper operator()(const X&... x) const { return { this->FunctionBase>::operator()(x...) }; } @@ -226,4 +243,7 @@ namespace codac2 } }; + AnalyticFunction(const FunctionArgsList&, std::initializer_list>) -> + AnalyticFunction; + } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_constants.h b/src/core/functions/analytic/codac2_analytic_constants.h index 1dbb421c4..66d8ded10 100644 --- a/src/core/functions/analytic/codac2_analytic_constants.h +++ b/src/core/functions/analytic/codac2_analytic_constants.h @@ -61,8 +61,8 @@ namespace codac2 }; template - std::shared_ptr::Domain>> const_value(const T& x) + AnalyticExprWrapper::Domain> const_value(const T& x) { - return std::make_shared::Domain>>(x); + return { std::make_shared::Domain>>(x) }; } } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_operations.h b/src/core/functions/analytic/codac2_analytic_operations.h index a1a2b0eb5..4e2365b25 100644 --- a/src/core/functions/analytic/codac2_analytic_operations.h +++ b/src/core/functions/analytic/codac2_analytic_operations.h @@ -13,571 +13,572 @@ #include "codac2_AnalyticExpr.h" #include "codac2_analytic_variables.h" #include "codac2_analytic_constants.h" +#include "codac2_AnalyticExprWrapper.h" namespace codac2 { - using ScalarExpr_ptr = std::shared_ptr>; - using VectorExpr_ptr = std::shared_ptr>; - using MatrixExpr_ptr = std::shared_ptr>; + using ScalarExpr = AnalyticExprWrapper; + using VectorExpr = AnalyticExprWrapper; + using MatrixExpr = AnalyticExprWrapper; template - concept IsScalarExprOrVar = (std::is_base_of_v || std::is_base_of_v); + concept IsScalarExprOrVar = (std::is_base_of_v || std::is_base_of_v); template - concept IsVectorExprOrVar = (std::is_base_of_v || std::is_base_of_v); + concept IsVectorExprOrVar = (std::is_base_of_v || std::is_base_of_v); template - concept IsMatrixExprOrVar = (std::is_base_of_v || std::is_base_of_v); + concept IsMatrixExprOrVar = (std::is_base_of_v || std::is_base_of_v); // operator+ (unary case) - inline ScalarExpr_ptr - operator+(const ScalarExpr_ptr& x1) + inline ScalarExpr + operator+(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline VectorExpr_ptr - operator+(const VectorExpr_ptr& x1) + inline VectorExpr + operator+(const VectorExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline MatrixExpr_ptr - operator+(const MatrixExpr_ptr& x1) + inline MatrixExpr + operator+(const MatrixExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } // operator+ - inline ScalarExpr_ptr - operator+(ScalarExpr_ptr x1, ScalarExpr_ptr x2) + inline ScalarExpr + operator+(ScalarExpr x1, ScalarExpr x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } template requires (!IsScalarExprOrVar) - inline ScalarExpr_ptr - operator+(const X1& x1, ScalarExpr_ptr x2) + inline ScalarExpr + operator+(const X1& x1, ScalarExpr x2) { return operator+(const_value(x1),x2); } template requires (!IsScalarExprOrVar) - inline ScalarExpr_ptr - operator+(ScalarExpr_ptr x1, const X2& x2) + inline ScalarExpr + operator+(ScalarExpr x1, const X2& x2) { return operator+(x1, const_value(x2)); } - inline VectorExpr_ptr - operator+(VectorExpr_ptr x1, VectorExpr_ptr x2) + inline VectorExpr + operator+(VectorExpr x1, VectorExpr x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } template requires (!IsVectorExprOrVar) - inline VectorExpr_ptr - operator+(const X1& x1, VectorExpr_ptr x2) + inline VectorExpr + operator+(const X1& x1, VectorExpr x2) { return operator+(const_value(x1),x2); } template requires (!IsVectorExprOrVar) - inline VectorExpr_ptr - operator+(VectorExpr_ptr x1, const X2& x2) + inline VectorExpr + operator+(VectorExpr x1, const X2& x2) { return operator+(x1, const_value(x2)); } - inline MatrixExpr_ptr - operator+(MatrixExpr_ptr x1, MatrixExpr_ptr x2) + inline MatrixExpr + operator+(MatrixExpr x1, MatrixExpr x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } template requires (!IsMatrixExprOrVar) - inline MatrixExpr_ptr - operator+(const X1& x1, MatrixExpr_ptr x2) + inline MatrixExpr + operator+(const X1& x1, MatrixExpr x2) { return operator+(const_value(x1),x2); } template requires (!IsMatrixExprOrVar) - inline MatrixExpr_ptr - operator+(MatrixExpr_ptr x1, const X2& x2) + inline MatrixExpr + operator+(MatrixExpr x1, const X2& x2) { return operator+(x1, const_value(x2)); } // operator- (unary case) - inline ScalarExpr_ptr - operator-(const ScalarExpr_ptr& x1) + inline ScalarExpr + operator-(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline VectorExpr_ptr - operator-(const VectorExpr_ptr& x1) + inline VectorExpr + operator-(const VectorExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline MatrixExpr_ptr - operator-(const MatrixExpr_ptr& x1) + inline MatrixExpr + operator-(const MatrixExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } // operator- - inline ScalarExpr_ptr - operator-(const ScalarExpr_ptr& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + operator-(const ScalarExpr& x1, const ScalarExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } template requires (!IsScalarExprOrVar) - inline ScalarExpr_ptr - operator-(const X1& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + operator-(const X1& x1, const ScalarExpr& x2) { return operator-(const_value(x1),x2); } template requires (!IsScalarExprOrVar) - inline ScalarExpr_ptr - operator-(const ScalarExpr_ptr& x1, const X2& x2) + inline ScalarExpr + operator-(const ScalarExpr& x1, const X2& x2) { return operator-(x1, const_value(x2)); } - inline VectorExpr_ptr - operator-(const VectorExpr_ptr& x1, const VectorExpr_ptr& x2) + inline VectorExpr + operator-(const VectorExpr& x1, const VectorExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } template requires (!IsVectorExprOrVar) - inline VectorExpr_ptr - operator-(const X1& x1, const VectorExpr_ptr& x2) + inline VectorExpr + operator-(const X1& x1, const VectorExpr& x2) { return operator-(const_value(x1),x2); } template requires (!IsVectorExprOrVar) - inline VectorExpr_ptr - operator-(const VectorExpr_ptr& x1, const X2& x2) + inline VectorExpr + operator-(const VectorExpr& x1, const X2& x2) { return operator-(x1, const_value(x2)); } - inline MatrixExpr_ptr - operator-(const MatrixExpr_ptr& x1, const MatrixExpr_ptr& x2) + inline MatrixExpr + operator-(const MatrixExpr& x1, const MatrixExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } template requires (!IsMatrixExprOrVar) - inline MatrixExpr_ptr - operator-(const X1& x1, const MatrixExpr_ptr& x2) + inline MatrixExpr + operator-(const X1& x1, const MatrixExpr& x2) { return operator-(const_value(x1),x2); } template requires (!IsMatrixExprOrVar) - inline MatrixExpr_ptr - operator-(const MatrixExpr_ptr& x1, const X2& x2) + inline MatrixExpr + operator-(const MatrixExpr& x1, const X2& x2) { return operator-(x1, const_value(x2)); } // operator* - inline ScalarExpr_ptr - operator*(const ScalarExpr_ptr& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + operator*(const ScalarExpr& x1, const ScalarExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } - inline VectorExpr_ptr - operator*(const ScalarExpr_ptr& x1, const VectorExpr_ptr& x2) + inline VectorExpr + operator*(const ScalarExpr& x1, const VectorExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } - inline VectorExpr_ptr - operator*(const VectorExpr_ptr& x1, const ScalarExpr_ptr& x2) + inline VectorExpr + operator*(const VectorExpr& x1, const ScalarExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } - inline ScalarExpr_ptr - operator*(const Interval& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + operator*(const Interval& x1, const ScalarExpr& x2) { return operator*(const_value(x1),x2); } - inline ScalarExpr_ptr - operator*(const ScalarExpr_ptr& x1, const Interval& x2) + inline ScalarExpr + operator*(const ScalarExpr& x1, const Interval& x2) { return operator*(x1,const_value(x2)); } - inline VectorExpr_ptr - operator*(const Interval& x1, const VectorExpr_ptr& x2) + inline VectorExpr + operator*(const Interval& x1, const VectorExpr& x2) { return operator*(const_value(x1),x2); } - inline VectorExpr_ptr - operator*(const VectorExpr_ptr& x1, const Interval& x2) + inline VectorExpr + operator*(const VectorExpr& x1, const Interval& x2) { return operator*(x1,const_value(x2)); } - inline VectorExpr_ptr - operator*(const ScalarExpr_ptr& x1, const IntervalVector& x2) + inline VectorExpr + operator*(const ScalarExpr& x1, const IntervalVector& x2) { return operator*(x1,const_value(x2)); } - inline VectorExpr_ptr - operator*(const IntervalVector& x1, const ScalarExpr_ptr& x2) + inline VectorExpr + operator*(const IntervalVector& x1, const ScalarExpr& x2) { return operator*(const_value(x1),x2); } - inline VectorExpr_ptr - operator*(const MatrixExpr_ptr& x1, const VectorExpr_ptr& x2) + inline VectorExpr + operator*(const MatrixExpr& x1, const VectorExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } - inline VectorExpr_ptr - operator*(const MatrixExpr_ptr& x1, const IntervalVector& x2) + inline VectorExpr + operator*(const MatrixExpr& x1, const IntervalVector& x2) { - return std::make_shared>(x1,const_value(x2)); + return { std::make_shared>(x1,const_value(x2)) }; } - inline VectorExpr_ptr - operator*(const IntervalMatrix& x1, const VectorExpr_ptr& x2) + inline VectorExpr + operator*(const IntervalMatrix& x1, const VectorExpr& x2) { - return std::make_shared>(const_value(x1),x2); + return { std::make_shared>(const_value(x1),x2) }; } // operator/ - inline ScalarExpr_ptr - operator/(const ScalarExpr_ptr& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + operator/(const ScalarExpr& x1, const ScalarExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } template requires (!IsScalarExprOrVar) - inline ScalarExpr_ptr - operator/(const X1& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + operator/(const X1& x1, const ScalarExpr& x2) { return operator/(const_value(x1),x2); } template requires (!IsScalarExprOrVar) - inline ScalarExpr_ptr - operator/(const ScalarExpr_ptr& x1, const X2& x2) + inline ScalarExpr + operator/(const ScalarExpr& x1, const X2& x2) { return operator/(x1, const_value(x2)); } - inline VectorExpr_ptr - operator/(const VectorExpr_ptr& x1, const ScalarExpr_ptr& x2) + inline VectorExpr + operator/(const VectorExpr& x1, const ScalarExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } // Other operators - inline ScalarExpr_ptr - pow(const ScalarExpr_ptr& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + pow(const ScalarExpr& x1, const ScalarExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } template requires (!IsScalarExprOrVar) - inline ScalarExpr_ptr - pow(const X1& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + pow(const X1& x1, const ScalarExpr& x2) { return pow(const_value(x1),x2); } template requires (!IsScalarExprOrVar) - inline ScalarExpr_ptr - pow(const ScalarExpr_ptr& x1, const X2& x2) + inline ScalarExpr + pow(const ScalarExpr& x1, const X2& x2) { return pow(x1,const_value(x2)); } - inline ScalarExpr_ptr - sqr(const ScalarExpr_ptr& x1) + inline ScalarExpr + sqr(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - sqrt(const ScalarExpr_ptr& x1) + inline ScalarExpr + sqrt(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - exp(const ScalarExpr_ptr& x1) + inline ScalarExpr + exp(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - log(const ScalarExpr_ptr& x1) + inline ScalarExpr + log(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - cos(const ScalarExpr_ptr& x1) + inline ScalarExpr + cos(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - sin(const ScalarExpr_ptr& x1) + inline ScalarExpr + sin(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - tan(const ScalarExpr_ptr& x1) + inline ScalarExpr + tan(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - acos(const ScalarExpr_ptr& x1) + inline ScalarExpr + acos(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - asin(const ScalarExpr_ptr& x1) + inline ScalarExpr + asin(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - atan(const ScalarExpr_ptr& x1) + inline ScalarExpr + atan(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - atan2(const ScalarExpr_ptr& x1, const ScalarExpr_ptr& x2) + inline ScalarExpr + atan2(const ScalarExpr& x1, const ScalarExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } - inline ScalarExpr_ptr - cosh(const ScalarExpr_ptr& x1) + inline ScalarExpr + cosh(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - sinh(const ScalarExpr_ptr& x1) + inline ScalarExpr + sinh(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - tanh(const ScalarExpr_ptr& x1) + inline ScalarExpr + tanh(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - abs(const ScalarExpr_ptr& x1) + inline ScalarExpr + abs(const ScalarExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } // Structural operators - inline ScalarExpr_ptr _add_to_vec(const ScalarExpr_ptr& x) + inline ScalarExpr _add_to_vec(const ScalarExpr& x) { return x; } - inline ScalarExpr_ptr _add_to_vec(double x) + inline ScalarExpr _add_to_vec(double x) { return const_value(x); } template - concept IsNotScalarExpr = !std::is_base_of_v; + concept IsNotScalarExpr = !std::is_base_of_v; template requires IsNotScalarExpr - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1) { - return std::make_shared>( - _add_to_vec(x1)); + _add_to_vec(x1)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2)); + _add_to_vec(x1),_add_to_vec(x2)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3)); + _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4)); + _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5)); + _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6)); + _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6, const X7& x7) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7)); + _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6, const X7& x7, const X8& x8) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8)); + _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6, const X7& x7, const X8& x8, const X9& x9) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8),_add_to_vec(x9)); + _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8),_add_to_vec(x9)) }; } template requires (IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr && IsNotScalarExpr) - inline VectorExpr_ptr + inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6, const X7& x7, const X8& x8, const X9& x9, const X10& x10) { - return std::make_shared>( - _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8),_add_to_vec(x9),_add_to_vec(x10)); + _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8),_add_to_vec(x9),_add_to_vec(x10)) }; } // Generic variadic case, cannot handle const values (int, double) for now template - inline VectorExpr_ptr - vec(const std::shared_ptr>&... x) + inline VectorExpr + vec(const AnalyticExprWrapper&... x) { - return std::make_shared>(x...); + return { std::make_shared>(x...) }; } - inline ScalarExpr_ptr - ind(Index i, const VectorExpr_ptr& x1) + inline ScalarExpr + ind(Index i, const VectorExpr& x1) { - return std::make_shared>(x1,i); + return { std::make_shared>(x1,i) }; } template - inline MatrixExpr_ptr + inline MatrixExpr mat(const std::shared_ptr>&... x) { - return std::make_shared>( - AnalyticOperationExpr(x...)); + return { std::make_shared>( + AnalyticOperationExpr(x...)) }; } // Vectorial operations - inline ScalarExpr_ptr - det(const MatrixExpr_ptr& x1) + inline ScalarExpr + det(const MatrixExpr& x1) { - return std::make_shared>(x1); + return { std::make_shared>(x1) }; } - inline ScalarExpr_ptr - det(const VectorExpr_ptr& x1, const VectorExpr_ptr& x2) + inline ScalarExpr + det(const VectorExpr& x1, const VectorExpr& x2) { - return std::make_shared>(x1,x2); + return { std::make_shared>(x1,x2) }; } - inline ScalarExpr_ptr - det(const VectorExpr_ptr& x1, const VectorExpr_ptr& x2, const VectorExpr_ptr& x3) + inline ScalarExpr + det(const VectorExpr& x1, const VectorExpr& x2, const VectorExpr& x3) { - return std::make_shared>(x1,x2,x3); + return { std::make_shared>(x1,x2,x3) }; } } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_variables.cpp b/src/core/functions/analytic/codac2_analytic_variables.cpp new file mode 100644 index 000000000..1495e9e96 --- /dev/null +++ b/src/core/functions/analytic/codac2_analytic_variables.cpp @@ -0,0 +1,86 @@ +/** + * codac2_ExprBase.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_analytic_variables.h" +#include "codac2_AnalyticExprWrapper.h" + +using namespace std; +using namespace codac2; + + +// ScalarVar class + + ScalarVar::ScalarVar() + { } + + ScalarVar::ScalarVar(const ScalarVar& x) + : AnalyticVarExpr(x) + { } + + std::shared_ptr ScalarVar::arg_copy() const + { + return std::make_shared(*this); + } + + std::shared_ptr ScalarVar::copy() const + { + return std::make_shared(*this); + } + + Index ScalarVar::size() const + { + return 1; + } + + AnalyticExprWrapper ScalarVar::operator-() const + { + return { std::make_shared>(*this) }; + } + + +// VectorVar class + + VectorVar::VectorVar(Index n) + : _n(n) + { + assert_release(n > 0); + } + + VectorVar::VectorVar(const VectorVar& x) + : AnalyticVarExpr(x), _n(x._n) + { } + + std::shared_ptr VectorVar::arg_copy() const + { + return std::make_shared(*this); + } + + std::shared_ptr VectorVar::copy() const + { + return std::make_shared(*this); + } + + Index VectorVar::size() const + { + return _n; + } + + AnalyticExprWrapper VectorVar::operator[](Index i) const + { + assert_release(i >= 0 && i < _n); + return { std::make_shared>( + std::dynamic_pointer_cast>(this->copy()), i) }; + } + + AnalyticExprWrapper VectorVar::subvector(Index i, Index j) const + { + assert_release(i >= 0 && i < _n && j >= i && j < _n); + return { std::make_shared>( + std::dynamic_pointer_cast>(this->copy()), i, j) }; + } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_variables.h b/src/core/functions/analytic/codac2_analytic_variables.h index 3ea24a07a..aa4bce1d4 100644 --- a/src/core/functions/analytic/codac2_analytic_variables.h +++ b/src/core/functions/analytic/codac2_analytic_variables.h @@ -15,6 +15,9 @@ namespace codac2 { + template + class AnalyticExprWrapper; + template class AnalyticVarExpr : public AnalyticExpr, public VarBase { @@ -39,10 +42,16 @@ namespace codac2 void replace_expr([[maybe_unused]] const ExprID& old_expr_id, [[maybe_unused]] const std::shared_ptr& new_expr) { } + // to remove operator std::shared_ptr>() const { return std::dynamic_pointer_cast>(this->copy()); } + + operator AnalyticExprWrapper() const + { + return { std::dynamic_pointer_cast>(this->copy()) }; + } virtual bool belongs_to_args_list(const FunctionArgsList& args) const { @@ -57,76 +66,29 @@ namespace codac2 { public: - ScalarVar() - { } - - ScalarVar(const ScalarVar& x) - : AnalyticVarExpr(x) - { } - - std::shared_ptr arg_copy() const - { - return std::make_shared(*this); - } + ScalarVar(); + ScalarVar(const ScalarVar& x); - std::shared_ptr copy() const - { - return std::make_shared(*this); - } + std::shared_ptr arg_copy() const; + std::shared_ptr copy() const; + Index size() const; - Index size() const - { - return 1; - } - - std::shared_ptr> operator-() const - { - return std::make_shared>(*this); - } + AnalyticExprWrapper operator-() const; }; class VectorVar : public AnalyticVarExpr { public: - explicit VectorVar(Index n) - : _n(n) - { - assert_release(n > 0); - } + explicit VectorVar(Index n); + VectorVar(const VectorVar& x); - VectorVar(const VectorVar& x) - : AnalyticVarExpr(x), _n(x._n) - { } - - std::shared_ptr arg_copy() const - { - return std::make_shared(*this); - } - - std::shared_ptr copy() const - { - return std::make_shared(*this); - } + std::shared_ptr arg_copy() const; + std::shared_ptr copy() const; + Index size() const; - Index size() const - { - return _n; - } - - std::shared_ptr> operator[](Index i) const - { - assert_release(i >= 0 && i < _n); - return std::make_shared>( - std::dynamic_pointer_cast>(this->copy()), i); - } - - std::shared_ptr> subvector(Index i, Index j) const - { - assert_release(i >= 0 && i < _n && j >= i && j < _n); - return std::make_shared>( - std::dynamic_pointer_cast>(this->copy()), i, j); - } + AnalyticExprWrapper operator[](Index i) const; + AnalyticExprWrapper subvector(Index i, Index j) const; protected: diff --git a/src/core/functions/codac2_FunctionBase.h b/src/core/functions/codac2_FunctionBase.h index f3d4fd422..24fa453a9 100644 --- a/src/core/functions/codac2_FunctionBase.h +++ b/src/core/functions/codac2_FunctionBase.h @@ -83,13 +83,22 @@ namespace codac2 return std::dynamic_pointer_cast(x->copy()); } + template + std::shared_ptr __get_copy(const AnalyticExprWrapper& x) const + { + return x->copy(); + } + template auto __get_copy(const A& x) const { if constexpr(std::is_base_of_v) return std::dynamic_pointer_cast(x.copy()); else + { + // todo: make this generic (analytic / set): return const_value(x); + } } const std::shared_ptr _y; diff --git a/src/core/trajectory/codac2_Trajectory_operator.h b/src/core/trajectory/codac2_Trajectory_operator.h index dc71aa5f8..58ce6fe10 100644 --- a/src/core/trajectory/codac2_Trajectory_operator.h +++ b/src/core/trajectory/codac2_Trajectory_operator.h @@ -95,11 +95,13 @@ namespace codac2 template AnalyticFunction::Domain> TrajectoryBase::as_function() const { + using D = typename ArgWrapper::Domain; + ScalarVar t; return {{t}, - std::make_shared< + AnalyticExprWrapper(std::make_shared< AnalyticOperationExpr - , typename ArgWrapper::Domain, ScalarOpValue>>(*this,t) + , D, ScalarOpValue>>(*this,t)) }; } } \ No newline at end of file From 11e161cdd69be65c6c45d1ce25d94caf3cfb7491 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sun, 22 Dec 2024 19:40:37 +0100 Subject: [PATCH 040/126] [fnc] revised binding with recent updates (vec, AnalyticExprWrapper, etc) --- examples/02_centered_form/main.py | 4 +- python/codac/core/__init__.py | 16 +- python/src/core/codac2_py_core.cpp | 2 - .../analytic/codac2_py_AnalyticFunction.h | 159 +++++++++++++--- .../analytic/codac2_py_ExprWrapper.h | 174 ------------------ .../codac2_py_analytic_operations.cpp | 94 +++++----- .../analytic/codac2_py_analytic_variables.cpp | 6 +- .../graphics/figures/codac2_py_Figure2D.cpp | 4 +- .../analytic/codac2_AnalyticExprWrapper.h | 4 + .../analytic/codac2_AnalyticFunction.h | 8 + .../analytic/codac2_analytic_operations.h | 8 + .../analytic/codac2_tests_AnalyticFunction.py | 14 +- 12 files changed, 230 insertions(+), 263 deletions(-) diff --git a/examples/02_centered_form/main.py b/examples/02_centered_form/main.py index 374f861d6..41ff95f49 100644 --- a/examples/02_centered_form/main.py +++ b/examples/02_centered_form/main.py @@ -4,10 +4,10 @@ from codac import * x = VectorVar(3) -f = AnalyticFunction([x], vec( +f = AnalyticFunction([x], [ -sqr(x[2])+2*x[2]*sin(x[2]*x[0])+cos(x[2]*x[1]), 2*x[2]*cos(x[2]*x[0])-sin(x[2]*x[1]) -)) +]) ctc = CtcInverse(f, [0,0]) graphics.draw_while_paving([[0,2],[2,4],[0,10]], ctc, 0.004) \ No newline at end of file diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index 1c9cd2207..6948719f8 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -19,9 +19,17 @@ class AnalyticFunction: def __init__(self, args, e): if isinstance(e, (int,float,Interval,ScalarVar,ScalarExpr)): - self.f = AnalyticFunction_Scalar(args,e) + self.f = AnalyticFunction_Scalar(args,ScalarExpr(e)) elif isinstance(e, (Vector,IntervalVector,VectorVar,VectorExpr)): - self.f = AnalyticFunction_Vector(args,e) + self.f = AnalyticFunction_Vector(args,VectorExpr(e)) + elif isinstance(e, list): + lst=[] + for e_i in e: + if isinstance(e_i, (int,float,Interval,ScalarVar,ScalarExpr)): + lst.append(ScalarExpr(e_i)) + else: + codac_error("AnalyticFunction: invalid vectorial expression") + self.f = AnalyticFunction_Vector(args,lst) else: codac_error("AnalyticFunction: can only build functions from scalar or vector expressions") @@ -44,9 +52,9 @@ def __call__(self,*args): lst=[] for arg in args: if isinstance(arg, (int,float,Interval,ScalarVar,ScalarExpr)): - lst.append(ScalarExpr(arg).raw_copy()) + lst.append(ScalarExpr(arg)) elif isinstance(arg, (Vector,IntervalVector,VectorVar,VectorExpr)): - lst.append(VectorExpr(arg).raw_copy()) + lst.append(VectorExpr(arg)) else: codac_error("AnalyticFunction: invalid input arguments") return self.f(lst) diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index 04a1a0f73..0ec5f4fd1 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -62,7 +62,6 @@ void export_PavingNode(py::module& m); void export_Subpaving(py::module& m); // functions -void export_ExprWrapperBase(py::module& m); void export_ScalarVar(py::module& m); void export_VectorVar(py::module& m); void export_expression_operations(py::module& m); @@ -192,7 +191,6 @@ PYBIND11_MODULE(_core, m) .def(py::self | py::self, EVALMODE_OPERATOROR_EVALMODE_EVALMODE) ; - export_ExprWrapperBase(m); export_ScalarExpr(m); export_VectorExpr(m); export_AnalyticFunction(m,"AnalyticFunction_Scalar"); diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index dc4e57000..05d3cc609 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -89,6 +89,52 @@ using namespace pybind11::literals; \ ; \ + +AnalyticExprWrapper pyobj_to_ScalarExpr(py::object& obj) +{ + if(py::isinstance(obj)) + return obj.cast(); + assert(false && "unable to convert py::object to ScalarExpr"); + return { nullptr }; +} + +std::shared_ptr pyobj_to_ExprBase(const py::object& obj) +{ + if(obj) + { + if(py::isinstance>(obj)) + return obj.cast>()->copy(); + + else if(py::isinstance>(obj)) + return obj.cast>()->copy(); + } + + assert_release("invalid expression"); + return nullptr; +} + +FunctionArgsList create_FunctionArgsList(const std::vector& l) +{ + FunctionArgsList args {}; + Index i = 0; + + for(const auto& li : l) + { + i++; + + if(py::isinstance(li)) + args.push_back(li.cast().arg_copy()); + + else if(py::isinstance(li)) + args.push_back(li.cast().arg_copy()); + + else + throw std::invalid_argument("Argument " + std::to_string(i) + " is invalid. Only variables are accepted."); + } + + return args; +} + template void export_AnalyticFunction(py::module& m, const std::string& export_name) { @@ -97,38 +143,107 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) exported .def(py::init( - [](const std::vector& l, const ExprWrapper& expr) + [](const std::vector& l, const AnalyticExprWrapper& expr) { - FunctionArgsList args {}; - Index i = 0; - - for(const auto& li : l) - { - i++; - - if(py::isinstance(li)) - args.push_back(li.cast().arg_copy()); - - else if(py::isinstance(li)) - args.push_back(li.cast().arg_copy()); - - else - throw std::invalid_argument("Argument " + std::to_string(i) + " is invalid. Only variables are accepted."); - } - - return std::make_unique>(args, expr.copy()); + return std::make_unique>( + create_FunctionArgsList(l), + std::dynamic_pointer_cast>(expr.get()->copy()) + ); } ), ANALYTICFUNCTION_T_ANALYTICFUNCTION_CONST_FUNCTIONARGSLIST_REF_CONST_SHARED_PTR_ANALYTICEXPR_T_REF) + ; + + if constexpr(std::is_same_v) + { + exported.def(py::init( + [](const std::vector& l, std::vector& v_expr) + { + return std::make_unique>( + create_FunctionArgsList(l), + [&]() -> VectorExpr { + switch(v_expr.size()) + { + case 1: + return vec( + pyobj_to_ScalarExpr(v_expr[0]) + ); + case 2: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]) + ); + case 3: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), + pyobj_to_ScalarExpr(v_expr[2]) + ); + case 4: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), + pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]) + ); + case 5: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), + pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), + pyobj_to_ScalarExpr(v_expr[4]) + ); + case 6: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), + pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), + pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]) + ); + case 7: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), + pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), + pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]), + pyobj_to_ScalarExpr(v_expr[6]) + ); + case 8: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), + pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), + pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]), + pyobj_to_ScalarExpr(v_expr[6]), pyobj_to_ScalarExpr(v_expr[7]) + ); + case 9: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), + pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), + pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]), + pyobj_to_ScalarExpr(v_expr[6]), pyobj_to_ScalarExpr(v_expr[7]), + pyobj_to_ScalarExpr(v_expr[8]) + ); + case 10: + return vec( + pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), + pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), + pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]), + pyobj_to_ScalarExpr(v_expr[6]), pyobj_to_ScalarExpr(v_expr[7]), + pyobj_to_ScalarExpr(v_expr[8]), pyobj_to_ScalarExpr(v_expr[9]) + ); + default: + assert_release("cannot create AnalyticFunction with provided vector arguments"); + return { nullptr }; + } + }() + ); + } + ), ANALYTICFUNCTION_T_ANALYTICFUNCTION_CONST_FUNCTIONARGSLIST_REF_CONST_SCALAREXPRLIST_REF); + } + + exported .def("input_size", &AnalyticFunction::input_size, INDEX_FUNCTIONBASE_E_INPUT_SIZE_CONST) - .def("__call__", [](const AnalyticFunction& f, const std::vector& x) + .def("__call__", [](const AnalyticFunction& f, py::list& x) { std::vector> v(x.size()); for(size_t i = 0 ; i < x.size() ; i++) - v[i] = x[i].eb->copy(); - return ExprWrapper(std::dynamic_pointer_cast>(f(v)->copy())); + v[i] = pyobj_to_ExprBase(x[i]); + return AnalyticExprWrapper(std::dynamic_pointer_cast>(f(v)->copy())); }, SHARED_PTR_E_FUNCTIONBASE_E_OPERATORCALL_CONST_X_REF_VARIADIC_CONST) ; diff --git a/python/src/core/functions/analytic/codac2_py_ExprWrapper.h b/python/src/core/functions/analytic/codac2_py_ExprWrapper.h index 0bac7b357..c58bed113 100644 --- a/python/src/core/functions/analytic/codac2_py_ExprWrapper.h +++ b/python/src/core/functions/analytic/codac2_py_ExprWrapper.h @@ -23,174 +23,6 @@ using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -template -struct ExprWrapper; - -struct ExprWrapperBase -{ - ExprWrapperBase() - { } - - ExprWrapperBase(const std::shared_ptr& eb_) - : eb(eb_) - { } - - std::shared_ptr eb = nullptr; -}; - -template<> -struct ExprWrapper -{ - ExprWrapper(const Interval& e) - : e(std::dynamic_pointer_cast>(const_value(e)->copy())) - { } - - ExprWrapper(const ScalarVar& e) - : e(std::dynamic_pointer_cast>(e.copy())) - { } - - ExprWrapper(const ExprWrapper& e) - : e(std::dynamic_pointer_cast>(e.copy())) - { } - - explicit ExprWrapper(const std::shared_ptr>& e) - : e(std::dynamic_pointer_cast>(e->copy())) - { } - - std::shared_ptr> copy() const - { - return std::dynamic_pointer_cast>(e->copy()); - } - - operator std::shared_ptr>() - { - return copy(); - } - - virtual ExprWrapperBase raw_copy() const - { - return ExprWrapperBase(e->copy()); - } - - std::shared_ptr> e; -}; - -using ScalarExpr = ExprWrapper; - -// Scalar operations - -inline const ScalarExpr& operator+(const ScalarExpr& e1) -{ - return e1; -} - -inline ScalarExpr operator+(const ScalarExpr& e1, const ScalarExpr& e2) -{ - return ScalarExpr(e1.e+e2.e); -} - -inline ScalarExpr operator-(const ScalarExpr& e1) -{ - return ScalarExpr(-e1.e); -} - -inline ScalarExpr operator-(const ScalarExpr& e1, const ScalarExpr& e2) -{ - return ScalarExpr(e1.e-e2.e); -} - -inline ScalarExpr operator*(const ScalarExpr& e1, const ScalarExpr& e2) -{ - return ScalarExpr(e1.e*e2.e); -} - -inline ScalarExpr operator/(const ScalarExpr& e1, const ScalarExpr& e2) -{ - return ScalarExpr(e1.e/e2.e); -} - -template<> -struct ExprWrapper -{ - ExprWrapper(const IntervalVector& e) - : e(std::dynamic_pointer_cast>(const_value(e)->copy())) - { } - - ExprWrapper(const VectorVar& e) - : e(std::dynamic_pointer_cast>(e.copy())) - { } - - ExprWrapper(const ExprWrapper& e) - : e(std::dynamic_pointer_cast>(e.copy())) - { } - - explicit ExprWrapper(const std::shared_ptr>& e) - : e(std::dynamic_pointer_cast>(e->copy())) - { } - - std::shared_ptr> copy() const - { - return std::dynamic_pointer_cast>(e->copy()); - } - - operator std::shared_ptr>() - { - return copy(); - } - - virtual ExprWrapperBase raw_copy() const - { - return ExprWrapperBase(e->copy()); - } - - std::shared_ptr> e; -}; - -using VectorExpr = ExprWrapper; - -// Vector operations - -inline const VectorExpr& operator+(const VectorExpr& e1) -{ - return e1; -} - -inline VectorExpr operator+(const VectorExpr& e1, const VectorExpr& e2) -{ - return VectorExpr(e1.e+e2.e); -} - -inline VectorExpr operator-(const VectorExpr& e1) -{ - return VectorExpr(-e1.e); -} - -inline VectorExpr operator-(const VectorExpr& e1, const VectorExpr& e2) -{ - return VectorExpr(e1.e-e2.e); -} - -inline VectorExpr operator*(const ScalarExpr& e1, const VectorExpr& e2) -{ - return VectorExpr(e1.e*e2.e); -} - -inline VectorExpr operator*(const VectorExpr& e1, const ScalarExpr& e2) -{ - return VectorExpr(e1.e*e2.e); -} - -inline VectorExpr operator/(const VectorExpr& e1, const ScalarExpr& e2) -{ - return VectorExpr(e1.e/e2.e); -} - -inline void export_ExprWrapperBase(py::module& m) -{ - py::class_ py_wrap(m, "ExprWrapperBase"); - py_wrap .def(py::init&>()); -} - inline void export_ScalarExpr(py::module& m) { py::class_ @@ -198,12 +30,9 @@ inline void export_ScalarExpr(py::module& m) exported - .def(py::init>>()) .def(py::init()) .def(py::init()) .def(py::init()) - .def("copy", &ScalarExpr::copy) - .def("raw_copy", &ScalarExpr::raw_copy) .def("__pos__", [](const ScalarExpr& e1) { return e1; }, py::is_operator()) .def(py::self + py::self) @@ -243,12 +72,9 @@ inline void export_VectorExpr(py::module& m) exported - .def(py::init>>()) .def(py::init()) .def(py::init()) .def(py::init()) - .def("copy", &VectorExpr::copy) - .def("raw_copy", &VectorExpr::raw_copy) .def("__pos__", [](const VectorExpr& e1) { return e1; }, py::is_operator()) .def(py::self + py::self) diff --git a/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp b/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp index dc0008579..52c353426 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp @@ -27,92 +27,92 @@ void export_expression_operations(py::module& m) { m - .def("pow", [](const ScalarExpr& e1, const ScalarExpr& e2) { return ScalarExpr(pow(e1.e,e2.e)); }, - SCALAREXPR_PTR_POW_CONST_SCALAREXPR_PTR_REF_CONST_SCALAREXPR_PTR_REF, + .def("pow", [](const ScalarExpr& e1, const ScalarExpr& e2) { return ScalarExpr(pow(e1,e2)); }, + SCALAREXPR_POW_CONST_SCALAREXPR_REF_CONST_SCALAREXPR_REF, "x1"_a, "x2"_a) - .def("pow", [](const Interval& e1, const ScalarExpr& e2) { return ScalarExpr(pow(e1,e2.e)); }, - SCALAREXPR_PTR_POW_CONST_X1_REF_CONST_SCALAREXPR_PTR_REF, + .def("pow", [](const Interval& e1, const ScalarExpr& e2) { return ScalarExpr(pow(e1,e2)); }, + SCALAREXPR_POW_CONST_X1_REF_CONST_SCALAREXPR_REF, "x1"_a, "x2"_a) - .def("pow", [](const ScalarExpr& e1, const Interval& e2) { return ScalarExpr(pow(e1.e,e2)); }, - SCALAREXPR_PTR_POW_CONST_SCALAREXPR_PTR_REF_CONST_X2_REF, + .def("pow", [](const ScalarExpr& e1, const Interval& e2) { return ScalarExpr(pow(e1,e2)); }, + SCALAREXPR_POW_CONST_SCALAREXPR_REF_CONST_X2_REF, "x1"_a, "x2"_a) - .def("sqr", [](const ScalarExpr& e1) { return ScalarExpr(sqr(e1.e)); }, - SCALAREXPR_PTR_SQR_CONST_SCALAREXPR_PTR_REF, + .def("sqr", [](const ScalarExpr& e1) { return ScalarExpr(sqr(e1)); }, + SCALAREXPR_SQR_CONST_SCALAREXPR_REF, "x1"_a) - .def("sqrt", [](const ScalarExpr& e1) { return ScalarExpr(sqrt(e1.e)); }, - SCALAREXPR_PTR_SQRT_CONST_SCALAREXPR_PTR_REF, + .def("sqrt", [](const ScalarExpr& e1) { return ScalarExpr(sqrt(e1)); }, + SCALAREXPR_SQRT_CONST_SCALAREXPR_REF, "x1"_a) - .def("exp", [](const ScalarExpr& e1) { return ScalarExpr(exp(e1.e)); }, - SCALAREXPR_PTR_EXP_CONST_SCALAREXPR_PTR_REF, + .def("exp", [](const ScalarExpr& e1) { return ScalarExpr(exp(e1)); }, + SCALAREXPR_EXP_CONST_SCALAREXPR_REF, "x1"_a) - .def("log", [](const ScalarExpr& e1) { return ScalarExpr(log(e1.e)); }, - SCALAREXPR_PTR_LOG_CONST_SCALAREXPR_PTR_REF, + .def("log", [](const ScalarExpr& e1) { return ScalarExpr(log(e1)); }, + SCALAREXPR_LOG_CONST_SCALAREXPR_REF, "x1"_a) - .def("cos", [](const ScalarExpr& e1) { return ScalarExpr(cos(e1.e)); }, - SCALAREXPR_PTR_COS_CONST_SCALAREXPR_PTR_REF, + .def("cos", [](const ScalarExpr& e1) { return ScalarExpr(cos(e1)); }, + SCALAREXPR_COS_CONST_SCALAREXPR_REF, "x1"_a) - .def("sin", [](const ScalarExpr& e1) { return ScalarExpr(sin(e1.e)); }, - SCALAREXPR_PTR_SIN_CONST_SCALAREXPR_PTR_REF, + .def("sin", [](const ScalarExpr& e1) { return ScalarExpr(sin(e1)); }, + SCALAREXPR_SIN_CONST_SCALAREXPR_REF, "x1"_a) - .def("tan", [](const ScalarExpr& e1) { return ScalarExpr(tan(e1.e)); }, - SCALAREXPR_PTR_TAN_CONST_SCALAREXPR_PTR_REF, + .def("tan", [](const ScalarExpr& e1) { return ScalarExpr(tan(e1)); }, + SCALAREXPR_TAN_CONST_SCALAREXPR_REF, "x1"_a) - .def("acos", [](const ScalarExpr& e1) { return ScalarExpr(acos(e1.e)); }, - SCALAREXPR_PTR_ACOS_CONST_SCALAREXPR_PTR_REF, + .def("acos", [](const ScalarExpr& e1) { return ScalarExpr(acos(e1)); }, + SCALAREXPR_ACOS_CONST_SCALAREXPR_REF, "x1"_a) - .def("asin", [](const ScalarExpr& e1) { return ScalarExpr(asin(e1.e)); }, - SCALAREXPR_PTR_ASIN_CONST_SCALAREXPR_PTR_REF, + .def("asin", [](const ScalarExpr& e1) { return ScalarExpr(asin(e1)); }, + SCALAREXPR_ASIN_CONST_SCALAREXPR_REF, "x1"_a) - .def("atan", [](const ScalarExpr& e1) { return ScalarExpr(atan(e1.e)); }, - SCALAREXPR_PTR_ATAN_CONST_SCALAREXPR_PTR_REF, + .def("atan", [](const ScalarExpr& e1) { return ScalarExpr(atan(e1)); }, + SCALAREXPR_ATAN_CONST_SCALAREXPR_REF, "x1"_a) - .def("atan2", [](const ScalarExpr& e1, const ScalarExpr& e2) { return ScalarExpr(atan2(e1.e,e2.e)); }, - SCALAREXPR_PTR_ATAN2_CONST_SCALAREXPR_PTR_REF_CONST_SCALAREXPR_PTR_REF, + .def("atan2", [](const ScalarExpr& e1, const ScalarExpr& e2) { return ScalarExpr(atan2(e1,e2)); }, + SCALAREXPR_ATAN2_CONST_SCALAREXPR_REF_CONST_SCALAREXPR_REF, "x1"_a, "x2"_a) - .def("cosh", [](const ScalarExpr& e1) { return ScalarExpr(cosh(e1.e)); }, - SCALAREXPR_PTR_COSH_CONST_SCALAREXPR_PTR_REF, + .def("cosh", [](const ScalarExpr& e1) { return ScalarExpr(cosh(e1)); }, + SCALAREXPR_COSH_CONST_SCALAREXPR_REF, "x1"_a) - .def("sinh", [](const ScalarExpr& e1) { return ScalarExpr(sinh(e1.e)); }, - SCALAREXPR_PTR_SINH_CONST_SCALAREXPR_PTR_REF, + .def("sinh", [](const ScalarExpr& e1) { return ScalarExpr(sinh(e1)); }, + SCALAREXPR_SINH_CONST_SCALAREXPR_REF, "x1"_a) - .def("tanh", [](const ScalarExpr& e1) { return ScalarExpr(tanh(e1.e)); }, - SCALAREXPR_PTR_TANH_CONST_SCALAREXPR_PTR_REF, + .def("tanh", [](const ScalarExpr& e1) { return ScalarExpr(tanh(e1)); }, + SCALAREXPR_TANH_CONST_SCALAREXPR_REF, "x1"_a) - .def("abs", [](const ScalarExpr& e1) { return ScalarExpr(abs(e1.e)); }, - SCALAREXPR_PTR_ABS_CONST_SCALAREXPR_PTR_REF, + .def("abs", [](const ScalarExpr& e1) { return ScalarExpr(abs(e1)); }, + SCALAREXPR_ABS_CONST_SCALAREXPR_REF, "x1"_a) ; - const char* EVAL_VEC_DOC = VECTOREXPR_PTR_VEC_CONST_SHARED_PTR_ANALYTICEXPR_X_REF_VARIADIC; + const char* EVAL_VEC_DOC = VECTOREXPR_VEC_CONST_ANALYTICEXPRWRAPPER_X_REF_VARIADIC; using S = const ScalarExpr&; - m .def("vec", [](S e1) { return VectorExpr(vec(e1.e)); }, EVAL_VEC_DOC, "x1"_a) - .def("vec", [](S e1, S e2) { return VectorExpr(vec(e1.e,e2.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a) - .def("vec", [](S e1, S e2, S e3) { return VectorExpr(vec(e1.e,e2.e,e3.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a) - .def("vec", [](S e1, S e2, S e3, S e4) { return VectorExpr(vec(e1.e,e2.e,e3.e,e4.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5) { return VectorExpr(vec(e1.e,e2.e,e3.e,e4.e,e5.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6) { return VectorExpr(vec(e1.e,e2.e,e3.e,e4.e,e5.e,e6.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7) { return VectorExpr(vec(e1.e,e2.e,e3.e,e4.e,e5.e,e6.e,e7.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8) { return VectorExpr(vec(e1.e,e2.e,e3.e,e4.e,e5.e,e6.e,e7.e,e8.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8, S e9) { return VectorExpr(vec(e1.e,e2.e,e3.e,e4.e,e5.e,e6.e,e7.e,e8.e,e9.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a,"x9"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8, S e9, S e10) { return VectorExpr(vec(e1.e,e2.e,e3.e,e4.e,e5.e,e6.e,e7.e,e8.e,e9.e,e10.e)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a,"x9"_a,"x10"_a) + m .def("vec", [](S e1) { return VectorExpr(vec(e1)); }, EVAL_VEC_DOC, "x1"_a) + .def("vec", [](S e1, S e2) { return VectorExpr(vec(e1,e2)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a) + .def("vec", [](S e1, S e2, S e3) { return VectorExpr(vec(e1,e2,e3)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a) + .def("vec", [](S e1, S e2, S e3, S e4) { return VectorExpr(vec(e1,e2,e3,e4)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5) { return VectorExpr(vec(e1,e2,e3,e4,e5)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6,e7)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6,e7,e8)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8, S e9) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6,e7,e8,e9)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a,"x9"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8, S e9, S e10) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6,e7,e8,e9,e10)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a,"x9"_a,"x10"_a) ; } \ No newline at end of file diff --git a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp index ba7f2c7f3..fa7d97734 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp @@ -94,13 +94,13 @@ void export_VectorVar(py::module& m) exported.def("__call__", [](const VectorVar& v, Index_type i) -> ScalarExpr { return get_item(v, i); - }, SHARED_PTR_ANALYTICEXPR_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); + }, ANALYTICEXPRWRAPPER_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); else exported.def("__getitem__", [](const VectorVar& v, Index_type i) -> ScalarExpr { return get_item(v, i); - }, SHARED_PTR_ANALYTICEXPR_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); + }, ANALYTICEXPRWRAPPER_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); exported @@ -109,7 +109,7 @@ void export_VectorVar(py::module& m) matlab::test_integer(i, j); return VectorExpr(std::dynamic_pointer_cast>( v.subvector(matlab::input_index(i),matlab::input_index(j))->copy())); - }, SHARED_PTR_ANALYTICEXPR_VECTOROPVALUE_VECTORVAR_SUBVECTOR_INDEX_INDEX_CONST) + }, ANALYTICEXPRWRAPPER_VECTOROPVALUE_VECTORVAR_SUBVECTOR_INDEX_INDEX_CONST) .def("__pos__", [](const VectorVar& e1) { return VectorExpr(VectorExpr(e1)); }, py::is_operator()) .def("__add__", [](const VectorVar& e1, const VectorVar& e2) { return VectorExpr(VectorExpr(e1) + VectorExpr(e2)); }, py::is_operator()) diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index f976cca23..e4898aea8 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -126,7 +126,7 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_DRAW_ELLIPSE_CONST_VECTOR_REF_CONST_VECTOR_REF_DOUBLE_CONST_STYLEPROPERTIES_REF, "c"_a, "ab"_a, "theta"_a, "s"_a=StyleProperties()) - .def("draw_trajectory", [](Figure2D& fig, py::object x, const StyleProperties& s) + .def("draw_trajectory", [](Figure2D& fig, const py::object& x, const StyleProperties& s) { py::object x_traj = x.attr("traj"); @@ -222,7 +222,7 @@ void export_Figure2D(py::module& m) STATIC_VOID_DEFAULTVIEW_DRAW_PIE_CONST_VECTOR_REF_CONST_INTERVAL_REF_CONST_INTERVAL_REF_CONST_STYLEPROPERTIES_REF, "c"_a, "r"_a, "theta"_a, "s"_a=StyleProperties()) - .def_static("draw_trajectory", [](py::object x, const StyleProperties& s) + .def_static("draw_trajectory", [](const py::object& x, const StyleProperties& s) { py::object x_traj = x.attr("traj"); diff --git a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h index e6e40a977..14263fc76 100644 --- a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h +++ b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h @@ -20,6 +20,10 @@ namespace codac2 : std::shared_ptr>(e) { } + explicit AnalyticExprWrapper(const typename T::Domain& e) + : std::shared_ptr>(const_value(e)) + { } + template requires std::is_same_v inline AnalyticExprWrapper operator[](Index i) diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index 18cb2e9fc..e98357ea6 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -50,6 +50,14 @@ namespace codac2 public: AnalyticFunction(const FunctionArgsList& args, const ScalarExprList& y) + requires(std::is_same_v) + : FunctionBase>(args, y) + { + assert_release(y->belongs_to_args_list(this->args()) && + "Invalid argument: variable not present in input arguments"); + } + + AnalyticFunction(const FunctionArgsList& args, const AnalyticExprWrapper& y) : FunctionBase>(args, y) { assert_release(y->belongs_to_args_list(this->args()) && diff --git a/src/core/functions/analytic/codac2_analytic_operations.h b/src/core/functions/analytic/codac2_analytic_operations.h index 4e2365b25..077a2bc01 100644 --- a/src/core/functions/analytic/codac2_analytic_operations.h +++ b/src/core/functions/analytic/codac2_analytic_operations.h @@ -310,6 +310,14 @@ namespace codac2 return { std::make_shared>(x1,x2) }; } + template + requires (!IsScalarExprOrVar) + inline VectorExpr + operator/(const VectorExpr& x1, const X2& x2) + { + return operator/(x1, const_value(x2)); + } + // Other operators inline ScalarExpr diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py index e27da09bd..92e429740 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py @@ -55,16 +55,16 @@ def test_eval(f,*args): f = AnalyticFunction([x], cos(x)) self.assertTrue(Approx(test_eval(f,Interval(0))) == 1) - f = AnalyticFunction([x], vec(x,x)) + f = AnalyticFunction([x], [x,x]) - fvec = AnalyticFunction([x], vec(x,x)) + fvec = AnalyticFunction([x], [x,x]) self.assertTrue(Approx(test_eval(f,1)) == IntervalVector([[1],[1]])) - self.assertTrue(test_eval(AnalyticFunction([], +4), ) == 4) - self.assertTrue(test_eval(AnalyticFunction([], +4.), ) == 4.) - self.assertTrue(test_eval(AnalyticFunction([], +Interval(4,5)), ) == Interval(4,5)) - self.assertTrue(test_eval(AnalyticFunction([], Vector([2,9])), ) == Vector([2,9])) - self.assertTrue(test_eval(AnalyticFunction([], IntervalVector(3)), ) == IntervalVector([[-oo,oo],[-oo,oo],[-oo,oo]])) + self.assertTrue(test_eval(AnalyticFunction([], +4)) == 4) + self.assertTrue(test_eval(AnalyticFunction([], +4.)) == 4.) + self.assertTrue(test_eval(AnalyticFunction([], +Interval(4,5))) == Interval(4,5)) + self.assertTrue(test_eval(AnalyticFunction([], Vector([2,9]))) == Vector([2,9])) + self.assertTrue(test_eval(AnalyticFunction([], IntervalVector(3))) == IntervalVector([[-oo,oo],[-oo,oo],[-oo,oo]])) x1 = ScalarVar() x2 = ScalarVar() From c08ba44b94261c214a73a9175d74f8ead4a01e79 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sun, 22 Dec 2024 19:50:55 +0100 Subject: [PATCH 041/126] [fnc] py binding: operator[] for vector expressions --- doc/manual/index.rst | 10 +++++++++- python/src/core/CMakeLists.txt | 2 +- ...rWrapper.h => codac2_py_AnalyticExprWrapper.h} | 13 ++++++++++--- .../analytic/codac2_py_AnalyticFunction.h | 6 +++--- .../analytic/codac2_py_analytic_operations.cpp | 2 +- .../analytic/codac2_py_analytic_variables.cpp | 2 +- .../analytic/codac2_AnalyticExprWrapper.h | 15 ++++++++++++++- .../analytic/codac2_analytic_operations.h | 13 ------------- 8 files changed, 39 insertions(+), 24 deletions(-) rename python/src/core/functions/analytic/{codac2_py_ExprWrapper.h => codac2_py_AnalyticExprWrapper.h} (90%) diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 460fb89b5..1dc364340 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -13,15 +13,23 @@ Codac manual .. toctree:: :caption: User manual - :maxdepth: 3 + :maxdepth: 2 installation/index.rst intervals/index.rst linear/index.rst functions/index.rst tubes/index.rst + +.. toctree:: + :maxdepth: 3 + contractors/index.rst separators/index.rst + +.. toctree:: + :maxdepth: 2 + pavers/index.rst cn/index.rst geometry/index.rst diff --git a/python/src/core/CMakeLists.txt b/python/src/core/CMakeLists.txt index 5fb9220ce..5caa37207 100644 --- a/python/src/core/CMakeLists.txt +++ b/python/src/core/CMakeLists.txt @@ -47,7 +47,7 @@ functions/analytic/codac2_py_analytic_operations.cpp functions/analytic/codac2_py_analytic_variables.cpp functions/analytic/codac2_py_AnalyticFunction.h - functions/analytic/codac2_py_ExprWrapper.h + functions/analytic/codac2_py_AnalyticExprWrapper.h geometry/codac2_py_Edge.cpp geometry/codac2_py_geometry.cpp diff --git a/python/src/core/functions/analytic/codac2_py_ExprWrapper.h b/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h similarity index 90% rename from python/src/core/functions/analytic/codac2_py_ExprWrapper.h rename to python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h index c58bed113..b130b3b67 100644 --- a/python/src/core/functions/analytic/codac2_py_ExprWrapper.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h @@ -14,10 +14,10 @@ #include #include #include +#include "codac2_AnalyticExprWrapper.h" #include "codac2_analytic_operations.h" -#include "codac2_analytic_variables.h" -#include "codac2_AnalyticExpr.h" -#include "codac2_AnalyticFunction.h" +#include "codac2_py_matlab.h" +#include "codac2_py_AnalyticExprWrapper_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) using namespace codac2; namespace py = pybind11; @@ -76,6 +76,13 @@ inline void export_VectorExpr(py::module& m) .def(py::init()) .def(py::init()) + .def("__getitem__", [](const VectorExpr& x, Index_type index) + { + matlab::test_integer(index); + return x[matlab::input_index(index)]; + }, py::return_value_policy::reference_internal, + ANALYTICEXPRWRAPPER_SCALAROPVALUE_ANALYTICEXPRWRAPPER_T_OPERATORCOMPO_INDEX_CONST) + .def("__pos__", [](const VectorExpr& e1) { return e1; }, py::is_operator()) .def(py::self + py::self) .def("__add__", [](const VectorExpr& e1, const VectorVar& e2) { return e1+e2; }, py::is_operator()) diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index 05d3cc609..6c776edfb 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -19,7 +19,7 @@ #include #include "codac2_py_AnalyticFunction_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) #include "codac2_py_FunctionBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_ExprWrapper.h" +#include "codac2_py_AnalyticExprWrapper.h" using namespace codac2; namespace py = pybind11; @@ -90,7 +90,7 @@ using namespace pybind11::literals; ; \ -AnalyticExprWrapper pyobj_to_ScalarExpr(py::object& obj) +AnalyticExprWrapper pyobj_to_ScalarExpr(const py::object& obj) { if(py::isinstance(obj)) return obj.cast(); @@ -156,7 +156,7 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) if constexpr(std::is_same_v) { exported.def(py::init( - [](const std::vector& l, std::vector& v_expr) + [](const std::vector& l, const std::vector& v_expr) { return std::make_unique>( create_FunctionArgsList(l), diff --git a/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp b/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp index 52c353426..9706af0da 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp @@ -16,7 +16,7 @@ #include #include #include "codac2_py_analytic_operations_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) -#include "codac2_py_ExprWrapper.h" +#include "codac2_py_AnalyticExprWrapper.h" using namespace codac2; namespace py = pybind11; diff --git a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp index fa7d97734..08f15fa42 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp @@ -14,7 +14,7 @@ #include #include #include "codac2_py_analytic_variables_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): -#include "codac2_py_ExprWrapper.h" +#include "codac2_py_AnalyticExprWrapper.h" #include "codac2_py_matlab.h" using namespace codac2; diff --git a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h index 14263fc76..c5049a5ab 100644 --- a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h +++ b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h @@ -26,9 +26,22 @@ namespace codac2 template requires std::is_same_v - inline AnalyticExprWrapper operator[](Index i) + inline AnalyticExprWrapper operator[](Index i) const { return { std::make_shared>(*this,i) }; } }; + + using ScalarExpr = AnalyticExprWrapper; + using VectorExpr = AnalyticExprWrapper; + using MatrixExpr = AnalyticExprWrapper; + + template + concept IsScalarExprOrVar = (std::is_base_of_v || std::is_base_of_v); + + template + concept IsVectorExprOrVar = (std::is_base_of_v || std::is_base_of_v); + + template + concept IsMatrixExprOrVar = (std::is_base_of_v || std::is_base_of_v); } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_operations.h b/src/core/functions/analytic/codac2_analytic_operations.h index 077a2bc01..a8aac1625 100644 --- a/src/core/functions/analytic/codac2_analytic_operations.h +++ b/src/core/functions/analytic/codac2_analytic_operations.h @@ -17,19 +17,6 @@ namespace codac2 { - using ScalarExpr = AnalyticExprWrapper; - using VectorExpr = AnalyticExprWrapper; - using MatrixExpr = AnalyticExprWrapper; - - template - concept IsScalarExprOrVar = (std::is_base_of_v || std::is_base_of_v); - - template - concept IsVectorExprOrVar = (std::is_base_of_v || std::is_base_of_v); - - template - concept IsMatrixExprOrVar = (std::is_base_of_v || std::is_base_of_v); - // operator+ (unary case) inline ScalarExpr From 0c95113c414bfb7873e5c71d0ab757907badbcab Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 26 Dec 2024 12:19:00 +0100 Subject: [PATCH 042/126] [fnc] updated functions implementation --- .../analytic/codac2_py_AnalyticExprWrapper.h | 13 +- .../analytic/codac2_py_AnalyticFunction.h | 4 +- .../codac2_py_analytic_operations.cpp | 8 - src/core/CMakeLists.txt | 1 + .../functions/analytic/codac2_AnalyticExpr.h | 12 -- .../analytic/codac2_AnalyticExprWrapper.h | 22 +- .../analytic/codac2_AnalyticFunction.h | 48 ++--- .../analytic/codac2_ScalarExprList.h | 135 +++++++++++++ .../analytic/codac2_analytic_constants.h | 2 - .../analytic/codac2_analytic_operations.h | 190 ------------------ .../analytic/codac2_analytic_variables.cpp | 11 +- .../analytic/codac2_analytic_variables.h | 13 -- src/core/functions/codac2_ExprBase.h | 1 - src/core/trajectory/codac2_TrajectoryBase.h | 1 + .../trajectory/codac2_Trajectory_operator.h | 3 +- .../codac2_tests_AnalyticFunction.cpp | 64 +++++- .../analytic/codac2_tests_AnalyticFunction.py | 42 ++++ .../codac2_tests_SampledTrajectory.cpp | 23 ++- 18 files changed, 307 insertions(+), 286 deletions(-) create mode 100644 src/core/functions/analytic/codac2_ScalarExprList.h diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h b/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h index b130b3b67..c51485c88 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h @@ -30,30 +30,28 @@ inline void export_ScalarExpr(py::module& m) exported - .def(py::init()) + .def(py::init()) + .def(py::init()) .def(py::init()) + .def(py::init()) .def(py::init()) .def("__pos__", [](const ScalarExpr& e1) { return e1; }, py::is_operator()) .def(py::self + py::self) - .def("__radd__", [](const ScalarExpr& e1, const ScalarVar& e2) { return e2+e1; }, py::is_operator()) .def("__add__", [](const ScalarExpr& e1, const Interval& e2) { return e1+e2; }, py::is_operator()) .def("__radd__", [](const ScalarExpr& e1, const Interval& e2) { return e2+e1; }, py::is_operator()) .def(- py::self) .def(py::self - py::self) - .def("__sub__", [](const ScalarExpr& e1, const ScalarVar& e2) { return e1-e2; }, py::is_operator()) .def("__sub__", [](const ScalarExpr& e1, const Interval& e2) { return e1-e2; }, py::is_operator()) .def("__rsub__", [](const ScalarExpr& e1, const Interval& e2) { return e2-e1; }, py::is_operator()) .def(py::self * py::self) - .def("__mul__", [](const ScalarExpr& e1, const ScalarVar& e2) { return e1*e2; }, py::is_operator()) .def("__mul__", [](const ScalarExpr& e1, const Interval& e2) { return e1*e2; }, py::is_operator()) .def("__rmul__", [](const ScalarExpr& e1, const Interval& e2) { return e2*e1; }, py::is_operator()) .def("__mul__", [](const ScalarExpr& e1, const VectorExpr& e2) { return e1*e2; }, py::is_operator()) .def("__truediv__", [](const ScalarExpr& e1, const ScalarExpr& e2) { return e1/e2; }, py::is_operator()) - .def("__truediv__", [](const ScalarExpr& e1, const ScalarVar& e2) { return e1/e2; }, py::is_operator()) .def("__truediv__", [](const ScalarExpr& e1, const Interval& e2) { return e1/e2; }, py::is_operator()) .def("__rtruediv__", [](const ScalarExpr& e1, const Interval& e2) { return e2/e1; }, py::is_operator()) @@ -72,8 +70,9 @@ inline void export_VectorExpr(py::module& m) exported - .def(py::init()) + .def(py::init()) .def(py::init()) + .def(py::init()) .def(py::init()) .def("__getitem__", [](const VectorExpr& x, Index_type index) @@ -85,13 +84,11 @@ inline void export_VectorExpr(py::module& m) .def("__pos__", [](const VectorExpr& e1) { return e1; }, py::is_operator()) .def(py::self + py::self) - .def("__add__", [](const VectorExpr& e1, const VectorVar& e2) { return e1+e2; }, py::is_operator()) .def("__add__", [](const VectorExpr& e1, const IntervalVector& e2) { return e1+e2; }, py::is_operator()) .def("__radd__", [](const VectorExpr& e1, const IntervalVector& e2) { return e1+e2; }, py::is_operator()) .def(- py::self) .def(py::self - py::self) - .def("__sub__", [](const VectorExpr& e1, const VectorVar& e2) { return e1-e2; }, py::is_operator()) .def("__sub__", [](const VectorExpr& e1, const IntervalVector& e2) { return e1-e2; }, py::is_operator()) .def("__rsub__", [](const VectorExpr& e1, const IntervalVector& e2) { return e2-e1; }, py::is_operator()) diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index 6c776edfb..ae636ad78 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -147,10 +147,10 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) { return std::make_unique>( create_FunctionArgsList(l), - std::dynamic_pointer_cast>(expr.get()->copy()) + AnalyticExprWrapper{ std::dynamic_pointer_cast>(expr.get()->copy()) } ); } - ), ANALYTICFUNCTION_T_ANALYTICFUNCTION_CONST_FUNCTIONARGSLIST_REF_CONST_SHARED_PTR_ANALYTICEXPR_T_REF) + ), ANALYTICFUNCTION_T_ANALYTICFUNCTION_CONST_FUNCTIONARGSLIST_REF_CONST_ANALYTICEXPRWRAPPER_T_REF) ; if constexpr(std::is_same_v) diff --git a/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp b/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp index 9706af0da..29ddaf39e 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp @@ -31,14 +31,6 @@ void export_expression_operations(py::module& m) SCALAREXPR_POW_CONST_SCALAREXPR_REF_CONST_SCALAREXPR_REF, "x1"_a, "x2"_a) - .def("pow", [](const Interval& e1, const ScalarExpr& e2) { return ScalarExpr(pow(e1,e2)); }, - SCALAREXPR_POW_CONST_X1_REF_CONST_SCALAREXPR_REF, - "x1"_a, "x2"_a) - - .def("pow", [](const ScalarExpr& e1, const Interval& e2) { return ScalarExpr(pow(e1,e2)); }, - SCALAREXPR_POW_CONST_SCALAREXPR_REF_CONST_X2_REF, - "x1"_a, "x2"_a) - .def("sqr", [](const ScalarExpr& e1) { return ScalarExpr(sqr(e1)); }, SCALAREXPR_SQR_CONST_SCALAREXPR_REF, "x1"_a) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6ff50980e..feb6f0214 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -75,6 +75,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticExpr.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticExprWrapper.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticFunction.h + ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_ScalarExprList.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/set/codac2_set_operations.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/set/codac2_set_operators.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/set/codac2_set_variables.h diff --git a/src/core/functions/analytic/codac2_AnalyticExpr.h b/src/core/functions/analytic/codac2_AnalyticExpr.h index 134d62a2e..a0bd43af9 100644 --- a/src/core/functions/analytic/codac2_AnalyticExpr.h +++ b/src/core/functions/analytic/codac2_AnalyticExpr.h @@ -63,10 +63,6 @@ namespace codac2 : OperationExprBase...>(x...) { } - AnalyticOperationExpr(const AnalyticOperationExpr& e) - : OperationExprBase...>(e) - { } - std::shared_ptr copy() const { return std::make_shared>(*this); @@ -124,10 +120,6 @@ namespace codac2 : OperationExprBase>(x1), _i(i) { } - AnalyticOperationExpr(const AnalyticOperationExpr& e) - : OperationExprBase>(e), _i(e._i) - { } - std::shared_ptr copy() const { return std::make_shared>(*this); @@ -169,10 +161,6 @@ namespace codac2 : OperationExprBase>(x1), _i(i), _j(j) { } - AnalyticOperationExpr(const AnalyticOperationExpr& e) - : OperationExprBase>(e), _i(e._i), _j(e._j) - { } - std::shared_ptr copy() const { return std::make_shared>(*this); diff --git a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h index c5049a5ab..972c6be27 100644 --- a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h +++ b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h @@ -10,6 +10,7 @@ #pragma once #include "codac2_AnalyticExpr.h" +#include "codac2_analytic_constants.h" namespace codac2 { @@ -19,14 +20,25 @@ namespace codac2 AnalyticExprWrapper(const std::shared_ptr>& e) : std::shared_ptr>(e) { } - - explicit AnalyticExprWrapper(const typename T::Domain& e) + + AnalyticExprWrapper(const ScalarVar& e) + requires std::is_same_v + : std::shared_ptr>({ std::dynamic_pointer_cast>(e.copy()) }) + { } + + AnalyticExprWrapper(const VectorVar& e) + requires std::is_same_v + : std::shared_ptr>({ std::dynamic_pointer_cast>(e.copy()) }) + { } + + template + AnalyticExprWrapper(const V& e) + requires std::is_same_v::Domain,T> : std::shared_ptr>(const_value(e)) { } - - template - requires std::is_same_v + inline AnalyticExprWrapper operator[](Index i) const + requires std::is_same_v { return { std::make_shared>(*this,i) }; } diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index e98357ea6..dc796d6d3 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -17,6 +17,7 @@ #include "codac2_template_tools.h" #include "codac2_analytic_operations.h" #include "codac2_AnalyticExprWrapper.h" +#include "codac2_ScalarExprList.h" namespace codac2 { @@ -33,16 +34,6 @@ namespace codac2 inline EvalMode operator|(EvalMode a, EvalMode b) { return static_cast(static_cast(a) | static_cast(b)); } - class ScalarExprList : public AnalyticExprWrapper - { - public: - - template - ScalarExprList(const S&... y) - : AnalyticExprWrapper(vec(y...)) - { } - }; - template requires std::is_base_of_v class AnalyticFunction : public FunctionBase> @@ -64,19 +55,8 @@ namespace codac2 "Invalid argument: variable not present in input arguments"); } - AnalyticFunction(const FunctionArgsList& args, const std::shared_ptr>& y) - : FunctionBase>(args, y) - { - assert_release(y->belongs_to_args_list(this->args()) && - "Invalid argument: variable not present in input arguments"); - } - AnalyticFunction(const FunctionArgsList& args, const AnalyticVarExpr& y) - : AnalyticFunction(args, y.operator std::shared_ptr>()) - { } - - AnalyticFunction(const AnalyticFunction& f) - : FunctionBase>(f) + : AnalyticFunction(args, { std::dynamic_pointer_cast>(y.copy()) }) { } template @@ -251,7 +231,29 @@ namespace codac2 } }; - AnalyticFunction(const FunctionArgsList&, std::initializer_list>) -> + AnalyticFunction(const FunctionArgsList&, double) -> + AnalyticFunction; + + AnalyticFunction(const FunctionArgsList&, const Interval&) -> + AnalyticFunction; + + AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> + AnalyticFunction; + + AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> + AnalyticFunction; + + AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> AnalyticFunction; + AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> + AnalyticFunction; + + AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> + AnalyticFunction; + + template + AnalyticFunction(const FunctionArgsList&, const T&) -> + AnalyticFunction::Domain>; + } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_ScalarExprList.h b/src/core/functions/analytic/codac2_ScalarExprList.h new file mode 100644 index 000000000..7ac1f6301 --- /dev/null +++ b/src/core/functions/analytic/codac2_ScalarExprList.h @@ -0,0 +1,135 @@ +/** + * \file codac2_ScalarExprList.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_AnalyticExprWrapper.h" + +namespace codac2 +{ + // Template parameter packs cannot be used for ScalarExprList because arguments are + // provided by std::initializer_list (see template deduction guides for AnalyticFunction) + + template + concept IsScalar = std::is_same_v || std::is_same_v || + std::is_same_v::Domain,ScalarOpValue>; + + struct ScalarExprList : public AnalyticExprWrapper + { + template + requires IsScalar + ScalarExprList(const S1& y1) + : AnalyticExprWrapper(vec(to_ScalarExpr(y1))) + { } + + template + requires IsScalar && IsScalar + ScalarExprList(const S1& y1, const S2& y2) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1),to_ScalarExpr(y2) + )) + { } + + template + requires IsScalar && IsScalar && IsScalar + ScalarExprList(const S1& y1, const S2& y2, const S3& y3) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3) + )) + { } + + template + requires IsScalar && IsScalar && IsScalar && IsScalar + ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4) + )) + { } + + template + requires IsScalar && IsScalar && IsScalar && IsScalar && IsScalar + ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5) + )) + { } + + template + requires IsScalar && IsScalar && IsScalar && IsScalar && IsScalar + && IsScalar + ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, + const S6& y6) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), + to_ScalarExpr(y6) + )) + { } + + template + requires IsScalar && IsScalar && IsScalar && IsScalar && IsScalar + && IsScalar && IsScalar + ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, + const S6& y6, const S7& y7) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), + to_ScalarExpr(y6), to_ScalarExpr(y7) + )) + { } + + template + requires IsScalar && IsScalar && IsScalar && IsScalar && IsScalar + && IsScalar && IsScalar && IsScalar + ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, + const S6& y6, const S7& y7, const S8& y8) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), + to_ScalarExpr(y6), to_ScalarExpr(y7), to_ScalarExpr(y8) + )) + { } + + template + requires IsScalar && IsScalar && IsScalar && IsScalar && IsScalar + && IsScalar && IsScalar && IsScalar && IsScalar + ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, + const S6& y6, const S7& y7, const S8& y8, const S9& y9) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), + to_ScalarExpr(y6), to_ScalarExpr(y7), to_ScalarExpr(y8), to_ScalarExpr(y9) + )) + { } + + template + requires IsScalar && IsScalar && IsScalar && IsScalar && IsScalar + && IsScalar && IsScalar && IsScalar && IsScalar && IsScalar + ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, + const S6& y6, const S7& y7, const S8& y8, const S9& y9, const S10& y10) + : AnalyticExprWrapper(vec( + to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), + to_ScalarExpr(y6), to_ScalarExpr(y7), to_ScalarExpr(y8), to_ScalarExpr(y9), to_ScalarExpr(y10) + )) + { } + + const ScalarExpr& to_ScalarExpr(const ScalarExpr& e) + { + return e; + } + + template + requires std::is_same_v::Domain,ScalarOpValue> + ScalarExpr to_ScalarExpr(const T& e) + { + return const_value(e); + } + }; +} \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_constants.h b/src/core/functions/analytic/codac2_analytic_constants.h index 66d8ded10..72cd7f1ec 100644 --- a/src/core/functions/analytic/codac2_analytic_constants.h +++ b/src/core/functions/analytic/codac2_analytic_constants.h @@ -22,8 +22,6 @@ namespace codac2 : _x(x) { } - ConstValueExpr(const ConstValueExpr& e) = default; - std::shared_ptr copy() const { return std::make_shared>(*this); diff --git a/src/core/functions/analytic/codac2_analytic_operations.h b/src/core/functions/analytic/codac2_analytic_operations.h index a8aac1625..0b2778600 100644 --- a/src/core/functions/analytic/codac2_analytic_operations.h +++ b/src/core/functions/analytic/codac2_analytic_operations.h @@ -45,66 +45,18 @@ namespace codac2 return { std::make_shared>(x1,x2) }; } - template - requires (!IsScalarExprOrVar) - inline ScalarExpr - operator+(const X1& x1, ScalarExpr x2) - { - return operator+(const_value(x1),x2); - } - - template - requires (!IsScalarExprOrVar) - inline ScalarExpr - operator+(ScalarExpr x1, const X2& x2) - { - return operator+(x1, const_value(x2)); - } - inline VectorExpr operator+(VectorExpr x1, VectorExpr x2) { return { std::make_shared>(x1,x2) }; } - template - requires (!IsVectorExprOrVar) - inline VectorExpr - operator+(const X1& x1, VectorExpr x2) - { - return operator+(const_value(x1),x2); - } - - template - requires (!IsVectorExprOrVar) - inline VectorExpr - operator+(VectorExpr x1, const X2& x2) - { - return operator+(x1, const_value(x2)); - } - inline MatrixExpr operator+(MatrixExpr x1, MatrixExpr x2) { return { std::make_shared>(x1,x2) }; } - template - requires (!IsMatrixExprOrVar) - inline MatrixExpr - operator+(const X1& x1, MatrixExpr x2) - { - return operator+(const_value(x1),x2); - } - - template - requires (!IsMatrixExprOrVar) - inline MatrixExpr - operator+(MatrixExpr x1, const X2& x2) - { - return operator+(x1, const_value(x2)); - } - // operator- (unary case) inline ScalarExpr @@ -133,66 +85,18 @@ namespace codac2 return { std::make_shared>(x1,x2) }; } - template - requires (!IsScalarExprOrVar) - inline ScalarExpr - operator-(const X1& x1, const ScalarExpr& x2) - { - return operator-(const_value(x1),x2); - } - - template - requires (!IsScalarExprOrVar) - inline ScalarExpr - operator-(const ScalarExpr& x1, const X2& x2) - { - return operator-(x1, const_value(x2)); - } - inline VectorExpr operator-(const VectorExpr& x1, const VectorExpr& x2) { return { std::make_shared>(x1,x2) }; } - template - requires (!IsVectorExprOrVar) - inline VectorExpr - operator-(const X1& x1, const VectorExpr& x2) - { - return operator-(const_value(x1),x2); - } - - template - requires (!IsVectorExprOrVar) - inline VectorExpr - operator-(const VectorExpr& x1, const X2& x2) - { - return operator-(x1, const_value(x2)); - } - inline MatrixExpr operator-(const MatrixExpr& x1, const MatrixExpr& x2) { return { std::make_shared>(x1,x2) }; } - template - requires (!IsMatrixExprOrVar) - inline MatrixExpr - operator-(const X1& x1, const MatrixExpr& x2) - { - return operator-(const_value(x1),x2); - } - - template - requires (!IsMatrixExprOrVar) - inline MatrixExpr - operator-(const MatrixExpr& x1, const X2& x2) - { - return operator-(x1, const_value(x2)); - } - // operator* inline ScalarExpr @@ -213,60 +117,12 @@ namespace codac2 return { std::make_shared>(x1,x2) }; } - inline ScalarExpr - operator*(const Interval& x1, const ScalarExpr& x2) - { - return operator*(const_value(x1),x2); - } - - inline ScalarExpr - operator*(const ScalarExpr& x1, const Interval& x2) - { - return operator*(x1,const_value(x2)); - } - - inline VectorExpr - operator*(const Interval& x1, const VectorExpr& x2) - { - return operator*(const_value(x1),x2); - } - - inline VectorExpr - operator*(const VectorExpr& x1, const Interval& x2) - { - return operator*(x1,const_value(x2)); - } - - inline VectorExpr - operator*(const ScalarExpr& x1, const IntervalVector& x2) - { - return operator*(x1,const_value(x2)); - } - - inline VectorExpr - operator*(const IntervalVector& x1, const ScalarExpr& x2) - { - return operator*(const_value(x1),x2); - } - inline VectorExpr operator*(const MatrixExpr& x1, const VectorExpr& x2) { return { std::make_shared>(x1,x2) }; } - inline VectorExpr - operator*(const MatrixExpr& x1, const IntervalVector& x2) - { - return { std::make_shared>(x1,const_value(x2)) }; - } - - inline VectorExpr - operator*(const IntervalMatrix& x1, const VectorExpr& x2) - { - return { std::make_shared>(const_value(x1),x2) }; - } - // operator/ inline ScalarExpr @@ -274,22 +130,6 @@ namespace codac2 { return { std::make_shared>(x1,x2) }; } - - template - requires (!IsScalarExprOrVar) - inline ScalarExpr - operator/(const X1& x1, const ScalarExpr& x2) - { - return operator/(const_value(x1),x2); - } - - template - requires (!IsScalarExprOrVar) - inline ScalarExpr - operator/(const ScalarExpr& x1, const X2& x2) - { - return operator/(x1, const_value(x2)); - } inline VectorExpr operator/(const VectorExpr& x1, const ScalarExpr& x2) @@ -297,14 +137,6 @@ namespace codac2 return { std::make_shared>(x1,x2) }; } - template - requires (!IsScalarExprOrVar) - inline VectorExpr - operator/(const VectorExpr& x1, const X2& x2) - { - return operator/(x1, const_value(x2)); - } - // Other operators inline ScalarExpr @@ -313,22 +145,6 @@ namespace codac2 return { std::make_shared>(x1,x2) }; } - template - requires (!IsScalarExprOrVar) - inline ScalarExpr - pow(const X1& x1, const ScalarExpr& x2) - { - return pow(const_value(x1),x2); - } - - template - requires (!IsScalarExprOrVar) - inline ScalarExpr - pow(const ScalarExpr& x1, const X2& x2) - { - return pow(x1,const_value(x2)); - } - inline ScalarExpr sqr(const ScalarExpr& x1) { @@ -543,12 +359,6 @@ namespace codac2 return { std::make_shared>(x...) }; } - inline ScalarExpr - ind(Index i, const VectorExpr& x1) - { - return { std::make_shared>(x1,i) }; - } - template inline MatrixExpr mat(const std::shared_ptr>&... x) diff --git a/src/core/functions/analytic/codac2_analytic_variables.cpp b/src/core/functions/analytic/codac2_analytic_variables.cpp index 1495e9e96..cdce629c2 100644 --- a/src/core/functions/analytic/codac2_analytic_variables.cpp +++ b/src/core/functions/analytic/codac2_analytic_variables.cpp @@ -19,10 +19,6 @@ using namespace codac2; ScalarVar::ScalarVar() { } - ScalarVar::ScalarVar(const ScalarVar& x) - : AnalyticVarExpr(x) - { } - std::shared_ptr ScalarVar::arg_copy() const { return std::make_shared(*this); @@ -40,7 +36,8 @@ using namespace codac2; AnalyticExprWrapper ScalarVar::operator-() const { - return { std::make_shared>(*this) }; + return { std::make_shared>( + std::dynamic_pointer_cast>(this->copy())) }; } @@ -52,10 +49,6 @@ using namespace codac2; assert_release(n > 0); } - VectorVar::VectorVar(const VectorVar& x) - : AnalyticVarExpr(x), _n(x._n) - { } - std::shared_ptr VectorVar::arg_copy() const { return std::make_shared(*this); diff --git a/src/core/functions/analytic/codac2_analytic_variables.h b/src/core/functions/analytic/codac2_analytic_variables.h index aa4bce1d4..8ac4441f8 100644 --- a/src/core/functions/analytic/codac2_analytic_variables.h +++ b/src/core/functions/analytic/codac2_analytic_variables.h @@ -41,17 +41,6 @@ namespace codac2 void replace_expr([[maybe_unused]] const ExprID& old_expr_id, [[maybe_unused]] const std::shared_ptr& new_expr) { } - - // to remove - operator std::shared_ptr>() const - { - return std::dynamic_pointer_cast>(this->copy()); - } - - operator AnalyticExprWrapper() const - { - return { std::dynamic_pointer_cast>(this->copy()) }; - } virtual bool belongs_to_args_list(const FunctionArgsList& args) const { @@ -67,7 +56,6 @@ namespace codac2 public: ScalarVar(); - ScalarVar(const ScalarVar& x); std::shared_ptr arg_copy() const; std::shared_ptr copy() const; @@ -81,7 +69,6 @@ namespace codac2 public: explicit VectorVar(Index n); - VectorVar(const VectorVar& x); std::shared_ptr arg_copy() const; std::shared_ptr copy() const; diff --git a/src/core/functions/codac2_ExprBase.h b/src/core/functions/codac2_ExprBase.h index 8ae3045d1..47394eaa8 100644 --- a/src/core/functions/codac2_ExprBase.h +++ b/src/core/functions/codac2_ExprBase.h @@ -25,7 +25,6 @@ namespace codac2 public: ExprID(); - ExprID(const ExprID& i) = default; Index id() const; bool operator==(const ExprID& i) const; bool operator<(const ExprID& i) const; diff --git a/src/core/trajectory/codac2_TrajectoryBase.h b/src/core/trajectory/codac2_TrajectoryBase.h index a7f766cc9..84d7b98f1 100644 --- a/src/core/trajectory/codac2_TrajectoryBase.h +++ b/src/core/trajectory/codac2_TrajectoryBase.h @@ -84,6 +84,7 @@ namespace codac2 return p; } + // Implementation in codac2_Trajectory_operator.h AnalyticFunction::Domain> as_function() const; }; } \ No newline at end of file diff --git a/src/core/trajectory/codac2_Trajectory_operator.h b/src/core/trajectory/codac2_Trajectory_operator.h index 58ce6fe10..1806f2e5d 100644 --- a/src/core/trajectory/codac2_Trajectory_operator.h +++ b/src/core/trajectory/codac2_Trajectory_operator.h @@ -11,6 +11,7 @@ #include "codac2_analytic_operations.h" #include "codac2_SampledTrajectory.h" +#include "codac2_AnalyticExprWrapper.h" namespace codac2 { @@ -52,7 +53,7 @@ namespace codac2 using O = typename ArgWrapper::Domain; - AnalyticOperationExpr(const TrajectoryBase& x1, const std::shared_ptr>& x2) + AnalyticOperationExpr(const TrajectoryBase& x1, const ScalarExpr& x2) : OperationExprBase>(x2), _x1(x1) { } diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp index 8fabf900b..47abb017d 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp @@ -75,12 +75,11 @@ TEST_CASE("AnalyticFunction") } { - // todo: remove call to "const_value" method - CHECK(AnalyticFunction({}, const_value(+Interval(4,5))).eval(m) == Interval(4,5)); - CHECK(AnalyticFunction({}, const_value(+4)).eval(m) == 4); - CHECK(AnalyticFunction({}, const_value(+4.)).eval(m) == 4.); - CHECK(AnalyticFunction({}, const_value(Vector({2,9}))).eval(m) == Vector({2,9})); - CHECK(AnalyticFunction({}, const_value(IntervalVector(3))).eval(m) == IntervalVector({{-oo,oo},{-oo,oo},{-oo,oo}})); + CHECK(AnalyticFunction({}, +Interval(4,5)).eval(m) == Interval(4,5)); + CHECK(AnalyticFunction({}, +4).eval(m) == 4); + CHECK(AnalyticFunction({}, +4.).eval(m) == 4.); + CHECK(AnalyticFunction({}, Vector({2,9})).eval(m) == Vector({2,9})); + CHECK(AnalyticFunction({}, IntervalVector(3)).eval(m) == IntervalVector({{-oo,oo},{-oo,oo},{-oo,oo}})); ScalarVar x1; ScalarVar x2; @@ -261,6 +260,59 @@ TEST_CASE("AnalyticFunction") CHECK(f.eval(Interval(-1,1)) == Interval(0)); } + { + // Scalar outputs + { + AnalyticFunction f1({}, (int)3); + CHECK(f1.eval() == Interval(3)); + + AnalyticFunction f2({}, (double)3.); + CHECK(f2.eval() == Interval(3)); + + AnalyticFunction f3({}, Interval(3.)); + CHECK(f3.eval() == Interval(3)); + + ScalarVar x; + AnalyticFunction f4({x}, x*x); + CHECK(f4.eval(2.) == Interval(4)); + } + + // Vectorial outputs + { + AnalyticFunction f1({}, { (int)3 }); + CHECK(f1.eval() == IntervalVector({3})); + + AnalyticFunction f2({}, { (double)3. }); + CHECK(f2.eval() == IntervalVector({3})); + + AnalyticFunction f3({}, { Interval(3.) }); + CHECK(f3.eval() == IntervalVector({3})); + + ScalarVar x; + AnalyticFunction f4({x}, { x*x }); + CHECK(f4.eval(2.) == IntervalVector({4})); + + AnalyticFunction f_2args({x}, { x*x,x*x }); + CHECK(f_2args.eval(1.) == IntervalVector::constant(2,{1})); + AnalyticFunction f_3args({x}, { x,x*x,1 }); + CHECK(f_3args.eval(1.) == IntervalVector::constant(3,{1})); + AnalyticFunction f_4args({x}, { x,x*x,1,x }); + CHECK(f_4args.eval(1.) == IntervalVector::constant(4,{1})); + AnalyticFunction f_5args({x}, { x,x*x,1,x,x }); + CHECK(f_5args.eval(1.) == IntervalVector::constant(5,{1})); + AnalyticFunction f_6args({x}, { x,x*x,1,x,x,1*x }); + CHECK(f_6args.eval(1.) == IntervalVector::constant(6,{1})); + AnalyticFunction f_7args({x}, { x,x*x,1,x,x,1*x,x*x }); + CHECK(f_7args.eval(1.) == IntervalVector::constant(7,{1})); + AnalyticFunction f_8args({x}, { x,x*x,1,x,x,1*x,x*x,1 }); + CHECK(f_8args.eval(1.) == IntervalVector::constant(8,{1})); + AnalyticFunction f_9args({x}, { x,x*x,1,x,x,1*x,x*x,1,x }); + CHECK(f_9args.eval(1.) == IntervalVector::constant(9,{1})); + AnalyticFunction f_10args({x}, { x,x*x,1,x,x,1*x,x*x,1,x,1*x }); + CHECK(f_10args.eval(1.) == IntervalVector::constant(10,{1})); + } + } + // Subvector on variables { VectorVar p(2); diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py index 92e429740..ce53c67e1 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.py @@ -236,6 +236,48 @@ def test_eval(f,*args): self.assertTrue(f.eval(EvalMode.CENTERED,Interval(-1,1)) == Interval(0)) self.assertTrue(f.eval(Interval(-1,1)) == Interval(0)) + # Scalar outputs + f1 = AnalyticFunction([], 3) + self.assertTrue(f1.eval() == Interval(3)) + f2 = AnalyticFunction([], 3.) + self.assertTrue(f2.eval() == Interval(3)) + f3 = AnalyticFunction([], Interval(3.)) + self.assertTrue(f3.eval() == Interval(3)) + x = ScalarVar() + f4 = AnalyticFunction([x], x*x) + self.assertTrue(f4.eval(2.) == Interval(4)) + + # Vectorial outputs + + f1 = AnalyticFunction([], [ 3 ]) + self.assertTrue(f1.eval() == IntervalVector([3])) + f2 = AnalyticFunction([], [ 3. ]) + self.assertTrue(f2.eval() == IntervalVector([3])) + f3 = AnalyticFunction([], [ Interval(3.) ]) + self.assertTrue(f3.eval() == IntervalVector([3])) + x = ScalarVar() + f4 = AnalyticFunction([x], [ x*x ]) + self.assertTrue(f4.eval(2.) == IntervalVector([4])) + + f_2args = AnalyticFunction([x], [ x*x,x*x ]) + self.assertTrue(f_2args.eval(1.) == IntervalVector.constant(2,[1])) + f_3args = AnalyticFunction([x], [ x,x*x,1 ]) + self.assertTrue(f_3args.eval(1.) == IntervalVector.constant(3,[1])) + f_4args = AnalyticFunction([x], [ x,x*x,1,x ]) + self.assertTrue(f_4args.eval(1.) == IntervalVector.constant(4,[1])) + f_5args = AnalyticFunction([x], [ x,x*x,1,x,x ]) + self.assertTrue(f_5args.eval(1.) == IntervalVector.constant(5,[1])) + f_6args = AnalyticFunction([x], [ x,x*x,1,x,x,1*x ]) + self.assertTrue(f_6args.eval(1.) == IntervalVector.constant(6,[1])) + f_7args = AnalyticFunction([x], [ x,x*x,1,x,x,1*x,x*x ]) + self.assertTrue(f_7args.eval(1.) == IntervalVector.constant(7,[1])) + f_8args = AnalyticFunction([x], [ x,x*x,1,x,x,1*x,x*x,1 ]) + self.assertTrue(f_8args.eval(1.) == IntervalVector.constant(8,[1])) + f_9args = AnalyticFunction([x], [ x,x*x,1,x,x,1*x,x*x,1,x ]) + self.assertTrue(f_9args.eval(1.) == IntervalVector.constant(9,[1])) + f_10args = AnalyticFunction([x], [ x,x*x,1,x,x,1*x,x*x,1,x,1*x ]) + self.assertTrue(f_10args.eval(1.) == IntervalVector.constant(10,[1])) + # Subvector on variables p = VectorVar(2) x = VectorVar(4) diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp index 7fdbb1477..ab2695cb9 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp @@ -88,11 +88,22 @@ TEST_CASE("SampledTrajectory as operator (nd case)") auto sampled_traj = analytic_traj.sampled(1e-2); auto g = sampled_traj.as_function(); - AnalyticFunction h { - {t}, - vec(1.*ind(0,g(t)),1.*ind(1,g(t))) - }; + { + AnalyticFunction h { + {t}, + g(t) + }; + + for(double t = 0 ; t < 5 ; t+=1e-2) + CHECK(Approx(h.real_eval(t)) == Vector({2*cos(t),sin(2*t)})); + } + { + AnalyticFunction h { + {t}, + { g(t)[0],g(t)[1] } + }; - for(double t = 0 ; t < 5 ; t+=1e-2) - CHECK(Approx(h.real_eval(t)) == Vector({2*cos(t),sin(2*t)})); + for(double t = 0 ; t < 5 ; t+=1e-2) + CHECK(Approx(h.real_eval(t)) == Vector({2*cos(t),sin(2*t)})); + } } \ No newline at end of file From 656aea97803eced78c240c1806867687d4c31efa Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 26 Dec 2024 15:54:35 +0100 Subject: [PATCH 043/126] [fnc] renaming types --- python/src/core/codac2_py_core.cpp | 18 +-- .../core/contractors/codac2_py_CtcInverse.h | 21 +-- .../contractors/codac2_py_CtcInverseNotIn.h | 17 +-- .../analytic/codac2_py_AnalyticExprWrapper.h | 2 +- .../analytic/codac2_py_AnalyticFunction.h | 12 +- .../analytic/codac2_py_analytic_variables.cpp | 10 +- python/src/core/paver/codac2_py_pave.cpp | 4 +- .../core/separators/codac2_py_SepInverse.h | 15 ++- .../separators/codac2_py_SepTransform.cpp | 4 +- .../codac2_py_AnalyticTrajectory.cpp | 4 +- .../trajectory/codac2_py_TrajectoryBase.h | 2 +- .../graphics/figures/codac2_py_Figure2D.cpp | 16 +-- src/core/CMakeLists.txt | 3 +- src/core/contractors/codac2_CtcInverse.h | 12 +- src/core/contractors/codac2_CtcInverseNotIn.h | 4 +- src/core/contractors/codac2_directed_ctc.cpp | 82 ++++++------ src/core/contractors/codac2_directed_ctc.h | 90 ++++++------- src/core/domains/codac2_Wrapper.h | 1 - .../functions/analytic/codac2_AnalyticExpr.h | 34 ++--- .../analytic/codac2_AnalyticExprWrapper.h | 27 ++-- .../analytic/codac2_AnalyticFunction.h | 36 +++--- .../functions/analytic/codac2_AnalyticType.h | 54 ++++++++ .../analytic/codac2_ScalarExprList.h | 26 ++-- .../functions/analytic/codac2_ValueType.h | 64 +++++++++ .../analytic/codac2_analytic_constants.h | 6 +- .../analytic/codac2_analytic_operations.h | 122 +++++++++--------- .../analytic/codac2_analytic_values.h | 98 -------------- .../analytic/codac2_analytic_variables.cpp | 18 +-- .../analytic/codac2_analytic_variables.h | 10 +- src/core/functions/set/codac2_SetExpr.h | 4 +- .../functions/set/codac2_set_operations.h | 4 +- src/core/functions/set/codac2_set_operators.h | 4 +- src/core/separators/codac2_SepInverse.h | 4 +- src/core/separators/codac2_SepTransform.h | 4 +- .../trajectory/codac2_SampledTrajectory.h | 2 +- src/core/trajectory/codac2_TrajectoryBase.h | 7 +- .../trajectory/codac2_Trajectory_operator.h | 36 +++--- src/graphics/figures/codac2_Figure2D.cpp | 2 +- src/graphics/figures/codac2_Figure2D.h | 4 +- 39 files changed, 457 insertions(+), 426 deletions(-) create mode 100644 src/core/functions/analytic/codac2_AnalyticType.h create mode 100644 src/core/functions/analytic/codac2_ValueType.h delete mode 100644 src/core/functions/analytic/codac2_analytic_values.h diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index 0ec5f4fd1..977560bbc 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include "codac2_py_AnalyticFunction.h" @@ -139,10 +139,10 @@ PYBIND11_MODULE(_core, m) export_CtcIdentity(m, py_ctc_iv); export_CtcInnerOuter(m, py_ctc_iv); export_CtcInter(m, py_ctc_iv); - export_CtcInverse(m,"CtcInverse_Interval",py_ctc_iv); - export_CtcInverse(m,"CtcInverse_IntervalVector",py_ctc_iv); - export_CtcInverseNotIn(m,"CtcInverseNotIn_Interval",py_ctc_iv); - export_CtcInverseNotIn(m,"CtcInverseNotIn_IntervalVector",py_ctc_iv); + export_CtcInverse(m,"CtcInverse_Interval",py_ctc_iv); + export_CtcInverse(m,"CtcInverse_IntervalVector",py_ctc_iv); + export_CtcInverseNotIn(m,"CtcInverseNotIn_Interval",py_ctc_iv); + export_CtcInverseNotIn(m,"CtcInverseNotIn_IntervalVector",py_ctc_iv); export_CtcLazy(m, py_ctc_iv); export_CtcNot(m, py_ctc_iv); export_CtcPolar(m, py_ctc_iv); @@ -193,8 +193,8 @@ PYBIND11_MODULE(_core, m) export_ScalarExpr(m); export_VectorExpr(m); - export_AnalyticFunction(m,"AnalyticFunction_Scalar"); - export_AnalyticFunction(m,"AnalyticFunction_Vector"); + export_AnalyticFunction(m,"AnalyticFunction_Scalar"); + export_AnalyticFunction(m,"AnalyticFunction_Vector"); export_ScalarVar(m); export_VectorVar(m); export_expression_operations(m); @@ -214,8 +214,8 @@ PYBIND11_MODULE(_core, m) export_SepCtcBoundary(m,py_sep); export_SepCtcPair(m,py_sep); export_SepInter(m,py_sep); - export_SepInverse(m,"SepInverse_Interval",py_sep); - export_SepInverse(m,"SepInverse_IntervalVector",py_sep); + export_SepInverse(m,"SepInverse_Interval",py_sep); + export_SepInverse(m,"SepInverse_IntervalVector",py_sep); export_SepNot(m,py_sep); export_SepPolygon(m,py_sep); export_SepProj(m,py_sep); diff --git a/python/src/core/contractors/codac2_py_CtcInverse.h b/python/src/core/contractors/codac2_py_CtcInverse.h index c88ab18d4..02b6942e7 100644 --- a/python/src/core/contractors/codac2_py_CtcInverse.h +++ b/python/src/core/contractors/codac2_py_CtcInverse.h @@ -19,31 +19,32 @@ using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -template +template void export_CtcInverse(py::module& m, const std::string& export_name, py::class_,pyCtcIntervalVector>& pyctc) { - py::class_> exported(m, export_name.c_str(), pyctc, CTCINVERSE_MAIN); + using D = typename T::Domain; + py::class_> exported(m, export_name.c_str(), pyctc, CTCINVERSE_MAIN); exported - .def(py::init>&, const T&, bool>(), + .def(py::init&, const D&, bool>(), "f"_a, "y"_a, "with_centered_form"_a = true, - CTCINVERSE_Y_CTCINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_ARGWRAPPER_Y_DOMAIN_REF_CONST_Y_REF_BOOL_BOOL); + CTCINVERSE_Y_CTCINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CONST_Y_REF_BOOL_BOOL); - if constexpr(std::is_same_v) // separators only associated with interval vectors + if constexpr(std::is_same_v) // separators only associated with interval vectors { exported - .def(py::init>&, const pyCtcIntervalVector&, bool>(), + .def(py::init&, const pyCtcIntervalVector&, bool>(), "f"_a, "c"_a, "with_centered_form"_a = true, - CTCINVERSE_Y_CTCINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_ARGWRAPPER_Y_DOMAIN_REF_CONST_C_REF_BOOL_BOOL); + CTCINVERSE_Y_CTCINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CONST_C_REF_BOOL_BOOL); } exported - .def(CONTRACT_BOX_METHOD(CtcInverse_, + .def(CONTRACT_BOX_METHOD(CtcInverse_, VOID_CTCINVERSE_Y_CONTRACT_X_REF_VARIADIC_CONST)) - .def("function", &CtcInverse_::function, - CONST_ANALYTICFUNCTION_TYPENAME_ARGWRAPPER_Y_DOMAIN_REF_CTCINVERSE_Y_FUNCTION_CONST) + .def("function", &CtcInverse_::function, + CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CTCINVERSE_Y_FUNCTION_CONST) ; } \ No newline at end of file diff --git a/python/src/core/contractors/codac2_py_CtcInverseNotIn.h b/python/src/core/contractors/codac2_py_CtcInverseNotIn.h index 3c4831738..8b5e761cf 100644 --- a/python/src/core/contractors/codac2_py_CtcInverseNotIn.h +++ b/python/src/core/contractors/codac2_py_CtcInverseNotIn.h @@ -19,27 +19,28 @@ using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -template +template void export_CtcInverseNotIn(py::module& m, const std::string& export_name, py::class_,pyCtcIntervalVector>& pyctc) { - py::class_> exported(m, export_name.c_str(), pyctc, CTCINVERSE_MAIN); + using D = typename T::Domain; + py::class_> exported(m, export_name.c_str(), pyctc, CTCINVERSE_MAIN); exported - .def(py::init>&, const T&, bool>(), + .def(py::init&, const D&, bool>(), "f"_a, "y"_a, "with_centered_form"_a = true, - CTCINVERSENOTIN_YX_CTCINVERSENOTIN_CONST_ANALYTICFUNCTION_TYPENAME_ARGWRAPPER_Y_DOMAIN_REF_CONST_Y_REF_BOOL); + CTCINVERSENOTIN_YX_CTCINVERSENOTIN_CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CONST_Y_REF_BOOL); - if constexpr(std::is_same_v) // separators only associated with interval vectors + if constexpr(std::is_same_v) // separators only associated with interval vectors { exported - .def(py::init>&, const pyCtcIntervalVector&, bool>(), + .def(py::init&, const pyCtcIntervalVector&, bool>(), "f"_a, "c"_a, "with_centered_form"_a = true, - CTCINVERSENOTIN_YX_CTCINVERSENOTIN_CONST_ANALYTICFUNCTION_TYPENAME_ARGWRAPPER_Y_DOMAIN_REF_CONST_C_REF_BOOL); + CTCINVERSENOTIN_YX_CTCINVERSENOTIN_CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CONST_C_REF_BOOL); } exported - .def(CONTRACT_BOX_METHOD(CtcInverseNotIn, + .def(CONTRACT_BOX_METHOD(CtcInverseNotIn, VOID_CTCINVERSENOTIN_YX_CONTRACT_X_REF_CONST)) ; diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h b/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h index c51485c88..291bb6180 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticExprWrapper.h @@ -80,7 +80,7 @@ inline void export_VectorExpr(py::module& m) matlab::test_integer(index); return x[matlab::input_index(index)]; }, py::return_value_policy::reference_internal, - ANALYTICEXPRWRAPPER_SCALAROPVALUE_ANALYTICEXPRWRAPPER_T_OPERATORCOMPO_INDEX_CONST) + ANALYTICEXPRWRAPPER_SCALARTYPE_ANALYTICEXPRWRAPPER_T_OPERATORCOMPO_INDEX_CONST) .def("__pos__", [](const VectorExpr& e1) { return e1; }, py::is_operator()) .def(py::self + py::self) diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index ae636ad78..8df9ce3ff 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -90,7 +90,7 @@ using namespace pybind11::literals; ; \ -AnalyticExprWrapper pyobj_to_ScalarExpr(const py::object& obj) +AnalyticExprWrapper pyobj_to_ScalarExpr(const py::object& obj) { if(py::isinstance(obj)) return obj.cast(); @@ -102,11 +102,11 @@ std::shared_ptr pyobj_to_ExprBase(const py::object& obj) { if(obj) { - if(py::isinstance>(obj)) - return obj.cast>()->copy(); + if(py::isinstance>(obj)) + return obj.cast>()->copy(); - else if(py::isinstance>(obj)) - return obj.cast>()->copy(); + else if(py::isinstance>(obj)) + return obj.cast>()->copy(); } assert_release("invalid expression"); @@ -153,7 +153,7 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) ), ANALYTICFUNCTION_T_ANALYTICFUNCTION_CONST_FUNCTIONARGSLIST_REF_CONST_ANALYTICEXPRWRAPPER_T_REF) ; - if constexpr(std::is_same_v) + if constexpr(std::is_same_v) { exported.def(py::init( [](const std::vector& l, const std::vector& v_expr) diff --git a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp index 08f15fa42..d397409f1 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp @@ -68,7 +68,7 @@ ScalarExpr get_item(const VectorVar& v, Index_type i) if(i < 0 || i >= static_cast(v.size())) throw py::index_error("index is out of range"); - return ScalarExpr(std::dynamic_pointer_cast>(v[static_cast(i)]->copy())); + return ScalarExpr(std::dynamic_pointer_cast>(v[static_cast(i)]->copy())); } void export_VectorVar(py::module& m) @@ -94,22 +94,22 @@ void export_VectorVar(py::module& m) exported.def("__call__", [](const VectorVar& v, Index_type i) -> ScalarExpr { return get_item(v, i); - }, ANALYTICEXPRWRAPPER_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); + }, ANALYTICEXPRWRAPPER_SCALARTYPE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); else exported.def("__getitem__", [](const VectorVar& v, Index_type i) -> ScalarExpr { return get_item(v, i); - }, ANALYTICEXPRWRAPPER_SCALAROPVALUE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); + }, ANALYTICEXPRWRAPPER_SCALARTYPE_VECTORVAR_OPERATORCOMPO_INDEX_CONST); exported .def("subvector", [](const VectorVar& v, Index_type i, Index_type j) -> VectorExpr { matlab::test_integer(i, j); - return VectorExpr(std::dynamic_pointer_cast>( + return VectorExpr(std::dynamic_pointer_cast>( v.subvector(matlab::input_index(i),matlab::input_index(j))->copy())); - }, ANALYTICEXPRWRAPPER_VECTOROPVALUE_VECTORVAR_SUBVECTOR_INDEX_INDEX_CONST) + }, ANALYTICEXPRWRAPPER_VECTORTYPE_VECTORVAR_SUBVECTOR_INDEX_INDEX_CONST) .def("__pos__", [](const VectorVar& e1) { return VectorExpr(VectorExpr(e1)); }, py::is_operator()) .def("__add__", [](const VectorVar& e1, const VectorVar& e2) { return VectorExpr(VectorExpr(e1) + VectorExpr(e2)); }, py::is_operator()) diff --git a/python/src/core/paver/codac2_py_pave.cpp b/python/src/core/paver/codac2_py_pave.cpp index 2554b65dc..685f1b9bf 100644 --- a/python/src/core/paver/codac2_py_pave.cpp +++ b/python/src/core/paver/codac2_py_pave.cpp @@ -28,11 +28,11 @@ void export_pave(py::module& m) PAVINGINOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_SEPBASE_REF_DOUBLE, "x"_a, "s"_a, "eps"_a); - m.def("sivia_", (PavingInOut (*)(const IntervalVector&,const AnalyticFunction&,const Interval&,double))&codac2::sivia, + m.def("sivia_", (PavingInOut (*)(const IntervalVector&,const AnalyticFunction&,const Interval&,double))&codac2::sivia, PAVINGINOUT_SIVIA_CONST_INTERVALVECTOR_REF_CONST_ANALYTICFUNCTION_Y_REF_CONST_TYPENAME_Y_DOMAIN_REF_DOUBLE, "x"_a, "f"_a, "y"_a, "eps"_a); - m.def("sivia_", (PavingInOut (*)(const IntervalVector&,const AnalyticFunction&,const IntervalVector&,double))&codac2::sivia, + m.def("sivia_", (PavingInOut (*)(const IntervalVector&,const AnalyticFunction&,const IntervalVector&,double))&codac2::sivia, PAVINGINOUT_SIVIA_CONST_INTERVALVECTOR_REF_CONST_ANALYTICFUNCTION_Y_REF_CONST_TYPENAME_Y_DOMAIN_REF_DOUBLE, "x"_a, "f"_a, "y"_a, "eps"_a); } \ No newline at end of file diff --git a/python/src/core/separators/codac2_py_SepInverse.h b/python/src/core/separators/codac2_py_SepInverse.h index bf8bcdc0e..d6fcca5e4 100644 --- a/python/src/core/separators/codac2_py_SepInverse.h +++ b/python/src/core/separators/codac2_py_SepInverse.h @@ -21,27 +21,28 @@ using namespace codac2; namespace py = pybind11; using namespace pybind11::literals; -template +template void export_SepInverse(py::module& m, const std::string& export_name, py::class_& pysep) { - py::class_> exported(m, export_name.c_str(), pysep, SEPINVERSE_MAIN); + using D = typename T::Domain; + py::class_> exported(m, export_name.c_str(), pysep, SEPINVERSE_MAIN); exported - .def(py::init>&,const T&,bool>(), - SEPINVERSE_Y_SEPINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_ARGWRAPPER_Y_DOMAIN_REF_CONST_Y_REF_BOOL, + .def(py::init&,const D&,bool>(), + SEPINVERSE_Y_SEPINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CONST_Y_REF_BOOL, "f"_a, "y"_a, "with_centered_form"_a = true); if constexpr(std::is_same_v) // separators only associated with interval vectors { exported - .def(py::init>&,const pySep&,bool>(), - SEPINVERSE_Y_SEPINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_ARGWRAPPER_Y_DOMAIN_REF_CONST_S_REF_BOOL, + .def(py::init&,const pySep&,bool>(), + SEPINVERSE_Y_SEPINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CONST_S_REF_BOOL, "f"_a, "s"_a, "with_centered_form"_a = true); } exported - .def("separate", &SepInverse::separate, + .def("separate", &SepInverse::separate, BOXPAIR_SEPCTCPAIR_SEPARATE_CONST_INTERVALVECTOR_REF_CONST, "x"_a) ; diff --git a/python/src/core/separators/codac2_py_SepTransform.cpp b/python/src/core/separators/codac2_py_SepTransform.cpp index cf97daf85..19e8751a8 100644 --- a/python/src/core/separators/codac2_py_SepTransform.cpp +++ b/python/src/core/separators/codac2_py_SepTransform.cpp @@ -22,7 +22,7 @@ using namespace pybind11::literals; void export_SepTransform(py::module& m, py::class_& pysep) { - using FNC = AnalyticFunction; + using FNC = AnalyticFunction; py::class_ exported(m, "SepTransform", pysep, SEPTRANSFORM_MAIN); exported @@ -36,7 +36,7 @@ void export_SepTransform(py::module& m, py::class_& pysep) return std::make_unique(s.copy(), _f.cast(), _f_inv.cast()); }), - SEPTRANSFORM_SEPTRANSFORM_CONST_S_REF_CONST_ANALYTICFUNCTION_VECTOROPVALUE_REF_CONST_ANALYTICFUNCTION_VECTOROPVALUE_REF, + SEPTRANSFORM_SEPTRANSFORM_CONST_S_REF_CONST_ANALYTICFUNCTION_VECTORTYPE_REF_CONST_ANALYTICFUNCTION_VECTORTYPE_REF, "s"_a, "f"_a, "f_inv"_a) .def("separate", &SepTransform::separate, diff --git a/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp b/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp index f742c3f40..c3a49279a 100644 --- a/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp +++ b/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp @@ -40,6 +40,6 @@ void _export_AnalyticTrajectory(py::module& m, const string& class_name) void export_AnalyticTrajectory(py::module& m) { - _export_AnalyticTrajectory(m, "AnalyticTrajectory_Scalar"); - _export_AnalyticTrajectory(m, "AnalyticTrajectory_Vector"); + _export_AnalyticTrajectory(m, "AnalyticTrajectory_Scalar"); + _export_AnalyticTrajectory(m, "AnalyticTrajectory_Vector"); } \ No newline at end of file diff --git a/python/src/core/trajectory/codac2_py_TrajectoryBase.h b/python/src/core/trajectory/codac2_py_TrajectoryBase.h index 34bf43b96..9c91c5e98 100644 --- a/python/src/core/trajectory/codac2_py_TrajectoryBase.h +++ b/python/src/core/trajectory/codac2_py_TrajectoryBase.h @@ -84,7 +84,7 @@ void export_TrajectoryBase(py::class_& pyclass) VIRTUAL_SAMPLEDTRAJECTORY_T_TRAJECTORYBASE_T_SAMPLED_DOUBLE_CONST, "dt"_a) - .def("primitive", [](const S& x, const typename S::ScalarType& y0, double dt) + .def("primitive", [](const S& x, const typename S::Type::Scalar& y0, double dt) { return x.primitive(y0,dt); }, diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index e4898aea8..56b38b27b 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -132,9 +132,9 @@ void export_Figure2D(py::module& m) if(x_traj) { - if(py::isinstance>(x_traj)) + if(py::isinstance>(x_traj)) { - fig.draw_trajectory(x_traj.cast>(),s); + fig.draw_trajectory(x_traj.cast>(),s); return; } @@ -146,9 +146,9 @@ void export_Figure2D(py::module& m) } assert_release(false && - "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); + "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); }, - VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTOROPVALUE_REF_CONST_STYLEPROPERTIES_REF, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) // Robots @@ -228,9 +228,9 @@ void export_Figure2D(py::module& m) if(x_traj) { - if(py::isinstance>(x_traj)) + if(py::isinstance>(x_traj)) { - DefaultView::draw_trajectory(x_traj.cast>(),s); + DefaultView::draw_trajectory(x_traj.cast>(),s); return; } @@ -242,9 +242,9 @@ void export_Figure2D(py::module& m) } assert_release(false && - "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); + "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); }, - VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTOROPVALUE_REF_CONST_STYLEPROPERTIES_REF, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) // Robots diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index feb6f0214..96a2e9ee3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -69,13 +69,14 @@ ${CMAKE_CURRENT_SOURCE_DIR}/functions/codac2_VarBase.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_constants.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_operations.h - ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_values.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_variables.cpp ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_analytic_variables.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticExpr.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticExprWrapper.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticFunction.h + ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_AnalyticType.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_ScalarExprList.h + ${CMAKE_CURRENT_SOURCE_DIR}/functions/analytic/codac2_ValueType.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/set/codac2_set_operations.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/set/codac2_set_operators.h ${CMAKE_CURRENT_SOURCE_DIR}/functions/set/codac2_set_variables.h diff --git a/src/core/contractors/codac2_CtcInverse.h b/src/core/contractors/codac2_CtcInverse.h index d0756159a..b1b0cc056 100644 --- a/src/core/contractors/codac2_CtcInverse.h +++ b/src/core/contractors/codac2_CtcInverse.h @@ -27,14 +27,14 @@ namespace codac2 template requires IsCtcBaseOrPtr - CtcInverse(const AnalyticFunction::Domain>& f, const C& ctc_y, bool with_centered_form = true, bool is_not_in = false) + CtcInverse(const AnalyticFunction::Type>& f, const C& ctc_y, bool with_centered_form = true, bool is_not_in = false) : _f(f), _ctc_y(ctc_y), _with_centered_form(with_centered_form), _is_not_in(is_not_in) { assert_release([&]() { return f.output_size() == size_of(ctc_y); }() && "CtcInverse: invalid dimension of image argument ('y' or 'ctc_y')"); } - CtcInverse(const AnalyticFunction::Domain>& f, const Y& y, bool with_centered_form = true, bool is_not_in = false) + CtcInverse(const AnalyticFunction::Type>& f, const Y& y, bool with_centered_form = true, bool is_not_in = false) : CtcInverse(f, CtcWrapper_(y), with_centered_form, is_not_in) { } @@ -122,14 +122,14 @@ namespace codac2 _f.intersect_from_args(v, x...); // updating input values } - const AnalyticFunction::Domain>& function() const + const AnalyticFunction::Type>& function() const { return _f; } protected: - const AnalyticFunction::Domain> _f; + const AnalyticFunction::Type> _f; const Collection> _ctc_y; bool _with_centered_form; bool _is_not_in = false; @@ -140,7 +140,7 @@ namespace codac2 { public: - CtcInverse_(const AnalyticFunction::Domain>& f, const Y& y, bool with_centered_form = true, bool is_not_in = false) + CtcInverse_(const AnalyticFunction::Type>& f, const Y& y, bool with_centered_form = true, bool is_not_in = false) : Ctc,X>(f.args()[0]->size() /* f must have only one arg, see following assert */), CtcInverse(f, y, with_centered_form,is_not_in) { @@ -149,7 +149,7 @@ namespace codac2 template requires IsCtcBaseOrPtr - CtcInverse_(const AnalyticFunction::Domain>& f, const C& ctc_y, bool with_centered_form = true, bool is_not_in = false) + CtcInverse_(const AnalyticFunction::Type>& f, const C& ctc_y, bool with_centered_form = true, bool is_not_in = false) : Ctc,X>(f.args()[0]->size() /* f must have only one arg, see following assert */), CtcInverse(f, ctc_y, with_centered_form,is_not_in) { diff --git a/src/core/contractors/codac2_CtcInverseNotIn.h b/src/core/contractors/codac2_CtcInverseNotIn.h index da0cada77..eb166de28 100644 --- a/src/core/contractors/codac2_CtcInverseNotIn.h +++ b/src/core/contractors/codac2_CtcInverseNotIn.h @@ -21,7 +21,7 @@ namespace codac2 { public: - CtcInverseNotIn(const AnalyticFunction::Domain>& f, const Y& y, bool with_centered_form = true) + CtcInverseNotIn(const AnalyticFunction::Type>& f, const Y& y, bool with_centered_form = true) : CtcUnion(f.args()[0]->size() /* f must have only one arg, see following assert */) { assert_release(f.args().size() == 1 && "f must have only one arg"); @@ -46,7 +46,7 @@ namespace codac2 template requires IsCtcBaseOrPtr - CtcInverseNotIn(const AnalyticFunction::Domain>& f, const C& ctc_compl, bool with_centered_form = true) + CtcInverseNotIn(const AnalyticFunction::Type>& f, const C& ctc_compl, bool with_centered_form = true) : CtcUnion(f.args()[0]->size() /* f must have only one arg, see following assert */) { assert_release(f.args().size() == 1 && "f must have only one arg"); diff --git a/src/core/contractors/codac2_directed_ctc.cpp b/src/core/contractors/codac2_directed_ctc.cpp index db25b48a0..fddb1f559 100644 --- a/src/core/contractors/codac2_directed_ctc.cpp +++ b/src/core/contractors/codac2_directed_ctc.cpp @@ -22,7 +22,7 @@ using namespace codac2; return x1; } - ScalarOpValue AddOp::fwd(const ScalarOpValue& x1) + ScalarType AddOp::fwd(const ScalarType& x1) { return { fwd(x1.m), @@ -40,7 +40,7 @@ using namespace codac2; return x1; } - VectorOpValue AddOp::fwd(const VectorOpValue& x1) + VectorType AddOp::fwd(const VectorType& x1) { return { fwd(x1.m), @@ -60,7 +60,7 @@ using namespace codac2; return x1; } - MatrixOpValue AddOp::fwd(const MatrixOpValue& x1) + MatrixType AddOp::fwd(const MatrixType& x1) { return { fwd(x1.m), @@ -83,7 +83,7 @@ using namespace codac2; return x1 + x2; } - ScalarOpValue AddOp::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) + ScalarType AddOp::fwd(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.size() == x2.da.size()); return { @@ -105,7 +105,7 @@ using namespace codac2; return x1 + x2; } - VectorOpValue AddOp::fwd(const VectorOpValue& x1, const VectorOpValue& x2) + VectorType AddOp::fwd(const VectorType& x1, const VectorType& x2) { assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { @@ -129,7 +129,7 @@ using namespace codac2; return x1 + x2; } - MatrixOpValue AddOp::fwd(const MatrixOpValue& x1, const MatrixOpValue& x2) + MatrixType AddOp::fwd(const MatrixType& x1, const MatrixType& x2) { return { fwd(x1.m, x2.m), @@ -154,7 +154,7 @@ using namespace codac2; return -x1; } - ScalarOpValue SubOp::fwd(const ScalarOpValue& x1) + ScalarType SubOp::fwd(const ScalarType& x1) { return { fwd(x1.m), @@ -175,7 +175,7 @@ using namespace codac2; return -x1; } - VectorOpValue SubOp::fwd(const VectorOpValue& x1) + VectorType SubOp::fwd(const VectorType& x1) { return { fwd(x1.m), @@ -197,7 +197,7 @@ using namespace codac2; return -x1; } - MatrixOpValue SubOp::fwd(const MatrixOpValue& x1) + MatrixType SubOp::fwd(const MatrixType& x1) { return { fwd(x1.m), @@ -222,7 +222,7 @@ using namespace codac2; return x1 - x2; } - ScalarOpValue SubOp::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) + ScalarType SubOp::fwd(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { @@ -244,7 +244,7 @@ using namespace codac2; return x1 - x2; } - VectorOpValue SubOp::fwd(const VectorOpValue& x1, const VectorOpValue& x2) + VectorType SubOp::fwd(const VectorType& x1, const VectorType& x2) { assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { @@ -268,7 +268,7 @@ using namespace codac2; return x1 - x2; } - MatrixOpValue SubOp::fwd(const MatrixOpValue& x1, const MatrixOpValue& x2) + MatrixType SubOp::fwd(const MatrixType& x1, const MatrixType& x2) { assert(x1.a.cols() == x2.a.cols() && x1.a.rows() == x2.a.rows()); return { @@ -294,7 +294,7 @@ using namespace codac2; return x1 * x2; } - ScalarOpValue MulOp::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) + ScalarType MulOp::fwd(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.rows() == 1); assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); @@ -321,7 +321,7 @@ using namespace codac2; return x1 * x2; } - VectorOpValue MulOp::fwd(const ScalarOpValue& x1, const VectorOpValue& x2) + VectorType MulOp::fwd(const ScalarType& x1, const VectorType& x2) { assert(x1.da.rows() == 1); assert(x1.da.cols() == x2.da.cols()); @@ -352,7 +352,7 @@ using namespace codac2; return MulOp::fwd(x2,x1); } - VectorOpValue MulOp::fwd(const VectorOpValue& x1, const ScalarOpValue& x2) + VectorType MulOp::fwd(const VectorType& x1, const ScalarType& x2) { return MulOp::fwd(x2,x1); } @@ -371,9 +371,9 @@ using namespace codac2; return s; } - //ScalarOpValue MulOp::fwd(const RowOpValue& x1, const VectorOpValue& x2) + //ScalarType MulOp::fwd(const RowType& x1, const VectorType& x2) //{ - // // RowOpValue not yet defined + // // RowType not yet defined //} void MulOp::bwd(const Interval& y, IntervalRow& x1, IntervalVector& x2) @@ -410,7 +410,7 @@ using namespace codac2; return x1 * x2; } - VectorOpValue MulOp::fwd(const MatrixOpValue& x1, const VectorOpValue& x2) + VectorType MulOp::fwd(const MatrixType& x1, const VectorType& x2) { return { fwd(x1.a, /* <<----- x1.m */ x2.m), @@ -507,7 +507,7 @@ using namespace codac2; return x1 / x2; } - ScalarOpValue DivOp::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) + ScalarType DivOp::fwd(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.size() == x2.da.size()); @@ -533,7 +533,7 @@ using namespace codac2; return x1 / x2; } - VectorOpValue DivOp::fwd(const VectorOpValue& x1, const ScalarOpValue& x2) + VectorType DivOp::fwd(const VectorType& x1, const ScalarType& x2) { assert(x1.da.size() == x2.da.size()); @@ -563,7 +563,7 @@ using namespace codac2; return pow(x1,x2); } - ScalarOpValue PowOp::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) + ScalarType PowOp::fwd(const ScalarType& x1, const ScalarType& x2) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -590,7 +590,7 @@ using namespace codac2; return sqr(x1); } - ScalarOpValue SqrOp::fwd(const ScalarOpValue& x1) + ScalarType SqrOp::fwd(const ScalarType& x1) { assert(x1.da.rows() == 1); @@ -619,7 +619,7 @@ using namespace codac2; return sqrt(x1); } - ScalarOpValue SqrtOp::fwd(const ScalarOpValue& x1) + ScalarType SqrtOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -648,7 +648,7 @@ using namespace codac2; return exp(x1); } - ScalarOpValue ExpOp::fwd(const ScalarOpValue& x1) + ScalarType ExpOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -675,7 +675,7 @@ using namespace codac2; return log(x1); } - ScalarOpValue LogOp::fwd(const ScalarOpValue& x1) + ScalarType LogOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -704,7 +704,7 @@ using namespace codac2; return cos(x1); } - ScalarOpValue CosOp::fwd(const ScalarOpValue& x1) + ScalarType CosOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -731,7 +731,7 @@ using namespace codac2; return sin(x1); } - ScalarOpValue SinOp::fwd(const ScalarOpValue& x1) + ScalarType SinOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -758,7 +758,7 @@ using namespace codac2; return tan(x1); } - ScalarOpValue TanOp::fwd(const ScalarOpValue& x1) + ScalarType TanOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -785,7 +785,7 @@ using namespace codac2; return acos(x1); } - ScalarOpValue AcosOp::fwd(const ScalarOpValue& x1) + ScalarType AcosOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -814,7 +814,7 @@ using namespace codac2; return asin(x1); } - ScalarOpValue AsinOp::fwd(const ScalarOpValue& x1) + ScalarType AsinOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -843,7 +843,7 @@ using namespace codac2; return atan(x1); } - ScalarOpValue AtanOp::fwd(const ScalarOpValue& x1) + ScalarType AtanOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -870,7 +870,7 @@ using namespace codac2; return atan2(x1,x2); } - ScalarOpValue Atan2Op::fwd(const ScalarOpValue& x1, const ScalarOpValue& x2) + ScalarType Atan2Op::fwd(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.rows() == 1); assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); @@ -901,7 +901,7 @@ using namespace codac2; return cosh(x1); } - ScalarOpValue CoshOp::fwd(const ScalarOpValue& x1) + ScalarType CoshOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -928,7 +928,7 @@ using namespace codac2; return sinh(x1); } - ScalarOpValue SinhOp::fwd(const ScalarOpValue& x1) + ScalarType SinhOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -955,7 +955,7 @@ using namespace codac2; return tanh(x1); } - ScalarOpValue TanhOp::fwd(const ScalarOpValue& x1) + ScalarType TanhOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -982,7 +982,7 @@ using namespace codac2; return abs(x1); } - ScalarOpValue AbsOp::fwd(const ScalarOpValue& x1) + ScalarType AbsOp::fwd(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -1010,7 +1010,7 @@ using namespace codac2; return x1[i]; } - ScalarOpValue ComponentOp::fwd(const VectorOpValue& x1, Index i) + ScalarType ComponentOp::fwd(const VectorType& x1, Index i) { assert(i >= 0 && i < x1.a.rows()); return { @@ -1036,7 +1036,7 @@ using namespace codac2; return x1.subvector(i,j); } - VectorOpValue SubvectorOp::fwd(const VectorOpValue& x1, Index i, Index j) + VectorType SubvectorOp::fwd(const VectorType& x1, Index i, Index j) { assert(i >= 0 && i < x1.a.rows() && j >= i && j < x1.a.rows()); return { @@ -1085,7 +1085,7 @@ using namespace codac2; return Interval::empty(); // unhandled case } - ScalarOpValue DetOp::fwd(const MatrixOpValue& x) + ScalarType DetOp::fwd(const MatrixType& x) { return { fwd(x.m), @@ -1127,7 +1127,7 @@ using namespace codac2; return DetOp::fwd(m); } - ScalarOpValue DetOp::fwd(const VectorOpValue& x1, const VectorOpValue& x2) + ScalarType DetOp::fwd(const VectorType& x1, const VectorType& x2) { IntervalMatrix m(2,2); m.col(0) = x1.m; m.col(1) = x2.m; @@ -1162,7 +1162,7 @@ using namespace codac2; return DetOp::fwd(m); } - ScalarOpValue DetOp::fwd(const VectorOpValue& x1, const VectorOpValue& x2, const VectorOpValue& x3) + ScalarType DetOp::fwd(const VectorType& x1, const VectorType& x2, const VectorType& x3) { IntervalMatrix m(3,3); m.col(0) = x1.m; m.col(1) = x2.m; m.col(2) = x3.m; diff --git a/src/core/contractors/codac2_directed_ctc.h b/src/core/contractors/codac2_directed_ctc.h index 4b9ad4607..3c3f6124a 100644 --- a/src/core/contractors/codac2_directed_ctc.h +++ b/src/core/contractors/codac2_directed_ctc.h @@ -10,7 +10,7 @@ #pragma once #include -#include "codac2_analytic_values.h" +#include "codac2_AnalyticType.h" #include "codac2_template_tools.h" #include "codac2_IntervalRow.h" @@ -20,28 +20,28 @@ namespace codac2 { // Unary operations static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); static IntervalVector fwd(const IntervalVector& x1); - static VectorOpValue fwd(const VectorOpValue& x1); + static VectorType fwd(const VectorType& x1); static void bwd(const IntervalVector& y, IntervalVector& x1); static IntervalMatrix fwd(const IntervalMatrix& x1); - static MatrixOpValue fwd(const MatrixOpValue& x1); + static MatrixType fwd(const MatrixType& x1); static void bwd(const IntervalMatrix& y, IntervalMatrix& x1); // Binary operations static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarOpValue fwd(const ScalarOpValue& x1, const ScalarOpValue& x2); + static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); static IntervalVector fwd(const IntervalVector& x1, const IntervalVector& x2); - static VectorOpValue fwd(const VectorOpValue& x1, const VectorOpValue& x2); + static VectorType fwd(const VectorType& x1, const VectorType& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, IntervalVector& x2); static IntervalMatrix fwd(const IntervalMatrix& x1, const IntervalMatrix& x2); - static MatrixOpValue fwd(const MatrixOpValue& x1, const MatrixOpValue& x2); + static MatrixType fwd(const MatrixType& x1, const MatrixType& x2); static void bwd(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2); }; @@ -49,188 +49,188 @@ namespace codac2 { // Unary operations static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); static IntervalVector fwd(const IntervalVector& x1); - static VectorOpValue fwd(const VectorOpValue& x1); + static VectorType fwd(const VectorType& x1); static void bwd(const IntervalVector& y, IntervalVector& x1); static IntervalMatrix fwd(const IntervalMatrix& x1); - static MatrixOpValue fwd(const MatrixOpValue& x1); + static MatrixType fwd(const MatrixType& x1); static void bwd(const IntervalMatrix& y, IntervalMatrix& x1); // Binary operations static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarOpValue fwd(const ScalarOpValue& x1, const ScalarOpValue& x2); + static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); static IntervalVector fwd(const IntervalVector& x1, const IntervalVector& x2); - static VectorOpValue fwd(const VectorOpValue& x1, const VectorOpValue& x2); + static VectorType fwd(const VectorType& x1, const VectorType& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, IntervalVector& x2); static IntervalMatrix fwd(const IntervalMatrix& x1, const IntervalMatrix& x2); - static MatrixOpValue fwd(const MatrixOpValue& x1, const MatrixOpValue& x2); + static MatrixType fwd(const MatrixType& x1, const MatrixType& x2); static void bwd(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2); }; struct MulOp { static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarOpValue fwd(const ScalarOpValue& x1, const ScalarOpValue& x2); + static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); static IntervalVector fwd(const Interval& x1, const IntervalVector& x2); - static VectorOpValue fwd(const ScalarOpValue& x1, const VectorOpValue& x2); + static VectorType fwd(const ScalarType& x1, const VectorType& x2); static void bwd(const IntervalVector& y, Interval& x1, IntervalVector& x2); static IntervalVector fwd(const IntervalVector& x1, const Interval& x2); - static VectorOpValue fwd(const VectorOpValue& x1, const ScalarOpValue& x2); + static VectorType fwd(const VectorType& x1, const ScalarType& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2); static Interval fwd(const IntervalRow& x1, const IntervalVector& x2); - //static ScalarOpValue fwd(const RowOpValue& x1, const VectorOpValue& x2); // RowOpValue not yet defined + //static ScalarType fwd(const RowType& x1, const VectorType& x2); // RowType not yet defined static void bwd(const Interval& y, IntervalRow& x1, IntervalVector& x2); static IntervalVector fwd(const IntervalMatrix& x1, const IntervalVector& x2); - static VectorOpValue fwd(const MatrixOpValue& x1, const VectorOpValue& x2); + static VectorType fwd(const MatrixType& x1, const VectorType& x2); static void bwd(const IntervalVector& y, IntervalMatrix& x1, IntervalVector& x2); }; struct DivOp { static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarOpValue fwd(const ScalarOpValue& x1, const ScalarOpValue& x2); + static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); static IntervalVector fwd(const IntervalVector& x1, const Interval& x2); - static VectorOpValue fwd(const VectorOpValue& x1, const ScalarOpValue& x2); + static VectorType fwd(const VectorType& x1, const ScalarType& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2); }; struct PowOp { static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarOpValue fwd(const ScalarOpValue& x1, const ScalarOpValue& x2); + static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); }; struct SqrOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct SqrtOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct ExpOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct LogOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct CosOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct SinOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct TanOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct AcosOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct AsinOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct AtanOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct Atan2Op { static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarOpValue fwd(const ScalarOpValue& x1, const ScalarOpValue& x2); + static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); }; struct CoshOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct SinhOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct TanhOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct AbsOp { static Interval fwd(const Interval& x1); - static ScalarOpValue fwd(const ScalarOpValue& x1); + static ScalarType fwd(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct ComponentOp { static Interval fwd(const IntervalVector& x1, Index i); - static ScalarOpValue fwd(const VectorOpValue& x1, Index i); + static ScalarType fwd(const VectorType& x1, Index i); static void bwd(const Interval& y, IntervalVector& x1, Index i); }; struct SubvectorOp { static IntervalVector fwd(const IntervalVector& x1, Index i, Index j); - static VectorOpValue fwd(const VectorOpValue& x1, Index i, Index j); + static VectorType fwd(const VectorType& x1, Index i, Index j); static void bwd(const IntervalVector& y, IntervalVector& x1, Index i, Index j); }; @@ -244,8 +244,8 @@ namespace codac2 } template - requires (std::is_base_of_v && ...) - static VectorOpValue fwd(const X&... x) + requires (std::is_base_of_v && ...) + static VectorType fwd(const X&... x) { IntervalMatrix d(sizeof...(X),std::get<0>(std::tie(x...)).da.cols()); Index i = 0; @@ -287,8 +287,8 @@ namespace codac2 } template - requires (std::is_base_of_v && ...) - static MatrixOpValue fwd(const X&... x) + requires (std::is_base_of_v && ...) + static MatrixType fwd(const X&... x) { throw std::runtime_error("MatrixOp not fully implemented yet"); return { @@ -313,17 +313,17 @@ namespace codac2 { // For matrices static Interval fwd(const IntervalMatrix& x); - static ScalarOpValue fwd(const MatrixOpValue& x); + static ScalarType fwd(const MatrixType& x); static void bwd(const Interval& y, IntervalMatrix& x); // For two vectors (merged into a 2×2 matrix) static Interval fwd(const IntervalVector& x1, const IntervalVector& x2); - static ScalarOpValue fwd(const VectorOpValue& x1, const VectorOpValue& x2); + static ScalarType fwd(const VectorType& x1, const VectorType& x2); static void bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2); // For three vectors (merged into a 3×3 matrix) static Interval fwd(const IntervalVector& x1, const IntervalVector& x2, const IntervalVector& x3); - static ScalarOpValue fwd(const VectorOpValue& x1, const VectorOpValue& x2, const VectorOpValue& x3); + static ScalarType fwd(const VectorType& x1, const VectorType& x2, const VectorType& x3); static void bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2, IntervalVector& x3); }; } \ No newline at end of file diff --git a/src/core/domains/codac2_Wrapper.h b/src/core/domains/codac2_Wrapper.h index baa9779ea..b58544dba 100644 --- a/src/core/domains/codac2_Wrapper.h +++ b/src/core/domains/codac2_Wrapper.h @@ -14,7 +14,6 @@ #include "codac2_Matrix.h" #include "codac2_IntervalVector.h" #include "codac2_IntervalMatrix.h" -#include "codac2_analytic_values.h" namespace codac2 { diff --git a/src/core/functions/analytic/codac2_AnalyticExpr.h b/src/core/functions/analytic/codac2_AnalyticExpr.h index a0bd43af9..671c285d6 100644 --- a/src/core/functions/analytic/codac2_AnalyticExpr.h +++ b/src/core/functions/analytic/codac2_AnalyticExpr.h @@ -19,7 +19,7 @@ namespace codac2 { - using ValuesMap = std::map>; + using ValuesMap = std::map>; template class AnalyticExpr : public ExprBase @@ -112,33 +112,33 @@ namespace codac2 }; template<> - class AnalyticOperationExpr : public AnalyticExpr, public OperationExprBase> + class AnalyticOperationExpr : public AnalyticExpr, public OperationExprBase> { public: - AnalyticOperationExpr(const std::shared_ptr>& x1, Index i) - : OperationExprBase>(x1), _i(i) + AnalyticOperationExpr(const std::shared_ptr>& x1, Index i) + : OperationExprBase>(x1), _i(i) { } std::shared_ptr copy() const { - return std::make_shared>(*this); + return std::make_shared>(*this); } void replace_expr(const ExprID& old_expr_id, const std::shared_ptr& new_expr) { - return OperationExprBase>::replace_expr(old_expr_id, new_expr); + return OperationExprBase>::replace_expr(old_expr_id, new_expr); } - ScalarOpValue fwd_eval(ValuesMap& v, Index total_input_size) const + ScalarType fwd_eval(ValuesMap& v, Index total_input_size) const { - return AnalyticExpr::init_value( + return AnalyticExpr::init_value( v, ComponentOp::fwd(std::get<0>(this->_x)->fwd_eval(v, total_input_size), _i)); } void bwd_eval(ValuesMap& v) const { - ComponentOp::bwd(AnalyticExpr::value(v).a, std::get<0>(this->_x)->value(v).a, _i); + ComponentOp::bwd(AnalyticExpr::value(v).a, std::get<0>(this->_x)->value(v).a, _i); std::get<0>(this->_x)->bwd_eval(v); } @@ -153,33 +153,33 @@ namespace codac2 }; template<> - class AnalyticOperationExpr : public AnalyticExpr, public OperationExprBase> + class AnalyticOperationExpr : public AnalyticExpr, public OperationExprBase> { public: - AnalyticOperationExpr(const std::shared_ptr>& x1, Index i, Index j) - : OperationExprBase>(x1), _i(i), _j(j) + AnalyticOperationExpr(const std::shared_ptr>& x1, Index i, Index j) + : OperationExprBase>(x1), _i(i), _j(j) { } std::shared_ptr copy() const { - return std::make_shared>(*this); + return std::make_shared>(*this); } void replace_expr(const ExprID& old_expr_id, const std::shared_ptr& new_expr) { - return OperationExprBase>::replace_expr(old_expr_id, new_expr); + return OperationExprBase>::replace_expr(old_expr_id, new_expr); } - VectorOpValue fwd_eval(ValuesMap& v, Index total_input_size) const + VectorType fwd_eval(ValuesMap& v, Index total_input_size) const { - return AnalyticExpr::init_value( + return AnalyticExpr::init_value( v, SubvectorOp::fwd(std::get<0>(this->_x)->fwd_eval(v, total_input_size), _i, _j)); } void bwd_eval(ValuesMap& v) const { - SubvectorOp::bwd(AnalyticExpr::value(v).a, std::get<0>(this->_x)->value(v).a, _i, _j); + SubvectorOp::bwd(AnalyticExpr::value(v).a, std::get<0>(this->_x)->value(v).a, _i, _j); std::get<0>(this->_x)->bwd_eval(v); } diff --git a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h index 972c6be27..d2756e835 100644 --- a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h +++ b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h @@ -10,10 +10,17 @@ #pragma once #include "codac2_AnalyticExpr.h" -#include "codac2_analytic_constants.h" +#include "codac2_ValueType.h" +#include "codac2_analytic_variables.h" namespace codac2 { + template + struct AnalyticExprWrapper; + + template + AnalyticExprWrapper::Type> const_value(const T& x); + template struct AnalyticExprWrapper : public std::shared_ptr> { @@ -22,31 +29,31 @@ namespace codac2 { } AnalyticExprWrapper(const ScalarVar& e) - requires std::is_same_v + requires std::is_same_v : std::shared_ptr>({ std::dynamic_pointer_cast>(e.copy()) }) { } AnalyticExprWrapper(const VectorVar& e) - requires std::is_same_v + requires std::is_same_v : std::shared_ptr>({ std::dynamic_pointer_cast>(e.copy()) }) { } template AnalyticExprWrapper(const V& e) - requires std::is_same_v::Domain,T> + requires std::is_same_v::Type,T> : std::shared_ptr>(const_value(e)) { } - inline AnalyticExprWrapper operator[](Index i) const - requires std::is_same_v + inline AnalyticExprWrapper operator[](Index i) const + requires std::is_same_v { - return { std::make_shared>(*this,i) }; + return { std::make_shared>(*this,i) }; } }; - using ScalarExpr = AnalyticExprWrapper; - using VectorExpr = AnalyticExprWrapper; - using MatrixExpr = AnalyticExprWrapper; + using ScalarExpr = AnalyticExprWrapper; + using VectorExpr = AnalyticExprWrapper; + using MatrixExpr = AnalyticExprWrapper; template concept IsScalarExprOrVar = (std::is_base_of_v || std::is_base_of_v); diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index dc796d6d3..ded5cc69e 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -35,13 +35,13 @@ namespace codac2 { return static_cast(static_cast(a) | static_cast(b)); } template - requires std::is_base_of_v + requires std::is_base_of_v class AnalyticFunction : public FunctionBase> { public: AnalyticFunction(const FunctionArgsList& args, const ScalarExprList& y) - requires(std::is_same_v) + requires(std::is_same_v) : FunctionBase>(args, y) { assert_release(y->belongs_to_args_list(this->args()) && @@ -89,7 +89,7 @@ namespace codac2 auto flatten_x = cart_prod(x...); assert(x_.da.rows() == x_.a.size() && x_.da.cols() == flatten_x.size()); - if constexpr(std::is_same_v) + if constexpr(std::is_same_v) return x_.m + (x_.da*(flatten_x-flatten_x.mid()))[0]; else return x_.m + (x_.da*(flatten_x-flatten_x.mid())).col(0); @@ -104,7 +104,7 @@ namespace codac2 else { auto flatten_x = cart_prod(x...); - if constexpr(std::is_same_v) + if constexpr(std::is_same_v) return x_.a & (x_.m + (x_.da*(flatten_x-flatten_x.mid()))[0]); else { @@ -131,10 +131,10 @@ namespace codac2 Index output_size() const { - if constexpr(std::is_same_v) + if constexpr(std::is_same_v) return 1; - else if constexpr(std::is_same_v) + else if constexpr(std::is_same_v) { // A dump evaluation is performed to estimate the dimension // of the image of this function. A natural evaluation is assumed @@ -151,9 +151,9 @@ namespace codac2 friend std::ostream& operator<<(std::ostream& os, [[maybe_unused]] const AnalyticFunction& f) { - if constexpr(std::is_same_v) + if constexpr(std::is_same_v) os << "scalar function"; - else if constexpr(std::is_same_v) + else if constexpr(std::is_same_v) os << "vector function"; return os; } @@ -178,7 +178,7 @@ namespace codac2 for(Index k = p ; k < p+size_of(x) ; k++) d(k-p,k) = 1.; - using D_DOMAIN = typename ArgWrapper::Domain; + using D_DOMAIN = typename ValueType::Type; v[this->args()[i]->unique_id()] = std::make_shared(typename D_DOMAIN::Domain(x).mid(), x, d, true); @@ -195,7 +195,7 @@ namespace codac2 void intersect_value_from_arg_map(const ValuesMap& v, D& x, Index i) const { assert(v.find(this->args()[i]->unique_id()) != v.end() && "argument cannot be found"); - x &= std::dynamic_pointer_cast::Domain>(v.at(this->args()[i]->unique_id()))->a; + x &= std::dynamic_pointer_cast::Type>(v.at(this->args()[i]->unique_id()))->a; } template @@ -232,28 +232,28 @@ namespace codac2 }; AnalyticFunction(const FunctionArgsList&, double) -> - AnalyticFunction; + AnalyticFunction; AnalyticFunction(const FunctionArgsList&, const Interval&) -> - AnalyticFunction; + AnalyticFunction; AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> - AnalyticFunction; + AnalyticFunction; AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> - AnalyticFunction; + AnalyticFunction; AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> - AnalyticFunction; + AnalyticFunction; AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> - AnalyticFunction; + AnalyticFunction; AnalyticFunction(const FunctionArgsList&, std::initializer_list) -> - AnalyticFunction; + AnalyticFunction; template AnalyticFunction(const FunctionArgsList&, const T&) -> - AnalyticFunction::Domain>; + AnalyticFunction::Type>; } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_AnalyticType.h b/src/core/functions/analytic/codac2_AnalyticType.h new file mode 100644 index 000000000..c5c7eda85 --- /dev/null +++ b/src/core/functions/analytic/codac2_AnalyticType.h @@ -0,0 +1,54 @@ +/** + * \file codac2_AnalyticType.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_Interval.h" +#include "codac2_Vector.h" +#include "codac2_Matrix.h" +#include "codac2_IntervalVector.h" +#include "codac2_IntervalMatrix.h" + +namespace codac2 +{ + struct AnalyticTypeBase + { + virtual ~AnalyticTypeBase() = default; + }; + + template + struct AnalyticType : public AnalyticTypeBase + { + using Scalar = S; + using Domain = T; + + T m; + T a; + M da; + bool def_domain; + + AnalyticType() = delete; + + AnalyticType(const T& m_, const T& a_, const M& da_, bool def_domain_) + : m(m_), a(a_), da(da_), def_domain(def_domain_) + { } + + AnalyticType& operator&=(const AnalyticType& x) + { + a &= x.a; + // restore this? da &= x.da; + def_domain &= x.def_domain; + return *this; + } + }; + + using ScalarType = AnalyticType; + using VectorType = AnalyticType; + using MatrixType = AnalyticType; +} \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_ScalarExprList.h b/src/core/functions/analytic/codac2_ScalarExprList.h index 7ac1f6301..0d14d49ba 100644 --- a/src/core/functions/analytic/codac2_ScalarExprList.h +++ b/src/core/functions/analytic/codac2_ScalarExprList.h @@ -18,20 +18,20 @@ namespace codac2 template concept IsScalar = std::is_same_v || std::is_same_v || - std::is_same_v::Domain,ScalarOpValue>; + std::is_same_v::Type,ScalarType>; - struct ScalarExprList : public AnalyticExprWrapper + struct ScalarExprList : public AnalyticExprWrapper { template requires IsScalar ScalarExprList(const S1& y1) - : AnalyticExprWrapper(vec(to_ScalarExpr(y1))) + : AnalyticExprWrapper(vec(to_ScalarExpr(y1))) { } template requires IsScalar && IsScalar ScalarExprList(const S1& y1, const S2& y2) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1),to_ScalarExpr(y2) )) { } @@ -39,7 +39,7 @@ namespace codac2 template requires IsScalar && IsScalar && IsScalar ScalarExprList(const S1& y1, const S2& y2, const S3& y3) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3) )) { } @@ -47,7 +47,7 @@ namespace codac2 template requires IsScalar && IsScalar && IsScalar && IsScalar ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4) )) { } @@ -55,7 +55,7 @@ namespace codac2 template requires IsScalar && IsScalar && IsScalar && IsScalar && IsScalar ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5) )) { } @@ -66,7 +66,7 @@ namespace codac2 && IsScalar ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, const S6& y6) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), to_ScalarExpr(y6) )) @@ -78,7 +78,7 @@ namespace codac2 && IsScalar && IsScalar ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, const S6& y6, const S7& y7) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), to_ScalarExpr(y6), to_ScalarExpr(y7) )) @@ -90,7 +90,7 @@ namespace codac2 && IsScalar && IsScalar && IsScalar ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, const S6& y6, const S7& y7, const S8& y8) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), to_ScalarExpr(y6), to_ScalarExpr(y7), to_ScalarExpr(y8) )) @@ -102,7 +102,7 @@ namespace codac2 && IsScalar && IsScalar && IsScalar && IsScalar ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, const S6& y6, const S7& y7, const S8& y8, const S9& y9) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), to_ScalarExpr(y6), to_ScalarExpr(y7), to_ScalarExpr(y8), to_ScalarExpr(y9) )) @@ -114,7 +114,7 @@ namespace codac2 && IsScalar && IsScalar && IsScalar && IsScalar && IsScalar ScalarExprList(const S1& y1, const S2& y2, const S3& y3, const S4& y4, const S5& y5, const S6& y6, const S7& y7, const S8& y8, const S9& y9, const S10& y10) - : AnalyticExprWrapper(vec( + : AnalyticExprWrapper(vec( to_ScalarExpr(y1), to_ScalarExpr(y2), to_ScalarExpr(y3), to_ScalarExpr(y4), to_ScalarExpr(y5), to_ScalarExpr(y6), to_ScalarExpr(y7), to_ScalarExpr(y8), to_ScalarExpr(y9), to_ScalarExpr(y10) )) @@ -126,7 +126,7 @@ namespace codac2 } template - requires std::is_same_v::Domain,ScalarOpValue> + requires std::is_same_v::Type,ScalarType> ScalarExpr to_ScalarExpr(const T& e) { return const_value(e); diff --git a/src/core/functions/analytic/codac2_ValueType.h b/src/core/functions/analytic/codac2_ValueType.h new file mode 100644 index 000000000..06086ce16 --- /dev/null +++ b/src/core/functions/analytic/codac2_ValueType.h @@ -0,0 +1,64 @@ +/** + * \file codac2_ValueType.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_Interval.h" +#include "codac2_Vector.h" +#include "codac2_Matrix.h" +#include "codac2_IntervalVector.h" +#include "codac2_IntervalMatrix.h" +#include "codac2_AnalyticType.h" + +namespace codac2 +{ + template + struct ValueType + { }; + + template<> + struct ValueType { + using Type = ScalarType; + }; + + template<> + struct ValueType { + using Type = ScalarType; + }; + + template<> + struct ValueType { + using Type = ScalarType; + }; + + template<> + struct ValueType { + using Type = ScalarType; + }; + + template<> + struct ValueType { + using Type = VectorType; + }; + + template<> + struct ValueType { + using Type = VectorType; + }; + + template<> + struct ValueType { + using Type = MatrixType; + }; + + template<> + struct ValueType { + using Type = MatrixType; + }; +} \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_constants.h b/src/core/functions/analytic/codac2_analytic_constants.h index 72cd7f1ec..a3d75b381 100644 --- a/src/core/functions/analytic/codac2_analytic_constants.h +++ b/src/core/functions/analytic/codac2_analytic_constants.h @@ -10,6 +10,8 @@ #pragma once #include "codac2_Index.h" +#include "codac2_ValueType.h" +#include "codac2_AnalyticExprWrapper.h" namespace codac2 { @@ -59,8 +61,8 @@ namespace codac2 }; template - AnalyticExprWrapper::Domain> const_value(const T& x) + AnalyticExprWrapper::Type> const_value(const T& x) { - return { std::make_shared::Domain>>(x) }; + return { std::make_shared::Type>>(x) }; } } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_operations.h b/src/core/functions/analytic/codac2_analytic_operations.h index 0b2778600..9960b2786 100644 --- a/src/core/functions/analytic/codac2_analytic_operations.h +++ b/src/core/functions/analytic/codac2_analytic_operations.h @@ -11,7 +11,7 @@ #include #include "codac2_AnalyticExpr.h" -#include "codac2_analytic_variables.h" +#include "codac2_AnalyticType.h" #include "codac2_analytic_constants.h" #include "codac2_AnalyticExprWrapper.h" @@ -22,19 +22,19 @@ namespace codac2 inline ScalarExpr operator+(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline VectorExpr operator+(const VectorExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline MatrixExpr operator+(const MatrixExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } // operator+ @@ -42,19 +42,19 @@ namespace codac2 inline ScalarExpr operator+(ScalarExpr x1, ScalarExpr x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline VectorExpr operator+(VectorExpr x1, VectorExpr x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline MatrixExpr operator+(MatrixExpr x1, MatrixExpr x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } // operator- (unary case) @@ -62,19 +62,19 @@ namespace codac2 inline ScalarExpr operator-(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline VectorExpr operator-(const VectorExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline MatrixExpr operator-(const MatrixExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } // operator- @@ -82,19 +82,19 @@ namespace codac2 inline ScalarExpr operator-(const ScalarExpr& x1, const ScalarExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline VectorExpr operator-(const VectorExpr& x1, const VectorExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline MatrixExpr operator-(const MatrixExpr& x1, const MatrixExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } // operator* @@ -102,25 +102,25 @@ namespace codac2 inline ScalarExpr operator*(const ScalarExpr& x1, const ScalarExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline VectorExpr operator*(const ScalarExpr& x1, const VectorExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline VectorExpr operator*(const VectorExpr& x1, const ScalarExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline VectorExpr operator*(const MatrixExpr& x1, const VectorExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } // operator/ @@ -128,13 +128,13 @@ namespace codac2 inline ScalarExpr operator/(const ScalarExpr& x1, const ScalarExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline VectorExpr operator/(const VectorExpr& x1, const ScalarExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } // Other operators @@ -142,97 +142,97 @@ namespace codac2 inline ScalarExpr pow(const ScalarExpr& x1, const ScalarExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline ScalarExpr sqr(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr sqrt(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr exp(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr log(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr cos(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr sin(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr tan(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr acos(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr asin(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr atan(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr atan2(const ScalarExpr& x1, const ScalarExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline ScalarExpr cosh(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr sinh(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr tanh(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr abs(const ScalarExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } // Structural operators @@ -255,8 +255,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1)) }; } @@ -265,8 +265,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2)) }; } @@ -275,8 +275,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3)) }; } @@ -285,8 +285,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4)) }; } @@ -295,8 +295,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5)) }; } @@ -305,8 +305,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6)) }; } @@ -315,8 +315,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6, const X7& x7) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7)) }; } @@ -325,8 +325,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6, const X7& x7, const X8& x8) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8)) }; } @@ -335,8 +335,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6, const X7& x7, const X8& x8, const X9& x9) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8),_add_to_vec(x9)) }; } @@ -345,8 +345,8 @@ namespace codac2 inline VectorExpr vec(const X1& x1, const X2& x2, const X3& x3, const X4& x4, const X5& x5, const X6& x6, const X7& x7, const X8& x8, const X9& x9, const X10& x10) { - return { std::make_shared>( + return { std::make_shared>( _add_to_vec(x1),_add_to_vec(x2),_add_to_vec(x3),_add_to_vec(x4),_add_to_vec(x5),_add_to_vec(x6),_add_to_vec(x7),_add_to_vec(x8),_add_to_vec(x9),_add_to_vec(x10)) }; } @@ -356,15 +356,15 @@ namespace codac2 inline VectorExpr vec(const AnalyticExprWrapper&... x) { - return { std::make_shared>(x...) }; + return { std::make_shared>(x...) }; } template inline MatrixExpr mat(const std::shared_ptr>&... x) { - return { std::make_shared>( - AnalyticOperationExpr(x...)) }; + return { std::make_shared>( + AnalyticOperationExpr(x...)) }; } // Vectorial operations @@ -372,18 +372,18 @@ namespace codac2 inline ScalarExpr det(const MatrixExpr& x1) { - return { std::make_shared>(x1) }; + return { std::make_shared>(x1) }; } inline ScalarExpr det(const VectorExpr& x1, const VectorExpr& x2) { - return { std::make_shared>(x1,x2) }; + return { std::make_shared>(x1,x2) }; } inline ScalarExpr det(const VectorExpr& x1, const VectorExpr& x2, const VectorExpr& x3) { - return { std::make_shared>(x1,x2,x3) }; + return { std::make_shared>(x1,x2,x3) }; } } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_values.h b/src/core/functions/analytic/codac2_analytic_values.h deleted file mode 100644 index 670887529..000000000 --- a/src/core/functions/analytic/codac2_analytic_values.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * \file codac2_analytic_values.h - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include "codac2_Interval.h" -#include "codac2_Vector.h" -#include "codac2_Matrix.h" -#include "codac2_IntervalVector.h" -#include "codac2_IntervalMatrix.h" - -namespace codac2 -{ - struct OpValueBase - { - virtual ~OpValueBase() = default; - }; - - template - struct OpValue : public OpValueBase - { - using Scalar = S; - using Domain = T; - - T m; - T a; - M da; - bool def_domain; - - OpValue() = delete; - - OpValue(const T& m_, const T& a_, const M& da_, bool def_domain_) - : m(m_), a(a_), da(da_), def_domain(def_domain_) - { } - - OpValue& operator&=(const OpValue& x) - { - a &= x.a; - // restore this? da &= x.da; - def_domain &= x.def_domain; - return *this; - } - }; - - using ScalarOpValue = OpValue; - using VectorOpValue = OpValue; - using MatrixOpValue = OpValue; - - template - struct ArgWrapper - { }; - - template<> - struct ArgWrapper { - using Domain = ScalarOpValue; - }; - - template<> - struct ArgWrapper { - using Domain = ScalarOpValue; - }; - - template<> - struct ArgWrapper { - using Domain = ScalarOpValue; - }; - - template<> - struct ArgWrapper { - using Domain = ScalarOpValue; - }; - - template<> - struct ArgWrapper { - using Domain = VectorOpValue; - }; - - template<> - struct ArgWrapper { - using Domain = VectorOpValue; - }; - - template<> - struct ArgWrapper { - using Domain = MatrixOpValue; - }; - - template<> - struct ArgWrapper { - using Domain = MatrixOpValue; - }; -} \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_variables.cpp b/src/core/functions/analytic/codac2_analytic_variables.cpp index cdce629c2..90be2abe8 100644 --- a/src/core/functions/analytic/codac2_analytic_variables.cpp +++ b/src/core/functions/analytic/codac2_analytic_variables.cpp @@ -34,10 +34,10 @@ using namespace codac2; return 1; } - AnalyticExprWrapper ScalarVar::operator-() const + AnalyticExprWrapper ScalarVar::operator-() const { - return { std::make_shared>( - std::dynamic_pointer_cast>(this->copy())) }; + return { std::make_shared>( + std::dynamic_pointer_cast>(this->copy())) }; } @@ -64,16 +64,16 @@ using namespace codac2; return _n; } - AnalyticExprWrapper VectorVar::operator[](Index i) const + AnalyticExprWrapper VectorVar::operator[](Index i) const { assert_release(i >= 0 && i < _n); - return { std::make_shared>( - std::dynamic_pointer_cast>(this->copy()), i) }; + return { std::make_shared>( + std::dynamic_pointer_cast>(this->copy()), i) }; } - AnalyticExprWrapper VectorVar::subvector(Index i, Index j) const + AnalyticExprWrapper VectorVar::subvector(Index i, Index j) const { assert_release(i >= 0 && i < _n && j >= i && j < _n); - return { std::make_shared>( - std::dynamic_pointer_cast>(this->copy()), i, j) }; + return { std::make_shared>( + std::dynamic_pointer_cast>(this->copy()), i, j) }; } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_analytic_variables.h b/src/core/functions/analytic/codac2_analytic_variables.h index 8ac4441f8..fa436c736 100644 --- a/src/core/functions/analytic/codac2_analytic_variables.h +++ b/src/core/functions/analytic/codac2_analytic_variables.h @@ -51,7 +51,7 @@ namespace codac2 } }; - class ScalarVar : public AnalyticVarExpr + class ScalarVar : public AnalyticVarExpr { public: @@ -61,10 +61,10 @@ namespace codac2 std::shared_ptr copy() const; Index size() const; - AnalyticExprWrapper operator-() const; + AnalyticExprWrapper operator-() const; }; - class VectorVar : public AnalyticVarExpr + class VectorVar : public AnalyticVarExpr { public: @@ -74,8 +74,8 @@ namespace codac2 std::shared_ptr copy() const; Index size() const; - AnalyticExprWrapper operator[](Index i) const; - AnalyticExprWrapper subvector(Index i, Index j) const; + AnalyticExprWrapper operator[](Index i) const; + AnalyticExprWrapper subvector(Index i, Index j) const; protected: diff --git a/src/core/functions/set/codac2_SetExpr.h b/src/core/functions/set/codac2_SetExpr.h index 3f0e548fc..0985fbd2b 100644 --- a/src/core/functions/set/codac2_SetExpr.h +++ b/src/core/functions/set/codac2_SetExpr.h @@ -147,7 +147,7 @@ namespace codac2 { public: - SetOperationExpr(const AnalyticFunction& f, std::shared_ptr x) + SetOperationExpr(const AnalyticFunction& f, std::shared_ptr x) : OperationExprBase(x), _f(f) { } @@ -182,7 +182,7 @@ namespace codac2 protected: - const AnalyticFunction _f; + const AnalyticFunction _f; }; template<> diff --git a/src/core/functions/set/codac2_set_operations.h b/src/core/functions/set/codac2_set_operations.h index e8dc14f6b..d6bb1f4de 100644 --- a/src/core/functions/set/codac2_set_operations.h +++ b/src/core/functions/set/codac2_set_operations.h @@ -85,13 +85,13 @@ namespace codac2 } inline SetExpr_ptr - inverse(const AnalyticFunction& f, const SetExpr_ptr& x1) + inverse(const AnalyticFunction& f, const SetExpr_ptr& x1) { return std::make_shared>(f,x1); } inline SetExpr_ptr - inverse(const AnalyticFunction& f, const IntervalVector& x1) + inverse(const AnalyticFunction& f, const IntervalVector& x1) { return std::make_shared>(f,const_set(x1)); } diff --git a/src/core/functions/set/codac2_set_operators.h b/src/core/functions/set/codac2_set_operators.h index 8a400b4c6..c897b1aad 100644 --- a/src/core/functions/set/codac2_set_operators.h +++ b/src/core/functions/set/codac2_set_operators.h @@ -94,12 +94,12 @@ namespace codac2 struct InverseSetOp { - static std::shared_ptr> create_ctc(const AnalyticFunction& f, const std::shared_ptr>& s1) + static std::shared_ptr> create_ctc(const AnalyticFunction& f, const std::shared_ptr>& s1) { return std::make_shared>(f,s1); } - static std::shared_ptr create_sep(const AnalyticFunction& f, const std::shared_ptr& s1) + static std::shared_ptr create_sep(const AnalyticFunction& f, const std::shared_ptr& s1) { return std::make_shared>(f,s1); } diff --git a/src/core/separators/codac2_SepInverse.h b/src/core/separators/codac2_SepInverse.h index 8cc6cbed6..ba8c5f8c9 100644 --- a/src/core/separators/codac2_SepInverse.h +++ b/src/core/separators/codac2_SepInverse.h @@ -27,13 +27,13 @@ namespace codac2 public: - SepInverse(const AnalyticFunction::Domain>& f, const Y& y, bool with_centered_form = true) + SepInverse(const AnalyticFunction::Type>& f, const Y& y, bool with_centered_form = true) : SepCtcPair(CtcInverseNotIn(f,y,with_centered_form), CtcInverse_(f,y,with_centered_form)) { } template requires (std::is_same_v && IsSepBaseOrPtr) - SepInverse(const AnalyticFunction::Domain>& f, const S& sep_y, bool with_centered_form = true) + SepInverse(const AnalyticFunction::Type>& f, const S& sep_y, bool with_centered_form = true) : SepCtcPair(CtcInverseNotIn(f,CtcInner(sep_y),with_centered_form), CtcInverse_(f,CtcOuter(sep_y),with_centered_form)) { } }; diff --git a/src/core/separators/codac2_SepTransform.h b/src/core/separators/codac2_SepTransform.h index 17835ace8..bb08d53fa 100644 --- a/src/core/separators/codac2_SepTransform.h +++ b/src/core/separators/codac2_SepTransform.h @@ -25,7 +25,7 @@ namespace codac2 template requires IsSepBaseOrPtr - SepTransform(const S& s, const AnalyticFunction& f, const AnalyticFunction& f_inv) + SepTransform(const S& s, const AnalyticFunction& f, const AnalyticFunction& f_inv) : Sep(f.args()[0]->size() /* f must have only one arg, see following assert */), _sep(s), _ctc_inv(f, IntervalVector(f_inv.args()[0]->size())), _f(f), _f_inv(f_inv) { @@ -39,6 +39,6 @@ namespace codac2 const Collection _sep; const CtcInverse_ _ctc_inv; - const AnalyticFunction _f, _f_inv; + const AnalyticFunction _f, _f_inv; }; } \ No newline at end of file diff --git a/src/core/trajectory/codac2_SampledTrajectory.h b/src/core/trajectory/codac2_SampledTrajectory.h index 004802ee7..5b094105a 100644 --- a/src/core/trajectory/codac2_SampledTrajectory.h +++ b/src/core/trajectory/codac2_SampledTrajectory.h @@ -31,7 +31,7 @@ namespace codac2 // size is not the std::map::size() ! virtual Index size() const { - if constexpr(std::is_same_v::Domain,Interval>) // if type is scalar: int,double,etc. + if constexpr(std::is_same_v::Type,ScalarType>) return 1; else diff --git a/src/core/trajectory/codac2_TrajectoryBase.h b/src/core/trajectory/codac2_TrajectoryBase.h index 84d7b98f1..e7b8a2d99 100644 --- a/src/core/trajectory/codac2_TrajectoryBase.h +++ b/src/core/trajectory/codac2_TrajectoryBase.h @@ -12,6 +12,7 @@ #include "codac2_Interval.h" #include "codac2_Wrapper.h" #include "codac2_AnalyticFunction.h" +#include "codac2_ValueType.h" namespace codac2 { @@ -23,7 +24,7 @@ namespace codac2 { public: - using ScalarType = T; + using Type = ValueType::Type; TrajectoryBase() { } @@ -38,7 +39,7 @@ namespace codac2 auto nan_value() const { - if constexpr(std::is_same_v::Domain,Interval>) // if type is int,double,etc. + if constexpr(std::is_same_v::Type,ScalarType>) return std::numeric_limits::quiet_NaN(); else @@ -85,6 +86,6 @@ namespace codac2 } // Implementation in codac2_Trajectory_operator.h - AnalyticFunction::Domain> as_function() const; + AnalyticFunction::Type> as_function() const; }; } \ No newline at end of file diff --git a/src/core/trajectory/codac2_Trajectory_operator.h b/src/core/trajectory/codac2_Trajectory_operator.h index 1806f2e5d..47d1d428c 100644 --- a/src/core/trajectory/codac2_Trajectory_operator.h +++ b/src/core/trajectory/codac2_Trajectory_operator.h @@ -12,19 +12,21 @@ #include "codac2_analytic_operations.h" #include "codac2_SampledTrajectory.h" #include "codac2_AnalyticExprWrapper.h" +#include "codac2_ValueType.h" +#include "codac2_Wrapper.h" namespace codac2 { - template::Domain> - requires (std::is_same_v || std::is_same_v) + template + requires (std::is_same_v::Type,ScalarType> || std::is_same_v::Type,VectorType>) struct TrajectoryOp { - static D fwd(const TrajectoryBase& x1, const Interval& x2) + static typename Wrapper::Domain fwd(const TrajectoryBase& x1, const Interval& x2) { return x1(x2); } - static typename ArgWrapper::Domain fwd(const TrajectoryBase& x1, const ScalarOpValue& x2) + static typename ValueType::Type fwd(const TrajectoryBase& x1, const ScalarType& x2) { IntervalMatrix d(x1.size(),x2.da.cols()); @@ -38,7 +40,7 @@ namespace codac2 static void bwd( [[maybe_unused]] const TrajectoryBase& x1, - [[maybe_unused]] const D& y, + [[maybe_unused]] const typename Wrapper::Domain& y, [[maybe_unused]] Interval& x2) { // todo @@ -46,29 +48,25 @@ namespace codac2 }; template - class AnalyticOperationExpr,typename ArgWrapper::Domain,ScalarOpValue> - : public AnalyticExpr::Domain>, public OperationExprBase> + class AnalyticOperationExpr,typename ValueType::Type,ScalarType> + : public AnalyticExpr::Type>, public OperationExprBase> { public: - using O = typename ArgWrapper::Domain; + using O = typename ValueType::Type; AnalyticOperationExpr(const TrajectoryBase& x1, const ScalarExpr& x2) - : OperationExprBase>(x2), _x1(x1) - { } - - AnalyticOperationExpr(const AnalyticOperationExpr& e) - : OperationExprBase>(e), _x1(e._x1) + : OperationExprBase>(x2), _x1(x1) { } std::shared_ptr copy() const { - return std::make_shared,O,ScalarOpValue>>(*this); + return std::make_shared,O,ScalarType>>(*this); } void replace_expr(const ExprID& old_expr_id, const std::shared_ptr& new_expr) { - return OperationExprBase>::replace_expr(old_expr_id, new_expr); + return OperationExprBase>::replace_expr(old_expr_id, new_expr); } O fwd_eval(ValuesMap& v, Index total_input_size) const @@ -92,17 +90,17 @@ namespace codac2 const TrajectoryBase& _x1; }; - + template - AnalyticFunction::Domain> TrajectoryBase::as_function() const + AnalyticFunction::Type> TrajectoryBase::as_function() const { - using D = typename ArgWrapper::Domain; + using D = typename ValueType::Type; ScalarVar t; return {{t}, AnalyticExprWrapper(std::make_shared< AnalyticOperationExpr - , D, ScalarOpValue>>(*this,t)) + , D, ScalarType>>(*this,t)) }; } } \ No newline at end of file diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 608da895f..bb18871d7 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -207,7 +207,7 @@ void Figure2D::draw_trajectory(const SampledTrajectory& x, const StylePr draw_polyline(values,s); } -void Figure2D::draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s) +void Figure2D::draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s) { draw_trajectory(x.sampled(x.tdomain().diam()/1e4), s); } diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 0f2bf9a7e..cd5883a50 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -91,7 +91,7 @@ namespace codac2 void draw_pie(const Vector& c, const Interval& r, const Interval& theta, const StyleProperties& s = StyleProperties()); void draw_ellipse(const Vector& c, const Vector& ab, double theta, const StyleProperties& s = StyleProperties()); void draw_trajectory(const SampledTrajectory& x, const StyleProperties& s = StyleProperties()); - void draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s = StyleProperties()); + void draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s = StyleProperties()); // Robots void draw_tank(const Vector& x, float size, const StyleProperties& s = StyleProperties()); void draw_AUV(const Vector& x, float size, const StyleProperties& s = StyleProperties()); @@ -212,7 +212,7 @@ namespace codac2 selected_fig()->draw_trajectory(x,s); } - static void draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s = StyleProperties()) + static void draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s = StyleProperties()) { auto_init(); selected_fig()->draw_trajectory(x,s); From a137e9abd4dafa057b3b3d69d7b0090027380034 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 26 Dec 2024 17:45:55 +0100 Subject: [PATCH 044/126] [traj] binding for as_function() method + tests --- python/codac/core/__init__.py | 48 ++++++++++++----- .../codac2_py_AnalyticTrajectory.cpp | 1 + .../codac2_py_SampledTrajectory.cpp | 12 +++++ .../trajectory/codac2_py_TrajectoryBase.h | 8 ++- src/core/trajectory/codac2_TrajectoryBase.h | 6 +-- .../codac2_tests_SampledTrajectory.py | 53 ++++++++++++++++++- 6 files changed, 109 insertions(+), 19 deletions(-) diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index 6948719f8..e8c550b84 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -17,21 +17,27 @@ def codac_error(message): class AnalyticFunction: - def __init__(self, args, e): - if isinstance(e, (int,float,Interval,ScalarVar,ScalarExpr)): - self.f = AnalyticFunction_Scalar(args,ScalarExpr(e)) - elif isinstance(e, (Vector,IntervalVector,VectorVar,VectorExpr)): - self.f = AnalyticFunction_Vector(args,VectorExpr(e)) - elif isinstance(e, list): - lst=[] - for e_i in e: - if isinstance(e_i, (int,float,Interval,ScalarVar,ScalarExpr)): - lst.append(ScalarExpr(e_i)) - else: - codac_error("AnalyticFunction: invalid vectorial expression") - self.f = AnalyticFunction_Vector(args,lst) + def __init__(self, args, e=None): + if e: + if isinstance(e, (int,float,Interval,ScalarVar,ScalarExpr)): + self.f = AnalyticFunction_Scalar(args,ScalarExpr(e)) + elif isinstance(e, (Vector,IntervalVector,VectorVar,VectorExpr)): + self.f = AnalyticFunction_Vector(args,VectorExpr(e)) + elif isinstance(e, list): + lst=[] + for e_i in e: + if isinstance(e_i, (int,float,Interval,ScalarVar,ScalarExpr)): + lst.append(ScalarExpr(e_i)) + else: + codac_error("AnalyticFunction: invalid vectorial expression") + self.f = AnalyticFunction_Vector(args,lst) + else: + codac_error("AnalyticFunction: can only build functions from scalar or vector expressions") else: - codac_error("AnalyticFunction: can only build functions from scalar or vector expressions") + if isinstance(args, (AnalyticFunction_Scalar,AnalyticFunction_Vector)): + self.f = args + else: + codac_error("AnalyticFunction: invalid function argument") def input_size(self): return self.f.input_size() @@ -279,6 +285,9 @@ def sampled(self, dt): def primitive(self, y0, t): return SampledTrajectory(self.traj.primitive(y0, t)) + def as_function(self): + return AnalyticFunction(self.traj.as_function()) + # Methods from AnalyticTrajectory: # none @@ -296,6 +305,14 @@ def __init__(self, m): self.traj = SampledTrajectory_Vector(m) else: codac_error("SampledTrajectory: can only build this trajectory from maps of scalar or vector values") + + # Methods from std::map: + + def __setitem__(self, t, y): + self.traj[t] = y + + def __getitem__(self, t): + return self.traj[t] # Methods from TrajectoryBase: @@ -326,6 +343,9 @@ def sampled(self, *args): def primitive(self, y0, t): return SampledTrajectory(self.traj.primitive(y0, t)) + def as_function(self): + return AnalyticFunction(self.traj.as_function()) + # Methods from SampledTrajectory: def nb_samples(self): diff --git a/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp b/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp index c3a49279a..7c05e51c3 100644 --- a/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp +++ b/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp @@ -16,6 +16,7 @@ #include "codac2_py_AnalyticTrajectory_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_TrajectoryBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_TrajectoryBase.h" +#include "codac2_Trajectory_operator.h" #include "codac2_py_doc.h" using namespace std; diff --git a/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp b/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp index b290da303..ca4b45d22 100644 --- a/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp +++ b/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp @@ -15,6 +15,7 @@ #include "codac2_py_SampledTrajectory_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_TrajectoryBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_TrajectoryBase.h" +#include "codac2_Trajectory_operator.h" #include "codac2_py_doc.h" using namespace std; @@ -47,6 +48,17 @@ void _export_SampledTrajectory(py::module& m, const string& class_name) SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY_T_SAMPLED_DOUBLE_BOOL_CONST, "dt"_a, "keep_original_values"_a) + .def("__getitem__", [](const SampledTrajectory& x, Index_type index) -> const T& + { + matlab::test_integer(index); + return x.at(matlab::input_index(index)); + }, py::return_value_policy::reference_internal) + + .def("__setitem__", [](SampledTrajectory& x, Index_type index, const T& a) + { + matlab::test_integer(index); + x[matlab::input_index(index)] = a; + }) ; } diff --git a/python/src/core/trajectory/codac2_py_TrajectoryBase.h b/python/src/core/trajectory/codac2_py_TrajectoryBase.h index 9c91c5e98..442f51ac5 100644 --- a/python/src/core/trajectory/codac2_py_TrajectoryBase.h +++ b/python/src/core/trajectory/codac2_py_TrajectoryBase.h @@ -84,12 +84,18 @@ void export_TrajectoryBase(py::class_& pyclass) VIRTUAL_SAMPLEDTRAJECTORY_T_TRAJECTORYBASE_T_SAMPLED_DOUBLE_CONST, "dt"_a) - .def("primitive", [](const S& x, const typename S::Type::Scalar& y0, double dt) + .def("primitive", [](const S& x, const typename S::TrajType::Scalar& y0, double dt) { return x.primitive(y0,dt); }, SAMPLEDTRAJECTORY_T_TRAJECTORYBASE_T_PRIMITIVE_CONST_T_REF_DOUBLE_CONST, "y0"_a, "dt"_a) + .def("as_function", [](const S& x) + { + return x.as_function(); + }, + ANALYTICFUNCTION_TYPENAME_VALUETYPE_T_TYPE_TRAJECTORYBASE_T_AS_FUNCTION_CONST) + ; } \ No newline at end of file diff --git a/src/core/trajectory/codac2_TrajectoryBase.h b/src/core/trajectory/codac2_TrajectoryBase.h index e7b8a2d99..7626d037a 100644 --- a/src/core/trajectory/codac2_TrajectoryBase.h +++ b/src/core/trajectory/codac2_TrajectoryBase.h @@ -24,7 +24,7 @@ namespace codac2 { public: - using Type = ValueType::Type; + using TrajType = ValueType::Type; TrajectoryBase() { } @@ -39,7 +39,7 @@ namespace codac2 auto nan_value() const { - if constexpr(std::is_same_v::Type,ScalarType>) + if constexpr(std::is_same_v) return std::numeric_limits::quiet_NaN(); else @@ -86,6 +86,6 @@ namespace codac2 } // Implementation in codac2_Trajectory_operator.h - AnalyticFunction::Type> as_function() const; + AnalyticFunction as_function() const; }; } \ No newline at end of file diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.py b/tests/core/trajectory/codac2_tests_SampledTrajectory.py index 62fb8e823..29b30f328 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.py +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.py @@ -9,7 +9,7 @@ import unittest from codac import * -import sys +import sys, math class TestSampledTrajectory(unittest.TestCase): @@ -58,5 +58,56 @@ def tests_SampledTrajectory(self): #DefaultView.draw_trajectory(x, Color.blue()) #DefaultView.draw_trajectory(x_sampled, Color.red()) + # SampledTrajectory as operator (1d case) + + t = ScalarVar() + f = AnalyticFunction( + [t], cos(t) + ) + analytic_traj = AnalyticTrajectory(f, [-math.pi,math.pi]) + sampled_traj = analytic_traj.sampled(1e-2) + g = sampled_traj.as_function() + + h = AnalyticFunction( + [t], g(t) + ) + + t_ = -math.pi + while t_ < math.pi: + self.assertTrue(Approx(h.real_eval(t_)) == math.cos(t_)) + t_=t_+1e-2 + + # SampledTrajectory as operator (nd case) + + t = ScalarVar() + f = AnalyticFunction( + [t], + vec(2*cos(t),sin(2*t)) + ) + + analytic_traj = AnalyticTrajectory(f, [0,5]) + sampled_traj = analytic_traj.sampled(1e-2) + g = sampled_traj.as_function() + + h = AnalyticFunction( + [t], + g(t) + ) + + t_ = 0 + while t_ < 5: + self.assertTrue(Approx(h.real_eval(t_)) == Vector([2*math.cos(t_),math.sin(2*t_)])) + t_=t_+1e-2 + + h = AnalyticFunction( + [t], + [ g(t)[0],g(t)[1] ] + ) + + t_ = 0 + while t_ < 5: + self.assertTrue(Approx(h.real_eval(t_)) == Vector([2*math.cos(t_),math.sin(2*t_)])) + t_=t_+1e-2 + if __name__ == '__main__': unittest.main() \ No newline at end of file From 70ca2dd97f7bacc73f50bd87ed58727ca39378df Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 26 Dec 2024 18:42:52 +0100 Subject: [PATCH 045/126] [sep] simplifying binding of SepInverse --- python/codac/core/__init__.py | 20 +---------- python/src/core/codac2_py_core.cpp | 3 +- .../analytic/codac2_py_AnalyticFunction.h | 14 ++++++++ .../core/separators/codac2_py_SepInverse.h | 34 ++++++++++++++----- src/core/functions/set/codac2_set_operators.h | 2 +- src/core/separators/codac2_SepInverse.h | 18 ++++++---- .../separators/codac2_tests_SepCartProd.cpp | 4 +-- .../separators/codac2_tests_SepInverse.cpp | 4 +-- .../core/separators/codac2_tests_SepProj.cpp | 2 +- .../separators/codac2_tests_SepTransform.cpp | 2 +- 10 files changed, 59 insertions(+), 44 deletions(-) diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index e8c550b84..3ee1b8547 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -133,24 +133,6 @@ def copy(self): return self.c.copy() -class SepInverse(Sep): - - def __init__(self, f, y, with_centered_form = True): - Sep.__init__(self, f.input_size()) - if isinstance(f.f, AnalyticFunction_Scalar): - self.s = SepInverse_Interval(f.f,Interval(y),with_centered_form) - elif isinstance(f.f, AnalyticFunction_Vector): - self.s = SepInverse_IntervalVector(f.f,IntervalVector(y),with_centered_form) - else: - codac_error("SepInverse: can only build SepInverse from scalar or vector functions") - - def separate(self,x): - return self.s.separate(x) - - def copy(self): - return super().copy() - - class Approx: def __init__(self, x, eps = float_info.epsilon*10): @@ -209,7 +191,7 @@ def cart_prod(*args): mode = 1 lst.append(arg) - elif isinstance(arg, Sep): + elif isinstance(arg, (Sep,SepBase)): if mode != -1 and mode != 2: codac_error("cart_prod: invalid input arguments, was expecting a " + mode_str[mode] + ", got a separator") mode = 2 diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index 977560bbc..50fb4fb57 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -214,8 +214,7 @@ PYBIND11_MODULE(_core, m) export_SepCtcBoundary(m,py_sep); export_SepCtcPair(m,py_sep); export_SepInter(m,py_sep); - export_SepInverse(m,"SepInverse_Interval",py_sep); - export_SepInverse(m,"SepInverse_IntervalVector",py_sep); + export_SepInverse(m,py_sep); export_SepNot(m,py_sep); export_SepPolygon(m,py_sep); export_SepProj(m,py_sep); diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index 8df9ce3ff..f15069498 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -98,6 +98,20 @@ AnalyticExprWrapper pyobj_to_ScalarExpr(const py::object& obj) return { nullptr }; } +template +AnalyticFunction cast_to_AnalyticFunction(const py::object& f) +{ + py::object f_ = f.attr("f"); + + if(!f_) + assert_release("cast_function: py::object f has no attribute named 'f'"); + + if(!py::isinstance>(f_)) + assert_release("cast_function: provided analytic function has incorrect type"); + + return f_.cast>(); +} + std::shared_ptr pyobj_to_ExprBase(const py::object& obj) { if(obj) diff --git a/python/src/core/separators/codac2_py_SepInverse.h b/python/src/core/separators/codac2_py_SepInverse.h index d6fcca5e4..0ca6a4cf5 100644 --- a/python/src/core/separators/codac2_py_SepInverse.h +++ b/python/src/core/separators/codac2_py_SepInverse.h @@ -15,6 +15,7 @@ #include "codac2_py_Sep.h" #include "codac2_py_SepInverse_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_SepCtcPair_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_AnalyticFunction.h" using namespace std; using namespace codac2; @@ -22,27 +23,42 @@ namespace py = pybind11; using namespace pybind11::literals; template -void export_SepInverse(py::module& m, const std::string& export_name, py::class_& pysep) +void export_SepInverse_type(py::class_& exported) { - using D = typename T::Domain; - py::class_> exported(m, export_name.c_str(), pysep, SEPINVERSE_MAIN); - exported - .def(py::init&,const D&,bool>(), - SEPINVERSE_Y_SEPINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CONST_Y_REF_BOOL, + .def(py::init( + [](const py::object& f, const typename T::Domain& y, bool with_centered_form) + { + return std::make_unique(cast_to_AnalyticFunction(f), y, with_centered_form); + } + ), + SEPINVERSE_SEPINVERSE_CONST_ANALYTICFUNCTION_T_REF_CONST_TYPENAME_T_DOMAIN_REF_BOOL, "f"_a, "y"_a, "with_centered_form"_a = true); if constexpr(std::is_same_v) // separators only associated with interval vectors { exported - .def(py::init&,const pySep&,bool>(), - SEPINVERSE_Y_SEPINVERSE_CONST_ANALYTICFUNCTION_TYPENAME_VALUETYPE_Y_TYPE_REF_CONST_S_REF_BOOL, + .def(py::init( + [](const py::object& f, const pySep& s, bool with_centered_form) + { + return std::make_unique(cast_to_AnalyticFunction(f), s, with_centered_form); + } + ), + SEPINVERSE_SEPINVERSE_CONST_ANALYTICFUNCTION_T_REF_CONST_S_REF_BOOL, "f"_a, "s"_a, "with_centered_form"_a = true); } +} + +void export_SepInverse(py::module& m, py::class_& pysep) +{ + py::class_ exported(m, "SepInverse", pysep, SEPINVERSE_MAIN); + + export_SepInverse_type(exported); + export_SepInverse_type(exported); exported - .def("separate", &SepInverse::separate, + .def("separate", &SepInverse::separate, BOXPAIR_SEPCTCPAIR_SEPARATE_CONST_INTERVALVECTOR_REF_CONST, "x"_a) ; diff --git a/src/core/functions/set/codac2_set_operators.h b/src/core/functions/set/codac2_set_operators.h index c897b1aad..f8c29d6bf 100644 --- a/src/core/functions/set/codac2_set_operators.h +++ b/src/core/functions/set/codac2_set_operators.h @@ -101,7 +101,7 @@ namespace codac2 static std::shared_ptr create_sep(const AnalyticFunction& f, const std::shared_ptr& s1) { - return std::make_shared>(f,s1); + return std::make_shared(f,s1); } }; diff --git a/src/core/separators/codac2_SepInverse.h b/src/core/separators/codac2_SepInverse.h index ba8c5f8c9..a0879cc56 100644 --- a/src/core/separators/codac2_SepInverse.h +++ b/src/core/separators/codac2_SepInverse.h @@ -20,21 +20,25 @@ namespace codac2 { - template class SepInverse : public SepCtcPair { using X = IntervalVector; public: - SepInverse(const AnalyticFunction::Type>& f, const Y& y, bool with_centered_form = true) - : SepCtcPair(CtcInverseNotIn(f,y,with_centered_form), CtcInverse_(f,y,with_centered_form)) + template + SepInverse(const AnalyticFunction& f, const typename T::Domain& y, bool with_centered_form = true) + : SepCtcPair( + CtcInverseNotIn(f,y,with_centered_form), + CtcInverse_(f,y,with_centered_form)) { } - template - requires (std::is_same_v && IsSepBaseOrPtr) - SepInverse(const AnalyticFunction::Type>& f, const S& sep_y, bool with_centered_form = true) - : SepCtcPair(CtcInverseNotIn(f,CtcInner(sep_y),with_centered_form), CtcInverse_(f,CtcOuter(sep_y),with_centered_form)) + template + requires (std::is_same_v && IsSepBaseOrPtr) + SepInverse(const AnalyticFunction& f, const S& sep_y, bool with_centered_form = true) + : SepCtcPair( + CtcInverseNotIn(f,CtcInner(sep_y),with_centered_form), + CtcInverse_(f,CtcOuter(sep_y),with_centered_form)) { } }; } \ No newline at end of file diff --git a/tests/core/separators/codac2_tests_SepCartProd.cpp b/tests/core/separators/codac2_tests_SepCartProd.cpp index 15a76acce..96a53a054 100644 --- a/tests/core/separators/codac2_tests_SepCartProd.cpp +++ b/tests/core/separators/codac2_tests_SepCartProd.cpp @@ -18,8 +18,8 @@ TEST_CASE("SepCartProd") { { VectorVar v(1); - SepInverse s1(AnalyticFunction({v}, v), IntervalVector({{-1,1}})); - SepInverse s2(AnalyticFunction({v}, v), IntervalVector({{5,6}})); + SepInverse s1(AnalyticFunction({v}, v), IntervalVector({{-1,1}})); + SepInverse s2(AnalyticFunction({v}, v), IntervalVector({{5,6}})); { IntervalVector x({{0,8},{5.5,oo}}); diff --git a/tests/core/separators/codac2_tests_SepInverse.cpp b/tests/core/separators/codac2_tests_SepInverse.cpp index 6c55c64a1..71ee8fb8e 100644 --- a/tests/core/separators/codac2_tests_SepInverse.cpp +++ b/tests/core/separators/codac2_tests_SepInverse.cpp @@ -20,7 +20,7 @@ TEST_CASE("SepInverse") { VectorVar x(2); AnalyticFunction f { {x}, vec(x[0],sqr(x[0]/7.)+sqr(x[1]/3.)) }; - SepInverse s(f, {{0,oo},{-oo,1}}); + SepInverse s(f, {{0,oo},{-oo,1}}); //pave(IntervalVector({{-10,10},{-10,10}}), s, 0.1); @@ -79,7 +79,7 @@ TEST_CASE("SepInverse - other test") { VectorVar x(2); AnalyticFunction f { {x}, vec(sqr(x[0])+sqr(x[1])) }; - SepInverse s(f, {{0,1}}); + SepInverse s(f, {{0,1}}); //pave({{-5,5},{-5,5}}, s, 0.01); diff --git a/tests/core/separators/codac2_tests_SepProj.cpp b/tests/core/separators/codac2_tests_SepProj.cpp index 55309e3b8..148499147 100644 --- a/tests/core/separators/codac2_tests_SepProj.cpp +++ b/tests/core/separators/codac2_tests_SepProj.cpp @@ -22,7 +22,7 @@ TEST_CASE("SepProj") { VectorVar x(3); AnalyticFunction f_ellipsoid({x}, 2*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+sqr(x[1])+sqr(x[2])); - SepInverse sep_ellipsoid(f_ellipsoid, {0.7,1}); + SepInverse sep_ellipsoid(f_ellipsoid, {0.7,1}); SepProj sep_proj(sep_ellipsoid, {0,1}, {{0.1,0.2}}); // todo: test with SepProj sep_proj(sep_ellipsoid, {0,1}, {{-oo,oo}}); diff --git a/tests/core/separators/codac2_tests_SepTransform.cpp b/tests/core/separators/codac2_tests_SepTransform.cpp index 2f4b4d60a..b3a162562 100644 --- a/tests/core/separators/codac2_tests_SepTransform.cpp +++ b/tests/core/separators/codac2_tests_SepTransform.cpp @@ -20,7 +20,7 @@ TEST_CASE("SepTransform") { { VectorVar x(2); - SepInverse s1(AnalyticFunction({x}, sqr(x[0])+sqr(x[1])), Interval(0,1)); + SepInverse s1(AnalyticFunction({x}, sqr(x[0])+sqr(x[1])), Interval(0,1)); SepTransform s2(s1, AnalyticFunction({x}, vec(x[0]+2,x[1]+2)), AnalyticFunction({x}, vec(x[0]-2,x[1]-2))); From f745eabab6aef238a158893a57f218124d4c183d Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 26 Dec 2024 18:43:52 +0100 Subject: [PATCH 046/126] [ex] added example "explored_area" (c++/py) for using trajectories in functions --- examples/04_explored_area/CMakeLists.txt | 40 ++++++++++++++++++++++++ examples/04_explored_area/main.cpp | 38 ++++++++++++++++++++++ examples/04_explored_area/main.py | 33 +++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 examples/04_explored_area/CMakeLists.txt create mode 100644 examples/04_explored_area/main.cpp create mode 100644 examples/04_explored_area/main.py diff --git a/examples/04_explored_area/CMakeLists.txt b/examples/04_explored_area/CMakeLists.txt new file mode 100644 index 000000000..314b49ffc --- /dev/null +++ b/examples/04_explored_area/CMakeLists.txt @@ -0,0 +1,40 @@ +# ================================================================== +# codac / basics example - cmake configuration file +# ================================================================== + + cmake_minimum_required(VERSION 3.0.2) + project(codac_example LANGUAGES CXX) + + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Adding IBEX + + # In case you installed IBEX in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option. + # set(CMAKE_PREFIX_PATH "~/ibex-lib/build_install") + + find_package(IBEX REQUIRED) + ibex_init_common() # IBEX should have installed this function + message(STATUS "Found IBEX version ${IBEX_VERSION}") + +# Adding Codac + + # In case you installed Codac in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option. + # set(CMAKE_PREFIX_PATH "~/codac/build_install") + + find_package(CODAC REQUIRED) + message(STATUS "Found Codac version ${CODAC_VERSION}") + +# Compilation + + if(FAST_RELEASE) + add_compile_definitions(FAST_RELEASE) + message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") + endif() + + 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}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file diff --git a/examples/04_explored_area/main.cpp b/examples/04_explored_area/main.cpp new file mode 100644 index 000000000..7271db870 --- /dev/null +++ b/examples/04_explored_area/main.cpp @@ -0,0 +1,38 @@ +// Example: A sampled trajectory, 'sampled_f' (composed of time-stamped positions with +// linear interpolation between them), is first obtained by discretizing an analytical +// expression (the function 'f,' which represents a Lissajous curve) and then appending +// an additional position. This trajectory is subsequently used in another analytical +// expression (function 'h'). The projection of an inverse separator is then employed +// to validate the result. + +#include + +using namespace codac2; + +int main() +{ + ScalarVar t; + AnalyticFunction f { + {t}, + { 2*cos(t), sin(2*t) } + }; + + Interval tdomain(0,5); + auto sampled_f = AnalyticTrajectory(f,tdomain).sampled(0.8); + sampled_f[6] = {0,-1}; + + VectorVar w(3); + auto g = sampled_f.as_function(); + AnalyticFunction h { + {w}, + sqr(w[0]-g(w[2])[0])+sqr(w[1]-g(w[2])[1]) + }; + + SepInverse s_h(h, {0,0.1}); + SepProj s_projh(s_h, {0,1}, {sampled_f.tdomain()}); + + DefaultView::set_window_properties({75,75},{700,700}); + draw_while_paving({{-3,3},{-2,2}}, s_projh, 5e-2); + DefaultView::draw_trajectory(sampled_f); + DefaultView::draw_trajectory(AnalyticTrajectory(f,tdomain), Color::dark_gray()); +} \ No newline at end of file diff --git a/examples/04_explored_area/main.py b/examples/04_explored_area/main.py new file mode 100644 index 000000000..384816546 --- /dev/null +++ b/examples/04_explored_area/main.py @@ -0,0 +1,33 @@ +from codac import * + +# Example: A sampled trajectory, 'sampled_f' (composed of time-stamped positions with +# linear interpolation between them), is first obtained by discretizing an analytical +# expression (the function 'f,' which represents a Lissajous curve) and then appending +# an additional position. This trajectory is subsequently used in another analytical +# expression (function 'h'). The projection of an inverse separator is then employed +# to validate the result. + +t = ScalarVar() +f = AnalyticFunction( + [t], + [ 2*cos(t), sin(2*t) ] +) + +tdomain = [0,5] +sampled_f = AnalyticTrajectory(f,tdomain).sampled(0.8) +sampled_f[6] = [0,-1] + +w = VectorVar(3) +g = sampled_f.as_function() +h = AnalyticFunction( + [w], + sqr(w[0]-g(w[2])[0])+sqr(w[1]-g(w[2])[1]) +) + +s_h = SepInverse(h, [0,0.1]) +s_projh = SepProj(s_h, [0,1], [sampled_f.tdomain()]) + +DefaultView.set_window_properties([75,75],[700,700]) +draw_while_paving([[-3,3],[-2,2]], s_projh, 5e-2) +DefaultView.draw_trajectory(sampled_f) +DefaultView.draw_trajectory(AnalyticTrajectory(f,tdomain), Color.dark_gray()) \ No newline at end of file From 2a0391a5254dd5318991314cf2c5a25cd3ee8816 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 27 Dec 2024 17:47:12 +0100 Subject: [PATCH 047/126] [pr] minor corrections --- tests/core/trajectory/codac2_tests_SampledTrajectory.cpp | 4 ++-- tests/core/trajectory/codac2_tests_SampledTrajectory.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp index ab2695cb9..008cbd644 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp @@ -66,13 +66,13 @@ TEST_CASE("SampledTrajectory as operator (1d case)") { ScalarVar t; AnalyticFunction f { {t}, cos(t) }; - AnalyticTrajectory analytic_traj(f, {-M_PI,M_PI}); + AnalyticTrajectory analytic_traj(f, {-pi,pi}); auto sampled_traj = analytic_traj.sampled(1e-2); auto g = sampled_traj.as_function(); AnalyticFunction h { {t}, g(t) }; - for(double t = -M_PI ; t < M_PI ; t+=1e-2) + for(double t = -pi ; t < pi ; t+=1e-2) CHECK(Approx(h.real_eval(t)) == cos(t)); } diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.py b/tests/core/trajectory/codac2_tests_SampledTrajectory.py index 29b30f328..7d3cdf910 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.py +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.py @@ -74,7 +74,7 @@ def tests_SampledTrajectory(self): t_ = -math.pi while t_ < math.pi: - self.assertTrue(Approx(h.real_eval(t_)) == math.cos(t_)) + self.assertTrue(Approx(h.real_eval(t_),1e-8) == math.cos(t_)) t_=t_+1e-2 # SampledTrajectory as operator (nd case) From 834e37299655e67db5327c7dd86ba62d9874b805 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 27 Dec 2024 18:09:53 +0100 Subject: [PATCH 048/126] [math] using pi from GAOL as default value --- src/core/tools/codac2_math.h | 5 +- .../3rd/vibes/codac2_Figure2D_VIBes.cpp | 8 ++-- src/graphics/figures/codac2_Figure2D.cpp | 2 +- .../interval/codac2_tests_Interval_bwd.cpp | 48 +++++++++---------- .../codac2_tests_AnalyticFunction.cpp | 36 +++++++------- .../codac2_tests_SampledTrajectory.cpp | 1 + 6 files changed, 51 insertions(+), 49 deletions(-) diff --git a/src/core/tools/codac2_math.h b/src/core/tools/codac2_math.h index ba4cae144..9094dc9e3 100644 --- a/src/core/tools/codac2_math.h +++ b/src/core/tools/codac2_math.h @@ -13,5 +13,8 @@ namespace codac2 { - constexpr double pi = std::numbers::pi; // Need C++20 + // As long as GAOL defines pi in common namespace, + // we use it as default pi value instead of the pi + // from the standard library. + //constexpr double pi = std::numbers::pi; // Need C++20 } \ No newline at end of file diff --git a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp index 582e5a975..bdeb6c363 100644 --- a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp +++ b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp @@ -118,28 +118,28 @@ void Figure2D_VIBes::draw_pie(const Vector& c, const Interval& r, const Interval assert(_fig.size() <= c.size()); assert(r.lb() >= 0.); // Corrected a bug in VIBEs in case of r=[..,oo] (the pie disappears when zoomed in) - vibes::drawPie(c[i()],c[j()], r.lb(),(r.ub()>1e5?1e5:r.ub()), 180.*theta.lb()/codac2::pi,180.*theta.ub()/codac2::pi, to_vibes_style(s), _params); + vibes::drawPie(c[i()],c[j()], r.lb(),(r.ub()>1e5?1e5:r.ub()), 180.*theta.lb()/pi,180.*theta.ub()/pi, to_vibes_style(s), _params); } void Figure2D_VIBes::draw_ellipse(const Vector& c, const Vector& ab, double theta, const StyleProperties& s) { assert(c.size() == 2); assert(ab.size() == 2); - vibes::drawEllipse(c[0],c[1], ab[0],ab[1], 180.*theta/codac2::pi, to_vibes_style(s), _params); + vibes::drawEllipse(c[0],c[1], ab[0],ab[1], 180.*theta/pi, to_vibes_style(s), _params); } void Figure2D_VIBes::draw_tank(const Vector& x, float size, const StyleProperties& s) { assert(_fig.size() <= x.size()+1); assert(j()+1 < x.size()); - vibes::drawTank(x[i()],x[j()],180.*x[j()+1]/codac2::pi, size, to_vibes_style(s), _params); + vibes::drawTank(x[i()],x[j()],180.*x[j()+1]/pi, size, to_vibes_style(s), _params); } void Figure2D_VIBes::draw_AUV(const Vector& x, float size, const StyleProperties& s) { assert(_fig.size() <= x.size()+1); assert(j()+1 < x.size()); - vibes::drawAUV(x[i()],x[j()],180.*x[j()+1]/codac2::pi, size, to_vibes_style(s), _params); + vibes::drawAUV(x[i()],x[j()],180.*x[j()+1]/pi, size, to_vibes_style(s), _params); } string Figure2D_VIBes::to_vibes_style(const StyleProperties& s) diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index bb18871d7..0320fd715 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -178,7 +178,7 @@ void Figure2D::draw_pie(const Vector& c, const Interval& r, const Interval& thet Interval theta_(theta); if(theta.is_unbounded()) - theta_ = Interval(0,2.*codac2::pi); + theta_ = Interval(0,2.*pi); Interval r_(r); if(r.is_unbounded()) diff --git a/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp b/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp index 4f2715c72..dbfdac1e8 100644 --- a/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp +++ b/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp @@ -22,8 +22,6 @@ using namespace std; using namespace codac2; -#define PI codac2::pi - const double MAX_DOUBLE = std::numeric_limits::max(); void CHECK_bwd_trigo(const Interval& y, const Interval& x, const Interval& expected_x) @@ -263,25 +261,25 @@ TEST_CASE("Interval bwd operations") Interval a, y; - a = Interval(PI/6.,PI/3.); y = Interval(.5,10.); x = Interval(.5,2.); + a = Interval(pi/6.,pi/3.); y = Interval(.5,10.); x = Interval(.5,2.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(.5,2.*sqrt(3.))); CHECK(Approx(x) == Interval(.5,2.)); - a = Interval(PI/6.,PI/3.); y = Interval(.5,2.); x = Interval(.5,10.); + a = Interval(pi/6.,pi/3.); y = Interval(.5,2.); x = Interval(.5,10.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(.5,2.)); CHECK(Approx(x) == Interval(.5,2.*sqrt(3.))); - a = Interval(-PI/4.,PI/4.); y = Interval(1.,2.); x = Interval(.5,2.); + a = Interval(-pi/4.,pi/4.); y = Interval(1.,2.); x = Interval(.5,2.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(1.,2.)); CHECK(Approx(x) == Interval(1.,2.)); - a = Interval(-PI/2.,0.); y = Interval(.5,2.); x = Interval(.5,10.); + a = Interval(-pi/2.,0.); y = Interval(.5,2.); x = Interval(.5,10.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval::empty()); CHECK(Approx(x) == Interval::empty()); - a = Interval(2.*PI,3.*PI); y = Interval(-.5,2.); x = Interval(.5,10.); + a = Interval(2.*pi,3.*pi); y = Interval(-.5,2.); x = Interval(.5,10.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval::empty()); CHECK(Approx(x) == Interval::empty()); - a = Interval(2*PI/3.,5.*PI/6.); y = Interval(0.,100.); x = Interval(-20.,-sqrt(3.)/2.); + a = Interval(2*pi/3.,5.*pi/6.); y = Interval(0.,100.); x = Interval(-20.,-sqrt(3.)/2.); bwd_atan2(a,y,x); CHECK(Approx(y,1e-10) == Interval(.5,20.*sqrt(3.))); CHECK(Approx(x) == Interval(-20.,-sqrt(3.)/2)); - a = Interval(-3*PI/4.,-2*PI/3.); y = Interval(-sqrt(3.)/2.,2.); x = Interval(-sqrt(2.)/2.,0.); + a = Interval(-3*pi/4.,-2*pi/3.); y = Interval(-sqrt(3.)/2.,2.); x = Interval(-sqrt(2.)/2.,0.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(-sqrt(3.)/2.,0.)); CHECK(Approx(x) == Interval(-sqrt(2.)/2.,0.)); - a = Interval(-3*PI/4.,-2*PI/3.); y = Interval(-sqrt(3.)/2.,2.); x = Interval(-1.,-.5); + a = Interval(-3*pi/4.,-2*pi/3.); y = Interval(-sqrt(3.)/2.,2.); x = Interval(-1.,-.5); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(-sqrt(3.)/2.,-.5)); CHECK(Approx(x) == Interval(-sqrt(3.)/2.,-.5)); - a = Interval(-3*PI/4.,-PI/4.); y = Interval(-5.,-.5); x = Interval(-oo,oo); + a = Interval(-3*pi/4.,-pi/4.); y = Interval(-5.,-.5); x = Interval(-oo,oo); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(-5.,-.5)); CHECK(Approx(x) == Interval(-5.,5.)); - a = Interval(-PI/3.,PI/4.); y = Interval(-oo,oo); x = Interval(sqrt(3.)/2.); + a = Interval(-pi/3.,pi/4.); y = Interval(-oo,oo); x = Interval(sqrt(3.)/2.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(-1.5,sqrt(3.)/2.)); CHECK(Approx(x) == Interval(sqrt(3.)/2.)); a = Interval::half_pi(); y = Interval(1); x = 0.; bwd_atan2(a,y,x); CHECK(Approx(y) == 1.); CHECK(Approx(x) == 0.); @@ -294,15 +292,15 @@ TEST_CASE("Interval bwd operations") x = Interval(-1,5); bwd_sqrt(Interval(2,5), x); CHECK(x == Interval(4,5)); x = Interval(-oo,oo); bwd_sqrt(Interval(-4,-2), x); CHECK(x == Interval::empty()); - x = Interval(-1.,3.); bwd_atan(Interval(0.,PI/6.),x); CHECK(x == tan(Interval(0.,PI/6.))); - x = Interval(0,5*PI/2.0); bwd_atan(Interval(-PI,1.5),x); CHECK(x == Interval(0,5*PI/2.0)); - x = Interval(.2,.5); bwd_atan(Interval(0.,PI/6.),x); CHECK(x == Interval(.2,.5)); - x = Interval(-100,100); bwd_atan(Interval(-PI/2-0.1,PI/2+0.1),x); CHECK(x == Interval(-100,100)); - x = Interval(-100,100); bwd_atan(Interval(PI/2+0.1,PI),x); CHECK(x == Interval::empty()); - x = Interval(-100,100); bwd_atan(Interval(-PI,-PI/2-0.1),x); CHECK(x == Interval::empty()); + x = Interval(-1.,3.); bwd_atan(Interval(0.,pi/6.),x); CHECK(x == tan(Interval(0.,pi/6.))); + x = Interval(0,5*pi/2.0); bwd_atan(Interval(-pi,1.5),x); CHECK(x == Interval(0,5*pi/2.0)); + x = Interval(.2,.5); bwd_atan(Interval(0.,pi/6.),x); CHECK(x == Interval(.2,.5)); + x = Interval(-100,100); bwd_atan(Interval(-pi/2-0.1,pi/2+0.1),x); CHECK(x == Interval(-100,100)); + x = Interval(-100,100); bwd_atan(Interval(pi/2+0.1,pi),x); CHECK(x == Interval::empty()); + x = Interval(-100,100); bwd_atan(Interval(-pi,-pi/2-0.1),x); CHECK(x == Interval::empty()); - x = Interval(-oo,oo); bwd_atan(Interval(-PI/4,PI/2.), x); CHECK(x.lb() == -1); CHECK(x.ub() > 1000); - x = Interval(-oo,oo); bwd_atan(Interval(-PI/2,PI/4.), x); CHECK(x.ub() == +1); CHECK(x.lb() < -1000); + x = Interval(-oo,oo); bwd_atan(Interval(-pi/4,pi/2.), x); CHECK(x.lb() == -1); CHECK(x.ub() > 1000); + x = Interval(-oo,oo); bwd_atan(Interval(-pi/2,pi/4.), x); CHECK(x.ub() == +1); CHECK(x.lb() < -1000); CHECK_bwd_add(Interval(1,3),Interval(1,2),Interval(-10,5),Interval(1,2),Interval(-1,2)); CHECK_bwd_add(Interval::empty(),Interval(0.1,2.0),Interval(-10,2),Interval::empty(),Interval::empty()); @@ -319,11 +317,11 @@ TEST_CASE("Interval bwd operations") CHECK_bwd_imod(3.,Interval(3.,5.),Interval(1.,2.),Interval(4.,5.),Interval(1.,2.)); CHECK_bwd_imod(2.,Interval(7.,8.),Interval(.5,2.),Interval(7.,8.),Interval(1.,2.)); CHECK_bwd_imod(2.,Interval(7.,8.),Interval(0.,2.),Interval(7.,8.),Interval(0.,2.)); - CHECK_bwd_imod(2.*PI,Interval(2.*PI,3.*PI),Interval(PI/6,PI/2.),Interval(13.*PI/6.,5.*PI/2.),Interval(PI/6,PI/2.)); - CHECK_bwd_imod(2.*PI,Interval(3.*PI,4.*PI),Interval(PI/3,PI/2.),Interval::empty(),Interval::empty()); - CHECK_bwd_imod(2.*PI,Interval(3.*PI,4.*PI),Interval(0.,PI/2.),Interval(4*PI),Interval(0.)); - CHECK_bwd_imod(2.*PI,Interval(2.*PI,4.*PI),Interval(-PI/6,PI/2.),Interval(2.*PI,4.*PI),Interval(-PI/6,PI/2.)); - CHECK_bwd_imod(2.*PI,Interval(7.*PI/4.,8.*PI/3),Interval(-PI/2,PI/2.),Interval(7.*PI/4.,5.*PI/2.),Interval(-PI/4,PI/2.)); + CHECK_bwd_imod(2.*pi,Interval(2.*pi,3.*pi),Interval(pi/6,pi/2.),Interval(13.*pi/6.,5.*pi/2.),Interval(pi/6,pi/2.)); + CHECK_bwd_imod(2.*pi,Interval(3.*pi,4.*pi),Interval(pi/3,pi/2.),Interval::empty(),Interval::empty()); + CHECK_bwd_imod(2.*pi,Interval(3.*pi,4.*pi),Interval(0.,pi/2.),Interval(4*pi),Interval(0.)); + CHECK_bwd_imod(2.*pi,Interval(2.*pi,4.*pi),Interval(-pi/6,pi/2.),Interval(2.*pi,4.*pi),Interval(-pi/6,pi/2.)); + CHECK_bwd_imod(2.*pi,Interval(7.*pi/4.,8.*pi/3),Interval(-pi/2,pi/2.),Interval(7.*pi/4.,5.*pi/2.),Interval(-pi/4,pi/2.)); x = Interval(-oo,oo); bwd_floor(Interval::empty(),x); CHECK(x == Interval::empty()); x = Interval(-oo,-0.000001); bwd_floor(Interval(-oo,-1),x); CHECK(x == Interval(-oo,-0.000001)); diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp index 47abb017d..4ba9ad3dd 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp @@ -148,47 +148,47 @@ TEST_CASE("AnalyticFunction") //.def(py::self + py::self); CHECK(Approx(AnalyticFunction({x1}, cos(x1)+cos(x1)).eval(m, Interval(0.))) == Interval(2.)); //.def("__add__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)+x1).eval(m, codac2::pi)) == codac2::pi-1); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)+x1).eval(m, pi)) == pi-1); //.def("__radd__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1+cos(x1)).eval(m, codac2::pi)) == codac2::pi-1); + CHECK(Approx(AnalyticFunction({x1}, x1+cos(x1)).eval(m, pi)) == pi-1); //.def("__add__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)+Interval(10.)).eval(m, codac2::pi)) == Interval(9)); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)+Interval(10.)).eval(m, pi)) == Interval(9)); //.def("__radd__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, 10+cos(x1)).eval(m, codac2::pi)) == Interval(9)); + CHECK(Approx(AnalyticFunction({x1}, 10+cos(x1)).eval(m, pi)) == Interval(9)); //.def(- py::self); CHECK(Approx(AnalyticFunction({x1}, -cos(x1)).eval(m, Interval(0.))) == Interval(-1.)); //.def(py::self - py::self); CHECK(Approx(AnalyticFunction({x1}, cos(x1)-cos(x1)).eval(m, Interval(0.))) == Interval(0.)); //.def("__sub__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)-x1).eval(m, codac2::pi)) == -codac2::pi-1); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)-x1).eval(m, pi)) == -pi-1); //.def("__rsub__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1-cos(x1)).eval(m, codac2::pi)) == codac2::pi+1); + CHECK(Approx(AnalyticFunction({x1}, x1-cos(x1)).eval(m, pi)) == pi+1); //.def("__sub__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)-Interval(10.)).eval(m, codac2::pi)) == -Interval(11)); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)-Interval(10.)).eval(m, pi)) == -Interval(11)); //.def("__rsub__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, 10-cos(x1)).eval(m, codac2::pi)) == Interval(11)); + CHECK(Approx(AnalyticFunction({x1}, 10-cos(x1)).eval(m, pi)) == Interval(11)); //.def(py::self * py::self); CHECK(Approx(AnalyticFunction({x1}, cos(x1)*cos(x1)).eval(m, Interval(0.))) == Interval(1.)); //.def("__mul__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)*x1).eval(m, codac2::pi)) == -1*codac2::pi); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)*x1).eval(m, pi)) == -1*pi); //.def("__rmul__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1*cos(x1)).eval(m, codac2::pi)) == -1*codac2::pi); + CHECK(Approx(AnalyticFunction({x1}, x1*cos(x1)).eval(m, pi)) == -1*pi); //.def("__mul__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)*Interval(10.)).eval(m, codac2::pi),1e-9) == -Interval(10)); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)*Interval(10.)).eval(m, pi),1e-9) == -Interval(10)); //.def("__rmul__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, Interval(10.)*cos(x1)).eval(m, codac2::pi),1e-9) == -10); + CHECK(Approx(AnalyticFunction({x1}, Interval(10.)*cos(x1)).eval(m, pi),1e-9) == -10); //.def("__mul__", {}(const ScalarExpr& e1, const VectorExpr& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({codac2::pi,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); + CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({pi,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); //.def("__truediv__", {}(const ScalarExpr& e1, const ScalarExpr& e2); CHECK(Approx(AnalyticFunction({x1}, cos(x1)/cos(x1)).eval(m, Interval(0.))) == Interval(1.)); //.def("__truediv__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)/x1).eval(m, codac2::pi)) == -1/codac2::pi); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)/x1).eval(m, pi)) == -1/pi); //.def("__rtruediv__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1/cos(x1)).eval(m, codac2::pi)) == -codac2::pi); + CHECK(Approx(AnalyticFunction({x1}, x1/cos(x1)).eval(m, pi)) == -pi); //.def("__truediv__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)/Interval(4.)).eval(m, codac2::pi)) == -1./4); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)/Interval(4.)).eval(m, pi)) == -1./4); //.def("__rtruediv__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, 4./cos(x1)).eval(m, codac2::pi)) == -4); + CHECK(Approx(AnalyticFunction({x1}, 4./cos(x1)).eval(m, pi)) == -4); // ======> VectorExpr @@ -218,7 +218,7 @@ TEST_CASE("AnalyticFunction") //.def("__rsub__", {}(const VectorExpr& e1, const IntervalVector& e2); CHECK(Approx(AnalyticFunction({v1,v2}, Vector({1,5})-(v1-v2)).eval(m, IntervalVector({2,3}),Vector({1,5}))) == IntervalVector({0,7})); //.def("__rmul__", {}(const VectorExpr& e1, const ScalarExpr& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({codac2::pi,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); + CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({pi,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); //.def("__rmul__", {}(const VectorExpr& e1, const ScalarVar& e2); CHECK(Approx(AnalyticFunction({x1}, x1*vec(3*x1,2*x1)).eval(m, 3),1e-9) == IntervalVector({27,18})); } diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp index 008cbd644..de92caf1e 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp @@ -12,6 +12,7 @@ #include #include #include +#include using namespace std; using namespace codac2; From c9bc8f65713625738fd3cb55465488b9192e4815 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 27 Dec 2024 18:53:51 +0100 Subject: [PATCH 049/126] [math] missing include --- src/core/tools/codac2_math.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/tools/codac2_math.h b/src/core/tools/codac2_math.h index 9094dc9e3..b747447ba 100644 --- a/src/core/tools/codac2_math.h +++ b/src/core/tools/codac2_math.h @@ -9,7 +9,8 @@ #pragma once -#include +//#include +#include <3rd/gaol/gaol_port.h> namespace codac2 { From 6ec280bb9341c345fc547e789e95756e920441ed Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 27 Dec 2024 19:30:50 +0100 Subject: [PATCH 050/126] [math] redefining PI --- src/core/tools/codac2_math.h | 8 +--- .../3rd/vibes/codac2_Figure2D_VIBes.cpp | 8 ++-- src/graphics/figures/codac2_Figure2D.cpp | 2 +- .../interval/codac2_tests_Interval_bwd.cpp | 46 +++++++++---------- .../codac2_tests_AnalyticFunction.cpp | 36 +++++++-------- .../codac2_tests_SampledTrajectory.cpp | 4 +- 6 files changed, 50 insertions(+), 54 deletions(-) diff --git a/src/core/tools/codac2_math.h b/src/core/tools/codac2_math.h index b747447ba..4ee59b7a4 100644 --- a/src/core/tools/codac2_math.h +++ b/src/core/tools/codac2_math.h @@ -9,13 +9,9 @@ #pragma once -//#include -#include <3rd/gaol/gaol_port.h> +#include namespace codac2 { - // As long as GAOL defines pi in common namespace, - // we use it as default pi value instead of the pi - // from the standard library. - //constexpr double pi = std::numbers::pi; // Need C++20 + constexpr double PI = std::numbers::pi; // Need C++20 } \ No newline at end of file diff --git a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp index bdeb6c363..42aba5d28 100644 --- a/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp +++ b/src/graphics/3rd/vibes/codac2_Figure2D_VIBes.cpp @@ -118,28 +118,28 @@ void Figure2D_VIBes::draw_pie(const Vector& c, const Interval& r, const Interval assert(_fig.size() <= c.size()); assert(r.lb() >= 0.); // Corrected a bug in VIBEs in case of r=[..,oo] (the pie disappears when zoomed in) - vibes::drawPie(c[i()],c[j()], r.lb(),(r.ub()>1e5?1e5:r.ub()), 180.*theta.lb()/pi,180.*theta.ub()/pi, to_vibes_style(s), _params); + vibes::drawPie(c[i()],c[j()], r.lb(),(r.ub()>1e5?1e5:r.ub()), 180.*theta.lb()/PI,180.*theta.ub()/PI, to_vibes_style(s), _params); } void Figure2D_VIBes::draw_ellipse(const Vector& c, const Vector& ab, double theta, const StyleProperties& s) { assert(c.size() == 2); assert(ab.size() == 2); - vibes::drawEllipse(c[0],c[1], ab[0],ab[1], 180.*theta/pi, to_vibes_style(s), _params); + vibes::drawEllipse(c[0],c[1], ab[0],ab[1], 180.*theta/PI, to_vibes_style(s), _params); } void Figure2D_VIBes::draw_tank(const Vector& x, float size, const StyleProperties& s) { assert(_fig.size() <= x.size()+1); assert(j()+1 < x.size()); - vibes::drawTank(x[i()],x[j()],180.*x[j()+1]/pi, size, to_vibes_style(s), _params); + vibes::drawTank(x[i()],x[j()],180.*x[j()+1]/PI, size, to_vibes_style(s), _params); } void Figure2D_VIBes::draw_AUV(const Vector& x, float size, const StyleProperties& s) { assert(_fig.size() <= x.size()+1); assert(j()+1 < x.size()); - vibes::drawAUV(x[i()],x[j()],180.*x[j()+1]/pi, size, to_vibes_style(s), _params); + vibes::drawAUV(x[i()],x[j()],180.*x[j()+1]/PI, size, to_vibes_style(s), _params); } string Figure2D_VIBes::to_vibes_style(const StyleProperties& s) diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 0320fd715..a80d6344c 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -178,7 +178,7 @@ void Figure2D::draw_pie(const Vector& c, const Interval& r, const Interval& thet Interval theta_(theta); if(theta.is_unbounded()) - theta_ = Interval(0,2.*pi); + theta_ = Interval(0,2.*PI); Interval r_(r); if(r.is_unbounded()) diff --git a/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp b/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp index dbfdac1e8..4a37fcc32 100644 --- a/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp +++ b/tests/core/domains/interval/codac2_tests_Interval_bwd.cpp @@ -261,25 +261,25 @@ TEST_CASE("Interval bwd operations") Interval a, y; - a = Interval(pi/6.,pi/3.); y = Interval(.5,10.); x = Interval(.5,2.); + a = Interval(PI/6.,PI/3.); y = Interval(.5,10.); x = Interval(.5,2.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(.5,2.*sqrt(3.))); CHECK(Approx(x) == Interval(.5,2.)); - a = Interval(pi/6.,pi/3.); y = Interval(.5,2.); x = Interval(.5,10.); + a = Interval(PI/6.,PI/3.); y = Interval(.5,2.); x = Interval(.5,10.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(.5,2.)); CHECK(Approx(x) == Interval(.5,2.*sqrt(3.))); - a = Interval(-pi/4.,pi/4.); y = Interval(1.,2.); x = Interval(.5,2.); + a = Interval(-PI/4.,PI/4.); y = Interval(1.,2.); x = Interval(.5,2.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(1.,2.)); CHECK(Approx(x) == Interval(1.,2.)); - a = Interval(-pi/2.,0.); y = Interval(.5,2.); x = Interval(.5,10.); + a = Interval(-PI/2.,0.); y = Interval(.5,2.); x = Interval(.5,10.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval::empty()); CHECK(Approx(x) == Interval::empty()); - a = Interval(2.*pi,3.*pi); y = Interval(-.5,2.); x = Interval(.5,10.); + a = Interval(2.*PI,3.*PI); y = Interval(-.5,2.); x = Interval(.5,10.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval::empty()); CHECK(Approx(x) == Interval::empty()); - a = Interval(2*pi/3.,5.*pi/6.); y = Interval(0.,100.); x = Interval(-20.,-sqrt(3.)/2.); + a = Interval(2*PI/3.,5.*PI/6.); y = Interval(0.,100.); x = Interval(-20.,-sqrt(3.)/2.); bwd_atan2(a,y,x); CHECK(Approx(y,1e-10) == Interval(.5,20.*sqrt(3.))); CHECK(Approx(x) == Interval(-20.,-sqrt(3.)/2)); - a = Interval(-3*pi/4.,-2*pi/3.); y = Interval(-sqrt(3.)/2.,2.); x = Interval(-sqrt(2.)/2.,0.); + a = Interval(-3*PI/4.,-2*PI/3.); y = Interval(-sqrt(3.)/2.,2.); x = Interval(-sqrt(2.)/2.,0.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(-sqrt(3.)/2.,0.)); CHECK(Approx(x) == Interval(-sqrt(2.)/2.,0.)); - a = Interval(-3*pi/4.,-2*pi/3.); y = Interval(-sqrt(3.)/2.,2.); x = Interval(-1.,-.5); + a = Interval(-3*PI/4.,-2*PI/3.); y = Interval(-sqrt(3.)/2.,2.); x = Interval(-1.,-.5); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(-sqrt(3.)/2.,-.5)); CHECK(Approx(x) == Interval(-sqrt(3.)/2.,-.5)); - a = Interval(-3*pi/4.,-pi/4.); y = Interval(-5.,-.5); x = Interval(-oo,oo); + a = Interval(-3*PI/4.,-PI/4.); y = Interval(-5.,-.5); x = Interval(-oo,oo); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(-5.,-.5)); CHECK(Approx(x) == Interval(-5.,5.)); - a = Interval(-pi/3.,pi/4.); y = Interval(-oo,oo); x = Interval(sqrt(3.)/2.); + a = Interval(-PI/3.,PI/4.); y = Interval(-oo,oo); x = Interval(sqrt(3.)/2.); bwd_atan2(a,y,x); CHECK(Approx(y) == Interval(-1.5,sqrt(3.)/2.)); CHECK(Approx(x) == Interval(sqrt(3.)/2.)); a = Interval::half_pi(); y = Interval(1); x = 0.; bwd_atan2(a,y,x); CHECK(Approx(y) == 1.); CHECK(Approx(x) == 0.); @@ -292,15 +292,15 @@ TEST_CASE("Interval bwd operations") x = Interval(-1,5); bwd_sqrt(Interval(2,5), x); CHECK(x == Interval(4,5)); x = Interval(-oo,oo); bwd_sqrt(Interval(-4,-2), x); CHECK(x == Interval::empty()); - x = Interval(-1.,3.); bwd_atan(Interval(0.,pi/6.),x); CHECK(x == tan(Interval(0.,pi/6.))); - x = Interval(0,5*pi/2.0); bwd_atan(Interval(-pi,1.5),x); CHECK(x == Interval(0,5*pi/2.0)); - x = Interval(.2,.5); bwd_atan(Interval(0.,pi/6.),x); CHECK(x == Interval(.2,.5)); - x = Interval(-100,100); bwd_atan(Interval(-pi/2-0.1,pi/2+0.1),x); CHECK(x == Interval(-100,100)); - x = Interval(-100,100); bwd_atan(Interval(pi/2+0.1,pi),x); CHECK(x == Interval::empty()); - x = Interval(-100,100); bwd_atan(Interval(-pi,-pi/2-0.1),x); CHECK(x == Interval::empty()); + x = Interval(-1.,3.); bwd_atan(Interval(0.,PI/6.),x); CHECK(x == tan(Interval(0.,PI/6.))); + x = Interval(0,5*PI/2.0); bwd_atan(Interval(-PI,1.5),x); CHECK(x == Interval(0,5*PI/2.0)); + x = Interval(.2,.5); bwd_atan(Interval(0.,PI/6.),x); CHECK(x == Interval(.2,.5)); + x = Interval(-100,100); bwd_atan(Interval(-PI/2-0.1,PI/2+0.1),x); CHECK(x == Interval(-100,100)); + x = Interval(-100,100); bwd_atan(Interval(PI/2+0.1,PI),x); CHECK(x == Interval::empty()); + x = Interval(-100,100); bwd_atan(Interval(-PI,-PI/2-0.1),x); CHECK(x == Interval::empty()); - x = Interval(-oo,oo); bwd_atan(Interval(-pi/4,pi/2.), x); CHECK(x.lb() == -1); CHECK(x.ub() > 1000); - x = Interval(-oo,oo); bwd_atan(Interval(-pi/2,pi/4.), x); CHECK(x.ub() == +1); CHECK(x.lb() < -1000); + x = Interval(-oo,oo); bwd_atan(Interval(-PI/4,PI/2.), x); CHECK(x.lb() == -1); CHECK(x.ub() > 1000); + x = Interval(-oo,oo); bwd_atan(Interval(-PI/2,PI/4.), x); CHECK(x.ub() == +1); CHECK(x.lb() < -1000); CHECK_bwd_add(Interval(1,3),Interval(1,2),Interval(-10,5),Interval(1,2),Interval(-1,2)); CHECK_bwd_add(Interval::empty(),Interval(0.1,2.0),Interval(-10,2),Interval::empty(),Interval::empty()); @@ -317,11 +317,11 @@ TEST_CASE("Interval bwd operations") CHECK_bwd_imod(3.,Interval(3.,5.),Interval(1.,2.),Interval(4.,5.),Interval(1.,2.)); CHECK_bwd_imod(2.,Interval(7.,8.),Interval(.5,2.),Interval(7.,8.),Interval(1.,2.)); CHECK_bwd_imod(2.,Interval(7.,8.),Interval(0.,2.),Interval(7.,8.),Interval(0.,2.)); - CHECK_bwd_imod(2.*pi,Interval(2.*pi,3.*pi),Interval(pi/6,pi/2.),Interval(13.*pi/6.,5.*pi/2.),Interval(pi/6,pi/2.)); - CHECK_bwd_imod(2.*pi,Interval(3.*pi,4.*pi),Interval(pi/3,pi/2.),Interval::empty(),Interval::empty()); - CHECK_bwd_imod(2.*pi,Interval(3.*pi,4.*pi),Interval(0.,pi/2.),Interval(4*pi),Interval(0.)); - CHECK_bwd_imod(2.*pi,Interval(2.*pi,4.*pi),Interval(-pi/6,pi/2.),Interval(2.*pi,4.*pi),Interval(-pi/6,pi/2.)); - CHECK_bwd_imod(2.*pi,Interval(7.*pi/4.,8.*pi/3),Interval(-pi/2,pi/2.),Interval(7.*pi/4.,5.*pi/2.),Interval(-pi/4,pi/2.)); + CHECK_bwd_imod(2.*PI,Interval(2.*PI,3.*PI),Interval(PI/6,PI/2.),Interval(13.*PI/6.,5.*PI/2.),Interval(PI/6,PI/2.)); + CHECK_bwd_imod(2.*PI,Interval(3.*PI,4.*PI),Interval(PI/3,PI/2.),Interval::empty(),Interval::empty()); + CHECK_bwd_imod(2.*PI,Interval(3.*PI,4.*PI),Interval(0.,PI/2.),Interval(4*PI),Interval(0.)); + CHECK_bwd_imod(2.*PI,Interval(2.*PI,4.*PI),Interval(-PI/6,PI/2.),Interval(2.*PI,4.*PI),Interval(-PI/6,PI/2.)); + CHECK_bwd_imod(2.*PI,Interval(7.*PI/4.,8.*PI/3),Interval(-PI/2,PI/2.),Interval(7.*PI/4.,5.*PI/2.),Interval(-PI/4,PI/2.)); x = Interval(-oo,oo); bwd_floor(Interval::empty(),x); CHECK(x == Interval::empty()); x = Interval(-oo,-0.000001); bwd_floor(Interval(-oo,-1),x); CHECK(x == Interval(-oo,-0.000001)); diff --git a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp index 4ba9ad3dd..8799c5998 100644 --- a/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp +++ b/tests/core/functions/analytic/codac2_tests_AnalyticFunction.cpp @@ -148,47 +148,47 @@ TEST_CASE("AnalyticFunction") //.def(py::self + py::self); CHECK(Approx(AnalyticFunction({x1}, cos(x1)+cos(x1)).eval(m, Interval(0.))) == Interval(2.)); //.def("__add__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)+x1).eval(m, pi)) == pi-1); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)+x1).eval(m, PI)) == PI-1); //.def("__radd__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1+cos(x1)).eval(m, pi)) == pi-1); + CHECK(Approx(AnalyticFunction({x1}, x1+cos(x1)).eval(m, PI)) == PI-1); //.def("__add__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)+Interval(10.)).eval(m, pi)) == Interval(9)); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)+Interval(10.)).eval(m, PI)) == Interval(9)); //.def("__radd__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, 10+cos(x1)).eval(m, pi)) == Interval(9)); + CHECK(Approx(AnalyticFunction({x1}, 10+cos(x1)).eval(m, PI)) == Interval(9)); //.def(- py::self); CHECK(Approx(AnalyticFunction({x1}, -cos(x1)).eval(m, Interval(0.))) == Interval(-1.)); //.def(py::self - py::self); CHECK(Approx(AnalyticFunction({x1}, cos(x1)-cos(x1)).eval(m, Interval(0.))) == Interval(0.)); //.def("__sub__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)-x1).eval(m, pi)) == -pi-1); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)-x1).eval(m, PI)) == -PI-1); //.def("__rsub__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1-cos(x1)).eval(m, pi)) == pi+1); + CHECK(Approx(AnalyticFunction({x1}, x1-cos(x1)).eval(m, PI)) == PI+1); //.def("__sub__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)-Interval(10.)).eval(m, pi)) == -Interval(11)); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)-Interval(10.)).eval(m, PI)) == -Interval(11)); //.def("__rsub__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, 10-cos(x1)).eval(m, pi)) == Interval(11)); + CHECK(Approx(AnalyticFunction({x1}, 10-cos(x1)).eval(m, PI)) == Interval(11)); //.def(py::self * py::self); CHECK(Approx(AnalyticFunction({x1}, cos(x1)*cos(x1)).eval(m, Interval(0.))) == Interval(1.)); //.def("__mul__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)*x1).eval(m, pi)) == -1*pi); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)*x1).eval(m, PI)) == -1*PI); //.def("__rmul__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1*cos(x1)).eval(m, pi)) == -1*pi); + CHECK(Approx(AnalyticFunction({x1}, x1*cos(x1)).eval(m, PI)) == -1*PI); //.def("__mul__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)*Interval(10.)).eval(m, pi),1e-9) == -Interval(10)); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)*Interval(10.)).eval(m, PI),1e-9) == -Interval(10)); //.def("__rmul__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, Interval(10.)*cos(x1)).eval(m, pi),1e-9) == -10); + CHECK(Approx(AnalyticFunction({x1}, Interval(10.)*cos(x1)).eval(m, PI),1e-9) == -10); //.def("__mul__", {}(const ScalarExpr& e1, const VectorExpr& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({pi,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); + CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({PI,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); //.def("__truediv__", {}(const ScalarExpr& e1, const ScalarExpr& e2); CHECK(Approx(AnalyticFunction({x1}, cos(x1)/cos(x1)).eval(m, Interval(0.))) == Interval(1.)); //.def("__truediv__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)/x1).eval(m, pi)) == -1/pi); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)/x1).eval(m, PI)) == -1/PI); //.def("__rtruediv__", {}(const ScalarExpr& e1, const ScalarVar& e2); - CHECK(Approx(AnalyticFunction({x1}, x1/cos(x1)).eval(m, pi)) == -pi); + CHECK(Approx(AnalyticFunction({x1}, x1/cos(x1)).eval(m, PI)) == -PI); //.def("__truediv__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, cos(x1)/Interval(4.)).eval(m, pi)) == -1./4); + CHECK(Approx(AnalyticFunction({x1}, cos(x1)/Interval(4.)).eval(m, PI)) == -1./4); //.def("__rtruediv__", {}(const ScalarExpr& e1, const Interval& e2); - CHECK(Approx(AnalyticFunction({x1}, 4./cos(x1)).eval(m, pi)) == -4); + CHECK(Approx(AnalyticFunction({x1}, 4./cos(x1)).eval(m, PI)) == -4); // ======> VectorExpr @@ -218,7 +218,7 @@ TEST_CASE("AnalyticFunction") //.def("__rsub__", {}(const VectorExpr& e1, const IntervalVector& e2); CHECK(Approx(AnalyticFunction({v1,v2}, Vector({1,5})-(v1-v2)).eval(m, IntervalVector({2,3}),Vector({1,5}))) == IntervalVector({0,7})); //.def("__rmul__", {}(const VectorExpr& e1, const ScalarExpr& e2); - CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({pi,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); + CHECK(Approx(AnalyticFunction({v1,v2}, cos(v1[0])*(v2+v2)).eval(m, Vector({PI,-1}),Vector({2,3})),1e-9) == IntervalVector({-4,-6})); //.def("__rmul__", {}(const VectorExpr& e1, const ScalarVar& e2); CHECK(Approx(AnalyticFunction({x1}, x1*vec(3*x1,2*x1)).eval(m, 3),1e-9) == IntervalVector({27,18})); } diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp index de92caf1e..c538269d2 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp @@ -67,13 +67,13 @@ TEST_CASE("SampledTrajectory as operator (1d case)") { ScalarVar t; AnalyticFunction f { {t}, cos(t) }; - AnalyticTrajectory analytic_traj(f, {-pi,pi}); + AnalyticTrajectory analytic_traj(f, {-PI,PI}); auto sampled_traj = analytic_traj.sampled(1e-2); auto g = sampled_traj.as_function(); AnalyticFunction h { {t}, g(t) }; - for(double t = -pi ; t < pi ; t+=1e-2) + for(double t = -PI ; t < PI ; t+=1e-2) CHECK(Approx(h.real_eval(t)) == cos(t)); } From f9f6f56350fc82dc807f055028df916a6b675ef2 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 27 Dec 2024 20:11:59 +0100 Subject: [PATCH 051/126] [pr] minor corrections --- tests/core/trajectory/codac2_tests_SampledTrajectory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.py b/tests/core/trajectory/codac2_tests_SampledTrajectory.py index 7d3cdf910..b1d3128a2 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.py +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.py @@ -96,7 +96,7 @@ def tests_SampledTrajectory(self): t_ = 0 while t_ < 5: - self.assertTrue(Approx(h.real_eval(t_)) == Vector([2*math.cos(t_),math.sin(2*t_)])) + self.assertTrue(Approx(h.real_eval(t_),1e-8) == Vector([2*math.cos(t_),math.sin(2*t_)])) t_=t_+1e-2 h = AnalyticFunction( @@ -106,7 +106,7 @@ def tests_SampledTrajectory(self): t_ = 0 while t_ < 5: - self.assertTrue(Approx(h.real_eval(t_)) == Vector([2*math.cos(t_),math.sin(2*t_)])) + self.assertTrue(Approx(h.real_eval(t_),1e-8) == Vector([2*math.cos(t_),math.sin(2*t_)])) t_=t_+1e-2 if __name__ == '__main__': From 60e0405b64cf960f4ee5054caf7079e50186bc75 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 27 Dec 2024 20:54:14 +0100 Subject: [PATCH 052/126] [pr] minor corrections --- tests/core/trajectory/codac2_tests_SampledTrajectory.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp index c538269d2..06207d17e 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp @@ -74,7 +74,7 @@ TEST_CASE("SampledTrajectory as operator (1d case)") AnalyticFunction h { {t}, g(t) }; for(double t = -PI ; t < PI ; t+=1e-2) - CHECK(Approx(h.real_eval(t)) == cos(t)); + CHECK(Approx(h.real_eval(t),1e-8) == cos(t)); } TEST_CASE("SampledTrajectory as operator (nd case)") @@ -96,7 +96,7 @@ TEST_CASE("SampledTrajectory as operator (nd case)") }; for(double t = 0 ; t < 5 ; t+=1e-2) - CHECK(Approx(h.real_eval(t)) == Vector({2*cos(t),sin(2*t)})); + CHECK(Approx(h.real_eval(t),1e-8) == Vector({2*cos(t),sin(2*t)})); } { AnalyticFunction h { @@ -105,6 +105,6 @@ TEST_CASE("SampledTrajectory as operator (nd case)") }; for(double t = 0 ; t < 5 ; t+=1e-2) - CHECK(Approx(h.real_eval(t)) == Vector({2*cos(t),sin(2*t)})); + CHECK(Approx(h.real_eval(t),1e-8) == Vector({2*cos(t),sin(2*t)})); } } \ No newline at end of file From 1818336cad2c0e284aec3538705beb79dc4af3ea Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sat, 28 Dec 2024 11:35:21 +0100 Subject: [PATCH 053/126] [py] added constant PI --- python/src/core/codac2_py_core.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index 50fb4fb57..d18b30f6e 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "codac2_py_AnalyticFunction.h" #include "codac2_py_CtcInverse.h" #include "codac2_py_CtcInverseNotIn.h" @@ -122,6 +123,7 @@ PYBIND11_MODULE(_core, m) { m.doc() = string(FOR_MATLAB ? "Matlab" : "Python") + " binding of Codac (core)"; m.attr("oo") = oo; + m.attr("PI") = PI; // 3rd From 23c7e8589449942bd9b72f0491a3e83d8143dcce Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sat, 28 Dec 2024 11:36:13 +0100 Subject: [PATCH 054/126] =?UTF-8?q?[graphics]=20added=20example=20of=20Col?= =?UTF-8?q?orMap=20(Ma=C3=ABl's=20update)=20with=20Fermat's=20spiral?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/00_graphics/graphic_examples.py | 14 +++++++++- .../graphics/figures/codac2_py_Figure2D.cpp | 10 +++---- .../trajectory/codac2_SampledTrajectory.h | 2 +- src/graphics/figures/codac2_Figure2D.cpp | 28 ++++++++----------- src/graphics/figures/codac2_Figure2D.h | 14 +++++----- 5 files changed, 38 insertions(+), 30 deletions(-) diff --git a/examples/00_graphics/graphic_examples.py b/examples/00_graphics/graphic_examples.py index 2f2e6919c..f6c8770e2 100644 --- a/examples/00_graphics/graphic_examples.py +++ b/examples/00_graphics/graphic_examples.py @@ -73,4 +73,16 @@ fig3.draw_box([[i,i+1],[-2,-1]],[Color.black(),cmap_default.color(ratio)]) fig3.draw_box([[i,i+1],[-3,-2]],[Color.black(),cmap_blue_tube.color(ratio)]) fig3.draw_box([[i,i+1],[-4,-3]],[Color.black(),cmap_red_tube.color(ratio)]) - fig3.draw_box([[i,i+1],[-5,-4]],[Color.black(),cmap_rainbow.color(ratio)]) \ No newline at end of file + fig3.draw_box([[i,i+1],[-5,-4]],[Color.black(),cmap_rainbow.color(ratio)]) + +fig3 = Figure2D("My figure 3", GraphicOutput.VIBES) + +fig3.set_window_properties([500,50],[500,500]) +fig3.set_axes(axis(0,[-10,10]), axis(1,[-10,10])) + +a = 0.8 +t=ScalarVar() +# Fermat's spiral +f1=AnalyticFunction([t], [a*sqrt(t)*cos(t),a*sqrt(t)*sin(t)]) +traj3=AnalyticTrajectory(f1, [0,100]) +fig3.draw_trajectory(traj3, ColorMap.rainbow()) \ No newline at end of file diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index 8ca63de0e..dc943a1ac 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -2,7 +2,7 @@ * Codac binding (core) * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Maël Godard * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -108,11 +108,11 @@ void export_Figure2D(py::module& m) .def("draw_line", &Figure2D::draw_line, VOID_FIGURE2D_DRAW_LINE_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_STYLEPROPERTIES_REF, - "a"_a, "b"_a, "s"_a=StyleProperties()) + "p1"_a, "p2"_a, "s"_a=StyleProperties()) .def("draw_arrow", &Figure2D::draw_arrow, VOID_FIGURE2D_DRAW_ARROW_CONST_VECTOR_REF_CONST_VECTOR_REF_FLOAT_CONST_STYLEPROPERTIES_REF, - "a"_a, "b"_a, "tip_length"_a, "s"_a=StyleProperties()) + "p1"_a, "p2"_a, "tip_length"_a, "s"_a=StyleProperties()) .def("draw_polyline", (void(Figure2D::*)(const std::vector&,const StyleProperties&))&Figure2D::draw_polyline, VOID_FIGURE2D_DRAW_POLYLINE_CONST_VECTOR_VECTOR_REF_CONST_STYLEPROPERTIES_REF, @@ -241,11 +241,11 @@ void export_Figure2D(py::module& m) .def_static("draw_line", &DefaultView::draw_line, STATIC_VOID_DEFAULTVIEW_DRAW_LINE_CONST_VECTOR_REF_CONST_VECTOR_REF_CONST_STYLEPROPERTIES_REF, - "a"_a, "b"_a, "s"_a=StyleProperties()) + "p1"_a, "p2"_a, "s"_a=StyleProperties()) .def_static("draw_arrow", &DefaultView::draw_arrow, STATIC_VOID_DEFAULTVIEW_DRAW_ARROW_CONST_VECTOR_REF_CONST_VECTOR_REF_FLOAT_CONST_STYLEPROPERTIES_REF, - "a"_a, "b"_a, "tip_length"_a, "s"_a=StyleProperties()) + "p1"_a, "p2"_a, "tip_length"_a, "s"_a=StyleProperties()) .def_static("draw_polyline", (void(*)(const std::vector&,const StyleProperties&))&DefaultView::draw_polyline, STATIC_VOID_DEFAULTVIEW_DRAW_POLYLINE_CONST_VECTOR_VECTOR_REF_CONST_STYLEPROPERTIES_REF, diff --git a/src/core/trajectory/codac2_SampledTrajectory.h b/src/core/trajectory/codac2_SampledTrajectory.h index 5b094105a..663852489 100644 --- a/src/core/trajectory/codac2_SampledTrajectory.h +++ b/src/core/trajectory/codac2_SampledTrajectory.h @@ -58,7 +58,7 @@ namespace codac2 if(this->empty()) return Interval::empty(); else - return { this->begin()->first, std::prev(this->end())->first }; + return { this->begin()->first, this->rbegin()->first }; } virtual void truncate_tdomain(const Interval& new_tdomain) diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 915e707f0..6cca590ee 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -2,7 +2,7 @@ * codac2_Figure2D.cpp * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Maël Godard * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -138,22 +138,18 @@ void Figure2D::draw_ring(const Vector& c, const Interval& r, const StyleProperti output_fig->draw_ring(c,r,s); } -void Figure2D::draw_line(const Vector& a, const Vector& b, const StyleProperties& s) +void Figure2D::draw_line(const Vector& p1, const Vector& p2, const StyleProperties& s) { - assert_release(a.size() == b.size()); - assert_release(a.size() == 2); - vector values = {a,b}; - - draw_polyline(values,s); + assert_release(p1.size() == p2.size()); + assert_release(this->size() <= p1.size()); + draw_polyline({p1,p2}, s); } -void Figure2D::draw_arrow(const Vector& a, const Vector& b, float tip_length, const StyleProperties& s) +void Figure2D::draw_arrow(const Vector& p1, const Vector& p2, float tip_length, const StyleProperties& s) { - assert_release(a.size() == b.size()); - assert_release(a.size() == 2); - vector values = {a,b}; - - draw_polyline(values,tip_length,s); + assert_release(p1.size() == p2.size()); + assert_release(this->size() <= p1.size()); + draw_polyline({p1,p2}, tip_length, s); } void Figure2D::draw_polyline(const vector& x, const StyleProperties& s) @@ -234,13 +230,13 @@ void Figure2D::draw_trajectory(const SampledTrajectory& x, const ColorMa { assert_release(this->size() <= x.size()); - double range = x.rbegin()->first - x.begin()->first; + double range = x.tdomain().diam(); for(auto it = x.begin(); std::next(it) != x.end(); ++it) { draw_polyline( - { it->second, std::next(it)->second }, - cmap.color((it->first - x.begin()->first) / range)); + { it->second, std::next(it)->second }, + cmap.color((it->first - x.begin()->first) / range)); } } diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 8df52ebc5..bf5b1c0a3 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -2,7 +2,7 @@ * \file codac2_Figure2D.h * ---------------------------------------------------------------------------- * \date 2024 - * \author Simon Rohou + * \author Simon Rohou, Maël Godard * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ @@ -86,8 +86,8 @@ namespace codac2 void draw_box(const IntervalVector& x, const StyleProperties& s = StyleProperties()); void draw_circle(const Vector& c, double r, const StyleProperties& s = StyleProperties()); void draw_ring(const Vector& c, const Interval& r, const StyleProperties& s = StyleProperties()); - void draw_line(const Vector& a, const Vector& b, const StyleProperties& s = StyleProperties()); - void draw_arrow(const Vector& a, const Vector& b, float tip_length, const StyleProperties& s = StyleProperties()); + void draw_line(const Vector& p1, const Vector& p2, const StyleProperties& s = StyleProperties()); + void draw_arrow(const Vector& p1, const Vector& p2, float tip_length, const StyleProperties& s = StyleProperties()); void draw_polyline(const std::vector& x, const StyleProperties& s = StyleProperties()); void draw_polyline(const std::vector& x, float tip_length, const StyleProperties& s = StyleProperties()); void draw_polygone(const std::vector& x, const StyleProperties& s = StyleProperties()); @@ -182,16 +182,16 @@ namespace codac2 selected_fig()->draw_ring(c,r,s); } - static void draw_line(const Vector& x1, const Vector& x2, const StyleProperties& s = StyleProperties()) + static void draw_line(const Vector& p1, const Vector& p2, const StyleProperties& s = StyleProperties()) { auto_init(); - selected_fig()->draw_line(x1,x2,s); + selected_fig()->draw_line(p1,p2,s); } - static void draw_arrow(const Vector& x1, const Vector& x2, float tip_length, const StyleProperties& s = StyleProperties()) + static void draw_arrow(const Vector& p1, const Vector& p2, float tip_length, const StyleProperties& s = StyleProperties()) { auto_init(); - selected_fig()->draw_arrow(x1,x2,tip_length,s); + selected_fig()->draw_arrow(p1,p2,tip_length,s); } static void draw_polyline(const std::vector& x, const StyleProperties& s = StyleProperties()) From 0471d68f42ddfd33d9a723df8309507683e05dd4 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sat, 28 Dec 2024 18:28:56 +0100 Subject: [PATCH 055/126] [py] casting functions + simplifying binding --- python/codac/core/__init__.py | 16 --- python/src/core/CMakeLists.txt | 1 + python/src/core/codac2_py_cast.h | 107 ++++++++++++++++++ .../analytic/codac2_py_AnalyticFunction.h | 101 ++++++----------- .../codac2_py_analytic_operations.cpp | 54 ++++----- .../analytic/codac2_py_analytic_variables.cpp | 67 ++++++----- python/src/core/paver/codac2_py_pave.cpp | 23 +++- .../core/separators/codac2_py_SepInverse.h | 9 +- .../separators/codac2_py_SepTransform.cpp | 12 +- python/src/graphics/CMakeLists.txt | 1 + .../graphics/figures/codac2_py_Figure2D.cpp | 103 +++++------------ 11 files changed, 258 insertions(+), 236 deletions(-) create mode 100644 python/src/core/codac2_py_cast.h diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index 3ee1b8547..b00434847 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -210,22 +210,6 @@ def cart_prod(*args): codac_error("cart_prod: invalid input arguments") -def sivia(x,f,y,eps): - - if isinstance(f.f, AnalyticFunction_Scalar): - if not isinstance(y, (list,float,Interval)): - codac_error("Provided function is scalar, the output 'y' should be an interval") - return sivia_(x, f.f, Interval(y), eps) - - if isinstance(f.f, AnalyticFunction_Vector): - if not isinstance(y, (list,Vector,IntervalVector)): - codac_error("Provided function is vectorial, the output 'y' should be an interval vector") - return sivia_(x, f.f, IntervalVector(y), eps) - - else: - codac_error("sivia: can only compute sivia from scalar or vector functions") - - class AnalyticTrajectory: def __init__(self, f, t): diff --git a/python/src/core/CMakeLists.txt b/python/src/core/CMakeLists.txt index 5caa37207..479cece14 100644 --- a/python/src/core/CMakeLists.txt +++ b/python/src/core/CMakeLists.txt @@ -6,6 +6,7 @@ pybind11_add_module(_core SHARED codac2_py_core.cpp + codac2_py_cast.h actions/codac2_py_OctaSym.cpp diff --git a/python/src/core/codac2_py_cast.h b/python/src/core/codac2_py_cast.h new file mode 100644 index 000000000..959a41649 --- /dev/null +++ b/python/src/core/codac2_py_cast.h @@ -0,0 +1,107 @@ +/** + * \file + * Codac binding (core) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2021 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include +#include + +namespace py = pybind11; +using namespace pybind11::literals; + +namespace codac2 +{ + // Common caster + + template + bool is_instance(const py::object& x) + { + return py::isinstance(x); + } + + template + const T& cast(const py::object& x) + { + if(!is_instance(x)) + { assert_release("cast error"); } + return x.cast(); + } + + // Casting to trajectory types + + template + requires std::is_same_v + bool is_instance(const py::object& x) + { + const py::object& x_traj = x.attr("traj"); + return x_traj && py::isinstance(x_traj); + } + + template + requires std::is_same_v + const Tr& cast(const py::object& x) + { + assert(is_instance(x)); + const py::object& x_traj = x.attr("traj"); + return x_traj.cast(); + } + + // Casting to function/expression types + + template + requires std::is_same_v + const T& cast(const py::object& x) + { + if(!is_instance(x)) + { assert("unable to cast the provided py::object into a ScalarExpr"); } + return x.cast(); + } + + template + requires std::is_same_v> + T cast(const py::object& x) + { + if(!py::isinstance(x) + && !py::isinstance(x) + && !py::isinstance(x)) + { assert("unable to cast the provided py::object into a ExprBase"); } + + if(py::isinstance(x)) + return x.cast()->copy(); + + else if(py::isinstance(x)) + return x.cast()->copy(); + + else + return x.cast()->copy(); + } + + template + requires (std::is_same_v,T> + || std::is_same_v,T> + || std::is_same_v,T>) + bool is_instance(const py::object& x) + { + const py::object& f_ = x.attr("f"); + return f_ && py::isinstance(f_); + } + + template + requires (std::is_same_v,T> + || std::is_same_v,T> + || std::is_same_v,T>) + const T& cast(const py::object& x) + { + assert(is_instance(x)); + const py::object& f_ = x.attr("f"); + return f_.cast(); + } +} \ No newline at end of file diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index f15069498..cb8257c8e 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -20,6 +20,7 @@ #include "codac2_py_AnalyticFunction_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) #include "codac2_py_FunctionBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py) #include "codac2_py_AnalyticExprWrapper.h" +#include "codac2_py_cast.h" using namespace codac2; namespace py = pybind11; @@ -89,44 +90,6 @@ using namespace pybind11::literals; \ ; \ - -AnalyticExprWrapper pyobj_to_ScalarExpr(const py::object& obj) -{ - if(py::isinstance(obj)) - return obj.cast(); - assert(false && "unable to convert py::object to ScalarExpr"); - return { nullptr }; -} - -template -AnalyticFunction cast_to_AnalyticFunction(const py::object& f) -{ - py::object f_ = f.attr("f"); - - if(!f_) - assert_release("cast_function: py::object f has no attribute named 'f'"); - - if(!py::isinstance>(f_)) - assert_release("cast_function: provided analytic function has incorrect type"); - - return f_.cast>(); -} - -std::shared_ptr pyobj_to_ExprBase(const py::object& obj) -{ - if(obj) - { - if(py::isinstance>(obj)) - return obj.cast>()->copy(); - - else if(py::isinstance>(obj)) - return obj.cast>()->copy(); - } - - assert_release("invalid expression"); - return nullptr; -} - FunctionArgsList create_FunctionArgsList(const std::vector& l) { FunctionArgsList args {}; @@ -179,63 +142,63 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) { case 1: return vec( - pyobj_to_ScalarExpr(v_expr[0]) + cast(v_expr[0]) ); case 2: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]) + cast(v_expr[0]), cast(v_expr[1]) ); case 3: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), - pyobj_to_ScalarExpr(v_expr[2]) + cast(v_expr[0]), cast(v_expr[1]), + cast(v_expr[2]) ); case 4: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), - pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]) + cast(v_expr[0]), cast(v_expr[1]), + cast(v_expr[2]), cast(v_expr[3]) ); case 5: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), - pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), - pyobj_to_ScalarExpr(v_expr[4]) + cast(v_expr[0]), cast(v_expr[1]), + cast(v_expr[2]), cast(v_expr[3]), + cast(v_expr[4]) ); case 6: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), - pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), - pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]) + cast(v_expr[0]), cast(v_expr[1]), + cast(v_expr[2]), cast(v_expr[3]), + cast(v_expr[4]), cast(v_expr[5]) ); case 7: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), - pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), - pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]), - pyobj_to_ScalarExpr(v_expr[6]) + cast(v_expr[0]), cast(v_expr[1]), + cast(v_expr[2]), cast(v_expr[3]), + cast(v_expr[4]), cast(v_expr[5]), + cast(v_expr[6]) ); case 8: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), - pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), - pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]), - pyobj_to_ScalarExpr(v_expr[6]), pyobj_to_ScalarExpr(v_expr[7]) + cast(v_expr[0]), cast(v_expr[1]), + cast(v_expr[2]), cast(v_expr[3]), + cast(v_expr[4]), cast(v_expr[5]), + cast(v_expr[6]), cast(v_expr[7]) ); case 9: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), - pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), - pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]), - pyobj_to_ScalarExpr(v_expr[6]), pyobj_to_ScalarExpr(v_expr[7]), - pyobj_to_ScalarExpr(v_expr[8]) + cast(v_expr[0]), cast(v_expr[1]), + cast(v_expr[2]), cast(v_expr[3]), + cast(v_expr[4]), cast(v_expr[5]), + cast(v_expr[6]), cast(v_expr[7]), + cast(v_expr[8]) ); case 10: return vec( - pyobj_to_ScalarExpr(v_expr[0]), pyobj_to_ScalarExpr(v_expr[1]), - pyobj_to_ScalarExpr(v_expr[2]), pyobj_to_ScalarExpr(v_expr[3]), - pyobj_to_ScalarExpr(v_expr[4]), pyobj_to_ScalarExpr(v_expr[5]), - pyobj_to_ScalarExpr(v_expr[6]), pyobj_to_ScalarExpr(v_expr[7]), - pyobj_to_ScalarExpr(v_expr[8]), pyobj_to_ScalarExpr(v_expr[9]) + cast(v_expr[0]), cast(v_expr[1]), + cast(v_expr[2]), cast(v_expr[3]), + cast(v_expr[4]), cast(v_expr[5]), + cast(v_expr[6]), cast(v_expr[7]), + cast(v_expr[8]), cast(v_expr[9]) ); default: assert_release("cannot create AnalyticFunction with provided vector arguments"); @@ -256,7 +219,7 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) { std::vector> v(x.size()); for(size_t i = 0 ; i < x.size() ; i++) - v[i] = pyobj_to_ExprBase(x[i]); + v[i] = cast>(x[i]); return AnalyticExprWrapper(std::dynamic_pointer_cast>(f(v)->copy())); }, SHARED_PTR_E_FUNCTIONBASE_E_OPERATORCALL_CONST_X_REF_VARIADIC_CONST) diff --git a/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp b/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp index 29ddaf39e..c7fc6f60c 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_operations.cpp @@ -27,67 +27,67 @@ void export_expression_operations(py::module& m) { m - .def("pow", [](const ScalarExpr& e1, const ScalarExpr& e2) { return ScalarExpr(pow(e1,e2)); }, + .def("pow", [](const ScalarExpr& e1, const ScalarExpr& e2) { return pow(e1,e2); }, SCALAREXPR_POW_CONST_SCALAREXPR_REF_CONST_SCALAREXPR_REF, "x1"_a, "x2"_a) - .def("sqr", [](const ScalarExpr& e1) { return ScalarExpr(sqr(e1)); }, + .def("sqr", [](const ScalarExpr& e1) { return sqr(e1); }, SCALAREXPR_SQR_CONST_SCALAREXPR_REF, "x1"_a) - .def("sqrt", [](const ScalarExpr& e1) { return ScalarExpr(sqrt(e1)); }, + .def("sqrt", [](const ScalarExpr& e1) { return sqrt(e1); }, SCALAREXPR_SQRT_CONST_SCALAREXPR_REF, "x1"_a) - .def("exp", [](const ScalarExpr& e1) { return ScalarExpr(exp(e1)); }, + .def("exp", [](const ScalarExpr& e1) { return exp(e1); }, SCALAREXPR_EXP_CONST_SCALAREXPR_REF, "x1"_a) - .def("log", [](const ScalarExpr& e1) { return ScalarExpr(log(e1)); }, + .def("log", [](const ScalarExpr& e1) { return log(e1); }, SCALAREXPR_LOG_CONST_SCALAREXPR_REF, "x1"_a) - .def("cos", [](const ScalarExpr& e1) { return ScalarExpr(cos(e1)); }, + .def("cos", [](const ScalarExpr& e1) { return cos(e1); }, SCALAREXPR_COS_CONST_SCALAREXPR_REF, "x1"_a) - .def("sin", [](const ScalarExpr& e1) { return ScalarExpr(sin(e1)); }, + .def("sin", [](const ScalarExpr& e1) { return sin(e1); }, SCALAREXPR_SIN_CONST_SCALAREXPR_REF, "x1"_a) - .def("tan", [](const ScalarExpr& e1) { return ScalarExpr(tan(e1)); }, + .def("tan", [](const ScalarExpr& e1) { return tan(e1); }, SCALAREXPR_TAN_CONST_SCALAREXPR_REF, "x1"_a) - .def("acos", [](const ScalarExpr& e1) { return ScalarExpr(acos(e1)); }, + .def("acos", [](const ScalarExpr& e1) { return acos(e1); }, SCALAREXPR_ACOS_CONST_SCALAREXPR_REF, "x1"_a) - .def("asin", [](const ScalarExpr& e1) { return ScalarExpr(asin(e1)); }, + .def("asin", [](const ScalarExpr& e1) { return asin(e1); }, SCALAREXPR_ASIN_CONST_SCALAREXPR_REF, "x1"_a) - .def("atan", [](const ScalarExpr& e1) { return ScalarExpr(atan(e1)); }, + .def("atan", [](const ScalarExpr& e1) { return atan(e1); }, SCALAREXPR_ATAN_CONST_SCALAREXPR_REF, "x1"_a) - .def("atan2", [](const ScalarExpr& e1, const ScalarExpr& e2) { return ScalarExpr(atan2(e1,e2)); }, + .def("atan2", [](const ScalarExpr& e1, const ScalarExpr& e2) { return atan2(e1,e2); }, SCALAREXPR_ATAN2_CONST_SCALAREXPR_REF_CONST_SCALAREXPR_REF, - "x1"_a, "x2"_a) + "y"_a, "x"_a) - .def("cosh", [](const ScalarExpr& e1) { return ScalarExpr(cosh(e1)); }, + .def("cosh", [](const ScalarExpr& e1) { return cosh(e1); }, SCALAREXPR_COSH_CONST_SCALAREXPR_REF, "x1"_a) - .def("sinh", [](const ScalarExpr& e1) { return ScalarExpr(sinh(e1)); }, + .def("sinh", [](const ScalarExpr& e1) { return sinh(e1); }, SCALAREXPR_SINH_CONST_SCALAREXPR_REF, "x1"_a) - .def("tanh", [](const ScalarExpr& e1) { return ScalarExpr(tanh(e1)); }, + .def("tanh", [](const ScalarExpr& e1) { return tanh(e1); }, SCALAREXPR_TANH_CONST_SCALAREXPR_REF, "x1"_a) - .def("abs", [](const ScalarExpr& e1) { return ScalarExpr(abs(e1)); }, + .def("abs", [](const ScalarExpr& e1) { return abs(e1); }, SCALAREXPR_ABS_CONST_SCALAREXPR_REF, "x1"_a) @@ -96,15 +96,15 @@ void export_expression_operations(py::module& m) const char* EVAL_VEC_DOC = VECTOREXPR_VEC_CONST_ANALYTICEXPRWRAPPER_X_REF_VARIADIC; using S = const ScalarExpr&; - m .def("vec", [](S e1) { return VectorExpr(vec(e1)); }, EVAL_VEC_DOC, "x1"_a) - .def("vec", [](S e1, S e2) { return VectorExpr(vec(e1,e2)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a) - .def("vec", [](S e1, S e2, S e3) { return VectorExpr(vec(e1,e2,e3)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a) - .def("vec", [](S e1, S e2, S e3, S e4) { return VectorExpr(vec(e1,e2,e3,e4)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5) { return VectorExpr(vec(e1,e2,e3,e4,e5)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6,e7)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6,e7,e8)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8, S e9) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6,e7,e8,e9)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a,"x9"_a) - .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8, S e9, S e10) { return VectorExpr(vec(e1,e2,e3,e4,e5,e6,e7,e8,e9,e10)); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a,"x9"_a,"x10"_a) + m .def("vec", [](S e1) { return vec(e1); }, EVAL_VEC_DOC, "x1"_a) + .def("vec", [](S e1, S e2) { return vec(e1,e2); }, EVAL_VEC_DOC, "x1"_a,"x2"_a) + .def("vec", [](S e1, S e2, S e3) { return vec(e1,e2,e3); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a) + .def("vec", [](S e1, S e2, S e3, S e4) { return vec(e1,e2,e3,e4); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5) { return vec(e1,e2,e3,e4,e5); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6) { return vec(e1,e2,e3,e4,e5,e6); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7) { return vec(e1,e2,e3,e4,e5,e6,e7); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8) { return vec(e1,e2,e3,e4,e5,e6,e7,e8); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8, S e9) { return vec(e1,e2,e3,e4,e5,e6,e7,e8,e9); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a,"x9"_a) + .def("vec", [](S e1, S e2, S e3, S e4, S e5, S e6, S e7, S e8, S e9, S e10) { return vec(e1,e2,e3,e4,e5,e6,e7,e8,e9,e10); }, EVAL_VEC_DOC, "x1"_a,"x2"_a,"x3"_a,"x4"_a,"x5"_a,"x6"_a,"x7"_a,"x8"_a,"x9"_a,"x10"_a) ; } \ No newline at end of file diff --git a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp index d397409f1..e94142577 100644 --- a/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp +++ b/python/src/core/functions/analytic/codac2_py_analytic_variables.cpp @@ -34,27 +34,27 @@ void export_ScalarVar(py::module& m) .def("size", &ScalarVar::size, INDEX_SCALARVAR_SIZE_CONST) - .def("__pos__", [](const ScalarVar& e1) { return ScalarExpr(ScalarExpr(e1)); }, py::is_operator()) - .def("__add__", [](const ScalarVar& e1, const ScalarVar& e2) { return ScalarExpr(ScalarExpr(e1) + ScalarExpr(e2)); }, py::is_operator()) - .def("__add__", [](const ScalarVar& e1, const ScalarExpr& e2) { return ScalarExpr(ScalarExpr(e1) + e2); }, py::is_operator()) - .def("__add__", [](const ScalarVar& e1, const Interval& e2) { return ScalarExpr(ScalarExpr(e1) + ScalarExpr(e2)); }, py::is_operator()) - .def("__radd__", [](const ScalarVar& e1, const Interval& e2) { return ScalarExpr(ScalarExpr(e2) + ScalarExpr(e1)); }, py::is_operator()) - .def("__neg__", [](const ScalarVar& e1) { return ScalarExpr(-ScalarExpr(e1)); }, py::is_operator()) - .def("__sub__", [](const ScalarVar& e1, const ScalarVar& e2) { return ScalarExpr(ScalarExpr(e1) - ScalarExpr(e2)); }, py::is_operator()) - .def("__sub__", [](const ScalarVar& e1, const ScalarExpr& e2) { return ScalarExpr(ScalarExpr(e1) - e2); }, py::is_operator()) - .def("__sub__", [](const ScalarVar& e1, const Interval& e2) { return ScalarExpr(ScalarExpr(e1) - ScalarExpr(e2)); }, py::is_operator()) - .def("__rsub__", [](const ScalarVar& e1, const Interval& e2) { return ScalarExpr(ScalarExpr(e2) - ScalarExpr(e1)); }, py::is_operator()) - .def("__mul__", [](const ScalarVar& e1, const ScalarVar& e2) { return ScalarExpr(ScalarExpr(e1) * ScalarExpr(e2)); }, py::is_operator()) - .def("__mul__", [](const ScalarVar& e1, const ScalarExpr& e2) { return ScalarExpr(ScalarExpr(e1) * e2); }, py::is_operator()) - .def("__mul__", [](const ScalarVar& e1, const Interval& e2) { return ScalarExpr(ScalarExpr(e1) * ScalarExpr(e2)); }, py::is_operator()) - .def("__rmul__", [](const ScalarVar& e1, const Interval& e2) { return ScalarExpr(ScalarExpr(e2) * ScalarExpr(e1)); }, py::is_operator()) - .def("__mul__", [](const ScalarVar& e1, const VectorVar& e2) { return VectorExpr(ScalarExpr(e1) * VectorExpr(e2)); }, py::is_operator()) - .def("__mul__", [](const ScalarVar& e1, const VectorExpr& e2) { return VectorExpr(ScalarExpr(e1) * e2); }, py::is_operator()) - .def("__mul__", [](const ScalarVar& e1, const IntervalVector& e2) { return VectorExpr(ScalarExpr(e1) * VectorExpr(e2)); }, py::is_operator()) - .def("__truediv__", [](const ScalarVar& e1, const ScalarVar& e2) { return ScalarExpr(ScalarExpr(e1) / ScalarExpr(e2)); }, py::is_operator()) - .def("__truediv__", [](const ScalarVar& e1, const ScalarExpr& e2) { return ScalarExpr(ScalarExpr(e1) / e2); }, py::is_operator()) - .def("__truediv__", [](const ScalarVar& e1, const Interval& e2) { return ScalarExpr(ScalarExpr(e1) / ScalarExpr(e2)); }, py::is_operator()) - .def("__rtruediv__", [](const ScalarVar& e1, const Interval& e2) { return ScalarExpr(ScalarExpr(e2) / ScalarExpr(e1)); }, py::is_operator()) + .def("__pos__", [](const ScalarVar& e1) { return e1; }, py::is_operator()) + .def("__add__", [](const ScalarVar& e1, const ScalarVar& e2) { return e1 + e2; }, py::is_operator()) + .def("__add__", [](const ScalarVar& e1, const ScalarExpr& e2) { return e1 + e2; }, py::is_operator()) + .def("__add__", [](const ScalarVar& e1, const Interval& e2) { return e1 + e2; }, py::is_operator()) + .def("__radd__", [](const ScalarVar& e1, const Interval& e2) { return e2 + e1; }, py::is_operator()) + .def("__neg__", [](const ScalarVar& e1) { return -e1; }, py::is_operator()) + .def("__sub__", [](const ScalarVar& e1, const ScalarVar& e2) { return e1 - e2; }, py::is_operator()) + .def("__sub__", [](const ScalarVar& e1, const ScalarExpr& e2) { return e1 - e2; }, py::is_operator()) + .def("__sub__", [](const ScalarVar& e1, const Interval& e2) { return e1 - e2; }, py::is_operator()) + .def("__rsub__", [](const ScalarVar& e1, const Interval& e2) { return e2 - e1; }, py::is_operator()) + .def("__mul__", [](const ScalarVar& e1, const ScalarVar& e2) { return e1 * e2; }, py::is_operator()) + .def("__mul__", [](const ScalarVar& e1, const ScalarExpr& e2) { return e1 * e2; }, py::is_operator()) + .def("__mul__", [](const ScalarVar& e1, const Interval& e2) { return e1 * e2; }, py::is_operator()) + .def("__rmul__", [](const ScalarVar& e1, const Interval& e2) { return e2 * e1; }, py::is_operator()) + .def("__mul__", [](const ScalarVar& e1, const VectorVar& e2) { return e1 * e2; }, py::is_operator()) + .def("__mul__", [](const ScalarVar& e1, const VectorExpr& e2) { return e1 * e2; }, py::is_operator()) + .def("__mul__", [](const ScalarVar& e1, const IntervalVector& e2) { return e1 * e2; }, py::is_operator()) + .def("__truediv__", [](const ScalarVar& e1, const ScalarVar& e2) { return e1 / e2; }, py::is_operator()) + .def("__truediv__", [](const ScalarVar& e1, const ScalarExpr& e2) { return e1 / e2; }, py::is_operator()) + .def("__truediv__", [](const ScalarVar& e1, const Interval& e2) { return e1 / e2; }, py::is_operator()) + .def("__rtruediv__", [](const ScalarVar& e1, const Interval& e2) { return e2 / e1; }, py::is_operator()) ; py::implicitly_convertible(); @@ -68,7 +68,7 @@ ScalarExpr get_item(const VectorVar& v, Index_type i) if(i < 0 || i >= static_cast(v.size())) throw py::index_error("index is out of range"); - return ScalarExpr(std::dynamic_pointer_cast>(v[static_cast(i)]->copy())); + return v[static_cast(i)]; } void export_VectorVar(py::module& m) @@ -107,20 +107,19 @@ void export_VectorVar(py::module& m) .def("subvector", [](const VectorVar& v, Index_type i, Index_type j) -> VectorExpr { matlab::test_integer(i, j); - return VectorExpr(std::dynamic_pointer_cast>( - v.subvector(matlab::input_index(i),matlab::input_index(j))->copy())); + return v.subvector(matlab::input_index(i),matlab::input_index(j)); }, ANALYTICEXPRWRAPPER_VECTORTYPE_VECTORVAR_SUBVECTOR_INDEX_INDEX_CONST) - .def("__pos__", [](const VectorVar& e1) { return VectorExpr(VectorExpr(e1)); }, py::is_operator()) - .def("__add__", [](const VectorVar& e1, const VectorVar& e2) { return VectorExpr(VectorExpr(e1) + VectorExpr(e2)); }, py::is_operator()) - .def("__add__", [](const VectorVar& e1, const IntervalVector& e2) { return VectorExpr(VectorExpr(e1) + VectorExpr(e2)); }, py::is_operator()) - .def("__add__", [](const VectorVar& e1, const VectorExpr& e2) { return VectorExpr(e1)+e2; }, py::is_operator()) - .def("__radd__", [](const VectorVar& e1, const IntervalVector& e2) { return VectorExpr(VectorExpr(e2) + VectorExpr(e1)); }, py::is_operator()) - .def("__neg__", [](const VectorVar& e1) { return VectorExpr(-VectorExpr(e1)); }, py::is_operator()) - .def("__sub__", [](const VectorVar& e1, const VectorVar& e2) { return VectorExpr(VectorExpr(e1) - VectorExpr(e2)); }, py::is_operator()) - .def("__sub__", [](const VectorVar& e1, const VectorExpr& e2) { return VectorExpr(e1)-e2; }, py::is_operator()) - .def("__sub__", [](const VectorVar& e1, const IntervalVector& e2) { return VectorExpr(VectorExpr(e1) - VectorExpr(e2)); }, py::is_operator()) - .def("__rsub__", [](const VectorVar& e1, const IntervalVector& e2) { return VectorExpr(VectorExpr(e2) - VectorExpr(e1)); }, py::is_operator()) + .def("__pos__", [](const VectorVar& e1) { return e1; }, py::is_operator()) + .def("__add__", [](const VectorVar& e1, const VectorVar& e2) { return e1 + e2; }, py::is_operator()) + .def("__add__", [](const VectorVar& e1, const IntervalVector& e2) { return e1 + e2; }, py::is_operator()) + .def("__add__", [](const VectorVar& e1, const VectorExpr& e2) { return e1 + e2; }, py::is_operator()) + .def("__radd__", [](const VectorVar& e1, const IntervalVector& e2) { return e2 + e1; }, py::is_operator()) + .def("__neg__", [](const VectorVar& e1) { return -e1; }, py::is_operator()) + .def("__sub__", [](const VectorVar& e1, const VectorVar& e2) { return e1 - e2; }, py::is_operator()) + .def("__sub__", [](const VectorVar& e1, const VectorExpr& e2) { return e1 - e2; }, py::is_operator()) + .def("__sub__", [](const VectorVar& e1, const IntervalVector& e2) { return e1 - e2; }, py::is_operator()) + .def("__rsub__", [](const VectorVar& e1, const IntervalVector& e2) { return e2 - e1; }, py::is_operator()) ; py::implicitly_convertible(); diff --git a/python/src/core/paver/codac2_py_pave.cpp b/python/src/core/paver/codac2_py_pave.cpp index 685f1b9bf..8ad665770 100644 --- a/python/src/core/paver/codac2_py_pave.cpp +++ b/python/src/core/paver/codac2_py_pave.cpp @@ -12,6 +12,7 @@ #include #include #include "codac2_py_pave_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_cast.h" using namespace std; using namespace codac2; @@ -28,11 +29,25 @@ void export_pave(py::module& m) PAVINGINOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_SEPBASE_REF_DOUBLE, "x"_a, "s"_a, "eps"_a); - m.def("sivia_", (PavingInOut (*)(const IntervalVector&,const AnalyticFunction&,const Interval&,double))&codac2::sivia, - PAVINGINOUT_SIVIA_CONST_INTERVALVECTOR_REF_CONST_ANALYTICFUNCTION_Y_REF_CONST_TYPENAME_Y_DOMAIN_REF_DOUBLE, - "x"_a, "f"_a, "y"_a, "eps"_a); + m.def("sivia", + [](const IntervalVector& x, const py::object& f, const py::object& y, double eps) + { + if(!is_instance>(f) + && !is_instance>(f) + && !is_instance>(f)) + { + assert_release("sivia: invalid function type"); + } + + if(is_instance>(f)) + return sivia(x, cast>(f), y.cast(), eps); + + else if(is_instance>(f)) + return sivia(x, cast>(f), y.cast(), eps); - m.def("sivia_", (PavingInOut (*)(const IntervalVector&,const AnalyticFunction&,const IntervalVector&,double))&codac2::sivia, + else + return sivia(x, cast>(f), y.cast(), eps); + }, PAVINGINOUT_SIVIA_CONST_INTERVALVECTOR_REF_CONST_ANALYTICFUNCTION_Y_REF_CONST_TYPENAME_Y_DOMAIN_REF_DOUBLE, "x"_a, "f"_a, "y"_a, "eps"_a); } \ No newline at end of file diff --git a/python/src/core/separators/codac2_py_SepInverse.h b/python/src/core/separators/codac2_py_SepInverse.h index 0ca6a4cf5..de7ef2ca5 100644 --- a/python/src/core/separators/codac2_py_SepInverse.h +++ b/python/src/core/separators/codac2_py_SepInverse.h @@ -16,6 +16,7 @@ #include "codac2_py_SepInverse_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_SepCtcPair_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_AnalyticFunction.h" +#include "codac2_py_cast.h" using namespace std; using namespace codac2; @@ -29,7 +30,9 @@ void export_SepInverse_type(py::class_& exported) .def(py::init( [](const py::object& f, const typename T::Domain& y, bool with_centered_form) { - return std::make_unique(cast_to_AnalyticFunction(f), y, with_centered_form); + return std::make_unique( + cast>(f), + y, with_centered_form); } ), SEPINVERSE_SEPINVERSE_CONST_ANALYTICFUNCTION_T_REF_CONST_TYPENAME_T_DOMAIN_REF_BOOL, @@ -41,7 +44,9 @@ void export_SepInverse_type(py::class_& exported) .def(py::init( [](const py::object& f, const pySep& s, bool with_centered_form) { - return std::make_unique(cast_to_AnalyticFunction(f), s, with_centered_form); + return std::make_unique( + cast>(f), + s, with_centered_form); } ), SEPINVERSE_SEPINVERSE_CONST_ANALYTICFUNCTION_T_REF_CONST_S_REF_BOOL, diff --git a/python/src/core/separators/codac2_py_SepTransform.cpp b/python/src/core/separators/codac2_py_SepTransform.cpp index 19e8751a8..67edcde97 100644 --- a/python/src/core/separators/codac2_py_SepTransform.cpp +++ b/python/src/core/separators/codac2_py_SepTransform.cpp @@ -14,6 +14,7 @@ #include #include "codac2_py_Sep.h" #include "codac2_py_SepTransform_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_cast.h" using namespace std; using namespace codac2; @@ -22,19 +23,16 @@ using namespace pybind11::literals; void export_SepTransform(py::module& m, py::class_& pysep) { - using FNC = AnalyticFunction; - py::class_ exported(m, "SepTransform", pysep, SEPTRANSFORM_MAIN); exported .def(py::init( [](const SepBase& s, const py::object& f, const py::object& f_inv) { - py::object _f = f.attr("f"), _f_inv = f_inv.attr("f"); - assert_release(py::isinstance(_f) && py::isinstance(_f_inv) - && "SepTransform: provided arguments are not vectorial AnalyticFunctions"); - - return std::make_unique(s.copy(), _f.cast(), _f_inv.cast()); + return std::make_unique( + s.copy(), + cast>(f), + cast>(f_inv)); }), SEPTRANSFORM_SEPTRANSFORM_CONST_S_REF_CONST_ANALYTICFUNCTION_VECTORTYPE_REF_CONST_ANALYTICFUNCTION_VECTORTYPE_REF, "s"_a, "f"_a, "f_inv"_a) diff --git a/python/src/graphics/CMakeLists.txt b/python/src/graphics/CMakeLists.txt index 8b5add113..bb3fc85a3 100644 --- a/python/src/graphics/CMakeLists.txt +++ b/python/src/graphics/CMakeLists.txt @@ -19,6 +19,7 @@ target_include_directories(_graphics PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../../docstring PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../../../include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../core/ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/figures/ diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index dc943a1ac..b08cd58b6 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -13,6 +13,7 @@ #include #include "codac2_py_Figure2D_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_matlab.h" +#include "codac2_py_cast.h" #include using namespace std; @@ -136,50 +137,24 @@ void export_Figure2D(py::module& m) .def("draw_trajectory", [](Figure2D& fig, const py::object& x, const StyleProperties& s) { - py::object x_traj = x.attr("traj"); - - if(x_traj) - { - if(py::isinstance>(x_traj)) - { - fig.draw_trajectory(x_traj.cast>(),s); - return; - } - - else if(py::isinstance>(x_traj)) - { - fig.draw_trajectory(x_traj.cast>(),s); - return; - } - } - - assert_release(false && - "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); + if(is_instance>(x)) + return fig.draw_trajectory(cast>(x),s); + else if(is_instance>(x)) + return fig.draw_trajectory(cast>(x),s); + else + assert_release(false && "invalid provided trajectory"); }, VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) - .def("draw_trajectory", [](Figure2D& fig, py::object x, const ColorMap& cmap) + .def("draw_trajectory", [](Figure2D& fig, const py::object& x, const ColorMap& cmap) { - py::object x_traj = x.attr("traj"); - - if(x_traj) - { - if(py::isinstance>(x_traj)) - { - fig.draw_trajectory(x_traj.cast>(),cmap); - return; - } - - else if(py::isinstance>(x_traj)) - { - fig.draw_trajectory(x_traj.cast>(),cmap); - return; - } - } - - assert_release(false && - "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); + if(is_instance>(x)) + return fig.draw_trajectory(cast>(x),cmap); + else if(is_instance>(x)) + return fig.draw_trajectory(cast>(x),cmap); + else + assert_release(false && "invalid provided trajectory"); }, VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "cmap"_a) @@ -265,50 +240,24 @@ void export_Figure2D(py::module& m) .def_static("draw_trajectory", [](const py::object& x, const StyleProperties& s) { - py::object x_traj = x.attr("traj"); - - if(x_traj) - { - if(py::isinstance>(x_traj)) - { - DefaultView::draw_trajectory(x_traj.cast>(),s); - return; - } - - else if(py::isinstance>(x_traj)) - { - DefaultView::draw_trajectory(x_traj.cast>(),s); - return; - } - } - - assert_release(false && - "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); + if(is_instance>(x)) + return DefaultView::draw_trajectory(cast>(x),s); + else if(is_instance>(x)) + return DefaultView::draw_trajectory(cast>(x),s); + else + assert_release(false && "invalid provided trajectory"); }, VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) .def_static("draw_trajectory", [](py::object x, const ColorMap& cmap) { - py::object x_traj = x.attr("traj"); - - if(x_traj) - { - if(py::isinstance>(x_traj)) - { - DefaultView::draw_trajectory(x_traj.cast>(),cmap); - return; - } - - else if(py::isinstance>(x_traj)) - { - DefaultView::draw_trajectory(x_traj.cast>(),cmap); - return; - } - } - - assert_release(false && - "provided trajectory is not of type AnalyticTrajectory or SampledTrajectory"); + if(is_instance>(x)) + return DefaultView::draw_trajectory(cast>(x),cmap); + else if(is_instance>(x)) + return DefaultView::draw_trajectory(cast>(x),cmap); + else + assert_release(false && "invalid provided trajectory"); }, VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "cmap"_a) From cefbce468c8223f0a0cfb1e06b6308fe13c08d5a Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sat, 28 Dec 2024 19:03:54 +0100 Subject: [PATCH 056/126] [fnc] restoring copy constructors --- src/core/functions/analytic/codac2_AnalyticExpr.h | 12 ++++++++++++ .../functions/analytic/codac2_AnalyticExprWrapper.h | 4 ++++ .../functions/analytic/codac2_AnalyticFunction.h | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/src/core/functions/analytic/codac2_AnalyticExpr.h b/src/core/functions/analytic/codac2_AnalyticExpr.h index 671c285d6..69bab2a30 100644 --- a/src/core/functions/analytic/codac2_AnalyticExpr.h +++ b/src/core/functions/analytic/codac2_AnalyticExpr.h @@ -63,6 +63,10 @@ namespace codac2 : OperationExprBase...>(x...) { } + AnalyticOperationExpr(const AnalyticOperationExpr& e) + : OperationExprBase...>(e) + { } + std::shared_ptr copy() const { return std::make_shared>(*this); @@ -120,6 +124,10 @@ namespace codac2 : OperationExprBase>(x1), _i(i) { } + AnalyticOperationExpr(const AnalyticOperationExpr& e) + : OperationExprBase>(e), _i(e._i) + { } + std::shared_ptr copy() const { return std::make_shared>(*this); @@ -161,6 +169,10 @@ namespace codac2 : OperationExprBase>(x1), _i(i), _j(j) { } + AnalyticOperationExpr(const AnalyticOperationExpr& e) + : OperationExprBase>(e), _i(e._i), _j(e._j) + { } + std::shared_ptr copy() const { return std::make_shared>(*this); diff --git a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h index d2756e835..c11828a9b 100644 --- a/src/core/functions/analytic/codac2_AnalyticExprWrapper.h +++ b/src/core/functions/analytic/codac2_AnalyticExprWrapper.h @@ -24,6 +24,10 @@ namespace codac2 template struct AnalyticExprWrapper : public std::shared_ptr> { + AnalyticExprWrapper(const AnalyticExprWrapper& e) + : std::shared_ptr>(e) + { } + AnalyticExprWrapper(const std::shared_ptr>& e) : std::shared_ptr>(e) { } diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index ded5cc69e..e7b066f61 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -59,6 +59,10 @@ namespace codac2 : AnalyticFunction(args, { std::dynamic_pointer_cast>(y.copy()) }) { } + AnalyticFunction(const AnalyticFunction& f) + : FunctionBase>(f) + { } + template AnalyticExprWrapper operator()(const X&... x) const { From 86288875604d3e882fd40f2f37b666439bb1fe2f Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Sat, 28 Dec 2024 19:32:57 +0100 Subject: [PATCH 057/126] [tests] added parabolas example in tests --- .../contractors/codac2_tests_CtcInverse.cpp | 36 +++++++++++++++++++ .../contractors/codac2_tests_CtcInverse.py | 29 +++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/tests/core/contractors/codac2_tests_CtcInverse.cpp b/tests/core/contractors/codac2_tests_CtcInverse.cpp index 666c00840..a57216142 100644 --- a/tests/core/contractors/codac2_tests_CtcInverse.cpp +++ b/tests/core/contractors/codac2_tests_CtcInverse.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include using namespace std; using namespace codac2; @@ -166,4 +168,38 @@ TEST_CASE("CtcInverse") //DefaultView::draw_box(b,Color::blue()); } } +} + +TEST_CASE("ParabolasExample") +{ + ScalarVar u; + ScalarVar v; + VectorVar a(4); + VectorVar a0(3); VectorVar a1(3); VectorVar a2(3); + VectorVar b0(3); VectorVar b1(3); VectorVar b2(3); + + AnalyticFunction b({u,a0,a1,a2}, sqr(1-u)*a0+2*u*(1-u)*a1+sqr(u)*a2); + AnalyticFunction f({u,v,a0,a1,a2,b0,b1,b2}, (1-v)*b(u,a0,a1,a2)+v*b(u,b0,b1,b2)); + + AnalyticFunction h({a}, + f(a[0],a[1], + Vector({0,0,0}),Vector({1,0,1}),Vector({2,0,0}), + Vector({0,2,0}),Vector({1,2,1}),Vector({2,2,0})) + -f(a[2],a[3], + Vector({0,0,0.55}),Vector({0,1,-0.45}),Vector({0,2,0.55}), + Vector({2,0,0.55}),Vector({2,1,-0.45}),Vector({2,2,0.55})) + ); + + CtcInverse_ ctc(h, IntervalVector::zero(3)); + IntervalVector x0 {{0,1},{0,1},{0,0.2},{0,0.2}}; + //draw_while_paving(x0, ctc, 0.001); + auto p = pave(x0, ctc, 0.01); + auto cs = p.connected_subsets(); + CHECK(cs.size() == 1); + CHECK(Approx(cs.begin()->box(),1e-4) == IntervalVector({ + {0.13244,0.201099}, + {0.131459,0.202575}, + {0.132274,0.200001}, + {0.132283,0.200001} + })); } \ No newline at end of file diff --git a/tests/core/contractors/codac2_tests_CtcInverse.py b/tests/core/contractors/codac2_tests_CtcInverse.py index 1a8ac9457..21586f412 100644 --- a/tests/core/contractors/codac2_tests_CtcInverse.py +++ b/tests/core/contractors/codac2_tests_CtcInverse.py @@ -98,6 +98,35 @@ def tests_CtcInverse_3(self): b = IntervalVector([[2,3],[-1,1]]) c.contract(b) self.assertTrue(b == IntervalVector.empty(2)) + + def tests_ParabolasExample(self): + + u = ScalarVar() + v = ScalarVar() + a = VectorVar(4) + a0 = VectorVar(3); a1 = VectorVar(3); a2 = VectorVar(3) + b0 = VectorVar(3); b1 = VectorVar(3); b2 = VectorVar(3) + + b = AnalyticFunction([u,a0,a1,a2], sqr(1-u)*a0+2*u*(1-u)*a1+sqr(u)*a2) + f = AnalyticFunction([u,v,a0,a1,a2,b0,b1,b2], (1-v)*b(u,a0,a1,a2)+v*b(u,b0,b1,b2)) + + h = AnalyticFunction([a], + f(a[0],a[1], + IntervalVector([[0],[0],[0]]),IntervalVector([[1],[0],[1]]),IntervalVector([[2],[0],[0]]), + IntervalVector([[0],[2],[0]]),IntervalVector([[1],[2],[1]]),IntervalVector([[2],[2],[0]])) + -f(a[2],a[3], + IntervalVector([[0],[0],[0.55]]),IntervalVector([[0],[1],[-0.45]]),IntervalVector([[0],[2],[0.55]]), + IntervalVector([[2],[0],[0.55]]),IntervalVector([[2],[1],[-0.45]]),IntervalVector([[2],[2],[0.55]])) + ) + + ctc = CtcInverse(h, [0,0,0]) + x0 = [[0,1],[0,1],[0,0.2],[0,0.2]] + #draw_while_paving(x0, ctc, 0.001) + p = pave(x0, ctc, 0.01) + cs = p.connected_subsets() + self.assertTrue(len(cs) == 1) + self.assertTrue(Approx(cs[0].box(),1e-4) == [[0.13244,0.201099],[0.131459,0.202575],[0.132274,0.200001],[0.132283,0.200001]]) + if __name__ == '__main__': unittest.main() \ No newline at end of file From f0092a56ace7d3e0a177d795cbe9f60a6335cd13 Mon Sep 17 00:00:00 2001 From: godardma Date: Mon, 6 Jan 2025 15:04:12 +0100 Subject: [PATCH 058/126] [graphics] correction for IPE polygon drawing (not closing in some cases --- src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp index b9349c996..2968daac8 100644 --- a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp +++ b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp @@ -194,7 +194,20 @@ void Figure2D_IPE::draw_polyline(const std::vector& x, float tip_length, void Figure2D_IPE::draw_polygone(const std::vector& x, const StyleProperties& s) { - draw_polyline(x,0.,s); + assert(x.size() > 1); + assert(tip_length >= 0.); + + begin_path(s, 0); + + for(size_t k = 0 ; k < x.size() ; k++) + { + assert(_fig.size() <= x[k].size()); + _f_temp_content << scale_x(x[k][i()]) << " " << scale_y(x[k][j()]) << ((k == 0 ? " m \n" : " l \n")); + } + + _f_temp_content << scale_x(x[0][i()]) << " " << scale_y(x[0][j()]) << " l \n"; // Close the polygon + + _f_temp_content << ""; } void Figure2D_IPE::draw_pie(const Vector& c, const Interval& r, const Interval& theta, const StyleProperties& s) From 7bf050c939d75d7e8bb3e3a213ca9d3d1dfd9ae7 Mon Sep 17 00:00:00 2001 From: godardma Date: Mon, 6 Jan 2025 17:36:45 +0100 Subject: [PATCH 059/126] [graphics] minor correction --- src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp index 2968daac8..d5d2f9d94 100644 --- a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp +++ b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp @@ -195,7 +195,6 @@ void Figure2D_IPE::draw_polyline(const std::vector& x, float tip_length, void Figure2D_IPE::draw_polygone(const std::vector& x, const StyleProperties& s) { assert(x.size() > 1); - assert(tip_length >= 0.); begin_path(s, 0); From b78008ebdcdd0e342f2834bb007b0f125c0e454e Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 7 Jan 2025 10:36:39 +0100 Subject: [PATCH 060/126] [graphics] minor factorization --- src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp index d5d2f9d94..94e94fa46 100644 --- a/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp +++ b/src/graphics/3rd/ipe/codac2_Figure2D_IPE.cpp @@ -196,17 +196,9 @@ void Figure2D_IPE::draw_polygone(const std::vector& x, const StyleProper { assert(x.size() > 1); - begin_path(s, 0); - - for(size_t k = 0 ; k < x.size() ; k++) - { - assert(_fig.size() <= x[k].size()); - _f_temp_content << scale_x(x[k][i()]) << " " << scale_y(x[k][j()]) << ((k == 0 ? " m \n" : " l \n")); - } - - _f_temp_content << scale_x(x[0][i()]) << " " << scale_y(x[0][j()]) << " l \n"; // Close the polygon - - _f_temp_content << ""; + std::vector x_temp = x; + x_temp.push_back(x[0]); + draw_polyline(x_temp, 0., s); } void Figure2D_IPE::draw_pie(const Vector& c, const Interval& r, const Interval& theta, const StyleProperties& s) From 8220a0866bf75299ea09b464663067323f2787fe Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 7 Jan 2025 10:59:51 +0100 Subject: [PATCH 061/126] [capd] automatic finding of capd when codac codac is compiled with WITH_CAPD --- examples/01_batman/CMakeLists.txt | 10 +--------- examples/02_centered_form/CMakeLists.txt | 10 +--------- examples/03_sivia/CMakeLists.txt | 10 +--------- src/CMakeLists.txt | 4 +++- 4 files changed, 6 insertions(+), 28 deletions(-) diff --git a/examples/01_batman/CMakeLists.txt b/examples/01_batman/CMakeLists.txt index 9e88ae6b0..314b49ffc 100644 --- a/examples/01_batman/CMakeLists.txt +++ b/examples/01_batman/CMakeLists.txt @@ -27,11 +27,6 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") -# Adding CAPD - - # In case Codac was compiled with CAPD, you need to find it. - # find_package(CAPD REQUIRED) - # Compilation if(FAST_RELEASE) @@ -42,7 +37,4 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) - - # Link with CAPD if needed - # target_link_libraries(${PROJECT_NAME} PUBLIC capd::capd) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file diff --git a/examples/02_centered_form/CMakeLists.txt b/examples/02_centered_form/CMakeLists.txt index d46334add..314b49ffc 100644 --- a/examples/02_centered_form/CMakeLists.txt +++ b/examples/02_centered_form/CMakeLists.txt @@ -27,11 +27,6 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") -# Adding CAPD - - # In case Codac was compiled with CAPD, you need to find it. - # find_package(CAPD REQUIRED) - # Compilation if(FAST_RELEASE) @@ -42,7 +37,4 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) - - # Link with CAPD if needed - # target_link_libraries(${PROJECT_NAME} PUBLIC capd::capd) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file diff --git a/examples/03_sivia/CMakeLists.txt b/examples/03_sivia/CMakeLists.txt index d46334add..314b49ffc 100644 --- a/examples/03_sivia/CMakeLists.txt +++ b/examples/03_sivia/CMakeLists.txt @@ -27,11 +27,6 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") -# Adding CAPD - - # In case Codac was compiled with CAPD, you need to find it. - # find_package(CAPD REQUIRED) - # Compilation if(FAST_RELEASE) @@ -42,7 +37,4 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) - - # Link with CAPD if needed - # target_link_libraries(${PROJECT_NAME} PUBLIC capd::capd) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 577b6cfad..71c308fb1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -101,13 +101,15 @@ # Optional 3rd party: + find_package(CAPD REQUIRED) + find_path(CODAC_CAPD_INCLUDE_DIR ${PROJECT_NAME}-capd.h PATH_SUFFIXES include/${PROJECT_NAME}-capd) set(CODAC_INCLUDE_DIRS \${CODAC_INCLUDE_DIRS} \${CODAC_CAPD_INCLUDE_DIR}) find_library(CODAC_CAPD_LIBRARY NAMES ${PROJECT_NAME}-capd PATH_SUFFIXES lib) - set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY}) + set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY} capd::capd) ") endif() From b84b5b4408a5146209f08395d82c460b10a22262 Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 7 Jan 2025 11:05:49 +0100 Subject: [PATCH 062/126] [capd] added example 05 --- examples/05_capd_conversions/CMakeLists.txt | 40 +++++++++++++++++++++ examples/05_capd_conversions/main.cpp | 33 +++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 examples/05_capd_conversions/CMakeLists.txt create mode 100644 examples/05_capd_conversions/main.cpp diff --git a/examples/05_capd_conversions/CMakeLists.txt b/examples/05_capd_conversions/CMakeLists.txt new file mode 100644 index 000000000..75fbd6090 --- /dev/null +++ b/examples/05_capd_conversions/CMakeLists.txt @@ -0,0 +1,40 @@ +# ================================================================== +# codac / basics example - cmake configuration file +# ================================================================== + +cmake_minimum_required(VERSION 3.0.2) +project(codac_example LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Adding IBEX + +# In case you installed IBEX in a local directory, you need +# to specify its path with the CMAKE_PREFIX_PATH option. +# set(CMAKE_PREFIX_PATH "~/ibex-lib/build_install") + +find_package(IBEX REQUIRED) +ibex_init_common() # IBEX should have installed this function +message(STATUS "Found IBEX version ${IBEX_VERSION}") + +# Adding Codac + +# In case you installed Codac in a local directory, you need +# to specify its path with the CMAKE_PREFIX_PATH option. +# set(CMAKE_PREFIX_PATH "~/codac/build_install") + +find_package(CODAC REQUIRED) +message(STATUS "Found Codac version ${CODAC_VERSION}") + +# Compilation + +if(FAST_RELEASE) + add_compile_definitions(FAST_RELEASE) + message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") +endif() + +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}) +target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file diff --git a/examples/05_capd_conversions/main.cpp b/examples/05_capd_conversions/main.cpp new file mode 100644 index 000000000..4ea17a07f --- /dev/null +++ b/examples/05_capd_conversions/main.cpp @@ -0,0 +1,33 @@ +#include "capd/capdlib.h" +#include +using namespace std; +using namespace codac2; + +int main() +{ + cout<<"Interval"< -using namespace std; -using namespace codac2; - -int main() -{ - cout<<"Interval"< +#include + +using namespace std; +using namespace codac2; + +TEST_CASE("CAPD") +{ + { + Interval codac_interval(0., 2.); + capd::Interval capd_interval=to_capd(codac_interval); + CHECK(capd_interval == capd::Interval(0., 2.)); + CHECK(to_codac(capd_interval) == Interval(0., 2.)); + } + + { + IntervalVector codac_interval_vector({Interval(0., 2.), Interval(1., 3.)}); + capd::IVector capd_interval_vector=to_capd(codac_interval_vector); + CHECK(capd_interval_vector == capd::IVector({capd::Interval(0., 2.), capd::Interval(1., 3.)})); + CHECK(to_codac(capd_interval_vector) == IntervalVector({Interval(0., 2.), Interval(1., 3.)})); + } + + { + IntervalMatrix codac_interval_matrix({{Interval(0., 2.), Interval(1., 3.)}, {Interval(2., 4.), Interval(3., 5.)}}); + capd::IMatrix capd_interval_matrix=to_capd(codac_interval_matrix); + CHECK(capd_interval_matrix == capd::IMatrix({{capd::Interval(0., 2.), capd::Interval(1., 3.)}, {capd::Interval(2., 4.), capd::Interval(3., 5.)}})); + CHECK(to_codac(capd_interval_matrix) == IntervalMatrix({{Interval(0., 2.), Interval(1., 3.)}, {Interval(2., 4.), Interval(3., 5.)}})); + } +} \ No newline at end of file From fc79237e8f7f53f2965d1622aff5ce7d9f866f39 Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 7 Jan 2025 15:50:02 +0100 Subject: [PATCH 064/126] [capd] minor update --- examples/05_capd_solver/main.cpp | 2 - include/codac-capd.h | 8 ---- include/codac2-capd.h | 8 ---- include/codac2_capd.h | 75 -------------------------------- src/CMakeLists.txt | 3 -- src/capd/codac2_capd.cpp | 18 ++------ tests/CMakeLists.txt | 24 +++++----- tests/capd/codac2_tests_capd.py | 19 ++++++++ 8 files changed, 35 insertions(+), 122 deletions(-) delete mode 100644 include/codac-capd.h delete mode 100644 include/codac2-capd.h delete mode 100644 include/codac2_capd.h create mode 100644 tests/capd/codac2_tests_capd.py diff --git a/examples/05_capd_solver/main.cpp b/examples/05_capd_solver/main.cpp index a193796e1..f2ef56985 100644 --- a/examples/05_capd_solver/main.cpp +++ b/examples/05_capd_solver/main.cpp @@ -51,9 +51,7 @@ int main() DefaultView::set_axes(axis(0,{-2,1.5}),axis(1,{-2,3})); for (float t=0.;t<20.;t+=0.05) - { DefaultView::draw_box(to_codac(solution(t))); - } DefaultView::draw_box(to_codac(c),Color::green()); DefaultView::draw_box(to_codac(result),Color::red()); diff --git a/include/codac-capd.h b/include/codac-capd.h deleted file mode 100644 index 0f703eef8..000000000 --- a/include/codac-capd.h +++ /dev/null @@ -1,8 +0,0 @@ -/* This file is generated by CMake */ - -#ifndef __CODAC2_3RD_CAPD_H__ -#define __CODAC2_3RD_CAPD_H__ - -#include - -#endif diff --git a/include/codac2-capd.h b/include/codac2-capd.h deleted file mode 100644 index 0f703eef8..000000000 --- a/include/codac2-capd.h +++ /dev/null @@ -1,8 +0,0 @@ -/* This file is generated by CMake */ - -#ifndef __CODAC2_3RD_CAPD_H__ -#define __CODAC2_3RD_CAPD_H__ - -#include - -#endif diff --git a/include/codac2_capd.h b/include/codac2_capd.h deleted file mode 100644 index 9056f95c6..000000000 --- a/include/codac2_capd.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * \file codac2_capd.h - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Maël Godard - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#pragma once - -#include "capd/capdlib.h" -#include "codac2_IntervalVector.h" -#include "codac2_Matrix.h" -#include "codac2_IntervalMatrix.h" - -namespace codac2 -{ - /** - * \brief Casts a reference to a Codac Interval object into a reference to an CAPD Interval object - * - * \param x Codac type Interval - * \return CAPD type Interval - */ - capd::Interval& to_capd(codac2::Interval& x); - - /** - * \brief Casts a Codac Interval object into an CAPD Interval object - * - * \param x const Codac type Interval - * \return const CAPD type Interval - */ - const capd::Interval& to_capd(const codac2::Interval& x); - - /** - * \brief Casts an CAPD Interval object into a Codac Interval object - * - * \param x const CAPD type Interval - * \return Codac type Interval - */ - codac2::Interval to_codac(const capd::Interval& x); - - /** - * \brief Casts a Codac IntervalVector object into an CAPD IntervalVector object - * - * \param x const Codac type IntervalVector - * \return CAPD type IntervalVector - */ - capd::IVector to_capd(const codac2::IntervalVector& x); - - /** - * \brief Casts an CAPD IntervalVector object into a Codac IntervalVector object - * - * \param x const CAPD type IntervalVector - * \return Codac type IntervalVector - */ - codac2::IntervalVector to_codac(const capd::IVector& x); - - /** - * \brief Casts a Codac IntervalMatrix object into an CAPD IntervalMatrix object - * - * \param x const Codac type IntervalMatrix - * \return CAPD type IntervalMatrix - */ - capd::IMatrix to_capd(const codac2::IntervalMatrix& x); - - /** - * \brief Casts an CAPD IntervalMatrix object into a Codac IntervalMatrix object - * - * \param x const CAPD type IntervalMatrix - * \return Codac type IntervalMatrix - */ - codac2::IntervalMatrix to_codac(const capd::IMatrix& x); - -} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 71c308fb1..aece5fd9e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,7 +75,6 @@ set(CODAC_CXX_FLAGS \"\") ") - #if(WITH_PYTHON) # # file(APPEND ${CODAC_CMAKE_CONFIG_FILE} " @@ -94,7 +93,6 @@ # #endif() - if(WITH_CAPD) file(APPEND ${CODAC_CMAKE_CONFIG_FILE} " @@ -114,7 +112,6 @@ endif() - install(FILES ${CODAC_CMAKE_CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_CMAKE}) diff --git a/src/capd/codac2_capd.cpp b/src/capd/codac2_capd.cpp index 62de19aee..f5398f6ab 100644 --- a/src/capd/codac2_capd.cpp +++ b/src/capd/codac2_capd.cpp @@ -18,14 +18,12 @@ namespace codac2 { capd::Interval to_capd(const Interval &x) { - capd::Interval y(x.lb(), x.ub()); - return y; + return {x.lb(), x.ub()}; } Interval to_codac(const capd::Interval &x) { - Interval y(x.leftBound(), x.rightBound()); - return y; + return {x.leftBound(), x.rightBound()}; } capd::IVector to_capd(const IntervalVector &x) @@ -51,13 +49,9 @@ namespace codac2 capd::IMatrix to_capd(const IntervalMatrix &x) { capd::IMatrix y(x.rows(), x.cols()); - for (Index i = 0; i < (Index)x.rows(); i++) - { - for (Index j = 0; j < (Index)x.cols(); j++) - { + for (Index i = 0; i < x.rows(); i++) + for (Index j = 0; j < x.cols(); j++) y[i][j] = to_capd(x(i, j)); - } - } return y; } @@ -65,12 +59,8 @@ namespace codac2 { IntervalMatrix y(x.numberOfRows(), x.numberOfColumns()); for (Index i = 0; i < (Index)x.numberOfRows(); i++) - { for (Index j = 0; j < (Index)x.numberOfColumns(); j++) - { y(i, j) = to_codac(x[i][j]); - } - } return y; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6d9eab70b..50565ba9f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -84,6 +84,16 @@ list(APPEND SRC_TESTS # listing files without extension graphics/styles/codac2_tests_Color ) +set(CODAC_LIBRARIES ${PROJECT_NAME}-core) + +# CAPD test +if (WITH_CAPD) + list(APPEND SRC_TESTS + capd/codac2_tests_capd + ) + set(CODAC_LIBRARIES ${CODAC_LIBRARIES} ${PROJECT_NAME}-capd capd::capd) +endif() + foreach(SRC_TEST ${SRC_TESTS}) string(REPLACE "/" "_" TEST_NAME ${SRC_TEST}) string(REPLACE "codac2_tests_" "" TEST_NAME ${TEST_NAME}) @@ -93,7 +103,7 @@ foreach(SRC_TEST ${SRC_TESTS}) add_executable(${TEST_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_TEST}.cpp) set(CODAC_HEADERS_DIR ${CMAKE_CURRENT_BINARY_DIR}/../include) target_include_directories(${TEST_NAME} SYSTEM PUBLIC ${CODAC_HEADERS_DIR}) - target_link_libraries(${TEST_NAME} PUBLIC Ibex::ibex ${PROJECT_NAME}-core PRIVATE Catch2::Catch2WithMain) + target_link_libraries(${TEST_NAME} PUBLIC Ibex::ibex ${CODAC_LIBRARIES} PRIVATE Catch2::Catch2WithMain) add_dependencies(check ${TEST_NAME}) add_test(NAME ${TEST_NAME}_cpp COMMAND ${TEST_NAME}) @@ -102,14 +112,4 @@ foreach(SRC_TEST ${SRC_TESTS}) add_test(NAME ${TEST_NAME}_py COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_TEST}.py) endif() -endforeach() - -# CAPD test -if (WITH_CAPD) - add_executable(capd_tests capd/codac2_tests_capd.cpp) - set(CODAC_HEADERS_DIR ${CMAKE_CURRENT_BINARY_DIR}/../include) - target_include_directories(capd_tests SYSTEM PUBLIC ${CODAC_HEADERS_DIR}) - target_link_libraries(capd_tests PUBLIC Ibex::ibex capd::capd ${PROJECT_NAME}-core ${PROJECT_NAME}-capd PRIVATE Catch2::Catch2WithMain) - add_dependencies(check capd_tests) - add_test(NAME capd_tests_cpp COMMAND capd_tests) -endif() \ No newline at end of file +endforeach() \ No newline at end of file diff --git a/tests/capd/codac2_tests_capd.py b/tests/capd/codac2_tests_capd.py new file mode 100644 index 000000000..178dfe158 --- /dev/null +++ b/tests/capd/codac2_tests_capd.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +# Codac tests +# ---------------------------------------------------------------------------- +# \date 2024 +# \author Maël Godard +# \copyright Copyright 2024 Codac Team +# \license GNU Lesser General Public License (LGPL) + +import unittest +from codac import * + +class TestCAPD(unittest.TestCase): + + def tests_capd(self): + self.assertTrue(True) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From e2b228b6e7e743f4306c02d443018dcc7d4d70ca Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 7 Jan 2025 15:51:45 +0100 Subject: [PATCH 065/126] [capd] minor update --- examples/05_capd_solver/main.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/05_capd_solver/main.cpp b/examples/05_capd_solver/main.cpp index f2ef56985..36cd3d2f4 100644 --- a/examples/05_capd_solver/main.cpp +++ b/examples/05_capd_solver/main.cpp @@ -1,8 +1,11 @@ +// Author : Maël GODARD +// Adapted from CAPD examples + #include using namespace std; using namespace codac2; -// Adapted from CAPD examples + int main() { From 2bb5ee632c801f0937156a006be527a3129539be Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 7 Jan 2025 15:51:54 +0100 Subject: [PATCH 066/126] [capd] minor update --- examples/05_capd_solver/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/05_capd_solver/main.cpp b/examples/05_capd_solver/main.cpp index 36cd3d2f4..e45ed0172 100644 --- a/examples/05_capd_solver/main.cpp +++ b/examples/05_capd_solver/main.cpp @@ -6,7 +6,6 @@ using namespace std; using namespace codac2; - int main() { // Equation of the pendulum with friction From 41894a5c4cef5db64e264487fe812518b81ced92 Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 7 Jan 2025 18:47:35 +0100 Subject: [PATCH 067/126] [graphics] added missing color binding --- python/src/graphics/styles/codac2_py_Color.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/src/graphics/styles/codac2_py_Color.cpp b/python/src/graphics/styles/codac2_py_Color.cpp index d960b3acd..4e518227b 100644 --- a/python/src/graphics/styles/codac2_py_Color.cpp +++ b/python/src/graphics/styles/codac2_py_Color.cpp @@ -109,6 +109,14 @@ void export_Color(py::module& m) .def_static("dark_gray", &Color::dark_gray, STATIC_COLOR_COLOR_DARK_GRAY_FLOAT, "alpha"_a=1.) + + .def_static("purple", &Color::purple, + STATIC_COLOR_COLOR_PURPLE_FLOAT, + "alpha"_a=1.) + + .def_static("dark_green", &Color::dark_green, + STATIC_COLOR_COLOR_DARK_GREEN_FLOAT, + "alpha"_a=1.) ; py::implicitly_convertible(); From 0afea67ab0ff75962139afed24c98b44534e4d4b Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 8 Jan 2025 10:54:24 +0100 Subject: [PATCH 068/126] [doc] solving Doxygen issue with template specializations --- src/core/separators/codac2_SepWrapper.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/separators/codac2_SepWrapper.h b/src/core/separators/codac2_SepWrapper.h index bb6ad2acc..c56194ee5 100644 --- a/src/core/separators/codac2_SepWrapper.h +++ b/src/core/separators/codac2_SepWrapper.h @@ -16,6 +16,8 @@ namespace codac2 { + /// \cond SepWrapper_ + template class SepWrapper_ : public Sep> { @@ -30,6 +32,8 @@ namespace codac2 const T _y; }; + /// \endcond + template<> class SepWrapper_ : public SepCtcPair { From 53157ce4c5538a1027ebe0c2f8b61f4a027a0b97 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 8 Jan 2025 10:54:41 +0100 Subject: [PATCH 069/126] [ex] added comments --- examples/04_explored_area/main.cpp | 4 ++-- examples/04_explored_area/main.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/04_explored_area/main.cpp b/examples/04_explored_area/main.cpp index 7271db870..a203fd30e 100644 --- a/examples/04_explored_area/main.cpp +++ b/examples/04_explored_area/main.cpp @@ -19,12 +19,12 @@ int main() Interval tdomain(0,5); auto sampled_f = AnalyticTrajectory(f,tdomain).sampled(0.8); - sampled_f[6] = {0,-1}; + sampled_f[6] = {0,-1}; // appending the position (0,-1) at t=6 VectorVar w(3); auto g = sampled_f.as_function(); AnalyticFunction h { - {w}, + {w}, // w=(t,x,y) sqr(w[0]-g(w[2])[0])+sqr(w[1]-g(w[2])[1]) }; diff --git a/examples/04_explored_area/main.py b/examples/04_explored_area/main.py index 384816546..e55a590cd 100644 --- a/examples/04_explored_area/main.py +++ b/examples/04_explored_area/main.py @@ -15,12 +15,12 @@ tdomain = [0,5] sampled_f = AnalyticTrajectory(f,tdomain).sampled(0.8) -sampled_f[6] = [0,-1] +sampled_f[6] = [0,-1] # appending the position (0,-1) at t=6 w = VectorVar(3) g = sampled_f.as_function() h = AnalyticFunction( - [w], + [w], # w=(t,x,y) sqr(w[0]-g(w[2])[0])+sqr(w[1]-g(w[2])[1]) ) From 3fdb97c201fa9e885f1eb0640e17b26c050fec8e Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 8 Jan 2025 15:05:58 +0100 Subject: [PATCH 070/126] [doc] using Furo style + customization --- doc/manual/_static/css/custom.css | 17 ++-- doc/manual/_static/logos/logo_codac.svg | 117 ++++++++++++++++++++++++ doc/manual/conf.py.in | 35 ++++++- doc/manual/index.rst | 103 +++++++++++---------- doc/manual/installation/cpp.rst | 23 +++++ doc/manual/installation/index.rst | 9 ++ doc/manual/installation/matlab.rst | 12 +++ doc/manual/installation/python.rst | 9 ++ 8 files changed, 267 insertions(+), 58 deletions(-) create mode 100644 doc/manual/_static/logos/logo_codac.svg create mode 100644 doc/manual/installation/cpp.rst create mode 100644 doc/manual/installation/index.rst create mode 100644 doc/manual/installation/matlab.rst create mode 100644 doc/manual/installation/python.rst diff --git a/doc/manual/_static/css/custom.css b/doc/manual/_static/css/custom.css index bf36547f9..fbc9b2897 100644 --- a/doc/manual/_static/css/custom.css +++ b/doc/manual/_static/css/custom.css @@ -1,10 +1,13 @@ -div.rst-content a:visited -{ - color: #2980b9; - text-decoration: none; +.sidebar-tree .current > .reference { + background: none; } -div.rst-content li.toctree-l1 > a -{ - font-weight: bold; +.sidebar-tree .current-page > .reference { + background: var(--color-sidebar-item-background--current); + font-weight: normal; +} + +a.sidebar-brand { + padding: 2rem 0rem; + padding-right: 1rem; } \ No newline at end of file diff --git a/doc/manual/_static/logos/logo_codac.svg b/doc/manual/_static/logos/logo_codac.svg new file mode 100644 index 000000000..8c13fe083 --- /dev/null +++ b/doc/manual/_static/logos/logo_codac.svg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/manual/conf.py.in b/doc/manual/conf.py.in index e7d94daba..6f0b19687 100644 --- a/doc/manual/conf.py.in +++ b/doc/manual/conf.py.in @@ -8,13 +8,15 @@ project = 'Codac' copyright = 'Codac Team' -author = 'Codac Team' +author = 'Simon Rohou, Benoît Desrochers, Fabrice Le Bars and others' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ 'sphinx_rtd_theme', + 'sphinx_math_dollar', + 'sphinx.ext.mathjax' ] templates_path = ['_templates'] @@ -25,7 +27,7 @@ exclude_patterns = [] # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_static_path = ['_static'] -html_theme = "sphinx_rtd_theme" +html_theme = "furo" html_logo = "_static/logos/logo_codac.svg" # These paths are either relative to html_static_path @@ -35,6 +37,31 @@ html_css_files = [ ] html_theme_options = { - 'logo_only': True, - 'display_version': True, + + "sidebar_hide_name": True, + + "light_css_variables": { + "color-brand-primary": "white", + "color-brand-content": "#1F506B", + + "color-sidebar-background": "#3281AC", + "color-sidebar-caption-text": "white", + "color-sidebar-item-background--current": "var(--color-brand-content)", + "color-sidebar-item-background--hover": "#3B9ACC", + "color-sidebar-item-expander-background--hover": "#3B9ACC", + "color-sidebar-link-text": "white", + "sidebar-caption-font-size": "120%", + + "color-link--visited": "var(--color-link)", + }, + + "announcement": "You are currently reading the new Codac documentation, which is currently in preparation.", +} + +# See https://www.sympy.org/sphinx-math-dollar/ +mathjax3_config = { + "tex": { + "inlineMath": [['\\(', '\\)']], + "displayMath": [["\\[", "\\]"]], + } } \ No newline at end of file diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 1dc364340..97584dbf6 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -1,59 +1,68 @@ Codac manual ============ +Welcome to the Codac website. + -.. toctree:: - :caption: Overview of Codac - :maxdepth: 3 - Constraint programming and IA - The Codac framework - Target audience +.. .. toctree:: +.. :hidden: +.. :caption: Overview of Codac +.. :maxdepth: 3 +.. +.. Intervals and constraints +.. The Codac framework +.. Target audience .. toctree:: + :hidden: :caption: User manual :maxdepth: 2 installation/index.rst - intervals/index.rst - linear/index.rst - functions/index.rst - tubes/index.rst - -.. toctree:: - :maxdepth: 3 - - contractors/index.rst - separators/index.rst - -.. toctree:: - :maxdepth: 2 - - pavers/index.rst - cn/index.rst - geometry/index.rst - ellipsoids/index.rst - topology/index.rst - visualization/index.rst - extensions/index.rst - seealso/index.rst - references/index.rst - - -.. toctree:: - :caption: How-to guides - :maxdepth: 3 - - howto/robotics/index.rst - howto/geometry/index.rst - howto/dynamical/index.rst - - -.. toctree:: - :caption: Development - :maxdepth: 3 - - Changelog - C++ API - Information for developers \ No newline at end of file +.. intervals/index.rst +.. linear/index.rst +.. functions/index.rst +.. tubes/index.rst + +.. .. toctree:: +.. :hidden: +.. :maxdepth: 3 +.. +.. contractors/index.rst +.. separators/index.rst + +.. .. toctree:: +.. :hidden: +.. :maxdepth: 2 +.. +.. pavers/index.rst +.. cn/index.rst +.. geometry/index.rst +.. ellipsoids/index.rst +.. topology/index.rst +.. visualization/index.rst +.. extensions/index.rst +.. seealso/index.rst +.. references/index.rst + + +.. .. toctree:: +.. :hidden: +.. :caption: How-to guides +.. :maxdepth: 3 +.. +.. howto/robotics/index.rst +.. howto/geometry/index.rst +.. howto/dynamical/index.rst + + +.. .. toctree:: +.. :hidden: +.. :caption: Development +.. :maxdepth: 3 +.. +.. Changelog +.. C++ API +.. Information for developers \ No newline at end of file diff --git a/doc/manual/installation/cpp.rst b/doc/manual/installation/cpp.rst new file mode 100644 index 000000000..2c8a414cf --- /dev/null +++ b/doc/manual/installation/cpp.rst @@ -0,0 +1,23 @@ +C++ installation +================ + +1. **Dependencies**: Ensure you have CMake (>=3.10) and a C++14 compatible compiler. +2. **Clone the repository**: + + .. code-block:: bash + + git clone https://github.com/codac-team/codac.git + cd codac + +3. **Build the library**: + + .. code-block:: bash + + mkdir build + cd build + cmake .. + make + + +Using Codac in CMake projects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/doc/manual/installation/index.rst b/doc/manual/installation/index.rst new file mode 100644 index 000000000..932dd8f71 --- /dev/null +++ b/doc/manual/installation/index.rst @@ -0,0 +1,9 @@ +Installation Guide +================== + +.. toctree:: + :maxdepth: 1 + + python.rst + cpp.rst + matlab.rst \ No newline at end of file diff --git a/doc/manual/installation/matlab.rst b/doc/manual/installation/matlab.rst new file mode 100644 index 000000000..e19fc8845 --- /dev/null +++ b/doc/manual/installation/matlab.rst @@ -0,0 +1,12 @@ +MATLAB installation +=================== + +1. **Dependencies**: Ensure you have MATLAB R2019b or later. +2. **Python integration**: Follow the instructions `here `_ to set up Python integration. +3. **Install the Python package**: + + .. code-block:: bash + + pip install codac + +Once Codac is installed, you can use it in your MATLAB scripts, ensuring proper integration with Python for functionality. \ No newline at end of file diff --git a/doc/manual/installation/python.rst b/doc/manual/installation/python.rst new file mode 100644 index 000000000..f044fdcbb --- /dev/null +++ b/doc/manual/installation/python.rst @@ -0,0 +1,9 @@ +Python installation +=================== + +1. **Dependencies**: Ensure you have a supported version of Python (>=3.6). +2. **Install via pip**: Use the following command to install Codac: + + .. code-block:: bash + + pip install codac \ No newline at end of file From 982155cc02b045c621aeb72eb6abbca96af720dd Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 8 Jan 2025 17:27:50 +0100 Subject: [PATCH 071/126] [doc] install + info dev --- doc/manual/_static/css/custom.css | 6 ++++ doc/manual/development/info_dev.rst | 24 +++++++++++++++ doc/manual/index.rst | 11 ++++--- doc/manual/installation/cpp.rst | 6 +++- doc/manual/installation/index.rst | 2 ++ doc/manual/installation/python.rst | 48 ++++++++++++++++++++++++++++- 6 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 doc/manual/development/info_dev.rst diff --git a/doc/manual/_static/css/custom.css b/doc/manual/_static/css/custom.css index fbc9b2897..50ffda480 100644 --- a/doc/manual/_static/css/custom.css +++ b/doc/manual/_static/css/custom.css @@ -10,4 +10,10 @@ a.sidebar-brand { padding: 2rem 0rem; padding-right: 1rem; +} + +.sidebar-logo +{ + max-width: 120%; + float: right; } \ No newline at end of file diff --git a/doc/manual/development/info_dev.rst b/doc/manual/development/info_dev.rst new file mode 100644 index 000000000..426f8c097 --- /dev/null +++ b/doc/manual/development/info_dev.rst @@ -0,0 +1,24 @@ +Information for developers +========================== + +Building the Manual with Sphinx +------------------------------- + +To build this manual using Sphinx, follow these steps: + +1. **Requirements**: Install `Sphinx `_ together with the extensions used by Codac, if they are not already installed. + + .. code-block:: bash + + pip install sphinx furo sphinx-math-dollar + +2. **Building the manual**: After configuring the CMake project, the manual can be build with: + + .. code-block:: bash + + make manual + + The generated website will be locally available in ``./build/doc/manual``. + +To contribute and extend this manual, please consult the Sphinx documentation: +https://www.sphinx-doc.org \ No newline at end of file diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 97584dbf6..beee9bae0 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -58,11 +58,12 @@ Welcome to the Codac website. .. howto/dynamical/index.rst -.. .. toctree:: -.. :hidden: -.. :caption: Development -.. :maxdepth: 3 +.. toctree:: + :hidden: + :caption: Development + :maxdepth: 3 + + development/info_dev.rst .. .. Changelog .. C++ API -.. Information for developers \ No newline at end of file diff --git a/doc/manual/installation/cpp.rst b/doc/manual/installation/cpp.rst index 2c8a414cf..c9867afde 100644 --- a/doc/manual/installation/cpp.rst +++ b/doc/manual/installation/cpp.rst @@ -1,3 +1,5 @@ +.. _sec-start-cpp-project: + C++ installation ================ @@ -20,4 +22,6 @@ C++ installation Using Codac in CMake projects -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +... \ No newline at end of file diff --git a/doc/manual/installation/index.rst b/doc/manual/installation/index.rst index 932dd8f71..f366c446a 100644 --- a/doc/manual/installation/index.rst +++ b/doc/manual/installation/index.rst @@ -1,6 +1,8 @@ Installation Guide ================== +Codac is available in both C++20 and Python3, as well as MATLAB `through its Python interface `_. Note that if you want to contribute to Codac, you have to make the full C++ installation from sources. + .. toctree:: :maxdepth: 1 diff --git a/doc/manual/installation/python.rst b/doc/manual/installation/python.rst index f044fdcbb..044842b4c 100644 --- a/doc/manual/installation/python.rst +++ b/doc/manual/installation/python.rst @@ -1,9 +1,55 @@ +.. _sec-start-py-project: + Python installation =================== +In case you want to use Codac only with Python, then the installation procedure is simply: + 1. **Dependencies**: Ensure you have a supported version of Python (>=3.6). 2. **Install via pip**: Use the following command to install Codac: .. code-block:: bash - pip install codac \ No newline at end of file + pip install codac + + +You can also update and test your Codac Python package. + +* **Update via pip**: Use the following command to update your already installed Codac package: + .. code-block:: bash + + pip install codac --upgrade + + +* **Testing the installation**: In order to verify that your installation is working properly in Python, you can run: + .. code-block:: bash + + python -m unittest discover codac.tests + + +Troubleshooting +--------------- + +Depending on your configuration, you may encounter difficulties when installing the Codac Python package. Here are a few tips to help you. + +.. admonition:: Debian Bookworm and possibly other configurations + + | ``pip install ...`` or ``pip3 install ...`` commands may only work inside `virtual environments `_ or with ``--break-system-packages`` parameter, *e.g.*: + + .. code-block:: bash + + pip3 install --break-system-packages codac + +.. admonition:: macOS Big Sur and later (x86_64) + + | Python wheels provided for Catalina or earlier `may need to be installed with something similar to `_: + + .. code-block:: bash + + sudo pip3 install --upgrade vibes # Add here any other non-binary wheels dependencies... + sudo pip3 install --upgrade --nodeps --platform macosx_10_9_x86_64 --only-binary=:all: --target=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages codac + + Depending on the way Python was installed, the path to specify after ``--target`` may differ, *e.g.* if Python was installed from https://www.python.org/ftp/python/3.10.4/python-3.10.4-macos11.pkg, it may be ``/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages``. Otherwise, run ``python3 -m site`` to check the ``site-packages`` full path in ``sys.path`` list. Also, the value ``10_9`` may need to be changed to ``10_14`` (or possibly another value) for some Python versions. + + +Finally, note that unsupported configurations can still probably follow the instructions from :ref:`Installing local Python binding `, for building the Codac Python binding locally on your machine. \ No newline at end of file From 8749d7654d7168fc82a15b8e654f2a61b8d89ad4 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 9 Jan 2025 14:16:54 +0100 Subject: [PATCH 072/126] [doc] install C++ --- doc/manual/_static/css/custom.css | 11 +- doc/manual/conf.py.in | 3 + doc/manual/development/info_dev.rst | 2 +- doc/manual/installation/cpp.rst | 265 ++++++++++++++++++++++++++-- doc/manual/installation/index.rst | 2 + doc/manual/installation/matlab.rst | 2 + doc/manual/installation/python.rst | 2 +- 7 files changed, 271 insertions(+), 16 deletions(-) diff --git a/doc/manual/_static/css/custom.css b/doc/manual/_static/css/custom.css index 50ffda480..b326520fa 100644 --- a/doc/manual/_static/css/custom.css +++ b/doc/manual/_static/css/custom.css @@ -1,3 +1,7 @@ +.strike { + text-decoration: line-through; +} + .sidebar-tree .current > .reference { background: none; } @@ -12,8 +16,11 @@ a.sidebar-brand { padding-right: 1rem; } -.sidebar-logo -{ +.sidebar-logo { max-width: 120%; float: right; +} + +.announcement-content { + font-size: 0.8rem; } \ No newline at end of file diff --git a/doc/manual/conf.py.in b/doc/manual/conf.py.in index 6f0b19687..b125e43ae 100644 --- a/doc/manual/conf.py.in +++ b/doc/manual/conf.py.in @@ -9,6 +9,7 @@ project = 'Codac' copyright = 'Codac Team' author = 'Simon Rohou, Benoît Desrochers, Fabrice Le Bars and others' +version = u'${PROJECT_VERSION}' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration @@ -53,6 +54,8 @@ html_theme_options = { "sidebar-caption-font-size": "120%", "color-link--visited": "var(--color-link)", + + "header-height": "2rem", }, "announcement": "You are currently reading the new Codac documentation, which is currently in preparation.", diff --git a/doc/manual/development/info_dev.rst b/doc/manual/development/info_dev.rst index 426f8c097..7b2033af4 100644 --- a/doc/manual/development/info_dev.rst +++ b/doc/manual/development/info_dev.rst @@ -10,7 +10,7 @@ To build this manual using Sphinx, follow these steps: .. code-block:: bash - pip install sphinx furo sphinx-math-dollar + pip install sphinx sphinx_rtd_theme furo sphinx-math-dollar 2. **Building the manual**: After configuring the CMake project, the manual can be build with: diff --git a/doc/manual/installation/cpp.rst b/doc/manual/installation/cpp.rst index c9867afde..5a85db574 100644 --- a/doc/manual/installation/cpp.rst +++ b/doc/manual/installation/cpp.rst @@ -1,27 +1,268 @@ -.. _sec-start-cpp-project: +.. _sec-install-cpp: + +.. role:: strike + :class: strike C++ installation ================ -1. **Dependencies**: Ensure you have CMake (>=3.10) and a C++14 compatible compiler. -2. **Clone the repository**: +This page describes how to install the C++ library on Linux, Windows, and macOS. Follow the steps outlined for your operating system. + + +Linux Installation +------------------ + + +Install from packages (latest release) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This installation procedure is valid for Ubuntu (amd64, arm64), Debian (arm64, armhf) and possibly others. +A Debian package is available for the last release |version| of the library: + +.. code-block:: bash + + sudo sh -c 'echo "deb [trusted=yes] https://packages.ensta-bretagne.fr/$(if [ -z "$(. /etc/os-release && echo $UBUNTU_CODENAME)" ]; then echo debian/$(. /etc/os-release && echo $VERSION_CODENAME); else echo ubuntu/$(. /etc/os-release && echo $UBUNTU_CODENAME); fi) ./" > /etc/apt/sources.list.d/ensta-bretagne.list' + sudo apt update + sudo apt install libcodac-dev + +Then, check your installation :ref:`with the instructions of this page `. + +.. warning:: + + | :strike:`URL changed: Please uninstall before.` + +.. admonition:: Uninstall Codac + + To uninstall Codac, you might want to do the following: + + .. code-block:: bash + + sudo apt remove libcodac-dev libibex-dev + sudo rm -f /etc/apt/sources.list.d/ensta-bretagne.list + sudo apt update + + :strike:`Note also that ``libeigen3-dev`` ` :strike:`might have been installed as a dependency of Codac but might be also used by other software. You might want to keep it.` + +.. admonition:: Standalone archives + + Standalone archives exist also for all the supported configurations, *e.g.* for a Raspberry Pi running Raspberry Pi OS Bookworm 32 bit, download and extract ``codac_standalone_armhf_bookworm.zip`` from ``_, then in the ``example`` folder run: + + .. code-block:: bash + + cmake . ; cmake --build . ; ./my_project + + and check that the graphical output appears. + + +Install from the sources (latest developments) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you prefer to use the latest development version, you can install Codac by compiling it from the source code. + +Steps +~~~~~ + +1. **Ensure the following prerequisites are met**: + + - A C++ compiler supporting C++20 or later (*e.g.*, GCC 11.0+, Clang 13.0+). + - CMake 3.14 or higher. + - Git (to clone the repository). + + These prerequisites can be installed directly with the command:: + + sudo apt-get install -y g++ gcc cmake git + +2. **Install the IBEX dependency**: + + Codac still uses some features of the `IBEX library `_ that you have to install first. The last version of IBEX is maintained on `this unofficial development repository `_: .. code-block:: bash - git clone https://github.com/codac-team/codac.git - cd codac + # Requirements to compile IBEX + sudo apt-get install -y flex bison + + # Download IBEX sources from GitHub + git clone -b master https://github.com/lebarsfa/ibex-lib.git $HOME/ibex-lib + + # Configure IBEX before installation + cd $HOME/ibex-lib + mkdir build && cd build + cmake -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release .. + + # Building + installing + make + make install + cd ../.. + + For further CMake options, please refer to the IBEX documentation. + + .. warning:: -3. **Build the library**: + **GAOL prerequisite:** On some platforms, you might need to install manually `MathLib `_ and `GAOL `_ with CMake and `specify where they are `_ in order to build IBEX successfully and have accurate computations. + +3. **Install the Codac library**: .. code-block:: bash - - mkdir build - cd build + + # The codac directory can be placed in your home, same level as IBEX + git clone https://github.com/codac-team/codac $HOME/codac + + # Configure Codac before installation + cd $HOME/codac + # Get automatically pybind11 and eigen submodules: + git submodule init ; git submodule update + mkdir build && cd build + cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release .. + + # Building + installing + make + make install + cd ../.. + +4. **Configure your system to find Codac**: + + In case Codac and its dependencies have been installed locally on your system, you will have to configure your environment variables. This can be done temporarily with: + + .. code-block:: bash + + export CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:$HOME/ibex-lib/build_install + export CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:$HOME/codac/build_install + + ... or permanently by updating your ``.bashrc`` file by appending the above commands. + +5. **Verify the installation** (optional): + + To ensure that the installation has worked properly, the unit tests of the library can be run. For this, you have to configure CMake using the ``-DBUILD_TESTS=ON`` option, before compilation. Then, from the ``$HOME/codac/build`` directory: + + .. code-block:: bash + + make test + +6. **Try an example** (optional): + + You may want to try Codac by running one of the proposed examples. After the installation, you can run the following commands: + + .. code-block:: bash + + cd $HOME/codac/examples/01_batman + mkdir build && cd build cmake .. make + Before executing the example, you will have to launch the VIBes viewer. Then, + + .. code-block:: bash + + ./codac_example + + You should obtain a graphical output corresponding to a curious set inversion. + + +Windows Installation +-------------------- + +Install from packages (latest release) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Using MinGW +~~~~~~~~~~~ + +Check https://community.chocolatey.org/packages/codac. + + +Using Visual Studio +~~~~~~~~~~~~~~~~~~~ + +Download and extract *e.g.* ``codac_standalone_x64_vc17.zip`` (for Visual Studio 2022) from https://github.com/codac-team/codac/releases/latest, open ``example\CMakelists.txt``, choose ``x64-Release`` configuration in Visual Studio (instead of ``x64-Debug``), double-click on ``main.cpp`` in the Solution Explorer and then click on the green Start button, and finally check that the graphical output appears. + +Note that in order to obtain graphical outputs, you will have to download and run https://github.com/ENSTABretagneRobotics/VIBES/releases/download/0.2.3/VIBes-0.2.3-win32.exe before running the project. + + +Install from the sources (latest developments) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You will probably need to install these prerequisites (assuming you already installed `Chocolatey package manager `_): + +.. code-block:: bash + + choco install cmake git make patch winflexbison + choco install eigen + +Then, install the desired compiler (*e.g.* ``choco install mingw --version=11.2.0.07112021``). + +Optionally, for Python binding (*e.g.* ``choco install python --version=3.10.4``) and documentation: + +.. code-block:: bash + + choco install doxygen.install --version=1.13 + choco install graphviz + python -m pip install --upgrade pip + pip install --upgrade wheel setuptools sphinx sphinx_rtd_theme furo sphinx-math-dollar + +The logic to follow will then be similar to Linux (note that for Visual Studio, commands such as ``make install`` need to be replaced with something similar to: + +.. code-block:: bash + + cmake --build . --config Release --target install + +.. warning:: + + | You might need to replace all occurences of :literal:`PATH_SUFFIXES \ ` with something similar to :literal:`PATHS ${CMAKE_CURRENT_LIST_FILE}/../../../../ PATH_SUFFIXES \ ` in all ``.cmake`` in ``codac/share/codac/cmake/`` (where Codac was installed) if a CMake project that tries to use Codac appears to find its installation location but fails to configure the project properly. + + + +macOS Installation +------------------- + +Install from packages (latest release) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Install `Homebrew package manager `_ and then build tools: + +.. code-block:: bash + + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + brew install wget autoconf automake libtool + brew install --cask cmake + +Download and extract *e.g.* ``codac_standalone_arm64_monterey.zip`` from ``_, then in ``example`` folder run: + +.. code-block:: bash + + cmake . ; cmake --build . ; ./my_project + +and check that the graphical output appears. + +.. admonition:: For macOS 12 Monterey + + For macOS 12 Monterey on a Mac with Apple silicon (arm64 processor), use ``codac_standalone_x86_64_monterey.zip`` for a Mac with an Intel processor (x86_64 processor), see https://support.apple.com/en-us/116943. + + +Note that in order to obtain graphical outputs, you will have to download and run https://github.com/ENSTABretagneRobotics/VIBES/releases/download/0.2.3/VIBes-0.2.2-osx.dmg before running the project. + + + +Install from the sources (latest developments) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The logic to follow will then be similar to Linux. + +Optionally, for Python binding and documentation: + +.. code-block:: bash + + wget https://github.com/Homebrew/homebrew-core/raw/d2267b9f2ad247bc9c8273eb755b39566a474a70/Formula/doxygen.rb ; brew reinstall ./doxygen.rb ; brew pin doxygen + brew install graphviz + python -m pip install --upgrade pip + pip install --upgrade wheel setuptools sphinx sphinx_rtd_theme furo sphinx-math-dollar + + +Troubleshooting +---------------- +If you encounter issues during the installation process, consider the following: + +- Ensure all prerequisites are installed and up to date. +- Check `the GitHub issues `_ page for known problems. -Using Codac in CMake projects -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If you need further assistance, reach out to the library maintainers via the GitHub repository's issue tracker or email support at `simon.rohou [at] ensta.fr`. -... \ No newline at end of file diff --git a/doc/manual/installation/index.rst b/doc/manual/installation/index.rst index f366c446a..ef004ae3f 100644 --- a/doc/manual/installation/index.rst +++ b/doc/manual/installation/index.rst @@ -1,3 +1,5 @@ +.. _sec-install: + Installation Guide ================== diff --git a/doc/manual/installation/matlab.rst b/doc/manual/installation/matlab.rst index e19fc8845..ff7cf2875 100644 --- a/doc/manual/installation/matlab.rst +++ b/doc/manual/installation/matlab.rst @@ -1,3 +1,5 @@ +.. _sec-install-matlab: + MATLAB installation =================== diff --git a/doc/manual/installation/python.rst b/doc/manual/installation/python.rst index 044842b4c..cb7826308 100644 --- a/doc/manual/installation/python.rst +++ b/doc/manual/installation/python.rst @@ -1,4 +1,4 @@ -.. _sec-start-py-project: +.. _sec-install-py: Python installation =================== From ece0e6124af36f11a0aeb74fe8fe81d4a439619f Mon Sep 17 00:00:00 2001 From: godardma Date: Fri, 10 Jan 2025 15:29:11 +0100 Subject: [PATCH 073/126] [capd] modified imports --- examples/05_capd_solver/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/05_capd_solver/main.cpp b/examples/05_capd_solver/main.cpp index e45ed0172..9428bdb54 100644 --- a/examples/05_capd_solver/main.cpp +++ b/examples/05_capd_solver/main.cpp @@ -2,6 +2,9 @@ // Adapted from CAPD examples #include +#include +#include "capd/capdlib.h" + using namespace std; using namespace codac2; From 522ac2765f8fb096c7d185cec6296ac363f47800 Mon Sep 17 00:00:00 2001 From: godardma Date: Fri, 10 Jan 2025 15:30:37 +0100 Subject: [PATCH 074/126] [capd] modified imports --- examples/05_capd_solver/main.cpp | 2 +- src/CMakeLists.txt | 1 + src/capd/CMakeLists.txt | 1 - src/capd/codac2_capd.cpp | 2 -- src/capd/codac2_capd.h | 4 +++- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/05_capd_solver/main.cpp b/examples/05_capd_solver/main.cpp index 9428bdb54..bd537bb4a 100644 --- a/examples/05_capd_solver/main.cpp +++ b/examples/05_capd_solver/main.cpp @@ -3,7 +3,7 @@ #include #include -#include "capd/capdlib.h" +#include using namespace std; using namespace codac2; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aece5fd9e..99109ee6e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -107,6 +107,7 @@ find_library(CODAC_CAPD_LIBRARY NAMES ${PROJECT_NAME}-capd PATH_SUFFIXES lib) + set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY} capd::capd) ") diff --git a/src/capd/CMakeLists.txt b/src/capd/CMakeLists.txt index 8a4fe56d5..eb20b24b9 100644 --- a/src/capd/CMakeLists.txt +++ b/src/capd/CMakeLists.txt @@ -45,7 +45,6 @@ list(APPEND CODAC_CAPD_SRC # Generating the file codac-capd.h set(CODAC_CAPD_MAIN_HEADER ${CMAKE_CURRENT_BINARY_DIR}/codac-capd.h) - set(CODAC_MAIN_SUBHEADERS ${CODAC_MAIN_SUBHEADERS} "codac-capd.h" PARENT_SCOPE) file(WRITE ${CODAC_CAPD_MAIN_HEADER} "/* This file is generated by CMake */\n\n") file(APPEND ${CODAC_CAPD_MAIN_HEADER} "#pragma once\n\n") foreach(header_path ${CODAC_CAPD_HDR}) diff --git a/src/capd/codac2_capd.cpp b/src/capd/codac2_capd.cpp index f5398f6ab..e847102a3 100644 --- a/src/capd/codac2_capd.cpp +++ b/src/capd/codac2_capd.cpp @@ -12,8 +12,6 @@ using namespace std; -#include - namespace codac2 { capd::Interval to_capd(const Interval &x) diff --git a/src/capd/codac2_capd.h b/src/capd/codac2_capd.h index 659bfff9b..9c442fcd3 100644 --- a/src/capd/codac2_capd.h +++ b/src/capd/codac2_capd.h @@ -9,7 +9,9 @@ #pragma once -#include "capd/capdlib.h" +// #include "capd/capdlib.h" +#include +#include #include "codac2_IntervalVector.h" #include "codac2_Matrix.h" #include "codac2_IntervalMatrix.h" From b6c3f3a4b41a5429c27c4a333f5c70b7f9cf9cb4 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 10 Jan 2025 16:06:31 +0100 Subject: [PATCH 075/126] [doc] files structure --- doc/manual/extensions/capd/index.rst | 10 ++++++++++ doc/manual/extensions/index.rst | 11 +++++++++++ doc/manual/index.rst | 5 +++-- doc/manual/visualization/3d_visualization.rst | 5 +++++ doc/manual/visualization/colors.rst | 5 +++++ doc/manual/visualization/figures.rst | 4 ++++ doc/manual/visualization/index.rst | 12 ++++++++++++ doc/manual/visualization/ipe.rst | 4 ++++ doc/manual/visualization/vibes.rst | 4 ++++ 9 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 doc/manual/extensions/capd/index.rst create mode 100644 doc/manual/extensions/index.rst create mode 100644 doc/manual/visualization/3d_visualization.rst create mode 100644 doc/manual/visualization/colors.rst create mode 100644 doc/manual/visualization/figures.rst create mode 100644 doc/manual/visualization/index.rst create mode 100644 doc/manual/visualization/ipe.rst create mode 100644 doc/manual/visualization/vibes.rst diff --git a/doc/manual/extensions/capd/index.rst b/doc/manual/extensions/capd/index.rst new file mode 100644 index 000000000..d63410f2c --- /dev/null +++ b/doc/manual/extensions/capd/index.rst @@ -0,0 +1,10 @@ +.. _sec-extensions-capd: + +CAPD (rigorous numerics in dynamical systems) +============================================= + +Installing the codac-capd extension +----------------------------------- + +How to use +---------- \ No newline at end of file diff --git a/doc/manual/extensions/index.rst b/doc/manual/extensions/index.rst new file mode 100644 index 000000000..fc9c8371b --- /dev/null +++ b/doc/manual/extensions/index.rst @@ -0,0 +1,11 @@ +.. _sec-extensions: + +Extensions +========== + +.. toctree:: + + capd/index.rst +.. ibex/index.rst +.. sympy/index.rst +.. unsupported/index.rst \ No newline at end of file diff --git a/doc/manual/index.rst b/doc/manual/index.rst index beee9bae0..545197880 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -21,6 +21,9 @@ Welcome to the Codac website. :maxdepth: 2 installation/index.rst + visualization/index.rst + extensions/index.rst + .. intervals/index.rst .. linear/index.rst .. functions/index.rst @@ -42,8 +45,6 @@ Welcome to the Codac website. .. geometry/index.rst .. ellipsoids/index.rst .. topology/index.rst -.. visualization/index.rst -.. extensions/index.rst .. seealso/index.rst .. references/index.rst diff --git a/doc/manual/visualization/3d_visualization.rst b/doc/manual/visualization/3d_visualization.rst new file mode 100644 index 000000000..826dfdad9 --- /dev/null +++ b/doc/manual/visualization/3d_visualization.rst @@ -0,0 +1,5 @@ +.. _sec-graphics-3d: + +Tools for 3d visualization +========================== + diff --git a/doc/manual/visualization/colors.rst b/doc/manual/visualization/colors.rst new file mode 100644 index 000000000..db4e5ba40 --- /dev/null +++ b/doc/manual/visualization/colors.rst @@ -0,0 +1,5 @@ +.. _sec-graphics-colors: + +Colors and color maps +===================== + diff --git a/doc/manual/visualization/figures.rst b/doc/manual/visualization/figures.rst new file mode 100644 index 000000000..13d92725e --- /dev/null +++ b/doc/manual/visualization/figures.rst @@ -0,0 +1,4 @@ +.. _sec-graphics-figures: + +The Figure classes +================== diff --git a/doc/manual/visualization/index.rst b/doc/manual/visualization/index.rst new file mode 100644 index 000000000..79b3cce63 --- /dev/null +++ b/doc/manual/visualization/index.rst @@ -0,0 +1,12 @@ +.. _sec-graphics: + +Visualization +============= + +.. toctree:: + + colors.rst + figures.rst + vibes.rst + ipe.rst + 3d_visualization.rst \ No newline at end of file diff --git a/doc/manual/visualization/ipe.rst b/doc/manual/visualization/ipe.rst new file mode 100644 index 000000000..56c24a1cc --- /dev/null +++ b/doc/manual/visualization/ipe.rst @@ -0,0 +1,4 @@ +.. _sec-graphics-ipe: + +The IPE editor +============== \ No newline at end of file diff --git a/doc/manual/visualization/vibes.rst b/doc/manual/visualization/vibes.rst new file mode 100644 index 000000000..f70a9485e --- /dev/null +++ b/doc/manual/visualization/vibes.rst @@ -0,0 +1,4 @@ +.. _sec-graphics-vibes: + +The VIBes viewer +================ From c2cf9e993a404678e513bdd41eec2bc4925af1cc Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 10 Jan 2025 18:20:46 +0100 Subject: [PATCH 076/126] [traj] build a SampledTraj from numpy arrays --- python/codac/core/__init__.py | 17 ++++- .../codac2_py_SampledTrajectory.cpp | 62 +++++++++++++++++++ .../trajectory/codac2_SampledTrajectory.h | 19 ++++++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index b00434847..714b230f5 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -1,6 +1,6 @@ from codac._core import * from sys import float_info - +import numpy def codac_error(message): print(f''' @@ -272,6 +272,16 @@ def __init__(self, m): else: codac_error("SampledTrajectory: can only build this trajectory from maps of scalar or vector values") + def __init__(self, l_t, l_x): + if not isinstance(l_t,(list,numpy.ndarray)) or not isinstance(l_x,(list,numpy.ndarray)): + codac_error("SampledTrajectory: can only build this trajectory from two lists") + elif isinstance(next(iter(l_x)), (int,float,numpy.float64)): + self.traj = SampledTrajectory_double(l_t,l_x) + elif isinstance(next(iter(l_x)), (Vector,list,tuple,numpy.ndarray)): + self.traj = SampledTrajectory_Vector(l_t,l_x) + else: + codac_error("SampledTrajectory: can only build this trajectory from a list of dates and a list of scalar or vector values") + # Methods from std::map: def __setitem__(self, t, y): @@ -315,4 +325,7 @@ def as_function(self): # Methods from SampledTrajectory: def nb_samples(self): - return self.traj.nb_samples() \ No newline at end of file + return self.traj.nb_samples() + + def __repr__(self): + return str(self.traj) \ No newline at end of file diff --git a/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp b/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp index ca4b45d22..26cd3da48 100644 --- a/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp +++ b/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "codac2_py_SampledTrajectory_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_TrajectoryBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): @@ -33,6 +34,60 @@ void _export_SampledTrajectory(py::module& m, const string& class_name) .def(py::init<>(), SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY) + + ; + + if constexpr(std::is_same_v) + { + exported_class + .def(py::init&,const std::list&>(), + SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY_CONST_LIST_DOUBLE_REF_CONST_LIST_T_REF, + "l_t"_a, "l_x"_a) + ; + } + + else if constexpr(std::is_same_v) + { + exported_class + .def(py::init( + [](const py::array_t& l_t, const py::array_t& l_x) + { + if constexpr(std::is_same_v) + { + assert_release(l_t.size() > 0 && l_x.size() > 0); + + list l_vx; + + py::buffer_info info = l_x.request(); + auto ptr = static_cast(info.ptr); + + size_t nb_values = 1; + for(const auto& r : info.shape) + nb_values *= r; + + assert(nb_values % l_t.size() == 0); + size_t n = nb_values / l_t.size(); + + for(size_t i = 0 ; i < nb_values ; i+=n) + { + Vector x(n); + for(size_t k = 0 ; k < n ; k++) + x[k] = *ptr++; + l_vx.push_back(x); + } + + return std::make_unique>(l_t.cast>(), l_vx); + } + + else + return std::make_unique>(); + }), + SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY_CONST_LIST_DOUBLE_REF_CONST_LIST_T_REF, + "l_t"_a, "l_x"_a) + ; + } + + exported_class .def(py::init&>(), SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY_CONST_MAP_DOUBLET_REF, @@ -59,6 +114,13 @@ void _export_SampledTrajectory(py::module& m, const string& class_name) matlab::test_integer(index); x[matlab::input_index(index)] = a; }) + + .def("__repr__", [](const SampledTrajectory& x) { + std::ostringstream stream; + stream << x; + return string(stream.str()); + }, + OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_SAMPLEDTRAJECTORY_T_REF) ; } diff --git a/src/core/trajectory/codac2_SampledTrajectory.h b/src/core/trajectory/codac2_SampledTrajectory.h index 663852489..1c6f165ff 100644 --- a/src/core/trajectory/codac2_SampledTrajectory.h +++ b/src/core/trajectory/codac2_SampledTrajectory.h @@ -24,6 +24,18 @@ namespace codac2 : TrajectoryBase(), std::map() { } + SampledTrajectory(const std::list& l_t, const std::list& l_x) + : SampledTrajectory() + { + assert_release(l_t.size() == l_x.size()); + auto it_t = l_t.begin(); auto it_x = l_x.begin(); + while(it_t != l_t.end()) + { + (*this)[*(it_t)] = *(it_x); + it_t++; it_x++; + } + } + SampledTrajectory(const std::map& m) : TrajectoryBase(), std::map(m) { } @@ -148,4 +160,11 @@ namespace codac2 return straj; } }; + + template + inline std::ostream& operator<<(std::ostream& os, const SampledTrajectory& x) + { + os << "SampledTraj. " << x.tdomain() << "↦" << x.codomain() << ", " << x.nb_samples() << " pts"; + return os; + } } \ No newline at end of file From 3438318ffc7a43d0e972221705db6a9f67c30321 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Mon, 13 Jan 2025 11:02:21 +0100 Subject: [PATCH 077/126] [doc] sphinx tabs --- doc/manual/_static/css/custom.css | 7 ++++ doc/manual/conf.py.in | 3 +- doc/manual/development/info_dev.rst | 2 +- doc/manual/index.rst | 4 +- doc/manual/installation/cpp.rst | 4 +- doc/manual/intervals/class.rst | 57 +++++++++++++++++++++++++++++ doc/manual/intervals/index.rst | 12 ++++++ 7 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 doc/manual/intervals/class.rst create mode 100644 doc/manual/intervals/index.rst diff --git a/doc/manual/_static/css/custom.css b/doc/manual/_static/css/custom.css index b326520fa..de6a2c853 100644 --- a/doc/manual/_static/css/custom.css +++ b/doc/manual/_static/css/custom.css @@ -23,4 +23,11 @@ a.sidebar-brand { .announcement-content { font-size: 0.8rem; +} + + +/* Removes empty space below blocks of code in tabs */ +.sphinx-tabs-panel div[class^="highlight"] { + margin-bottom: 0; + margin-top: 0; } \ No newline at end of file diff --git a/doc/manual/conf.py.in b/doc/manual/conf.py.in index b125e43ae..58d9338f8 100644 --- a/doc/manual/conf.py.in +++ b/doc/manual/conf.py.in @@ -17,7 +17,8 @@ version = u'${PROJECT_VERSION}' extensions = [ 'sphinx_rtd_theme', 'sphinx_math_dollar', - 'sphinx.ext.mathjax' + 'sphinx.ext.mathjax', + 'sphinx_tabs.tabs', ] templates_path = ['_templates'] diff --git a/doc/manual/development/info_dev.rst b/doc/manual/development/info_dev.rst index 7b2033af4..be3dddb36 100644 --- a/doc/manual/development/info_dev.rst +++ b/doc/manual/development/info_dev.rst @@ -10,7 +10,7 @@ To build this manual using Sphinx, follow these steps: .. code-block:: bash - pip install sphinx sphinx_rtd_theme furo sphinx-math-dollar + pip install sphinx sphinx_rtd_theme furo sphinx-math-dollar sphinx_tabs 2. **Building the manual**: After configuring the CMake project, the manual can be build with: diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 545197880..5377ab6a4 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -21,10 +21,10 @@ Welcome to the Codac website. :maxdepth: 2 installation/index.rst + intervals/index.rst visualization/index.rst extensions/index.rst - -.. intervals/index.rst + .. linear/index.rst .. functions/index.rst .. tubes/index.rst diff --git a/doc/manual/installation/cpp.rst b/doc/manual/installation/cpp.rst index 5a85db574..6078c7a89 100644 --- a/doc/manual/installation/cpp.rst +++ b/doc/manual/installation/cpp.rst @@ -197,7 +197,7 @@ Optionally, for Python binding (*e.g.* ``choco install python --version=3.10.4`` choco install doxygen.install --version=1.13 choco install graphviz python -m pip install --upgrade pip - pip install --upgrade wheel setuptools sphinx sphinx_rtd_theme furo sphinx-math-dollar + pip install --upgrade wheel setuptools sphinx sphinx_rtd_theme furo sphinx-math-dollar sphinx_tabs The logic to follow will then be similar to Linux (note that for Visual Studio, commands such as ``make install`` need to be replaced with something similar to: @@ -254,7 +254,7 @@ Optionally, for Python binding and documentation: wget https://github.com/Homebrew/homebrew-core/raw/d2267b9f2ad247bc9c8273eb755b39566a474a70/Formula/doxygen.rb ; brew reinstall ./doxygen.rb ; brew pin doxygen brew install graphviz python -m pip install --upgrade pip - pip install --upgrade wheel setuptools sphinx sphinx_rtd_theme furo sphinx-math-dollar + pip install --upgrade wheel setuptools sphinx sphinx_rtd_theme furo sphinx-math-dollar sphinx_tabs Troubleshooting diff --git a/doc/manual/intervals/class.rst b/doc/manual/intervals/class.rst new file mode 100644 index 000000000..9b95b1845 --- /dev/null +++ b/doc/manual/intervals/class.rst @@ -0,0 +1,57 @@ +.. _sec-intervals-class: + +The Interval class +================== + +``Interval x(double lb, double ub)`` will define the interval :math:`[x]`. +It is made of its lower and upper bounds :math:`[x^{-},x^{+}]`. + +.. tabs:: + + .. code-tab:: py + + x = Interval(0,10) # [0,10] + x = Interval(1,oo) # [1,∞] + x = Interval(-oo,-10) # [-∞,-10] + + .. code-tab:: c++ + + Interval x(0,10); // [0,10] + Interval x(1,oo); // [1,∞] + Interval x(-oo,-10); // [-∞,-10] + +Some pre-defined values are also at hand: + +.. tabs:: + + .. code-tab:: py + + x = Interval() # [-∞,∞] (default value) + x = Interval.empty() # ∅ + x = Interval.pi() # [π] + x = Interval.two_pi() # [2π] + x = Interval.half_pi() # [π/2] + + .. code-tab:: c++ + + Interval x; // [-∞,∞] (default value) + Interval x = Interval::empty(); // ∅ + Interval x = Interval::pi(); // [π] + Interval x = Interval::two_pi(); // [2π] + Interval x = Interval::half_pi(); // [π/2] + +.. _sec-intervals-class-pi: + +Note that the constant :math:`[\pi]` is a reliable enclosure of the :math:`\pi` value, that cannot be exactly represented in a computer with a single floating-point value. + +.. tabs:: + + .. code-tab:: py + + x = Interval.pi() # [π] + # x = [3.141592653589793, 3.141592653589794] + + .. code-tab:: c++ + + Interval x = Interval::pi(); // [π] + // x = [3.141592653589793, 3.141592653589794] \ No newline at end of file diff --git a/doc/manual/intervals/index.rst b/doc/manual/intervals/index.rst new file mode 100644 index 000000000..32676e62d --- /dev/null +++ b/doc/manual/intervals/index.rst @@ -0,0 +1,12 @@ +.. _sec-intervals: + +Intervals +========= + +.. toctree:: + + class.rst + +.. What is an interval? + The Interval class + Boolean intervals \ No newline at end of file From 3835519356f8bed7151f95fbd46fa0f68a3edd93 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Mon, 13 Jan 2025 13:16:38 +0100 Subject: [PATCH 078/126] [py] optional import numpy --- python/codac/core/__init__.py | 53 ++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index 714b230f5..63c7cac62 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -1,6 +1,5 @@ from codac._core import * -from sys import float_info -import numpy +import sys def codac_error(message): print(f''' @@ -135,7 +134,7 @@ def copy(self): class Approx: - def __init__(self, x, eps = float_info.epsilon*10): + def __init__(self, x, eps = sys.float_info.epsilon*10): if isinstance(x, (int,float)): self.a = Approx_double(x,eps) elif isinstance(x, (Interval)): @@ -260,27 +259,41 @@ def as_function(self): class SampledTrajectory: - def __init__(self, m): - if isinstance(m, (SampledTrajectory_double,SampledTrajectory_Vector)): - self.traj = m - elif not isinstance(m,dict): - codac_error("SampledTrajectory: can only build this trajectory from a dictionary") - elif isinstance(next(iter(m.values())), (int,float)): - self.traj = SampledTrajectory_double(m) - elif isinstance(next(iter(m.values())), (Vector,list)): - self.traj = SampledTrajectory_Vector(m) - else: - codac_error("SampledTrajectory: can only build this trajectory from maps of scalar or vector values") - - def __init__(self, l_t, l_x): - if not isinstance(l_t,(list,numpy.ndarray)) or not isinstance(l_x,(list,numpy.ndarray)): + def __init__(self, l_t, l_x=[]): + + if isinstance(l_t, (SampledTrajectory_double,SampledTrajectory_Vector)): + self.traj = l_t + return + + elif isinstance(l_t,dict): + if isinstance(next(iter(l_t.values())), (int,float)): + self.traj = SampledTrajectory_double(l_t) + elif isinstance(next(iter(l_t.values())), (Vector,list)): + self.traj = SampledTrajectory_Vector(l_t) + else: + codac_error("SampledTrajectory: invalid input") + return + + elif 'numpy' in sys.modules: # a SampledTrajectory object can be built from numpy arrays + + if not isinstance(l_t,(list,sys.modules['numpy'].ndarray)) or not isinstance(l_x,(list,sys.modules['numpy'].ndarray)): + codac_error("SampledTrajectory: can only build this trajectory from two lists") + return + elif isinstance(next(iter(l_x)), sys.modules['numpy'].float64): + self.traj = SampledTrajectory_double(l_t,l_x) + return + elif isinstance(next(iter(l_x)), sys.modules['numpy'].ndarray): + self.traj = SampledTrajectory_Vector(l_t,l_x) + return + + if not isinstance(l_t,list) or not isinstance(l_x,list): codac_error("SampledTrajectory: can only build this trajectory from two lists") - elif isinstance(next(iter(l_x)), (int,float,numpy.float64)): + elif isinstance(next(iter(l_x)), (int,float)): self.traj = SampledTrajectory_double(l_t,l_x) - elif isinstance(next(iter(l_x)), (Vector,list,tuple,numpy.ndarray)): + elif isinstance(next(iter(l_x)), (Vector,list,tuple)): self.traj = SampledTrajectory_Vector(l_t,l_x) else: - codac_error("SampledTrajectory: can only build this trajectory from a list of dates and a list of scalar or vector values") + codac_error("SampledTrajectory: invalid input") # Methods from std::map: From 1e22ff4224338d558775de55c1e87d489852ee46 Mon Sep 17 00:00:00 2001 From: godardma Date: Mon, 13 Jan 2025 15:59:30 +0100 Subject: [PATCH 079/126] [doc] early doc for figures --- doc/manual/visualization/figures.rst | 68 ++++++++++++++++++++++++++ doc/manual/visualization/functions.rst | 5 ++ doc/manual/visualization/index.rst | 3 +- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 doc/manual/visualization/functions.rst diff --git a/doc/manual/visualization/figures.rst b/doc/manual/visualization/figures.rst index 13d92725e..170f157e4 100644 --- a/doc/manual/visualization/figures.rst +++ b/doc/manual/visualization/figures.rst @@ -2,3 +2,71 @@ The Figure classes ================== + +This page describes the classes used in Codac for 2D visualization. + +Graphical outputs +----------------- + +Two graphical outputs are currently supported in Codac: :ref:`VIBes ` and :ref:`IPE `. VIBes is used for real-time +visualization while IPE creates a file that can be edited by the IPE editor. These outputs are referenced by the enumeration GraphicOutput: + +.. tabs:: + + .. code-tab:: py + + GraphicOutput.VIBES # for VIBes + GraphicOutput.IPE # for IPE + GraphicOutput.VIBES | GraphicOutput.IPE # for both + + .. code-tab:: c++ + + GraphicOutput::VIBES // for VIBes + GraphicOutput::IPE // for IPE + GraphicOutput::VIBES | GraphicOutput::IPE // for both + +Note that for the VIBes output to work, the VIBes viewer must be launched before the program is run. + +Figure2D +-------- + + + + +.. tabs:: + + .. code-tab:: py + + from codac import * + + # .. next questions will be here + + .. code-tab:: c++ + + #include + + using namespace std; + using namespace codac; + + int main() + { + // .. next questions will be here + } + +DefaultView +----------- + +A DefaultView using only VIBes as graphical output is available. This figure is for example used in `draw_while_paving` by default. +Any Figure2D object can be used as DefaultView with the set method: + +.. tabs:: + + .. code-tab:: py + + figure = Figure2D("My figure", GraphicOutput.VIBES | GraphicOutput.IPE) + DefaultView.set(figure) + + .. code-tab:: c++ + + Figure2D figure = std::make_shared("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); + DefaultView::set(figure); \ No newline at end of file diff --git a/doc/manual/visualization/functions.rst b/doc/manual/visualization/functions.rst new file mode 100644 index 000000000..3451b92f2 --- /dev/null +++ b/doc/manual/visualization/functions.rst @@ -0,0 +1,5 @@ +.. _sec-graphics-functions: + +Drawing functions +================= + diff --git a/doc/manual/visualization/index.rst b/doc/manual/visualization/index.rst index 79b3cce63..7b50c4644 100644 --- a/doc/manual/visualization/index.rst +++ b/doc/manual/visualization/index.rst @@ -5,8 +5,9 @@ Visualization .. toctree:: - colors.rst figures.rst + functions.rst + colors.rst vibes.rst ipe.rst 3d_visualization.rst \ No newline at end of file From 0562baf8f0999ca15df1f1a61a94201a65770166 Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 14 Jan 2025 13:53:11 +0100 Subject: [PATCH 080/126] [capd] minor update --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 99109ee6e..e878211fb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,7 +108,7 @@ find_library(CODAC_CAPD_LIBRARY NAMES ${PROJECT_NAME}-capd PATH_SUFFIXES lib) - set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY} capd::capd) + set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY} capd::capd \${CODAC_CORE_LIBRARY}) ") endif() From 39ae61d263b8627e617deb1509218e4240e9d9cf Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 14 Jan 2025 14:34:56 +0100 Subject: [PATCH 081/126] [capd] minor update --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e878211fb..31e21c395 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,7 +108,7 @@ find_library(CODAC_CAPD_LIBRARY NAMES ${PROJECT_NAME}-capd PATH_SUFFIXES lib) - set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY} capd::capd \${CODAC_CORE_LIBRARY}) + set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY} capd::capd \${CODAC_GRAPHICS_LIBRARY}) ") endif() From 20e8a7788ed16a7cddfd455d10f20f03cdd74f82 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 15 Jan 2025 16:26:06 +0100 Subject: [PATCH 082/126] [traj] updated binding + operators --- doc/manual/index.rst | 2 +- .../{class.rst => Interval_class.rst} | 0 doc/manual/intervals/index.rst | 2 +- examples/04_explored_area/main.cpp | 4 +- examples/04_explored_area/main.py | 4 +- python/codac/core/__init__.py | 105 +------- python/src/core/CMakeLists.txt | 6 +- python/src/core/codac2_py_cast.h | 21 -- python/src/core/codac2_py_core.cpp | 9 +- .../analytic/codac2_py_AnalyticFunction.h | 16 ++ .../trajectory/codac2_py_AnalyticTraj.cpp | 46 ++++ .../codac2_py_AnalyticTrajectory.cpp | 46 ---- .../core/trajectory/codac2_py_SampledTraj.cpp | 225 ++++++++++++++++++ .../codac2_py_SampledTrajectory.cpp | 131 ---------- ..._TrajectoryBase.h => codac2_py_TrajBase.h} | 26 +- .../graphics/figures/codac2_py_Figure2D.cpp | 66 ++--- src/core/CMakeLists.txt | 9 +- src/core/tools/codac2_math.h | 21 ++ src/core/tools/codac2_template_tools.h | 7 + ...yticTrajectory.h => codac2_AnalyticTraj.h} | 12 +- ...mpledTrajectory.h => codac2_SampledTraj.h} | 26 +- ...ac2_TrajectoryBase.h => codac2_TrajBase.h} | 16 +- ...tory_operator.h => codac2_Traj_operator.h} | 16 +- src/graphics/figures/codac2_Figure2D.cpp | 8 +- src/graphics/figures/codac2_Figure2D.h | 16 +- .../figures/codac2_Figure2DInterface.h | 4 +- tests/CMakeLists.txt | 4 +- ...tory.cpp => codac2_tests_AnalyticTraj.cpp} | 6 +- ...ectory.py => codac2_tests_AnalyticTraj.py} | 6 +- ...ctory.cpp => codac2_tests_SampledTraj.cpp} | 26 +- ...jectory.py => codac2_tests_SampledTraj.py} | 14 +- 31 files changed, 462 insertions(+), 438 deletions(-) rename doc/manual/intervals/{class.rst => Interval_class.rst} (100%) create mode 100644 python/src/core/trajectory/codac2_py_AnalyticTraj.cpp delete mode 100644 python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp create mode 100644 python/src/core/trajectory/codac2_py_SampledTraj.cpp delete mode 100644 python/src/core/trajectory/codac2_py_SampledTrajectory.cpp rename python/src/core/trajectory/{codac2_py_TrajectoryBase.h => codac2_py_TrajBase.h} (68%) rename src/core/trajectory/{codac2_AnalyticTrajectory.h => codac2_AnalyticTraj.h} (82%) rename src/core/trajectory/{codac2_SampledTrajectory.h => codac2_SampledTraj.h} (85%) rename src/core/trajectory/{codac2_TrajectoryBase.h => codac2_TrajBase.h} (87%) rename src/core/trajectory/{codac2_Trajectory_operator.h => codac2_Traj_operator.h} (83%) rename tests/core/trajectory/{codac2_tests_AnalyticTrajectory.cpp => codac2_tests_AnalyticTraj.cpp} (94%) rename tests/core/trajectory/{codac2_tests_AnalyticTrajectory.py => codac2_tests_AnalyticTraj.py} (94%) rename tests/core/trajectory/{codac2_tests_SampledTrajectory.cpp => codac2_tests_SampledTraj.cpp} (82%) rename tests/core/trajectory/{codac2_tests_SampledTrajectory.py => codac2_tests_SampledTraj.py} (90%) diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 5377ab6a4..adb6fadca 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -22,6 +22,7 @@ Welcome to the Codac website. installation/index.rst intervals/index.rst + ellipsoids/index.rst visualization/index.rst extensions/index.rst @@ -43,7 +44,6 @@ Welcome to the Codac website. .. pavers/index.rst .. cn/index.rst .. geometry/index.rst -.. ellipsoids/index.rst .. topology/index.rst .. seealso/index.rst .. references/index.rst diff --git a/doc/manual/intervals/class.rst b/doc/manual/intervals/Interval_class.rst similarity index 100% rename from doc/manual/intervals/class.rst rename to doc/manual/intervals/Interval_class.rst diff --git a/doc/manual/intervals/index.rst b/doc/manual/intervals/index.rst index 32676e62d..b7587d388 100644 --- a/doc/manual/intervals/index.rst +++ b/doc/manual/intervals/index.rst @@ -5,7 +5,7 @@ Intervals .. toctree:: - class.rst + Interval_class.rst .. What is an interval? The Interval class diff --git a/examples/04_explored_area/main.cpp b/examples/04_explored_area/main.cpp index a203fd30e..0f559b638 100644 --- a/examples/04_explored_area/main.cpp +++ b/examples/04_explored_area/main.cpp @@ -18,7 +18,7 @@ int main() }; Interval tdomain(0,5); - auto sampled_f = AnalyticTrajectory(f,tdomain).sampled(0.8); + auto sampled_f = AnalyticTraj(f,tdomain).sampled(0.8); sampled_f[6] = {0,-1}; // appending the position (0,-1) at t=6 VectorVar w(3); @@ -34,5 +34,5 @@ int main() DefaultView::set_window_properties({75,75},{700,700}); draw_while_paving({{-3,3},{-2,2}}, s_projh, 5e-2); DefaultView::draw_trajectory(sampled_f); - DefaultView::draw_trajectory(AnalyticTrajectory(f,tdomain), Color::dark_gray()); + DefaultView::draw_trajectory(AnalyticTraj(f,tdomain), Color::dark_gray()); } \ No newline at end of file diff --git a/examples/04_explored_area/main.py b/examples/04_explored_area/main.py index e55a590cd..96e2bcd6a 100644 --- a/examples/04_explored_area/main.py +++ b/examples/04_explored_area/main.py @@ -14,7 +14,7 @@ ) tdomain = [0,5] -sampled_f = AnalyticTrajectory(f,tdomain).sampled(0.8) +sampled_f = AnalyticTraj(f,tdomain).sampled(0.8) sampled_f[6] = [0,-1] # appending the position (0,-1) at t=6 w = VectorVar(3) @@ -30,4 +30,4 @@ DefaultView.set_window_properties([75,75],[700,700]) draw_while_paving([[-3,3],[-2,2]], s_projh, 5e-2) DefaultView.draw_trajectory(sampled_f) -DefaultView.draw_trajectory(AnalyticTrajectory(f,tdomain), Color.dark_gray()) \ No newline at end of file +DefaultView.draw_trajectory(AnalyticTraj(f,tdomain), Color.dark_gray()) \ No newline at end of file diff --git a/python/codac/core/__init__.py b/python/codac/core/__init__.py index 63c7cac62..2807fbeb1 100644 --- a/python/codac/core/__init__.py +++ b/python/codac/core/__init__.py @@ -209,19 +209,19 @@ def cart_prod(*args): codac_error("cart_prod: invalid input arguments") -class AnalyticTrajectory: +class AnalyticTraj: def __init__(self, f, t): if isinstance(f, AnalyticFunction): self.__init__(f.f,t) elif isinstance(f, AnalyticFunction_Scalar): - self.traj = AnalyticTrajectory_Scalar(f,t) + self.traj = AnalyticTraj_Scalar(f,t) elif isinstance(f, AnalyticFunction_Vector): - self.traj = AnalyticTrajectory_Vector(f,t) + self.traj = AnalyticTraj_Vector(f,t) else: - codac_error("AnalyticTrajectory: can only build this trajectory from an AnalyticFunction_[Scalar/Vector]") + codac_error("AnalyticTraj: can only build this trajectory from an AnalyticFunction_[Scalar/Vector]") - # Methods from TrajectoryBase: + # Methods from TrajBase: def size(self): return self.traj.size() @@ -245,100 +245,13 @@ def nan_value(self): return self.traj.nan_value() def sampled(self, dt): - return SampledTrajectory(self.traj.sampled(dt)) + return self.traj.sampled(dt) def primitive(self, y0, t): - return SampledTrajectory(self.traj.primitive(y0, t)) + return self.traj.primitive(y0, t) def as_function(self): return AnalyticFunction(self.traj.as_function()) - # Methods from AnalyticTrajectory: - # none - - -class SampledTrajectory: - - def __init__(self, l_t, l_x=[]): - - if isinstance(l_t, (SampledTrajectory_double,SampledTrajectory_Vector)): - self.traj = l_t - return - - elif isinstance(l_t,dict): - if isinstance(next(iter(l_t.values())), (int,float)): - self.traj = SampledTrajectory_double(l_t) - elif isinstance(next(iter(l_t.values())), (Vector,list)): - self.traj = SampledTrajectory_Vector(l_t) - else: - codac_error("SampledTrajectory: invalid input") - return - - elif 'numpy' in sys.modules: # a SampledTrajectory object can be built from numpy arrays - - if not isinstance(l_t,(list,sys.modules['numpy'].ndarray)) or not isinstance(l_x,(list,sys.modules['numpy'].ndarray)): - codac_error("SampledTrajectory: can only build this trajectory from two lists") - return - elif isinstance(next(iter(l_x)), sys.modules['numpy'].float64): - self.traj = SampledTrajectory_double(l_t,l_x) - return - elif isinstance(next(iter(l_x)), sys.modules['numpy'].ndarray): - self.traj = SampledTrajectory_Vector(l_t,l_x) - return - - if not isinstance(l_t,list) or not isinstance(l_x,list): - codac_error("SampledTrajectory: can only build this trajectory from two lists") - elif isinstance(next(iter(l_x)), (int,float)): - self.traj = SampledTrajectory_double(l_t,l_x) - elif isinstance(next(iter(l_x)), (Vector,list,tuple)): - self.traj = SampledTrajectory_Vector(l_t,l_x) - else: - codac_error("SampledTrajectory: invalid input") - - # Methods from std::map: - - def __setitem__(self, t, y): - self.traj[t] = y - - def __getitem__(self, t): - return self.traj[t] - - # Methods from TrajectoryBase: - - def size(self): - return self.traj.size() - - def is_empty(self): - return self.traj.is_empty() - - def tdomain(self): - return self.traj.tdomain() - - def truncate_tdomain(self, new_tdomain): - return self.traj.truncate_tdomain(new_tdomain) - - def codomain(self): - return self.traj.codomain() - - def __call__(self, t): - return self.traj(t) - - def nan_value(self): - return self.traj.nan_value() - - def sampled(self, *args): - return SampledTrajectory(self.traj.sampled(*args)) - - def primitive(self, y0, t): - return SampledTrajectory(self.traj.primitive(y0, t)) - - def as_function(self): - return AnalyticFunction(self.traj.as_function()) - - # Methods from SampledTrajectory: - - def nb_samples(self): - return self.traj.nb_samples() - - def __repr__(self): - return str(self.traj) \ No newline at end of file + # Methods from AnalyticTraj: + # none \ No newline at end of file diff --git a/python/src/core/CMakeLists.txt b/python/src/core/CMakeLists.txt index 479cece14..2ac525d86 100644 --- a/python/src/core/CMakeLists.txt +++ b/python/src/core/CMakeLists.txt @@ -84,9 +84,9 @@ tools/codac2_py_Approx.cpp - trajectory/codac2_py_AnalyticTrajectory.cpp - trajectory/codac2_py_SampledTrajectory.cpp - trajectory/codac2_py_TrajectoryBase.h + trajectory/codac2_py_AnalyticTraj.cpp + trajectory/codac2_py_SampledTraj.cpp + trajectory/codac2_py_TrajBase.h ) target_include_directories(_core diff --git a/python/src/core/codac2_py_cast.h b/python/src/core/codac2_py_cast.h index 959a41649..e9c3efb38 100644 --- a/python/src/core/codac2_py_cast.h +++ b/python/src/core/codac2_py_cast.h @@ -11,8 +11,6 @@ #pragma once #include -#include -#include namespace py = pybind11; using namespace pybind11::literals; @@ -35,25 +33,6 @@ namespace codac2 return x.cast(); } - // Casting to trajectory types - - template - requires std::is_same_v - bool is_instance(const py::object& x) - { - const py::object& x_traj = x.attr("traj"); - return x_traj && py::isinstance(x_traj); - } - - template - requires std::is_same_v - const Tr& cast(const py::object& x) - { - assert(is_instance(x)); - const py::object& x_traj = x.attr("traj"); - return x_traj.cast(); - } - // Casting to function/expression types template diff --git a/python/src/core/codac2_py_core.cpp b/python/src/core/codac2_py_core.cpp index d18b30f6e..a298a1aa1 100644 --- a/python/src/core/codac2_py_core.cpp +++ b/python/src/core/codac2_py_core.cpp @@ -115,8 +115,8 @@ void export_SepWrapper(py::module& m, py::class_& sep); void export_Approx(py::module& m); // trajectory -void export_AnalyticTrajectory(py::module& m); -void export_SampledTrajectory(py::module& m); +void export_AnalyticTraj(py::module& m); +void export_SampledTraj(py::module& m); PYBIND11_MODULE(_core, m) @@ -228,7 +228,6 @@ PYBIND11_MODULE(_core, m) export_Approx(m); // trajectory - export_AnalyticTrajectory(m); - export_SampledTrajectory(m); - + export_AnalyticTraj(m); + export_SampledTraj(m); } diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index cb8257c8e..f227b24c5 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -215,6 +215,22 @@ void export_AnalyticFunction(py::module& m, const std::string& export_name) .def("input_size", &AnalyticFunction::input_size, INDEX_FUNCTIONBASE_E_INPUT_SIZE_CONST) + .def("__call__", [](const AnalyticFunction& f, const ScalarExpr& x) + { + return AnalyticExprWrapper( + std::dynamic_pointer_cast>( + f(x)->copy())); + }, + SHARED_PTR_E_FUNCTIONBASE_E_OPERATORCALL_CONST_X_REF_VARIADIC_CONST) + + .def("__call__", [](const AnalyticFunction& f, const ScalarVar& x) + { + return AnalyticExprWrapper( + std::dynamic_pointer_cast>( + f(x)->copy())); + }, + SHARED_PTR_E_FUNCTIONBASE_E_OPERATORCALL_CONST_X_REF_VARIADIC_CONST) + .def("__call__", [](const AnalyticFunction& f, py::list& x) { std::vector> v(x.size()); diff --git a/python/src/core/trajectory/codac2_py_AnalyticTraj.cpp b/python/src/core/trajectory/codac2_py_AnalyticTraj.cpp new file mode 100644 index 000000000..e3f0aa2bb --- /dev/null +++ b/python/src/core/trajectory/codac2_py_AnalyticTraj.cpp @@ -0,0 +1,46 @@ +/** + * AnalyticTraj Python binding + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include +#include "codac2_py_AnalyticTraj_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_TrajBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_TrajBase.h" +#include "codac2_Traj_operator.h" +#include "codac2_py_doc.h" + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +template +void _export_AnalyticTraj(py::module& m, const string& class_name) +{ + py::class_> exported_class(m, class_name.c_str(), ANALYTICTRAJ_MAIN); + export_TrajBase>(exported_class); + + exported_class + + .def(py::init&,const Interval&>(), + ANALYTICTRAJ_OS_ANALYTICTRAJ_CONST_ANALYTICFUNCTION_O_REF_CONST_INTERVAL_REF, + "f"_a, "tdomain"_a) + + ; +} + +void export_AnalyticTraj(py::module& m) +{ + _export_AnalyticTraj(m, "AnalyticTraj_Scalar"); + _export_AnalyticTraj(m, "AnalyticTraj_Vector"); +} \ No newline at end of file diff --git a/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp b/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp deleted file mode 100644 index 7c05e51c3..000000000 --- a/python/src/core/trajectory/codac2_py_AnalyticTrajectory.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/** - * AnalyticTrajectory Python binding - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include -#include -#include -#include -#include -#include -#include "codac2_py_AnalyticTrajectory_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): -#include "codac2_py_TrajectoryBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): -#include "codac2_py_TrajectoryBase.h" -#include "codac2_Trajectory_operator.h" -#include "codac2_py_doc.h" - -using namespace std; -using namespace codac2; -namespace py = pybind11; -using namespace pybind11::literals; - -template -void _export_AnalyticTrajectory(py::module& m, const string& class_name) -{ - py::class_> exported_class(m, class_name.c_str(), ANALYTICTRAJECTORY_MAIN); - export_TrajectoryBase>(exported_class); - - exported_class - - .def(py::init&,const Interval&>(), - ANALYTICTRAJECTORY_OS_ANALYTICTRAJECTORY_CONST_ANALYTICFUNCTION_O_REF_CONST_INTERVAL_REF, - "f"_a, "tdomain"_a) - - ; -} - -void export_AnalyticTrajectory(py::module& m) -{ - _export_AnalyticTrajectory(m, "AnalyticTrajectory_Scalar"); - _export_AnalyticTrajectory(m, "AnalyticTrajectory_Vector"); -} \ No newline at end of file diff --git a/python/src/core/trajectory/codac2_py_SampledTraj.cpp b/python/src/core/trajectory/codac2_py_SampledTraj.cpp new file mode 100644 index 000000000..d7c0ecdde --- /dev/null +++ b/python/src/core/trajectory/codac2_py_SampledTraj.cpp @@ -0,0 +1,225 @@ +/** + * SampledTraj binding + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include +#include +#include "codac2_py_SampledTraj_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_TrajBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_SampledTraj_operations_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_TrajBase.h" + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +template +void _export_SampledTraj(py::module& m, const string& class_name) +{ + py::class_> exported_class(m, class_name.c_str(), SAMPLEDTRAJ_MAIN); + export_TrajBase>(exported_class); + + exported_class + + .def(py::init<>(), + SAMPLEDTRAJ_T_SAMPLEDTRAJ) + + ; + + if constexpr(std::is_same_v) + { + exported_class + .def(py::init&,const std::list&>(), + SAMPLEDTRAJ_T_SAMPLEDTRAJ_CONST_LIST_DOUBLE_REF_CONST_LIST_T_REF, + "l_t"_a, "l_x"_a) + ; + } + + else if constexpr(std::is_same_v) + { + exported_class + .def(py::init( + [](const py::array_t& l_t, const py::array_t& l_x) + { + if constexpr(std::is_same_v) + { + assert_release(l_t.size() > 0 && l_x.size() > 0); + + list l_vx; + + py::buffer_info info = l_x.request(); + auto ptr = static_cast(info.ptr); + + size_t nb_values = 1; + for(const auto& r : info.shape) + nb_values *= r; + + assert(nb_values % l_t.size() == 0); + size_t n = nb_values / l_t.size(); + + for(size_t i = 0 ; i < nb_values ; i+=n) + { + Vector x(n); + for(size_t k = 0 ; k < n ; k++) + x[k] = *ptr++; + l_vx.push_back(x); + } + + return std::make_unique>(l_t.cast>(), l_vx); + } + + else + return std::make_unique>(); + }), + SAMPLEDTRAJ_T_SAMPLEDTRAJ_CONST_LIST_DOUBLE_REF_CONST_LIST_T_REF, + "l_t"_a, "l_x"_a) + ; + } + + exported_class + + .def(py::init&>(), + SAMPLEDTRAJ_T_SAMPLEDTRAJ_CONST_MAP_DOUBLET_REF, + "m"_a) + + .def("nb_samples", &SampledTraj::nb_samples, + SIZET_SAMPLEDTRAJ_T_NB_SAMPLES_CONST) + + .def("sampled", [](const SampledTraj& x, double dt, bool keep_original_values) + { + return x.sampled(dt,keep_original_values); + }, + SAMPLEDTRAJ_T_SAMPLEDTRAJ_T_SAMPLED_DOUBLE_BOOL_CONST, + "dt"_a, "keep_original_values"_a) + + .def("__getitem__", [](const SampledTraj& x, Index_type index) -> const T& + { + matlab::test_integer(index); + return x.at(matlab::input_index(index)); + }, py::return_value_policy::reference_internal) + + .def("__setitem__", [](SampledTraj& x, Index_type index, const T& a) + { + matlab::test_integer(index); + x[matlab::input_index(index)] = a; + }) + + .def("__repr__", [](const SampledTraj& x) { + std::ostringstream stream; + stream << x; + return string(stream.str()); + }, + OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_SAMPLEDTRAJ_T_REF) + ; +} + +void export_SampledTraj(py::module& m) +{ + _export_SampledTraj(m, "SampledTraj"); + _export_SampledTraj(m, "SampledVectorTraj"); + + m + + .def("sqr", (SampledTraj (*)(const SampledTraj&)) &codac2::sqr, + py::is_operator(), + SAMPLEDTRAJ_T_SQR_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("sqrt", (SampledTraj (*)(const SampledTraj&)) &codac2::sqrt, + py::is_operator(), + SAMPLEDTRAJ_T_SQRT_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("pow", (SampledTraj (*)(const SampledTraj&,int)) &codac2::pow, + py::is_operator(), + SAMPLEDTRAJ_T_POW_CONST_SAMPLEDTRAJ_T_REF_INT, + "x1"_a, "x2"_a) + + .def("pow", (SampledTraj (*)(const SampledTraj&,double)) &codac2::pow, + py::is_operator(), + SAMPLEDTRAJ_T_POW_CONST_SAMPLEDTRAJ_T_REF_DOUBLE, + "x1"_a, "x2"_a) + + .def("root", (SampledTraj (*)(const SampledTraj&,int)) &codac2::root, + py::is_operator(), + SAMPLEDTRAJ_T_ROOT_CONST_SAMPLEDTRAJ_T_REF_INT, + "x1"_a, "x2"_a) + + .def("exp", (SampledTraj (*)(const SampledTraj&)) &codac2::exp, + py::is_operator(), + SAMPLEDTRAJ_T_EXP_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("log", (SampledTraj (*)(const SampledTraj&)) &codac2::log, + py::is_operator(), + SAMPLEDTRAJ_T_LOG_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("cos", (SampledTraj (*)(const SampledTraj&)) &codac2::cos, + py::is_operator(), + SAMPLEDTRAJ_T_COS_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("sin", (SampledTraj (*)(const SampledTraj&)) &codac2::sin, + py::is_operator(), + SAMPLEDTRAJ_T_SIN_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("tan", (SampledTraj (*)(const SampledTraj&)) &codac2::tan, + py::is_operator(), + SAMPLEDTRAJ_T_TAN_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("acos", (SampledTraj (*)(const SampledTraj&)) &codac2::acos, + py::is_operator(), + SAMPLEDTRAJ_T_ACOS_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("asin", (SampledTraj (*)(const SampledTraj&)) &codac2::asin, + py::is_operator(), + SAMPLEDTRAJ_T_ASIN_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + + .def("atan", (SampledTraj (*)(const SampledTraj&)) &codac2::atan, + py::is_operator(), + SAMPLEDTRAJ_T_ATAN_CONST_SAMPLEDTRAJ_T_REF, + "x1"_a) + +#if 0 + 20 + inline SampledTraj atan2(const SampledTraj& x1, const SampledTraj& x2) + inline SampledTraj atan2(const SampledTraj& x1, const T& x2) + inline SampledTraj atan2(const T& x1, const SampledTraj& x2) + inline SampledTraj cosh(const SampledTraj& x1) + inline SampledTraj sinh(const SampledTraj& x1) + inline SampledTraj tanh(const SampledTraj& x1) + inline SampledTraj acosh(const SampledTraj& x1) + inline SampledTraj asinh(const SampledTraj& x1) + inline SampledTraj atanh(const SampledTraj& x1) + inline SampledTraj abs(const SampledTraj& x1) + inline SampledTraj min(const SampledTraj& x1, const SampledTraj& x2) + inline SampledTraj min(const SampledTraj& x1, const T& x2) + inline SampledTraj min(const T& x1, const SampledTraj& x2) + inline SampledTraj max(const SampledTraj& x1, const SampledTraj& x2) + inline SampledTraj max(const SampledTraj& x1, const T& x2) + inline SampledTraj max(const T& x1, const SampledTraj& x2) + inline SampledTraj sign(const SampledTraj& x1) + inline SampledTraj integer(const SampledTraj& x1) + inline SampledTraj floor(const SampledTraj& x1) + inline SampledTraj ceil(const SampledTraj& x1) + + #endif + ; + +} \ No newline at end of file diff --git a/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp b/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp deleted file mode 100644 index 26cd3da48..000000000 --- a/python/src/core/trajectory/codac2_py_SampledTrajectory.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/** - * SampledTrajectory Python binding - * ---------------------------------------------------------------------------- - * \date 2024 - * \author Simon Rohou - * \copyright Copyright 2024 Codac Team - * \license GNU Lesser General Public License (LGPL) - */ - -#include -#include -#include -#include -#include -#include -#include "codac2_py_SampledTrajectory_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): -#include "codac2_py_TrajectoryBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): -#include "codac2_py_TrajectoryBase.h" -#include "codac2_Trajectory_operator.h" -#include "codac2_py_doc.h" - -using namespace std; -using namespace codac2; -namespace py = pybind11; -using namespace pybind11::literals; - -template -void _export_SampledTrajectory(py::module& m, const string& class_name) -{ - py::class_> exported_class(m, class_name.c_str(), SAMPLEDTRAJECTORY_MAIN); - export_TrajectoryBase>(exported_class); - - exported_class - - .def(py::init<>(), - SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY) - - ; - - if constexpr(std::is_same_v) - { - exported_class - .def(py::init&,const std::list&>(), - SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY_CONST_LIST_DOUBLE_REF_CONST_LIST_T_REF, - "l_t"_a, "l_x"_a) - ; - } - - else if constexpr(std::is_same_v) - { - exported_class - .def(py::init( - [](const py::array_t& l_t, const py::array_t& l_x) - { - if constexpr(std::is_same_v) - { - assert_release(l_t.size() > 0 && l_x.size() > 0); - - list l_vx; - - py::buffer_info info = l_x.request(); - auto ptr = static_cast(info.ptr); - - size_t nb_values = 1; - for(const auto& r : info.shape) - nb_values *= r; - - assert(nb_values % l_t.size() == 0); - size_t n = nb_values / l_t.size(); - - for(size_t i = 0 ; i < nb_values ; i+=n) - { - Vector x(n); - for(size_t k = 0 ; k < n ; k++) - x[k] = *ptr++; - l_vx.push_back(x); - } - - return std::make_unique>(l_t.cast>(), l_vx); - } - - else - return std::make_unique>(); - }), - SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY_CONST_LIST_DOUBLE_REF_CONST_LIST_T_REF, - "l_t"_a, "l_x"_a) - ; - } - - exported_class - - .def(py::init&>(), - SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY_CONST_MAP_DOUBLET_REF, - "m"_a) - - .def("nb_samples", &SampledTrajectory::nb_samples, - SIZET_SAMPLEDTRAJECTORY_T_NB_SAMPLES_CONST) - - .def("sampled", [](const SampledTrajectory& x, double dt, bool keep_original_values) - { - return x.sampled(dt,keep_original_values); - }, - SAMPLEDTRAJECTORY_T_SAMPLEDTRAJECTORY_T_SAMPLED_DOUBLE_BOOL_CONST, - "dt"_a, "keep_original_values"_a) - - .def("__getitem__", [](const SampledTrajectory& x, Index_type index) -> const T& - { - matlab::test_integer(index); - return x.at(matlab::input_index(index)); - }, py::return_value_policy::reference_internal) - - .def("__setitem__", [](SampledTrajectory& x, Index_type index, const T& a) - { - matlab::test_integer(index); - x[matlab::input_index(index)] = a; - }) - - .def("__repr__", [](const SampledTrajectory& x) { - std::ostringstream stream; - stream << x; - return string(stream.str()); - }, - OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_SAMPLEDTRAJECTORY_T_REF) - ; -} - -void export_SampledTrajectory(py::module& m) -{ - _export_SampledTrajectory(m, "SampledTrajectory_double"); - _export_SampledTrajectory(m, "SampledTrajectory_Vector"); -} \ No newline at end of file diff --git a/python/src/core/trajectory/codac2_py_TrajectoryBase.h b/python/src/core/trajectory/codac2_py_TrajBase.h similarity index 68% rename from python/src/core/trajectory/codac2_py_TrajectoryBase.h rename to python/src/core/trajectory/codac2_py_TrajBase.h index 442f51ac5..fa53eb640 100644 --- a/python/src/core/trajectory/codac2_py_TrajectoryBase.h +++ b/python/src/core/trajectory/codac2_py_TrajBase.h @@ -1,5 +1,5 @@ /** - * TrajectoryBase Python binding + * TrajBase Python binding * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou @@ -22,7 +22,7 @@ namespace py = pybind11; using namespace pybind11::literals; template -void export_TrajectoryBase(py::class_& pyclass) +void export_TrajBase(py::class_& pyclass) { pyclass @@ -30,72 +30,72 @@ void export_TrajectoryBase(py::class_& pyclass) { return x.size(); }, - VIRTUAL_INDEX_TRAJECTORYBASE_T_SIZE_CONST) + VIRTUAL_INDEX_TRAJBASE_T_SIZE_CONST) .def("is_empty", [](const S& x) { return x.is_empty(); }, - VIRTUAL_BOOL_TRAJECTORYBASE_T_IS_EMPTY_CONST) + VIRTUAL_BOOL_TRAJBASE_T_IS_EMPTY_CONST) .def("tdomain", [](const S& x) { return x.tdomain(); }, - VIRTUAL_INTERVAL_TRAJECTORYBASE_T_TDOMAIN_CONST) + VIRTUAL_INTERVAL_TRAJBASE_T_TDOMAIN_CONST) .def("truncate_tdomain", [](S& x, const Interval& new_tdomain) { x.truncate_tdomain(new_tdomain); }, - VIRTUAL_VOID_TRAJECTORYBASE_T_TRUNCATE_TDOMAIN_CONST_INTERVAL_REF, + VIRTUAL_VOID_TRAJBASE_T_TRUNCATE_TDOMAIN_CONST_INTERVAL_REF, "new_tdomain"_a) .def("codomain", [](const S& x) { return x.codomain(); }, - VIRTUAL_WRAPPER_T_DOMAIN_TRAJECTORYBASE_T_CODOMAIN_CONST) + VIRTUAL_WRAPPER_T_DOMAIN_TRAJBASE_T_CODOMAIN_CONST) .def("__call__", [](const S& x, double t) { return x(t); }, - VIRTUAL_T_TRAJECTORYBASE_T_OPERATORCALL_DOUBLE_CONST, + VIRTUAL_T_TRAJBASE_T_OPERATORCALL_DOUBLE_CONST, "t"_a) .def("__call__", [](const S& x, const Interval& t) { return x(t); }, - VIRTUAL_WRAPPER_T_DOMAIN_TRAJECTORYBASE_T_OPERATORCALL_CONST_INTERVAL_REF_CONST, + VIRTUAL_WRAPPER_T_DOMAIN_TRAJBASE_T_OPERATORCALL_CONST_INTERVAL_REF_CONST, "t"_a) .def("nan_value", [](const S& x) { return x.nan_value(); }, - AUTO_TRAJECTORYBASE_T_NAN_VALUE_CONST) + AUTO_TRAJBASE_T_NAN_VALUE_CONST) .def("sampled", [](const S& x, double dt) { return x.sampled(dt); }, - VIRTUAL_SAMPLEDTRAJECTORY_T_TRAJECTORYBASE_T_SAMPLED_DOUBLE_CONST, + VIRTUAL_SAMPLEDTRAJ_T_TRAJBASE_T_SAMPLED_DOUBLE_CONST, "dt"_a) .def("primitive", [](const S& x, const typename S::TrajType::Scalar& y0, double dt) { return x.primitive(y0,dt); }, - SAMPLEDTRAJECTORY_T_TRAJECTORYBASE_T_PRIMITIVE_CONST_T_REF_DOUBLE_CONST, + SAMPLEDTRAJ_T_TRAJBASE_T_PRIMITIVE_CONST_T_REF_DOUBLE_CONST, "y0"_a, "dt"_a) .def("as_function", [](const S& x) { return x.as_function(); }, - ANALYTICFUNCTION_TYPENAME_VALUETYPE_T_TYPE_TRAJECTORYBASE_T_AS_FUNCTION_CONST) + ANALYTICFUNCTION_TYPENAME_VALUETYPE_T_TYPE_TRAJBASE_T_AS_FUNCTION_CONST) ; } \ No newline at end of file diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index b08cd58b6..08dd3a6e3 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -135,28 +135,20 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_DRAW_ELLIPSE_CONST_VECTOR_REF_CONST_VECTOR_REF_DOUBLE_CONST_STYLEPROPERTIES_REF, "c"_a, "ab"_a, "theta"_a, "s"_a=StyleProperties()) - .def("draw_trajectory", [](Figure2D& fig, const py::object& x, const StyleProperties& s) - { - if(is_instance>(x)) - return fig.draw_trajectory(cast>(x),s); - else if(is_instance>(x)) - return fig.draw_trajectory(cast>(x),s); - else - assert_release(false && "invalid provided trajectory"); - }, - VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, + .def("draw_trajectory", (void(Figure2D::*)(const AnalyticTraj&,const StyleProperties&))&Figure2D::draw_trajectory, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) - .def("draw_trajectory", [](Figure2D& fig, const py::object& x, const ColorMap& cmap) - { - if(is_instance>(x)) - return fig.draw_trajectory(cast>(x),cmap); - else if(is_instance>(x)) - return fig.draw_trajectory(cast>(x),cmap); - else - assert_release(false && "invalid provided trajectory"); - }, - VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, + .def("draw_trajectory", (void(Figure2D::*)(const SampledTraj&,const StyleProperties&))&Figure2D::draw_trajectory, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_STYLEPROPERTIES_REF, + "x"_a, "s"_a=StyleProperties()) + + .def("draw_trajectory", (void(Figure2D::*)(const AnalyticTraj&,const ColorMap&))&Figure2D::draw_trajectory, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF, + "x"_a, "cmap"_a) + + .def("draw_trajectory", (void(Figure2D::*)(const SampledTraj&,const ColorMap&))&Figure2D::draw_trajectory, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_COLORMAP_REF, "x"_a, "cmap"_a) // Robots @@ -237,29 +229,21 @@ void export_Figure2D(py::module& m) .def_static("draw_pie", &DefaultView::draw_pie, STATIC_VOID_DEFAULTVIEW_DRAW_PIE_CONST_VECTOR_REF_CONST_INTERVAL_REF_CONST_INTERVAL_REF_CONST_STYLEPROPERTIES_REF, "c"_a, "r"_a, "theta"_a, "s"_a=StyleProperties()) - - .def_static("draw_trajectory", [](const py::object& x, const StyleProperties& s) - { - if(is_instance>(x)) - return DefaultView::draw_trajectory(cast>(x),s); - else if(is_instance>(x)) - return DefaultView::draw_trajectory(cast>(x),s); - else - assert_release(false && "invalid provided trajectory"); - }, - VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, + + .def_static("draw_trajectory", (void(*)(const AnalyticTraj&,const StyleProperties&))&DefaultView::draw_trajectory, + STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) - .def_static("draw_trajectory", [](py::object x, const ColorMap& cmap) - { - if(is_instance>(x)) - return DefaultView::draw_trajectory(cast>(x),cmap); - else if(is_instance>(x)) - return DefaultView::draw_trajectory(cast>(x),cmap); - else - assert_release(false && "invalid provided trajectory"); - }, - VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJECTORY_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, + .def_static("draw_trajectory", (void(*)(const SampledTraj&,const StyleProperties&))&DefaultView::draw_trajectory, + STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_STYLEPROPERTIES_REF, + "x"_a, "s"_a=StyleProperties()) + + .def_static("draw_trajectory", (void(*)(const AnalyticTraj&,const ColorMap&))&DefaultView::draw_trajectory, + STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF, + "x"_a, "cmap"_a) + + .def_static("draw_trajectory", (void(*)(const SampledTraj&,const ColorMap&))&DefaultView::draw_trajectory, + STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_COLORMAP_REF, "x"_a, "cmap"_a) // Robots diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 96a2e9ee3..33e45b776 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -161,10 +161,11 @@ ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_object_file_format.h ${CMAKE_CURRENT_SOURCE_DIR}/tools/codac2_template_tools.h - ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_AnalyticTrajectory.h - ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_SampledTrajectory.h - ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_Trajectory_operator.h - ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_TrajectoryBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_AnalyticTraj.h + ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_SampledTraj.h + ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_SampledTraj_operations.h + ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_Traj_operator.h + ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_TrajBase.h ) ################################################################################ diff --git a/src/core/tools/codac2_math.h b/src/core/tools/codac2_math.h index 4ee59b7a4..9ecb9750b 100644 --- a/src/core/tools/codac2_math.h +++ b/src/core/tools/codac2_math.h @@ -10,8 +10,29 @@ #pragma once #include +#include namespace codac2 { constexpr double PI = std::numbers::pi; // Need C++20 + + inline int sign(double x) + { + return (x > 0) ? 1 : ((x < 0) ? -1 : 0); + } + + inline int integer(double x) + { + return (int)x; + } + + inline double pow(double v, double p) + { + return v < 0 ? -std::pow(-v,p) : std::pow(v,p); + } + + inline double root(double v, double p) + { + return pow(v, 1./p); + } } \ No newline at end of file diff --git a/src/core/tools/codac2_template_tools.h b/src/core/tools/codac2_template_tools.h index 0e1cd4cf7..5c6497588 100644 --- a/src/core/tools/codac2_template_tools.h +++ b/src/core/tools/codac2_template_tools.h @@ -12,6 +12,8 @@ #include #include "codac2_Sep.h" #include "codac2_Ctc.h" +#include "codac2_Matrix.h" +#include "codac2_Vector.h" namespace codac2 { @@ -26,6 +28,11 @@ namespace codac2 concept IsSepBaseOrPtr = (std::is_base_of_v || std::is_base_of_v>); + template + concept IsRealType = (std::is_same_v + || std::is_same_v + || std::is_same_v); + inline Index size_of([[maybe_unused]] int x) { return 1; diff --git a/src/core/trajectory/codac2_AnalyticTrajectory.h b/src/core/trajectory/codac2_AnalyticTraj.h similarity index 82% rename from src/core/trajectory/codac2_AnalyticTrajectory.h rename to src/core/trajectory/codac2_AnalyticTraj.h index b0b8f5ad8..8d0716c23 100644 --- a/src/core/trajectory/codac2_AnalyticTrajectory.h +++ b/src/core/trajectory/codac2_AnalyticTraj.h @@ -1,5 +1,5 @@ /** - * \file codac2_AnalyticTrajectory.h + * \file codac2_AnalyticTraj.h * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou @@ -10,18 +10,18 @@ #pragma once #include "codac2_AnalyticFunction.h" -#include "codac2_TrajectoryBase.h" -#include "codac2_SampledTrajectory.h" +#include "codac2_TrajBase.h" +#include "codac2_SampledTraj.h" namespace codac2 { template - class AnalyticTrajectory : public TrajectoryBase, public AnalyticFunction + class AnalyticTraj : public TrajBase, public AnalyticFunction { public: - AnalyticTrajectory(const AnalyticFunction& f, const Interval& tdomain) - : TrajectoryBase(), AnalyticFunction(f), _tdomain(tdomain) + AnalyticTraj(const AnalyticFunction& f, const Interval& tdomain) + : TrajBase(), AnalyticFunction(f), _tdomain(tdomain) { assert_release(f.args().total_size() == 1 && "domain of f must be 1d"); } diff --git a/src/core/trajectory/codac2_SampledTrajectory.h b/src/core/trajectory/codac2_SampledTraj.h similarity index 85% rename from src/core/trajectory/codac2_SampledTrajectory.h rename to src/core/trajectory/codac2_SampledTraj.h index 1c6f165ff..50f9aa6f8 100644 --- a/src/core/trajectory/codac2_SampledTrajectory.h +++ b/src/core/trajectory/codac2_SampledTraj.h @@ -1,5 +1,5 @@ /** - * \file codac2_SampledTrajectory.h + * \file codac2_SampledTraj.h * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou @@ -10,22 +10,22 @@ #pragma once #include -#include "codac2_TrajectoryBase.h" +#include "codac2_TrajBase.h" #include "codac2_analytic_variables.h" namespace codac2 { template - class SampledTrajectory : public TrajectoryBase, public std::map + class SampledTraj : public TrajBase, public std::map { public: - SampledTrajectory() - : TrajectoryBase(), std::map() + SampledTraj() + : TrajBase(), std::map() { } - SampledTrajectory(const std::list& l_t, const std::list& l_x) - : SampledTrajectory() + SampledTraj(const std::list& l_t, const std::list& l_x) + : SampledTraj() { assert_release(l_t.size() == l_x.size()); auto it_t = l_t.begin(); auto it_x = l_x.begin(); @@ -36,8 +36,8 @@ namespace codac2 } } - SampledTrajectory(const std::map& m) - : TrajectoryBase(), std::map(m) + SampledTraj(const std::map& m) + : TrajBase(), std::map(m) { } // size is not the std::map::size() ! @@ -138,17 +138,17 @@ namespace codac2 } } - virtual SampledTrajectory sampled(double dt) const + virtual SampledTraj sampled(double dt) const { return sampled(dt, true); } - SampledTrajectory sampled(double dt, bool keep_original_values) const + SampledTraj sampled(double dt, bool keep_original_values) const { assert(dt > 0.); assert(!is_empty()); - auto straj = TrajectoryBase::sampled(dt); + auto straj = TrajBase::sampled(dt); if(keep_original_values) { @@ -162,7 +162,7 @@ namespace codac2 }; template - inline std::ostream& operator<<(std::ostream& os, const SampledTrajectory& x) + inline std::ostream& operator<<(std::ostream& os, const SampledTraj& x) { os << "SampledTraj. " << x.tdomain() << "↦" << x.codomain() << ", " << x.nb_samples() << " pts"; return os; diff --git a/src/core/trajectory/codac2_TrajectoryBase.h b/src/core/trajectory/codac2_TrajBase.h similarity index 87% rename from src/core/trajectory/codac2_TrajectoryBase.h rename to src/core/trajectory/codac2_TrajBase.h index 7626d037a..11eec6186 100644 --- a/src/core/trajectory/codac2_TrajectoryBase.h +++ b/src/core/trajectory/codac2_TrajBase.h @@ -1,5 +1,5 @@ /** - * \file codac2_TrajectoryBase.h + * \file codac2_TrajBase.h * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou @@ -17,16 +17,16 @@ namespace codac2 { template - class SampledTrajectory; + class SampledTraj; template - class TrajectoryBase + class TrajBase { public: using TrajType = ValueType::Type; - TrajectoryBase() + TrajBase() { } virtual Index size() const = 0; @@ -47,25 +47,25 @@ namespace codac2 .init(std::numeric_limits::quiet_NaN()); } - virtual SampledTrajectory sampled(double dt) const + virtual SampledTraj sampled(double dt) const { assert_release(dt > 0.); assert_release(!is_empty()); auto tdom = tdomain(); - SampledTrajectory straj; + SampledTraj straj; for(double t = tdom.lb() ; t < tdom.ub() ; t+=dt) straj[t] = (*this)(t); straj[tdom.ub()] = (*this)(tdom.ub()); return straj; } - SampledTrajectory primitive(const T& y0, double dt) const + SampledTraj primitive(const T& y0, double dt) const { assert_release(dt > 0.); assert_release(!is_empty()); - SampledTrajectory p; + SampledTraj p; double t = tdomain().lb(), last_t = t; p[t] = y0; t += dt; T y = y0; diff --git a/src/core/trajectory/codac2_Trajectory_operator.h b/src/core/trajectory/codac2_Traj_operator.h similarity index 83% rename from src/core/trajectory/codac2_Trajectory_operator.h rename to src/core/trajectory/codac2_Traj_operator.h index 47d1d428c..310d94696 100644 --- a/src/core/trajectory/codac2_Trajectory_operator.h +++ b/src/core/trajectory/codac2_Traj_operator.h @@ -1,5 +1,5 @@ /** - * \file codac2_Trajectory_operator.h + * \file codac2_Traj_operator.h * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou @@ -10,7 +10,7 @@ #pragma once #include "codac2_analytic_operations.h" -#include "codac2_SampledTrajectory.h" +#include "codac2_SampledTraj.h" #include "codac2_AnalyticExprWrapper.h" #include "codac2_ValueType.h" #include "codac2_Wrapper.h" @@ -21,12 +21,12 @@ namespace codac2 requires (std::is_same_v::Type,ScalarType> || std::is_same_v::Type,VectorType>) struct TrajectoryOp { - static typename Wrapper::Domain fwd(const TrajectoryBase& x1, const Interval& x2) + static typename Wrapper::Domain fwd(const TrajBase& x1, const Interval& x2) { return x1(x2); } - static typename ValueType::Type fwd(const TrajectoryBase& x1, const ScalarType& x2) + static typename ValueType::Type fwd(const TrajBase& x1, const ScalarType& x2) { IntervalMatrix d(x1.size(),x2.da.cols()); @@ -39,7 +39,7 @@ namespace codac2 } static void bwd( - [[maybe_unused]] const TrajectoryBase& x1, + [[maybe_unused]] const TrajBase& x1, [[maybe_unused]] const typename Wrapper::Domain& y, [[maybe_unused]] Interval& x2) { @@ -55,7 +55,7 @@ namespace codac2 using O = typename ValueType::Type; - AnalyticOperationExpr(const TrajectoryBase& x1, const ScalarExpr& x2) + AnalyticOperationExpr(const TrajBase& x1, const ScalarExpr& x2) : OperationExprBase>(x2), _x1(x1) { } @@ -88,11 +88,11 @@ namespace codac2 protected: - const TrajectoryBase& _x1; + const TrajBase& _x1; }; template - AnalyticFunction::Type> TrajectoryBase::as_function() const + AnalyticFunction::Type> TrajBase::as_function() const { using D = typename ValueType::Type; diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index 6cca590ee..7b47ae7c0 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -211,7 +211,7 @@ void Figure2D::draw_ellipse(const Vector& c, const Vector& ab, double theta, con output_fig->draw_ellipse(c,ab,theta,s); } -void Figure2D::draw_trajectory(const SampledTrajectory& x, const StyleProperties& s) +void Figure2D::draw_trajectory(const SampledTraj& x, const StyleProperties& s) { assert_release(this->size() <= x.size()); std::vector values(x.nb_samples()); @@ -221,12 +221,12 @@ void Figure2D::draw_trajectory(const SampledTrajectory& x, const StylePr draw_polyline(values,s); } -void Figure2D::draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s) +void Figure2D::draw_trajectory(const AnalyticTraj& x, const StyleProperties& s) { draw_trajectory(x.sampled(x.tdomain().diam()/1e4), s); } -void Figure2D::draw_trajectory(const SampledTrajectory& x, const ColorMap& cmap) +void Figure2D::draw_trajectory(const SampledTraj& x, const ColorMap& cmap) { assert_release(this->size() <= x.size()); @@ -240,7 +240,7 @@ void Figure2D::draw_trajectory(const SampledTrajectory& x, const ColorMa } } -void Figure2D::draw_trajectory(const AnalyticTrajectory& x, const ColorMap& cmap) +void Figure2D::draw_trajectory(const AnalyticTraj& x, const ColorMap& cmap) { draw_trajectory(x.sampled(x.tdomain().diam()/1e4), cmap); } diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index bf5b1c0a3..58b5cb400 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -93,10 +93,10 @@ namespace codac2 void draw_polygone(const std::vector& x, const StyleProperties& s = StyleProperties()); void draw_pie(const Vector& c, const Interval& r, const Interval& theta, const StyleProperties& s = StyleProperties()); void draw_ellipse(const Vector& c, const Vector& ab, double theta, const StyleProperties& s = StyleProperties()); - void draw_trajectory(const SampledTrajectory& x, const StyleProperties& s = StyleProperties()); - void draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s = StyleProperties()); - void draw_trajectory(const SampledTrajectory& x, const ColorMap& cmap); - void draw_trajectory(const AnalyticTrajectory& x, const ColorMap& cmap); + void draw_trajectory(const SampledTraj& x, const StyleProperties& s = StyleProperties()); + void draw_trajectory(const AnalyticTraj& x, const StyleProperties& s = StyleProperties()); + void draw_trajectory(const SampledTraj& x, const ColorMap& cmap); + void draw_trajectory(const AnalyticTraj& x, const ColorMap& cmap); // Robots void draw_tank(const Vector& x, float size, const StyleProperties& s = StyleProperties()); @@ -224,25 +224,25 @@ namespace codac2 selected_fig()->draw_ellipse(c,ab,theta,s); } - static void draw_trajectory(const SampledTrajectory& x, const StyleProperties& s = StyleProperties()) + static void draw_trajectory(const SampledTraj& x, const StyleProperties& s = StyleProperties()) { auto_init(); selected_fig()->draw_trajectory(x,s); } - static void draw_trajectory(const AnalyticTrajectory& x, const StyleProperties& s = StyleProperties()) + static void draw_trajectory(const AnalyticTraj& x, const StyleProperties& s = StyleProperties()) { auto_init(); selected_fig()->draw_trajectory(x,s); } - static void draw_trajectory(const SampledTrajectory& x, const ColorMap& cmap) + static void draw_trajectory(const SampledTraj& x, const ColorMap& cmap) { auto_init(); selected_fig()->draw_trajectory(x,cmap); } - static void draw_trajectory(const AnalyticTrajectory& x, const ColorMap& cmap) + static void draw_trajectory(const AnalyticTraj& x, const ColorMap& cmap) { auto_init(); selected_fig()->draw_trajectory(x,cmap); diff --git a/src/graphics/figures/codac2_Figure2DInterface.h b/src/graphics/figures/codac2_Figure2DInterface.h index 31b0552aa..b3e63b37a 100644 --- a/src/graphics/figures/codac2_Figure2DInterface.h +++ b/src/graphics/figures/codac2_Figure2DInterface.h @@ -14,8 +14,8 @@ #include "codac2_Vector.h" #include "codac2_IntervalVector.h" #include "codac2_StyleProperties.h" -#include "codac2_SampledTrajectory.h" -#include "codac2_AnalyticTrajectory.h" +#include "codac2_SampledTraj.h" +#include "codac2_AnalyticTraj.h" namespace codac2 { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f0d4ca91f..280f8e353 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -78,8 +78,8 @@ list(APPEND SRC_TESTS # listing files without extension core/tools/codac2_tests_Approx - core/trajectory/codac2_tests_AnalyticTrajectory - core/trajectory/codac2_tests_SampledTrajectory + core/trajectory/codac2_tests_AnalyticTraj + core/trajectory/codac2_tests_SampledTraj graphics/styles/codac2_tests_Color ) diff --git a/tests/core/trajectory/codac2_tests_AnalyticTrajectory.cpp b/tests/core/trajectory/codac2_tests_AnalyticTraj.cpp similarity index 94% rename from tests/core/trajectory/codac2_tests_AnalyticTrajectory.cpp rename to tests/core/trajectory/codac2_tests_AnalyticTraj.cpp index 2853c2abc..7fa5a4e9d 100644 --- a/tests/core/trajectory/codac2_tests_AnalyticTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_AnalyticTraj.cpp @@ -8,7 +8,7 @@ */ #include -#include +#include #include using namespace std; @@ -19,7 +19,7 @@ double prim_value(double x) return 1.+(1./3.)*std::pow(x,3); } -TEST_CASE("AnalyticTrajectory") +TEST_CASE("AnalyticTraj") { ScalarVar t; AnalyticFunction f { @@ -27,7 +27,7 @@ TEST_CASE("AnalyticTrajectory") sqr(t) }; - AnalyticTrajectory traj(f, {-1,10}); + AnalyticTraj traj(f, {-1,10}); CHECK(traj.tdomain() == Interval(-1,10)); CHECK(traj.codomain() == Interval(0,100)); diff --git a/tests/core/trajectory/codac2_tests_AnalyticTrajectory.py b/tests/core/trajectory/codac2_tests_AnalyticTraj.py similarity index 94% rename from tests/core/trajectory/codac2_tests_AnalyticTrajectory.py rename to tests/core/trajectory/codac2_tests_AnalyticTraj.py index 2e1583a71..1dda2ae1c 100644 --- a/tests/core/trajectory/codac2_tests_AnalyticTrajectory.py +++ b/tests/core/trajectory/codac2_tests_AnalyticTraj.py @@ -15,9 +15,9 @@ def prim_value(x): return 1.+(1./3.)*math.pow(x,3) -class TestAnalyticTrajectory(unittest.TestCase): +class TestAnalyticTraj(unittest.TestCase): - def tests_AnalyticTrajectory(self): + def tests_AnalyticTraj(self): t = ScalarVar() f = AnalyticFunction( @@ -25,7 +25,7 @@ def tests_AnalyticTrajectory(self): sqr(t) ) - traj = AnalyticTrajectory(f, [-1,10]) + traj = AnalyticTraj(f, [-1,10]) self.assertTrue(traj.tdomain() == Interval(-1,10)) self.assertTrue(traj.codomain() == Interval(0,100)) diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp b/tests/core/trajectory/codac2_tests_SampledTraj.cpp similarity index 82% rename from tests/core/trajectory/codac2_tests_SampledTrajectory.cpp rename to tests/core/trajectory/codac2_tests_SampledTraj.cpp index 06207d17e..e1170ae13 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.cpp +++ b/tests/core/trajectory/codac2_tests_SampledTraj.cpp @@ -8,8 +8,9 @@ */ #include -#include -#include +#include +#include +#include #include #include #include @@ -17,9 +18,9 @@ using namespace std; using namespace codac2; -TEST_CASE("SampledTrajectory") +TEST_CASE("SampledTraj") { - SampledTrajectory x({ + SampledTraj x({ { 0.25, {-0.5,0.5} }, { 1., {0,0} }, { 2., {1,0} }, @@ -63,11 +64,11 @@ TEST_CASE("SampledTrajectory") //DefaultView::draw_trajectory(x_sampled, Color::red()); } -TEST_CASE("SampledTrajectory as operator (1d case)") +TEST_CASE("SampledTraj as operator (1d case)") { ScalarVar t; AnalyticFunction f { {t}, cos(t) }; - AnalyticTrajectory analytic_traj(f, {-PI,PI}); + AnalyticTraj analytic_traj(f, {-PI,PI}); auto sampled_traj = analytic_traj.sampled(1e-2); auto g = sampled_traj.as_function(); @@ -77,7 +78,7 @@ TEST_CASE("SampledTrajectory as operator (1d case)") CHECK(Approx(h.real_eval(t),1e-8) == cos(t)); } -TEST_CASE("SampledTrajectory as operator (nd case)") +TEST_CASE("SampledTraj as operator (nd case)") { ScalarVar t; AnalyticFunction f { @@ -85,7 +86,7 @@ TEST_CASE("SampledTrajectory as operator (nd case)") vec(2*cos(t),sin(2*t)) }; - auto analytic_traj = AnalyticTrajectory(f, {0,5}); + auto analytic_traj = AnalyticTraj(f, {0,5}); auto sampled_traj = analytic_traj.sampled(1e-2); auto g = sampled_traj.as_function(); @@ -107,4 +108,13 @@ TEST_CASE("SampledTrajectory as operator (nd case)") for(double t = 0 ; t < 5 ; t+=1e-2) CHECK(Approx(h.real_eval(t),1e-8) == Vector({2*cos(t),sin(2*t)})); } +} + +TEST_CASE("SampledTraj: operations") +{ + ScalarVar t; + AnalyticFunction h { {t}, t }; + auto analytic_traj = AnalyticTraj(h, {-PI,PI}); + SampledTraj x = analytic_traj.sampled(1e-2); + CHECK(Approx(cos(x).codomain(),1e-5) == Interval(-1,1)); } \ No newline at end of file diff --git a/tests/core/trajectory/codac2_tests_SampledTrajectory.py b/tests/core/trajectory/codac2_tests_SampledTraj.py similarity index 90% rename from tests/core/trajectory/codac2_tests_SampledTrajectory.py rename to tests/core/trajectory/codac2_tests_SampledTraj.py index b1d3128a2..6754c7924 100644 --- a/tests/core/trajectory/codac2_tests_SampledTrajectory.py +++ b/tests/core/trajectory/codac2_tests_SampledTraj.py @@ -11,11 +11,11 @@ from codac import * import sys, math -class TestSampledTrajectory(unittest.TestCase): +class TestSampledTraj(unittest.TestCase): - def tests_SampledTrajectory(self): + def tests_SampledTraj(self): - x = SampledTrajectory({ + x = SampledVectorTraj({ 0.25: [-0.5,0.5], 1.: [0,0], 2.: [1,0], @@ -58,13 +58,13 @@ def tests_SampledTrajectory(self): #DefaultView.draw_trajectory(x, Color.blue()) #DefaultView.draw_trajectory(x_sampled, Color.red()) - # SampledTrajectory as operator (1d case) + # SampledTraj as operator (1d case) t = ScalarVar() f = AnalyticFunction( [t], cos(t) ) - analytic_traj = AnalyticTrajectory(f, [-math.pi,math.pi]) + analytic_traj = AnalyticTraj(f, [-math.pi,math.pi]) sampled_traj = analytic_traj.sampled(1e-2) g = sampled_traj.as_function() @@ -77,7 +77,7 @@ def tests_SampledTrajectory(self): self.assertTrue(Approx(h.real_eval(t_),1e-8) == math.cos(t_)) t_=t_+1e-2 - # SampledTrajectory as operator (nd case) + # SampledTraj as operator (nd case) t = ScalarVar() f = AnalyticFunction( @@ -85,7 +85,7 @@ def tests_SampledTrajectory(self): vec(2*cos(t),sin(2*t)) ) - analytic_traj = AnalyticTrajectory(f, [0,5]) + analytic_traj = AnalyticTraj(f, [0,5]) sampled_traj = analytic_traj.sampled(1e-2) g = sampled_traj.as_function() From 3d5bfa822f9cdfd24f8be8fe1d84e401e7b6acb5 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 15 Jan 2025 16:26:49 +0100 Subject: [PATCH 083/126] [doc] empty ellipsoids pages (for Morgan) --- doc/manual/ellipsoids/Ellipsoid_class.rst | 17 ++++++++++ doc/manual/ellipsoids/ellipsoid_def.png | Bin 0 -> 91997 bytes doc/manual/ellipsoids/index.rst | 11 +++++++ doc/manual/ellipsoids/what_is_ellipsoid.rst | 34 ++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 doc/manual/ellipsoids/Ellipsoid_class.rst create mode 100644 doc/manual/ellipsoids/ellipsoid_def.png create mode 100644 doc/manual/ellipsoids/index.rst create mode 100644 doc/manual/ellipsoids/what_is_ellipsoid.rst diff --git a/doc/manual/ellipsoids/Ellipsoid_class.rst b/doc/manual/ellipsoids/Ellipsoid_class.rst new file mode 100644 index 000000000..614374c0a --- /dev/null +++ b/doc/manual/ellipsoids/Ellipsoid_class.rst @@ -0,0 +1,17 @@ +.. _sec-ellipsoids-class: + +The Ellipsoid class +=================== + +*Main author:* `Morgan Louédec `_ + + +.. tabs:: + + .. code-tab:: py + + # Python code + + .. code-tab:: c++ + + // C++ code diff --git a/doc/manual/ellipsoids/ellipsoid_def.png b/doc/manual/ellipsoids/ellipsoid_def.png new file mode 100644 index 0000000000000000000000000000000000000000..52eae6bc54130921a779359705470bf08e57b264 GIT binary patch literal 91997 zcmeEucRZH=_y65eiKL7ul!VOe5Gt}qw(PRE>`f`5>^&mcTiJw=y|PCk+ima7{X3WH z^ZkB*fBpXZ{qwyakM}#}zOVaryTR#$0I0rA6bGqK}cM_Y&DmL;K`Zo5@tn^R@<`!mpjMh3gkjO?Qwt30mnrvoW$TzoB4criU`qvtqiz!g0g+nYkU)4c5D?95+}vd06i9 zaB#`luU|%?ZlJ`39x6D*E(|-W^h}LoF#V`k-uq1BIVB&bqf1SEUqu>CRVvCws~QWm zaH=tM^!HfzgvhCu-bgo$6gM(2oveKB9UYxK?!}v#wZ5MyV@-L+OE2=71Ak7-e01sP zwriD^O_}uOIN$cw_ri&?u*&1tH>P_ky#M}!YUCxr{QJuQzOVbgpBK*63HXRt*@G-$=j`8~zxh8oIQ92uZ4ug|6MuisyY;`9NBw`>9O=G`+7jdA;{;c) zrd2p^&+To_XQ&otz#pmnu6vEuWA0VA#6(4Z7{t4#Xq4ME8L~HbcgqWU;dD*}2$SM1ytzPC^qBXj4-$T zMJ~Tc<@c%ikWb#^m90`^*;;^>`XuUmZRR`;p%Eto}$7=kUmOzE4qG`y+ZUM20_| zjMpx51aq{%obfbY-%aSBCI7zpX74>FDT&JOI=5WB%UaVd33o9%&95a?usw6%UY^=p zYhmuzsIox^qYEP|o|S(4w+7vWC-JNBJ2|ng7Urthu~>TLoJh@Li&0H@p>sN7 zxMaw9Y<|FH2uVrlJgc>Xvi^NEGVzJPYL#&>UB$s#i zyt^^z7TX8wot00RAp3|>wXcPQdU|)0XreHrn>#oFWDf<$6qQs-Z59EX}KRN z-n@A;L%noOuwOYxJ^fj&*BwSiDYKtNz5ZmpljGyT!~!S(UhiYzogSG31HGB{58@IM zAsaKhN8EP~?H2|Tz^+Vcy>J5<4sRQ+{H`Wt(|=E8ggH8l<}gue7yO4b*c`qX$%Uc9 zmW?v&nRf0Woxv}9zVF`2!yCI@Wmg0$wuVen`Y#YO5m0>pcMFrJ>)fgBmVOyI4JS)P zTwi=~bl`ZKn%cO*pG>vL^r_eSTz_t^T(Y=WFc=ykAz@hJ{y#9o=JLhh{3^4RKrE38 zx%X_4r@@+9(%E{tkJ(yB3jTu?!QH*R=^b7a6Baldj|RAv`?Ae$-X@1CK4MA9(q4(7x$F-a|0By@mV^ zt607HzU*jDv*_z&WQB&El(^UL-EDCGcYIH@eG$Kwiei1dzrEbw97brJqe_yJ?>WtesI;`S#N;e3R|K82R13wAj*hT#aoaYooQUFf*~#16 zUe0}9=X-~pT_I7}56s{{JDvRP`X-w}`}GgJ_R_)Zdd&oUha25i*48bZnz*FwKVmE@ z(|6ZrGUZdHdEh#L&l{WlTCj4pJwPMHEESeBXU}G8Rk>l~;Dm;Rgdm6pXlDWdS@vSW z%Wh%dCNp#Hb-jCb3z04^E()K7&YQs|fC+W{w?%xYj{IqDy;coKJc&l9&(0cl5A>wV zbC?Yks4qG%46tOYm&$?Tg=A)CeyynBaM`gWydy_7{Po9=C*b?iT;{)?_>pq-WUFy) zF8)-$c#(Vm+xO2p4U>zDj50DZ@D`?Fn*Sh8qu)u{gQ}I93#w%{MrAC@%E%FkbC~oM zh^NFNcj>e-n=n%0JfE3c8T{^@MANCoGz6s|TZ=yxbJV%%ss3{X8%~Xb zYktB~vG-(+jEn-lR_eErF8(TIa~GWYF;@Gwx7b1p0X*=P92~6LTQi6UWWav=2jKrh zCIWL#*Pf2GsTPjs-@PSg92_0*Ffd3;OBe0))wz=`%NH6eav1l_23aG~m5?ym+xr}{ zOY}-vjWePD48d7D-^|g)J@XU>3j*5XH+!o`tU+Mvj&yGa|0hGt9m&f0j1SGS$p`l^J4S1E3w) z9)!nz;JlD^3y zoAlu2%695ef3{k~mAPODG6_XyKN0GUTnm0od3oxrcrb9^WEP!z!>xruyzFwf!!j&9 z@+=^G(e*&dH`{raC)MnbOL|NpqJziDX9Ic9QuM3 zS62fiNiVaVPw~RNmJ+kQ+CV`M(QkMFPv9UhX9Lp$9Kx`(_4s-R$A^sl8r}`tsg$z) zX19bQv6I%_-F>*iSviD8MhQ|2seVXg!p+TXY&HZ%b_f_%H-h#@O07l2#Kasat|Au- z%>8q(tJ@Q9Mdrg9kOZo*_-(%S@>REOD$)FJ+W{lbGy5`3V;-FXvvqEgo54b-1Ng*U*p}^D|wZCX7*yb65p(v;rVPuB&y#=(r<$d;1Q%@OQ+_ zbex==Kj)EEqrwFd8^?Yv`1YdF?2iO=oM=be3jr>Rkse4Ndp|xr1<{h9nNojtX}H{J zxng_cV74o?aR`GvgM}4cfq(!?+wl(?1ct$zoBR8fH|Ki0C73IcBDCBF*~#(o5x&c? zJ&&fx1WQn0d6Xi0;oSYnVJH|cq#3?MpUnMW#u)|dg41>nL0wG5O9F)22egQX3 z3Jkn7496NwzPF~0EYrhw^*aJKMj`>^Va3J8;^7SGK$daIc-V(mIWv{ASxw?0W1q_| z9_a!y-&^VGEcJn>S1zc#)NV04eIw%N;Q0uUvq|F))k5QB`om;__$|y#(Bs3sO?ePX z*oNsjIhDXbLa2a}FxEN(iuJrcf2H7g9d;O#hN?t3L(?;-IuSDrG1x4K&2hpm_{_jqY(DMf&soIFFbq6`Pilf$jx ze!e@#ZFgr!G?>$L;G=jLo!DOfkE3~qC^$nC$W@;nWr_G-7u$9NSaYP~CncpldV_5YnvfS*Moh$#tFEr@mf#;uIfGyd zQD|`RCqyQA_UxIjxA$GbLuC1%K7C?vS_a!q12*ck@VTKUM}rqYO0&?Uzi5_ky{po7 ze{z04b7#lF>{p2_q^m3%*Emfh(|4*IRzJadQsF-}dgGMX*w_NADe>L?{dqWU()$j1 znhs-c?pHJf-4d~Zbk;^Ej9xjsxY$121isf zML2bZxc{>LnF%gLK{7k%iALK~K0Zt_fu~;HT)uhMo zh|(Qa$3ek}_rjyd0UT|ruI8-VGZ?LO1<_6x@P=9@E=yU{aVmiui5!q~Al@j3eeq&n zEVnhH&Wyguue+RFwJ}3XjOhlQENZF@90AlpDcEz_w-?D6@Ntoy(mqqPs6HO&fV*2*F0b4qhN+>7S2i2Ib7m>rFX zi78#9p!u=sw>DZXt#=4mIJwTWlO66%1ndU>;MAye*-iKix29WG59*r$W;cM!sOI%~ zqNd|?CGR2<0G~u;Z3v_h zYqPJ7i=GkXvsc*z7*eA<+z>#mO;p< z`Bg>BW%Y4*L;YkuEEYs5=DP3S(^Nh`M*=LeAALhN1-)hg=;VxzGsy2dd;~9@1Aiz` zQBvy#kcCv0d3Yd-&0unBYV*gh$w}SK%+$CkZ|R2H7l!X8MN z^yl;f6)CiykxouYQQdI6cu^WmDS=MOG>cWwI8!o8l}@89yg4*IIrw&FQ}xZ|qoCNx ztJyJJw`?YaOL8>%vLqt5=C&5uSV{c`N9JKWoyL7=HXz>5`*Dplt}~+`NT)h&FJ+gM z+~elq0jXLMaH?={et3Aex5C-pY~<_HU;+XH1=@EQgnm@NI)mn4y>#i)$1@j*l46MA zB*E=81r9etoVFIy-7)*4yJW|ybs!#s8gJ@>6K){V6&&^+IyIhQOYduYdmTWpykgF; z1iyc>Q`7K<|`TJ17EZxH{(t83B_%2ENT6`N0u`gPqlsargcljWWxzSH}H0 zA81G}U;{JDewr_QxWCO6h5yiaiv92*JNEjq zbDu|8Yk7ERXc9y?M5RM`x|Nkx+-PlEb}%R(Nu(S+>H2N$8BeMuusqFN{iHuXC+sOe z-{mmlk-T%~Jdd@0g+GN>)~Nfa{ua%NB8$-+P}B@T(*?m?Hizxa+qd*QdmUO2-jnev zL8SonvkIq8If$Y*pl~NACmXFzHmR1|ndPh#vIF8NJ2;f+w?!xa{;fS+@qyf^HfJm$)c}(N;*Z~wgG!X9(XL$MvKvx)2|K{!r32=zEXbn*7XcTitWT#rV z8oLh}+nSmb{jTB3P1JkZ%=Z~Bj$$a@ykV4ARqd-H*aa=H2f{cKaX`RsQ@lt)LD3e) zCL%2@4eGh6|Mm+@%O4Qt3Y|8Mk!3M4F@f~~6Dn<1zU1iOU)I6*q9X;6^KBe%k7goTcx7>7Vj>7Y zkrSKl%Ajlek+4zAY<)QkjLdefM;6q%EV5%1(LMu5?QycrkllEHYY{1K6uKQcL25AF zR9WX6raWB6pP}3#V>`d4(D_MkO;<}zF-6jhZ@rbvcyLY66>~@r1j;65T}MZ!x7^-h zap1EcqKc>fQNg}lKfXE|;w7k=3J)H5w8wIX&^U)Ppc91s_A+G?XC}uwg|R$!;uh2b zd(t|eCW=t>hBI2sHU@b}#vfra4?rbjmI*)3!n6euKReUh6hc#|U48P*nKO5Qz4q^i z(T?Q^`^AMs^rOI~3QL)%3bANtfJSm?ahTY3mf7A4i@hE{_6sUYX)^Kr2$28!^=pkq zZ|OD_RivhX!^$^bF>LCiV@=0n@e`Ca2fhMmLGmMgfr#M;luWED;$zfq%MWT*IGt@i z!eKYwhy^Iho@#NXy*Xy*wJ!aECm8}VJuNLQMYrB4z^2XanjXOBEa=RtP=-Pe&2}bo zSpI$hY+MOc=U~XHAP}0@6%@_(`UpD(uik?=W($y`zBn~I`w0s-PAOl%BUAbV`J1(?@e82G z23#aR$R)pD5;OG+@dn^2kZ$SnQ?*3FSAiq8Xx~i}4WcxLia^;sFy<$!s?l=t@>BEk z5~~+`vgf{|p%}~mYMmvE+`d{a!6r+<*!9jQ(3Z)WM9XU8w!Kn+Z8vES2 zyA=U`evFnP;FYcG4HWK%aP)h7^SOk?#1WYlbP9$^4dmAnrrWd>06Nxa6As0tq`Gpe za{4P>^KGY^6HK##!G=;&QYwJjdLj8w(P#R%4|sRmJ*SN{1P6X84uZ{ zMRPbm45R02seQdg4}gjwkmp$edCAr=oEZ|Fi>##GwF2L`J9VtYHO{(2IO16K%g?) z<`XvhUoU`KfP9^=-}+tn7C5!7r9*|8_QM<2GKZO37$e(denI=?qZIkn$~Mc9$)=D( z;O-gF`|Jf&WUy^J{=u-nPoG*U~5djwrF`Q=NpBEo02v^NY&H z#-F6)aQa}M2?%Xjf5Mr&hy+j0Y?m@={(|V3CeqI9u=0`9{1>f&K$ZH`A8D8y$qpNd zeSCaWzv%ktw?-yF_Bd^b=UFYgIlnDC->0KkZpS5dU)J2eq~scC{?=stUmvWl7F!jF zR5-a=*;_D*0YCm)X1nh`l=n=*Yu%tN`Z1Dm0tSX5nLGm>NHFxvFVMCjn@}t zle}Y83$7;9#6>1`C7Vo}J>a#Qs6S7}fBoYXnv-F{Yd4ggZ5MXz%C_60{d%fB*KH>1 znFC_0O!}F~_+3=Mf7^RqkD11UEm`CnC_xfH(yE2Qd|RleTwffURuVHC`U)nkId+eN zjl|Dr?{GWbX65%+(+{KZQ9QOzP%+;^*W+M`*e>pUR?2qbskPN|+r9nA7s;;KqNrA^-R>-yY6RRw%u)*5c5iJ6L5&Y^?9}i%0ug`^!H8e2abkDsDDClrzrR zUg$wri1_#CVnPvjfZ{OUniJ?Vkfz+?;wn}*IJO|vbRq!Kqz?cR5{Z#wm4CoSx>9z< zP+?5g-sXOzwq@hQ>ou2?^Q_N>L`V5c8)hDZKenTqpb5b|z%W@7QJ zey4ilRk_ia+1c3%$KVOtN^GL@v2%IECMcdjO^Sp2D`lwwK9d@4%yx3q9nSY{cD`d? zLjIHW#B#lJxGw5*S+V!?1TU$;(R&w{>E^*wp`z{C9wXzF{%c(1v<5TdB$`^q<{CxI z=a28f>aG46RG>~mLIP-crCt}wGS+803{0}CwF6UUx@_-wrHulail;ujjR zJ)Ee2oTkn#li!cTYC!QO8~=Rk^Bl$->R$a^W5X%2|afFBmnmKPTDMm19^rXsA z96}fyRNXfi8&x|xI?Lg(f~A|?R47UtfLNpQ-@JK)ZsQv5fm}YnqEFlMNuuy!Z+drmhRSE3GhH{K!k5)uJbF>i zIKxq9)Y;*F!cbv(3`eou;*ymeQ%+LSfQaU3p-DuU-J-Fb((x_?BF#1)3>u|Yk3l|( z0~szXJUl$R5X&<$nw=!epKMfdcMX>z^iq_M_qo2I!dm#XDJi{jyS$j#XJ4Pvy+)2{ z{zYanY3av`6;2`_1gg+M{q~DPVHMwwuYW@siH{^u0`ET9UFUG!vw;Al>+HHXG~Aom zV5*q05qYMo`uf<|sNrzg3|#yOW6v*zqR5_ecA}y$K2wb^@RC)-0q5 ziYh89MSYMkW!lcanCn6Fm6nAUKH<@g=!{JH@gu?(PzGJER^T93;p`ry7p0XGo7x;< zVd%6bklGx!-nycyprDYmg*4cqj*-mc(If~n(X4vDARTpmz?ff@=@^+CwDxZf&o)W0 zX*{3EqB!3l(B*TbrOU6_c+=NuGuoo>%0b;b<)Gs2)Y79#VIZQcU+q9VP+$CGnXMv# z!fzf}S$#Qq^5h0o73q0+c+^aW!Inh=1~X(6L*8`VOqG)lA-K#clq&N!>6*o;n{SzY zd{B19eZKf++qh4UCG;E+W>7jpalF*Xw_xlGzfz=P*k6nbec*HERGSx%$Vpxr#>9X9 ziY3abLVewefrCTVqz~suZk4$xS6oP!KyFEiuKIz9h)4_cQfdEQzI}Wx20!Fl3Q*^u zmW)JlWqp$m5dXm;;^G{hKTpv*cVS*k+P^zP(baaWhO;{oV6k|cq0np}^OR9pU*;e+ zIr$DKPq!t)TO0le`~=cq0@?;ppDh3;3_7DCfY_kwJbF;A!in)ox?C?~=*7~oNC&M^ zmu`s&=4CcNP!Bd2xRoK=>DTE-39K?7I{w1@8^*$s4YZpCy#{Husi~>?QkY{kHNCcZ zn46)ztev3Scma?6m*SJaTqw00lCoXB-kaJHVcfTHhMsyqBt*VbGMDD|?J0R^YlIgx z%DAKQPC-u6eU`!nNuOysIC?>9co!}k!9+2;+R)IVZCRlGXi`aCJv5woyU*`hRU{H) zHy6u=q+%`>KmUROH9Zi$`ROqmrtbKnsK#rE)qi{A!ZLeUY+T_$^5-uQ(pUHvH8gRyMAD`^QALN=?^{KlqAD7jg6nD^lPZ^w4Xb^;&F|G z;K@u!e1FM{i2}WraMSEe)y)^Xdu}NiiWJ39SSOSBx0#IxznDWDRZAPK8D-3*T>^&0CC~fNO8P4DjFJ-`u8N!{H|q}udp$zV%poXKRIngW~WHK6=PLl zy0O-}_|t&!>VQUPXM~i_W8V^JZ`uS&B?d02sw8v3%ga0S-*=JrfpqM>1ldGkG^7vu zxhz+4jJtFr5f6u4(W2U>Q350xC2ehcP;)r^2pLsX1>c&7f~Y`G-J+szaBvL=3(f+0 zt(}LnCP1A(f8GgmxXoeE9&76AXaRymZ}~Pcry9XTXO5OY4wBIDAB7vW0*-j$?#lw= zWk)htL;NApoQVA68f%Ev43q#qG(wrD>S!->(8QPEPKw>)$dd;D<;KpS)T|4^naX(d zw2dO?&)ZAtn45>OKmV?zm^JX-x9JNJ*@snPNhp%BP=p*W?MVrcGY>ysfB!zDMaBKd z1q6VoiuUgOVsL)w#xhp9OU5uZUN@}z`BO0z^(1wY#TEO#@qa25nex$7v&l$G*4Md% zptH{Mhi@EbNCO|C`Ng<3k_GfptG*D743L(o2{vUvQa*!f-MrBC8FvNC6*h4(vAcdC ziOAm)HdT&dEzFK=b#ce=zj8HOS~ZL}}J zi+pV!mFB_xQIodlBXs5UV)fEJ$gs-ALuv25an!GKhrqV>KNjX~QFW-K)8O9=a$cLJ z{O9L7o9Okh3?(xiSXYv_w|2G$uey;@Q_5#-LQ zZv^HD2lowI*8MLwEQDn^!cCohIQN^OrS4tu;NL|WgeT|1#O9(q+Vk2$?cAM`kFc8X9u<;6l>tG)sY zJp+`}X~K`I09vzPq1>ez5)pVkIm5anIQ~SEXCu0uRTd(A*NwRy_xnsku1-QN8PZK-A@!l8aGt7*=CdM zUg1>1ZaR>1Qf*H{PNAm>Cl|@V0d(3Mkjn0Ztt7x?T3S))>qJ`Kkn)REkm7s;GaDrbKx><%wUL*zwAGd^=G@Q^rWxB2$iqd|2`SRrr*eE0D=7Tm! zHWR;h5_cS(I}}>NnZ?Fq>tC5S_-_{?(YqdERhP#J6GTExR&czPKVBskLcJS_(ALH{ z_-aF_gaRju`87NYQHIGD+PsEifybwVdS%?5;y2y?A+vbY?WedAML6si*N8*y#!>ll zWp_BET2G<~9(~G5ZL|Aue!JRGGC;~O8=y2sYwY!>cgyQE#34(1*H!hA&3JuU3@_{m zgtNYHFHJ7EpqceF51>Qm-XD*i-iK;(?^j1__+BZfr1n;Oo`r@jOc(r9q4}^XEVXqe zG%7~Gy%O^KEvhp}eu%WcTiJ4LiIeVnze6n*6PeM^VW}M@L6ln+c8qrMkzE4+KN04g?&K zQfUx9hnzeL!xj1N-8(?6V43szc2K4gaZ9iOIfIBv-SCYN$`mP6sWhUyQ#Zd~kuij1 zOkZG1D_>u^Vy&6kxbsz_>%z;<$c)W-t)A5ht<-B4AP|5e_lN{%Yc*iZdHd*zoSdXr z{~aVSXqx~%MatJL5zG?7noj83g@7O39R0ak{jeu({Eui@SY$yMFN1nP&bt0&#r8;x zB?b!Zpk)6fD(6D|)Ti(}g&K(b_U!?(a}5C$TqczvA(=p467X*orQ4vR!*Sob1Vu+D zahPDuefRlhGqLznCMaIZV*yRf8^N^Lwh|3|A|gVWKLrU@Uy49s1c6>AcoO=*wnyCs zx_6=6MauI0wJ$MqPK2h@omxl8@n$P`k-PAI*&mgDP8~#^lZE+v=FE>k3%sp$jM(R)R%Jq zz)u!z{?&E=&fJKrSD4(>_Nf*UVoY3I9Mn)0{w$O=0=hl%_;0L8jTyeh3;?tj^ zIYB0(hsf~31lO)*LhS*HT2G;xI8^0c)f{>!5z5fBNP!}6Lq=3IFd!g+$9^fxaeca} z3GE)H2B`zmX=l6i>nYU!yPzixWVuYpm{MaR$UwXA1JnKzi@+h2o)HC?yA03c)jJW1 z6E`9NSJd~9Qc7h61#PFz zUgdn(T+r;0KGMd%=zcAC4G>waUc6}9Iz$mjB0$I;2u29EmkHhJ&Fl*y z<=sjG9mROeCeQ0G|=u-`azs+ z+1dm9MFRk!>!FQcV=_br#6RPx99(Q{)(Ucdmy*G4NePK=K#%;x^Do_DULXpT-q1`w z)Nz|v;2S8-r9&Yzn%g?%DJFR8_YzYKt>;#R6PJy$|f5#Kfr9r`Xwv;k^bt zs0&~>)412E%eQH*AIg4gUzMO(Q)oKKO3@8#LrsI7zC&*cTsX*5FR^^6QD)N##gBZ~ zQTP_4)$zLEB&dR!K=DsM7Z(SoHKc|gW-X9%+9vZQ)Nun@<97hE-mIr=i^JvpS-Vj6 z3a!GNutl#W;9wmw_mKmOl9ULyk&|py?2gPdd5TL>`IwyC3`l@hO z6zj(eB7tpyLg8&OXvpGp9tLCWf!Zl939ArXsjZLCPdE_?bI^R035_7CRc;mP8X9e? z*O22Iaime(ZfS*94l7&TOVDqpgpDGH+VydhP<{u0Ceq|pm|{Es8OUZDu+?X9l;My_ znCx0v)HRH<`jwU{cCB|Thn72=04;RqGC%kf8A(r~xxKmh$KO15GZfN4A)Xuz2_4aJ zr7Ld>w4rCoLS>QNYEl%2E!ci;$AbC0?Tnp8x?&)tk;zAV6P1hCq;Z0bs2${AX4oKu|+!&miz162U7^ z&#A@54~x!cPM@BIxeGY}j{*R; zk_YtZ+o;RoWyij&F3N;q&*A-oDQj7AmxTe8m;++AZJ`;1ed* z-W{cIB)iReMt2FP^(Z@xa3*$UWbks`PHX8*VA%)WVp6qY;ZP$>F4F(C*JUA1ErG46T5h_1^fr&kWOs z17@Zt?|)zX>E0Ae!DB;rY`LiVp2)iHzt<#diLPK7D z?v!0T&|xTIX?YisM-(dFJhsLm`GO@CvnBU}wd-_4fP28SY8p);UJqDYJw5sUAkiW_q&=Dku;@asHf-&@1RW?=D4eHga7On|C`QbD> zN1AabOuwng(WBfxpeYvb;zck2i^Vm_y-_aaLnIj(8d92#wp$!Zr^Us`zlIS?Is=VZ zuc35${l3GK^gY$WXi8c`vS{`f$ll>x2EfAg@ww3QzQ~05Rkf$i$HZCzI;|3i7p_s( zct=p-7X8MK9FkD<1n_Sq`_q)4SO?l}d?H@S5V>$et{DY+e=My)bw)Ymi^oX4{|3Rs`%Z;Z|V{P`ucEBxIZZ*Nf|J9h81dS4%( zmvHWKQtm;brwwM%SGlc-V~$iGQR3^&_jTrS9G2Tt;AxH0avowPIukF5N`+PU8o|k4 z@+n~?f~GKd1yTR@b*IdD0p)cT$2DCBjWUIFC;4utb2#to)GSIf?~xc`e=a$9jmzuz z+LV-D{f7^!wZpFd(Q-yb7`F#&TF^dx^7gTvz-~Ss*rEAEdYglT5LkX4#Nn_Ei=H&z zSDq8v&pOrXnndNj>)v?3yC5vyT*NwIy4ONYL_GGZR3&O17?=p8qNgQ~_YMBHhPVtz zJ+!P}A|QDE7LS51i_k~N(kAw_Ob5ls#6;!?JYA>j>Pl70IZ<2|^%4z2l=%1WyLp6k z?;A^|4Cbg0zWVwVCu$us$G>*`pY@GFlT!U#3ODcZ@#k*}y}Sx9UCKL|t%gT*gT%euX37Rnd>vl9M??}!^Vz#zB%_&R7xt;-$$ryWqqIQ1JC0$mZ<5L z_DZek^FA0zBt62y!aRJAZ68h-A6zMI2(Xac3y0(tblu)j9Q~5aeDaiX^^YHqU>`#! zr&Dx#>12{p<3s$>-~glU+&nf{0h@XSt*qFoE`M&_g$}KAkzRi<8CqR0fUk)3|9;DR zRvQ=h_S3l(jbv@bO;C8ak-d@VN^MhDwYRVkcnVLsO`@~V!P~-6S z{=IwduTe#NBZo!A%F23IxA77rLkj78TZBmJN|ZU8Bk?f8FLpa8Qcl%8m0t03T?M z=%6D%f4(j3H{>boSC+~0bTcH9*11psB?;QmN2=pJ;E;Inf`v(|@;wxnCu-hY=n}?& z=LN;ZY2IEA0;A}Oa>!+6XMgSIhihtT3M;wb?Cfka`{M+3jy`}Ooam%g1|2(A3se2a--;WTZE;GRTxmpkr6gpznNkUfv}TzC@weVU`0s z*M)b2$8NzJ#LDXSc4^!@KB7-eAv6dFi&8~$S&$?B1)<^LbXmDtRkt2JDype@r50eA z$ZPMf-9}15K*$&2|5SxtP(|fF1LI&XD+EEO#xP1A|de^P#L86*P8l$>9vOk;ja!Y z35}}Cv-5ptJ|$6U@hFuS;nvh#T+yCE-0z+%kNEW0(o$|HJN@;Qq*AzyC8(F*8yar$ z^OHldLe`$D`o7D~C6Erkg9>s2RbO8Zi}NZk=Y=8mA1PATIB2N4%qe|@C}r)>=}AW3 zJpq9|yt2Ki=_O1=lV0h?f&RD}NS9WjMe`;jBQ6ZPsN`v%K#H_WhDpgwBNZ25&?A=5 zS?O7}DAlWXEesor``oA;{yt&l+@%NV>X*dDv6FQA`m*tfi14h}>y0IqTs11co}cf> z3*r`lIbQ~qya(U@cw_Vw81+Dr*)=Fr`ay|gzR=Sat;MKT^c`mZ#}*g;fW@yHp(tNM z&_{W|STgALj~IvqsV+YQ0p=<+W|!#%g>yTuQ9(sBl&7`v+czA~vkf0@=c`Xr-IB5y zt5G!_x$f1~72&MYmp$*1m*)@}#i5|{WzKByizZBv3zZ`HP+~QOy|7s7dKn3ZMo6Xs z)0!tBv%lwda4$oQS4sy8E@wepIERh>Dk6ed;Pj2lsB0K17{2v}+Qcao^hE?fQk>3> zZxjNv3pW@TaCUchu}w^RjbA}t`|(+A&hdJdei@q%lfFdOqX)AD|HUSIe=h!f``Jp* zJ!%~UtQrt?|D7>E2?>cxxgBF)u2uljWN&+_>wVPJUG7=${hn=BxnD!0 zA5vXTC=0@Y?wxqz4Adll?G=Bf#3UVb#E&pL0fG1o>U(|tmsJ@$MFoY|Krtwxbez72kglK3 z_%^nyTL8Z$J>OoIvhQ6o_<}8=_LKydGg5X&PCnxO4V+a$y z2b0v$0DcB;$}1)}D>j#|5C^w2@r90!`M{;c`Ch^Oz0J=0AyTZeGQ}fJLOnfG9C{rc z8d!qT_g-1jiE_(zUAmu4vVYSMcY)SFtfzGVA@cIgG$+HV-D^N5e9fa$I=H2VAp zY?s-GLQ^^u@ktOpfge%v6|it}5`pIH8At9O^`zH%ZSp)q9bh7yKC8F0(=&6v-_kBF zXHPrn^X1Fal>BbOQ7q2R7N^fzc*Mnhj+X1aE)w8Iv+X`&&>C4SVu>)3w0dsmEe5xP zRgo->av~6meVL!g39_+mnD^ndw?!ww<0oc2lf>RAt(f>?>FXP6>th8Jj|BVc5fhCs z_b6O1cP2i+y>xSINnAw2TL3qo1F#~MZg~CC@FW; z4#*n=8#KT(KN;tilw5@r7;<+COVIncD&s4XZ(|i3oysL*{89ci-?;Qs72Va@xtiWS zqMV|losrs8_W57(X7+3szS`mLoBw+7@OC_w0~kgnjJ~zT3sBq=e*cXo-sPmT^FE!l zjDoe%j6GE_Jv?Y;Zvx7~lw4fOenx53Fumaw6B8pRg-Mb6fKTH1O3Iy)I>`I8ncAd@ z6b5{T5^|WBBSk7ME;7u)t^HU(h#wu?*KZ_W_en->LqrYlShB$A0 z>-0XCBpLm>bZKeULMO3M3bV$ZpZASdqx?C{CNv)G=w#txzmjPQ599Cn2rK{!L?ZAE z2z+Ss?^!w_^u1mnOb1lE{pN4iicGveaNmzj?D>6R1~tlM_pkcvhmf@FEb^}dU1;*HCz0l67g2RnGQckTpo3)s#nT)noAa|R*z z8E%kZezsdwEin5@1c^=w{FuBX-_b)ragTcpV6ueImX65DF~L4x|Mz(n->BL7TaDEx zehNNXfd?kwFD?fhadL+72rTsCSwcj93$!8g28(Q4b^G~>6qu@+?aPkYu!Yed(r&{z zNJapZoFMCa^M%^o(sWfGvXuV1rO7suHr{uA% zsa~;6l8p66x3`1WD~;{L10J5id|qC0aRaoocz{xreuGhVv%&RpnmS@-P$@itg2(4P zbaLWBo*px;Fc%RT`Wi+R;C4@ym6iSI?R_jOi;wi1wZ?K^LAWK%ylRy%L4E4#Jd09l_$X+`;`-zF@$}~jak_@g=J-4E879W`&+k8gHMSwFbS!v-<6Xq3L~+% zi@RvQ&222MXidh;NnBU=rP%tKfZKfr28O>ec0(T;gjTB0QfR|OWLQ~cT>71QJM=3S zjk0e=c8hew6b!Ip?hN`|(Nes#P8 z0)1n9yW8Rrqz@7?N6ZYGU#~_*MbUL+Gr?@>Yk0y5WcY0PSl-_EYEr7g>6zN=qB;2W zqK_zp&c(&84{j*GjEy~e&(+DN)e)u)5WfG{`NFnAtAPHFQ!p@*rO;jVCiymzgX7p% zPx{VKZC>cKb_9@rXF&d)r8?yk!!?nt z1GlHCd0}jFqmneFR~-V>+u&fAsCDQJC5OSh8`_AEQhxFc5vB6>_ZNmjAPYPZ3nmhk zW}S$yT{FcyU)?JfayR+1ltBj1R(QC|?9`iU@+rSVMk-_*8q*&2L*4NV>^)GR@9^+1 zh0x%%JxFSGNm<6H=H_7+@N!kv5N<=sW^fUKdFDJ3Jryj}(l$yzK% zw~Y3fGlzBnOKWTA#rY@Xyu32+$z5>@O@5~FUp2~l^(s}Ru=&dN5?RC_0YD8)q(Kb0 zvGvsC{ReVg6s$9TetxR}?0>mL+Bme0UWA!cgvI~|BrNOeZof!#>(&d}``7sy)z+w3 zaJzoA;*6G+jx7}!?ew+bhS%2FyE@FzJn8&#|uYw9Rg^vENF0Uj{M^KL<;a zV`iNOIX#1V$tAG=dZ_Eu+hkjJr`)?r?q888oFFn$PbV&_Sl#*!6~D3M$19(TxSX-_ z@ADoD3#O8>_wW(d0jWVDGFa4lb@z5K8frE_oTu=MVMq`VBmdF%rFV4zZ3Hkv;R&CC zy!sQgRUrA#)7#SK%5UKzN`eeTwQX(LlIusH(cS}7iBdH&F)1l6t*{FK)=dd|Ef5kQ z+}Sq2>g$Ea_O;6GZ~=yDfki#j*7ksLit53^r-{*4mwiq{&7mgiX+A-puMp+NBJUL@ zCanxO>;iB^Z=cl%!u5~QkvTahye?|I>&re1*?3!cm@ToGSc`6ZOmy@(7}e#w$j0CY zt+mJTy@P;t)@AstGBq1@q z?c(Z0LnmaME-=LjkITW@*xXc%4HvbxtP=>E-#~Y-tgO)HSFOX*u7Zl+Qkszk5gpl( zt1Qn?U%Y+~$)^}p3&6cJ4S#$*0l_IXxYmq9!0kPpO>I}#UCFU^%4|3+X!;C=OFUm zbBE_ejgQ}jM<=nH4G{qEcUkm2Ym2BMDk_lxYQWo0W7U5_%QQBZdCtxvn6|e^4LVMH zN|i4e-yZJw=Y#uk(sB1mV0`Dw-wk^X+YciOLNHQK-?L$1YVIF);>10ClBN`Q4g(|8 z_ZI3JFU-2AzIGSV+XywA{ZLR*@rJ^24V+zi{y86GY|bMz2Rw`5>RoLVs2m_VsOa;; z^809Q19B_(u&+={etUK1g5^X#uIW(0dEhPxpMxi&od3iuh#}u#{yUQ$14BFS zA!YpyXg*MEK|w9$l+RZ)(;DRoLcwV)Eb#^?7B?TN!gCFpDt!1zo zAMKY%R@T-Ysj8B~)qP+Ezaj1;(H{D=yg)Yi2&Ff@xEq&L?d&+=5mYV1YqM4F{TT6y ziYOL`-kb}3&;C?jANy0H^8~s(;;rWVd<-QdDhmtuLD`sg-rJxK4vA=q<>KN(!t!6d zq^#@e?q-2TF-d5NMb|p}ZEheI7C|E|q|)I3tF{WuNY~t-mVzSo{d=L@6sfSvB?PZ~ z(yu`GPg;$QP_(C?JKZgqV1z;WyX@@Wq5EGpRhsPd*|QQe2*!klhBj6-K<1JMU2Ig; z)HMwaXFp+FPR>J44{aHOT3Qs4Dy?j8J_hRxJG{;Wt@6{GP$tb-7-3%cS&WBA!Oy@3 zk3^6FE28_#32uq{JvF7cbN~-OK*V5ZF&l@z8z$@alPG95#D>}!JPYCsH1*??lKR5a zP?XjT@Y?%|Sv9zWKn-jlalr@Kp+C zzsCmQu+cC>c9Wl9bIG;xXwL-3ETzoZs^IXu_D6sqxdX`{Jis~H9QE1*aRh2C%%R0K ze892CY&+rw8sJffr%<4XJSpV>A%(uRwRJM?rM9`bKVr?_s$?ks4^!72&vpB~HK}AK zo2(LLl|oi15*1NKnW+#m8nVk?ktif3$_!=i5i+w$*)kI{vi+`i&+~j=zy7LT>hu2G z@B2RYIoG+a>uAjV^f(U17@e57_!*f`LGSbm7m!TsG@m&3cRl(}(u4_4`Ta#bD=Wju zc6WR2SAEg?T;)V;TvS=y*$I;dT`esGv^O{J|9j~^Az(S!g9#ArR=Y=8rYSm|Y%~uu z<-KC?TfTEj5wctNB^xVVi4fXkb#HvGYv7_bKo3`hS%Af~iMy3zPXo4deWtpBWYG}x z8Iw!zPl$`ZMk3MNk)EC|GIjC71y}fq7=b;71H%l^_F6j{?aD3%poJb^Wh|J3oZ0~4 zetKb{63Z%V)lS{rsMrS1gJz;0H%))k z`>WQ5tM?ZRnv3^M8X{8tSYH=oVG9gXmacF_OK5KL8$F;TO=}6xc_bpY(b~(&%Nsy& zA)rm^SJn+s?nU>Mc6_vElo77AUYb zk?f(TuU*r*9EvbiQeG~fARm6>&I4u+j&DFRSE{!)Q{4N-Lg4$KzqsToSCz#uo_;J1 zAwpM@aQH&bU5f*jz0%yagh}IlaH;>dB5?7E!E%V%|Bh9kPf1R`eUx*vnzVGh$<6oy zyV$YiV^)Df_j)Tx&z)0dUDrkS4De&0q~vO*9;Moys>r*Qi#lYm{dedE z^%NW(CF|Uh3NYa1@5sr$0O|6@vrZ2jX1?E?_{EeA(@Qletd+l5iSXSav_WLbm<&
    z(|IVB8P=_e3y?)8>t?@iW`t_W9bh%d#(Ved%*>RzLU(lXXLq)Z3=J9l>`V_rJLJfX zbD_7YL!Lh6URz#ST-D z`bc>-on@Q2bLE~_sj02EUcbJ(?YYXz3$Yp64DtGA6>uvC7QTLcGj<@wGGTa!&23quYusIJN$=7YDrk9ahi@O>lGxL^*dc<{I^(Y@)__IUEmub$%UkV`JRKp?Qz<7FSl}72o}|iXxm!bouxC z37fU@g7vit3@MvGKQFffvKB_@_pUG^!Z^U9ko-7x6L^Uje-7f%f`LPs&Mv=U1}TY6 z;6WrdlWRy3*tKq!`07;t&%59QyB&jblg z3~?A?6j7!F0QV=G=+2g?sL~CGxEeE46OZDmz>05C5(kq*mADr{xDkRKTU=H&2r1aW z!I!iDQ2Quofncfb)m+5K$tkxyh)W0BXN}QiyiR<>H}UagC@vDiqF)}f>S00i_wbP{ z$TJ|EdB&Iz*##U;)8JNyo52WfzE-O}z*QNf9mN1-2qCS5+wU$kZmb-8FC&8_M~)>z zdD~gDJCA}vYMD1VMfbAl_QaQg>>F%oiak>JZKKP}%uMgklFRJrDJgd8CMl(JAd2wt zSqSIb#vSR1ubn8q@T+?l^7`0!@A#7^+vBO9^f=M8SNn{x?z%Dqy4T1raF5!BLubD!l7WW4=TQ;!P@Bt0^z zqa^xoDr}9=)I7NS$Xjr1&^9rUR{rs70uOBrVTOcU?MzHBy#5s!FkV>k- zk~YHM^#!bV4J~TJq>=1V8XMR0)yuZEyq4GBN3;f@;$9WH)wzFktne$To`yK&r=X{V ziNn#@2TWM9e_9@7L~jc38CM2x_BrG?8_VHhw`08#pa-&5YyG!t;CYh`(P0QDytGyntD!Vi$t%o@cN z<3@)hq%p(vE8W1?uU~U+_isic+Sx(v^KxB#DEV8S#zT=-o+ABm|^dX92-uYG#+ z2IP9g4gqmNFA0{!La4vA$0!-l0Vf9?Z_KUsx7|+$3YlUVPHT5{CjvYqYl@+_QgO&x zGt4_Ez+QF3j;YI|=U>y!xar2F7+BCgN9yXdvT%lSCFK|S?%hclV;e?s8*p?94hp(p z*|LG`@bSkZU>DI!?&zcMeTD_%_fIHADQj&j(GZX zs5t9KvkT#KhvMH&_8;1bE3B=N_#C{otjoyEC4IStJwzrf*EdW@GuC{JwW5rnA*EhT5Has!0G(0@h+ZPH#_jOjg4LS%&+dM z@{Z%acoDoDhHNjT@(MyXDA0SWNwsgKz4 z)PIym{_54_o#dbVdkX2=0Zg(1){sRqNK)<1_xP;H86Le`Q-l5eZn(ODO)h0dtgbqO zW3h|qv%oW?ElAzAu(Rg?LKD1cxCoL5YO=yh#P>$Jn5)kIfPk^TLR}8X8bsoBk#92)traDuMLo-UU<|Q0GX8#vgf4KZ zg>hAYyHJy2j(cP=P3UN7xA$TIi5yho<%p+rdV_s^`(!_i_g5@PqjcR$64xNTxM;kj>#*8^kD{ibiJ6w= zk&@!tx-CVqHmry)Po_=9$eLqd;9>BS4=HtGk?RqL=zgkQdBJb%49VE^%nbEE_>1XB zd^QK#MEwiW7Rf2p?0Y>=BeL^wJ+aFBc*Km6$!OsHRo>9q*cu2fU=HO9>{(;E?i8oy zfHS#9oUgBMA3g=$oXevUmh-dCK!>Nn$N~e;*Ky6r$cPFJp0qJ50|U=su6yZYX#Nij zTuIg*y!duZkjAHPOgviEW%unrzl5(8HtKBpw`%T#vP`1fCLCRMe<>``j=P0pcU3w+L|F0rxFY9W^4+?ranV9RPlZ>Ap0Y zGVm`-`}i@bQ50T?%589!*otc6!s7F|U^NTemAh0U#58$H+f+O}w7mo7D+?W}{s&i& zeqI}BOUcOCim3S{{|3QlHhD?=m$j)83O$G`gi0{c`kZ2W>pR1WoV;Oa3hx>DfU)n4 zryo2Z>n&h35_jqC0xcU-XyQ;?cH^-T`biqXK0Y#o{pBA;M&OBQ zAGniPvK>Uo#oJZ8KWe)2U_Q-ZNa@(xnZbZty=)am!j-qa?Z5Xe8qjN5L&N(rU18b; zn(Sqc=FM>Uhy#GP%kTQ%u7u1c5*yo=bR&%3L>_}b9+@uYZ4MjtfHg!;r#_&M~Ka`Q55PZ0CrhVuYvr71@ z8;d+>dw(_Lf)=lXs3vMZA{+Z}r@$Aq0uvzs|M6zO5BJ!%;N|h!Ej(Pd+B>mQK~d2$ z#URoItOw|(aIKO(^;MDvE6*&RUUdU`$3Y}g9h>_5y+CYKAs*nvhhO_7@+d__1kO}} zOh!fXfi*>!G+vmoaJ(|0FvrpUO`Sa}D=X330rI~2Epdx*TFe3TH$vmW#+)fUa&Y>a z)tg)o57`9o#P%Cb%LaKLKYouu9<_DrR$j;79!g|@Oxk3TzatTuwu<-K3O$R-<4T7nVx_}^p)e;@idz$J!h_*9Dv z)F8@j^n0&!fq$2D$-ZxWEhKTbA`^h=TCLn>y1$e>5a(3?!B#1{pg>!l;dJUCOfXDlIqG%eDRU ziwDfa-FO++^WzJNfoGU_4^Qs7l=Ax@o?f{2mV&hfL!cB_@i=#Aes<2VeHxGpr-RNy z9&;~T!~d3%-*6pp9zD7TES6`we+*Ogo{x_5Uf|>G*J5He9{C&`Z*IhyZ3z{vnEjJ{ z{-6iM(riI&F@V`yXWpHpvMvf%IpJ$chv3q~ynp|P%UgT%pSj9x%ng!~h<=Ycp_pb9 z$NYOXTB+*Lp$HDn0kZKn^VG^~8ZT`}E)6bB%8QIZGn00I#>iWNbJIm)g@Ut|uw~PX zt0;0s^$zP8ywA@^{@{M&@;eHYv?tFi-gU@C28N`y96&6{=yQNQeG+q#D=#iB8RB}{ zX@24!+aqw^sC?{Rzq{dY+1+#Te!U+hN!a0u`C>{EZq1;Gqowl``RNZb>3w})o~<(L z$U1p{kwZ%d;1Xl#0l_I@7(dBc)&tWfAtfbs`%B#lKBj!`TqSI{II`d7dThJ2n~j`R zKLV<*wDx}0iRm3POD_h2WqP{OCKXQ?xT~ zQmcUer2IDucijY_i*)+o_lSx|+X+6;W**LF^4it4CYVL$iV}Sg#D}fQ1lK|>^C^g| zNB~)28)aybs>g2F_^N`W#^uw8%c+$7ne2<;$EE|bmm!J2{y!K&=MbxTXBs~zXJAR4 z|Ay^*pPjot0?^5~F-POLe`13F0uhEdn@@v0tEi#z^n1jgygTv=@6HiV!t!=`xs!o~ z{K%Fq;i70mkx^2@LfXd_DK_~W+3F+nH6+fX z1$XN!O`yKBsn3xcVKEs`U0h8Q36Vu@*tEz-Km>?t)6cy{&0bZ z$2RBnr5pd=5?S_O8h`+~%ST}$EEVaFaBs`S5)FljxVTU{P(P|u#H|Om7QrXijV3q? zjI4Mja9KStg$b7<{WHP-U($*RD-z{71oaWkOpg$I$p?FhoarbT901g`z7=oWnw$9JqTKtf z$C)ZQS*PfXB#A2`(NW9qtlHZ5Zcp{h94}(m3~+bP?JV9H6fs^{=phsZe~E9td#L?( z;ng|VT-JnDDLZ1pf0vl;Xd{P**AwT7Vb5OyOgo->D}6jXGjsCDu3h1?K;sCW$@k(3 zYRzp@cS!efR_L(|tw4TOokHuQFg>?QE#+`7rE%>PC+pm(Fe7+`$+wTOvO3v~?+FAq zJH~!i8i9h}ky1TM-m9nt)=AG8&D&}yPoA83on#*WRwLHG+^ZOj>kpURoYFcTTghxLEoJ^X*KwPY{bj|>pv>o#C1^JdZrnKV-$sXT>^95qIUKe<-%Ci6wrqJ_ zTfwVfGH21lLd(kfqa6tzD>_%${uVfN!P_0u3;&KJYA?LGd~f2|`{t>*R4d>2S3@^q zbLG7*Y~5CYtg5Ja>P#Y#W^l5&X=v%g7>R0cJEh(>R#xesan+v&IKe#S`19%~=xN5| ztu;=c6^ZqU^+$*{>M!%KF)y;cr`Vz+dBi_nQa?X0Cilf*7gVdBrY$|INZhr-o@~AV zQ~PQ7_vgGT2KV<_#}}*CIhWEVYffO?dL>?ePPD*-#7{s}~pg4nrt|mr6&%UfgC!$;RE^nVxH7 zF1<8FYX=SazX@spx>ftK8BJd$`I$I7H}>z9QLwSkyy+G^`K>lZZH|Lk%>*$h))0AY zKdg$=#wbZFEqk#X>Y+t0UtWG-Kf)|>ZMRO=Txe04(x=V>adKQDnn2#f(sQV+txqB$ zycll%Z-7uui08!Z{|{Z+C|ndiUS&wi_;9j`;CKv&h=3A-G52H(vW&OW@lvbJXTd46 z^@wPwxC=0iWUX|$9NAb=;zjL4>v8(epQ^u|PYQ-!?ry;Xg4d$Oy6?~7c`!GFj_N@u?AXZ?FXUp#hRTR$IA9nVR@vPjOz zNN>_GF+L8@13I*oXoTp9tiUu9TEaoRC6STI@z&C+h6dvO^?;u|6OfejJp%sDd$hH+ ziCtZaUF}H_04`jhTA1ohO>3{8)Xn9e?QM0LO2O9Nv}Je;2`IQ!pcmIi{t0RDt2m`q zEKP>)y1Mp$K7B*Oy~v_I)kn@Wr_<}oii;N#2@5sIHC5FiyN3QAAmE;R{!8f4h=*6; zhEG2`DY+}hmq^aUpr)u3Z)_iJ7Xj7wfjgR*=Smb}cM~f|g47z?wa(m&Gl}+~(>3O2 zuT}~4YD~0mioaNOZaL4mN(i8##N;} z@8JxlcrbVWs~9eiflMa(avh?N>$y8$xysjXHtl+VAaofCl5etV>s70K=>-1Phi~7Y zEiS)-8`mmHkU_Jv$ceqbI>cOLWPWZg4R$$}Gx9{J;KL_+q6n;c(Lv{vR#JNw>5b@F zumh-v`u5pMgNX?05%?Kxb|_I2f)zMRQPrb%OG?Xf+4wrzGIC^-`WkF^n}m*LxQ1%- zBk?W#&IDbcKT{_2or$c_z{1W4!~NygUdNb4fkH!+5MyH_vBqFC68v6LuYIEX-}r(S zLDKL-n=|`5JVyu`#Xs1Ul5YJ=DQ0YYk&&u9Q-KTf<2#;v#}6-+w$SchUKSa76BC2W zO==UZnkowEU?xHo|I62x9x9sCy+zTxf<}3^Y_SFH!e_tg(9}UoBX#=zeo_OAZXJnB z7pBRRF6{=NhexxjRRY%}6>Imqx{ih3lxJCQ@HoU{@g1rw3p-2=d{@MrU~Zh3R-0_s zBi2m;gAGq(rc#|fl9;-m9p{H7sSmzGi=3giaJ3?oNq6B((-b#rmL#a`Q-o5)08ER;{d56Na8?}1XhS#nU6bd;^n81yQU$FtO zxDOyQ)LGDSWv|lGBKc{%g06<4rNKU1XLK2I>_0Bg@hRC7&$ykSKA~`@Yo8w#-X<5SiW7qo$mITaohWS=*` zly;h2yHZvY`u=l6ks#|4k;DKfH2$(M7&R;7&NAPIU?Nu(H3S_3+_gKz?*$2Qc!Hr#OwSKA_dF6r9u{F2O68>7eyMtcU1sp?_s0Yj`I!nazY84d-;#uR`9es>Grk^5G2+l1L7=&vBj&TBz^;tzt_xZfa^AY z7E&#)xgWH-w4YY(2k&xWXms>rOk%*}|MR3DFlwVg$I8IY8r|jV-tYaTJB}#hWwU59Fs1sV-xrhOPjdlGSZ-r z1D{gYQ3oCYYK2#zrx05f?o2G-i=31!>%rJJw6YTXH;K9q3c)GBxOGdWQVum&Lsb+) zkJnf4fZoESK@b27BEjbUF%fT<@9yB;BE2Cp5n)eug#*Xf$shTgYZ<%$*yBylW#qH z_LxT!T81s?{GQDf1^#;<9aZ-o#9>mjjZE^X5-Gux1`Fdur)86B2yz z5c_=nY`0bKOC8&I_*QfyRj)hnpBDV@5GV7Ab~N}H#vzlm$c_JvA51rG;e8smw>CKe z{Jk)NtN-N_*9k@&MrG73r3JDYS{QMHNIQ8XSCMjb;J-k?ESCWs*YdXXG^*=H-SEXVa$QQWzOZ~#fS~G z%PUaH)i_!(9UXP|_T~~gZguEBTOyOgf{Oh0>%MjN!AkBJx!9Vjum5ipswc+chTC!m zdpoSq?sx@6?jb0|;x3>q5jAIyti~H+!8qv!uDE7rABXU8s9n_Z`<6GSCq0Xb5@f60 zZ`>GJDt^Z}7i$bfuyJ=@DV5(37hZL3I@9IiSHFfga&43Jb?JK23@;Nq^;7J71MzsX zxY%2#)SIVl%rW@GA4V3aUx;5BSD|HtKhU*?mCRc{P-h~eY1U&uaRLIg>K7Yp_m*6u zx&K)s5Ht2~CueXyaDIsW+P7CHZ{SiR-M$@=_{He^j-O!b{TTcE@+2{By z+3MCWrG~t#tLv^xbH8=J{HTpgv-rlK#QmF6`ciu&o{K7PDLP1q676CBS<$p~>(bA` z`Gz;O&YDb}P2>rFYBW21Vd#fcn6~lFo8F+`fvIw$ z7GM>`uequ5et&qgcZb7ldXo+C8WwK>XDP zap=rdch6s59v(lda?B(Yt9%%Q`re5cS64TogJ>2vr5%bQP@{WQ#%^@ir>ZZ!M}{HY zgjZn4=SMFytAV9Wcj)U^r_7+y2aAjU9wZfeJlxhZFOO`pQw^>FTS=h*V&J)<)`=_l z_V1xH#Oo>{UKg)`KxN}=d22`-a_>NtE@akfsim8}mp6PE-miRcu`U)d27V7$UrIhl zK~21<`(Ic8B$W*pZ^fai_*)rU^g3_#B-h@;%DQ&EKqlcLA~327o#6t{jSpE_l?eDl zY<+*1NTUsmy4$GS(dbXnt-X3jMImt(FUw{lFvqf6VpGcn;<1{Tfs&ts%opYeJlW^Y ze<35%-n7?0oxWuR_|-le?au${`-k>`^QWday}VA8n#b1k7qgexFZ0y9pbEtH4Sue5 zH~-E1tG%UtrAg53U#1H_W5JDr2nE4ClS=>=59wx+!%Bljh@L1VsHy1bLGz~xpEdsR z^T;`c#I~+3rgN$hpI@N2DFr(4t~&2^KftcX3Ga|qIAGYAgMBV!H!1=7@%dL8ZC;Vz z?%lTG%dbKA_e*e)(E0vMIV@JZ?{G0n9pq_B=LA-6S`dZl;K$gy*Hs!)tTNK<9q+3* zsBVL4f+F|dTfFHkGVEvK9kG`V&yBn;QZS?AyOAGFO3AhljyxqtHM-Ml73Q{s7Vd#7 zvNi?Gj_Da6xui?C=BfwAmZb9TI%U^&x@|dfdwI@EB$fKZ*hX38(T$1$&QBHF2EXTO z{^O?bZRN6S)eTJtQ`2|1r~7W$n8Od-7rmXG{{*7ZIG7&{puZ|I@`#1yRe1`pPpcWk zkaKp|vdwe5DK)p^RE5rgiQES#4h^l5{+TTj_t;XFW!oai9&JBN=wjlyK$!-#LWm7g zHIv@pLExMcy-797in%0}+ns|q#&zFj3JnFdD`E@-m#9veB)GO~>!xHmS)`=2Wo3mX z-f8b%7JT)pPd1&`vZ9bqK_hI-o(l_}Lu&?cr=OH7pKD)R(P)@`5mKuh^nFD9PfO5% zi>4-HS$Sbl&~4eF9KTu{a^@`cFzX#>mCxEzv;BIMm}ui;JBK3U#uv7mW@aCr`%}r0 zakvL%o0-!NbZ7GWnUZk~FdQ>2TO3lgn9L)yXBQ3GAG;}#O^R5Xb_uJ-S5v|UCG>~5 z)ty-=;;x+7_a7I4ez0m|x7#b4nHj4ogIykS3a6aNRaLLrO&r_d>gcyVRlvXQ<>kO3 zJR`LJM}}S{^6uXH$m}HH?3fs`*RKbIp4cQVGkBGkdQ+P>7H^E)s@yMPH#hoS$BG12 zjk_@x#ONTkn&#NpSdQZuO;3S6*A%ZimE0asytfll;7wadn>TMM8wGqzQ*~%=zUlGn zY%vaZsh+F(0}3`DI@6PrVK7k%5sgRp1%-oZ{n0@Wpd*n0tH-RcyzAYUD>*rPvhH^rDe7@78YI|I>oo3)ezf)SD{_WesA-y@5cLEg~A3jL_?3whv@kKzBeekvz zm|RjnCr4_zjs?3-bZkJ7%`k|eRl^3D6my7&Gtum8bDS1N;$^(1=WwS=$CMA(N5R2q zuQk6Z_#+e&qj3jv?sdFxb$m*-O}MFYd-VD&Wev}24?8QXs)vjEf!1-apa;NP-H|n- zkIOJ}2aEdteWaFhoKDUa>4L&P@DImfN$|oA7nv#_jpUspe*u zt)!0^UyXh#?@V`5Ytr|Keb-w8he(lz^vui(2nn>66*Ss5K;8Mmf9XO~G?kpU0>RUl zv1F;K<;iB_9-lxnH9kH*NbHxXak&wb92xBv3k!17%OBsAoPc-gp|>10{yR6^TM0EV z45U1u1gW&Q_(tLBRV8p+Y;M7fm+d^{Rx5_4V^^G#6BAjsZ5xBryP%^J*AJ}eh{cQx zyTn~Pc|AR*hYvkDxCZy%on&%{>7(YCL7S!NIr2wQ-A9)^c+@p@A|6fOw$jiHJ@evC zQj#C^Lvo6W!bSQ%zq{b<`8!aSj6-1uHxEyL+0yLqz>|BZF1~JzKSMib(H&87)IF%n zKkLI2vAZDsN;)j~R~%K)Rx^1LB!S^5u91<yFfxBDs~RD>FM0Ux!vrDe;vM@{ zB_6h?toX8gsd?Z!H#cFU%)dGU7@1T)^0~Pw8rxF7?^OH&Jr-H1 zogb@M$HtBiJx|`xc77L^;yML3tfuCMl-}B}?Vg#LUMwxtrYBsSx6#mYF^=HwH9`yG z=T=U>$2zMx{|WqVviqjU6iUCtsmJ=xZHsNE<;YefvTkmIOFVbr#e8;kdX2>c?)a$^ zkZQ~eL%L#pI968!PoDqc9(QeAUN>JHe=7YvTKqD^>UceCKwX`f_>%Rs4>A_vw5YB=V7+i?wz3;J9>HQc>w_?aX9@Nnn?3ZnymWeDQd>oy zEFnpae9{?8lrw&hlv0ikvAR;7$^y$4=U$|tsj<;5)ruP?gP+v-=38QYsNbHG3b>lT zy?=f}fkf8Y`WQYPU-hHV(Wh4Yp~=alWE5 z-=3Y;82aNgSbj58hGS=KoQ3Xm?iCHCoBelZ22Sy<(w;_yp%R9UpU{p}inCCV8du&r z_3oUpmhve~$Mh=R*a0C?-m;eSy6x)PAA_MEap^BdzJByuT$$qFJmn%KMT@Tz6H~lX z!g=+qq>I3kJS|CGIieE5U~*6D9lhum~`_djiKe{w#3xc-~rcWRj0I?HZZZwr+P z@jUCHk&(ObJOvNteXaFI8V13n*c+x!eMTp9JkZrOq_N#n&*{*SS!rza*BM6@ucxkz zHc`8K1Sp!AoS7Gvmp505c0OsjLQeJdprD|v)^pODn%_JP{WiG-KM#(~wR%Ft{ZAz~ z?wU}%A?x{&lS4sRC}olKdGDb6h5l$N64VyYF-{$HvJ$aW)yQ>3<85B$#s?V!fDx(Ge=F0xHCIAe31yUqbb5sDNcB1HOI9s_z}Cqo%bc2a4QQZmLr-5 zc;ud*>}^ls2?YN2xPn{ZD;6ZaFxq)}2lNfbFW$t(Jw6jcA%8iW?regRQ-=BRJw-)c zC4*}n(Z6vvHnN5eTFlK`eed**j~A!fxvdTD{ue@b#!W{@Gj7ez`wW~>k@Uw{y=yPv zLmvo{>-7D(tyF(^hnl3ywv(*8cWY(d__ssiKFbR(S?=dp*OvZo+{cZ0{ zsxB_GJ;b&TQxEnWZ8YSTl#(y~VWz=;_MEhvH<^C0=JNcVnE@-Y2X^n3nu;xS=~cpi zQ)XmDi1Hm#Q~COp(t7$;@#o$puZ)ZgDmFF>_#^EN`S-QlQ`uJfzOu5Xzw zmTk1WJ0BbwS!=`;qk?nO+KzB2WL!y3<{{@}E5<_cz5CuPe8$4V;O!r?*dALC-gPTq zno`s?GUDds+<$Ukyu0iLpOG(uTmk~*m@}s6xGG(6-+H&)>%}U4K|S(M)gk(REEBj| zFTPdq`^hh>p=fWvX<;(*b56J*$*u1>)F5jZ|96V!t27pG@Nv_~?b+3`qRG1lbCd!R zNy2ZoN_$YX%>wngfB*igU;E%3x8VXE#_x?PRz2H{vwUM6?5|oC?MNQi( zD!%d_PO(35Me!X^-raf6kQSPw=Iz^Eft>o?Ui!@xY=1TXfpM8T)$LrzW9z)`CUUPy zR{oqnd1>$L{$9w3Dj-WmxcqyVl*)zZ*7F&eKR$P-YG&BGyxiE)Eceo#sU7)B-{|OP z8@?EFV(CD4!*X@c4A(PP+IQzIl~s7;?xs>xxqFxWbwL4DQ&Y4iyTk0T&!;6Go>WLF z_I}U(xU1YNwG6{HL2%g~ES{AW(%(Omt;Ej}qto#6YM|odK%oXkNcTaOu2ScW5kS63 zfQ?fOIODA(YmslHG1U|1SUlD*F0InWNQ&M6HX^eyb}@bMF}uw5<5X%)xC`P#!MK4; zrXM_6|Jg%_qwpCr1#2_PPlF5BBr`0#v-L(aE`@PQJa7((ahdA*DD3QrdAXWec*g=) z7Q?Lr6A})>J^6J)LbWKlucZ3% z?8%cdv7TI$vtduD_n{Z! zvr^41smGTkoK~EDg^ja(e=^Hz)J}Bxh~2-zcC&{>l2qYPC0${D-=$Z z917uBy`x*_Q}&tlLuR9ubDLw3W%q82#pTmwC9kCLgvnt2lW#tWC*-2iIK#19O=I&( z9u$!?%c8au$UKJ)iFDDOlaEVKkP=#LG71Vpvy^z8*#$lR$k(ZhVT!O(qS^LV3N#k^7S4WAA+fS#@29hC=*pSy))oFkw85hT7z^nwlHrOdMij z3}9!#wkiiG<%68HX>%)NaL%Q;7!1wPguVrGYi4spvoAB^7vvMq<`0FxBD{ zX|DdnIJ-yia6=bjk`U>F)zmjK;sv~>`ru(xvbS_4D*RqMID8YX9zM19^ywbH)exrm zHcB;9d@q7Go_QlKq$N8oGpbCTkMk@eV>Z46cc^)2*f8gb6DRpPIDLOCOv+fVN!U&Z z?%K7BMeMfgv00wX2OZhHkP6}(5a^I`lfJzC7J?(~w*#LgaNvMfDBA=qEJR#($4K6? zun;!cIeX(3G}BBNx!NPF@cGSEehhuzT#1w@eyQC z2saE~+^~>h6A+L|d+PgH$GK=o|2Fg8LVEQ=w&3E7j9E-Nq^%Uk*#ZRVnw~C?!4>*UR!9TqM2o$j7#J?cq(%ZLh zCj_C=*Kgb)MGx>6Pz|C>3A4q-FQTHNCKHe4o+==(5QeqvgDA{-#SC&Xf9B&9P!&N_ zMqy-ZT=DCM{Lly*D>PL)fM|?pM<}hAiPR1kbx7j~~f)2+98RNdZkYZ&qd~ zp`%ibEi3|{Cf0OOX$&{^f5X>7%LIoiKgg zTixiv)CaXiQdbl-#^{`Z8eNJ+L)%`p`8M_{-w1Sx&ml|tH*~SdeY`%5)bEzC=p;{O zB<3j{MuU|r)SP;WhKw)WD*C{O4+D%Ns?UYo9;DKe5QI7+c?4C-06`xC?6jKN;2+9x zVPnrd&D3&C#_)F9x$%*(s4#k*jSM=;tDl59vT~y#68(7a$nC~k zci`?u+x`S@Qw;lTy=<|qBuql$5D$mD5^amavy`%p6L|SadIlG+T&Wv356OFj9e5B! zUOmu6!6*>!hJGMNC+;4ot6N5$ndb4u>fyPl%2w%giafh;5`oL|2m-$`#B4CcHeBb!xarof zUb!;f?b(P^wfq8S@c1z%H8oHSgSs-^(A%mU7&unGQgUAhD zJnzZ>-Fd$dA(4nN$tfui`YRvq-9x2$+`9%2(-nY)kV;gDeQC1Zamykhz>Ck;TAM=P zS#P}g&6}eoUzcE-*h#N#C+p%HT7rG3Rf_JNW&oGv!h21NKz&boaDUC?k`Ti{yR18H#uGBt8lQBj`2gL3&% zgkGz(6zafD_m_Uh6%0}lIgvMncF=^lTL=31uRYZk)iA!MF2Z;@>QUg z+RNu6pp<|4@)%h?8{j(#Y#zctIy`eaVHewDFCY$|C+9V_<>WR)tr+~|$-@^fSkUz+ z23dcC$5j);0@ExUo~;+B4I%C)?i8s9b0u&eO=!E!ddl^zyL4lR3?QRg!~~oEU%x0|`{~alx-){D zUw6lmx10A}><^-f>3nYa{h*FpA?WY84GC+E0H{K?;V%3g7#oIE>1h`NCs@9INaB5L zbFS>Z@8I!tS1&8ak{L<+L77JI(OHr2d~>VRxF ztKV^}=j^P1&{)Hjj>@L)J{} zwtKe+#6<)!FZBn=;6IKfZ1C7@j$52jG%Mt-&Yxdll_|>a@Naxkq)HLPLtsGijHZd_l+9IomG|FIQ=(GI?N@xp9!LdL9B!t9$I2?=UMLH(YS&g(}2@0~uaKcHVE zqvh^=fCR`W|H#ReZK||~F9fW2MPP?hsV>54uBoXh2E`dvo`1RWqt;89pOJEU{+x4E zxDQgabYmA%Quymj<^Bfq))*4%_~c}F*fzrC-VYQ~fa0V`xZQErh#Wbxso?6QV_(T8 zNC7w?ssp&Dm21NT%M3!liV}~Dhi4noll#+sn^aU(hF0HQgblO>;n#R7a1EAvix^zV z_=R6U;578Ti5t=+CAjmAC>@SL>PzHCfX{<;x1V8?cH~Wu`T{v|6YiNX+G<5C2u9sM zB=Y8rxyg%>2p|{Vs+>e>fww{lT@JY9TySpfb^5~!Hw^Q7MJ6ku9GdQ)rz%#!duo?|pia&qzz>${UgWJk)Cw(tOm6^)toZF)n|8t!vC3XcJ=*P*HU#ZGEak9-l~ipeQkO)XK={ zAv(@{%Sqmgi}!Iri~-4VdYn3S@zSOCc)0^9^($X6I9-OI8H0mMU~fn+xJ0BO9CyTg ziN)baD-se!;M+Df4=?b3Lj1v1tK;MdCk0qAZ<@}cT!vL(y1}Nko_!7d zPsj^B!XzY{UsHMPY~JLAE;)P^xa3>@ue}c;c(Oq0c40|pf(sihoiEiCT zUFYNV-3V3nVpX3$Q2<>w0W7T0W7*y1R{N|&2+_Z(6oNQR!yskDM6s;alXeu!J{gh`{Wapq5G9OItM z!fCz)Yo_fq)Kylt8EX(ytvurEyOU_Q4KX~ct#IA6#Z2n*6^{JZhs|5vVgsC*yL$D% zLMpwLf`WqcxF6wnjqCiCCV%xL18S(NYrSCbh}0_$O{}evz-bTwEC~|yz=bXQ+^Kk) zaRtITspf>I&MRaU5}3SO2}vm92oT4u`n^iiOY<(DLaAaL*<{v9VX9Xq=2bPw0hJNX z%Z-C{!C6SU`{1us31u-|jFpUGFA-mm9~kj0l@$t5Qu=QZ)V zA|t=WE54q1RQm(Qq1g{ywwU6GG6D2a2>jaF*_uHrB3_P+40id^8&%8-pkxOHc-i^$f^ z)iU(1+2?m6GYiD+z8A+F;A9}Clx*F$jgaiyZIKNiw6~}mw?}`e!WsY~;3iYHzD>wz9f3OLezS%#p#RyXfj#rv9H_WV!cJmnTTIwWr6r=z5b% z>#u3j*-WvmQnKwiaUBFv?1kF7c@*DTgZIYs8e3Y*VPNA!I6&*@=!htt=2olw*6;2O z{KO3d7CHF&{j7UF2N%Bq-g;M#T5c%u)jrnzd-*ZR{<)7Q0c*uuW&0AC7RnmJ*AzfR z@|9e5)8orr^C9r^foZZ4N^Jim7t9v1MykV9nNAd-?_7<^1`T=tG6%6 z&AcXNatHSH^)Xc;>94)7XJW!bFwc_p3Ykj2F>?cj4^`eD^ZdRf8)5lK2-U$Ulm%TK ze|+0`%EjKm%t=E}v%-jm^SldOU0vCv6ao*QaM&xOe3M^sk3M7h%4OrC$(piwKzR@x4TW2`4h_Ee)xBn5B@-Q|ps;u6E`3fB8;O@P#ha1s-@m^~ zd06*uVoPp#_#gOHeJf;t@aN_3EsqvH_$v=37ZkurHHSlHgKvj2A9&!1N&atACKT7MMeA@VSwi+Dlv3nvB#ZmOxRrDkBzN}bKQB7hwHd%@}2(a9+x>LRNUUB~mCUJ9AF#aUKGEm_1!)}5zJ zKbze6B1dMxn6i3V!i2nAaF0bQEl^9O{V(S)<^TBc!#g106hJzJ7a-1l@R2X?>3P}4 z;`?ythQdL39Qa6<@t>P$ck269^oUr0_cA_o&ORkwwqjRwTwfJA7rnk$Pp?1oo zZB?u5*FA}(A6q?HI$*x9bPLWk4WQXZ+@qLuV*saYcrzIzXNL2`DG*(O;Fjy`KPBto z5;F~crI301p-OSp2nJZM%N#wLf&TF|C=iU>PHikxbM7DBNW`UZ;llK04-diDsa6LI zT@_A}p-NKW=3%|@!o<*!Fv*a;eEC`26$R>>rlzHU4+vw4hKAGlFgZE7+n98jJ6!Ym zvujk;)kl{ne=j*6JfMDcz_*?~Yl-7dM_dIOS zxOjQv^+slv9PP%MPwlTTdAq*utFd?w2@*neO-&663DQah)X_|L>OoBAkdY~_w3d$6 zUwir(Hf)5Y7-AXS=9~KwOVDH3x zoZli$M{@RB2DPNxl{WqjZ2zf3)#xn*bj`QUA57y(xA9wG^|)#CR(+>=x}xQA{!8B^ zVCqbu@SU0F^e_ZXhaU%#=P@yDgccmZ%#&N4LNGh+M_I>doOsS@Jyzi$-QK-rEiJSV z7}1Q}7Q5ol&aM)qZQ-B3Q|LU-r)(D59HXSrG} z8KxIm#BH|11r*`O_cOd`AOR^yN{4xngi$VF%a4`A!M9LSoisAy%(ELSTQ*M$fd{~q zT$@uvT35d{Q_Xy$TSu}}48uKWQ4=y^fMrnZ=39mUbA(q=@LAXOhUSvi-rn~1ux=r8 zA`gP{-3Zr1-|P~RD;gLWG{&2w#PX41V`Qv;;6QTc-U!8P$kPvHgEK<#7l5CVF$@PY zZp!bBIBq3iot&Jw^AsIjW8A52WFU@v;hSQy7bHZZk9zA;cvn<9B zdTVLC$_f8@;%>mJ`ncSM!Qjt@3^${?@P@g-J_!jX!c|%LOKa;McCy`;{ptxc#eKD*=MqREv|T>SCl$FjLUE;r!mrrs@koQvyCr7#jzB;jW! zMU}ddh5EF0V7?Sl3<1E~|17#CF&R0R|KQh(ipI8%8wYo*?O`E_?EYS|DeXt$z=jpQ zpd9a>f$aYBA7KHl^%GBMe2hIkJrC`-Pr`fD%C=->VP(~JnZ)!-a^_>?V9H@yjyO0S zpZ2cx+W!$(X{HTJ^hGE(w7{edSaR+&No5U#Cju8hy&fMl^JWTH z;d6|dSJ9Vm!>ors_(UQy5SWMATsVEUSzZ<;CraE!P_~+|p^5P%eBy9gBFdD6D@pG` zP=wRS)eI}a!hp$C3}YCeyc7l{Tbrq|s@5N0P+y*KFtQp`NR>G1^EYb zayvUaWpyKU{*SBgj;Ffs|33&>86kFrHVb+I&$OSbtlfjQR;qurG{L1%QYnmPht+`GuIVko+ZeMxf zCcowuc%l-RKQ`LkcdPpdZS7vyv+kUr$lohieRK!jaU_RV`)}jfikvQXP5T;=2EcGT zMxsgrwI}Iy__yww6}X}KIhHgqKv&t{TBumcVQ;@nUG~(;W{Rfiomh{}jO*rG=Ql5W zdU5XEc7)jxOELZVb2hYan8J!kNH7ALB_8}x{O}jyzt^iOt2^l{}sy$z>0@gNFJl@ z0kCY&EIj}xU|{8~DYqq9aGgKfwn%rGY^em(8yxG5BnY0@zYcXn*Sh7*F-dM4lwTx& zsbf!d&;+owl4Z{NN}?NWoRsLUb@1Dt0u!?PKe%dfcHU?FghAfoZG$I$zz=)+v zzHe}atpuvBNxjj*jW~ZDCqsl9{eer z3ww=<3xh{VY**kto%6YeBXQQMY)-O!R8Zg^Q9lmT{t@2oEXhQEsh(H|nm0q}%HsrS9S4+c2Z zp-mxyJjlwoodgRUil6s!UW34wK{zFnF}y*6debHH`PkW+an;~7?Hg?1pENX5zIAuM ze}ATGBbBqQySushki)l-Ww6_9=bZLH{BbV64IXl%KVHXmq;q6~dW_)-ToRNg|NPQ} zSceZ7@TZn%&*>kWg`U=PWwC(!7=>YhhYWdh2AnK%tPxl1K$E%M}!A@eEiVW%EfjZ zs1Zqdv!4-;MW7p)m#!lscVOW0?5Ixw$2Xgf?R(|q3CdNp3+W=CD*v>)qQH)#)z#r? zjT5-A?%7UsF?r73TF@c`M@Hz8j?CMT_b?9lzw)=S5f1DB%3u63@6+iRohe@(H+f(w z{w*arIRKfj#Hu5a05?BFx{u0cb{!oZ+?4xJl4Bg84x2Z#%Z4W~`~{p?w7MjzOoEMO zKaoCSWhIPNk6#rOEq1W+*T=L5ah}wPAFq)O$^l?ERG=Ki6oFoX#LG^kf1uq&;NS_> zRj0c>Xfp}d%11x3r$GUo^p99M6F3^@$`yNy5+0KhzmL+@JEw;|87KG zu*p5p><5Z@TlD<1YC!CS5)%`lk`Kl>xX9wsiVpDo4Meu zByiC)=TcvZ%yGk$Cqh3sInAh)((1mo_G2zXn6vDb=p>+PW^;cT{jsfWab1wQw$0lg zIbG4#_9}0Rn+t%Wrswnk8!U?{LT#J}^|Cg;DHW?2++(e<(K>MF(vqY7ZwS$X^HVrM z%*%4_so;L{B;F?84md7s?J_T)KcovhE1Vb^6Yh_g_G2uegI+ITj*f8ON0BMh#+DcJ z8OJ|i>JD>|e!STEa_W*g4gpvP_rNNU2xh^{x_$R99RbGTy^wl(dud?)i_?^!NPWY7 z4jac1JmUXGp-(^b)LJ_%5zbGLJs@gt9l&hD27kP>m<}B%4i3Uqk{Ce2rp$2V#yflg zw0%T3CakI|xM}xAt81Mnc?6Z5NeEAKPZUBdhpp+Or%$)S65r%SLkS#|h+skN_=6}M zkhyM+v_arJMA-x~2~hyR3lyGvTmHIDUzjoi-Q?;&T~1VXkz&+GxeEh@uyg zkx`5b_qvN21iyq{tKc%H#?KtwS>|Qe_7eGDxS54P>_M&6VC#8f6+{VQBt&?*@ZObH zmywYH9?mFpJi7)6A2BJ!v1kr|bsUC-&%IzzCrYq@J9SA0JZc(zA8m|{Xx@w&P$zp4 zxxml|u#mu}V48gkIef(I1ERcV)Z(Ad0Uz)wo@Yh$5y71Lvog0D{1tFDMuukO)9|cZ zsnLd$s>zEXY9!htoce_LK@?=FJx-k!SZq2@+BjrkOTq*U}`8ntN^Gb zTD-I8*#f9O#``6?g+XhlP#QTooM}}O%~GeizU}jJRdD)Y<1|=1I8CtD5G$D%bL)0T zDQG?4zHP+tN%P1NRs@c7Vx9q*n|~U3O$6Zfx(K^N`Ul|UjA;UfUV(T($UO-0b-iBS zPmt8^@4m$E|4J?vgu}<_>GiHQzpjA#&A+m8>EgvnLZ?N{>R^Gwe8JIC3#)$A9p0Wq z#|~{UGir+r3dMMYr-~TRV&h`4*^89dkT+x+;lb{|3;+wHeftA1>BY)cVp3ZZS@1vP z2F|c+FanOf%V}?Qa*F!&$r`V7=RUQid_4H%sb%mwdd7;J2_EXJ?l(-BfJj}c~Dlx_Me8KF}(WbW=2D`qo#ga=&_EVnt*>u!OFSUPlMt2bfc!4<)9WMD!Y(Kw8gJR|way`1M@IcZ)s< zn`U112KnPL_>17jHt0jVasK^%8jO^1Y5}tm!S)1AaakFa6I6cnOen(ix{vbu2LgR!V6dml3ulj!h4sGEA{r{o<4_Usy?-!@mS zT*kz7*=OI}kVcS=PAurk(a~QVSL&};UZ=-=f>SSZZL}IjfH0$>MW84Yz6@$hql(1* zt!T3Au(ak+IR3L9&$h^Pu>i-3$SK9x{g+@MN3rLt@`t$P&9W^($W9W&VS-Cz=1R;h zG>5r`vCAhGyRwcG>Mn;`{L-cqSE!{4ubiy^MvIv&+Zkzi?KR%`mjfrZIB2Wkv;I7>=qY}681@x>^iR*T@SD5-&PC<8 zsO;IplVcfHE@fi;haoxHHu~Yomuwn$w;pJvCfxVr14-Tb{8t#UmFUVTMrX&wd{J_) zVAr(f=~q!#S6{|_8fcjIU+=l`2*P(@%NCvIepBMNCeTvsGDDMhBGY7|9Vk~-YpZFO z!rJIC_|p*23mGN^*FvXbD@W@WU_k$Pk?yl!dMeEqHKwQ^zrRulyG4CgJU7hKuetZ> zTnS|XSA6+!dNYy6lkSEPm9>nFL>{FLg4kY!r#pjxVLpe$9+-x|OJuV3hN2SVB|6i% zhu%l~)XxO3)7LuMM80|%cKR;U10EN@*@QiL!q@)I_r{sh^P%x~NOLbHrWB-yypmyYn`_k_7o7Ilgl6klP$Z!M(cv$XJ zhCX_utT|>>SaM*sZE5<@*jNR#-0dEt=F0>N0EX+kuJ1QD#Q+M&F)BN~_|)X& zh|u+O{vX@Gm5gR|x#ZX7wYto_+i5i9ss4wG!4XjjiH!j62~5PrMzX|xI%vNk4FrL} z-~tRKD`1hA>y)sCnYmeno4I$O5U!eZ-JB)9ZA!ZlZ$$iBj%M>CS^kR5EYT-S*4Un2?9?9~VBE05nY29Fb!PwT@lFj80Io|M zAsKvNrd+fsF|u=X%<`xmC3GAl!fc1IY6Fs3hY4rJ;Pe!7W6;F$AeeYRJk_@zjSnH( zNl5&gGJge1OWiQ-_FIy}Fsn()t|eo3yF#9=6lb)AOAwhosvN$(5#iyFkj@c+fT0T) zE+m7ZjFXCK(N;r#f zlLoaVL0$!rPPA!Xvrn_Y_SOqSTU<$BA-Um44u^I8mx8Q47>W_6m4S}VgN7zQVb>#C zT8xk`T(AG~tgRqC;*!GIwbSwi+6vq}rB&TzcAYa_$LhR@3l+A+pYX+F??75Yh59uShu3_V6fdpVIr72wrl_ch?OYhESqh`*U_SFSkgE zWU?F=^nxPYdBh-2Df{TkiaMwy!Kj(vD&N#hy((s1iwl|{udZD~8|nrSn(^w~nCw&0 zKQRxz3lEUVii%6#8&*R9NJ@DH_VjR~Sy1R#L2NiG_lkyw5SPtZSHD@-uHBD=8`b$u z^cyxaL!bXdYC}QBIXX7BCGzyO#y5Py9EZw0oGTiwtFa|#MZY&%_&8}pw;oTIhQWL{oU{-DMAt@v}4g~m#n zayFrDt`{w@scfC-HmD^_S$pqDNB4*^f$UQwp^2**^SP&jb`T$&30N9AbhllI0buXw zvYcLMh^XiHZgq{Hd{OC4dU_Ijw}`$lHZ_g(T~djT^+mJ1nGh$k%)o|J^P<6KAsm^?V;IfG*$ljhUe1RNb$(Xd{1LuVraT))2WqNJZ?aq zQuW$w2ZP9>ilF-3SMk~be^BwJ&n*|34L%w=7hefBPJom!%cZ`hs*3YkS#~@iaj3>} zFL!IJcyWDDGC*sD$3_?z|9cf!rXk*#wP_HLUu2S=o~;6#ktubLv#=R?(ra5^cORLa zhq_5tO>zB++FGu9xXm=!@VEX&1D%Rl%l18cg28b^z_g|6U$~ILA?|!`Zti|G)Pw?a z@7Cu+Y+j7Qlo8kq)F4f6<6!vaQW^#ZLG#1f+&bsaUyHCE`_8^W@vfvyaxOC?J44Us zRLMFo^xZ&#gFvbOcUC~pW+aawp_ut^%i6|V()6?!ob69b+Q-W?vXU4p;uI8G>!IsI zzowm$E-^o&YIgavL87ieziaVOce#3)y~%f2L4(1;pq9iAbe^;y_V3V=8W|hYk^lhh z#|R%Z$X^=^&R}t$?E|NF9;83M!S({SHQWD>3()Ra+2q8p91x<}JMFGr_O+!&>y?w5 z>tU@Y`e+R>fA8z7;u~~9%MV68e7LNnHvW^qi45Bj=^=;(Y|o3w^vZXN779t(bWzGs z7!K-Q=Ses{w$}fZ5U9P=$YYNEZ7P7i`Ew}hDjY;1$;dQJ&pn%y8c-?Ph^+tLcXPzl7;4TtN=+sf;!n!d0C71Uj9e33ovG#_EJD*?U1eBjD1nqr zX=%Q>9zIp?ox~Odk0tw=DIlSh|iIHwQ3`6ZtZDb| zxgL2ca6hre9*J;7s5wr&XIKAAzLsQ_qr$Hp2 z0xc&0wc6SzJ`cboq-^<*9_mhAfx)SrkgM&1ERy#ar{>wQKfiV<`7VAxIp{m{`5@OG z9|P+kHDo2Ee1P3GmPd z7_RMsQ^9gqsnSqC-6b|@eZQe=C;6LMn4yt>BxHPiW?a-5>J28$VDGv_!h8d|j|5=5 z9J?*bmX&R6R&&030iwl_EV$t?yJpChiycLrk9Io|^&9b0QM%Uwt7o&RZ%TXGXKKWG z^7rtI_*)r)CrZ6({PDQ?c&J;L$&>s0?t`glar!i#P|U`HMUjYDP;)UW**`zQe%S@= zMBAQG}eps@`@8%oH7+n5 zAe=w8#eKAq)(nw7UHoEQeH7VfvT(GaDDyD`!_RE zAC!7q14YI!^EBq-p?14%-9n#p>y~(=;*SckpIU$>BDjD6fHz*ZxBBJ^vsh|2A>(f7 z_?|)?ENBAS#Ru3?yR@DunidC?*Fg~RQp6wbz9bDd0}Y%h$S^hPn-5Ain2P@!CA?#I zs-3~;JZ_A;F*jV2lTDTxbK`m$;&Ia;ij%mdM~UAyiWw)Nxak*QVUYlP-k*4dCtiEI z)7jWKSpHT&+rXiH-~cGL!9gZBGStA5`tO6+0H0m#`2J3r!N>}z4p;peO_5a$#1zz1PLT2{VZ4Vqd)T9l&0!n>aH9ImNmDYm%S7d!m66%4x^2Bu+82RH*QAU}&EG{q?zE$gPLR(o@K& zkqfqnXgA`;x=c0lEEiqd>(uoowD}H~*Fh-mQ}(}?ljYd%E=~LN=)J4lDLr^d;FJ=u zVyK`2aH+RH&xQ|u3ix$aTTp-aE1Ljm6=8M8!lX${94}JG9;atYb^FVH_nUrNqkwme z$dN<{e0hK#wwywCHCXwz=A?^lPLhi=)=qSgOssq5G^TCRQeVKkA}Am*2@_Ak(`2JP zk*U10@(P9s*lgNwQFgMxFOCIJQBCATk$V^nOm>z1D4{{=Z0WgZGIonPr>N*MR?8CF zk9#jg)k3$_h@IE?GSD9lSJxLcF8Uvy^6eRyCkceQtrckm!Q&Dh30tyZ1@thVIl**H zwfx@!YUDgHFo3YAqME6OVD>3WMhK3r9}6BMH*Yhoe_XkebHuCn_c6q!Y@&B){%glr z?La0G`LcS4LZneWWyYaB>5EcdwTf4~*nW6u<)+3_}BmcvlN{=mC!jH7NGWb z?20ildvQO6qvEyW@zDoLMo;F+C_?YauU>xbwcd;M(PGoXU14~6_lTGG4XOeTAt8B} z`1&tZ?RmosiK4WLmwwt2=(r<%QZr+lZHG zlY4@j+UAj_Ig3G`gha8cX=L=!y<=l+m|h3m`DcM;q+@7mTFbiekw(4US*!AJo(AoE z=O7qR0=Lf4Cud%Lw1VbIgJfizNijWrJ3qI$y9LA?Xd^TILo;?;2gP!8@$)kSRea#a zu+AcsfoY;2n2N7nr4bf94 z?}di)EY2*L!O_p;^YY5^ijS8wJH22KP>DD1*IAvbFp_cy8i4&&xpV_Q<{JPbmkY^qaB^A^Cn+}_Z&qHt33k9EXeXWft zN+(8}yodgoAsM0z3v!5vR)3q&hMN)!k1FWn{Qnu8YMVR&kSXidsj%JfvAFgY-_A1C zRcK53rKN-FuS0oO)5?>hsF=0=MD3&(1Ya&L#`R-k{{)k;XS-BgrT!KGLokTLjq#99 z+rTj0^s%217+I8KLz1$OsVfcQ5~HzFttBB@^y>ZYWK6=T5=A? zjAILKnf-Y92LY!bfw6#-g(}{PNqEor_%?S7ajwcPKM51lf;C5Uw0Sf{r4SEF)iC_T zTkMAFpIJyq2*xu^x5NLfj~hFIaS-;{!=BC;W#5R3t~sJ@(j4;jxy!{rXD?7FyqjS% z5LTI;t^3TnmdxaTZ*_IYAd#(6btCy?L=aip6f+)TR^=9XuhlL$mrwGDuqb6a*C91f zPo1X+wjl>5oR0>>Dd6EO|M#I=xk7U>wte7cHoug*zsj9zQgHK?Ls0oveQC30_Rz5E z+x%wB>inA{zsp-57My5KV#7<_KzuhrQIcK!ms-?HgQR=l8qs?PeJm}X3=Y8h&7mX%xItf!#UVs7xC-@_6UmDqLA~@6^-1y{`)zmvBA>O*o1^%9}LU0*(`S-6xFe z_4Su3>gqHquu{)_`z8fXe=TiofjH%>Fu5bt$}KG|2#xu-j#}aIC`QQ0GW$Oo8|VK1 zbB^#Oyel6qynQQ!Wx~Fob>wB5?gm|w{}ZkbZ8pbN=KAiD1{}J{mFVFC}QRa*f8Mc{k zwi?_ti=MCq9VK+NsVPKH@7NH()VFU+&VxtK>BtV0V-YJwbzy zA8OeLKf(={^13Bn;6hera#W_2-^P91$uI5tJK`);$_fjG=Y%@&-JTwiGFvW>yX~*B zZ5uNWb)v4mf6(9mu;naSUWDf89w%MF4WZgZn<~AFu2q%zVgwEdn#=8d+3-ORpgYb4 z|IEf;A0A1xzkVgu*Z=Es)h>kA6Zwud3e*$A|GwKh#PNy092>0sWVoiT28P0vm()!= z)*O^LdgDum(f#kKjQe(7l=QqQB6qUqeR`7S@zbS~?WH%?v=uch65v`n>Meu)pH&PKYy(cdTTN<5VP(Aei3|6s~0| zR!$vS_I?~c+UIyS`K%{C{?4Bx11izF*mDOjw&!XfLyGvvWIe$|#>*!TocDVPP2EW{|iX5y%)UrmTEoKn3%8 z@NqU!7e12L9R6=t@A`lt8DaXC*}r#TVID--!`-|Ek9yV zUsq9KGnnAB%vYJ0#}iw<)T>n#6!bQJ8d?>tW5-@rjUO`MW}&)w!l5Q$`$jU;@87$0 zy36$by$6@MaZUjhC4s$rU+me|3}y!g1B4IH|5Y>kPbidIxQDbrTp5nf`k2@|mvx-} zh|UwfQ;Lf7*B0&b`lx}gYN>;nne$z38>G_m-*`NGY)VBDa9=L9-wRBCrrpjqeF60x7_Sv!7`@})$wGO1 z@#4jwg(3@6%U+#+3rHbr{^7O2wO&=ldEj#@B~r6h+w#~K<1p&!g!mrsC6CNO&#u?O zjG>{w%I4a-x*GwhpPc&}#3~GRE)cHi(JyG} z1YH(qEOf=`cMNU>>AS6M19A9BZv0o-wK8OxJ%>Z+^CyvZpwp~}@@?Q3)BRzxre$f> zjBUMD|Iam1lg`h|Jo65_8qS(vhI`Jtq-BAgi)nS@&o9>>Zr#sMxt>}Ea>AtlXt!LO zZ^%#U-ttHYeR;tV79*~8+xFaUnvfeTI@-*4b^r8^sc!P~)BDx53x?lNg?~bEMDxGp zc_}3=Er@tA;&;vnt&NJR=d!elA;rKJ1I%t zy|dAQ;oLLVP2OmCq)Q=7`0AMIG8UK}syNTu;&D0jRroxdn zm&M-d!yjE|zbS^RTv_{7*`q>CMc~fd?hQ`X7eXvH&aR{Q7{7Sgi-e`{PK%&{L0)bv zH^bY_b8lrND(%DZm&ZbKfo1Q{A^KU_-dVpmr7^ffof?7M2` zyghbygi%aRF6iTlzQN$fgCEZ|eS71jc(U+frU`G#3md#uDM`r+5OL2o{q82yUvb|= zSW|P~OI+n*T*rFQ!Xl)z7%wjv(pvtV7lil!Z>f*L^2TMdM}tT}hQ~=-lNXe_E(arf z{=9$i$@uyGJID54*(pFrm&Ut%ijUvsPZKa}$z`^mZ+L8C~cbt}x zlVJRgI7u=itKo&!ypXla9Lr1aqn!%*ya5kV=N(NJOAh~^Sz9jZceqez3LJMRkNv4jqW-ALl>Tv zIMWO!sYtoMu?=LHFS~4cq#*wW^Y^DMUPQBVWnqV3$rYyG%!M=2b|VFj=AG&6SALGN zIpc^=5>!8vGG=0gjZq7}iH!J$=#+WM{B>_JKE(VLcbAGMory`yxh4@&YYf&H>;`F= zc~;axRf|`0xvoS0@2ueNCR0@z*!acWnpTys<}M9<*l}82cprbDg~g|j--=sO$muuP zdUtrpIw3XTx0xA=IMRN7**fD>r&KK8@RhS~x>;9J@~iB;=7F1?-SwG!_s+vt@w_ED z&zu#4EyNVZDX)*-VLqRu1(T+5@awQ%9?ohm{r%-5YM{*{BRx#}cf3HyfikKVK+3hM zq=o4Y$-&i3>|azU=e>L8vNyqK>?}-iGf0a4KJiAfyg_%Sqjb|sd;)QY*>pD7tQlVq zy&=o0xRxp#+xv-c>kW8i{ol3cT{zZcvm_rU59Z$a&p1_{uFP&2-y+`drVc{JUuv>q z6jq#VoRDroE}!~-FV$)29a$-q66Q0ff>q@V3#oVU2y7+BmBeYtF;y-9?_@K5fj!%c zD$?-Y=X!Nzb)nRCf>o()Ip@y2li$Im3QyPDD@%I5hE}tMJ>-$BobAb4jAnAWBIv>H zJDm&iaU1BViIE!mmT&(cds=o2eXypMp5W5o&b^*L%H^k*+12JrsF0<;l!i8j;R+x` zAf9slLO_%1E2^px;i4_BXZY#7r{@vvGiPGod%@WR8s;jHjczdgcN?y$0E-P3%H6#Z zB4TuZgW1KTvgYS@agij1RQAukqNk3?pNUa=b@kB~It(wm`vdMO>CSB|i(*_~aD7LX$7C8hSInRxjA*t!n#!`c9h!lAaDr2ie!A%_vQOGw8xwY2c=Mclj6(hU@@ zQ2pK-{@q`mb(<>p$7ayXsgBVJ%X1b%{cYmx0w>iYT=7&kr~j6-Q`Xx#Hhh472d- zV4gvNNdLd~MLYpYD-eN*865)J4<}sx{rih?)ZDIJwGPV4*D&oprz0+XFDQU!H+Cm- z#%;eBIJQHd%%!NPm*BHf%QE`fokeeX`F8AGvFQ?U66-PLII}T2G^T1ZwV)H$4o1TL zQfDW+!XD>z6WM+cioL%st#Lb?$!-h*LB8YlY z7NTsh@$T)*e*S|5PdRx!3h(ae!M0pG10nbi7>;)$ewmP;d{{{SFO!?{0H!jP-@ctl zjyP66-X%!0Ze8xn+>B)_ZRTb}qsl8XGTQGG!qy*q`q=00*4nz4fBu|J>@ILT4k_1- zM+?RUl~rW9LhS7aSu2+=#es-vNwkkGD@zhReKx@}Gsj&A{V=^C&?8Wq{%=8W$AMXj zvyEV~U~P;qkG194ez_+@E1pU*&KErTH2%7myBKe%Rrgc2Y~O_~M~^(9J?-vZJP6h! z;iQKFCa17Sv<=S0G(xhsJnxd(Us4kB>G}7IxSNdtQ~UIcuPV5@DgJCqfWr=Kz?s1m z_+KHzDYX^K6fncU+LTj3<*DMgY~JfuK0RAo=-4K$AZQwd>Og>%tu`y1>YL*;K4sf^ zD=cvNpk}L{#YuiY74jJ;12Wtu3I3N+>H%aK8?)}2d!7b9lGL=+>*r&}8JYIz`a($i zfs-sus|#;;PVFp4#ZTB%fSU4uee{$2@X;wMDk7+yo~z4Vp)LTgAd2Zl*_R%iGJ&wcZ+aARf?AW|o$oJ{!r| zsbgn87K6%5(UiM)71~>Q*e%Or_Zq-yiC~8SuR+QGLg-+s=*u0D}kGb&w8?_@s|F*jEFpityhLf`lhW_*VRZNB)$s{qOTr5uDP}F z^O-ESt~hhSr%Yypt~Zrd$B%1o-SRd*9pxsX&MUuuHA9ouh{BckWZAXi_pOlV$_G=V zPu=8Tl9H2K7t9`22Qm(7R;Vxlm3#&v{r_I|+gPx<5b$M%@l;4yn2f?|c27AZL-~LO zCyQ{n!OblK0-eS;Wwutr#%`{;?(@zeJnaJaDeTHDVJ8a?O{4u~^>D8ZYcY8+4GaWu z*g9|~(XB{DsjfOc056x&i5b_Av?^-FZBrz0BY3A&j{i{QkzRat;WI5r?B_ox{RbFX zI5K#PA6h=+p`}N}zWDPwwSi*2snU4N zW$#vom4t*}yeot@ZFu+=)*fQZGcIBuoCBC5@AigF{bgwMnM0C|Q`PUuv%~hw zbz+2bbEGxnx*qrQ=Znefv>TQ9_-_HE(3N~4}#^yN~{}G%aZilEpL$i)EZXR{_>^{bz4NP(UGu_+sD~R5%so_~Vjelh1x}(6# zFg#_7iOg8WTik*?b3)yb*^k_*-27z|Y)AKFN00J%cB)k&$?Inm2yB&vQ3(V~84y0* zjwIgajac4IVc)lHGZhSc;`y^bu)U{;5@~b}hM{3R%XjaFl|O$5VF^HS9^Pe~Kqs@8 z>>V74jEMP}V+*sPxJ+^(M}HJ}z0uturCG&5zqZ16spr~AY$p~+iIUf!Cz_X^ahOV= z)Z>bbjBNPu;oiQkR})t)#tcl}8XrqS#t04Qs!#s=*I@zx^BmFt8Vm|^9;~4ZWMs~6 zd3Sk5*Hp_?k7a3el*41*+4LZ13yzFjtV4p$jz#r-?ZJ(}Ta$3~m8R+|xJ~aIE$)`Fw<7GW$C^*sN?7j}g!FBW^@=ZVdMJF6by9JRr}xJsiL_y zOHUr&o1-z@=K7BqUiz(2_L)W8n;l@Y*=BiQczRGbEG*F6l&2(uzw%lIiLda2k^Ni* z6KhQ+r{_7E^0VG(mS_C)}e z_cr)^PQpROYln1sffth(1@VHCxpaZa#v4JL$vvFAAO6v zd)7Xii0Fj)@Kf8ityR6UR^F-8U%T;U!~h+GRaLaur_3JO!ABXAMG=BwyjnM{hCo^$ zD#&{IbLhf6b*}vO&p|EyQ=5iMN;tCK`b}HhNs7YL{dxZE{?{6GtX;V@(!;~FTUL(; zGp)ZZAjme6Q+_ibi2h_tmB(gS?6l|GulE@5427PKs~<*01ow3cw9aZcF6COF{({3i zlNxn-+SrYUhigOd=GPvTUhnzB9ljiRe8c3F__=e|U*FzU;@_P8X&EDyN@&;_u6@$p z#m7S3MV!cmm%B0I(AQ`D@tQ1$@luKQb(Rfg{mp5+T=&q@`V;g9Okh5J9SBq+I(u0~ z1y20@{e9KJo-0F~u3x@H-;KQ)WpO%YlgjJwTLjO?$USO$kQMQ9f}gF zu4z1+k)#=M5C5(na@0XLX*i^}H1}9n+heu_^r;#-a%SH1=ectlrw=k>;c2|q2xNYD^7DAf>o`Ysx@dFO?_2bwmo>sg zz2(n@ORTO=-rvb&$v|J3;qF+eXmT?nLy~B~a7t;yqc_wA<3oaIj-hZsaf0kzFCzY?BX4RThE@YSe>*!@-n|BDfNKH!KT11qNJifqZ`#$M&xlnOYJ0Md_pYN z7J9$6hfF@>{OW}n!ENz=`D~{jWw1NQBi7x`(b2P>-hS7E*$rfNlEF4MCxUr?&DTZY z8ZQw_dkQytOeD3TT!S(Aibuh4+BTp{%GG5^4>zUSz zvw{q-*Zio1bhBmYb&r)r%@q@eXTe=vO1pe^@968d-sQV*-_eIR7{Oz_CA~>^m{P)wyF<@*Xp&r_=%xM z4^w7CIEVH*^73E(ZOj=h6aK3u)9_2P=FyYjQjsr0_Yg-)8E-!wMu4IHknLvBX6>Nm)w?J0u; zEus8JF<=tL^P$vxRuh6bLM7u&Z+3Q~+>H?ktCEtF0HjJ>!XmBOKsC&NPeftt(Qw=< zFVS4K4(em#^w1RVPgX#dR~4Bp79g5iLAm*}n`cS~P={tXK~u@u*;yy7c4n0kWJOc> zPSK<4;r(~!F-c+Ti}=j-)g_TdM?P%2@=#@C>eYz@UpA`>8yiLYlxd3wOuXvuYs@L9 zB^_|;KJ#pdofOrS7!**vcjn>l=P^lImpCD;Sv^z8I{Uq#I{&4eQMvCDm)r0w$KXZC z8J}6ID}8I{-rTll*YjKf_M?f~LzRI;JI^tnTqj6rDYnNigoA_UwZ9j8^B4q`Q>yEQ zwCZcty#4%n?cC&kgjYE9I44i_VerpdG3doVR#hC z$Zpe~Yke<1TvrL#q7~>-&_{)~xHyh%{M43H#Ga?UM*F~GRkbbGix)r3MM0_lXGQ^s z*#BDiWbU5>eGm~Al>3-suon8M-XE8@+ zhSlRc^kYxzqk2`WNXAL(jHHZ=EZg^8r9&$24tZX1zKmj#Io{V?;_k0~{nXN5k@3Hm z-YbzeKQwK5suMeNJm)qCpi6W2vD9wgCIO2dZ#D)*M&>3eq}Egy4NF6r10que)CspO z8xwi4sA~Y=PJY-!B;cmvl%9kIBY-spOrc&DTY8C->`vQ3vAcBIpkv zZZ$olL9<%qC#asN9>u!1oZOXHSa=hK`AL($n-kim0jd%Xxp+f|5ieYWWY|+QUpQL* zG&CLoURoP;YZY~TEneOUV)#ZmcW1MDU1FK9i{G~$GnR#{FE4lBY@PXic*BZ(_L zGi@2i*~O^ysWtISXU>GMFlo%?6x+q^yoyZ4ikoaC|J8SKGWp)>zo+`CJS*i346$FH zn(D@GQuYwuyN^F%tHHLygMli=zke$!*=SpT79y!ZS<0nD?&;n<@8Q^1<*+zYW$Pj$ zf}{6PvTFJb-d_{!F?aNE@9CGgXIhcp&chwLQT7$s{ zsc)R*;v+cy61~c;TUDSkQrth6XW)*mgbhRl_r?D8xZF_o+GZvRy*TXkC1CjGDHoTa z0-rs+@q1I9Ka+=BGS{-Qp8cHUumweL27Fa4-gp`fduEwcTVH%OAFMBWXPde@qr}no zHQ)#s8VXaje!_4r1a(*na8TMO1a_TV0|)ElQJYcaRKKs-KXbCk(4pJ!#JGTxKTDPw zkDuxcbu~v@CaH7g%KZDJs8t!W{qGtw-h6gUd$#9t51fLiej;3zf4&&-?2~{0fsL1r z(WWtUJzv>5y`ZyF4ezx4Q^iP+U*D12EdT6GL=7W5bNSaDyJMGls~#6PhWQHq9tp!i z98;3Rk@Do)M~9AAInC_vZk%2DW@p&iqJ96-sXWU^!|3ak3H>oDg2Qt2k5I+IBCQ@3 zO)i9@@bxh@YJM>SGBETGM7IX0pNG3bVLQj}qeqKoX6(15rw)q)u!dou&Z`7vPJvBX zpZ22GC15H@Ck<^khj2;(IOKPLzrl{4$DrvO3nzs2B-}e1I;*Fno z>^|^a!B$vGvLXUn=zT{OU=|;rLauwJt3KWnxj3P*i6)E6M+1_kUy-F zYMECbK742zliwGrElP;1@pFe@T2wWd;5|taq|Vdntt{Vuc=uQ+Q>L^9R1}3ib2cf# zj6h&`_8k=GB5Y={H-BzgG?B=iw4@t@Py5CRUnSY$?$*`L4~ZEn7#Wl723K_tg+?pC zLYb-r?c#aoepQs5Cl8563(tHK8M=S}v7S`cG*9WxxInGELXp6)*+IQNszG9rLct%G z7l4rlcn=KxYCQeD)NdwZvi>df<|p)G-`8lXsQB`eKDlPNvgD2nDx3A)Pr1Aee=bIe z*Qjxp(s;L=x~-tRoD$3X&|~5ZeQ3-V*CE3Y6O-G~xBVNY2eV`kqAr1qfpAPF7QJ?5 zIT}g=Gl!|A0`%q=8oW+D*$Ur~_1R}iZ$T$0v+OUYD9;`VKhDW|A!44zOzAzt_ar|3 z?c4i{ZI(mDK6|#+H&Fdn1W|Vq)=SuH%;l<@CSUR&bvvc zlw>>>h8vEa%V_(~p96=<6@McO3Xthq6aYks}iquX=g{Y zDj&T6n#`*l@>5IMW+CZfaq4pwx%%doNL96~M|+o!7p6BaF3pY0y}D=Qj%^!Wce;d> z@sMgsM@x%AGCM?+#6zm_1lHCA2^geMR?z*r4?IWXb?IVvnILG}n((gSR+~6+nE5G` zI!)wNrnc{|7D$g7yzeDOruq3@cy(#hx}clVZ<32q=3zGPJlG`2+Ef1Aq#g^X8XrIe zQW)1?x+w5CIa%I9IOU|coE-1cUp8&4$Eljr=|>)1ho@*YEY$DZC8m(3#%-Tzv_*r$ zSSP}Wu^D+jdD0OzcKB5{nT!2*Lt6yGx96J=?2xl z%bsVqZe@Nbwhz&XpYji~r!jXNGDsAbSA1FHGPXF&v(K_1#%GJpf!GUzCZ>mdGH6=D zcdJkAgkdC!W96gz^&g7D!X(s92OtN>nSB*GC9vfQdbITQ-gW8{QXdFuJ4kcV1>VXk zYMT|YqFW;cC)ctwzN5BUY93&SU0kT_o9pi7;|qEAMkVMYc97yW%Q9BD-hq2&YI8Vc zI27j&(#chg>$OEWORiE+B15&{;E^N3@$n_1TeljHTOdampV0@0fL(qsWpUfxF-Se5 znm^w|r@gQwCb!!x)9qN2dj03Oca0_s4MmKND(9<%liQv!k$S$hX0`vw+R$uSR&!iL z4mFy?ODf(jh~3Fce+cpjK+{nM?%7Os@N@v zo_b`bTV z%RgslXM2DBLO8gYRDsJT0vowl4VBKVn+%;2NA?elv@s{#O}a}rhmL*q&$-?_4fT~Z zEXvB_>b}hKke2%WVPbe@9>BDD^QWCVpFNu|xU=9-!#C1roMM=G_u;L_A0D~%RI^XL zEK@_MORs{9P1@Opkf?*`sY(6}g8L-holaUjg2L(UV1kpE16+D-a9xL47?{96+WCgMxj%Q1*IPP$0k-QNU zWDNrnLm68iwUmw&r?T~CS^&jF4eHi6p~>ai&Svx>E-sG#^2E0ycgG~nX-pWy5Ob0Y zQ(rBrxiy{AwC&^#yW`p1en0BEHV>>U z_0NZI48hj?G5Ef+L4DPqvi~y2z`1iGzo%@``ZKwzlRh~%uPKSxbi89$PJM+t;@NY~ z$?1^4Y@`OObBejY|F+e60wgfQcj4}=ex3 zG}pf=bxf>XX|4A%9%5+7#cpuQ$?KgODmwQO)6^f>}F`u!VPro`gsk ztk!)_y&E0PDStH^R|uxtxz`q4{U!;4V#dht-oV)r1?N_Da=!f0etv6_Q6{gY6&?40 z$^Gmxe_D9(w#du<_?1`w%G51ZojE5}_X=r5DzkA(Rp8sm|jTqid zGVVz^bPu#VLa3QrRMBFAcMh%*+(m9M&|sdx(QOpMJ2(H~2d3 zLXPk7$Vhc9XY) z(l)$bY$mPp`BaK1wk9FV@dELS!!n(&9tXlI0~I{F)rNLmlJ<-YpQp-+e>N!;mP~8k zG6wdq*X3?!PfJsIv*^MOOC2q`58ks}yN}QtlE07ZbR@F=A?#S7bh}-08==M;^Aluh z7|pKHWL3^ zw~A7{Uc9`E`@!F5Zq@jLA4(bL(RPJ=$9nZs=!Kr}LvFYWcOTdT#C%+S!!lp+%j;;YrpVViDqbtXI@J` z3Nh}B>S4ELvh__)bjR4Y=Zb7D`#~znz%bhegVWK2+iq6|GTK7fh*5<&VG42k_H7W7 zP()3tT?`TG z35Smo%#nh(r>|b^>@3KdbnM@K$*SDVj%O>y7Z|aN^G{tBc4o~-MycB!>LaC3_pWC1 zJxj^Xo+)$*73dA**m$Gndg3NCrN4h%G&{(0Ew%7lnC$3-sbisUs6SFz#d zWpi9ePXjXSw~i>piH?F^vwPbPwJu_!2&eJG$)=k(&%>tCgJ^{Beg6D#d}5AzZcfs6 zFeNF;2-1Os-9qXj%OwPtlrsjhPF{D9YEP#^aoyvEb2yu^C6m9xDi}|WAKFQCwz@j2 zC;#NI)^zxWk)D-%y}3^l!VYXFZoZYE*`sIK+3(NnQbH-ek?YV-`?Q2#GvvXpM{94% z+!m;WT$2fZR9bdDZ< zLU$g84n80RtvLxq@q>pCCm?!fdrnl0e@zV!_tnMkrR&=*EQY${XfM~-HFh*JYxD7m z<%pfuHsGx2>m!IC`oaE(jZUrOzI$ia6en;B;Cfeqbt#Mr$j@?^l8HMOVW8g8$%)&r z`WC~#So+w!e(Xhd54bS zON;8jU8gh`;>w&>m&Ko?Sk${bc2;>>`G(HAy|3ST^2!<}i*Fc#O5n)ER`x3f0kx-2 z?XfwPmO%aVV>-*b(@l?*hR1s1oM&uV-leK{clb()iOC8iT>6keRJK`ALL$T-5QPBs z38`}md?I3d&1Pa)L*He->|^e+vuCsR3m+czp*Ox{;-NynsUi4^YU=}8F%on8H$3ie>dv~)saDK2<; zG`gZLEfY^eO4&h&^#G=1!qxyACVVJD#qq4z)u+P5g@E~;bxr!s1-h~WT>D6s1(%bb z%ZczRC=d+=UFObAn&*6c=AsswMS4G}V9ltz!P@HLnjoiNwf55f3hLX_IRc)wym49D z+^%$4BH7x44*%=+!w34`Zm3wK$PZq;m-GJFVc+#;?beTXE~{!p5EBl zh&1W+t5NRw8eF@i%yfEFLBUOBOPM)2FmH&A^7jf{$9v)Yw&m|+(+}^*c?D?Iuq%8M zE$*j$a`%VQHMIn;8*!7EsWZqfZrG*O^*ksEa?@p-1E98UWc0XsBAA1Jl@XUMH=#o6 z5!17gYPG<0&@;&T03b!ZW{p*_GM*wGVwj!by9RN<4I7w!Rvp^OlVgrf6&JgUD>Aoy zYBRc%$p6a1f`ubr{y~&1S4hJ{ro~c2s@1WVLO9K247o!;KTEajZKapGzGpJuWEExa zOeMo>6_sk8quuX!?)Dt0UrT;4{WD(On~cs-yV9rkhjT#5`!8RZrONVHR<3;i&QeM~ z`ph6D{T~(}HEnqr8;fznqK&_odha)ufNfC1Z9P(oS>N}ih0v>GoVKE(YA~#AlaP1} z_=8#L#q5PL7h2N3tgNKlqiXfP#e-qig6{mdq9RT3R>@W9RN(p$_x?vzXmr4fiHX8g zxl9*jEiLopWxbE7iOK%0WBDr<)1#TM-@T^79=94fNk#JapXu!trWG>WHC?ZVp#<@$=0*H;5+nLLS9V(3 ztL*z}GUbm@kZ=Vn*)Y{}S@yik-z#Zv(Mz4G>^%J{QAS2x{Bk-5a6c66j2>5{pRYa1 z%lh;tPERq)H}OAh+PvExr&5oxBQg}J9wYU zr^k6POBT)4cei?aOaiOYM}{waID1??*Z0-%$nvk@FP&W_e*IhdkhHTAM#cTJ>=amE zGymv09dhOH=zd7#Ln)A$tQP{u2euK>+5#-6btVC`g!3hW-}p+UdT1A_~ECP(CNaag`DIk@>#+v`I@f_vAiE-!D9LbwBnQd9B8 zQ-`?xxl8!}&A+BnKh~t?I7&GipPHx^z9feE=i^2f=qeM7 z>e-Rh%)dRK0~UcduK(Kg?PEq2_Tvi0z^=TCkXq5ZJ}~$2|nAQ2Hfhg zdR1J;i|!sxF*MEk%l&LqOUusQ??UL;`z(0Tx+!|$vTF}jzx`EL_qZpGUHy^tk&2}S zrI^f=cyISq?Ox5$h9se}&X=i;r}uvYgV8Y-rac)7YnE@mFd14|im7wn(OnkORpQJu z`n{WkE{Be1Wl>|e?!BfRne4CNG1^hk_mum}qi*SKwAXDteqD^|t?Y5#ZSx4{*8AEA z!%{D+zG}1QvZPl%C3>@c7fPHX=A<;8^8pki4E-?XyB!|xjbejPfkm@e=(;48qjbjK zaLXB8-SR(`&MaiDj9-4#RcKj-bkvN;|NOM!X!E5zL^6tKYm0_uwunKQ_GQl<(9bS> z@!~1$Pq3@RIKsjsvRrQe_a@4v2%$Cigmi`;h^wiM+g_Dx?zqmE0D+9KyLaEGpHp-U zdU4%5!JQ(fyIA1RK!Ke=j)r<8dCoS;!a_-UrZj>rxIU61J7t&5uZhEx3^GaME*G9X zqq%mi@+}C1cCHa;a>s}2*cG zSH=w++~C;I2YjX0gPg_v`}a4(ZU+mvHH1)Rdb;5K@rE^O`L9s&_4oDh*w-~??bs}K zXNitq?F!4*VkQ}xNib9d$s%sR-o1oRicd>n&tAk(+LHh_A$|h0`SqF9o42(U`RRH# z#=k7SCL}(6R3wQ}7{zFVtdP!HM)e2xpBSiyt*F})Jyfsxpi&3nFm zGiuJ+0ptf}YC9gmFzB5-rQh-(S01|<-Sms=EE!ap=3{g#4VmYTxL&`WT;+5IgH9P4 zJDTJCs?|$O{G`Q&tF>m0+tw}hN0{uck1;6rV}cV;URzs*X$jmCyHsW0l!O#29^6X8 z&exf|w7MhyWO(fsEZtJ0#o0=2Za=(#OM%_`;H=;o56sRfNSe(pMATk)-7d_T3$b}0 z#Of+!pQ?f(eK}L?d|&lOYmef|FV$F|ViaIzB|N24*Z-DOyFBhOa=_l+o*b?k0I{zz8cNZ$qF%4Ouzi)E0z2}6#|KZ5! zEg6f`Ti%J19w8u>@!@u#U>$`LlYvYTUBx{Hq!^PVuZPH-ireiowChltP2ZK^=K7 zZwGB5;8xxlG0g1#U7(p5=)G;*#KC{+^z*Kej<#$JtKyp_j}9NO3am2I{q+q`;wlb~ z*o@SGu`hk`rNa}6@jDE>eJX6*^GvRIgoQ^$`P2LOyl!|`P37QV7r8ICu9f@FAT(cz zjWYJ5bSn!}!y1_VatjMHLLZo=`@rkAw!(2TN?pQu0is=WE0)H_6!bf|&TmxvRdL*| z^5;E!_( z03A3bB=}+We#+?adr9BRoqh*+j>~h0%3%eRV!hVWM61PQ_qTv&EVcD@3f&z~%yJD% z!bxHBz5wFXY5HZ!jo+tSZyWLPGfn?GJEv@w^p(qA3F!1bM)o&c?o z$|+Zh`MfEkw^TJ>h`ba=6rw!9kt0aaq^J8%f1IUjqC_m~jENpIKVc%iFXnJ2I11 z<9oz|twE+W34OyK0_f^n(PjV+yALPv*)-hRxxM{gnMCTIt$6i5C*|qwjesp0YX^1z z$g{ax?j626boMjF7kT-{*9r4uZ|-em(%`XOwURO2;Jlz+oTeODxt@!fL_}H(Ydy+A zvkPCol9!)qcEl8??eXH0rXyv|El%cCV|bdP?vj~!zlgjd1M)tveX;#$FVPTh?(OAl z%dR}z`-F@!0wj!BuqTfBLloQi0Lk?EyZft2g$C!XpTh?0G_hAT-u~3j;Gx3&90h6r z)UPI}->MH57urzLGBT1#qwJz|A--JFxAF=l;(s`_c5!@q^Tu54@+OQDY9sGMhrTNP7F7_s_phe99$}9{SKXVI53b zk@-y1{+#7z>5_J@^NF96#O}dOk?KXh<=dzS_&6iPlt91m>fw<{e}A#5srxi+K8kX} z!V%fmF6wx}@@v1Lswx8n+kJC$MeVvvt54#{Drjo$N5@%kfu0UMdw;88s#Nf)6=0J% zuMK|mD=@pJt}#KR7debgPGi;eVpnlXSH6*SMU#0@Y=im94^^RbrFlvf(l~dh;#IidB=@DCrDxhlza;BC!@=5;|BQZ-b5nd0bG*Q=s%{FFpmX0= zi{0Wo5JeSLGg4AASv{mh-^H{CG%t-$vsck2BNx|Im_%*xr zRTRFTC_BqWe?E`QpKf2^(|zYS-QB?5zjN>2a__Y#CkA7dLhsM(W{ANhm4<<#2C8%^ zk{qZO7(*AG_UO~(x>MSiPF~>cF5TCzpSW!u7mqT}5TG_@A8??$=GsiH)Hb4ucqsY61OWFXc9w=g*#_w8EBl8@DnqQerfiO{rdN1}V&rJSa3{=y+pfYucCcQd{g%MN;#eF8Rl#R|1 z_Z4tZ;Z;8pzvwRB@GwH zFI3CldbrrImpanbKaEPhClR6X)EtJrsuq{>m2|5tc{m- zPq46FLB-{Aw_Oh*ETb5nHJ&NI%VN^>d^7vz&Ciui9nq8)5j6zqy~rEsVF!r2V9 zim{Q=>7YMcW9FyHLG;z%+bDXXM4RHS=;<~@@!0W_%Ins$ZTr~FEag+{&%oe27RWx7 zZ_ennM|YduRw5!9^%{D^V<_TaYtD|2#nbf;E6c_YWJ*XyMFO@Qnc%p9(aa7Qc+2nl z+)puEO7$U~Jw5%_7_qfdNXlX+UX7u;Q$j~9F7KKC)bVuYOI4O$?y(^WTn@U*in3dZ zr%t^B2;=QT>rXkExX%LG*RO9>i7{{+8Zx!b9R8Hc56QGfOjRsS{iZf*-jq7^fQCau z;}t+-8=2IlOUkVsUyHA@{@buE6|dg>1{InK7>FC{aTme*QBV zeN`sH%M&4FBQQ#^XwqRO4s^@qgc7Hhc{)O|rl%#-2H&wrtpea6-$+aODCmvh2NR!u zSoQq5V0fg@(1-qk(wCodd$#QwaqF~%{1()Vf@E$Mh7z-g-!C<-?D0%U#4n0pu}FW# zs}S>}iAVOqAxW;ND4~7>QOBR>;bU@GRW)-n0c-g4YH{7OnCb_gC?B7PVUb=*BR?lU zKvBd*LE+mS=b+fw?F7gPvTE7$9{+xYv1L1c#|=W>hi;5N?sVkgfnLxrX{WEg8i@}= zLnric2>4ZA;ldf6Kd<@s5D-tu2rKKdRym*y*i@bVQ5>qqwgb`sL2?1Ipd8-)>_ zmV_h)blc0{yh;AQA5xk4gSXljlal?7jT%+_FZq3CW4cC{s466PVPJPrD}-5A5gzA2 z!lVlS(Ez}wRqLv%D5IN&xWe0q7!uPrw}|0s8R{d>Yh6_4#OIeMidtc6`5As2gr!=_ z|9+J*nU=%Njp+UkUNmo0^FQImd-z5n+pT~}@AdL5P7BxCbK*7PZ!Kfo0pA_~2Z`@T zycB711}LB}veQ9Dwc!+gk!j->_Ya8=dxt-9oH*g&9el)0QTgUN>#<&mo9*m#bHldj zP4C}(U@^B>zmO!F`+UMV>d#x@&CH4Kt&>?h7Sf%hCc1-<@tC?g^In6+HKfnKMxEPA zOW5R(NK>gC9aH43D!hJ$z?zVyegko%auP)AD(dU$Ei4vOeg1pLGrB<<6fDvc znNKwq#N}@O+O-bi+3y>U9xak^uo7O+`M|HUQ+yTQQ!lR$=nBc8TB5ym%eMb4Ow&CH zyAOaYut&@o@FJqh@7GjMVNqteh^Q#$7-~OUo*qk3I>obYcj~8oA|tB|dxmdJ@*R`n zkhR`u>I~icVSVMjlDSR+H*F4`0uQ#9i4qu zR&G%0a;CR9SmnFWBBfmJ1?eoK!&FYc&hm;rdic=q=EAYQPDveTN7003So!-)dP6mj zXTROk&ZA_&^`U%>yDj>cH%h!QZJ;;VeFraZ*g;UNv9QzFk-&IQHw{KB()-M6VQ(mQ zFZd+yMlT<$SMMI)H0!3>R;8pIwW2n^$TcJ}^)n0fGmm5;!*0Lc9m;orIG_eXvc zfVb}d`W0`@YI$VOM@^`}HpW)+N*wI*iTXr}n$XF#0v0E|a3a$K0;St_n$zQ+d9<~a zeKlx>ARsY~hw!YoyZd1=K3;^u->)aN2!=**-tK?bQU!=SB7(4`HVOJDB(Z#__Y)3V zRyd`;x^;Fk zqH8AEJ{#{QafT|=mpB!fynC?Qyt6RBuCs^CRW(+ow;i0d$97_Rc+j>UJir83lZw&S znSO&-w49hl5u_044zxu6PJ+MBS;{S31TD>39i7Y$n5v&rzS8@ZIXL6o#oEA&=MO>S z+tcR9gWXC>bgPwga^X?Sy}y}K@0p$4`8WpNjsE(h@DV16?_R#XPXS74d2r|7>GhNG z)*T|*pQ}oD)tw~+1-T}MT)O6a`=`EU0sgQ3@f0N9JHKyR0NZvf{j8J4DThk%JmAk+ z#y=Wg;|A8M5n=@Ncrzav{X4)4ai{kzu1))*Eo)y;Lw1z9{$QPkhTiP_yYk$NI&pm< zCAvlEI6#rNs5zR#{+v=RkACqi1Aw1}>Z1hYlgLA$ceRB55x0VP1gM)YlMKsBr*iLa zj&|A5VvomopMRXf5Y4U=I<4z+FRUhRyobj}oP26H{#^XrCVc$RjjMFi(~scU!zPiO zMMsyjVe2AOhM{4|moGo9_brKo;z~%#t}G79Hh~Rjaq5o(kb=T3LItKSQuxTwCWSb8 z+||g846CARb93xUr_^&1GT~UW3q2?d)ISh)l@yUli(MQknfT`)o4tMhDMW^Efcf2{ zCF=A--R!62A_;n&$v=)tM$qX37zvlVUaLU?_Bw5j`g`+ z6rU();l5oj*6{4R8a@@|_WW~Iz=m&~pV$^=LQ?Gj_eS^D3!7HlMGFuF|GjFOmnJ6W_OEOY`*ceTYhhE{rii$=s$D>T)i%5-eJW{y8ydEGce_l^4DsUO$L%RDx!|NNdalH98FM`M% z97|0}p~-dn=i|hmT^T)_d|e`iPikHQv1XlY+0obaH+g2Hz`@+3_iP<_VuX!~0(WSg z3o2R|(bHiQoRnO$lDeIThw|OKcUa}gK>@R(l;PiBh|l!_5-ZJ-MxiW+kB(n%vxuM{yerC}dX_ zuX&gC>=zTmH4ZL=TshQOBccw%^i9g)M<962S^~1aLo4wQfi-JacERB_r?V(5>^P41 zg1N=W%a^?*zEf>j?`>AB>AAA_;$p+;^A}2)_x0B7*wIzxPRRruZ4AO#lDg$V;5aZB z_>9pdOq26FM~O8MI9_#d>br0VqaEn3c*0C4C&$9|?f>F$yPr3ir4cwF+rf<+xx*sk zrblp;R8+)`O-uwum!~d~h|KFevz{(2%_TWGd;Hf!_a1UVh36XnUHKn@J3?Q31jiN2 z#B=eZqa!0G09yj&y!kTuWMh2U7wntz zY8K~W;}0y?zdczQ%47Hiaf6xl!rI93^l#sIQAJhW6MP6O&2FW9o)p6}8TiZF2wl5xtHLaD**y%YKxkGq$Ahjd*GimRwwpZ4;f;%0DM7F20(AVt1CY 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 MbpIk>vikSG0EM}VLjV8( literal 0 HcmV?d00001 diff --git a/doc/manual/ellipsoids/index.rst b/doc/manual/ellipsoids/index.rst new file mode 100644 index 000000000..7956d3e91 --- /dev/null +++ b/doc/manual/ellipsoids/index.rst @@ -0,0 +1,11 @@ +.. _sec-ellipsoids: + +Ellipsoids +========== + +*Main author:* `Morgan Louédec `_ + +.. toctree:: + + what_is_ellipsoid.rst + Ellipsoid_class.rst \ No newline at end of file diff --git a/doc/manual/ellipsoids/what_is_ellipsoid.rst b/doc/manual/ellipsoids/what_is_ellipsoid.rst new file mode 100644 index 000000000..f1a080f56 --- /dev/null +++ b/doc/manual/ellipsoids/what_is_ellipsoid.rst @@ -0,0 +1,34 @@ +.. _sec-ellipsoids-intro: + +Ellipsoid in n-dimensional space (matrix definition) +==================================================== + +*Main author:* `Morgan Louédec `_ + +In **n-dimensional** space, an **ellipsoid** can be defined in terms of a matrix, which.. + +Matrix definition of an Ellipsoid +--------------------------------- + +An **ellipsoid** in \(n\)-dimensional space can be described by a unique midpoint +$\pmb{\mu}\in\mathbb{R}^n$, a unique shape matrix $\pmb{\Gamma}\in S_n^+$, and the quadratic form: + +.. math:: + + \mathcal{E}\left(\pmb{\mu},\pmb{\Gamma}\right) := \dots + + +.. figure:: ellipsoid_def.png + :width: 400 + + This is the caption. + + +References +---------- + +*(references générées par ChatGPT, à remplacer)* + +- A. B. Deaett, *Introduction to Ellipsoids and Quadratic Forms*, Journal of Applied Mathematics (2018). +- L. N. Trefethen and D. Bau, *Numerical Linear Algebra* (SIAM, 1997). +- D. Cohn, *The Ellipsoid Method in Optimization*, SIAM Review (2004). \ No newline at end of file From 1b13c4e47a86e946bc0bc909bf9708d941f779ad Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 15 Jan 2025 16:27:01 +0100 Subject: [PATCH 084/126] [traj] added codac2_SampledTraj_operations.h --- .../codac2_SampledTraj_operations.h | 587 ++++++++++++++++++ 1 file changed, 587 insertions(+) create mode 100644 src/core/trajectory/codac2_SampledTraj_operations.h diff --git a/src/core/trajectory/codac2_SampledTraj_operations.h b/src/core/trajectory/codac2_SampledTraj_operations.h new file mode 100644 index 000000000..a5469dee5 --- /dev/null +++ b/src/core/trajectory/codac2_SampledTraj_operations.h @@ -0,0 +1,587 @@ +/** + * \file codac2_SampledTraj_operations.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include "codac2_SampledTraj.h" +#include "codac2_math.h" +#include "codac2_template_tools.h" + +namespace codac2 +{ + #define macro_unary_traj(f) \ + { \ + auto y = x1; \ + for(auto it = y.begin() ; it != y.end() ; it++) \ + it->second = f(it->second); \ + return y; \ + }; \ + + #define macro_binary_traj_traj(f) \ + { \ + assert_release(x1.nb_samples() == x2.nb_samples()); \ + auto y = x1; \ + auto it_y = y.begin(); \ + auto it_x2 = x2.begin(); \ + while(it_y != y.end()) \ + { \ + assert_release(it_y->first == it_x2->first \ + && "inconsistent dates between the two trajectories"); \ + it_y->second = f((double)it_y->second,(double)it_x2->second); \ + it_y++; it_x2++; \ + } \ + return y; \ + } \ + + #define macro_binary_real_traj(f) \ + { \ + auto y = x2; \ + for(auto& [ti,xi] : y) \ + xi = f((double)x1,(double)xi); \ + return y; \ + } \ + + #define macro_binary_traj_real(f) \ + { \ + auto y = x1; \ + for(auto& [ti,xi] : y) \ + xi = f((double)xi,(double)x2); \ + return y; \ + } \ + + /** \brief \f$x1(\cdot)\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator+(const SampledTraj& x1); + + /** \brief \f$x_1(\cdot)+x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator+(const SampledTraj& x1, const SampledTraj& x2); + + /** \brief \f$x_1(\cdot)+x_2\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator+(const SampledTraj& x1, const T& x2); + + /** \brief \f$x+x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator+(const T& x1, const SampledTraj& x2); + + /** \brief \f$-x_1(\cdot)\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator-(const SampledTraj& x1); + + /** \brief \f$x_1(\cdot)-x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator-(const SampledTraj& x1, const SampledTraj& x2); + + /** \brief \f$x_1(\cdot)-x_2\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator-(const SampledTraj& x1, const T& x2); + + /** \brief \f$x-x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator-(const T& x1, const SampledTraj& x2); + + /** \brief \f$x_1(\cdot)\cdot x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + SampledTraj operator*(const SampledTraj& x1, const SampledTraj& x2); + + /** \brief \f$x_1(\cdot)\cdot x_2\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator*(const SampledTraj& x1, const T& x2); + + /** \brief \f$x\cdot x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator*(const T& x1, const SampledTraj& x2); + + + /** \brief \f$x_1(\cdot)/x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator/(const SampledTraj& x1, const SampledTraj& x2); + + /** \brief \f$x_1(\cdot)/x_2\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator/(const SampledTraj& x1, const T& x2); + + /** \brief \f$x/x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + SampledTraj operator/(const T& x1, const SampledTraj& x2); + + /** \brief \f$x^2(\cdot)\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj sqr(const SampledTraj& x1) + { + return pow(x1,2); + } + + /** \brief \f$\sqrt{x_1(\cdot)}\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj sqrt(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::sqrt) + /// \endcond + ; + + /** \brief \f$x^x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj pow(const SampledTraj& x1, int x2) + /// \cond + macro_binary_traj_real(codac2::pow) + /// \endcond + ; + + /** \brief \f$x^x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj pow(const SampledTraj& x1, double x2) + /// \cond + macro_binary_traj_real(codac2::pow) + /// \endcond + ; + + /** \brief \f$x^x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj root(const SampledTraj& x1, int x2) + /// \cond + macro_binary_traj_real(codac2::root) + /// \endcond + ; + + /** \brief \f$\exp(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj exp(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::exp) + /// \endcond + ; + + /** \brief \f$\log(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj log(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::log) + /// \endcond + ; + + /** \brief \f$\cos(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj cos(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::cos) + /// \endcond + ; + + /** \brief \f$\sin(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj sin(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::sin) + /// \endcond + ; + + /** \brief \f$\tan(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj tan(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::tan) + /// \endcond + ; + + /** \brief \f$\arccos(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj acos(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::acos) + /// \endcond + ; + + /** \brief \f$\arcsin(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj asin(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::asin) + /// \endcond + ; + + /** \brief \f$\arctan(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj atan(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::atan) + /// \endcond + ; + + /** \brief \f$\mathrm{arctan2}(x_1(\cdot),x_2(\cdot))\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj atan2(const SampledTraj& x1, const SampledTraj& x2) + /// \cond + macro_binary_traj_traj(std::atan2) + /// \endcond + ; + + /** \brief \f$\mathrm{arctan2}(x_1(\cdot),x_2)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj atan2(const SampledTraj& x1, const T& x2) + /// \cond + macro_binary_traj_real(std::atan2) + /// \endcond + ; + + /** \brief \f$\mathrm{arctan2}(x_1, x_2(\cdot))\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj atan2(const T& x1, const SampledTraj& x2) + /// \cond + macro_binary_real_traj(std::atan2) + /// \endcond + ; + + /** \brief \f$\cosh(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj cosh(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::cosh) + /// \endcond + ; + + /** \brief \f$\sinh(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj sinh(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::sinh) + /// \endcond + ; + + /** \brief \f$\tanh(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj tanh(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::tanh) + /// \endcond + ; + + /** \brief \f$\mathrm{arccosh}(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj acosh(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::acosh) + /// \endcond + ; + + /** \brief \f$\mathrm{arcsinh}(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj asinh(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::asinh) + /// \endcond + ; + + /** \brief \f$\mathrm{arctanh}(x_1(\cdot))\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj atanh(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::atanh) + /// \endcond + ; + + /** \brief \f$\mid x_1(\cdot)\mid\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj abs(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::abs) + /// \endcond + ; + + /** \brief \f$\min(x_1(\cdot),x_2(\cdot))\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj min(const SampledTraj& x1, const SampledTraj& x2) + /// \cond + macro_binary_traj_traj(std::min) + /// \endcond + ; + + /** \brief \f$\min(x_1(\cdot),x_2)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj min(const SampledTraj& x1, const T& x2) + /// \cond + macro_binary_traj_real(min) + /// \endcond + ; + + /** \brief \f$\min(x_1, x_2(\cdot))\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj min(const T& x1, const SampledTraj& x2) + /// \cond + macro_binary_real_traj(min) + /// \endcond + ; + + /** \brief \f$\max(x_1(\cdot),x_2(\cdot))\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj max(const SampledTraj& x1, const SampledTraj& x2) + /// \cond + macro_binary_traj_traj(std::max) + /// \endcond + ; + + /** \brief \f$\max(x_1(\cdot),x_2)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj max(const SampledTraj& x1, const T& x2) + /// \cond + macro_binary_traj_real(max) + /// \endcond + ; + + /** \brief \f$\max(x_1, x_2(\cdot))\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj max(const T& x1, const SampledTraj& x2) + /// \cond + macro_binary_real_traj(max) + /// \endcond + ; + + /** \brief \f$\mid x_1(\cdot)\mid\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj sign(const SampledTraj& x1) + /// \cond + macro_unary_traj(codac2::sign) + /// \endcond + ; + + /** \brief \f$\mid x_1(\cdot)\mid\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj integer(const SampledTraj& x1) + /// \cond + macro_unary_traj(codac2::integer) + /// \endcond + ; + + /** \brief \f$\mid x_1(\cdot)\mid\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj floor(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::floor) + /// \endcond + ; + + /** \brief \f$\mid x_1(\cdot)\mid\f$ + * \param x1 + * \return trajectory output + */ + template + requires IsRealType + inline SampledTraj ceil(const SampledTraj& x1) + /// \cond + macro_unary_traj(std::ceil) + /// \endcond + ; +} \ No newline at end of file From 19d2628dcff3a61341f4aba31dfa49f80382cbb0 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Thu, 16 Jan 2025 19:34:46 +0100 Subject: [PATCH 085/126] [traj] added operators for trajectories --- examples/04_explored_area/main.cpp | 2 +- examples/04_explored_area/main.py | 2 +- .../core/trajectory/codac2_py_SampledTraj.cpp | 272 +++++++++--- src/core/CMakeLists.txt | 1 + .../codac2_SampledTraj_operations.cpp | 120 +++++ .../codac2_SampledTraj_operations.h | 409 ++++++------------ src/core/trajectory/codac2_Traj_operator.h | 1 - 7 files changed, 453 insertions(+), 354 deletions(-) create mode 100644 src/core/trajectory/codac2_SampledTraj_operations.cpp diff --git a/examples/04_explored_area/main.cpp b/examples/04_explored_area/main.cpp index 0f559b638..fb474e3ff 100644 --- a/examples/04_explored_area/main.cpp +++ b/examples/04_explored_area/main.cpp @@ -24,7 +24,7 @@ int main() VectorVar w(3); auto g = sampled_f.as_function(); AnalyticFunction h { - {w}, // w=(t,x,y) + {w}, // w=(x,y,t) sqr(w[0]-g(w[2])[0])+sqr(w[1]-g(w[2])[1]) }; diff --git a/examples/04_explored_area/main.py b/examples/04_explored_area/main.py index 96e2bcd6a..7f0c13662 100644 --- a/examples/04_explored_area/main.py +++ b/examples/04_explored_area/main.py @@ -20,7 +20,7 @@ w = VectorVar(3) g = sampled_f.as_function() h = AnalyticFunction( - [w], # w=(t,x,y) + [w], # w=(x,y,t) sqr(w[0]-g(w[2])[0])+sqr(w[1]-g(w[2])[1]) ) diff --git a/python/src/core/trajectory/codac2_py_SampledTraj.cpp b/python/src/core/trajectory/codac2_py_SampledTraj.cpp index d7c0ecdde..a1127e25b 100644 --- a/python/src/core/trajectory/codac2_py_SampledTraj.cpp +++ b/python/src/core/trajectory/codac2_py_SampledTraj.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "codac2_py_SampledTraj_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_TrajBase_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): @@ -25,7 +26,7 @@ namespace py = pybind11; using namespace pybind11::literals; template -void _export_SampledTraj(py::module& m, const string& class_name) +py::class_> _export_SampledTraj(py::module& m, const string& class_name) { py::class_> exported_class(m, class_name.c_str(), SAMPLEDTRAJ_MAIN); export_TrajBase>(exported_class); @@ -122,104 +123,239 @@ void _export_SampledTraj(py::module& m, const string& class_name) }, OSTREAM_REF_OPERATOROUT_OSTREAM_REF_CONST_SAMPLEDTRAJ_T_REF) ; + + return exported_class; +} + +template +void add_operators(py::class_>& pyclass) +{ + pyclass + + .def("__add__", [](const SampledTraj& x1) { return x1; }, + CONST_SAMPLEDTRAJ_T_REF_OPERATORPLUS_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__add__", [](const SampledTraj& x1, const SampledTraj& x2) { return x1+x2; }, + SAMPLEDTRAJ_T_OPERATORPLUS_CONST_SAMPLEDTRAJ_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__add__", [](const SampledTraj& x1, const T& x2) { return x1+x2; }, + SAMPLEDTRAJ_T_OPERATORPLUS_CONST_SAMPLEDTRAJ_T_REF_CONST_T_REF, + py::is_operator()) + + .def("__add__", [](const T& x1, const SampledTraj& x2) { return x1+x2; }, + SAMPLEDTRAJ_T_OPERATORPLUS_CONST_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__sub__", [](const SampledTraj& x1) { return -x1; }, + SAMPLEDTRAJ_T_OPERATORMINUS_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__sub__", [](const SampledTraj& x1, const SampledTraj& x2) { return x1-x2; }, + SAMPLEDTRAJ_T_OPERATORMINUS_CONST_SAMPLEDTRAJ_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__sub__", [](const SampledTraj& x1, const T& x2) { return x1-x2; }, + SAMPLEDTRAJ_T_OPERATORMINUS_CONST_SAMPLEDTRAJ_T_REF_CONST_T_REF, + py::is_operator()) + + .def("__sub__", [](const T& x1, const SampledTraj& x2) { return x1-x2; }, + SAMPLEDTRAJ_T_OPERATORMINUS_CONST_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__mul__", [](const SampledTraj& x1, const SampledTraj& x2) { return x1*x2; }, + SAMPLEDTRAJ_T_OPERATORMUL_CONST_SAMPLEDTRAJ_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__mul__", [](double x1, const SampledTraj& x2) { return x1*x2; }, + SAMPLEDTRAJ_T_OPERATORMUL_DOUBLE_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__mul__", [](const SampledTraj& x1, double x2) { return x1*x2; }, + SAMPLEDTRAJ_T_OPERATORMUL_CONST_SAMPLEDTRAJ_T_REF_DOUBLE, + py::is_operator()) + + .def("__mul__", [](const T& x1, const SampledTraj& x2) { return x1*x2; }, + SAMPLEDTRAJ_T_OPERATORMUL_CONST_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def("__truediv__", [](const SampledTraj& x1, double x2) { return x1/x2; }, + SAMPLEDTRAJ_T_OPERATORDIV_CONST_SAMPLEDTRAJ_T_REF_DOUBLE, + py::is_operator()) + ; } void export_SampledTraj(py::module& m) { - _export_SampledTraj(m, "SampledTraj"); - _export_SampledTraj(m, "SampledVectorTraj"); + auto py_SampledTraj_double = _export_SampledTraj(m, "SampledScalarTraj"); + auto py_SampledTraj_Vector = _export_SampledTraj(m, "SampledVectorTraj"); + auto py_SampledTraj_Matrix = _export_SampledTraj(m, "SampledMatrixTraj"); + + add_operators(py_SampledTraj_double); + + py_SampledTraj_double + + .def(py::self * py::self, + SAMPLEDTRAJ_T_OPERATORMUL_CONST_SAMPLEDTRAJ_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def(py::self / py::self, + SAMPLEDTRAJ_T_OPERATORDIV_CONST_SAMPLEDTRAJ_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + .def(double() / py::self, + SAMPLEDTRAJ_T_OPERATORDIV_CONST_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + ; + + add_operators(py_SampledTraj_Matrix); + add_operators(py_SampledTraj_Vector); + py_SampledTraj_Matrix + + .def("__mul__", [](const SampledTraj& x1, const SampledTraj& x2) { return x1*x2; }, + SAMPLEDTRAJ_VECTOR_OPERATORMUL_CONST_SAMPLEDTRAJ_MATRIX_REF_CONST_SAMPLEDTRAJ_VECTOR_REF, + py::is_operator()) + + .def("__mul__", [](const SampledTraj& x1, const SampledTraj& x2) { return x1*x2; }, + SAMPLEDTRAJ_T_OPERATORMUL_CONST_SAMPLEDTRAJ_T_REF_CONST_SAMPLEDTRAJ_T_REF, + py::is_operator()) + + ; m .def("sqr", (SampledTraj (*)(const SampledTraj&)) &codac2::sqr, - py::is_operator(), - SAMPLEDTRAJ_T_SQR_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_SQR_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("sqrt", (SampledTraj (*)(const SampledTraj&)) &codac2::sqrt, - py::is_operator(), - SAMPLEDTRAJ_T_SQRT_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_SQRT_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("pow", (SampledTraj (*)(const SampledTraj&,int)) &codac2::pow, - py::is_operator(), - SAMPLEDTRAJ_T_POW_CONST_SAMPLEDTRAJ_T_REF_INT, - "x1"_a, "x2"_a) + SAMPLEDTRAJ_DOUBLE_POW_CONST_SAMPLEDTRAJ_DOUBLE_REF_INT, + "x1"_a, "x2"_a, py::is_operator()) .def("pow", (SampledTraj (*)(const SampledTraj&,double)) &codac2::pow, - py::is_operator(), - SAMPLEDTRAJ_T_POW_CONST_SAMPLEDTRAJ_T_REF_DOUBLE, - "x1"_a, "x2"_a) + SAMPLEDTRAJ_DOUBLE_POW_CONST_SAMPLEDTRAJ_DOUBLE_REF_DOUBLE, + "x1"_a, "x2"_a, py::is_operator()) .def("root", (SampledTraj (*)(const SampledTraj&,int)) &codac2::root, - py::is_operator(), - SAMPLEDTRAJ_T_ROOT_CONST_SAMPLEDTRAJ_T_REF_INT, - "x1"_a, "x2"_a) + SAMPLEDTRAJ_DOUBLE_ROOT_CONST_SAMPLEDTRAJ_DOUBLE_REF_INT, + "x1"_a, "x2"_a, py::is_operator()) .def("exp", (SampledTraj (*)(const SampledTraj&)) &codac2::exp, - py::is_operator(), - SAMPLEDTRAJ_T_EXP_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_EXP_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("log", (SampledTraj (*)(const SampledTraj&)) &codac2::log, - py::is_operator(), - SAMPLEDTRAJ_T_LOG_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_LOG_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("cos", (SampledTraj (*)(const SampledTraj&)) &codac2::cos, - py::is_operator(), - SAMPLEDTRAJ_T_COS_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_COS_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("sin", (SampledTraj (*)(const SampledTraj&)) &codac2::sin, - py::is_operator(), - SAMPLEDTRAJ_T_SIN_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_SIN_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("tan", (SampledTraj (*)(const SampledTraj&)) &codac2::tan, - py::is_operator(), - SAMPLEDTRAJ_T_TAN_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_TAN_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("acos", (SampledTraj (*)(const SampledTraj&)) &codac2::acos, - py::is_operator(), - SAMPLEDTRAJ_T_ACOS_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_ACOS_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("asin", (SampledTraj (*)(const SampledTraj&)) &codac2::asin, - py::is_operator(), - SAMPLEDTRAJ_T_ASIN_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) + SAMPLEDTRAJ_DOUBLE_ASIN_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) .def("atan", (SampledTraj (*)(const SampledTraj&)) &codac2::atan, - py::is_operator(), - SAMPLEDTRAJ_T_ATAN_CONST_SAMPLEDTRAJ_T_REF, - "x1"_a) - -#if 0 - 20 - inline SampledTraj atan2(const SampledTraj& x1, const SampledTraj& x2) - inline SampledTraj atan2(const SampledTraj& x1, const T& x2) - inline SampledTraj atan2(const T& x1, const SampledTraj& x2) - inline SampledTraj cosh(const SampledTraj& x1) - inline SampledTraj sinh(const SampledTraj& x1) - inline SampledTraj tanh(const SampledTraj& x1) - inline SampledTraj acosh(const SampledTraj& x1) - inline SampledTraj asinh(const SampledTraj& x1) - inline SampledTraj atanh(const SampledTraj& x1) - inline SampledTraj abs(const SampledTraj& x1) - inline SampledTraj min(const SampledTraj& x1, const SampledTraj& x2) - inline SampledTraj min(const SampledTraj& x1, const T& x2) - inline SampledTraj min(const T& x1, const SampledTraj& x2) - inline SampledTraj max(const SampledTraj& x1, const SampledTraj& x2) - inline SampledTraj max(const SampledTraj& x1, const T& x2) - inline SampledTraj max(const T& x1, const SampledTraj& x2) - inline SampledTraj sign(const SampledTraj& x1) - inline SampledTraj integer(const SampledTraj& x1) - inline SampledTraj floor(const SampledTraj& x1) - inline SampledTraj ceil(const SampledTraj& x1) - - #endif - ; + SAMPLEDTRAJ_DOUBLE_ATAN_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("atan2", (SampledTraj (*)(const SampledTraj&,const SampledTraj&)) &codac2::atan2, + SAMPLEDTRAJ_DOUBLE_ATAN2_CONST_SAMPLEDTRAJ_DOUBLE_REF_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, "x2"_a, py::is_operator()) + + .def("atan2", (SampledTraj (*)(const SampledTraj&,double)) &codac2::atan2, + SAMPLEDTRAJ_DOUBLE_ATAN2_CONST_SAMPLEDTRAJ_DOUBLE_REF_DOUBLE, + "x1"_a, "x2"_a, py::is_operator()) + + .def("atan2", (SampledTraj (*)(double,const SampledTraj&)) &codac2::atan2, + SAMPLEDTRAJ_DOUBLE_ATAN2_DOUBLE_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, "x2"_a, py::is_operator()) + + .def("cosh", (SampledTraj (*)(const SampledTraj&)) &codac2::cosh, + SAMPLEDTRAJ_DOUBLE_COSH_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("sinh", (SampledTraj (*)(const SampledTraj&)) &codac2::sinh, + SAMPLEDTRAJ_DOUBLE_SINH_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("tanh", (SampledTraj (*)(const SampledTraj&)) &codac2::tanh, + SAMPLEDTRAJ_DOUBLE_TANH_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("acosh", (SampledTraj (*)(const SampledTraj&)) &codac2::acosh, + SAMPLEDTRAJ_DOUBLE_ACOSH_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("asinh", (SampledTraj (*)(const SampledTraj&)) &codac2::asinh, + SAMPLEDTRAJ_DOUBLE_ASINH_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + .def("atanh", (SampledTraj (*)(const SampledTraj&)) &codac2::atanh, + SAMPLEDTRAJ_DOUBLE_ATANH_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("abs", (SampledTraj (*)(const SampledTraj&)) &codac2::abs, + SAMPLEDTRAJ_DOUBLE_ABS_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("min", (SampledTraj (*)(const SampledTraj&,const SampledTraj&)) &codac2::min, + SAMPLEDTRAJ_DOUBLE_MIN_CONST_SAMPLEDTRAJ_DOUBLE_REF_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, "x2"_a, py::is_operator()) + + .def("min", (SampledTraj (*)(const SampledTraj&,double)) &codac2::min, + SAMPLEDTRAJ_DOUBLE_MIN_CONST_SAMPLEDTRAJ_DOUBLE_REF_DOUBLE, + "x1"_a, "x2"_a, py::is_operator()) + + .def("min", (SampledTraj (*)(double,const SampledTraj&)) &codac2::min, + SAMPLEDTRAJ_DOUBLE_MIN_DOUBLE_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, "x2"_a, py::is_operator()) + + .def("max", (SampledTraj (*)(const SampledTraj&,const SampledTraj&)) &codac2::max, + SAMPLEDTRAJ_DOUBLE_MAX_CONST_SAMPLEDTRAJ_DOUBLE_REF_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, "x2"_a, py::is_operator()) + + .def("max", (SampledTraj (*)(const SampledTraj&,double)) &codac2::max, + SAMPLEDTRAJ_DOUBLE_MAX_CONST_SAMPLEDTRAJ_DOUBLE_REF_DOUBLE, + "x1"_a, "x2"_a, py::is_operator()) + + .def("max", (SampledTraj (*)(double,const SampledTraj&)) &codac2::max, + SAMPLEDTRAJ_DOUBLE_MAX_DOUBLE_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, "x2"_a, py::is_operator()) + + .def("sign", (SampledTraj (*)(const SampledTraj&)) &codac2::sign, + SAMPLEDTRAJ_DOUBLE_SIGN_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("integer", (SampledTraj (*)(const SampledTraj&)) &codac2::integer, + SAMPLEDTRAJ_DOUBLE_INTEGER_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("floor", (SampledTraj (*)(const SampledTraj&)) &codac2::floor, + SAMPLEDTRAJ_DOUBLE_FLOOR_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + .def("ceil", (SampledTraj (*)(const SampledTraj&)) &codac2::ceil, + SAMPLEDTRAJ_DOUBLE_CEIL_CONST_SAMPLEDTRAJ_DOUBLE_REF, + "x1"_a, py::is_operator()) + + ; } \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 33e45b776..b8d17d265 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -163,6 +163,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_AnalyticTraj.h ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_SampledTraj.h + ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_SampledTraj_operations.cpp ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_SampledTraj_operations.h ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_Traj_operator.h ${CMAKE_CURRENT_SOURCE_DIR}/trajectory/codac2_TrajBase.h diff --git a/src/core/trajectory/codac2_SampledTraj_operations.cpp b/src/core/trajectory/codac2_SampledTraj_operations.cpp new file mode 100644 index 000000000..14855358d --- /dev/null +++ b/src/core/trajectory/codac2_SampledTraj_operations.cpp @@ -0,0 +1,120 @@ +/** + * codac2_SampledTraj_operations.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Simon Rohou + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_SampledTraj_operations.h" +#include "codac2_math.h" + +using namespace std; + +namespace codac2 +{ + SampledTraj sqr(const SampledTraj& x1) { + return pow(x1,2); + } + + SampledTraj sqrt(const SampledTraj& x1) + macro_unary_traj(std::sqrt); + + inline double operator_pow(double x1, int x2) { return std::pow(x1,x2); } + inline double operator_pow(double x1, double x2) { return std::pow(x1,x2); } + inline double operator_root(double x1, double x2) { return root(x1,x2); } + + SampledTraj pow(const SampledTraj& x1, int x2) + macro_binary_traj_real(operator_pow); + + SampledTraj pow(const SampledTraj& x1, double x2) + macro_binary_traj_real(operator_pow); + + SampledTraj root(const SampledTraj& x1, int x2) + macro_binary_traj_real(operator_root); + + SampledTraj exp(const SampledTraj& x1) + macro_unary_traj(std::exp); + + SampledTraj log(const SampledTraj& x1) + macro_unary_traj(std::log); + + SampledTraj cos(const SampledTraj& x1) + macro_unary_traj(std::cos); + + SampledTraj sin(const SampledTraj& x1) + macro_unary_traj(std::sin); + + SampledTraj tan(const SampledTraj& x1) + macro_unary_traj(std::tan); + + SampledTraj acos(const SampledTraj& x1) + macro_unary_traj(std::acos); + + SampledTraj asin(const SampledTraj& x1) + macro_unary_traj(std::asin); + + SampledTraj atan(const SampledTraj& x1) + macro_unary_traj(std::atan); + + SampledTraj atan2(const SampledTraj& x1, const SampledTraj& x2) + macro_binary_traj_traj(std::atan2); + + SampledTraj atan2(const SampledTraj& x1, double x2) + macro_binary_traj_real(std::atan2); + + SampledTraj atan2(double x1, const SampledTraj& x2) + macro_binary_real_traj(std::atan2); + + SampledTraj cosh(const SampledTraj& x1) + macro_unary_traj(std::cosh); + + SampledTraj sinh(const SampledTraj& x1) + macro_unary_traj(std::sinh); + + SampledTraj tanh(const SampledTraj& x1) + macro_unary_traj(std::tanh); + + SampledTraj acosh(const SampledTraj& x1) + macro_unary_traj(std::acosh); + + SampledTraj asinh(const SampledTraj& x1) + macro_unary_traj(std::asinh); + + SampledTraj atanh(const SampledTraj& x1) + macro_unary_traj(std::atanh); + + SampledTraj abs(const SampledTraj& x1) + macro_unary_traj(std::abs); + + SampledTraj min(const SampledTraj& x1, const SampledTraj& x2) + macro_binary_traj_traj(std::min); + + SampledTraj min(const SampledTraj& x1, double x2) + macro_binary_traj_real(std::min); + + SampledTraj min(double x1, const SampledTraj& x2) + macro_binary_real_traj(std::min); + + SampledTraj max(const SampledTraj& x1, const SampledTraj& x2) + macro_binary_traj_traj(std::max); + + SampledTraj max(const SampledTraj& x1, double x2) + macro_binary_traj_real(std::max); + + SampledTraj max(double x1, const SampledTraj& x2) + macro_binary_real_traj(std::max); + + SampledTraj sign(const SampledTraj& x1) + macro_unary_traj(codac2::sign); + + SampledTraj integer(const SampledTraj& x1) + macro_unary_traj(codac2::integer); + + SampledTraj floor(const SampledTraj& x1) + macro_unary_traj(std::floor); + + SampledTraj ceil(const SampledTraj& x1) + macro_unary_traj(std::ceil); +} \ No newline at end of file diff --git a/src/core/trajectory/codac2_SampledTraj_operations.h b/src/core/trajectory/codac2_SampledTraj_operations.h index a5469dee5..94da0a383 100644 --- a/src/core/trajectory/codac2_SampledTraj_operations.h +++ b/src/core/trajectory/codac2_SampledTraj_operations.h @@ -11,7 +11,6 @@ #include "codac2_SampledTraj.h" #include "codac2_math.h" -#include "codac2_template_tools.h" namespace codac2 { @@ -26,15 +25,15 @@ namespace codac2 #define macro_binary_traj_traj(f) \ { \ assert_release(x1.nb_samples() == x2.nb_samples()); \ - auto y = x1; \ + auto y = x2; \ auto it_y = y.begin(); \ - auto it_x2 = x2.begin(); \ + auto it_x1 = x1.begin(); \ while(it_y != y.end()) \ { \ - assert_release(it_y->first == it_x2->first \ + assert_release(it_y->first == it_x1->first \ && "inconsistent dates between the two trajectories"); \ - it_y->second = f((double)it_y->second,(double)it_x2->second); \ - it_y++; it_x2++; \ + it_y->second = f(it_x1->second,it_y->second); \ + it_y++; it_x1++; \ } \ return y; \ } \ @@ -42,26 +41,43 @@ namespace codac2 #define macro_binary_real_traj(f) \ { \ auto y = x2; \ - for(auto& [ti,xi] : y) \ - xi = f((double)x1,(double)xi); \ + for(auto it_y = y.begin() ; it_y != y.end() ; it_y++) \ + it_y->second = f(x1,it_y->second); \ return y; \ } \ #define macro_binary_traj_real(f) \ { \ auto y = x1; \ - for(auto& [ti,xi] : y) \ - xi = f((double)xi,(double)x2); \ + for(auto it_y = y.begin() ; it_y != y.end() ; it_y++) \ + it_y->second = f(it_y->second,x2); \ return y; \ } \ + template + inline T operator_add(const T& x1, const T& x2) { return x1 + x2; } + template + inline T operator_sub(const T& x1, const T& x2) { return x1 - x2; } + template + inline T operator_mul(const T& x1, const T& x2) { return x1 * x2; } + template + inline T operator_mul_scal(double x1, const T& x2) { return x1 * x2; } + template + inline T operator_mul_scal(const T& x1, double x2) { return x1 * x2; } + inline Matrix operator_mul_vec(const Matrix& x1, const Vector& x2) { return x1 * x2; } + template + inline T operator_div(const T& x1, const T& x2) { return x1 / x2; } + template + inline T operator_div_scal(const T& x1, double x2) { return x1 / x2; } + /** \brief \f$x1(\cdot)\f$ * \param x1 * \return trajectory output */ template - requires IsRealType - SampledTraj operator+(const SampledTraj& x1); + inline const SampledTraj& operator+(const SampledTraj& x1) { + return x1; + } /** \brief \f$x_1(\cdot)+x_2(\cdot)\f$ * \param x1 @@ -69,8 +85,8 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator+(const SampledTraj& x1, const SampledTraj& x2); + inline SampledTraj operator+(const SampledTraj& x1, const SampledTraj& x2) + macro_binary_traj_traj(operator_add); /** \brief \f$x_1(\cdot)+x_2\f$ * \param x1 @@ -78,8 +94,8 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator+(const SampledTraj& x1, const T& x2); + inline SampledTraj operator+(const SampledTraj& x1, const T& x2) + macro_binary_traj_real(operator_add); /** \brief \f$x+x_2(\cdot)\f$ * \param x1 @@ -87,16 +103,17 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator+(const T& x1, const SampledTraj& x2); + inline SampledTraj operator+(const T& x1, const SampledTraj& x2) + macro_binary_real_traj(operator_add); /** \brief \f$-x_1(\cdot)\f$ * \param x1 * \return trajectory output */ template - requires IsRealType - SampledTraj operator-(const SampledTraj& x1); + inline SampledTraj operator-(const SampledTraj& x1) { + return -1.*x1; + } /** \brief \f$x_1(\cdot)-x_2(\cdot)\f$ * \param x1 @@ -104,8 +121,8 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator-(const SampledTraj& x1, const SampledTraj& x2); + inline SampledTraj operator-(const SampledTraj& x1, const SampledTraj& x2) + macro_binary_traj_traj(operator_sub); /** \brief \f$x_1(\cdot)-x_2\f$ * \param x1 @@ -113,8 +130,8 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator-(const SampledTraj& x1, const T& x2); + inline SampledTraj operator-(const SampledTraj& x1, const T& x2) + macro_binary_traj_real(operator_sub); /** \brief \f$x-x_2(\cdot)\f$ * \param x1 @@ -122,15 +139,37 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator-(const T& x1, const SampledTraj& x2); + inline SampledTraj operator-(const T& x1, const SampledTraj& x2) + macro_binary_real_traj(operator_sub); + + /** \brief \f$x_1\cdot x_2(\cdot)\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires (!std::is_same_v) + inline SampledTraj operator*(double x1, const SampledTraj& x2) + macro_binary_real_traj(operator_mul_scal); + + /** \brief \f$x_1(\cdot)\cdot x_2\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires (!std::is_same_v) + inline SampledTraj operator*(const SampledTraj& x1, double x2) + macro_binary_traj_real(operator_mul_scal); /** \brief \f$x_1(\cdot)\cdot x_2(\cdot)\f$ * \param x1 * \param x2 * \return trajectory output */ - SampledTraj operator*(const SampledTraj& x1, const SampledTraj& x2); + template + inline SampledTraj operator*(const SampledTraj& x1, const SampledTraj& x2) + macro_binary_traj_traj(operator_mul); /** \brief \f$x_1(\cdot)\cdot x_2\f$ * \param x1 @@ -138,8 +177,8 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator*(const SampledTraj& x1, const T& x2); + inline SampledTraj operator*(const SampledTraj& x1, const T& x2) + macro_binary_traj_real(operator_mul); /** \brief \f$x\cdot x_2(\cdot)\f$ * \param x1 @@ -147,9 +186,26 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator*(const T& x1, const SampledTraj& x2); + inline SampledTraj operator*(const T& x1, const SampledTraj& x2) + macro_binary_real_traj(operator_mul); + /** \brief \f$x_1(\cdot)\cdot x_2\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + inline SampledTraj operator*(const SampledTraj& x1, const SampledTraj& x2) + macro_binary_traj_traj(operator_mul_vec); + + /** \brief \f$x_2(\cdot)/x_1\f$ + * \param x1 + * \param x2 + * \return trajectory output + */ + template + requires (!std::is_same_v) + inline SampledTraj operator/(const SampledTraj& x1, double x2) + macro_binary_traj_real(operator_div_scal); /** \brief \f$x_1(\cdot)/x_2(\cdot)\f$ * \param x1 @@ -157,8 +213,8 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator/(const SampledTraj& x1, const SampledTraj& x2); + inline SampledTraj operator/(const SampledTraj& x1, const SampledTraj& x2) + macro_binary_traj_traj(operator_div); /** \brief \f$x_1(\cdot)/x_2\f$ * \param x1 @@ -166,8 +222,8 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator/(const SampledTraj& x1, const T& x2); + inline SampledTraj operator/(const SampledTraj& x1, const T& x2) + macro_binary_traj_real(operator_div); /** \brief \f$x/x_2(\cdot)\f$ * \param x1 @@ -175,413 +231,200 @@ namespace codac2 * \return trajectory output */ template - requires IsRealType - SampledTraj operator/(const T& x1, const SampledTraj& x2); + inline SampledTraj operator/(const T& x1, const SampledTraj& x2) + macro_binary_real_traj(operator_div); /** \brief \f$x^2(\cdot)\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj sqr(const SampledTraj& x1) - { - return pow(x1,2); - } + SampledTraj sqr(const SampledTraj& x1); /** \brief \f$\sqrt{x_1(\cdot)}\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj sqrt(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::sqrt) - /// \endcond - ; + SampledTraj sqrt(const SampledTraj& x1); /** \brief \f$x^x_2(\cdot)\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj pow(const SampledTraj& x1, int x2) - /// \cond - macro_binary_traj_real(codac2::pow) - /// \endcond - ; + SampledTraj pow(const SampledTraj& x1, int x2); /** \brief \f$x^x_2(\cdot)\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj pow(const SampledTraj& x1, double x2) - /// \cond - macro_binary_traj_real(codac2::pow) - /// \endcond - ; + SampledTraj pow(const SampledTraj& x1, double x2); /** \brief \f$x^x_2(\cdot)\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj root(const SampledTraj& x1, int x2) - /// \cond - macro_binary_traj_real(codac2::root) - /// \endcond - ; + SampledTraj root(const SampledTraj& x1, int x2); /** \brief \f$\exp(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj exp(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::exp) - /// \endcond - ; + SampledTraj exp(const SampledTraj& x1); /** \brief \f$\log(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj log(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::log) - /// \endcond - ; + SampledTraj log(const SampledTraj& x1); /** \brief \f$\cos(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj cos(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::cos) - /// \endcond - ; + SampledTraj cos(const SampledTraj& x1); /** \brief \f$\sin(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj sin(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::sin) - /// \endcond - ; + SampledTraj sin(const SampledTraj& x1); /** \brief \f$\tan(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj tan(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::tan) - /// \endcond - ; + SampledTraj tan(const SampledTraj& x1); /** \brief \f$\arccos(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj acos(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::acos) - /// \endcond - ; + SampledTraj acos(const SampledTraj& x1); /** \brief \f$\arcsin(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj asin(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::asin) - /// \endcond - ; + SampledTraj asin(const SampledTraj& x1); /** \brief \f$\arctan(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj atan(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::atan) - /// \endcond - ; + SampledTraj atan(const SampledTraj& x1); /** \brief \f$\mathrm{arctan2}(x_1(\cdot),x_2(\cdot))\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj atan2(const SampledTraj& x1, const SampledTraj& x2) - /// \cond - macro_binary_traj_traj(std::atan2) - /// \endcond - ; + SampledTraj atan2(const SampledTraj& x1, const SampledTraj& x2); /** \brief \f$\mathrm{arctan2}(x_1(\cdot),x_2)\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj atan2(const SampledTraj& x1, const T& x2) - /// \cond - macro_binary_traj_real(std::atan2) - /// \endcond - ; + SampledTraj atan2(const SampledTraj& x1, double x2); /** \brief \f$\mathrm{arctan2}(x_1, x_2(\cdot))\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj atan2(const T& x1, const SampledTraj& x2) - /// \cond - macro_binary_real_traj(std::atan2) - /// \endcond - ; + SampledTraj atan2(double x1, const SampledTraj& x2); /** \brief \f$\cosh(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj cosh(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::cosh) - /// \endcond - ; + SampledTraj cosh(const SampledTraj& x1); /** \brief \f$\sinh(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj sinh(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::sinh) - /// \endcond - ; + SampledTraj sinh(const SampledTraj& x1); /** \brief \f$\tanh(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj tanh(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::tanh) - /// \endcond - ; + SampledTraj tanh(const SampledTraj& x1); /** \brief \f$\mathrm{arccosh}(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj acosh(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::acosh) - /// \endcond - ; + SampledTraj acosh(const SampledTraj& x1); /** \brief \f$\mathrm{arcsinh}(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj asinh(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::asinh) - /// \endcond - ; + SampledTraj asinh(const SampledTraj& x1); /** \brief \f$\mathrm{arctanh}(x_1(\cdot))\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj atanh(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::atanh) - /// \endcond - ; + SampledTraj atanh(const SampledTraj& x1); /** \brief \f$\mid x_1(\cdot)\mid\f$ * \param x1 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj abs(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::abs) - /// \endcond - ; + SampledTraj abs(const SampledTraj& x1); /** \brief \f$\min(x_1(\cdot),x_2(\cdot))\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj min(const SampledTraj& x1, const SampledTraj& x2) - /// \cond - macro_binary_traj_traj(std::min) - /// \endcond - ; + SampledTraj min(const SampledTraj& x1, const SampledTraj& x2); /** \brief \f$\min(x_1(\cdot),x_2)\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj min(const SampledTraj& x1, const T& x2) - /// \cond - macro_binary_traj_real(min) - /// \endcond - ; + SampledTraj min(const SampledTraj& x1, double x2); /** \brief \f$\min(x_1, x_2(\cdot))\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj min(const T& x1, const SampledTraj& x2) - /// \cond - macro_binary_real_traj(min) - /// \endcond - ; + SampledTraj min(double x1, const SampledTraj& x2); /** \brief \f$\max(x_1(\cdot),x_2(\cdot))\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj max(const SampledTraj& x1, const SampledTraj& x2) - /// \cond - macro_binary_traj_traj(std::max) - /// \endcond - ; + SampledTraj max(const SampledTraj& x1, const SampledTraj& x2); /** \brief \f$\max(x_1(\cdot),x_2)\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj max(const SampledTraj& x1, const T& x2) - /// \cond - macro_binary_traj_real(max) - /// \endcond - ; + SampledTraj max(const SampledTraj& x1, double x2); /** \brief \f$\max(x_1, x_2(\cdot))\f$ * \param x1 * \param x2 * \return trajectory output */ - template - requires IsRealType - inline SampledTraj max(const T& x1, const SampledTraj& x2) - /// \cond - macro_binary_real_traj(max) - /// \endcond - ; + SampledTraj max(double x1, const SampledTraj& x2); - /** \brief \f$\mid x_1(\cdot)\mid\f$ - * \param x1 - * \return trajectory output - */ - template - requires IsRealType - inline SampledTraj sign(const SampledTraj& x1) - /// \cond - macro_unary_traj(codac2::sign) - /// \endcond - ; + SampledTraj sign(const SampledTraj& x1); - /** \brief \f$\mid x_1(\cdot)\mid\f$ - * \param x1 - * \return trajectory output - */ - template - requires IsRealType - inline SampledTraj integer(const SampledTraj& x1) - /// \cond - macro_unary_traj(codac2::integer) - /// \endcond - ; + SampledTraj integer(const SampledTraj& x1); - /** \brief \f$\mid x_1(\cdot)\mid\f$ - * \param x1 - * \return trajectory output - */ - template - requires IsRealType - inline SampledTraj floor(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::floor) - /// \endcond - ; + SampledTraj floor(const SampledTraj& x1); - /** \brief \f$\mid x_1(\cdot)\mid\f$ - * \param x1 - * \return trajectory output - */ - template - requires IsRealType - inline SampledTraj ceil(const SampledTraj& x1) - /// \cond - macro_unary_traj(std::ceil) - /// \endcond - ; + SampledTraj ceil(const SampledTraj& x1); } \ No newline at end of file diff --git a/src/core/trajectory/codac2_Traj_operator.h b/src/core/trajectory/codac2_Traj_operator.h index 310d94696..7e01e7596 100644 --- a/src/core/trajectory/codac2_Traj_operator.h +++ b/src/core/trajectory/codac2_Traj_operator.h @@ -18,7 +18,6 @@ namespace codac2 { template - requires (std::is_same_v::Type,ScalarType> || std::is_same_v::Type,VectorType>) struct TrajectoryOp { static typename Wrapper::Domain fwd(const TrajBase& x1, const Interval& x2) From e6235d06a4feb7abce3c89b20ac0771f6e26ecb7 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 10:59:10 +0100 Subject: [PATCH 086/126] [cmake] updated top CMakeLists for colored build type messages --- CMakeLists.txt | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a39db1a1..28ed9a9f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,13 +47,39 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) - message(STATUS "Configuring ${PROJECT_NAME} in DEBUG mode as none was specified.") if(MSVC) add_compile_options(/MD) # Temporary fix to avoid debug vs release inconsistencies... else() add_compile_options(-O3) endif() endif() + + if(FAST_RELEASE) + add_compile_definitions(FAST_RELEASE) + endif() + + if(NOT WIN32) + string(ASCII 27 Esc) + set(COLOR_RED "${Esc}[31m") + set(COLOR_BLUE "${Esc}[36m") + set(COLOR_RESET "${Esc}[m") + else() + set(COLOR_RED "") + set(COLOR_BLUE "") + set(COLOR_RESET "") + endif() + + message(STATUS "${COLOR_BLUE}Configuring ${PROJECT_NAME} in ${CMAKE_BUILD_TYPE} mode.${COLOR_RESET}") + + if(FAST_RELEASE) + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + message(STATUS "${COLOR_RED}Option FAST_RELEASE cannot be used in Debug mode.${COLOR_RESET}") + else() + message(STATUS "${COLOR_BLUE}Option FAST_RELEASE enabled.${COLOR_RESET}") + endif() + else() + message(STATUS "Note: in Release build mode, the option FAST_RELEASE=ON would allow faster computations if enabled.") + endif() if(MSVC) add_compile_options(/W4) @@ -115,11 +141,6 @@ # Compile sources ################################################################################ - if(FAST_RELEASE) - add_compile_definitions(FAST_RELEASE) - message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") - endif() - add_subdirectory(src) # C++ sources add_subdirectory(doc) # documentation (Doxygen + Sphinx manual) From 803a95b423b9dc7510350a26a974bfdba47bfee5 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 10:59:20 +0100 Subject: [PATCH 087/126] [sivia] verbose mode --- examples/03_sivia/main.cpp | 2 +- examples/03_sivia/main.py | 2 +- python/src/core/paver/codac2_py_pave.cpp | 12 ++++++------ src/core/paver/codac2_pave.h | 12 +++++++++++- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/examples/03_sivia/main.cpp b/examples/03_sivia/main.cpp index a1bd32c55..448dc0d4b 100644 --- a/examples/03_sivia/main.cpp +++ b/examples/03_sivia/main.cpp @@ -6,6 +6,6 @@ int main() { VectorVar x(2); AnalyticFunction f { {x}, sqr(x[0])*sin(sqr(x[0])+sqr(x[1]))-sqr(x[1]) }; - auto p = sivia({{-5,5},{-4,4}}, f, {0,oo}, 1e-2); + auto p = sivia({{-5,5},{-4,4}}, f, {0,oo}, 1e-2, true); DefaultView::draw_paving(p); } \ No newline at end of file diff --git a/examples/03_sivia/main.py b/examples/03_sivia/main.py index 3293131cc..4b1c1a1fc 100644 --- a/examples/03_sivia/main.py +++ b/examples/03_sivia/main.py @@ -2,5 +2,5 @@ x = VectorVar(2) f = AnalyticFunction([x], sqr(x[0])*sin(sqr(x[0])+sqr(x[1]))-sqr(x[1])) -p = sivia([[-5,5],[-4,4]], f, [0,oo], 1e-2) +p = sivia([[-5,5],[-4,4]], f, [0,oo], 1e-2, True) DefaultView.draw_paving(p) \ No newline at end of file diff --git a/python/src/core/paver/codac2_py_pave.cpp b/python/src/core/paver/codac2_py_pave.cpp index 8ad665770..13522c35b 100644 --- a/python/src/core/paver/codac2_py_pave.cpp +++ b/python/src/core/paver/codac2_py_pave.cpp @@ -30,7 +30,7 @@ void export_pave(py::module& m) "x"_a, "s"_a, "eps"_a); m.def("sivia", - [](const IntervalVector& x, const py::object& f, const py::object& y, double eps) + [](const IntervalVector& x, const py::object& f, const py::object& y, double eps, bool verbose) { if(!is_instance>(f) && !is_instance>(f) @@ -40,14 +40,14 @@ void export_pave(py::module& m) } if(is_instance>(f)) - return sivia(x, cast>(f), y.cast(), eps); + return sivia(x, cast>(f), y.cast(), eps, verbose); else if(is_instance>(f)) - return sivia(x, cast>(f), y.cast(), eps); + return sivia(x, cast>(f), y.cast(), eps, verbose); else - return sivia(x, cast>(f), y.cast(), eps); + return sivia(x, cast>(f), y.cast(), eps, verbose); }, - PAVINGINOUT_SIVIA_CONST_INTERVALVECTOR_REF_CONST_ANALYTICFUNCTION_Y_REF_CONST_TYPENAME_Y_DOMAIN_REF_DOUBLE, - "x"_a, "f"_a, "y"_a, "eps"_a); + PAVINGINOUT_SIVIA_CONST_INTERVALVECTOR_REF_CONST_ANALYTICFUNCTION_Y_REF_CONST_TYPENAME_Y_DOMAIN_REF_DOUBLE_BOOL, + "x"_a, "f"_a, "y"_a, "eps"_a, "verbose"_a=false); } \ No newline at end of file diff --git a/src/core/paver/codac2_pave.h b/src/core/paver/codac2_pave.h index 0f8c890ce..67ef50a44 100644 --- a/src/core/paver/codac2_pave.h +++ b/src/core/paver/codac2_pave.h @@ -24,8 +24,11 @@ namespace codac2 PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps); template - PavingInOut sivia(const IntervalVector& x, const AnalyticFunction& f, const typename Y::Domain& y, double eps) + PavingInOut sivia(const IntervalVector& x, const AnalyticFunction& f, const typename Y::Domain& y, double eps, bool verbose = false) { + clock_t t_start = clock(); + Index n_inner = 0, n_boundary = 0; + PavingInOut p(x); std::list> l { p.tree() }; @@ -38,7 +41,10 @@ namespace codac2 auto eval = f.eval(n->unknown()); if(eval.is_subset(y)) + { std::get<1>(n->boxes()).set_empty(); + n_inner++; + } else if(!eval.intersects(y)) std::get<0>(n->boxes()).set_empty(); @@ -48,9 +54,13 @@ namespace codac2 n->bisect(); l.push_back(n->left()); l.push_back(n->right()); + n_boundary++; } } + if(verbose) + printf("Computation time: %.4fs, %ld inner boxes, %ld boundary boxes\n", + (double)(clock()-t_start)/CLOCKS_PER_SEC, n_inner, n_boundary); return p; } } \ No newline at end of file From f1b1d65f6815f14de8fef436416f68020d4ca231 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 11:31:09 +0100 Subject: [PATCH 088/126] [doc] manual structure --- doc/manual/development/info_dev.rst | 2 ++ doc/manual/index.rst | 10 +++++----- .../{ => manual}/ellipsoids/Ellipsoid_class.rst | 0 .../{ => manual}/ellipsoids/ellipsoid_def.png | Bin doc/manual/{ => manual}/ellipsoids/index.rst | 0 .../{ => manual}/ellipsoids/what_is_ellipsoid.rst | 0 doc/manual/{ => manual}/extensions/capd/index.rst | 0 doc/manual/{ => manual}/extensions/index.rst | 0 doc/manual/{ => manual}/installation/cpp.rst | 0 doc/manual/{ => manual}/installation/index.rst | 0 doc/manual/{ => manual}/installation/matlab.rst | 0 doc/manual/{ => manual}/installation/python.rst | 2 +- .../{ => manual}/intervals/Interval_class.rst | 0 doc/manual/{ => manual}/intervals/index.rst | 0 .../{ => manual}/visualization/3d_visualization.rst | 0 doc/manual/{ => manual}/visualization/colors.rst | 0 doc/manual/{ => manual}/visualization/figures.rst | 0 doc/manual/{ => manual}/visualization/index.rst | 0 doc/manual/{ => manual}/visualization/ipe.rst | 0 doc/manual/{ => manual}/visualization/vibes.rst | 0 20 files changed, 8 insertions(+), 6 deletions(-) rename doc/manual/{ => manual}/ellipsoids/Ellipsoid_class.rst (100%) rename doc/manual/{ => manual}/ellipsoids/ellipsoid_def.png (100%) rename doc/manual/{ => manual}/ellipsoids/index.rst (100%) rename doc/manual/{ => manual}/ellipsoids/what_is_ellipsoid.rst (100%) rename doc/manual/{ => manual}/extensions/capd/index.rst (100%) rename doc/manual/{ => manual}/extensions/index.rst (100%) rename doc/manual/{ => manual}/installation/cpp.rst (100%) rename doc/manual/{ => manual}/installation/index.rst (100%) rename doc/manual/{ => manual}/installation/matlab.rst (100%) rename doc/manual/{ => manual}/installation/python.rst (96%) rename doc/manual/{ => manual}/intervals/Interval_class.rst (100%) rename doc/manual/{ => manual}/intervals/index.rst (100%) rename doc/manual/{ => manual}/visualization/3d_visualization.rst (100%) rename doc/manual/{ => manual}/visualization/colors.rst (100%) rename doc/manual/{ => manual}/visualization/figures.rst (100%) rename doc/manual/{ => manual}/visualization/index.rst (100%) rename doc/manual/{ => manual}/visualization/ipe.rst (100%) rename doc/manual/{ => manual}/visualization/vibes.rst (100%) diff --git a/doc/manual/development/info_dev.rst b/doc/manual/development/info_dev.rst index be3dddb36..77a6e8eb6 100644 --- a/doc/manual/development/info_dev.rst +++ b/doc/manual/development/info_dev.rst @@ -1,3 +1,5 @@ +.. _sec-dev-info: + Information for developers ========================== diff --git a/doc/manual/index.rst b/doc/manual/index.rst index adb6fadca..454b0e083 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -20,11 +20,11 @@ Welcome to the Codac website. :caption: User manual :maxdepth: 2 - installation/index.rst - intervals/index.rst - ellipsoids/index.rst - visualization/index.rst - extensions/index.rst + manual/installation/index.rst + manual/intervals/index.rst + manual/ellipsoids/index.rst + manual/visualization/index.rst + manual/extensions/index.rst .. linear/index.rst .. functions/index.rst diff --git a/doc/manual/ellipsoids/Ellipsoid_class.rst b/doc/manual/manual/ellipsoids/Ellipsoid_class.rst similarity index 100% rename from doc/manual/ellipsoids/Ellipsoid_class.rst rename to doc/manual/manual/ellipsoids/Ellipsoid_class.rst diff --git a/doc/manual/ellipsoids/ellipsoid_def.png b/doc/manual/manual/ellipsoids/ellipsoid_def.png similarity index 100% rename from doc/manual/ellipsoids/ellipsoid_def.png rename to doc/manual/manual/ellipsoids/ellipsoid_def.png diff --git a/doc/manual/ellipsoids/index.rst b/doc/manual/manual/ellipsoids/index.rst similarity index 100% rename from doc/manual/ellipsoids/index.rst rename to doc/manual/manual/ellipsoids/index.rst diff --git a/doc/manual/ellipsoids/what_is_ellipsoid.rst b/doc/manual/manual/ellipsoids/what_is_ellipsoid.rst similarity index 100% rename from doc/manual/ellipsoids/what_is_ellipsoid.rst rename to doc/manual/manual/ellipsoids/what_is_ellipsoid.rst diff --git a/doc/manual/extensions/capd/index.rst b/doc/manual/manual/extensions/capd/index.rst similarity index 100% rename from doc/manual/extensions/capd/index.rst rename to doc/manual/manual/extensions/capd/index.rst diff --git a/doc/manual/extensions/index.rst b/doc/manual/manual/extensions/index.rst similarity index 100% rename from doc/manual/extensions/index.rst rename to doc/manual/manual/extensions/index.rst diff --git a/doc/manual/installation/cpp.rst b/doc/manual/manual/installation/cpp.rst similarity index 100% rename from doc/manual/installation/cpp.rst rename to doc/manual/manual/installation/cpp.rst diff --git a/doc/manual/installation/index.rst b/doc/manual/manual/installation/index.rst similarity index 100% rename from doc/manual/installation/index.rst rename to doc/manual/manual/installation/index.rst diff --git a/doc/manual/installation/matlab.rst b/doc/manual/manual/installation/matlab.rst similarity index 100% rename from doc/manual/installation/matlab.rst rename to doc/manual/manual/installation/matlab.rst diff --git a/doc/manual/installation/python.rst b/doc/manual/manual/installation/python.rst similarity index 96% rename from doc/manual/installation/python.rst rename to doc/manual/manual/installation/python.rst index cb7826308..1754b3d7f 100644 --- a/doc/manual/installation/python.rst +++ b/doc/manual/manual/installation/python.rst @@ -52,4 +52,4 @@ Depending on your configuration, you may encounter difficulties when installing Depending on the way Python was installed, the path to specify after ``--target`` may differ, *e.g.* if Python was installed from https://www.python.org/ftp/python/3.10.4/python-3.10.4-macos11.pkg, it may be ``/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages``. Otherwise, run ``python3 -m site`` to check the ``site-packages`` full path in ``sys.path`` list. Also, the value ``10_9`` may need to be changed to ``10_14`` (or possibly another value) for some Python versions. -Finally, note that unsupported configurations can still probably follow the instructions from :ref:`Installing local Python binding `, for building the Codac Python binding locally on your machine. \ No newline at end of file +Finally, note that unsupported configurations can still probably follow the instructions from :ref:`Installing local Python binding `, for building the Codac Python binding locally on your machine. \ No newline at end of file diff --git a/doc/manual/intervals/Interval_class.rst b/doc/manual/manual/intervals/Interval_class.rst similarity index 100% rename from doc/manual/intervals/Interval_class.rst rename to doc/manual/manual/intervals/Interval_class.rst diff --git a/doc/manual/intervals/index.rst b/doc/manual/manual/intervals/index.rst similarity index 100% rename from doc/manual/intervals/index.rst rename to doc/manual/manual/intervals/index.rst diff --git a/doc/manual/visualization/3d_visualization.rst b/doc/manual/manual/visualization/3d_visualization.rst similarity index 100% rename from doc/manual/visualization/3d_visualization.rst rename to doc/manual/manual/visualization/3d_visualization.rst diff --git a/doc/manual/visualization/colors.rst b/doc/manual/manual/visualization/colors.rst similarity index 100% rename from doc/manual/visualization/colors.rst rename to doc/manual/manual/visualization/colors.rst diff --git a/doc/manual/visualization/figures.rst b/doc/manual/manual/visualization/figures.rst similarity index 100% rename from doc/manual/visualization/figures.rst rename to doc/manual/manual/visualization/figures.rst diff --git a/doc/manual/visualization/index.rst b/doc/manual/manual/visualization/index.rst similarity index 100% rename from doc/manual/visualization/index.rst rename to doc/manual/manual/visualization/index.rst diff --git a/doc/manual/visualization/ipe.rst b/doc/manual/manual/visualization/ipe.rst similarity index 100% rename from doc/manual/visualization/ipe.rst rename to doc/manual/manual/visualization/ipe.rst diff --git a/doc/manual/visualization/vibes.rst b/doc/manual/manual/visualization/vibes.rst similarity index 100% rename from doc/manual/visualization/vibes.rst rename to doc/manual/manual/visualization/vibes.rst From 1ebc5ff4d0732c4913512e64eeda2160d9b5cc90 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 13:52:08 +0100 Subject: [PATCH 089/126] [doc] install local python binding --- doc/manual/development/info_dev.rst | 100 +++++++++++++++++++++- doc/manual/index.rst | 3 +- doc/manual/manual/installation/cpp.rst | 2 + doc/manual/manual/installation/python.rst | 2 +- 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/doc/manual/development/info_dev.rst b/doc/manual/development/info_dev.rst index 77a6e8eb6..9514e9f76 100644 --- a/doc/manual/development/info_dev.rst +++ b/doc/manual/development/info_dev.rst @@ -23,4 +23,102 @@ To build this manual using Sphinx, follow these steps: The generated website will be locally available in ``./build/doc/manual``. To contribute and extend this manual, please consult the Sphinx documentation: -https://www.sphinx-doc.org \ No newline at end of file +https://www.sphinx-doc.org + +.. _sec-dev-info-binding: + +Building a local Python binding for Codac +----------------------------------------- + +You can compile Codac's Python binding binaries locally on your machine to take advantage of the library's latest features. +If you simply want to use the latest Codac release in Python, you can download the binaries directly from `PyPi `_ or :ref:`follow the standard installation procedure `. + +1. **Ensure the following prerequisites are met**: + + - the prerequisites for the :ref:`C++ installation of Codac `. + - a recent `Doxygen `_ version. On Linux systems, Debian packages are available: + + .. code-block:: bash + + sudo apt-get install -y doxygen + + - a supported version of Python (>=3.6). + +2. **Configure IBEX prior to compiling Codac**: + + We recall that IBEX sources can be obtained with: + + .. code-block:: bash + + git clone -b master https://github.com/lebarsfa/ibex-lib.git $HOME/ibex-lib + + You will need to compile both IBEX and Codac using the ``-fPIC`` options. This can be done with the following CMake configuration: + + .. code-block:: bash + + cd $HOME/ibex-lib/build + cmake -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release .. + make + make install + +3. **Compile Codac with Python binding**: + + We recall that Codac sources can be obtained with: + + .. code-block:: bash + + git clone https://github.com/codac-team/codac $HOME/codac + + In addition to the ``-fPIC`` options, you will have to configure ``WITH_PYTHON=ON``. Note that the ``git submodule`` commands will automatically get the `pybind11 `_ files required for the binding. + + .. code-block:: bash + + cd $HOME/codac/build + # Get automatically pybind11 and eigen submodules: + git submodule init ; git submodule update + # Configure CMake + 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 .. + make + +4. **Configure your Python environment**: + + Finally, you need to configure your system so that Python can find access to your Codac binding binaries: + + .. code-block:: bash + + cd $HOME/codac/build/python/python_package + python setup.py develop --user + +5. **Verify the installation** (optional): + + To ensure that the installation has worked properly, the unit tests of the library can be run: + + .. code-block:: bash + + python -m unittest discover codac.tests + +6. **Try an example** (optional): + + You may want to try Codac in Python by running one of the proposed examples. After the installation, you can run the following commands: + + .. code-block:: bash + + cd $HOME/codac/examples/03_sivia + python main.py + + Note that before executing the example, you will have to launch the VIBes viewer. + You should obtain a graphical output corresponding to a set inversion. + + +.. admonition:: About the use of Doxygen + + 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. + + +.. admonition:: For admins + + The command for uploading the generated wheels on PyPi is: + + .. code-block:: bash + + python -m twine upload --repository pypi * \ No newline at end of file diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 454b0e083..e0cbfd99d 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -22,10 +22,11 @@ Welcome to the Codac website. manual/installation/index.rst manual/intervals/index.rst - manual/ellipsoids/index.rst manual/visualization/index.rst manual/extensions/index.rst +.. manual/ellipsoids/index.rst + .. linear/index.rst .. functions/index.rst .. tubes/index.rst diff --git a/doc/manual/manual/installation/cpp.rst b/doc/manual/manual/installation/cpp.rst index 6078c7a89..75fc05693 100644 --- a/doc/manual/manual/installation/cpp.rst +++ b/doc/manual/manual/installation/cpp.rst @@ -62,6 +62,8 @@ If you prefer to use the latest development version, you can install Codac by co Steps ~~~~~ +.. _sec-install-cpp-prerequisites: + 1. **Ensure the following prerequisites are met**: - A C++ compiler supporting C++20 or later (*e.g.*, GCC 11.0+, Clang 13.0+). diff --git a/doc/manual/manual/installation/python.rst b/doc/manual/manual/installation/python.rst index 1754b3d7f..307219926 100644 --- a/doc/manual/manual/installation/python.rst +++ b/doc/manual/manual/installation/python.rst @@ -52,4 +52,4 @@ Depending on your configuration, you may encounter difficulties when installing Depending on the way Python was installed, the path to specify after ``--target`` may differ, *e.g.* if Python was installed from https://www.python.org/ftp/python/3.10.4/python-3.10.4-macos11.pkg, it may be ``/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages``. Otherwise, run ``python3 -m site`` to check the ``site-packages`` full path in ``sys.path`` list. Also, the value ``10_9`` may need to be changed to ``10_14`` (or possibly another value) for some Python versions. -Finally, note that unsupported configurations can still probably follow the instructions from :ref:`Installing local Python binding `, for building the Codac Python binding locally on your machine. \ No newline at end of file +Finally, note that unsupported configurations can still probably follow the instructions from :ref:`sec-dev-info-binding`, for building the Codac Python binding locally on your machine. \ No newline at end of file From d060c141318b598f3fe525c51425e86a5054d573 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 15:02:14 +0100 Subject: [PATCH 090/126] [doc] info that classic Python install not yet ready --- doc/manual/manual/installation/python.rst | 4 ++++ .../src/core/functions/analytic/codac2_py_AnalyticFunction.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/manual/manual/installation/python.rst b/doc/manual/manual/installation/python.rst index 307219926..6e487db42 100644 --- a/doc/manual/manual/installation/python.rst +++ b/doc/manual/manual/installation/python.rst @@ -3,6 +3,10 @@ Python installation =================== +.. error:: + + 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 `. + In case you want to use Codac only with Python, then the installation procedure is simply: 1. **Dependencies**: Ensure you have a supported version of Python (>=3.6). diff --git a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h index f227b24c5..8c18bc855 100644 --- a/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h +++ b/python/src/core/functions/analytic/codac2_py_AnalyticFunction.h @@ -90,7 +90,7 @@ using namespace pybind11::literals; \ ; \ -FunctionArgsList create_FunctionArgsList(const std::vector& l) +inline FunctionArgsList create_FunctionArgsList(const std::vector& l) { FunctionArgsList args {}; Index i = 0; From 7ecf99984fa33048801e82ae974f789a6872fd73 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 16:49:01 +0100 Subject: [PATCH 091/126] [py] corrected bug for draw_trajectory --- python/src/core/codac2_py_cast.h | 20 +++++++ python/src/core/paver/codac2_py_pave.cpp | 3 +- .../graphics/figures/codac2_py_Figure2D.cpp | 58 ++++++++++++++----- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/python/src/core/codac2_py_cast.h b/python/src/core/codac2_py_cast.h index e9c3efb38..dc1c8e7a3 100644 --- a/python/src/core/codac2_py_cast.h +++ b/python/src/core/codac2_py_cast.h @@ -11,6 +11,7 @@ #pragma once #include +#include namespace py = pybind11; using namespace pybind11::literals; @@ -33,6 +34,25 @@ namespace codac2 return x.cast(); } + // Casting to trajectory types + + template + requires std::is_same_v> + bool is_instance(const py::object& x) + { + const py::object& x_traj = x.attr("traj"); + return x_traj && py::isinstance(x_traj); + } + + template + requires std::is_same_v> + const T& cast(const py::object& x) + { + assert(is_instance(x)); + const py::object& x_traj = x.attr("traj"); + return x_traj.cast(); + } + // Casting to function/expression types template diff --git a/python/src/core/paver/codac2_py_pave.cpp b/python/src/core/paver/codac2_py_pave.cpp index 13522c35b..589a65d0c 100644 --- a/python/src/core/paver/codac2_py_pave.cpp +++ b/python/src/core/paver/codac2_py_pave.cpp @@ -34,8 +34,7 @@ void export_pave(py::module& m) { if(!is_instance>(f) && !is_instance>(f) - && !is_instance>(f)) - { + && !is_instance>(f)) { assert_release("sivia: invalid function type"); } diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index 08dd3a6e3..e4056c64a 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -10,11 +10,11 @@ #include #include #include +#include #include #include "codac2_py_Figure2D_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): #include "codac2_py_matlab.h" #include "codac2_py_cast.h" -#include using namespace std; using namespace codac2; @@ -135,22 +135,36 @@ void export_Figure2D(py::module& m) VOID_FIGURE2D_DRAW_ELLIPSE_CONST_VECTOR_REF_CONST_VECTOR_REF_DOUBLE_CONST_STYLEPROPERTIES_REF, "c"_a, "ab"_a, "theta"_a, "s"_a=StyleProperties()) - .def("draw_trajectory", (void(Figure2D::*)(const AnalyticTraj&,const StyleProperties&))&Figure2D::draw_trajectory, - VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, - "x"_a, "s"_a=StyleProperties()) - .def("draw_trajectory", (void(Figure2D::*)(const SampledTraj&,const StyleProperties&))&Figure2D::draw_trajectory, VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) - .def("draw_trajectory", (void(Figure2D::*)(const AnalyticTraj&,const ColorMap&))&Figure2D::draw_trajectory, - VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF, - "x"_a, "cmap"_a) + .def("draw_trajectory", [](Figure2D& fig, const py::object& x, const StyleProperties& s) + { + if(!is_instance>(x)) { + assert_release("draw_trajectory: invalid function type"); + } + + fig.draw_trajectory(cast>(x), s); + }, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, + "x"_a, "s"_a=StyleProperties()) .def("draw_trajectory", (void(Figure2D::*)(const SampledTraj&,const ColorMap&))&Figure2D::draw_trajectory, VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_COLORMAP_REF, "x"_a, "cmap"_a) + .def("draw_trajectory", [](Figure2D& fig, const py::object& x, const ColorMap& cmap) + { + if(!is_instance>(x)) { + assert_release("draw_trajectory: invalid function type"); + } + + fig.draw_trajectory(cast>(x), cmap); + }, + VOID_FIGURE2D_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF, + "x"_a, "cmap"_a) + // Robots .def("draw_tank", &Figure2D::draw_tank, @@ -230,22 +244,36 @@ void export_Figure2D(py::module& m) STATIC_VOID_DEFAULTVIEW_DRAW_PIE_CONST_VECTOR_REF_CONST_INTERVAL_REF_CONST_INTERVAL_REF_CONST_STYLEPROPERTIES_REF, "c"_a, "r"_a, "theta"_a, "s"_a=StyleProperties()) - .def_static("draw_trajectory", (void(*)(const AnalyticTraj&,const StyleProperties&))&DefaultView::draw_trajectory, - STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, - "x"_a, "s"_a=StyleProperties()) - .def_static("draw_trajectory", (void(*)(const SampledTraj&,const StyleProperties&))&DefaultView::draw_trajectory, STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_STYLEPROPERTIES_REF, "x"_a, "s"_a=StyleProperties()) - .def_static("draw_trajectory", (void(*)(const AnalyticTraj&,const ColorMap&))&DefaultView::draw_trajectory, - STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF, - "x"_a, "cmap"_a) + .def_static("draw_trajectory", [](const py::object& x, const StyleProperties& s) + { + if(!is_instance>(x)) { + assert_release("draw_trajectory: invalid function type"); + } + + DefaultView::draw_trajectory(cast>(x), s); + }, + STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_STYLEPROPERTIES_REF, + "x"_a, "s"_a=StyleProperties()) .def_static("draw_trajectory", (void(*)(const SampledTraj&,const ColorMap&))&DefaultView::draw_trajectory, STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_SAMPLEDTRAJ_VECTOR_REF_CONST_COLORMAP_REF, "x"_a, "cmap"_a) + .def_static("draw_trajectory", [](const py::object& x, const ColorMap& cmap) + { + if(!is_instance>(x)) { + assert_release("draw_trajectory: invalid function type"); + } + + DefaultView::draw_trajectory(cast>(x), cmap); + }, + STATIC_VOID_DEFAULTVIEW_DRAW_TRAJECTORY_CONST_ANALYTICTRAJ_VECTORTYPE_REF_CONST_COLORMAP_REF, + "x"_a, "cmap"_a) + // Robots .def_static("draw_tank", &DefaultView::draw_tank, From 94e52a1208aff6c1d1efe52d2e86c4178bf57d22 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 16:49:34 +0100 Subject: [PATCH 092/126] [doc] updated Doxygen installation procedure --- doc/CMakeLists.txt | 2 +- doc/manual/development/info_dev.rst | 32 +++++++++++++++++--------- doc/manual/manual/installation/cpp.rst | 6 ++--- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index ee4626e48..41476ad2a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -11,7 +11,7 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mathjax_stmaryrd.js if(WITH_PYTHON) - find_package(Doxygen 1.0.0) + find_package(Doxygen 1.13.0) if(NOT DOXYGEN_FOUND) diff --git a/doc/manual/development/info_dev.rst b/doc/manual/development/info_dev.rst index 9514e9f76..7fd6e3de0 100644 --- a/doc/manual/development/info_dev.rst +++ b/doc/manual/development/info_dev.rst @@ -36,13 +36,23 @@ If you simply want to use the latest Codac release in Python, you can download t 1. **Ensure the following prerequisites are met**: - the prerequisites for the :ref:`C++ installation of Codac `. - - a recent `Doxygen `_ version. On Linux systems, Debian packages are available: + - a supported version of Python (>=3.6). + - a recent `Doxygen `_ 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: .. code-block:: bash - sudo apt-get install -y doxygen + cd $HOME + git clone https://github.com/doxygen/doxygen + cd doxygen + git checkout Release_1_13_0 # 1.13.0, or any newer release + mkdir build ; cd build + cmake -DCMAKE_INSTALL_PREFIX=$HOME/doxygen/build_install .. + make ; make install + + .. admonition:: About the use of Doxygen + + 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. - - a supported version of Python (>=3.6). 2. **Configure IBEX prior to compiling Codac**: @@ -58,8 +68,7 @@ If you simply want to use the latest Codac release in Python, you can download t cd $HOME/ibex-lib/build cmake -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release .. - make - make install + make ; make install 3. **Compile Codac with Python binding**: @@ -78,7 +87,7 @@ If you simply want to use the latest Codac release in Python, you can download t git submodule init ; git submodule update # Configure CMake 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 .. - make + make ; make install 4. **Configure your Python environment**: @@ -89,6 +98,12 @@ If you simply want to use the latest Codac release in Python, you can download t cd $HOME/codac/build/python/python_package python setup.py develop --user + And update your configuration file (for instance, ``$HOME/.bashrc`` on Linux systems) with: + + .. code-block:: bash + + export PYTHONPATH="${PYTHONPATH}:$HOME/codac/build/python/python_package/" + 5. **Verify the installation** (optional): 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 You should obtain a graphical output corresponding to a set inversion. -.. admonition:: About the use of Doxygen - - 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. - - .. admonition:: For admins The command for uploading the generated wheels on PyPi is: diff --git a/doc/manual/manual/installation/cpp.rst b/doc/manual/manual/installation/cpp.rst index 75fc05693..374b445aa 100644 --- a/doc/manual/manual/installation/cpp.rst +++ b/doc/manual/manual/installation/cpp.rst @@ -88,7 +88,7 @@ Steps # Configure IBEX before installation cd $HOME/ibex-lib - mkdir build && cd build + mkdir build ; cd build cmake -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release .. # Building + installing @@ -113,7 +113,7 @@ Steps cd $HOME/codac # Get automatically pybind11 and eigen submodules: git submodule init ; git submodule update - mkdir build && cd build + mkdir build ; cd build cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release .. # Building + installing @@ -147,7 +147,7 @@ Steps .. code-block:: bash cd $HOME/codac/examples/01_batman - mkdir build && cd build + mkdir build ; cd build cmake .. make From 80dc2f07f487601a50c0ac17010bcaa6e477bb2e Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 17:44:56 +0100 Subject: [PATCH 093/126] [pave] verbose modes --- python/src/core/paver/codac2_py_pave.cpp | 12 +++--- src/core/paver/codac2_pave.cpp | 54 +++++++++++++++++------- src/core/paver/codac2_pave.h | 12 +++--- 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/python/src/core/paver/codac2_py_pave.cpp b/python/src/core/paver/codac2_py_pave.cpp index 589a65d0c..47588d5df 100644 --- a/python/src/core/paver/codac2_py_pave.cpp +++ b/python/src/core/paver/codac2_py_pave.cpp @@ -21,13 +21,13 @@ using namespace pybind11::literals; void export_pave(py::module& m) { - m.def("pave", (PavingOut (*)(const IntervalVector&,const CtcBase&,double))&codac2::pave, - PAVINGOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_CTCBASE_INTERVALVECTOR_REF_DOUBLE, - "x"_a, "c"_a, "eps"_a); + m.def("pave", (PavingOut (*)(const IntervalVector&,const CtcBase&,double,bool))&codac2::pave, + PAVINGOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_CTCBASE_INTERVALVECTOR_REF_DOUBLE_BOOL, + "x"_a, "c"_a, "eps"_a, "verbose"_a=false); - m.def("pave", (PavingInOut (*)(const IntervalVector&,const SepBase&,double))&codac2::pave, - PAVINGINOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_SEPBASE_REF_DOUBLE, - "x"_a, "s"_a, "eps"_a); + m.def("pave", (PavingInOut (*)(const IntervalVector&,const SepBase&,double,bool))&codac2::pave, + PAVINGINOUT_PAVE_CONST_INTERVALVECTOR_REF_CONST_SEPBASE_REF_DOUBLE_BOOL, + "x"_a, "s"_a, "eps"_a, "verbose"_a=false); m.def("sivia", [](const IntervalVector& x, const py::object& f, const py::object& y, double eps, bool verbose) diff --git a/src/core/paver/codac2_pave.cpp b/src/core/paver/codac2_pave.cpp index 81c5cff19..40dae5502 100644 --- a/src/core/paver/codac2_pave.cpp +++ b/src/core/paver/codac2_pave.cpp @@ -14,17 +14,20 @@ using namespace codac2; namespace codac2 { - PavingOut pave(const IntervalVector& x, std::shared_ptr> c, double eps) + PavingOut pave(const IntervalVector& x, std::shared_ptr> c, double eps, bool verbose) { - return pave(x, *c, eps); + return pave(x, *c, eps, verbose); } - PavingOut pave(const IntervalVector& x, const CtcBase& c, double eps) + PavingOut pave(const IntervalVector& x, const CtcBase& c, double eps, bool verbose) { assert_release(eps > 0.); assert_release(!x.is_empty()); assert_release(c.size() >= 2 && "cannot reveal 1d contractors"); + clock_t t_start = clock(); + Index n_boundary = 0; + PavingOut p(x); // In order to be able to reconstruct the initial box, the first level represents the // initial domain x (the left node is x, the right one is an empty box). @@ -42,28 +45,40 @@ namespace codac2 c.contract(get<0>(n->boxes())); - if(!get<0>(n->boxes()).is_empty() && get<0>(n->boxes()).max_diam() > eps) + if(!get<0>(n->boxes()).is_empty()) { - n->bisect(); - l.push_back(n->left()); - l.push_back(n->right()); + if(get<0>(n->boxes()).max_diam() > eps) + { + n->bisect(); + l.push_back(n->left()); + l.push_back(n->right()); + } + + else if(verbose) + n_boundary++; } - } + } + if(verbose) + printf("Computation time: %.4fs, %ld boxes\n", + (double)(clock()-t_start)/CLOCKS_PER_SEC, n_boundary); return p; } - PavingInOut pave(const IntervalVector& x, std::shared_ptr s, double eps) + PavingInOut pave(const IntervalVector& x, std::shared_ptr s, double eps, bool verbose) { - return pave(x, *s, eps); + return pave(x, *s, eps, verbose); } - PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps) + PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps, bool verbose) { assert_release(eps > 0.); assert_release(!x.is_empty()); assert_release(s.size() >= 2 && "cannot reveal 1d separators"); + clock_t t_start = clock(); + Index n_boundary = 0; + PavingInOut p(x); std::shared_ptr n; list> l { p.tree() }; @@ -77,14 +92,23 @@ namespace codac2 auto boundary = (xs.inner & xs.outer); n->boxes() = { xs.outer, xs.inner }; - if(!boundary.is_empty() && boundary.max_diam() > eps) + if(!boundary.is_empty()) { - n->bisect(); - l.push_back(n->left()); - l.push_back(n->right()); + if(boundary.max_diam() > eps) + { + n->bisect(); + l.push_back(n->left()); + l.push_back(n->right()); + } + + else + n_boundary++; } } + if(verbose) + printf("Computation time: %.4fs, %ld boundary boxes\n", + (double)(clock()-t_start)/CLOCKS_PER_SEC, n_boundary); return p; } } \ No newline at end of file diff --git a/src/core/paver/codac2_pave.h b/src/core/paver/codac2_pave.h index 67ef50a44..5f6a6e95b 100644 --- a/src/core/paver/codac2_pave.h +++ b/src/core/paver/codac2_pave.h @@ -18,10 +18,10 @@ namespace codac2 { // eps: accuracy of the paving algorithm, the undefined boxes will have their max_diam <= eps - PavingOut pave(const IntervalVector& x, std::shared_ptr> c, double eps); - PavingOut pave(const IntervalVector& x, const CtcBase& c, double eps); - PavingInOut pave(const IntervalVector& x, std::shared_ptr s, double eps); - PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps); + PavingOut pave(const IntervalVector& x, std::shared_ptr> c, double eps, bool verbose = false); + PavingOut pave(const IntervalVector& x, const CtcBase& c, double eps, bool verbose = false); + PavingInOut pave(const IntervalVector& x, std::shared_ptr s, double eps, bool verbose = false); + PavingInOut pave(const IntervalVector& x, const SepBase& s, double eps, bool verbose = false); template PavingInOut sivia(const IntervalVector& x, const AnalyticFunction& f, const typename Y::Domain& y, double eps, bool verbose = false) @@ -54,8 +54,10 @@ namespace codac2 n->bisect(); l.push_back(n->left()); l.push_back(n->right()); - n_boundary++; } + + else + n_boundary++; } if(verbose) From eb0905687305e662cae44ee5d4d6512d40b396a5 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Fri, 17 Jan 2025 18:03:21 +0100 Subject: [PATCH 094/126] [doc] Doxygen: removing minimum version required --- doc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 41476ad2a..5312b9fd7 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -11,7 +11,7 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/mathjax_stmaryrd.js if(WITH_PYTHON) - find_package(Doxygen 1.13.0) + find_package(Doxygen) if(NOT DOXYGEN_FOUND) From 83b20bbbbfb95b6faaa2bc50e613ab81d917165a Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sat, 18 Jan 2025 23:46:38 +0100 Subject: [PATCH 095/126] Wrong type of comment for the current shell --- .github/workflows/unixmatrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unixmatrix.yml b/.github/workflows/unixmatrix.yml index 5f7155325..de736fb04 100644 --- a/.github/workflows/unixmatrix.yml +++ b/.github/workflows/unixmatrix.yml @@ -119,7 +119,7 @@ jobs: echo export BASHMINGWPATH=/c/ProgramData/mingw64/mingw${{ matrix.cfg.bitness }}/bin>>%USERPROFILE%\.bashrc if: (matrix.cfg.runtime=='mingw13') - run: | - #choco install -y -r --no-progress eigen --version=3.4.0.20240224 ${{ matrix.cfg.choco_flags }} + rem choco install -y -r --no-progress eigen --version=3.4.0.20240224 ${{ matrix.cfg.choco_flags }} wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex.2.8.9.20241117.nupkg --no-check-certificate -nv choco install -y -r --no-progress --ignore-dependencies -s . ibex --version=2.8.9.20241117 ${{ matrix.cfg.choco_flags }} --params "'/url:https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20241117/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip'" del /f /q ibex.2.8.9.20241117.nupkg From 327c91444dcf975ecbd25ed5214adfb1ad500fce Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sat, 18 Jan 2025 22:35:10 +0100 Subject: [PATCH 096/126] Attempt to solve error for some MinGW 32 bit configurations: out of memory allocating 4194292 bytes --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f88dbbc10..64f6b8cf1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,11 +61,18 @@ add_compile_options(-Wall -Wextra -Wpedantic) endif() - # Temporary fix in case of error: number of sections exceeded object file format limit. + # Temporary attempts to fix errors similar to: + # _ number of sections exceeded object file format limit. + # _ out of memory allocating XXX bytes. + # _ string table overflow. + # _ .obj: file too big. if(MSVC) add_compile_options(/bigobj) elseif(MINGW) add_compile_options(-Wa,-mbig-obj) + if (CMAKE_SIZEOF_VOID_P EQUAL 4) + add_compile_options(-g0) + endif() endif() # # Check that the compiler supports c++20 From 4d7ce144a37209803e51f1e3c5d052665ed80b4d Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Mon, 13 Jan 2025 22:32:58 +0100 Subject: [PATCH 097/126] Tests for CAPD --- .github/workflows/tests.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0efbe9c81..86cbf97b1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,9 @@ jobs: fail-fast: false matrix: cfg: - - { os: ubuntu-24.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, desc: 'Ubuntu 24.04 GCC 11 Python 3.10 tests' } + - { os: ubuntu-24.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_capd: OFF, desc: 'Ubuntu 24.04 GCC 11 Python 3.10 tests' } + - { os: ubuntu-24.04, gcc_v: 13, py_v_maj: 3, py_v_min: 12, with_capd: ON, desc: 'Ubuntu 24.04 GCC 13 Python 3.12 CAPD tests' } + - { os: ubuntu-22.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_capd: ON, desc: 'Ubuntu 22.04 GCC 11 Python 3.10 CAPD tests' } name: ${{ matrix.cfg.desc }} steps: - uses: actions/checkout@v4 @@ -68,6 +70,7 @@ jobs: # CAPD # cancelled on 2023/05/09: bash scripts/dependencies/install_capd.sh + if [ "${{ matrix.cfg.with_capd }}" = "ON" ]; then git clone --depth 1 -b master https://github.com/CAPDGroup/CAPD.git ; cd CAPD ; mkdir build ; cd build ; cmake .. ; cmake -E env CXXFLAGS="-fPIC" CFLAGS="-fPIC" sudo cmake --build . -j 4 --config Release --target install ; cd ../.. ; fi # Environment variables export CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:$HOME/codac/build_install @@ -85,7 +88,7 @@ jobs: cd build # Building lib + tests - cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DWITH_PYTHON=ON -DBUILD_TESTS=ON -DTEST_EXAMPLES=ON .. + cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DWITH_CAPD=${{ matrix.cfg.with_capd }} -DWITH_PYTHON=ON -DBUILD_TESTS=ON -DTEST_EXAMPLES=ON .. make -j 4 #make doc # todo make install From c1070879792d4da68f1693f330f364ae85ca10e6 Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sun, 19 Jan 2025 16:14:56 +0100 Subject: [PATCH 098/126] Add "ctest -C Debug -V --output-on-failure" to unixmatrix.yml --- .github/workflows/unixmatrix.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unixmatrix.yml b/.github/workflows/unixmatrix.yml index de736fb04..2c4c302dc 100644 --- a/.github/workflows/unixmatrix.yml +++ b/.github/workflows/unixmatrix.yml @@ -146,7 +146,7 @@ jobs: - run: | if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi mkdir build ; cd build - cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D CMAKE_INSTALL_PREFIX="../codac" .. + cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D BUILD_TESTS=ON -D CMAKE_INSTALL_PREFIX="../codac" .. cmake --build . -j 4 --config Debug --target install cd .. sed_param=s/PATH_SUFFIXES\ /PATHS\ \$\{CMAKE_CURRENT_LIST_FILE\}\\/..\\/..\\/..\\/..\\/\ PATH_SUFFIXES\ / @@ -214,6 +214,12 @@ jobs: overwrite: true tag_name: autotagname-${{ github.sha }} if: (github.event_name!='pull_request')&&((github.ref_name=='codac1')||(github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) + - run: | + if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi + cd build && ctest -C Debug -V --output-on-failure + cd .. + shell: bash + if: (matrix.cfg.cross!=true) - run: | if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi rm -Rf codac From ac81ee151c09816eef37010810f02123d5ec4ea1 Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sun, 19 Jan 2025 15:53:45 +0100 Subject: [PATCH 099/126] Default Doxygen of Ubuntu 22.04 causes issues and is not necessary for CAPD --- .github/workflows/tests.yml | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 86cbf97b1..2fbe2afa7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,9 +15,9 @@ jobs: fail-fast: false matrix: cfg: - - { os: ubuntu-24.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_capd: OFF, desc: 'Ubuntu 24.04 GCC 11 Python 3.10 tests' } - - { os: ubuntu-24.04, gcc_v: 13, py_v_maj: 3, py_v_min: 12, with_capd: ON, desc: 'Ubuntu 24.04 GCC 13 Python 3.12 CAPD tests' } - - { os: ubuntu-22.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_capd: ON, desc: 'Ubuntu 22.04 GCC 11 Python 3.10 CAPD tests' } + - { os: ubuntu-24.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_python: ON, with_capd: OFF, desc: 'Ubuntu 24.04 GCC 11 Python 3.10 tests' } + - { os: ubuntu-24.04, gcc_v: 13, py_v_maj: 3, py_v_min: 12, with_python: OFF, with_capd: ON, desc: 'Ubuntu 24.04 GCC 13 CAPD tests' } + - { os: ubuntu-22.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_python: OFF, with_capd: ON, desc: 'Ubuntu 22.04 GCC 11 CAPD tests' } name: ${{ matrix.cfg.desc }} steps: - uses: actions/checkout@v4 @@ -51,6 +51,9 @@ jobs: pip install sphinx breathe sphinx-issues sphinx-tabs sphinx_rtd_theme sudo apt-get -y install doxygen graphviz + # Doxygen might need to be upgraded + #if [ "${{ matrix.cfg.with_python }}" = "ON" ]; then git clone --depth 1 https://github.com/doxygen/doxygen.git ; cd doxygen ; mkdir build ; cd build ; cmake .. ; sudo cmake --build . -j 4 --config Release --target install ; cd ../.. ; fi + # For Python wrapping #pip install wheel #pip install --upgrade pip @@ -88,19 +91,23 @@ jobs: cd build # Building lib + tests - cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DWITH_CAPD=${{ matrix.cfg.with_capd }} -DWITH_PYTHON=ON -DBUILD_TESTS=ON -DTEST_EXAMPLES=ON .. + cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DWITH_CAPD=${{ matrix.cfg.with_capd }} -DWITH_PYTHON=${{ matrix.cfg.with_python }} -DBUILD_TESTS=ON -DTEST_EXAMPLES=ON .. make -j 4 #make doc # todo make install - cd python/python_package - python setup.py develop --user - #pip install -e . - cd ../../ + if [ "${{ matrix.cfg.with_python }}" = "ON" ]; then + cd python/python_package + python setup.py develop --user + #pip install -e . + cd ../../ - python ../tests/core/domains/codac2_tests_BoolInterval.py + python ../tests/core/domains/codac2_tests_BoolInterval.py + fi make test - python -m unittest discover codac.tests + if [ "${{ matrix.cfg.with_python }}" = "ON" ]; then + python -m unittest discover codac.tests + fi ## Building the examples From 2e7877f078da62639b114f9882060ba0228c5018 Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sun, 19 Jan 2025 16:14:56 +0100 Subject: [PATCH 100/126] Add "ctest -C Debug -V --output-on-failure" to unixmatrix.yml --- .github/workflows/unixmatrix.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unixmatrix.yml b/.github/workflows/unixmatrix.yml index 41c66beaf..97060bd66 100644 --- a/.github/workflows/unixmatrix.yml +++ b/.github/workflows/unixmatrix.yml @@ -146,7 +146,7 @@ jobs: - run: | if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi mkdir build ; cd build - cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D CMAKE_INSTALL_PREFIX="../codac" .. + cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D BUILD_TESTS=ON -D CMAKE_INSTALL_PREFIX="../codac" .. cmake --build . -j 4 --config Debug --target install cd .. sed_param=s/PATH_SUFFIXES\ /PATHS\ \$\{CMAKE_CURRENT_LIST_FILE\}\\/..\\/..\\/..\\/..\\/\ PATH_SUFFIXES\ / @@ -214,6 +214,12 @@ jobs: overwrite: true tag_name: autotagname-${{ github.sha }} if: (github.event_name!='pull_request')&&((github.ref_name=='codac1')||(github.ref_name=='codac2')||(github.ref_name=='codac2_codac4matlab')) + - run: | + if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi + cd build && ctest -C Debug -V --output-on-failure + cd .. + shell: bash + if: (matrix.cfg.cross!=true) - run: | if [ ${{ runner.os }} = Windows ]; then source ~/refreshenv.bashrc ; refreshenv ; export PATH=$BASHMINGWPATH:$PATH ; fi rm -Rf codac From 5352b2b48d813c9c4e566b3c4a5c04a35aefc065 Mon Sep 17 00:00:00 2001 From: godardma Date: Mon, 20 Jan 2025 15:42:13 +0100 Subject: [PATCH 101/126] CMakeLists modifications --- doc/manual/manual/visualization/figures.rst | 43 +++++++++++++++++---- examples/01_batman/CMakeLists.txt | 12 +----- examples/02_centered_form/CMakeLists.txt | 12 +----- examples/03_sivia/CMakeLists.txt | 12 +----- examples/04_explored_area/CMakeLists.txt | 12 +----- src/CMakeLists.txt | 9 ++++- src/unsupported/CMakeLists.txt | 1 - 7 files changed, 47 insertions(+), 54 deletions(-) diff --git a/doc/manual/manual/visualization/figures.rst b/doc/manual/manual/visualization/figures.rst index 170f157e4..fa5fede38 100644 --- a/doc/manual/manual/visualization/figures.rst +++ b/doc/manual/manual/visualization/figures.rst @@ -5,6 +5,8 @@ The Figure classes This page describes the classes used in Codac for 2D visualization. +.. _subsec-graphics-figures-graphical-outputs: + Graphical outputs ----------------- @@ -27,11 +29,14 @@ visualization while IPE creates a file that can be edited by the IPE editor. The Note that for the VIBes output to work, the VIBes viewer must be launched before the program is run. +.. _subsec-graphics-figures-figure2d: + Figure2D -------- - - +The basic class for 2D visualization is Figure2D. It is used to create a figure that can be displayed in VIBes or saved in an xml file for IPE. +The constructor takes two arguments: the name of the figure and the graphical output. A boolean can be added to specify if the figure is to be used +DefaultView (see :ref:`_subsec-graphics-figures-figure2d-defaultview`). .. tabs:: @@ -39,24 +44,25 @@ Figure2D from codac import * - # .. next questions will be here + fig = Figure2D("My figure", GraphicOutput.VIBES | GraphicOutput.IPE) # for both VIBes and IPE .. code-tab:: c++ - #include + #include - using namespace std; using namespace codac; int main() { - // .. next questions will be here + Figure2D figure ("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); // for both VIBes and IPE } +.. _subsec-graphics-figures-figure2d-defaultview: + DefaultView ----------- -A DefaultView using only VIBes as graphical output is available. This figure is for example used in `draw_while_paving` by default. +A DefaultView using only VIBes as graphical output is available. This figure is the one used by the function `draw_while_paving` by default. Any Figure2D object can be used as DefaultView with the set method: .. tabs:: @@ -69,4 +75,25 @@ Any Figure2D object can be used as DefaultView with the set method: .. code-tab:: c++ Figure2D figure = std::make_shared("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); - DefaultView::set(figure); \ No newline at end of file + DefaultView::set(figure); + +Equivalently, a Figure2D can be used as DefaultView by setting the flag `set_as_default` to true in the constructor: + +.. tabs:: + + .. code-tab:: py + + from codac import * + + fig = Figure2D("My figure", GraphicOutput.VIBES | GraphicOutput.IPE, True) + + .. code-tab:: c++ + + #include + + using namespace codac; + + int main() + { + Figure2D figure ("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE,true); + } \ No newline at end of file diff --git a/examples/01_batman/CMakeLists.txt b/examples/01_batman/CMakeLists.txt index 314b49ffc..f22f661ab 100644 --- a/examples/01_batman/CMakeLists.txt +++ b/examples/01_batman/CMakeLists.txt @@ -8,16 +8,6 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# Adding IBEX - - # In case you installed IBEX in a local directory, you need - # to specify its path with the CMAKE_PREFIX_PATH option. - # set(CMAKE_PREFIX_PATH "~/ibex-lib/build_install") - - find_package(IBEX REQUIRED) - ibex_init_common() # IBEX should have installed this function - message(STATUS "Found IBEX version ${IBEX_VERSION}") - # Adding Codac # In case you installed Codac in a local directory, you need @@ -37,4 +27,4 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES}) \ No newline at end of file diff --git a/examples/02_centered_form/CMakeLists.txt b/examples/02_centered_form/CMakeLists.txt index 314b49ffc..f22f661ab 100644 --- a/examples/02_centered_form/CMakeLists.txt +++ b/examples/02_centered_form/CMakeLists.txt @@ -8,16 +8,6 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# Adding IBEX - - # In case you installed IBEX in a local directory, you need - # to specify its path with the CMAKE_PREFIX_PATH option. - # set(CMAKE_PREFIX_PATH "~/ibex-lib/build_install") - - find_package(IBEX REQUIRED) - ibex_init_common() # IBEX should have installed this function - message(STATUS "Found IBEX version ${IBEX_VERSION}") - # Adding Codac # In case you installed Codac in a local directory, you need @@ -37,4 +27,4 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES}) \ No newline at end of file diff --git a/examples/03_sivia/CMakeLists.txt b/examples/03_sivia/CMakeLists.txt index 314b49ffc..f22f661ab 100644 --- a/examples/03_sivia/CMakeLists.txt +++ b/examples/03_sivia/CMakeLists.txt @@ -8,16 +8,6 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# Adding IBEX - - # In case you installed IBEX in a local directory, you need - # to specify its path with the CMAKE_PREFIX_PATH option. - # set(CMAKE_PREFIX_PATH "~/ibex-lib/build_install") - - find_package(IBEX REQUIRED) - ibex_init_common() # IBEX should have installed this function - message(STATUS "Found IBEX version ${IBEX_VERSION}") - # Adding Codac # In case you installed Codac in a local directory, you need @@ -37,4 +27,4 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES}) \ No newline at end of file diff --git a/examples/04_explored_area/CMakeLists.txt b/examples/04_explored_area/CMakeLists.txt index 314b49ffc..f22f661ab 100644 --- a/examples/04_explored_area/CMakeLists.txt +++ b/examples/04_explored_area/CMakeLists.txt @@ -8,16 +8,6 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# Adding IBEX - - # In case you installed IBEX in a local directory, you need - # to specify its path with the CMAKE_PREFIX_PATH option. - # set(CMAKE_PREFIX_PATH "~/ibex-lib/build_install") - - find_package(IBEX REQUIRED) - ibex_init_common() # IBEX should have installed this function - message(STATUS "Found IBEX version ${IBEX_VERSION}") - # Adding Codac # In case you installed Codac in a local directory, you need @@ -37,4 +27,4 @@ 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}) - target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES} Ibex::ibex) \ No newline at end of file + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES}) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a3f79a44..e2f45a8c1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,8 +63,11 @@ find_library(CODAC_UNSUPPORTED_LIBRARY NAMES ${PROJECT_NAME}-unsupported PATH_SUFFIXES lib) + find_package(IBEX REQUIRED) + ibex_init_common() + set(CODAC_VERSION ${PROJECT_VERSION}) - set(CODAC_LIBRARIES \${CODAC_CORE_LIBRARY} \${CODAC_GRAPHICS_LIBRARY} \${CODAC_UNSUPPORTED_LIBRARY} \${CODAC_CORE_LIBRARY}) + set(CODAC_LIBRARIES \${CODAC_CORE_LIBRARY} \${CODAC_GRAPHICS_LIBRARY} \${CODAC_UNSUPPORTED_LIBRARY} Ibex::ibex) set(CODAC_INCLUDE_DIRS \${CODAC_CORE_INCLUDE_DIR}/../ \${CODAC_CORE_INCLUDE_DIR}/../eigen3/ \${CODAC_CORE_INCLUDE_DIR} \${CODAC_GRAPHICS_INCLUDE_DIR} \${CODAC_UNSUPPORTED_INCLUDE_DIR}) set(CODAC_C_FLAGS \"\") @@ -108,6 +111,10 @@ endif() + file(APPEND ${CODAC_CMAKE_CONFIG_FILE} " + set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_GRAPHICS_LIBRARY} \${CODAC_CORE_LIBRARY}) + ") + install(FILES ${CODAC_CMAKE_CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_CMAKE}) diff --git a/src/unsupported/CMakeLists.txt b/src/unsupported/CMakeLists.txt index efe341957..6d3bd2b25 100644 --- a/src/unsupported/CMakeLists.txt +++ b/src/unsupported/CMakeLists.txt @@ -52,7 +52,6 @@ # Generating the file codac-unsupported.h set(CODAC_UNSUPPORTED_MAIN_HEADER ${CMAKE_CURRENT_BINARY_DIR}/codac-unsupported.h) - set(CODAC_MAIN_SUBHEADERS ${CODAC_MAIN_SUBHEADERS} "codac-unsupported.h" PARENT_SCOPE) file(WRITE ${CODAC_UNSUPPORTED_MAIN_HEADER} "/* This file is generated by CMake */\n\n") file(APPEND ${CODAC_UNSUPPORTED_MAIN_HEADER} "#pragma once\n\n") foreach(header_path ${CODAC_UNSUPPORTED_HDR}) From be7854c90c27dc9cbb647ac74fc5b79a4e246b76 Mon Sep 17 00:00:00 2001 From: godardma Date: Mon, 20 Jan 2025 15:46:17 +0100 Subject: [PATCH 102/126] [doc] figure class done --- doc/manual/manual/visualization/figures.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/manual/manual/visualization/figures.rst b/doc/manual/manual/visualization/figures.rst index fa5fede38..acc3f9c63 100644 --- a/doc/manual/manual/visualization/figures.rst +++ b/doc/manual/manual/visualization/figures.rst @@ -36,7 +36,7 @@ Figure2D The basic class for 2D visualization is Figure2D. It is used to create a figure that can be displayed in VIBes or saved in an xml file for IPE. The constructor takes two arguments: the name of the figure and the graphical output. A boolean can be added to specify if the figure is to be used -DefaultView (see :ref:`_subsec-graphics-figures-figure2d-defaultview`). +DefaultView (see :ref:`subsec-graphics-figures-figure2d-defaultview`). .. tabs:: @@ -44,7 +44,7 @@ DefaultView (see :ref:`_subsec-graphics-figures-figure2d-defaultview`). from codac import * - fig = Figure2D("My figure", GraphicOutput.VIBES | GraphicOutput.IPE) # for both VIBes and IPE + fig = Figure2D("My figure", GraphicOutput.VIBES | GraphicOutput.IPE) .. code-tab:: c++ @@ -54,7 +54,7 @@ DefaultView (see :ref:`_subsec-graphics-figures-figure2d-defaultview`). int main() { - Figure2D figure ("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); // for both VIBes and IPE + Figure2D figure ("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); } .. _subsec-graphics-figures-figure2d-defaultview: From a521be00968543133e94d9fa696d0e44216b9afd Mon Sep 17 00:00:00 2001 From: godardma Date: Mon, 20 Jan 2025 16:42:34 +0100 Subject: [PATCH 103/126] attempt to solve actions not passing --- examples/01_batman/CMakeLists.txt | 4 ++++ examples/02_centered_form/CMakeLists.txt | 4 ++++ examples/03_sivia/CMakeLists.txt | 4 ++++ examples/04_explored_area/CMakeLists.txt | 4 ++++ src/CMakeLists.txt | 1 - 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/examples/01_batman/CMakeLists.txt b/examples/01_batman/CMakeLists.txt index f22f661ab..cf89b0f69 100644 --- a/examples/01_batman/CMakeLists.txt +++ b/examples/01_batman/CMakeLists.txt @@ -17,6 +17,10 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") +# Initializating Ibex + + ibex_init_common() + # Compilation if(FAST_RELEASE) diff --git a/examples/02_centered_form/CMakeLists.txt b/examples/02_centered_form/CMakeLists.txt index f22f661ab..cf89b0f69 100644 --- a/examples/02_centered_form/CMakeLists.txt +++ b/examples/02_centered_form/CMakeLists.txt @@ -17,6 +17,10 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") +# Initializating Ibex + + ibex_init_common() + # Compilation if(FAST_RELEASE) diff --git a/examples/03_sivia/CMakeLists.txt b/examples/03_sivia/CMakeLists.txt index f22f661ab..cf89b0f69 100644 --- a/examples/03_sivia/CMakeLists.txt +++ b/examples/03_sivia/CMakeLists.txt @@ -17,6 +17,10 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") +# Initializating Ibex + + ibex_init_common() + # Compilation if(FAST_RELEASE) diff --git a/examples/04_explored_area/CMakeLists.txt b/examples/04_explored_area/CMakeLists.txt index f22f661ab..cf89b0f69 100644 --- a/examples/04_explored_area/CMakeLists.txt +++ b/examples/04_explored_area/CMakeLists.txt @@ -17,6 +17,10 @@ find_package(CODAC REQUIRED) message(STATUS "Found Codac version ${CODAC_VERSION}") +# Initializating Ibex + + ibex_init_common() + # Compilation if(FAST_RELEASE) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e2f45a8c1..e18427a99 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,7 +64,6 @@ PATH_SUFFIXES lib) find_package(IBEX REQUIRED) - ibex_init_common() set(CODAC_VERSION ${PROJECT_VERSION}) set(CODAC_LIBRARIES \${CODAC_CORE_LIBRARY} \${CODAC_GRAPHICS_LIBRARY} \${CODAC_UNSUPPORTED_LIBRARY} Ibex::ibex) From a0f4ae0814180130a70cca5938d859e9da7f7d5d Mon Sep 17 00:00:00 2001 From: godardma Date: Mon, 20 Jan 2025 17:02:41 +0100 Subject: [PATCH 104/126] [doc] correction on figures --- doc/manual/manual/visualization/figures.rst | 4 +- examples/00_graphics/CMakeLists.txt | 34 +++++++++++++++++ examples/00_graphics/graphic_examples.cpp | 41 +++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 examples/00_graphics/CMakeLists.txt create mode 100644 examples/00_graphics/graphic_examples.cpp diff --git a/doc/manual/manual/visualization/figures.rst b/doc/manual/manual/visualization/figures.rst index acc3f9c63..8853feb05 100644 --- a/doc/manual/manual/visualization/figures.rst +++ b/doc/manual/manual/visualization/figures.rst @@ -74,9 +74,11 @@ Any Figure2D object can be used as DefaultView with the set method: .. code-tab:: c++ - Figure2D figure = std::make_shared("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); + std::shared_ptr figure = std::make_shared("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); DefaultView::set(figure); +Note that in C++ the figure must be a shared pointer in order to be passed to the `set` method. + Equivalently, a Figure2D can be used as DefaultView by setting the flag `set_as_default` to true in the constructor: .. tabs:: diff --git a/examples/00_graphics/CMakeLists.txt b/examples/00_graphics/CMakeLists.txt new file mode 100644 index 000000000..6219b4dab --- /dev/null +++ b/examples/00_graphics/CMakeLists.txt @@ -0,0 +1,34 @@ +# ================================================================== +# codac / basics example - cmake configuration file +# ================================================================== + + cmake_minimum_required(VERSION 3.0.2) + project(codac_example LANGUAGES CXX) + + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Adding Codac + + # In case you installed Codac in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option. + # set(CMAKE_PREFIX_PATH "~/codac/build_install") + + find_package(CODAC REQUIRED) + message(STATUS "Found Codac version ${CODAC_VERSION}") + +# Initializating Ibex + + ibex_init_common() + +# Compilation + + if(FAST_RELEASE) + add_compile_definitions(FAST_RELEASE) + message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") + endif() + + add_executable(${PROJECT_NAME} graphic_examples.cpp) + target_compile_options(${PROJECT_NAME} PUBLIC ${CODAC_CXX_FLAGS}) + target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CODAC_INCLUDE_DIRS}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES}) \ No newline at end of file diff --git a/examples/00_graphics/graphic_examples.cpp b/examples/00_graphics/graphic_examples.cpp new file mode 100644 index 000000000..35266b3a9 --- /dev/null +++ b/examples/00_graphics/graphic_examples.cpp @@ -0,0 +1,41 @@ +#include + +using namespace std; +using namespace codac2; + +int main(){ + + // Graphics can be directly called without a Figure2D instanciation, using "DefaultView" + + DefaultView::set_window_properties({600,600},{300,300}); + DefaultView::draw_box({{2.2,2.5},{2.2,2.5}},{Color::black(),Color::yellow(0.5)}); + DefaultView::draw_AUV({1,1,3.14/2},1.,{Color::black(),Color::yellow()}); + DefaultView::draw_tank({2,1,3.14/2},1.,{Color::black(),Color::yellow()}); + DefaultView::draw_pie({2,2},{1.5,2.5},{(3*3.14/4)-0.5,(3*3.14/4)+0.5},{Color::blue(),Color::cyan()}); + DefaultView::draw_polyline({{2,-0.5},{4,0.5},{3,1.5},{4,2.5},{3,3}}, Color::red()); + DefaultView::draw_polygone({{2,4.5},{4,4.5},{4.2,3.5},{3.5,3}}, {Color::none(),Color::green(0.5)}); + DefaultView::draw_polyline({{-0.8,0},{0,1.5}}, 0.2, {Color::red(),Color::black(0.3)}); + + // Last argument corresponds to "StyleProperties" with one or two colors: edge color + (optional) fill color + // Predefined Color objects can be configured with a float parameter for opacity (1=opaque, 0=transparent) + + // Custom figures can also be created: + std::shared_ptr fig1 = std::make_shared("My Figure 1",GraphicOutput::VIBES|GraphicOutput::IPE); + + // Here, graphics will be rendered by two tools: both VIBES and IPE + // For VIBES, it requires the VIBes viewer to be launched prior to the execution + // For IPE, it generates a file named "My figure 1.xml" that can be edited with IPE, and converted to PDF + + fig1->set_window_properties({50,50},{500,500}); // position, window size + fig1->set_axes(axis(0,{-10,10}), axis(1,{-10,10})); // (axis_id,{range_of_values_on_this_axis}) + fig1->draw_box({{-1,1},{-1,1}},{Color::green(),Color::red(0.2)}); // drawing a green box with red opacity values inside + fig1->draw_circle({1,1},0.5,Color({255,155,5})); // drawing a circle at (1,1) of radius 0.5 with a custom RGB color + fig1->draw_ring({1,1},{4,6},Color::red()); // drawing a ring at (1,1) of radius {4,6} with a predefined red color + + std::shared_ptr fig2 = std::make_shared("My Figure 2",GraphicOutput::VIBES|GraphicOutput::IPE); + fig2->set_axes(axis(0,{-1,5}), axis(1,{-1,5})); + fig2->set_window_properties({250,250},{500,500}); + + // The previously declared figure "fig2" can now be used as a DefaultView + DefaultView::set(fig2); +} From ce1641314db1ccfce9f4bfdf732d1b56b1f0c608 Mon Sep 17 00:00:00 2001 From: godardma Date: Mon, 20 Jan 2025 17:39:15 +0100 Subject: [PATCH 105/126] corrected graphic example --- doc/manual/manual/visualization/figures.rst | 37 +++++++------- examples/00_graphics/graphic_examples.cpp | 53 +++++++++++++++++++++ examples/00_graphics/graphic_examples.py | 10 ++-- 3 files changed, 77 insertions(+), 23 deletions(-) diff --git a/doc/manual/manual/visualization/figures.rst b/doc/manual/manual/visualization/figures.rst index 8853feb05..f25f0aad9 100644 --- a/doc/manual/manual/visualization/figures.rst +++ b/doc/manual/manual/visualization/figures.rst @@ -42,20 +42,11 @@ DefaultView (see :ref:`subsec-graphics-figures-figure2d-defaultview`). .. code-tab:: py - from codac import * - fig = Figure2D("My figure", GraphicOutput.VIBES | GraphicOutput.IPE) .. code-tab:: c++ - #include - - using namespace codac; - - int main() - { - Figure2D figure ("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); - } + Figure2D figure ("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE); .. _subsec-graphics-figures-figure2d-defaultview: @@ -85,17 +76,27 @@ Equivalently, a Figure2D can be used as DefaultView by setting the flag `set_as_ .. code-tab:: py - from codac import * - fig = Figure2D("My figure", GraphicOutput.VIBES | GraphicOutput.IPE, True) .. code-tab:: c++ - #include + Figure2D figure ("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE,true); + +.. _subsec-graphics-figures-figure2d-figure-properties: + +Figure properties +----------------- + +Once created, the properties of a Figure2D object can be modified using the following methods: + +.. tabs:: - using namespace codac; + .. code-tab:: py + + fig.set_window_properties([50,50],[500,500]) # set the window position and size + fig.set_axes(axis(0,[-10,10]), axis(1,[-10,10])) # set the range of values on each axis : 0 for x-axis, 1 for y-axis + + .. code-tab:: c++ - int main() - { - Figure2D figure ("My Figure",GraphicOutput::VIBES|GraphicOutput::IPE,true); - } \ No newline at end of file + fig.set_window_properties({50,50},{500,500}); // set the window position and size + fig.set_axes(axis(0,{-10,10}), axis(1,{-10,10})); // set the range of values on each axis : 0 for x-axis, 1 for y-axis \ No newline at end of file diff --git a/examples/00_graphics/graphic_examples.cpp b/examples/00_graphics/graphic_examples.cpp index 35266b3a9..1f69f70a8 100644 --- a/examples/00_graphics/graphic_examples.cpp +++ b/examples/00_graphics/graphic_examples.cpp @@ -38,4 +38,57 @@ int main(){ // The previously declared figure "fig2" can now be used as a DefaultView DefaultView::set(fig2); + DefaultView::draw_box({{2.2,2.5},{2.2,2.5}},{Color::black(),Color::green(0.8)}); + + DefaultView::set(fig1); + DefaultView::draw_box({{2.2,2.5},{2.2,2.5}},{Color::blue(),Color::cyan(0.8)}); + + fig2->draw_AUV({1,1,3.14/2},2.,{Color::black(),Color::yellow()}); + fig2->draw_tank({2,1,3.14/2},1.,{Color::black(),Color::yellow()}); + fig2->draw_pie({2,2},{1.5,2.5},{(3*3.14/4)-0.5,(3*3.14/4)+0.5},{Color::blue(),Color::cyan()}); + fig2->draw_polyline({{2,-0.5},{4,0.5},{3,1.5},{4,2.5},{3,3}}, Color::red()); + fig2->draw_polygone({{2,4.5},{4,4.5},{4.2,3.5},{3.5,3}}, {Color::none(),Color::green(0.5)}); + fig2->draw_polyline({{-0.8,0},{0,1.5}}, 0.2, {Color::red(),Color::black(0.3)}); + fig2->draw_ellipse({1,1},{0.5,2}, 0.2, {Color::blue(),Color::blue(0.3)}); + fig2->draw_line({1,1},{3,3}, Color::blue()); + fig2->draw_arrow({3,1},{2.2,2}, 0.2, {Color::red(),Color::black(0.3)}); + + // Colors + // predefined colors without and with opacity + fig2->draw_point({2,2}, {Color::red(),Color::yellow(0.5)}); + // HTML color without and with opacity + fig2->draw_box({{2.4,2.9},{2.4,2.9}},{Color("#da3907"),Color("#da390755")}); + // HSV color without and with opacity + fig2->draw_box({{2.6,3.1},{2.6,3.1}},{Color({108,90,78},Model::HSV),Color({108,90,78,20},Model::HSV)}); + + Figure2D fig3 ("My Figure 3",GraphicOutput::VIBES|GraphicOutput::IPE); + fig3.set_axes(axis(0,{-1,21}), axis(1,{-5.5,0.5})); + fig3.set_window_properties({800,250},{500,500}); + + ColorMap cmap_haxby = ColorMap::haxby(); + ColorMap cmap_default = ColorMap::basic(); + ColorMap cmap_blue_tube = ColorMap::blue_tube(); + ColorMap cmap_red_tube = ColorMap::red_tube(); + ColorMap cmap_rainbow = ColorMap::rainbow(); + + for (double i=0.; i<20; i++) + { + double ratio = i/20.; + fig3.draw_box({{i,i+1},{-1,0}},{Color::black(),cmap_haxby.color(ratio)}); + fig3.draw_box({{i,i+1},{-2,-1}},{Color::black(),cmap_default.color(ratio)}); + fig3.draw_box({{i,i+1},{-3,-2}},{Color::black(),cmap_blue_tube.color(ratio)}); + fig3.draw_box({{i,i+1},{-4,-3}},{Color::black(),cmap_red_tube.color(ratio)}); + fig3.draw_box({{i,i+1},{-5,-4}},{Color::black(),cmap_rainbow.color(ratio)}); + } + + Figure2D fig4 ("My Figure 4",GraphicOutput::VIBES); + + fig4.set_axes(axis(0,{-10,10}), axis(1,{-10,10})); + + double a=0.5; + ScalarVar t; + // Fermat's spiral + AnalyticFunction f1 ({t},{a*sqrt(t)*cos(t),a*sqrt(t)*sin(t)}); + AnalyticTraj traj4 (f1,{0,100}); + fig4.draw_trajectory(traj4,ColorMap::rainbow()); } diff --git a/examples/00_graphics/graphic_examples.py b/examples/00_graphics/graphic_examples.py index f6c8770e2..d0a5b2538 100644 --- a/examples/00_graphics/graphic_examples.py +++ b/examples/00_graphics/graphic_examples.py @@ -75,14 +75,14 @@ fig3.draw_box([[i,i+1],[-4,-3]],[Color.black(),cmap_red_tube.color(ratio)]) fig3.draw_box([[i,i+1],[-5,-4]],[Color.black(),cmap_rainbow.color(ratio)]) -fig3 = Figure2D("My figure 3", GraphicOutput.VIBES) +fig4 = Figure2D("My figure 4", GraphicOutput.VIBES) -fig3.set_window_properties([500,50],[500,500]) -fig3.set_axes(axis(0,[-10,10]), axis(1,[-10,10])) +fig4.set_window_properties([500,50],[500,500]) +fig4.set_axes(axis(0,[-10,10]), axis(1,[-10,10])) a = 0.8 t=ScalarVar() # Fermat's spiral f1=AnalyticFunction([t], [a*sqrt(t)*cos(t),a*sqrt(t)*sin(t)]) -traj3=AnalyticTrajectory(f1, [0,100]) -fig3.draw_trajectory(traj3, ColorMap.rainbow()) \ No newline at end of file +traj4=AnalyticTraj(f1, [0,100]) +fig4.draw_trajectory(traj4, ColorMap.rainbow()) \ No newline at end of file From 2b30bf74694efd4dfd5a1bf06201ef3a72a8e347 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Mon, 20 Jan 2025 18:29:44 +0100 Subject: [PATCH 106/126] [doc] updated manual (info dev) --- doc/manual/development/info_dev.rst | 27 +++++++++++++++++++++----- doc/manual/manual/installation/cpp.rst | 4 ++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/doc/manual/development/info_dev.rst b/doc/manual/development/info_dev.rst index 7fd6e3de0..2a3c32670 100644 --- a/doc/manual/development/info_dev.rst +++ b/doc/manual/development/info_dev.rst @@ -35,7 +35,12 @@ If you simply want to use the latest Codac release in Python, you can download t 1. **Ensure the following prerequisites are met**: - - the prerequisites for the :ref:`C++ installation of Codac `. + - the prerequisites for the :ref:`C++ installation of Codac `. On Linux systems, you can simply: + + .. code-block:: bash + + sudo apt-get install -y g++ gcc cmake git flex bison + - a supported version of Python (>=3.6). - a recent `Doxygen `_ 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: @@ -60,13 +65,14 @@ If you simply want to use the latest Codac release in Python, you can download t .. code-block:: bash - git clone -b master https://github.com/lebarsfa/ibex-lib.git $HOME/ibex-lib + git clone https://github.com/lebarsfa/ibex-lib.git $HOME/ibex-lib + cd $HOME/ibex-lib You will need to compile both IBEX and Codac using the ``-fPIC`` options. This can be done with the following CMake configuration: .. code-block:: bash - cd $HOME/ibex-lib/build + mkdir build ; cd build cmake -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DCMAKE_INSTALL_PREFIX=$HOME/ibex-lib/build_install -DCMAKE_BUILD_TYPE=Release .. make ; make install @@ -77,16 +83,27 @@ If you simply want to use the latest Codac release in Python, you can download t .. code-block:: bash git clone https://github.com/codac-team/codac $HOME/codac + cd $HOME/codac + + .. admonition:: Using Codac v2 simultaneously with Codac v1 + + In case you want to use the two versions of Codac in the same Python script, you will have to compile the binaries of Codac v2 under a different name in order to avoid ``import`` conflicts. Things are already prepared in the branch ``codac2_renamed``, you can therefore: + + .. code-block:: bash + + git checkout codac2_renamed + + Note that you will then have to ``import codac2`` instead of ``import codac`` in your Python scripts. In addition to the ``-fPIC`` options, you will have to configure ``WITH_PYTHON=ON``. Note that the ``git submodule`` commands will automatically get the `pybind11 `_ files required for the binding. .. code-block:: bash - cd $HOME/codac/build # Get automatically pybind11 and eigen submodules: git submodule init ; git submodule update # Configure CMake - 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 .. + mkdir build ; cd build + 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;$HOME/doxygen/build_install" -DCMAKE_BUILD_TYPE=Release .. make ; make install 4. **Configure your Python environment**: diff --git a/doc/manual/manual/installation/cpp.rst b/doc/manual/manual/installation/cpp.rst index 374b445aa..bfac3a8a3 100644 --- a/doc/manual/manual/installation/cpp.rst +++ b/doc/manual/manual/installation/cpp.rst @@ -263,8 +263,8 @@ Troubleshooting ---------------- If you encounter issues during the installation process, consider the following: -- Ensure all prerequisites are installed and up to date. -- Check `the GitHub issues `_ page for known problems. +- ensure all prerequisites are installed and up to date. +- check `the GitHub issues `_ page for known problems. If you need further assistance, reach out to the library maintainers via the GitHub repository's issue tracker or email support at `simon.rohou [at] ensta.fr`. From 26beffe05dacf8e06f246924d9c6196d4c39906a Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Mon, 20 Jan 2025 19:17:30 +0100 Subject: [PATCH 107/126] [traj] updated eval methods --- examples/00_graphics/graphic_examples.py | 2 +- examples/04_explored_area/main.cpp | 2 +- examples/04_explored_area/main.py | 2 +- .../trajectory/codac2_py_AnalyticTraj.cpp | 14 ++++++ .../core/trajectory/codac2_py_SampledTraj.cpp | 38 ++++++++++++---- .../src/core/trajectory/codac2_py_TrajBase.h | 14 ------ .../domains/ellipsoid/codac2_Ellipsoid.cpp | 8 ++-- src/core/trajectory/codac2_SampledTraj.h | 45 +++++++++++++++++-- src/core/trajectory/codac2_TrajBase.h | 10 ++--- 9 files changed, 96 insertions(+), 39 deletions(-) diff --git a/examples/00_graphics/graphic_examples.py b/examples/00_graphics/graphic_examples.py index f6c8770e2..f753ba5cc 100644 --- a/examples/00_graphics/graphic_examples.py +++ b/examples/00_graphics/graphic_examples.py @@ -84,5 +84,5 @@ t=ScalarVar() # Fermat's spiral f1=AnalyticFunction([t], [a*sqrt(t)*cos(t),a*sqrt(t)*sin(t)]) -traj3=AnalyticTrajectory(f1, [0,100]) +traj3=AnalyticTraj(f1, [0,100]) fig3.draw_trajectory(traj3, ColorMap.rainbow()) \ No newline at end of file diff --git a/examples/04_explored_area/main.cpp b/examples/04_explored_area/main.cpp index fb474e3ff..739dd90a5 100644 --- a/examples/04_explored_area/main.cpp +++ b/examples/04_explored_area/main.cpp @@ -19,7 +19,7 @@ int main() Interval tdomain(0,5); auto sampled_f = AnalyticTraj(f,tdomain).sampled(0.8); - sampled_f[6] = {0,-1}; // appending the position (0,-1) at t=6 + sampled_f.set(6., {0,-1}); // appending the position (0,-1) at t=6 VectorVar w(3); auto g = sampled_f.as_function(); diff --git a/examples/04_explored_area/main.py b/examples/04_explored_area/main.py index 7f0c13662..e0291553f 100644 --- a/examples/04_explored_area/main.py +++ b/examples/04_explored_area/main.py @@ -15,7 +15,7 @@ tdomain = [0,5] sampled_f = AnalyticTraj(f,tdomain).sampled(0.8) -sampled_f[6] = [0,-1] # appending the position (0,-1) at t=6 +sampled_f.set(6, [0,-1]) # appending the position (0,-1) at t=6 w = VectorVar(3) g = sampled_f.as_function() diff --git a/python/src/core/trajectory/codac2_py_AnalyticTraj.cpp b/python/src/core/trajectory/codac2_py_AnalyticTraj.cpp index e3f0aa2bb..9beb9cb69 100644 --- a/python/src/core/trajectory/codac2_py_AnalyticTraj.cpp +++ b/python/src/core/trajectory/codac2_py_AnalyticTraj.cpp @@ -36,6 +36,20 @@ void _export_AnalyticTraj(py::module& m, const string& class_name) ANALYTICTRAJ_OS_ANALYTICTRAJ_CONST_ANALYTICFUNCTION_O_REF_CONST_INTERVAL_REF, "f"_a, "tdomain"_a) + .def("__call__", [](const AnalyticTraj& x, double t) + { + return x(t); + }, + VIRTUAL_S_ANALYTICTRAJ_OS_OPERATORCALL_DOUBLE_CONST, + "t"_a) + + .def("__call__", [](const AnalyticTraj& x, const Interval& t) + { + return x(t); + }, + VIRTUAL_WRAPPER_S_DOMAIN_ANALYTICTRAJ_OS_OPERATORCALL_CONST_INTERVAL_REF_CONST, + "t"_a) + ; } diff --git a/python/src/core/trajectory/codac2_py_SampledTraj.cpp b/python/src/core/trajectory/codac2_py_SampledTraj.cpp index a1127e25b..cd739142a 100644 --- a/python/src/core/trajectory/codac2_py_SampledTraj.cpp +++ b/python/src/core/trajectory/codac2_py_SampledTraj.cpp @@ -50,6 +50,7 @@ py::class_> _export_SampledTraj(py::module& m, const string& clas else if constexpr(std::is_same_v) { exported_class + .def(py::init( [](const py::array_t& l_t, const py::array_t& l_x) { @@ -85,6 +86,18 @@ py::class_> _export_SampledTraj(py::module& m, const string& clas }), SAMPLEDTRAJ_T_SAMPLEDTRAJ_CONST_LIST_DOUBLE_REF_CONST_LIST_T_REF, "l_t"_a, "l_x"_a) + + .def("__getitem__", [](const SampledTraj& x, Index_type i) -> SampledTraj + { + matlab::test_integer(i); + return x[matlab::input_index(i)]; + }, py::return_value_policy::reference_internal) + + .def("subvector", [](const SampledTraj& x, Index_type i, Index_type j) -> SampledTraj + { + matlab::test_integer(i,j); + return x.subvector(matlab::input_index(i),matlab::input_index(j)); + }, py::return_value_policy::reference_internal) ; } @@ -104,17 +117,26 @@ py::class_> _export_SampledTraj(py::module& m, const string& clas SAMPLEDTRAJ_T_SAMPLEDTRAJ_T_SAMPLED_DOUBLE_BOOL_CONST, "dt"_a, "keep_original_values"_a) - .def("__getitem__", [](const SampledTraj& x, Index_type index) -> const T& + .def("__call__", [](const SampledTraj& x, double t) -> T { - matlab::test_integer(index); - return x.at(matlab::input_index(index)); - }, py::return_value_policy::reference_internal) + return x(t); + }, + VIRTUAL_T_SAMPLEDTRAJ_T_OPERATORCALL_DOUBLE_CONST, + "t"_a) + + .def("__call__", [](const SampledTraj& x, const Interval& t) -> typename Wrapper::Domain + { + return x(t); + }, + VIRTUAL_WRAPPER_T_DOMAIN_SAMPLEDTRAJ_T_OPERATORCALL_CONST_INTERVAL_REF_CONST, + "t"_a) - .def("__setitem__", [](SampledTraj& x, Index_type index, const T& a) + .def("set", [](SampledTraj& x, double ti, const T& xi) { - matlab::test_integer(index); - x[matlab::input_index(index)] = a; - }) + return x.set(ti,xi); + }, + VOID_SAMPLEDTRAJ_T_SET_DOUBLE_CONST_T_REF, + "ti"_a, "xi"_a) .def("__repr__", [](const SampledTraj& x) { std::ostringstream stream; diff --git a/python/src/core/trajectory/codac2_py_TrajBase.h b/python/src/core/trajectory/codac2_py_TrajBase.h index fa53eb640..7dac6b108 100644 --- a/python/src/core/trajectory/codac2_py_TrajBase.h +++ b/python/src/core/trajectory/codac2_py_TrajBase.h @@ -57,20 +57,6 @@ void export_TrajBase(py::class_& pyclass) }, VIRTUAL_WRAPPER_T_DOMAIN_TRAJBASE_T_CODOMAIN_CONST) - .def("__call__", [](const S& x, double t) - { - return x(t); - }, - VIRTUAL_T_TRAJBASE_T_OPERATORCALL_DOUBLE_CONST, - "t"_a) - - .def("__call__", [](const S& x, const Interval& t) - { - return x(t); - }, - VIRTUAL_WRAPPER_T_DOMAIN_TRAJBASE_T_OPERATORCALL_CONST_INTERVAL_REF_CONST, - "t"_a) - .def("nan_value", [](const S& x) { return x.nan_value(); diff --git a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp index dccf52b60..420f1574b 100644 --- a/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp +++ b/src/core/domains/ellipsoid/codac2_Ellipsoid.cpp @@ -167,12 +167,10 @@ namespace codac2 { return e_res + elli_error; } - Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box, const Vector& trig, const Vector& q) { - - Index n = G.cols(); - + Matrix nonlinear_mapping_base(const Matrix &G, const Matrix &J, const IntervalMatrix &J_box, const Vector& trig, const Vector& q) + { assert(G.is_squared() && J.is_squared() && J_box.is_squared()); - assert(n == J.cols() && n == J_box.cols() && n == q.size()); + assert(G.cols() == J.cols() && G.cols() == J_box.cols() && G.cols() == q.size()); auto JG = J * G; // note: reliability may be lost here! auto G_ = G.template cast(); diff --git a/src/core/trajectory/codac2_SampledTraj.h b/src/core/trajectory/codac2_SampledTraj.h index 50f9aa6f8..b8f93cace 100644 --- a/src/core/trajectory/codac2_SampledTraj.h +++ b/src/core/trajectory/codac2_SampledTraj.h @@ -12,6 +12,7 @@ #include #include "codac2_TrajBase.h" #include "codac2_analytic_variables.h" +#include "codac2_template_tools.h" namespace codac2 { @@ -31,7 +32,7 @@ namespace codac2 auto it_t = l_t.begin(); auto it_x = l_x.begin(); while(it_t != l_t.end()) { - (*this)[*(it_t)] = *(it_x); + this->set(*it_t,*it_x); it_t++; it_x++; } } @@ -90,8 +91,8 @@ namespace codac2 ++it; } - (*this)[new_tdomain.lb()] = y_lb; // clean truncation - (*this)[new_tdomain.ub()] = y_ub; + this->set(new_tdomain.lb(), y_lb); // clean truncation + this->set(new_tdomain.ub(), y_ub); } virtual typename Wrapper::Domain codomain() const @@ -138,6 +139,12 @@ namespace codac2 } } + void set(double t, const T& x) + { + assert(this->empty() || size_of(x) == this->size()); + std::map::operator[](t) = x; + } + virtual SampledTraj sampled(double dt) const { return sampled(dt, true); @@ -154,11 +161,41 @@ namespace codac2 { // Appending values from the initial map: for(const auto& [ti,xi] : *this) - straj[ti] = xi; + straj.set(ti, xi); } return straj; } + + template + requires std::is_same_v + SampledTraj operator[](Index i) const + { + assert_release(i >= 0 && i < size()); + std::map m; + for(const auto& [t,y] : *this) + { + assert(i < y.size()); + m[t] = y[i]; + } + + return { m }; + } + + template + requires std::is_same_v + SampledTraj subvector(Index i, Index j) const + { + assert_release(i >= 0 && i <= j && j < size()); + std::map m; + for(const auto& [t,y] : *this) + { + assert(j < y.size()); + m[t] = y.subvector(i,j); + } + + return { m }; + } }; template diff --git a/src/core/trajectory/codac2_TrajBase.h b/src/core/trajectory/codac2_TrajBase.h index 11eec6186..b74220a19 100644 --- a/src/core/trajectory/codac2_TrajBase.h +++ b/src/core/trajectory/codac2_TrajBase.h @@ -55,8 +55,8 @@ namespace codac2 auto tdom = tdomain(); SampledTraj straj; for(double t = tdom.lb() ; t < tdom.ub() ; t+=dt) - straj[t] = (*this)(t); - straj[tdom.ub()] = (*this)(tdom.ub()); + straj.set(t, (*this)(t)); + straj.set(tdom.ub(), (*this)(tdom.ub())); return straj; } @@ -67,20 +67,20 @@ namespace codac2 SampledTraj p; double t = tdomain().lb(), last_t = t; - p[t] = y0; t += dt; + p.set(t, y0); t += dt; T y = y0; while(t < tdomain().ub()) { y += ((*this)(last_t)+(*this)(t))*dt/2.; - p[t] = y; + p.set(t, y); last_t = t; t += dt; } t = tdomain().ub(); y += ((*this)(last_t)+(*this)(t))*(t-last_t)/2.; - p[t] = y; + p.set(t, y); return p; } From acfb48aba1c069dd5c6265ff74afaac07b2309dd Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Mon, 20 Jan 2025 19:44:08 +0100 Subject: [PATCH 108/126] [proj] releasing assertion --- src/core/contractors/codac2_CtcProj.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/contractors/codac2_CtcProj.h b/src/core/contractors/codac2_CtcProj.h index 1515d10e2..00dff8a38 100644 --- a/src/core/contractors/codac2_CtcProj.h +++ b/src/core/contractors/codac2_CtcProj.h @@ -35,7 +35,6 @@ namespace codac2 assert_release(*min_element(_xi.begin(),_xi.end()) >= 0); assert_release(*max_element(_xi.begin(),_xi.end()) < size_of(c)); assert_release(size_of(c) >= (Index)_xi.size() && "cannot compute a projection of a set into a superset"); - assert_release(y.is_bisectable()); assert_release(default_eps > 0.); } From 3e4eb7347eff7832dad4b25d3680b6054af1781b Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Mon, 20 Jan 2025 22:48:15 +0100 Subject: [PATCH 109/126] Keep Python tests when testing CAPD --- .github/workflows/tests.yml | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2fbe2afa7..cdadd1c57 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,9 +15,9 @@ jobs: fail-fast: false matrix: cfg: - - { os: ubuntu-24.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_python: ON, with_capd: OFF, desc: 'Ubuntu 24.04 GCC 11 Python 3.10 tests' } - - { os: ubuntu-24.04, gcc_v: 13, py_v_maj: 3, py_v_min: 12, with_python: OFF, with_capd: ON, desc: 'Ubuntu 24.04 GCC 13 CAPD tests' } - - { os: ubuntu-22.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_python: OFF, with_capd: ON, desc: 'Ubuntu 22.04 GCC 11 CAPD tests' } + - { os: ubuntu-24.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_capd: OFF, desc: 'Ubuntu 24.04 GCC 11 Python 3.10 tests' } + - { os: ubuntu-24.04, gcc_v: 13, py_v_maj: 3, py_v_min: 12, with_capd: ON, desc: 'Ubuntu 24.04 GCC 13 Python 3.10 CAPD tests' } + - { os: ubuntu-22.04, gcc_v: 11, py_v_maj: 3, py_v_min: 10, with_capd: ON, desc: 'Ubuntu 22.04 GCC 11 Python 3.10 CAPD tests' } name: ${{ matrix.cfg.desc }} steps: - uses: actions/checkout@v4 @@ -52,7 +52,7 @@ jobs: sudo apt-get -y install doxygen graphviz # Doxygen might need to be upgraded - #if [ "${{ matrix.cfg.with_python }}" = "ON" ]; then git clone --depth 1 https://github.com/doxygen/doxygen.git ; cd doxygen ; mkdir build ; cd build ; cmake .. ; sudo cmake --build . -j 4 --config Release --target install ; cd ../.. ; fi + git clone --depth 1 -b Release_1_13_0 https://github.com/doxygen/doxygen.git ; cd doxygen ; mkdir build ; cd build ; cmake .. ; sudo cmake --build . -j 4 --config Release --target install ; cd ../.. # For Python wrapping #pip install wheel @@ -91,23 +91,19 @@ jobs: cd build # Building lib + tests - cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DWITH_CAPD=${{ matrix.cfg.with_capd }} -DWITH_PYTHON=${{ matrix.cfg.with_python }} -DBUILD_TESTS=ON -DTEST_EXAMPLES=ON .. + cmake -DCMAKE_INSTALL_PREFIX=$HOME/codac/build_install -DCMAKE_PREFIX_PATH=$HOME/ibex-lib/build_install -DCMAKE_CXX_FLAGS="-fPIC" -DCMAKE_C_FLAGS="-fPIC" -DWITH_CAPD=${{ matrix.cfg.with_capd }} -DWITH_PYTHON=ON -DBUILD_TESTS=ON -DTEST_EXAMPLES=ON .. make -j 4 #make doc # todo make install - if [ "${{ matrix.cfg.with_python }}" = "ON" ]; then - cd python/python_package - python setup.py develop --user - #pip install -e . - cd ../../ + cd python/python_package + python setup.py develop --user + #pip install -e . + cd ../../ - python ../tests/core/domains/codac2_tests_BoolInterval.py - fi + python ../tests/core/domains/codac2_tests_BoolInterval.py make test - if [ "${{ matrix.cfg.with_python }}" = "ON" ]; then - python -m unittest discover codac.tests - fi + python -m unittest discover codac.tests ## Building the examples From c7df06b122ba12feb12d28d8687313fbf7511887 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 21 Jan 2025 13:22:35 +0100 Subject: [PATCH 110/126] [traj] operators --- .../codac2_SampledTraj_operations.h | 102 ++++++++++++++++++ .../trajectory/codac2_tests_SampledTraj.cpp | 3 + 2 files changed, 105 insertions(+) diff --git a/src/core/trajectory/codac2_SampledTraj_operations.h b/src/core/trajectory/codac2_SampledTraj_operations.h index 94da0a383..c391473f3 100644 --- a/src/core/trajectory/codac2_SampledTraj_operations.h +++ b/src/core/trajectory/codac2_SampledTraj_operations.h @@ -54,6 +54,28 @@ namespace codac2 return y; \ } \ + #define macro_member_binary_traj_traj(f) \ + { \ + assert_release(x1.nb_samples() == x2.nb_samples()); \ + auto it_x1 = x1.begin(); \ + auto it_x2 = x2.begin(); \ + while(it_x1 != x1.end()) \ + { \ + assert_release(it_x1->first == it_x2->first \ + && "inconsistent dates between the two trajectories"); \ + it_x1->second = f(it_x1->second,it_x2->second); \ + it_x1++; it_x2++; \ + } \ + return x1; \ + } \ + + #define macro_member_binary_traj_real(f) \ + { \ + for(auto it_x1 = x1.begin() ; it_x1 != x1.end() ; it_x1++) \ + it_x1->second = f(it_x1->second,x2); \ + return x1; \ + } \ + template inline T operator_add(const T& x1, const T& x2) { return x1 + x2; } template @@ -106,6 +128,26 @@ namespace codac2 inline SampledTraj operator+(const T& x1, const SampledTraj& x2) macro_binary_real_traj(operator_add); + /** + * \brief Operates += + * \param x1 + * \param x2 + * \return updated output + */ + template + inline SampledTraj& operator+=(SampledTraj& x1, const T& x2) + macro_member_binary_traj_real(operator_add); + + /** + * \brief Operates += + * \param x1 + * \param x2 + * \return updated output + */ + template + inline SampledTraj& operator+=(SampledTraj& x1, const SampledTraj& x2) + macro_member_binary_traj_traj(operator_add); + /** \brief \f$-x_1(\cdot)\f$ * \param x1 * \return trajectory output @@ -142,6 +184,26 @@ namespace codac2 inline SampledTraj operator-(const T& x1, const SampledTraj& x2) macro_binary_real_traj(operator_sub); + /** + * \brief Operates -= + * \param x1 + * \param x2 + * \return updated output + */ + template + inline SampledTraj& operator-=(SampledTraj& x1, const T& x2) + macro_member_binary_traj_real(operator_sub); + + /** + * \brief Operates -= + * \param x1 + * \param x2 + * \return updated output + */ + template + inline SampledTraj& operator-=(SampledTraj& x1, const SampledTraj& x2) + macro_member_binary_traj_traj(operator_sub); + /** \brief \f$x_1\cdot x_2(\cdot)\f$ * \param x1 * \param x2 @@ -197,6 +259,26 @@ namespace codac2 inline SampledTraj operator*(const SampledTraj& x1, const SampledTraj& x2) macro_binary_traj_traj(operator_mul_vec); + /** + * \brief Operates *= + * \param x1 + * \param x2 + * \return updated output + */ + template + inline SampledTraj& operator*=(SampledTraj& x1, const T& x2) + macro_member_binary_traj_real(operator_mul); + + /** + * \brief Operates *= + * \param x1 + * \param x2 + * \return updated output + */ + template + inline SampledTraj& operator*=(SampledTraj& x1, const SampledTraj& x2) + macro_member_binary_traj_traj(operator_mul); + /** \brief \f$x_2(\cdot)/x_1\f$ * \param x1 * \param x2 @@ -234,6 +316,26 @@ namespace codac2 inline SampledTraj operator/(const T& x1, const SampledTraj& x2) macro_binary_real_traj(operator_div); + /** + * \brief Operates /= + * \param x1 + * \param x2 + * \return updated output + */ + template + inline SampledTraj& operator/=(SampledTraj& x1, const T& x2) + macro_member_binary_traj_real(operator_div); + + /** + * \brief Operates /= + * \param x1 + * \param x2 + * \return updated output + */ + template + inline SampledTraj& operator/=(SampledTraj& x1, const SampledTraj& x2) + macro_member_binary_traj_traj(operator_div); + /** \brief \f$x^2(\cdot)\f$ * \param x1 * \return trajectory output diff --git a/tests/core/trajectory/codac2_tests_SampledTraj.cpp b/tests/core/trajectory/codac2_tests_SampledTraj.cpp index e1170ae13..cf6b7103e 100644 --- a/tests/core/trajectory/codac2_tests_SampledTraj.cpp +++ b/tests/core/trajectory/codac2_tests_SampledTraj.cpp @@ -117,4 +117,7 @@ TEST_CASE("SampledTraj: operations") auto analytic_traj = AnalyticTraj(h, {-PI,PI}); SampledTraj x = analytic_traj.sampled(1e-2); CHECK(Approx(cos(x).codomain(),1e-5) == Interval(-1,1)); + x = cos(x) + 4.; + x -= 42.; + CHECK(Approx(x.codomain(),1e-5) == Interval(-1,1)+4.-42.); } \ No newline at end of file From fe09de44f7f9e38635d73ff9ea0007a457428f99 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 21 Jan 2025 13:28:23 +0100 Subject: [PATCH 111/126] [pave] minor updates --- src/core/paver/codac2_pave.cpp | 18 +++++------------- src/core/paver/codac2_pave.h | 12 ++---------- src/graphics/paver/codac2_drawwhilepaving.cpp | 10 +--------- 3 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/core/paver/codac2_pave.cpp b/src/core/paver/codac2_pave.cpp index 40dae5502..fefcc77be 100644 --- a/src/core/paver/codac2_pave.cpp +++ b/src/core/paver/codac2_pave.cpp @@ -77,7 +77,6 @@ namespace codac2 assert_release(s.size() >= 2 && "cannot reveal 1d separators"); clock_t t_start = clock(); - Index n_boundary = 0; PavingInOut p(x); std::shared_ptr n; @@ -92,23 +91,16 @@ namespace codac2 auto boundary = (xs.inner & xs.outer); n->boxes() = { xs.outer, xs.inner }; - if(!boundary.is_empty()) + if(!boundary.is_empty() && boundary.max_diam() > eps) { - if(boundary.max_diam() > eps) - { - n->bisect(); - l.push_back(n->left()); - l.push_back(n->right()); - } - - else - n_boundary++; + n->bisect(); + l.push_back(n->left()); + l.push_back(n->right()); } } if(verbose) - printf("Computation time: %.4fs, %ld boundary boxes\n", - (double)(clock()-t_start)/CLOCKS_PER_SEC, n_boundary); + printf("Computation time: %.4fs\n", (double)(clock()-t_start)/CLOCKS_PER_SEC); return p; } } \ No newline at end of file diff --git a/src/core/paver/codac2_pave.h b/src/core/paver/codac2_pave.h index 5f6a6e95b..2a848cafd 100644 --- a/src/core/paver/codac2_pave.h +++ b/src/core/paver/codac2_pave.h @@ -27,7 +27,6 @@ namespace codac2 PavingInOut sivia(const IntervalVector& x, const AnalyticFunction& f, const typename Y::Domain& y, double eps, bool verbose = false) { clock_t t_start = clock(); - Index n_inner = 0, n_boundary = 0; PavingInOut p(x); std::list> l { p.tree() }; @@ -38,13 +37,10 @@ namespace codac2 l.pop_front(); assert(n->is_leaf()); - auto eval = f.eval(n->unknown()); + auto eval = f.eval(std::get<1>(n->boxes())); if(eval.is_subset(y)) - { std::get<1>(n->boxes()).set_empty(); - n_inner++; - } else if(!eval.intersects(y)) std::get<0>(n->boxes()).set_empty(); @@ -55,14 +51,10 @@ namespace codac2 l.push_back(n->left()); l.push_back(n->right()); } - - else - n_boundary++; } if(verbose) - printf("Computation time: %.4fs, %ld inner boxes, %ld boundary boxes\n", - (double)(clock()-t_start)/CLOCKS_PER_SEC, n_inner, n_boundary); + printf("Computation time: %.4fs\n", (double)(clock()-t_start)/CLOCKS_PER_SEC); return p; } } \ No newline at end of file diff --git a/src/graphics/paver/codac2_drawwhilepaving.cpp b/src/graphics/paver/codac2_drawwhilepaving.cpp index 8aa873239..6efd0715e 100644 --- a/src/graphics/paver/codac2_drawwhilepaving.cpp +++ b/src/graphics/paver/codac2_drawwhilepaving.cpp @@ -103,7 +103,6 @@ namespace codac2 clock_t t_start = clock(); list l { x0 }; - Index n_inner = 0, n_boundary = 0; while(!l.empty()) { @@ -114,10 +113,7 @@ namespace codac2 auto boundary = x_sep.inner & x_sep.outer; for(const auto& bi : x.diff(x_sep.inner)) - { - n_inner++; fig->draw_box(bi, StyleProperties::inside()); - } for(const auto& bi : x.diff(x_sep.outer)) fig->draw_box(bi, StyleProperties::outside()); @@ -125,10 +121,7 @@ namespace codac2 if(!boundary.is_empty()) { if(boundary.max_diam() <= eps) - { - n_boundary++; fig->draw_box(boundary, StyleProperties::boundary()); - } else { @@ -138,7 +131,6 @@ namespace codac2 } } - printf("Computation time: %.4fs, %ld inner boxes, %ld boundary boxes\n", - (double)(clock()-t_start)/CLOCKS_PER_SEC, n_inner, n_boundary); + printf("Computation time: %.4fs\n", (double)(clock()-t_start)/CLOCKS_PER_SEC); } } \ No newline at end of file From 61d7b1c0c694a43c60270043bbe57251da4f2a4e Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 21 Jan 2025 15:19:52 +0100 Subject: [PATCH 112/126] [cmake] removing some item in CODAC_LIBRARIES --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fae730e7d..9df7ac2fc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -110,7 +110,7 @@ find_library(CODAC_CAPD_LIBRARY NAMES ${PROJECT_NAME}-capd PATH_SUFFIXES lib) - set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY} capd::capd \${CODAC_GRAPHICS_LIBRARY}) + set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_CAPD_LIBRARY} capd::capd) ") endif() From a1f34e19b72b8f07833fd6c5f37c912ea5a79c54 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 21 Jan 2025 16:05:55 +0100 Subject: [PATCH 113/126] [fig] added missing include --- src/graphics/figures/codac2_Figure2D.cpp | 6 +----- src/graphics/figures/codac2_Figure2D.h | 1 + 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/graphics/figures/codac2_Figure2D.cpp b/src/graphics/figures/codac2_Figure2D.cpp index e9177a6d2..72d61f4cc 100644 --- a/src/graphics/figures/codac2_Figure2D.cpp +++ b/src/graphics/figures/codac2_Figure2D.cpp @@ -2,11 +2,7 @@ * codac2_Figure2D.cpp * ---------------------------------------------------------------------------- * \date 2024 -<<<<<<< HEAD - * \author Simon Rohou, Morgan Louédec -======= - * \author Simon Rohou, Maël Godard ->>>>>>> codac2_dev + * \author Simon Rohou, Maël Godard, Morgan Louédec * \copyright Copyright 2024 Codac Team * \license GNU Lesser General Public License (LGPL) */ diff --git a/src/graphics/figures/codac2_Figure2D.h b/src/graphics/figures/codac2_Figure2D.h index 8bc36877e..5f18049ad 100644 --- a/src/graphics/figures/codac2_Figure2D.h +++ b/src/graphics/figures/codac2_Figure2D.h @@ -17,6 +17,7 @@ #include "codac2_OutputFigure2D.h" #include "codac2_Paving.h" #include "codac2_ColorMap.h" +#include "codac2_Ellipsoid.h" #define DEFAULT_FIG_NAME "Codac - default view" From dd5074d4a39464fcd61845cc489b00c91121c6dd Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 21 Jan 2025 16:49:05 +0100 Subject: [PATCH 114/126] [cmake] graphics: repeat lib in target_link_libraries --- src/graphics/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/CMakeLists.txt b/src/graphics/CMakeLists.txt index c18ba4b8c..dba73b6a6 100644 --- a/src/graphics/CMakeLists.txt +++ b/src/graphics/CMakeLists.txt @@ -45,7 +45,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/paver ${CMAKE_CURRENT_SOURCE_DIR}/styles ) - target_link_libraries(${PROJECT_NAME}-graphics PUBLIC ${PROJECT_NAME}-core Ibex::ibex Eigen3::Eigen) + target_link_libraries(${PROJECT_NAME}-graphics PUBLIC ${PROJECT_NAME}-core Ibex::ibex Eigen3::Eigen ${PROJECT_NAME}-core) ################################################################################ From af23df3d876d30a6082c369913e6ffd11187a78a Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sun, 26 Jan 2025 19:44:10 +0100 Subject: [PATCH 115/126] Attempt to solve error for some MinGW configurations inside CLion --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 67a35973c..1f8e41045 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,9 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 4) add_compile_options(-g0) endif() + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + add_compile_options(-Os) + endif() endif() # # Check that the compiler supports c++20 From ee45e93b0c75e8854ce73d9139ec9b5995d4aa8b Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sun, 26 Jan 2025 20:51:07 +0100 Subject: [PATCH 116/126] Update dockermatrix.yml --- .github/workflows/dockermatrix.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dockermatrix.yml b/.github/workflows/dockermatrix.yml index c91d623e8..c2b16698a 100644 --- a/.github/workflows/dockermatrix.yml +++ b/.github/workflows/dockermatrix.yml @@ -67,7 +67,7 @@ jobs: - run: | docker run ${{ matrix.cfg.docker_flags }} -i -v "${PWD}/..:${PWD}/.." ${{ matrix.cfg.img }} /bin/bash -c "uname -a ; cat /etc/os-release ; lsb_release -a ; cd ${PWD} && pwd && \ git config --global --add safe.directory ${PWD} && \ - if [ ${{ matrix.cfg.deb }} = true ]; then \ + if [ \"${{ matrix.cfg.deb }}\" = \"true\" ]; then \ sudo sh -c 'echo \"deb [trusted=yes] https://packages.ensta-bretagne.fr/\$(if [ -z \"\$(. /etc/os-release && echo \$UBUNTU_CODENAME)\" ]; then echo debian/\$(. /etc/os-release && echo \$VERSION_CODENAME); else echo ubuntu/\$(. /etc/os-release && echo \$UBUNTU_CODENAME); fi) ./\" > /etc/apt/sources.list.d/ensta-bretagne.list' && \ #sudo apt-get -q update ; sudo apt-get -y install libeigen3-dev dpkg-dev || true && \\ sudo apt-get -q update ; sudo apt-get -y install dpkg-dev || true && \ @@ -86,7 +86,7 @@ jobs: cd .. && \ zip -q -r codac_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip codac && \ mkdir -p codac_standalone/example ; cd codac_standalone && \ - if [ ${{ matrix.cfg.deb }} = true ]; then mkdir -p ibex/include ; mkdir -p ibex/lib ; mkdir -p ibex/share ; mkdir -p ibex/bin ; cp -Rf /usr/include/ibex* ibex/include/ ; cp -Rf /usr/lib/*ibex* ibex/lib/ ; cp -Rf /usr/share/*ibex* ibex/share/ ; cp -Rf /usr/share/pkgconfig ibex/share/ ; cp -Rf /usr/bin/ibex* ibex/bin/ ; \ + if [ \"${{ matrix.cfg.deb }}\" = \"true\" ]; then mkdir -p ibex/include ; mkdir -p ibex/lib ; mkdir -p ibex/share ; mkdir -p ibex/bin ; cp -Rf /usr/include/ibex* ibex/include/ ; cp -Rf /usr/lib/*ibex* ibex/lib/ ; cp -Rf /usr/share/*ibex* ibex/share/ ; cp -Rf /usr/share/pkgconfig ibex/share/ ; cp -Rf /usr/bin/ibex* ibex/bin/ ; \ else cp -Rf ../ibex . ; \ fi && \ cp -Rf ../codac . ; cp -Rf ../tests/test_codac/* ./example/ ; cd .. ; zip -q -r codac_standalone_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip codac_standalone && \ @@ -96,7 +96,7 @@ jobs: file ./${{ matrix.cfg.test_config }}my_project && \ ./${{ matrix.cfg.test_config }}my_project && \ cd ../.. && \ - if [ ${{ matrix.cfg.deb }} = true ]; then \ + if [ \"${{ matrix.cfg.deb }}\" = \"true\" ]; then \ cd packages && \ chmod +x ./genlibcodac-dev.sh && \ ./genlibcodac-dev.sh \$(if [ -z \"\$(. /etc/os-release && echo \$UBUNTU_CODENAME)\" ]; then echo debian; else echo ubuntu; fi) ${{ matrix.cfg.runtime }} \$(dpkg --print-architecture) $SOFTWARE_VERSION $DEBIAN_PACKAGE_REV $PACKAGE_REV && \ From b43be415420e47d05ff4d185af10bc4bcdf03496 Mon Sep 17 00:00:00 2001 From: lebarsfa Date: Sun, 26 Jan 2025 23:01:51 +0100 Subject: [PATCH 117/126] Enable new arm64 Linux GitHub-hosted runners --- .github/workflows/dockermatrix.yml | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/dockermatrix.yml b/.github/workflows/dockermatrix.yml index c2b16698a..803d89af6 100644 --- a/.github/workflows/dockermatrix.yml +++ b/.github/workflows/dockermatrix.yml @@ -14,7 +14,7 @@ on: jobs: dockermatrix: - runs-on: ubuntu-latest + runs-on: ${{ matrix.cfg.os }} defaults: run: shell: ${{ matrix.cfg.shell }} @@ -22,22 +22,22 @@ jobs: fail-fast: false matrix: cfg: - - { img: 'lebarsfa/manylinux2014_x86_64-for-codac', shell: bash, arch: x86_64, bitness: 64, runtime: manylinux2014, cmake_flags: '-fPIC', desc: 'CentOS manylinux2014 x86_64' } - - { img: 'lebarsfa/manylinux2014_aarch64-for-codac', shell: bash, arch: aarch64, bitness: 64, runtime: manylinux2014, cmake_flags: '-fPIC', docker_flags: '--platform linux/arm64', desc: 'CentOS manylinux2014 aarch64' } - - { img: 'lebarsfa/pi-64:noble-for-codac', shell: bash, arch: arm64, bitness: 64, runtime: noble, cmake_flags: '-fPIC', deb: true, desc: 'Ubuntu 24.04 arm64' } - - { img: 'lebarsfa/pi-64:jammy-for-codac', shell: bash, arch: arm64, bitness: 64, runtime: jammy, cmake_flags: '-fPIC', deb: true, desc: 'Ubuntu 22.04 arm64' } + - { img: 'lebarsfa/manylinux2014_x86_64-for-codac', os: ubuntu-latest, shell: bash, arch: x86_64, bitness: 64, runtime: manylinux2014, cmake_flags: '-fPIC', desc: 'CentOS manylinux2014 x86_64' } + - { img: 'lebarsfa/manylinux2014_aarch64-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: aarch64, bitness: 64, runtime: manylinux2014, cmake_flags: '-fPIC', docker_flags: '--platform linux/arm64', desc: 'CentOS manylinux2014 aarch64' } + - { img: 'lebarsfa/pi-64:noble-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: arm64, bitness: 64, runtime: noble, cmake_flags: '-fPIC', deb: true, desc: 'Ubuntu 24.04 arm64' } + - { img: 'lebarsfa/pi-64:jammy-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: arm64, bitness: 64, runtime: jammy, cmake_flags: '-fPIC', deb: true, desc: 'Ubuntu 22.04 arm64' } # Problems related to C++20? - #- { img: 'lebarsfa/pi-64:focal-for-codac', shell: bash, arch: arm64, bitness: 64, runtime: focal, cmake_flags: '-fPIC', deb: true, desc: 'Ubuntu 20.04 arm64' } - - { img: 'lebarsfa/amd64:bookworm-for-codac', shell: bash, arch: amd64, bitness: 64, runtime: bookworm, cmake_flags: '-fPIC', deb: true, desc: 'Debian Bookworm amd64' } - - { img: 'lebarsfa/pi-64:bookworm-for-codac', shell: bash, arch: arm64, bitness: 64, runtime: bookworm, cmake_flags: '-fPIC', deb: true, desc: 'Debian Bookworm arm64' } - - { img: 'lebarsfa/pi:bookworm-for-codac', shell: bash, arch: armhf, bitness: 32, runtime: bookworm, cmake_flags: '-fPIC', deb: true, desc: 'Raspbian Bookworm armv6hf' } - - { img: 'lebarsfa/amd64:bullseye-for-codac', shell: bash, arch: amd64, bitness: 64, runtime: bullseye, cmake_flags: '-fPIC', deb: true, desc: 'Debian Bullseye amd64' } - - { img: 'lebarsfa/pi-64:bullseye-for-codac', shell: bash, arch: arm64, bitness: 64, runtime: bullseye, cmake_flags: '-fPIC', deb: true, desc: 'Debian Bullseye arm64' } - - { img: 'lebarsfa/pi:bullseye-for-codac', shell: bash, arch: armhf, bitness: 32, runtime: bullseye, cmake_flags: '-fPIC', deb: true, desc: 'Raspbian Bullseye armv6hf' } + #- { img: 'lebarsfa/pi-64:focal-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: arm64, bitness: 64, runtime: focal, cmake_flags: '-fPIC', deb: true, desc: 'Ubuntu 20.04 arm64' } + - { img: 'lebarsfa/amd64:bookworm-for-codac', os: ubuntu-latest, shell: bash, arch: amd64, bitness: 64, runtime: bookworm, cmake_flags: '-fPIC', deb: true, desc: 'Debian Bookworm amd64' } + - { img: 'lebarsfa/pi-64:bookworm-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: arm64, bitness: 64, runtime: bookworm, cmake_flags: '-fPIC', deb: true, desc: 'Debian Bookworm arm64' } + - { img: 'lebarsfa/pi:bookworm-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: armhf, bitness: 32, runtime: bookworm, cmake_flags: '-fPIC', deb: true, desc: 'Raspbian Bookworm armv6hf' } + - { img: 'lebarsfa/amd64:bullseye-for-codac', os: ubuntu-latest, shell: bash, arch: amd64, bitness: 64, runtime: bullseye, cmake_flags: '-fPIC', deb: true, desc: 'Debian Bullseye amd64' } + - { img: 'lebarsfa/pi-64:bullseye-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: arm64, bitness: 64, runtime: bullseye, cmake_flags: '-fPIC', deb: true, desc: 'Debian Bullseye arm64' } + - { img: 'lebarsfa/pi:bullseye-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: armhf, bitness: 32, runtime: bullseye, cmake_flags: '-fPIC', deb: true, desc: 'Raspbian Bullseye armv6hf' } # Problems related to C++20? - #- { img: 'lebarsfa/amd64:buster-for-codac', shell: bash, arch: amd64, bitness: 64, runtime: buster, cmake_flags: '-fPIC', deb: true, desc: 'Debian Buster amd64' } - #- { img: 'lebarsfa/pi-64:buster-for-codac', shell: bash, arch: arm64, bitness: 64, runtime: buster, cmake_flags: '-fPIC', deb: true, desc: 'Debian Buster arm64' } - #- { img: 'lebarsfa/pi:buster-for-codac', shell: bash, arch: armhf, bitness: 32, runtime: buster, cmake_flags: '-fPIC', deb: true, desc: 'Raspbian Buster armv6hf' } + #- { img: 'lebarsfa/amd64:buster-for-codac', os: ubuntu-latest, shell: bash, arch: amd64, bitness: 64, runtime: buster, cmake_flags: '-fPIC', deb: true, desc: 'Debian Buster amd64' } + #- { img: 'lebarsfa/pi-64:buster-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: arm64, bitness: 64, runtime: buster, cmake_flags: '-fPIC', deb: true, desc: 'Debian Buster arm64' } + #- { img: 'lebarsfa/pi:buster-for-codac', os: ubuntu-24.04-arm, shell: bash, arch: armhf, bitness: 32, runtime: buster, cmake_flags: '-fPIC', deb: true, desc: 'Raspbian Buster armv6hf' } name: ${{ matrix.cfg.desc }} steps: - uses: actions/checkout@v4 @@ -59,11 +59,11 @@ jobs: - run: echo "PACKAGE_VERSION=$SOFTWARE_VERSION-${DEBIAN_PACKAGE_REV}${{ matrix.cfg.runtime }}$PACKAGE_REV" >> $GITHUB_ENV shell: bash if: matrix.cfg.deb==true - - run: | - sudo apt-get -y install qemu binfmt-support qemu-user-static || true - #docker run --rm --privileged multiarch/qemu-user-static:register --reset - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - if: (matrix.cfg.arch!='amd64')&&(matrix.cfg.arch!='x86_64')&&(matrix.cfg.arch!='i386') + #- run: | + # sudo apt-get -y install qemu binfmt-support qemu-user-static || true + # #docker run --rm --privileged multiarch/qemu-user-static:register --reset + # docker run --rm --privileged multiarch/qemu-user-static --reset -p yes + # if: (matrix.cfg.arch!='amd64')&&(matrix.cfg.arch!='x86_64')&&(matrix.cfg.arch!='i386') - run: | docker run ${{ matrix.cfg.docker_flags }} -i -v "${PWD}/..:${PWD}/.." ${{ matrix.cfg.img }} /bin/bash -c "uname -a ; cat /etc/os-release ; lsb_release -a ; cd ${PWD} && pwd && \ git config --global --add safe.directory ${PWD} && \ From 9142edd7d97027e151d725f6f72c3791e34eb826 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 28 Jan 2025 12:59:26 +0100 Subject: [PATCH 118/126] [fnc] improving efficiency for simple natural evaluations --- src/core/contractors/codac2_CtcInverse.h | 3 +- src/core/contractors/codac2_directed_ctc.cpp | 409 ++++++++++++++++-- src/core/contractors/codac2_directed_ctc.h | 145 +++++-- .../functions/analytic/codac2_AnalyticExpr.h | 36 +- .../analytic/codac2_AnalyticFunction.h | 14 +- .../functions/analytic/codac2_AnalyticType.h | 4 + .../analytic/codac2_analytic_constants.h | 29 +- .../analytic/codac2_analytic_variables.h | 2 +- src/core/trajectory/codac2_Traj_operator.h | 4 +- 9 files changed, 531 insertions(+), 115 deletions(-) diff --git a/src/core/contractors/codac2_CtcInverse.h b/src/core/contractors/codac2_CtcInverse.h index b1b0cc056..08ceed461 100644 --- a/src/core/contractors/codac2_CtcInverse.h +++ b/src/core/contractors/codac2_CtcInverse.h @@ -65,7 +65,7 @@ namespace codac2 // Forward/backward algorithm: // [1/4] Forward evaluation - _f.expr()->fwd_eval(v, _f.args().total_size()); + _f.expr()->fwd_eval(v, _f.args().total_size(), !_with_centered_form); auto& val_expr = _f.expr()->value(v); if(_is_not_in && !val_expr.def_domain) @@ -104,7 +104,6 @@ namespace codac2 else { - IntervalVector p = x_ - x_mid; MulOp::bwd(fm, val_expr.da, p); x_ &= p + x_mid; diff --git a/src/core/contractors/codac2_directed_ctc.cpp b/src/core/contractors/codac2_directed_ctc.cpp index fddb1f559..2fc77cdbf 100644 --- a/src/core/contractors/codac2_directed_ctc.cpp +++ b/src/core/contractors/codac2_directed_ctc.cpp @@ -22,7 +22,15 @@ using namespace codac2; return x1; } - ScalarType AddOp::fwd(const ScalarType& x1) + ScalarType AddOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType AddOp::fwd_centered(const ScalarType& x1) { return { fwd(x1.m), @@ -40,7 +48,15 @@ using namespace codac2; return x1; } - VectorType AddOp::fwd(const VectorType& x1) + VectorType AddOp::fwd_natural(const VectorType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + VectorType AddOp::fwd_centered(const VectorType& x1) { return { fwd(x1.m), @@ -60,7 +76,15 @@ using namespace codac2; return x1; } - MatrixType AddOp::fwd(const MatrixType& x1) + MatrixType AddOp::fwd_natural(const MatrixType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + MatrixType AddOp::fwd_centered(const MatrixType& x1) { return { fwd(x1.m), @@ -83,7 +107,15 @@ using namespace codac2; return x1 + x2; } - ScalarType AddOp::fwd(const ScalarType& x1, const ScalarType& x2) + ScalarType AddOp::fwd_natural(const ScalarType& x1, const ScalarType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + ScalarType AddOp::fwd_centered(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.size() == x2.da.size()); return { @@ -105,7 +137,15 @@ using namespace codac2; return x1 + x2; } - VectorType AddOp::fwd(const VectorType& x1, const VectorType& x2) + VectorType AddOp::fwd_natural(const VectorType& x1, const VectorType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + VectorType AddOp::fwd_centered(const VectorType& x1, const VectorType& x2) { assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { @@ -129,7 +169,15 @@ using namespace codac2; return x1 + x2; } - MatrixType AddOp::fwd(const MatrixType& x1, const MatrixType& x2) + MatrixType AddOp::fwd_natural(const MatrixType& x1, const MatrixType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + MatrixType AddOp::fwd_centered(const MatrixType& x1, const MatrixType& x2) { return { fwd(x1.m, x2.m), @@ -154,7 +202,15 @@ using namespace codac2; return -x1; } - ScalarType SubOp::fwd(const ScalarType& x1) + ScalarType SubOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType SubOp::fwd_centered(const ScalarType& x1) { return { fwd(x1.m), @@ -175,7 +231,15 @@ using namespace codac2; return -x1; } - VectorType SubOp::fwd(const VectorType& x1) + VectorType SubOp::fwd_natural(const VectorType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + VectorType SubOp::fwd_centered(const VectorType& x1) { return { fwd(x1.m), @@ -197,7 +261,15 @@ using namespace codac2; return -x1; } - MatrixType SubOp::fwd(const MatrixType& x1) + MatrixType SubOp::fwd_natural(const MatrixType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + MatrixType SubOp::fwd_centered(const MatrixType& x1) { return { fwd(x1.m), @@ -222,7 +294,15 @@ using namespace codac2; return x1 - x2; } - ScalarType SubOp::fwd(const ScalarType& x1, const ScalarType& x2) + ScalarType SubOp::fwd_natural(const ScalarType& x1, const ScalarType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + ScalarType SubOp::fwd_centered(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { @@ -244,7 +324,15 @@ using namespace codac2; return x1 - x2; } - VectorType SubOp::fwd(const VectorType& x1, const VectorType& x2) + VectorType SubOp::fwd_natural(const VectorType& x1, const VectorType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + VectorType SubOp::fwd_centered(const VectorType& x1, const VectorType& x2) { assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); return { @@ -268,7 +356,16 @@ using namespace codac2; return x1 - x2; } - MatrixType SubOp::fwd(const MatrixType& x1, const MatrixType& x2) + MatrixType SubOp::fwd_natural(const MatrixType& x1, const MatrixType& x2) + { + assert(x1.a.cols() == x2.a.cols() && x1.a.rows() == x2.a.rows()); + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + MatrixType SubOp::fwd_centered(const MatrixType& x1, const MatrixType& x2) { assert(x1.a.cols() == x2.a.cols() && x1.a.rows() == x2.a.rows()); return { @@ -294,7 +391,15 @@ using namespace codac2; return x1 * x2; } - ScalarType MulOp::fwd(const ScalarType& x1, const ScalarType& x2) + ScalarType MulOp::fwd_natural(const ScalarType& x1, const ScalarType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + ScalarType MulOp::fwd_centered(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.rows() == 1); assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); @@ -321,7 +426,15 @@ using namespace codac2; return x1 * x2; } - VectorType MulOp::fwd(const ScalarType& x1, const VectorType& x2) + VectorType MulOp::fwd_natural(const ScalarType& x1, const VectorType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + VectorType MulOp::fwd_centered(const ScalarType& x1, const VectorType& x2) { assert(x1.da.rows() == 1); assert(x1.da.cols() == x2.da.cols()); @@ -352,9 +465,14 @@ using namespace codac2; return MulOp::fwd(x2,x1); } - VectorType MulOp::fwd(const VectorType& x1, const ScalarType& x2) + VectorType MulOp::fwd_natural(const VectorType& x1, const ScalarType& x2) { - return MulOp::fwd(x2,x1); + return MulOp::fwd_natural(x2,x1); + } + + VectorType MulOp::fwd_centered(const VectorType& x1, const ScalarType& x2) + { + return MulOp::fwd_centered(x2,x1); } void MulOp::bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2) @@ -410,7 +528,15 @@ using namespace codac2; return x1 * x2; } - VectorType MulOp::fwd(const MatrixType& x1, const VectorType& x2) + VectorType MulOp::fwd_natural(const MatrixType& x1, const VectorType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + VectorType MulOp::fwd_centered(const MatrixType& x1, const VectorType& x2) { return { fwd(x1.a, /* <<----- x1.m */ x2.m), @@ -507,7 +633,15 @@ using namespace codac2; return x1 / x2; } - ScalarType DivOp::fwd(const ScalarType& x1, const ScalarType& x2) + ScalarType DivOp::fwd_natural(const ScalarType& x1, const ScalarType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain && x2.a != 0. /* def domain of the derivative of div */ + }; + } + + ScalarType DivOp::fwd_centered(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.size() == x2.da.size()); @@ -533,7 +667,15 @@ using namespace codac2; return x1 / x2; } - VectorType DivOp::fwd(const VectorType& x1, const ScalarType& x2) + VectorType DivOp::fwd_natural(const VectorType& x1, const ScalarType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain && x2.a != 0. /* def domain of the derivative of div */ + }; + } + + VectorType DivOp::fwd_centered(const VectorType& x1, const ScalarType& x2) { assert(x1.da.size() == x2.da.size()); @@ -563,7 +705,15 @@ using namespace codac2; return pow(x1,x2); } - ScalarType PowOp::fwd(const ScalarType& x1, const ScalarType& x2) + ScalarType PowOp::fwd_natural(const ScalarType& x1, const ScalarType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + }; + } + + ScalarType PowOp::fwd_centered(const ScalarType& x1, const ScalarType& x2) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -590,7 +740,15 @@ using namespace codac2; return sqr(x1); } - ScalarType SqrOp::fwd(const ScalarType& x1) + ScalarType SqrOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType SqrOp::fwd_centered(const ScalarType& x1) { assert(x1.da.rows() == 1); @@ -619,7 +777,17 @@ using namespace codac2; return sqrt(x1); } - ScalarType SqrtOp::fwd(const ScalarType& x1) + ScalarType SqrtOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.a.is_subset({0,oo}) /* def domain of sqrt */ + && x1.a != 0. /* def domain of the derivative of sqrt */ + && x1.def_domain + }; + } + + ScalarType SqrtOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -648,7 +816,15 @@ using namespace codac2; return exp(x1); } - ScalarType ExpOp::fwd(const ScalarType& x1) + ScalarType ExpOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType ExpOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -675,7 +851,17 @@ using namespace codac2; return log(x1); } - ScalarType LogOp::fwd(const ScalarType& x1) + ScalarType LogOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.a.is_subset({0,oo}) /* def domain of log */ + && x1.a != 0. /* def domain of the derivative of log */ + && x1.def_domain + }; + } + + ScalarType LogOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -704,7 +890,15 @@ using namespace codac2; return cos(x1); } - ScalarType CosOp::fwd(const ScalarType& x1) + ScalarType CosOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType CosOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -731,7 +925,15 @@ using namespace codac2; return sin(x1); } - ScalarType SinOp::fwd(const ScalarType& x1) + ScalarType SinOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType SinOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -758,7 +960,15 @@ using namespace codac2; return tan(x1); } - ScalarType TanOp::fwd(const ScalarType& x1) + ScalarType TanOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain && cos(x1.a) != 0. /* def domain of the derivative of tan */ + }; + } + + ScalarType TanOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -785,7 +995,17 @@ using namespace codac2; return acos(x1); } - ScalarType AcosOp::fwd(const ScalarType& x1) + ScalarType AcosOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.a.is_subset({-1,1}) /* def domain of acos */ + && x1.a != 1. /* def domain of the derivative of acos */ + && x1.def_domain + }; + } + + ScalarType AcosOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -814,7 +1034,17 @@ using namespace codac2; return asin(x1); } - ScalarType AsinOp::fwd(const ScalarType& x1) + ScalarType AsinOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.a.is_subset({-1,1}) /* def domain of asin */ + && x1.a != 1. /* def domain of the derivative of asin */ + && x1.def_domain + }; + } + + ScalarType AsinOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -843,7 +1073,15 @@ using namespace codac2; return atan(x1); } - ScalarType AtanOp::fwd(const ScalarType& x1) + ScalarType AtanOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType AtanOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -870,7 +1108,16 @@ using namespace codac2; return atan2(x1,x2); } - ScalarType Atan2Op::fwd(const ScalarType& x1, const ScalarType& x2) + ScalarType Atan2Op::fwd_natural(const ScalarType& x1, const ScalarType& x2) + { + return { + fwd(x1.a, x2.a), + x1.def_domain && x2.def_domain + && !(x1.a == 0. && x2.a == 0.) /* def domain of the derivative of atan2 */ + }; + } + + ScalarType Atan2Op::fwd_centered(const ScalarType& x1, const ScalarType& x2) { assert(x1.da.rows() == 1); assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols()); @@ -901,7 +1148,15 @@ using namespace codac2; return cosh(x1); } - ScalarType CoshOp::fwd(const ScalarType& x1) + ScalarType CoshOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType CoshOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -928,7 +1183,15 @@ using namespace codac2; return sinh(x1); } - ScalarType SinhOp::fwd(const ScalarType& x1) + ScalarType SinhOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType SinhOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -955,8 +1218,16 @@ using namespace codac2; return tanh(x1); } - ScalarType TanhOp::fwd(const ScalarType& x1) - { + ScalarType TanhOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain + }; + } + + ScalarType TanhOp::fwd_centered(const ScalarType& x1) + { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) d(0,i) = x1.da(0,i)/sqr(cosh(x1.a)); @@ -982,7 +1253,15 @@ using namespace codac2; return abs(x1); } - ScalarType AbsOp::fwd(const ScalarType& x1) + ScalarType AbsOp::fwd_natural(const ScalarType& x1) + { + return { + fwd(x1.a), + x1.def_domain && x1.a != 0. /* def domain of the derivative of abs */ + }; + } + + ScalarType AbsOp::fwd_centered(const ScalarType& x1) { IntervalMatrix d(1,x1.da.size()); for(Index i = 0 ; i < d.size() ; i++) @@ -1010,7 +1289,16 @@ using namespace codac2; return x1[i]; } - ScalarType ComponentOp::fwd(const VectorType& x1, Index i) + ScalarType ComponentOp::fwd_natural(const VectorType& x1, Index i) + { + assert(i >= 0 && i < x1.a.rows()); + return { + fwd(x1.a,i), + x1.def_domain + }; + } + + ScalarType ComponentOp::fwd_centered(const VectorType& x1, Index i) { assert(i >= 0 && i < x1.a.rows()); return { @@ -1036,7 +1324,16 @@ using namespace codac2; return x1.subvector(i,j); } - VectorType SubvectorOp::fwd(const VectorType& x1, Index i, Index j) + VectorType SubvectorOp::fwd_natural(const VectorType& x1, Index i, Index j) + { + assert(i >= 0 && i < x1.a.rows() && j >= i && j < x1.a.rows()); + return { + fwd(x1.a,i,j), + x1.def_domain + }; + } + + VectorType SubvectorOp::fwd_centered(const VectorType& x1, Index i, Index j) { assert(i >= 0 && i < x1.a.rows() && j >= i && j < x1.a.rows()); return { @@ -1085,7 +1382,15 @@ using namespace codac2; return Interval::empty(); // unhandled case } - ScalarType DetOp::fwd(const MatrixType& x) + ScalarType DetOp::fwd_natural(const MatrixType& x) + { + return { + fwd(x.a), + x.def_domain + }; + } + + ScalarType DetOp::fwd_centered(const MatrixType& x) { return { fwd(x.m), @@ -1127,7 +1432,18 @@ using namespace codac2; return DetOp::fwd(m); } - ScalarType DetOp::fwd(const VectorType& x1, const VectorType& x2) + ScalarType DetOp::fwd_natural(const VectorType& x1, const VectorType& x2) + { + IntervalMatrix a(2,2); + a.col(0) = x1.a; a.col(1) = x2.a; + + return { + fwd(a), + x1.def_domain && x2.def_domain + }; + } + + ScalarType DetOp::fwd_centered(const VectorType& x1, const VectorType& x2) { IntervalMatrix m(2,2); m.col(0) = x1.m; m.col(1) = x2.m; @@ -1162,7 +1478,18 @@ using namespace codac2; return DetOp::fwd(m); } - ScalarType DetOp::fwd(const VectorType& x1, const VectorType& x2, const VectorType& x3) + ScalarType DetOp::fwd_natural(const VectorType& x1, const VectorType& x2, const VectorType& x3) + { + IntervalMatrix a(3,3); + a.col(0) = x1.a; a.col(1) = x2.a; a.col(2) = x3.a; + + return { + fwd(a), + x1.def_domain && x2.def_domain && x3.def_domain + }; + } + + ScalarType DetOp::fwd_centered(const VectorType& x1, const VectorType& x2, const VectorType& x3) { IntervalMatrix m(3,3); m.col(0) = x1.m; m.col(1) = x2.m; m.col(2) = x3.m; diff --git a/src/core/contractors/codac2_directed_ctc.h b/src/core/contractors/codac2_directed_ctc.h index 3c3f6124a..d2b9fb1d4 100644 --- a/src/core/contractors/codac2_directed_ctc.h +++ b/src/core/contractors/codac2_directed_ctc.h @@ -20,28 +20,34 @@ namespace codac2 { // Unary operations static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); static IntervalVector fwd(const IntervalVector& x1); - static VectorType fwd(const VectorType& x1); + static VectorType fwd_natural(const VectorType& x1); + static VectorType fwd_centered(const VectorType& x1); static void bwd(const IntervalVector& y, IntervalVector& x1); static IntervalMatrix fwd(const IntervalMatrix& x1); - static MatrixType fwd(const MatrixType& x1); + static MatrixType fwd_natural(const MatrixType& x1); + static MatrixType fwd_centered(const MatrixType& x1); static void bwd(const IntervalMatrix& y, IntervalMatrix& x1); // Binary operations static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_natural(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_centered(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); static IntervalVector fwd(const IntervalVector& x1, const IntervalVector& x2); - static VectorType fwd(const VectorType& x1, const VectorType& x2); + static VectorType fwd_natural(const VectorType& x1, const VectorType& x2); + static VectorType fwd_centered(const VectorType& x1, const VectorType& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, IntervalVector& x2); static IntervalMatrix fwd(const IntervalMatrix& x1, const IntervalMatrix& x2); - static MatrixType fwd(const MatrixType& x1, const MatrixType& x2); + static MatrixType fwd_natural(const MatrixType& x1, const MatrixType& x2); + static MatrixType fwd_centered(const MatrixType& x1, const MatrixType& x2); static void bwd(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2); }; @@ -49,43 +55,52 @@ namespace codac2 { // Unary operations static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); static IntervalVector fwd(const IntervalVector& x1); - static VectorType fwd(const VectorType& x1); + static VectorType fwd_natural(const VectorType& x1); + static VectorType fwd_centered(const VectorType& x1); static void bwd(const IntervalVector& y, IntervalVector& x1); static IntervalMatrix fwd(const IntervalMatrix& x1); - static MatrixType fwd(const MatrixType& x1); + static MatrixType fwd_natural(const MatrixType& x1); + static MatrixType fwd_centered(const MatrixType& x1); static void bwd(const IntervalMatrix& y, IntervalMatrix& x1); // Binary operations static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_natural(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_centered(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); static IntervalVector fwd(const IntervalVector& x1, const IntervalVector& x2); - static VectorType fwd(const VectorType& x1, const VectorType& x2); + static VectorType fwd_natural(const VectorType& x1, const VectorType& x2); + static VectorType fwd_centered(const VectorType& x1, const VectorType& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, IntervalVector& x2); static IntervalMatrix fwd(const IntervalMatrix& x1, const IntervalMatrix& x2); - static MatrixType fwd(const MatrixType& x1, const MatrixType& x2); + static MatrixType fwd_natural(const MatrixType& x1, const MatrixType& x2); + static MatrixType fwd_centered(const MatrixType& x1, const MatrixType& x2); static void bwd(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2); }; struct MulOp { static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_natural(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_centered(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); static IntervalVector fwd(const Interval& x1, const IntervalVector& x2); - static VectorType fwd(const ScalarType& x1, const VectorType& x2); + static VectorType fwd_natural(const ScalarType& x1, const VectorType& x2); + static VectorType fwd_centered(const ScalarType& x1, const VectorType& x2); static void bwd(const IntervalVector& y, Interval& x1, IntervalVector& x2); static IntervalVector fwd(const IntervalVector& x1, const Interval& x2); - static VectorType fwd(const VectorType& x1, const ScalarType& x2); + static VectorType fwd_natural(const VectorType& x1, const ScalarType& x2); + static VectorType fwd_centered(const VectorType& x1, const ScalarType& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2); static Interval fwd(const IntervalRow& x1, const IntervalVector& x2); @@ -93,144 +108,165 @@ namespace codac2 static void bwd(const Interval& y, IntervalRow& x1, IntervalVector& x2); static IntervalVector fwd(const IntervalMatrix& x1, const IntervalVector& x2); - static VectorType fwd(const MatrixType& x1, const VectorType& x2); + static VectorType fwd_natural(const MatrixType& x1, const VectorType& x2); + static VectorType fwd_centered(const MatrixType& x1, const VectorType& x2); static void bwd(const IntervalVector& y, IntervalMatrix& x1, IntervalVector& x2); }; struct DivOp { static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_natural(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_centered(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); static IntervalVector fwd(const IntervalVector& x1, const Interval& x2); - static VectorType fwd(const VectorType& x1, const ScalarType& x2); + static VectorType fwd_natural(const VectorType& x1, const ScalarType& x2); + static VectorType fwd_centered(const VectorType& x1, const ScalarType& x2); static void bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2); }; struct PowOp { static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_natural(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_centered(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); }; struct SqrOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct SqrtOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct ExpOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct LogOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct CosOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct SinOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct TanOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct AcosOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct AsinOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct AtanOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct Atan2Op { static Interval fwd(const Interval& x1, const Interval& x2); - static ScalarType fwd(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_natural(const ScalarType& x1, const ScalarType& x2); + static ScalarType fwd_centered(const ScalarType& x1, const ScalarType& x2); static void bwd(const Interval& y, Interval& x1, Interval& x2); }; struct CoshOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct SinhOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct TanhOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct AbsOp { static Interval fwd(const Interval& x1); - static ScalarType fwd(const ScalarType& x1); + static ScalarType fwd_natural(const ScalarType& x1); + static ScalarType fwd_centered(const ScalarType& x1); static void bwd(const Interval& y, Interval& x1); }; struct ComponentOp { static Interval fwd(const IntervalVector& x1, Index i); - static ScalarType fwd(const VectorType& x1, Index i); + static ScalarType fwd_natural(const VectorType& x1, Index i); + static ScalarType fwd_centered(const VectorType& x1, Index i); static void bwd(const Interval& y, IntervalVector& x1, Index i); }; struct SubvectorOp { static IntervalVector fwd(const IntervalVector& x1, Index i, Index j); - static VectorType fwd(const VectorType& x1, Index i, Index j); + static VectorType fwd_natural(const VectorType& x1, Index i, Index j); + static VectorType fwd_centered(const VectorType& x1, Index i, Index j); static void bwd(const IntervalVector& y, IntervalVector& x1, Index i, Index j); }; @@ -245,7 +281,20 @@ namespace codac2 template requires (std::is_base_of_v && ...) - static VectorType fwd(const X&... x) + static VectorType fwd_natural(const X&... x) + { + bool def_domain = true; + ((def_domain &= x.def_domain), ...); + + return { + fwd(x.a...), + def_domain + }; + } + + template + requires (std::is_base_of_v && ...) + static VectorType fwd_centered(const X&... x) { IntervalMatrix d(sizeof...(X),std::get<0>(std::tie(x...)).da.cols()); Index i = 0; @@ -288,7 +337,18 @@ namespace codac2 template requires (std::is_base_of_v && ...) - static MatrixType fwd(const X&... x) + static MatrixType fwd_natural(const X&... x) + { + throw std::runtime_error("MatrixOp not fully implemented yet"); + return { + IntervalMatrix({x.a...}), + true // todo with variadic + }; + } + + template + requires (std::is_base_of_v && ...) + static MatrixType fwd_centered(const X&... x) { throw std::runtime_error("MatrixOp not fully implemented yet"); return { @@ -313,17 +373,20 @@ namespace codac2 { // For matrices static Interval fwd(const IntervalMatrix& x); - static ScalarType fwd(const MatrixType& x); + static ScalarType fwd_natural(const MatrixType& x); + static ScalarType fwd_centered(const MatrixType& x); static void bwd(const Interval& y, IntervalMatrix& x); // For two vectors (merged into a 2×2 matrix) static Interval fwd(const IntervalVector& x1, const IntervalVector& x2); - static ScalarType fwd(const VectorType& x1, const VectorType& x2); + static ScalarType fwd_natural(const VectorType& x1, const VectorType& x2); + static ScalarType fwd_centered(const VectorType& x1, const VectorType& x2); static void bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2); // For three vectors (merged into a 3×3 matrix) static Interval fwd(const IntervalVector& x1, const IntervalVector& x2, const IntervalVector& x3); - static ScalarType fwd(const VectorType& x1, const VectorType& x2, const VectorType& x3); + static ScalarType fwd_natural(const VectorType& x1, const VectorType& x2, const VectorType& x3); + static ScalarType fwd_centered(const VectorType& x1, const VectorType& x2, const VectorType& x3); static void bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2, IntervalVector& x3); }; } \ No newline at end of file diff --git a/src/core/functions/analytic/codac2_AnalyticExpr.h b/src/core/functions/analytic/codac2_AnalyticExpr.h index 69bab2a30..97c033a19 100644 --- a/src/core/functions/analytic/codac2_AnalyticExpr.h +++ b/src/core/functions/analytic/codac2_AnalyticExpr.h @@ -28,7 +28,7 @@ namespace codac2 AnalyticExpr& operator=(const AnalyticExpr& x) = delete; - virtual T fwd_eval(ValuesMap& v, Index total_input_size) const = 0; + virtual T fwd_eval(ValuesMap& v, Index total_input_size, bool natural_eval) const = 0; virtual void bwd_eval(ValuesMap& v) const = 0; T init_value(ValuesMap& v, const T& x) const @@ -77,12 +77,16 @@ namespace codac2 return OperationExprBase...>::replace_expr(old_expr_id, new_expr); } - Y fwd_eval(ValuesMap& v, Index total_input_size) const + Y fwd_eval(ValuesMap& v, Index total_input_size, bool natural_eval) const { return std::apply( - [this,&v,total_input_size](auto &&... x) + [this,&v,total_input_size,natural_eval](auto &&... x) { - return AnalyticExpr::init_value(v, C::fwd(x->fwd_eval(v, total_input_size)...)); + if(natural_eval) + return AnalyticExpr::init_value(v, C::fwd_natural(x->fwd_eval(v, total_input_size, natural_eval)...)); + + else + return AnalyticExpr::init_value(v, C::fwd_centered(x->fwd_eval(v, total_input_size, natural_eval)...)); }, this->_x); } @@ -137,11 +141,15 @@ namespace codac2 { return OperationExprBase>::replace_expr(old_expr_id, new_expr); } - - ScalarType fwd_eval(ValuesMap& v, Index total_input_size) const + + ScalarType fwd_eval(ValuesMap& v, Index total_input_size, bool natural_eval) const { - return AnalyticExpr::init_value( - v, ComponentOp::fwd(std::get<0>(this->_x)->fwd_eval(v, total_input_size), _i)); + if(natural_eval) + return AnalyticExpr::init_value( + v, ComponentOp::fwd_natural(std::get<0>(this->_x)->fwd_eval(v, total_input_size, natural_eval), _i)); + else + return AnalyticExpr::init_value( + v, ComponentOp::fwd_centered(std::get<0>(this->_x)->fwd_eval(v, total_input_size, natural_eval), _i)); } void bwd_eval(ValuesMap& v) const @@ -183,10 +191,14 @@ namespace codac2 return OperationExprBase>::replace_expr(old_expr_id, new_expr); } - VectorType fwd_eval(ValuesMap& v, Index total_input_size) const - { - return AnalyticExpr::init_value( - v, SubvectorOp::fwd(std::get<0>(this->_x)->fwd_eval(v, total_input_size), _i, _j)); + VectorType fwd_eval(ValuesMap& v, Index total_input_size, bool natural_eval) const + { + if(natural_eval) + return AnalyticExpr::init_value( + v, SubvectorOp::fwd_natural(std::get<0>(this->_x)->fwd_eval(v, total_input_size, natural_eval), _i, _j)); + else + return AnalyticExpr::init_value( + v, SubvectorOp::fwd_centered(std::get<0>(this->_x)->fwd_eval(v, total_input_size, natural_eval), _i, _j)); } void bwd_eval(ValuesMap& v) const diff --git a/src/core/functions/analytic/codac2_AnalyticFunction.h b/src/core/functions/analytic/codac2_AnalyticFunction.h index e7b066f61..86c285efc 100644 --- a/src/core/functions/analytic/codac2_AnalyticFunction.h +++ b/src/core/functions/analytic/codac2_AnalyticFunction.h @@ -79,17 +79,17 @@ namespace codac2 typename T::Domain eval(const EvalMode& m, const Args&... x) const { check_valid_inputs(x...); - auto x_ = eval_(x...); switch(m) { case EvalMode::NATURAL: { - return x_.a; + return eval_(x...).a; } case EvalMode::CENTERED: { + auto x_ = eval_(x...); auto flatten_x = cart_prod(x...); assert(x_.da.rows() == x_.a.size() && x_.da.cols() == flatten_x.size()); @@ -102,6 +102,8 @@ namespace codac2 case EvalMode::DEFAULT: default: { + auto x_ = eval_(x...); + if(x_.da.size() == 0) // if the centered form is not available for this expression return eval(EvalMode::NATURAL, x...); @@ -130,7 +132,7 @@ namespace codac2 auto diff(const Args&... x) const { check_valid_inputs(x...); - return eval_(x...).da; + return eval_(x...).da; } Index output_size() const @@ -209,18 +211,18 @@ namespace codac2 (intersect_value_from_arg_map(v, x, i++), ...); } - template + template auto eval_(const Args&... x) const { ValuesMap v; if constexpr(sizeof...(Args) == 0) - return this->expr()->fwd_eval(v, 0); + return this->expr()->fwd_eval(v, 0, NATURAL_EVAL); else { fill_from_args(v, x...); - return this->expr()->fwd_eval(v, cart_prod(x...).size()); // todo: improve size computation + return this->expr()->fwd_eval(v, cart_prod(x...).size(), NATURAL_EVAL); // todo: improve size computation } } diff --git a/src/core/functions/analytic/codac2_AnalyticType.h b/src/core/functions/analytic/codac2_AnalyticType.h index c5c7eda85..4c0aaa18f 100644 --- a/src/core/functions/analytic/codac2_AnalyticType.h +++ b/src/core/functions/analytic/codac2_AnalyticType.h @@ -35,6 +35,10 @@ namespace codac2 AnalyticType() = delete; + AnalyticType(const T& a_, bool def_domain_) + : a(a_), def_domain(def_domain_) + { } + AnalyticType(const T& m_, const T& a_, const M& da_, bool def_domain_) : m(m_), a(a_), da(da_), def_domain(def_domain_) { } diff --git a/src/core/functions/analytic/codac2_analytic_constants.h b/src/core/functions/analytic/codac2_analytic_constants.h index a3d75b381..ca9c4122b 100644 --- a/src/core/functions/analytic/codac2_analytic_constants.h +++ b/src/core/functions/analytic/codac2_analytic_constants.h @@ -29,17 +29,26 @@ namespace codac2 return std::make_shared>(*this); } - T fwd_eval(ValuesMap& v, Index total_input_size) const + T fwd_eval(ValuesMap& v, Index total_input_size, bool natural_eval) const { - return AnalyticExpr::init_value(v, T( - // the mid is not considered for const values in centered form expression: - _x, - _x, - // the derivative of a const value is zero: - IntervalMatrix::zero(_x.size(),total_input_size), - // the definition domain is necesarily met at this point: - true - )); + if(natural_eval) + return AnalyticExpr::init_value(v, T( + // the mid is not considered for const values in centered form expression: + _x, + // the definition domain is necesarily met at this point: + true + )); + + else + return AnalyticExpr::init_value(v, T( + // the mid is not considered for const values in centered form expression: + _x, + _x, + // the derivative of a const value is zero: + IntervalMatrix::zero(_x.size(),total_input_size), + // the definition domain is necesarily met at this point: + true + )); } void bwd_eval(ValuesMap& v) const diff --git a/src/core/functions/analytic/codac2_analytic_variables.h b/src/core/functions/analytic/codac2_analytic_variables.h index fa436c736..e31d15c16 100644 --- a/src/core/functions/analytic/codac2_analytic_variables.h +++ b/src/core/functions/analytic/codac2_analytic_variables.h @@ -31,7 +31,7 @@ namespace codac2 return AnalyticExpr::unique_id(); } - T fwd_eval(ValuesMap& v, [[maybe_unused]] Index total_input_size) const + T fwd_eval(ValuesMap& v, [[maybe_unused]] Index total_input_size, [[maybe_unused]] bool natural_eval) const { return AnalyticExpr::value(v); } diff --git a/src/core/trajectory/codac2_Traj_operator.h b/src/core/trajectory/codac2_Traj_operator.h index 7e01e7596..06aec5d60 100644 --- a/src/core/trajectory/codac2_Traj_operator.h +++ b/src/core/trajectory/codac2_Traj_operator.h @@ -68,10 +68,10 @@ namespace codac2 return OperationExprBase>::replace_expr(old_expr_id, new_expr); } - O fwd_eval(ValuesMap& v, Index total_input_size) const + O fwd_eval(ValuesMap& v, Index total_input_size, bool natural_eval) const { return AnalyticExpr::init_value( - v, TrajectoryOp::fwd(_x1, std::get<0>(this->_x)->fwd_eval(v, total_input_size))); + v, TrajectoryOp::fwd(_x1, std::get<0>(this->_x)->fwd_eval(v, total_input_size, natural_eval))); } void bwd_eval(ValuesMap& v) const From 8fc5a59fbf9b4cebd6e1632b9b560ac8cadfb01a Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 28 Jan 2025 14:18:17 +0100 Subject: [PATCH 119/126] [graphics] added Figure3D with example --- examples/06_graphics_3D/CMakeLists.txt | 34 ++++++ examples/06_graphics_3D/main.cpp | 40 +++++++ examples/06_graphics_3D/main.py | 13 +++ src/graphics/CMakeLists.txt | 2 + src/graphics/figures/codac2_Figure3D.cpp | 140 +++++++++++++++++++++++ src/graphics/figures/codac2_Figure3D.h | 62 ++++++++++ 6 files changed, 291 insertions(+) create mode 100644 examples/06_graphics_3D/CMakeLists.txt create mode 100644 examples/06_graphics_3D/main.cpp create mode 100644 examples/06_graphics_3D/main.py create mode 100644 src/graphics/figures/codac2_Figure3D.cpp create mode 100644 src/graphics/figures/codac2_Figure3D.h diff --git a/examples/06_graphics_3D/CMakeLists.txt b/examples/06_graphics_3D/CMakeLists.txt new file mode 100644 index 000000000..cf89b0f69 --- /dev/null +++ b/examples/06_graphics_3D/CMakeLists.txt @@ -0,0 +1,34 @@ +# ================================================================== +# codac / basics example - cmake configuration file +# ================================================================== + + cmake_minimum_required(VERSION 3.0.2) + project(codac_example LANGUAGES CXX) + + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Adding Codac + + # In case you installed Codac in a local directory, you need + # to specify its path with the CMAKE_PREFIX_PATH option. + # set(CMAKE_PREFIX_PATH "~/codac/build_install") + + find_package(CODAC REQUIRED) + message(STATUS "Found Codac version ${CODAC_VERSION}") + +# Initializating Ibex + + ibex_init_common() + +# Compilation + + if(FAST_RELEASE) + add_compile_definitions(FAST_RELEASE) + message(STATUS "You are running Codac in fast release mode. (option -DCMAKE_BUILD_TYPE=Release is required)") + endif() + + 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}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${CODAC_LIBRARIES}) \ No newline at end of file diff --git a/examples/06_graphics_3D/main.cpp b/examples/06_graphics_3D/main.cpp new file mode 100644 index 000000000..62e388b1a --- /dev/null +++ b/examples/06_graphics_3D/main.cpp @@ -0,0 +1,40 @@ +// The generated .obj files can be visualized on https://3dviewer.net/ + +#include + +using namespace std; +using namespace codac2; + +int main() +{ + VectorVar x(3); + + // Example from the publication: + // https://www.ensta-bretagne.fr/jaulin/paper_centeredActa.pdf + + AnalyticFunction f { {x}, + { + -sqr(x[2])+2*x[2]*sin(x[2]*x[0])+cos(x[2]*x[1]), + 2*x[2]*cos(x[2]*x[0])-sin(x[2]*x[1]) + } + }; + + + CtcInverse_ ctc(f, IntervalVector::zero(2)); + auto p_ctc = pave({{0,2},{2,4},{0,10}}, ctc, 0.02); + Figure3D fig_ctc("PavingOut"); + fig_ctc.draw_axes(); + fig_ctc.draw_paving(p_ctc); + + + SepInverse sep_ellipsoid( + AnalyticFunction({x}, 2*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+sqr(x[1])+sqr(x[2])), + Interval(0.4,1)); + + auto p_sep = pave({{-1.1,1.1},{-1.1,1.1},{-1.1,1.1}}, sep_ellipsoid&IntervalVector({{-1.5,1.5},{-0.1,0.1},{-1.5,1.5}}), 0.04); + + Figure3D fig_sep("PavingInOut"); + fig_sep.draw_axes(0.4); + fig_sep.draw_paving(p_sep); + +} \ No newline at end of file diff --git a/examples/06_graphics_3D/main.py b/examples/06_graphics_3D/main.py new file mode 100644 index 000000000..41ff95f49 --- /dev/null +++ b/examples/06_graphics_3D/main.py @@ -0,0 +1,13 @@ +# Example from the publication: +# https://www.ensta-bretagne.fr/jaulin/paper_centeredActa.pdf + +from codac import * + +x = VectorVar(3) +f = AnalyticFunction([x], [ + -sqr(x[2])+2*x[2]*sin(x[2]*x[0])+cos(x[2]*x[1]), + 2*x[2]*cos(x[2]*x[0])-sin(x[2]*x[1]) +]) + +ctc = CtcInverse(f, [0,0]) +graphics.draw_while_paving([[0,2],[2,4],[0,10]], ctc, 0.004) \ No newline at end of file diff --git a/src/graphics/CMakeLists.txt b/src/graphics/CMakeLists.txt index dba73b6a6..f90c9a6db 100644 --- a/src/graphics/CMakeLists.txt +++ b/src/graphics/CMakeLists.txt @@ -16,6 +16,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure2DInterface.h ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_OutputFigure2D.cpp ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_OutputFigure2D.h + ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure3D.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/figures/codac2_Figure3D.h ${CMAKE_CURRENT_SOURCE_DIR}/paver/codac2_drawwhilepaving.cpp ${CMAKE_CURRENT_SOURCE_DIR}/paver/codac2_drawwhilepaving.h diff --git a/src/graphics/figures/codac2_Figure3D.cpp b/src/graphics/figures/codac2_Figure3D.cpp new file mode 100644 index 000000000..3167eedb7 --- /dev/null +++ b/src/graphics/figures/codac2_Figure3D.cpp @@ -0,0 +1,140 @@ +/** + * codac2_Figure3D.cpp + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include "codac2_Index.h" +#include "codac2_IntervalMatrix.h" +#include "codac2_Figure3D.h" +#include "codac2_math.h" + + +using namespace std; +using namespace codac2; + +Figure3D::Figure3D(const std::string& name) + : _name(name) +{ + _file.open(name + ".obj"); + _file<< "o "<left()->visit([&] + (std::shared_ptr n) + { + const IntervalVector& outer = get<0>(n->boxes()); + + if(n->is_leaf() && !outer.is_empty()) + draw_box(outer, boundary_style); + + return true; + }); +} + +void Figure3D::draw_paving(const PavingInOut& p, const StyleProperties& boundary_style, + const StyleProperties& inside_style) +{ + p.tree()->visit([&] + (std::shared_ptr n) + { + const IntervalVector& outer = get<0>(n->boxes()); + const IntervalVector& inner = get<1>(n->boxes()); + + IntervalVector hull = inner | outer; + + for(const auto& bi : hull.diff(inner)) + if (!bi.is_empty()) + draw_box(bi, inside_style); + + if(n->is_leaf()) + { + auto boundary = inner & outer; + if (!boundary.is_empty()) + draw_box(boundary, boundary_style); + } + return true; + }); +} \ No newline at end of file diff --git a/src/graphics/figures/codac2_Figure3D.h b/src/graphics/figures/codac2_Figure3D.h new file mode 100644 index 000000000..78e3ad880 --- /dev/null +++ b/src/graphics/figures/codac2_Figure3D.h @@ -0,0 +1,62 @@ +/** + * \file codac2_Figure3D.h + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#pragma once + +#include +#include +#include +#include "codac2_StyleProperties.h" +#include "codac2_IntervalVector.h" +#include "codac2_Paving.h" +#include "codac2_Vector.h" +#include "codac2_Matrix.h" + + +namespace codac2 +{ + + class Figure3D + { + public: + + Figure3D(const std::string& name); + ~Figure3D(); + + const std::string& name() const; + + void draw_axes(const double& size = 1.0); + + + // Geometric shapes + void draw_box(const IntervalVector& x, const StyleProperties& s = StyleProperties(Color::dark_gray(0.5))); + void draw_parallelepiped(const Vector& z, const Matrix& A, const StyleProperties& s = StyleProperties(Color::dark_gray(0.5))); + + // Pavings + void draw_paving(const PavingOut& p, + const StyleProperties& bound_s = StyleProperties(Color::yellow(0.5))); + void draw_paving(const PavingInOut& p, + const StyleProperties& bound_s = StyleProperties(Color::yellow(0.15)), + const StyleProperties& in_s = StyleProperties(Color::green(0.5))); + + template + void draw_subpaving(const Subpaving

    & p, const StyleProperties& s = StyleProperties()) + { + for(const auto& pi : p.boxes()) + draw_box(pi, s); + } + + protected: + + const std::string _name; + std::ofstream _file; + size_t vertex_count = 0; + + }; +} \ No newline at end of file From c7265a3c2b9c5c3e70416a398b7d3f6d97ea2841 Mon Sep 17 00:00:00 2001 From: godardma Date: Tue, 28 Jan 2025 14:44:22 +0100 Subject: [PATCH 120/126] [graphics] added python binding for Figure3D --- examples/06_graphics_3D/main.cpp | 5 +- examples/06_graphics_3D/main.py | 17 +++-- python/src/graphics/CMakeLists.txt | 1 + python/src/graphics/codac2_py_graphics.cpp | 2 + .../graphics/figures/codac2_py_Figure3D.cpp | 63 +++++++++++++++++++ 5 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 python/src/graphics/figures/codac2_py_Figure3D.cpp diff --git a/examples/06_graphics_3D/main.cpp b/examples/06_graphics_3D/main.cpp index 62e388b1a..2e34d02a3 100644 --- a/examples/06_graphics_3D/main.cpp +++ b/examples/06_graphics_3D/main.cpp @@ -22,8 +22,7 @@ int main() CtcInverse_ ctc(f, IntervalVector::zero(2)); auto p_ctc = pave({{0,2},{2,4},{0,10}}, ctc, 0.02); - Figure3D fig_ctc("PavingOut"); - fig_ctc.draw_axes(); + Figure3D fig_ctc("Paving contractor"); fig_ctc.draw_paving(p_ctc); @@ -33,7 +32,7 @@ int main() auto p_sep = pave({{-1.1,1.1},{-1.1,1.1},{-1.1,1.1}}, sep_ellipsoid&IntervalVector({{-1.5,1.5},{-0.1,0.1},{-1.5,1.5}}), 0.04); - Figure3D fig_sep("PavingInOut"); + Figure3D fig_sep("Paving separator"); fig_sep.draw_axes(0.4); fig_sep.draw_paving(p_sep); diff --git a/examples/06_graphics_3D/main.py b/examples/06_graphics_3D/main.py index 41ff95f49..26ef8d8c9 100644 --- a/examples/06_graphics_3D/main.py +++ b/examples/06_graphics_3D/main.py @@ -1,13 +1,22 @@ -# Example from the publication: -# https://www.ensta-bretagne.fr/jaulin/paper_centeredActa.pdf - from codac import * x = VectorVar(3) + +# Example from the publication: +# https://www.ensta-bretagne.fr/jaulin/paper_centeredActa.pdf f = AnalyticFunction([x], [ -sqr(x[2])+2*x[2]*sin(x[2]*x[0])+cos(x[2]*x[1]), 2*x[2]*cos(x[2]*x[0])-sin(x[2]*x[1]) ]) ctc = CtcInverse(f, [0,0]) -graphics.draw_while_paving([[0,2],[2,4],[0,10]], ctc, 0.004) \ No newline at end of file +p_ctc = pave([[0,2],[2,4],[0,10]], ctc, 0.02) +fig_ctc=Figure3D("Paving contractor") +fig_ctc.draw_paving(p_ctc) + + +sep_ellipsoid=SepInverse (AnalyticFunction([x], 2*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+sqr(x[1])+sqr(x[2])),Interval(0.4,1)) +p_sep = pave([[-1.1,1.1],[-1.1,1.1],[-1.1,1.1]], sep_ellipsoid&IntervalVector([[-1.5,1.5],[-0.1,0.1],[-1.5,1.5]]), 0.04) +fig_sep = Figure3D("Paving separator") +fig_sep.draw_axes(0.4) +fig_sep.draw_paving(p_sep) \ No newline at end of file diff --git a/python/src/graphics/CMakeLists.txt b/python/src/graphics/CMakeLists.txt index bb3fc85a3..31ec6b0f4 100644 --- a/python/src/graphics/CMakeLists.txt +++ b/python/src/graphics/CMakeLists.txt @@ -8,6 +8,7 @@ codac2_py_graphics.cpp figures/codac2_py_Figure2D.cpp + figures/codac2_py_Figure3D.cpp paver/codac2_py_drawwhilepaving.cpp diff --git a/python/src/graphics/codac2_py_graphics.cpp b/python/src/graphics/codac2_py_graphics.cpp index c5f9b520c..0a18835a1 100644 --- a/python/src/graphics/codac2_py_graphics.cpp +++ b/python/src/graphics/codac2_py_graphics.cpp @@ -16,6 +16,7 @@ namespace py = pybind11; // figures void export_Figure2D(py::module& m); +void export_Figure3D(py::module& m); // paver void export_drawwhilepaving(py::module& m); @@ -37,6 +38,7 @@ PYBIND11_MODULE(_graphics, m) // figures export_Figure2D(m); + export_Figure3D(m); // paver export_drawwhilepaving(m); diff --git a/python/src/graphics/figures/codac2_py_Figure3D.cpp b/python/src/graphics/figures/codac2_py_Figure3D.cpp new file mode 100644 index 000000000..e166a1d49 --- /dev/null +++ b/python/src/graphics/figures/codac2_py_Figure3D.cpp @@ -0,0 +1,63 @@ +/** + * Codac binding (graphics) + * ---------------------------------------------------------------------------- + * \date 2024 + * \author Maël Godard + * \copyright Copyright 2024 Codac Team + * \license GNU Lesser General Public License (LGPL) + */ + +#include +#include +#include +#include +#include +#include "codac2_py_Figure3D_docs.h" // Generated file from Doxygen XML (doxygen2docstring.py): +#include "codac2_py_matlab.h" +#include "codac2_py_cast.h" + +using namespace std; +using namespace codac2; +namespace py = pybind11; +using namespace pybind11::literals; + +void export_Figure3D(py::module& m) +{ + py::class_ + exported(m, "Figure3D", FIGURE3D_MAIN); + exported + + .def(py::init(), + FIGURE3D_FIGURE3D_CONST_STRING_REF, + "name"_a) + + .def("name", &Figure3D::name, + CONST_STRING_REF_FIGURE3D_NAME_CONST) + + .def("draw_axes", &Figure3D::draw_axes, + VOID_FIGURE3D_DRAW_AXES_CONST_DOUBLE_REF, + "size"_a=1.0) + + // Geometric shapes + + .def("draw_box", &Figure3D::draw_box, + VOID_FIGURE3D_DRAW_BOX_CONST_INTERVALVECTOR_REF_CONST_STYLEPROPERTIES_REF, + "x"_a, "s"_a=StyleProperties()) + + .def("draw_parallelepiped", &Figure3D::draw_parallelepiped, + VOID_FIGURE3D_DRAW_PARALLELEPIPED_CONST_VECTOR_REF_CONST_MATRIX_REF_CONST_STYLEPROPERTIES_REF, + "z"_a, "A"_a, "s"_a=StyleProperties()) + + + // Pavings + + .def("draw_paving", (void(Figure3D::*)(const PavingOut&, const StyleProperties&))&Figure3D::draw_paving, + VOID_FIGURE3D_DRAW_PAVING_CONST_PAVINGOUT_REF_CONST_STYLEPROPERTIES_REF, + "p"_a, "boundary_style"_a=StyleProperties(Color::yellow(0.5))) + + .def("draw_paving", (void(Figure3D::*)(const PavingInOut&,const StyleProperties&, const StyleProperties&))&Figure3D::draw_paving, + VOID_FIGURE3D_DRAW_PAVING_CONST_PAVINGINOUT_REF_CONST_STYLEPROPERTIES_REF_CONST_STYLEPROPERTIES_REF, + "p"_a, "boundary_style"_a=StyleProperties(Color::yellow(0.15)), "inside_style"_a=StyleProperties(Color::green(0.5))) + + ; +} \ No newline at end of file From db5eb0c3252ce214ca41fa3788b562d40db5937e Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 28 Jan 2025 17:38:33 +0100 Subject: [PATCH 121/126] [graphics] minor updates --- examples/06_graphics_3D/main.cpp | 3 --- examples/06_graphics_3D/main.py | 4 ---- python/src/graphics/codac2_py_graphics.cpp | 4 ++-- .../src/graphics/figures/codac2_py_Figure2D.cpp | 2 +- .../src/graphics/figures/codac2_py_Figure3D.cpp | 2 +- .../graphics/paver/codac2_py_drawwhilepaving.cpp | 2 +- python/src/graphics/styles/codac2_py_Color.cpp | 2 +- python/src/graphics/styles/codac2_py_ColorMap.cpp | 2 +- .../graphics/styles/codac2_py_StyleProperties.cpp | 2 +- python/src/unsupported/codac2_py_unsupported.cpp | 2 +- src/graphics/figures/codac2_Figure3D.cpp | 14 +++++++------- src/graphics/figures/codac2_Figure3D.h | 15 +++++++-------- 12 files changed, 23 insertions(+), 31 deletions(-) diff --git a/examples/06_graphics_3D/main.cpp b/examples/06_graphics_3D/main.cpp index 2e34d02a3..878befc79 100644 --- a/examples/06_graphics_3D/main.cpp +++ b/examples/06_graphics_3D/main.cpp @@ -9,9 +9,6 @@ int main() { VectorVar x(3); - // Example from the publication: - // https://www.ensta-bretagne.fr/jaulin/paper_centeredActa.pdf - AnalyticFunction f { {x}, { -sqr(x[2])+2*x[2]*sin(x[2]*x[0])+cos(x[2]*x[1]), diff --git a/examples/06_graphics_3D/main.py b/examples/06_graphics_3D/main.py index 26ef8d8c9..56997bb56 100644 --- a/examples/06_graphics_3D/main.py +++ b/examples/06_graphics_3D/main.py @@ -1,9 +1,6 @@ from codac import * x = VectorVar(3) - -# Example from the publication: -# https://www.ensta-bretagne.fr/jaulin/paper_centeredActa.pdf f = AnalyticFunction([x], [ -sqr(x[2])+2*x[2]*sin(x[2]*x[0])+cos(x[2]*x[1]), 2*x[2]*cos(x[2]*x[0])-sin(x[2]*x[1]) @@ -14,7 +11,6 @@ fig_ctc=Figure3D("Paving contractor") fig_ctc.draw_paving(p_ctc) - sep_ellipsoid=SepInverse (AnalyticFunction([x], 2*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+sqr(x[1])+sqr(x[2])),Interval(0.4,1)) p_sep = pave([[-1.1,1.1],[-1.1,1.1],[-1.1,1.1]], sep_ellipsoid&IntervalVector([[-1.5,1.5],[-0.1,0.1],[-1.5,1.5]]), 0.04) fig_sep = Figure3D("Paving separator") diff --git a/python/src/graphics/codac2_py_graphics.cpp b/python/src/graphics/codac2_py_graphics.cpp index 0a18835a1..38e977ef5 100644 --- a/python/src/graphics/codac2_py_graphics.cpp +++ b/python/src/graphics/codac2_py_graphics.cpp @@ -1,9 +1,9 @@ /** * \file - * Codac binding (core) + * Codac binding (graphics) * ---------------------------------------------------------------------------- * \date 2020 - * \author Simon Rohou, Benoît Desrochers + * \author Simon Rohou, Maël Godard * \copyright Copyright 2021 Codac Team * \license GNU Lesser General Public License (LGPL) */ diff --git a/python/src/graphics/figures/codac2_py_Figure2D.cpp b/python/src/graphics/figures/codac2_py_Figure2D.cpp index 6375cd1aa..c1987ec7b 100644 --- a/python/src/graphics/figures/codac2_py_Figure2D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure2D.cpp @@ -1,5 +1,5 @@ /** - * Codac binding (core) + * Codac binding (graphics) * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou, Maël Godard diff --git a/python/src/graphics/figures/codac2_py_Figure3D.cpp b/python/src/graphics/figures/codac2_py_Figure3D.cpp index e166a1d49..46158b308 100644 --- a/python/src/graphics/figures/codac2_py_Figure3D.cpp +++ b/python/src/graphics/figures/codac2_py_Figure3D.cpp @@ -35,7 +35,7 @@ void export_Figure3D(py::module& m) CONST_STRING_REF_FIGURE3D_NAME_CONST) .def("draw_axes", &Figure3D::draw_axes, - VOID_FIGURE3D_DRAW_AXES_CONST_DOUBLE_REF, + VOID_FIGURE3D_DRAW_AXES_DOUBLE, "size"_a=1.0) // Geometric shapes diff --git a/python/src/graphics/paver/codac2_py_drawwhilepaving.cpp b/python/src/graphics/paver/codac2_py_drawwhilepaving.cpp index 6d63aafd6..6964b8f99 100644 --- a/python/src/graphics/paver/codac2_py_drawwhilepaving.cpp +++ b/python/src/graphics/paver/codac2_py_drawwhilepaving.cpp @@ -1,5 +1,5 @@ /** - * Codac binding (core) + * Codac binding (graphics) * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou diff --git a/python/src/graphics/styles/codac2_py_Color.cpp b/python/src/graphics/styles/codac2_py_Color.cpp index 4e518227b..0bc4b032c 100644 --- a/python/src/graphics/styles/codac2_py_Color.cpp +++ b/python/src/graphics/styles/codac2_py_Color.cpp @@ -1,5 +1,5 @@ /** - * Codac binding (core) + * Codac binding (graphics) * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou diff --git a/python/src/graphics/styles/codac2_py_ColorMap.cpp b/python/src/graphics/styles/codac2_py_ColorMap.cpp index e127777e9..537d2f568 100644 --- a/python/src/graphics/styles/codac2_py_ColorMap.cpp +++ b/python/src/graphics/styles/codac2_py_ColorMap.cpp @@ -1,5 +1,5 @@ /** - * Codac binding (core) + * Codac binding (graphics) * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou, Maël Godard diff --git a/python/src/graphics/styles/codac2_py_StyleProperties.cpp b/python/src/graphics/styles/codac2_py_StyleProperties.cpp index 0259a3db9..a9e32fff5 100644 --- a/python/src/graphics/styles/codac2_py_StyleProperties.cpp +++ b/python/src/graphics/styles/codac2_py_StyleProperties.cpp @@ -1,5 +1,5 @@ /** - * Codac binding (core) + * Codac binding (graphics) * ---------------------------------------------------------------------------- * \date 2024 * \author Simon Rohou diff --git a/python/src/unsupported/codac2_py_unsupported.cpp b/python/src/unsupported/codac2_py_unsupported.cpp index 818efeff3..f214d7267 100644 --- a/python/src/unsupported/codac2_py_unsupported.cpp +++ b/python/src/unsupported/codac2_py_unsupported.cpp @@ -1,6 +1,6 @@ /** * \file - * Codac binding (core) + * Codac binding (unsupported) * ---------------------------------------------------------------------------- * \date 2020 * \author Simon Rohou, Benoît Desrochers diff --git a/src/graphics/figures/codac2_Figure3D.cpp b/src/graphics/figures/codac2_Figure3D.cpp index 3167eedb7..48d731bd7 100644 --- a/src/graphics/figures/codac2_Figure3D.cpp +++ b/src/graphics/figures/codac2_Figure3D.cpp @@ -33,7 +33,7 @@ const std::string& Figure3D::name() const return _name; } -void Figure3D::draw_axes(const double& size) +void Figure3D::draw_axes(double size) { _file<< "o axes\n"; // X axis @@ -88,12 +88,12 @@ void Figure3D::draw_parallelepiped(const Vector& z, const Matrix& A, const Style _file << "v " << v7[0] << " " << v7[1] << " " << v7[2] << "\n"; size_t v = vertex_count + 1; - _file << "f " << v + 0 << " " << v + 1 << " " << v + 3 << " " << v + 2 << "\n"; // Bottom face - _file << "f " << v + 4 << " " << v + 5 << " " << v + 7 << " " << v + 6 << "\n"; // Top face - _file << "f " << v + 0 << " " << v + 4 << " " << v + 6 << " " << v + 2 << "\n"; // Front face - _file << "f " << v + 1 << " " << v + 5 << " " << v + 7 << " " << v + 3 << "\n"; // Back face - _file << "f " << v + 0 << " " << v + 4 << " " << v + 5 << " " << v + 1 << "\n"; // Left face - _file << "f " << v + 2 << " " << v + 6 << " " << v + 7 << " " << v + 3 << "\n"; // Right face + _file << "f " << v + 0 << " " << v + 1 << " " << v + 3 << " " << v + 2 << "\n"; + _file << "f " << v + 4 << " " << v + 5 << " " << v + 7 << " " << v + 6 << "\n"; + _file << "f " << v + 0 << " " << v + 4 << " " << v + 6 << " " << v + 2 << "\n"; + _file << "f " << v + 1 << " " << v + 5 << " " << v + 7 << " " << v + 3 << "\n"; + _file << "f " << v + 0 << " " << v + 4 << " " << v + 5 << " " << v + 1 << "\n"; + _file << "f " << v + 2 << " " << v + 6 << " " << v + 7 << " " << v + 3 << "\n"; vertex_count += 8; diff --git a/src/graphics/figures/codac2_Figure3D.h b/src/graphics/figures/codac2_Figure3D.h index 78e3ad880..85d93863c 100644 --- a/src/graphics/figures/codac2_Figure3D.h +++ b/src/graphics/figures/codac2_Figure3D.h @@ -31,22 +31,22 @@ namespace codac2 const std::string& name() const; - void draw_axes(const double& size = 1.0); + void draw_axes(double size = 1.0); // Geometric shapes - void draw_box(const IntervalVector& x, const StyleProperties& s = StyleProperties(Color::dark_gray(0.5))); - void draw_parallelepiped(const Vector& z, const Matrix& A, const StyleProperties& s = StyleProperties(Color::dark_gray(0.5))); + void draw_box(const IntervalVector& x, const StyleProperties& s = { Color::dark_gray(0.5) }); + void draw_parallelepiped(const Vector& z, const Matrix& A, const StyleProperties& s = { Color::dark_gray(0.5) }); // Pavings void draw_paving(const PavingOut& p, - const StyleProperties& bound_s = StyleProperties(Color::yellow(0.5))); + const StyleProperties& bound_s = { Color::yellow(0.5) }); void draw_paving(const PavingInOut& p, - const StyleProperties& bound_s = StyleProperties(Color::yellow(0.15)), - const StyleProperties& in_s = StyleProperties(Color::green(0.5))); + const StyleProperties& bound_s = { Color::yellow(0.15) }, + const StyleProperties& in_s = { Color::green(0.5) }); template - void draw_subpaving(const Subpaving

    & p, const StyleProperties& s = StyleProperties()) + inline void draw_subpaving(const Subpaving

    & p, const StyleProperties& s = StyleProperties()) { for(const auto& pi : p.boxes()) draw_box(pi, s); @@ -57,6 +57,5 @@ namespace codac2 const std::string _name; std::ofstream _file; size_t vertex_count = 0; - }; } \ No newline at end of file From 4a014a5e46470693ecd8a956357e397f01f82776 Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Tue, 28 Jan 2025 18:28:36 +0100 Subject: [PATCH 122/126] [doc] added favicon --- doc/manual/_static/logos/logo_codac.ico | Bin 0 -> 1406 bytes doc/manual/conf.py.in | 1 + 2 files changed, 1 insertion(+) create mode 100644 doc/manual/_static/logos/logo_codac.ico diff --git a/doc/manual/_static/logos/logo_codac.ico b/doc/manual/_static/logos/logo_codac.ico new file mode 100644 index 0000000000000000000000000000000000000000..31f48dc9254a078d8a95a39b5016318a8736ea6b GIT binary patch literal 1406 zcmZQzU<5(|0R|w+!H~hqz#zuJz@P!dKp_SNAO?x!0y`Tt8TNFzG3*86Q%mX@&a7wy z;&z5JD?zveh&vh1tmPYy@-c=tk8U!&eRPZA?c>`(e23xP6Ci$ikKsKCKfBNHtM1cT{iV}!YRAB>Aa3HB70%wC5d@9OZ jC;~Dn%A(xdpu!CT7^T6^VTSP;7XO Date: Wed, 29 Jan 2025 12:47:10 +0100 Subject: [PATCH 123/126] [src] extensions folder --- src/CMakeLists.txt | 2 +- src/{ => extensions}/capd/CMakeLists.txt | 4 ++-- src/{ => extensions}/capd/codac2_capd.cpp | 0 src/{ => extensions}/capd/codac2_capd.h | 0 src/{ => extensions}/sympy/CMakeLists.txt | 0 src/{ => extensions}/sympy/codac2_sympy_empty.cpp | 0 src/{ => extensions}/sympy/codac2_sympy_empty.h | 0 7 files changed, 3 insertions(+), 3 deletions(-) rename src/{ => extensions}/capd/CMakeLists.txt (97%) rename src/{ => extensions}/capd/codac2_capd.cpp (100%) rename src/{ => extensions}/capd/codac2_capd.h (100%) rename src/{ => extensions}/sympy/CMakeLists.txt (100%) rename src/{ => extensions}/sympy/codac2_sympy_empty.cpp (100%) rename src/{ => extensions}/sympy/codac2_sympy_empty.h (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 444611bee..2602c588d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,7 +15,7 @@ #endif() if(WITH_CAPD) - add_subdirectory(capd) + add_subdirectory(extensions/capd) endif() diff --git a/src/capd/CMakeLists.txt b/src/extensions/capd/CMakeLists.txt similarity index 97% rename from src/capd/CMakeLists.txt rename to src/extensions/capd/CMakeLists.txt index eb20b24b9..ea71dc8a8 100644 --- a/src/capd/CMakeLists.txt +++ b/src/extensions/capd/CMakeLists.txt @@ -38,7 +38,7 @@ list(APPEND CODAC_CAPD_SRC foreach(srcfile ${CODAC_CAPD_SRC}) if(srcfile MATCHES "\\.h$" OR srcfile MATCHES "\\.hpp$") list(APPEND CODAC_CAPD_HDR ${srcfile}) - file(COPY ${srcfile} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../include) + file(COPY ${srcfile} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../../include) endif() endforeach() @@ -51,7 +51,7 @@ list(APPEND CODAC_CAPD_SRC get_filename_component(header_name ${header_path} NAME) file(APPEND ${CODAC_CAPD_MAIN_HEADER} "#include <${header_name}>\n") endforeach() - file(COPY ${CODAC_CAPD_MAIN_HEADER} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../include) + file(COPY ${CODAC_CAPD_MAIN_HEADER} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../../include) # Install files in system directories diff --git a/src/capd/codac2_capd.cpp b/src/extensions/capd/codac2_capd.cpp similarity index 100% rename from src/capd/codac2_capd.cpp rename to src/extensions/capd/codac2_capd.cpp diff --git a/src/capd/codac2_capd.h b/src/extensions/capd/codac2_capd.h similarity index 100% rename from src/capd/codac2_capd.h rename to src/extensions/capd/codac2_capd.h diff --git a/src/sympy/CMakeLists.txt b/src/extensions/sympy/CMakeLists.txt similarity index 100% rename from src/sympy/CMakeLists.txt rename to src/extensions/sympy/CMakeLists.txt diff --git a/src/sympy/codac2_sympy_empty.cpp b/src/extensions/sympy/codac2_sympy_empty.cpp similarity index 100% rename from src/sympy/codac2_sympy_empty.cpp rename to src/extensions/sympy/codac2_sympy_empty.cpp diff --git a/src/sympy/codac2_sympy_empty.h b/src/extensions/sympy/codac2_sympy_empty.h similarity index 100% rename from src/sympy/codac2_sympy_empty.h rename to src/extensions/sympy/codac2_sympy_empty.h From e377bcc8070a93ca84c3513a4b9dc4b0862a845d Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 29 Jan 2025 13:07:53 +0100 Subject: [PATCH 124/126] [ext] organizing extensions (capd/ibex) --- src/CMakeLists.txt | 32 ++++++++++++++++--- src/core/CMakeLists.txt | 4 --- src/extensions/capd/codac2_capd.h | 2 -- .../3rd => extensions/ibex}/codac2_ibex.cpp | 0 .../3rd => extensions/ibex}/codac2_ibex.h | 0 tests/CMakeLists.txt | 11 +++++-- .../capd/codac2_tests_capd.cpp | 0 .../capd/codac2_tests_capd.py | 0 .../ibex}/codac2_tests_ibex.cpp | 0 .../ibex}/codac2_tests_ibex.py | 0 10 files changed, 37 insertions(+), 12 deletions(-) rename src/{core/3rd => extensions/ibex}/codac2_ibex.cpp (100%) rename src/{core/3rd => extensions/ibex}/codac2_ibex.h (100%) rename tests/{ => extensions}/capd/codac2_tests_capd.cpp (100%) rename tests/{ => extensions}/capd/codac2_tests_capd.py (100%) rename tests/{core/3rd => extensions/ibex}/codac2_tests_ibex.cpp (100%) rename tests/{core/3rd => extensions/ibex}/codac2_tests_ibex.py (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2602c588d..0429fb501 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,13 +10,17 @@ add_subdirectory(graphics) add_subdirectory(unsupported) - #if(WITH_PYTHON) - # add_subdirectory(sympy) - #endif() - if(WITH_CAPD) add_subdirectory(extensions/capd) endif() + + #if(WITH_IBEX) # included by default for now + add_subdirectory(extensions/ibex) + #endif() + + #if(WITH_PYTHON) + # add_subdirectory(sympy) + #endif() # Generating PKG file @@ -115,6 +119,26 @@ endif() + #if(WITH_IBEX) # included by default for now + + file(APPEND ${CODAC_CMAKE_CONFIG_FILE} " + + # Optional 3rd party: + + find_package(IBEX REQUIRED) + + find_path(CODAC_IBEX_INCLUDE_DIR ${PROJECT_NAME}-ibex.h + PATH_SUFFIXES include/${PROJECT_NAME}-ibex) + set(CODAC_INCLUDE_DIRS \${CODAC_INCLUDE_DIRS} \${CODAC_IBEX_INCLUDE_DIR}) + + find_library(CODAC_IBEX_LIBRARY NAMES ${PROJECT_NAME}-ibex + PATH_SUFFIXES lib) + + set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_IBEX_LIBRARY} Ibex::ibex) + ") + + #endif() + file(APPEND ${CODAC_CMAKE_CONFIG_FILE} " set(CODAC_LIBRARIES \${CODAC_LIBRARIES} \${CODAC_GRAPHICS_LIBRARY} \${CODAC_CORE_LIBRARY}) ") diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 60e9057d5..0a5e55929 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -4,9 +4,6 @@ list(APPEND CODAC_CORE_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/3rd/codac2_ibex.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/3rd/codac2_ibex.h - ${CMAKE_CURRENT_SOURCE_DIR}/actions/codac2_OctaSym.cpp ${CMAKE_CURRENT_SOURCE_DIR}/actions/codac2_OctaSym.h @@ -184,7 +181,6 @@ add_library(${PROJECT_NAME}-core ${CODAC_CORE_SRC}) target_include_directories(${PROJECT_NAME}-core PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/3rd ${CMAKE_CURRENT_SOURCE_DIR}/actions ${CMAKE_CURRENT_SOURCE_DIR}/contractors ${CMAKE_CURRENT_SOURCE_DIR}/domains diff --git a/src/extensions/capd/codac2_capd.h b/src/extensions/capd/codac2_capd.h index 9c442fcd3..3e9d79051 100644 --- a/src/extensions/capd/codac2_capd.h +++ b/src/extensions/capd/codac2_capd.h @@ -9,7 +9,6 @@ #pragma once -// #include "capd/capdlib.h" #include #include #include "codac2_IntervalVector.h" @@ -18,7 +17,6 @@ namespace codac2 { - /** * \brief Casts a Codac Interval object into an CAPD Interval object * diff --git a/src/core/3rd/codac2_ibex.cpp b/src/extensions/ibex/codac2_ibex.cpp similarity index 100% rename from src/core/3rd/codac2_ibex.cpp rename to src/extensions/ibex/codac2_ibex.cpp diff --git a/src/core/3rd/codac2_ibex.h b/src/extensions/ibex/codac2_ibex.h similarity index 100% rename from src/core/3rd/codac2_ibex.h rename to src/extensions/ibex/codac2_ibex.h diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 990dd44af..094c3c71f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -34,7 +34,6 @@ list(APPEND SRC_TESTS # listing files without extension # Core core/3rd/codac2_tests_eigen - core/3rd/codac2_tests_ibex core/actions/codac2_tests_OctaSym @@ -90,11 +89,19 @@ set(CODAC_LIBRARIES ${PROJECT_NAME}-core) # CAPD test if (WITH_CAPD) list(APPEND SRC_TESTS - capd/codac2_tests_capd + extensions/capd/codac2_tests_capd ) set(CODAC_LIBRARIES ${CODAC_LIBRARIES} ${PROJECT_NAME}-capd capd::capd) endif() +# IBEX test +#if (WITH_IBEX) + list(APPEND SRC_TESTS + extensions/ibex/codac2_tests_ibex + ) + set(CODAC_LIBRARIES ${CODAC_LIBRARIES} ${PROJECT_NAME}-ibex) +#endif() + foreach(SRC_TEST ${SRC_TESTS}) string(REPLACE "/" "_" TEST_NAME ${SRC_TEST}) string(REPLACE "codac2_tests_" "" TEST_NAME ${TEST_NAME}) diff --git a/tests/capd/codac2_tests_capd.cpp b/tests/extensions/capd/codac2_tests_capd.cpp similarity index 100% rename from tests/capd/codac2_tests_capd.cpp rename to tests/extensions/capd/codac2_tests_capd.cpp diff --git a/tests/capd/codac2_tests_capd.py b/tests/extensions/capd/codac2_tests_capd.py similarity index 100% rename from tests/capd/codac2_tests_capd.py rename to tests/extensions/capd/codac2_tests_capd.py diff --git a/tests/core/3rd/codac2_tests_ibex.cpp b/tests/extensions/ibex/codac2_tests_ibex.cpp similarity index 100% rename from tests/core/3rd/codac2_tests_ibex.cpp rename to tests/extensions/ibex/codac2_tests_ibex.cpp diff --git a/tests/core/3rd/codac2_tests_ibex.py b/tests/extensions/ibex/codac2_tests_ibex.py similarity index 100% rename from tests/core/3rd/codac2_tests_ibex.py rename to tests/extensions/ibex/codac2_tests_ibex.py From 895df62f41400d1ef7b2b74dfdb1e4845cc653fc Mon Sep 17 00:00:00 2001 From: Simon Rohou Date: Wed, 29 Jan 2025 13:14:12 +0100 Subject: [PATCH 125/126] [ext] organizing extensions (capd/ibex) (missing CMakeLists) --- src/extensions/ibex/CMakeLists.txt | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/extensions/ibex/CMakeLists.txt diff --git a/src/extensions/ibex/CMakeLists.txt b/src/extensions/ibex/CMakeLists.txt new file mode 100644 index 000000000..529a13e06 --- /dev/null +++ b/src/extensions/ibex/CMakeLists.txt @@ -0,0 +1,60 @@ +# ================================================================== +# Codac - cmake configuration file +# ================================================================== + +list(APPEND CODAC_IBEX_SRC + + ${CMAKE_CURRENT_SOURCE_DIR}/codac2_ibex.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/codac2_ibex.h +) + +################################################################################ +# Create the target for libcodac-ibex +################################################################################ + + #if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + #endif() + + add_library(${PROJECT_NAME}-ibex ${CODAC_IBEX_SRC}) + target_link_libraries(${PROJECT_NAME}-ibex PUBLIC ${PROJECT_NAME}-core Ibex::ibex Eigen3::Eigen Ibex::ibex) + + + ################################################################################ + # For the generation of the PKG file + ################################################################################ + + set(CODAC_PKG_CONFIG_CFLAGS "${CODAC_PKG_CONFIG_CFLAGS} -I\${includedir}/${PROJECT_NAME}-ibex" PARENT_SCOPE) + set(CODAC_PKG_CONFIG_LIBS "${CODAC_PKG_CONFIG_LIBS} -l${PROJECT_NAME}-ibex" PARENT_SCOPE) + + + ################################################################################ + # Installation of libcodac-ibex files + ################################################################################ + + # Getting header files from sources + + foreach(srcfile ${CODAC_IBEX_SRC}) + if(srcfile MATCHES "\\.h$" OR srcfile MATCHES "\\.hpp$") + list(APPEND CODAC_IBEX_HDR ${srcfile}) + file(COPY ${srcfile} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../../include) + endif() + endforeach() + + # Generating the file codac-ibex.h + + set(CODAC_IBEX_MAIN_HEADER ${CMAKE_CURRENT_BINARY_DIR}/codac-ibex.h) + file(WRITE ${CODAC_IBEX_MAIN_HEADER} "/* This file is generated by CMake */\n\n") + file(APPEND ${CODAC_IBEX_MAIN_HEADER} "#pragma once\n\n") + foreach(header_path ${CODAC_IBEX_HDR}) + get_filename_component(header_name ${header_path} NAME) + file(APPEND ${CODAC_IBEX_MAIN_HEADER} "#include <${header_name}>\n") + endforeach() + file(COPY ${CODAC_IBEX_MAIN_HEADER} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../../../include) + + # Install files in system directories + + install(TARGETS ${PROJECT_NAME}-ibex DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(FILES ${CODAC_IBEX_HDR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-ibex) + install(FILES ${CODAC_IBEX_MAIN_HEADER} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-ibex) \ No newline at end of file From 408bd6d7aa2297852dadd3cac1ae7b3521e8cd93 Mon Sep 17 00:00:00 2001 From: godardma Date: Wed, 29 Jan 2025 19:18:35 +0100 Subject: [PATCH 126/126] [graphics] updated Figure3D example --- examples/06_graphics_3D/main.cpp | 9 ++++++--- examples/06_graphics_3D/main.py | 5 +++-- src/graphics/figures/codac2_Figure3D.h | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/06_graphics_3D/main.cpp b/examples/06_graphics_3D/main.cpp index 878befc79..a47191c36 100644 --- a/examples/06_graphics_3D/main.cpp +++ b/examples/06_graphics_3D/main.cpp @@ -23,11 +23,14 @@ int main() fig_ctc.draw_paving(p_ctc); - SepInverse sep_ellipsoid( - AnalyticFunction({x}, 2*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+sqr(x[1])+sqr(x[2])), + SepInverse sep_ellipsoid1( + AnalyticFunction({x}, 0.5*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+2*sqr(x[1])+2*sqr(x[2])), Interval(0.4,1)); + SepInverse sep_ellipsoid2( + AnalyticFunction({x}, 3*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+sqr(x[1])+sqr(x[2])), + Interval(0,1)); - auto p_sep = pave({{-1.1,1.1},{-1.1,1.1},{-1.1,1.1}}, sep_ellipsoid&IntervalVector({{-1.5,1.5},{-0.1,0.1},{-1.5,1.5}}), 0.04); + auto p_sep = pave({{-1.1,1.1},{-1.1,1.1},{-1.1,1.1}}, sep_ellipsoid1&sep_ellipsoid2, 0.1); Figure3D fig_sep("Paving separator"); fig_sep.draw_axes(0.4); diff --git a/examples/06_graphics_3D/main.py b/examples/06_graphics_3D/main.py index 56997bb56..3f2ea8cbd 100644 --- a/examples/06_graphics_3D/main.py +++ b/examples/06_graphics_3D/main.py @@ -11,8 +11,9 @@ fig_ctc=Figure3D("Paving contractor") fig_ctc.draw_paving(p_ctc) -sep_ellipsoid=SepInverse (AnalyticFunction([x], 2*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+sqr(x[1])+sqr(x[2])),Interval(0.4,1)) -p_sep = pave([[-1.1,1.1],[-1.1,1.1],[-1.1,1.1]], sep_ellipsoid&IntervalVector([[-1.5,1.5],[-0.1,0.1],[-1.5,1.5]]), 0.04) +sep_ellipsoid1=SepInverse (AnalyticFunction([x], 0.5*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+2*sqr(x[1])+2*sqr(x[2])),Interval(0.4,1)) +sep_ellipsoid2=SepInverse (AnalyticFunction([x], 3*sqr(x[0])+x[0]*x[1]+x[0]*x[2]+sqr(x[1])+sqr(x[2])),Interval(0.,1)) +p_sep = pave([[-1.5,1.5],[-1.5,1.5],[-1.5,1.5]], sep_ellipsoid1&sep_ellipsoid2, 0.1) fig_sep = Figure3D("Paving separator") fig_sep.draw_axes(0.4) fig_sep.draw_paving(p_sep) \ No newline at end of file diff --git a/src/graphics/figures/codac2_Figure3D.h b/src/graphics/figures/codac2_Figure3D.h index 85d93863c..18c77d4c5 100644 --- a/src/graphics/figures/codac2_Figure3D.h +++ b/src/graphics/figures/codac2_Figure3D.h @@ -42,7 +42,7 @@ namespace codac2 void draw_paving(const PavingOut& p, const StyleProperties& bound_s = { Color::yellow(0.5) }); void draw_paving(const PavingInOut& p, - const StyleProperties& bound_s = { Color::yellow(0.15) }, + const StyleProperties& bound_s = { Color::yellow(0.3) }, const StyleProperties& in_s = { Color::green(0.5) }); template