diff --git a/include/jrl-qp/SolverOptions.h b/include/jrl-qp/SolverOptions.h index 59694d9..4dcd110 100644 --- a/include/jrl-qp/SolverOptions.h +++ b/include/jrl-qp/SolverOptions.h @@ -16,6 +16,10 @@ struct JRLQP_DLLAPI SolverOptions int maxIter_ = 500; double bigBnd_ = 1e100; bool warmStart_ = false; + /** If true, the input matrix G must contain the lower triangular matrix L + * such that G = L L^T. The upper part of the matrix is ignored. + */ + bool factorizedG_ = false; std::uint32_t logFlags_ = 0; std::ostream * logStream_ = &defaultStream_; @@ -76,6 +80,16 @@ struct JRLQP_DLLAPI SolverOptions return *this; } + bool factorizedG() const + { + return factorizedG_; + } + SolverOptions & factorizedG(bool fact) + { + factorizedG_ = fact; + return *this; + } + std::ostream & logStream() const { return *logStream_; diff --git a/src/GoldfarbIdnaniSolver.cpp b/src/GoldfarbIdnaniSolver.cpp index 20f74e8..c2dc8cd 100644 --- a/src/GoldfarbIdnaniSolver.cpp +++ b/src/GoldfarbIdnaniSolver.cpp @@ -55,7 +55,7 @@ TerminationStatus GoldfarbIdnaniSolver::solve(MatrixRef G, internal::InitTermination GoldfarbIdnaniSolver::init_() { - auto ret = Eigen::internal::llt_inplace::blocked(pb_.G); + auto ret = (!options_.factorizedG_) ? Eigen::internal::llt_inplace::blocked(pb_.G) : -1; auto L = pb_.G.template triangularView(); if(ret >= 0) return TerminationStatus::NON_POS_HESSIAN; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b33f08d..428a19a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,6 +57,7 @@ add_dependencies(BlockGISolverTest extra-multiik-archive) addUnitTest(BoxAndSingleConstraintSolverTest) addUnitTest(GoldfarbIdnaniSolverTest QPSReader.cpp) addUnitTest(InternalTest) +addUnitTest(OptionsTest) addUnitTest(RandomProblemsTest) addUnitTest(StructuredTest) addUnitTest(triBlockDiagLLTTest) diff --git a/tests/OptionsTest.cpp b/tests/OptionsTest.cpp new file mode 100644 index 0000000..202c4ed --- /dev/null +++ b/tests/OptionsTest.cpp @@ -0,0 +1,37 @@ +/* Copyright 2024 CNRS-AIST JRL, Inria */ + +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS +#include "doctest/doctest.h" + +#include +#include + +using namespace jrl::qp::test; + +TEST_CASE("Test FactorizedG") +{ + jrl::qp::GoldfarbIdnaniSolver solver(7, 11, false); + jrl::qp::SolverOptions options; + + for(int i = 0; i < 10; ++i) + { + auto pb = QPProblem(randomProblem(ProblemCharacteristics(7, 7, 3, 8))); + pb.C.transposeInPlace(); + + auto llt = pb.G.llt(); + Eigen::MatrixXd L = llt.matrixL(); + + options.factorizedG(true); + solver.options(options); + solver.solve(L, pb.a, pb.C, pb.l, pb.u, pb.xl, pb.xu); + Eigen::VectorXd x1 = solver.solution(); + + options.factorizedG(false); + solver.options(options); + solver.solve(pb.G, pb.a, pb.C, pb.l, pb.u, pb.xl, pb.xu); + Eigen::VectorXd x2 = solver.solution(); + + FAST_CHECK_UNARY(x1.isApprox(x2)); + } +} \ No newline at end of file