Commit 1b32975f authored by Olivier Stasse's avatar Olivier Stasse Committed by olivier stasse
Browse files

Fix and test the inclusion problem of both fast and rt.

Add a unittest showing the problem with classical use of the library.
parent b08d57dd
......@@ -22,21 +22,7 @@
namespace eiquadprog {
namespace solvers {
/// Compute sqrt(a^2 + b^2)
template <typename Scalar>
inline Scalar distance(Scalar a, Scalar b) {
Scalar a1, b1, t;
a1 = std::abs(a);
b1 = std::abs(b);
if (a1 > b1) {
t = (b1 / a1);
return a1 * std::sqrt(1.0 + t * t);
} else if (b1 > a1) {
t = (a1 / b1);
return b1 * std::sqrt(1.0 + t * t);
}
return a1 * std::sqrt(2.0);
}
#include "eiquadprog/eiquadprog-utils.hxx"
EiquadprogFast::EiquadprogFast() {
m_maxIter = DEFAULT_MAX_ITER;
......@@ -216,14 +202,6 @@ void EiquadprogFast::delete_constraint(MatrixXd& R, MatrixXd& J, VectorXi& A, Ve
}
}
template <class Derived>
void print_vector(const char* name, Eigen::MatrixBase<Derived>& x, int n) {
// std::cerr << name << x.transpose() << std::endl;
}
template <class Derived>
void print_matrix(const char* name, Eigen::MatrixBase<Derived>& x, int n) {
// std::cerr << name << std::endl << x << std::endl;
}
EiquadprogFast_status EiquadprogFast::solve_quadprog(const MatrixXd& Hess, const VectorXd& g0, const MatrixXd& CE,
const VectorXd& ce0, const MatrixXd& CI, const VectorXd& ci0,
......@@ -634,4 +612,5 @@ l2a: /* Step 2a: determine step direction */
} /* namespace solvers */
} /* namespace eiquadprog */
#endif /* EIQUADPROGFAST_HXX_ */
......@@ -19,6 +19,8 @@
#ifndef __eiquadprog_rt_hxx__
#define __eiquadprog_rt_hxx__
#include "eiquadprog/eiquadprog-utils.hxx"
namespace eiquadprog {
namespace solvers {
......@@ -182,15 +184,6 @@ void RtEiquadprog<nVars, nEqCon, nIneqCon>::delete_constraint(typename RtMatrixX
}
}
template <class Derived>
void print_vector(const char* name, Eigen::MatrixBase<Derived>& x, int n) {
// std::cerr << name << x.transpose() << std::endl;
}
template <class Derived>
void print_matrix(const char* name, Eigen::MatrixBase<Derived>& x, int n) {
// std::cerr << name << std::endl << x << std::endl;
}
template <int nVars, int nEqCon, int nIneqCon>
RtEiquadprog_status RtEiquadprog<nVars, nEqCon, nIneqCon>::solve_quadprog(
const typename RtMatrixX<nVars, nVars>::d& Hess, const typename RtVectorX<nVars>::d& g0,
......
#ifndef EIQUADPROG_UTILS_HPP_
#define EIQUADPROG_UTILS_HPP_
/// Compute sqrt(a^2 + b^2)
template <typename Scalar>
inline Scalar distance(Scalar a, Scalar b) {
Scalar a1, b1, t;
a1 = std::abs(a);
b1 = std::abs(b);
if (a1 > b1) {
t = (b1 / a1);
return a1 * std::sqrt(1.0 + t * t);
} else if (b1 > a1) {
t = (a1 / b1);
return b1 * std::sqrt(1.0 + t * t);
}
return a1 * std::sqrt(2.0);
}
template <class Derived>
void print_vector(const char* name, Eigen::MatrixBase<Derived>& x, int n) {
// std::cerr << name << x.transpose() << std::endl;
}
template <class Derived>
void print_matrix(const char* name, Eigen::MatrixBase<Derived>& x, int n) {
// std::cerr << name << std::endl << x << std::endl;
}
#endif
......@@ -22,9 +22,16 @@ SET(TESTS
eiquadprog-basic
eiquadprog-fast
eiquadprog-rt
eiquadprog-both
)
FOREACH(test ${TESTS})
ADD_UNIT_TEST(${test} ${test}.cpp)
TARGET_LINK_LIBRARIES(${test} ${PROJECT_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
ENDFOREACH(test ${TESTS})
ADD_LIBRARY(testab SHARED TestA.cpp TestB.cpp)
TARGET_INCLUDE_DIRECTORIES(testab SYSTEM PRIVATE ${EIGEN3_INCLUDE_DIR})
#ADD_UNIT_TEST(test-integration test-integration.cpp )
#TARGET_LINK_LIBRARIES(test-integration ${PROJECT_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} testab)
#include <iostream>
#include <Eigen/Core>
#include <boost/test/unit_test.hpp>
#include "TestA.hpp"
using namespace eiquadprog::solvers;
using namespace eiquadprog::tests;
A::A():
Q_(2, 2),
C_(2),
Aeq_(0,2),
Beq_(0),
Aineq_(0,2),
Bineq_(0),
solution_(2),
QP_()
{
QP_.reset(2, 0, 0);
Q_.setZero();
Q_(0, 0) = 1.0;
Q_(1, 1) = 1.0;
C_.setZero();
solution_.setZero();
expected_ = EIQUADPROG_FAST_OPTIMAL;
}
EiquadprogFast_status A::solve(Eigen::VectorXd &x)
{
return QP_.solve_quadprog(Q_, C_, Aeq_, Beq_, Aineq_, Bineq_, x);
}
#include <iostream>
#include <Eigen/Core>
#include <boost/test/unit_test.hpp>
#include "TestB.hpp"
using namespace eiquadprog::solvers;
using namespace eiquadprog::tests;
B::B()
{
}
bool B::do_something()
{
}
//
// Copyright (c) 2019 CNRS
//
// This file is part of eiquadprog.
//
// eiquadprog is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
// eiquadprog is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with eiquadprog. If not, see <https://www.gnu.org/licenses/>.
#include <iostream>
#include <Eigen/Core>
#include <boost/test/unit_test.hpp>
#include "eiquadprog/eiquadprog-fast.hpp"
#include "eiquadprog/eiquadprog-rt.hpp"
using namespace eiquadprog::solvers;
/**
* solves the problem
* min. 0.5 * x' Hess x + g0' x
* s.t. CE x + ce0 = 0
* CI x + ci0 >= 0
*/
BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
// min ||x||^2
BOOST_AUTO_TEST_CASE(test_unbiased) {
EiquadprogFast qp;
qp.reset(2, 0, 0);
Eigen::MatrixXd Q(2, 2);
Q.setZero();
Q(0, 0) = 1.0;
Q(1, 1) = 1.0;
Eigen::VectorXd C(2);
C.setZero();
Eigen::MatrixXd Aeq(0, 2);
Eigen::VectorXd Beq(0);
Eigen::MatrixXd Aineq(0, 2);
Eigen::VectorXd Bineq(0);
Eigen::VectorXd x(2);
Eigen::VectorXd solution(2);
solution.setZero();
double val = 0.0;
EiquadprogFast_status expected = EIQUADPROG_FAST_OPTIMAL;
EiquadprogFast_status status = qp.solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x);
BOOST_CHECK_EQUAL(status, expected);
BOOST_CHECK_CLOSE(qp.getObjValue(), val, 1e-6);
BOOST_CHECK(x.isApprox(solution));
}
// min ||x-x_0||^2, x_0 = (1 1)^T
BOOST_AUTO_TEST_CASE(test_biased) {
RtEiquadprog<2, 0, 0> qp;
RtMatrixX<2, 2>::d Q;
Q.setZero();
Q(0, 0) = 1.0;
Q(1, 1) = 1.0;
RtVectorX<2>::d C;
C(0) = -1.;
C(1) = -1.;
RtMatrixX<0, 2>::d Aeq;
RtVectorX<0>::d Beq;
RtMatrixX<0, 2>::d Aineq;
RtVectorX<0>::d Bineq;
RtVectorX<2>::d x;
RtVectorX<2>::d solution;
solution(0) = 1.;
solution(1) = 1.;
double val = -1.;
RtEiquadprog_status expected = RT_EIQUADPROG_OPTIMAL;
RtEiquadprog_status status = qp.solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x);
BOOST_CHECK_EQUAL(status, expected);
BOOST_CHECK_CLOSE(qp.getObjValue(), val, 1e-6);
BOOST_CHECK(x.isApprox(solution));
}
// min ||x||^2
// s.t.
// x[1] = 1 - x[0]
BOOST_AUTO_TEST_CASE(test_equality_constraints) {
RtEiquadprog<2, 1, 0> qp;
RtMatrixX<2, 2>::d Q;
Q.setZero();
Q(0, 0) = 1.0;
Q(1, 1) = 1.0;
RtVectorX<2>::d C;
C.setZero();
RtMatrixX<1, 2>::d Aeq;
Aeq(0, 0) = 1.;
Aeq(0, 1) = 1.;
RtVectorX<1>::d Beq;
Beq(0) = -1.;
RtMatrixX<0, 2>::d Aineq;
RtVectorX<0>::d Bineq;
RtVectorX<2>::d x;
RtVectorX<2>::d solution;
solution(0) = 0.5;
solution(1) = 0.5;
double val = 0.25;
RtEiquadprog_status expected = RT_EIQUADPROG_OPTIMAL;
RtEiquadprog_status status = qp.solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x);
BOOST_CHECK_EQUAL(status, expected);
BOOST_CHECK_CLOSE(qp.getObjValue(), val, 1e-6);
BOOST_CHECK(x.isApprox(solution));
}
BOOST_AUTO_TEST_SUITE_END()
#include <iostream>
#include <Eigen/Core>
#include <boost/test/unit_test.hpp>
#include "TestA.hpp"
#include "TestB.hpp"
BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
BOOST_AUTO_TEST_CASE(test_class_A_and_class_B) {
eiquadprog::tests::B aB;
BOOST_CHECK(aB.do_something());
}
BOOST_AUTO_TEST_SUITE_END()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment