diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b563420a..867375bff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added * Allow use of installed cereal and jrl-cmakemodules via cmake * Add compatibility with jrl-cmakemodules workspace ([#339](https://github.com/Simple-Robotics/proxsuite/pull/339)) +* Specifically mention that timings are in microseconds ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) +* Fix cereal include directory in cmake ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) +* Extend doc with hint for conda installation from source ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) ## [0.6.6] - 2024-06-15 diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 02e94c2cc..252063b87 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -92,7 +92,8 @@ function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) endif(BUILD_WITH_OPENMP_SUPPORT) if(cereal_FOUND) - target_link_libraries(${target_name} SYSTEM PRIVATE cereal) + target_include_directories(${target_name} SYSTEM + PRIVATE ${CEREAL_INCLUDE_DIRS}) else() target_include_directories( ${target_name} SYSTEM diff --git a/bindings/python/src/expose-solve.hpp b/bindings/python/src/expose-solve.hpp index 8a0a2f091..038bccaec 100644 --- a/bindings/python/src/expose-solve.hpp +++ b/bindings/python/src/expose-solve.hpp @@ -82,7 +82,8 @@ solveDenseQp(pybind11::module_ m) true, "executes the default preconditioner for reducing ill " "conditioning and speeding up the solver."), - pybind11::arg_v("compute_timings", false, "compute solver's timings."), + pybind11::arg_v( + "compute_timings", false, "compute solver's timings in μs."), pybind11::arg_v("max_iter", nullopt, "maximum number of iteration."), pybind11::arg_v( "initial_guess", @@ -177,7 +178,8 @@ solveDenseQp(pybind11::module_ m) true, "executes the default preconditioner for reducing ill " "conditioning and speeding up the solver."), - pybind11::arg_v("compute_timings", false, "compute solver's timings."), + pybind11::arg_v( + "compute_timings", false, "compute solver's timings in μs."), pybind11::arg_v("max_iter", nullopt, "maximum number of iteration."), pybind11::arg_v( "initial_guess", @@ -255,7 +257,8 @@ solveSparseQp(pybind11::module_ m) true, "executes the default preconditioner for reducing ill " "conditioning and speeding up the solver."), - pybind11::arg_v("compute_timings", false, "compute solver's timings."), + pybind11::arg_v( + "compute_timings", false, "compute solver's timings in μs."), pybind11::arg_v("max_iter", nullopt, "maximum number of iteration."), pybind11::arg_v("initial_guess", proxsuite::proxqp::InitialGuessStatus:: diff --git a/doc/2-ProxQP_api.md b/doc/2-ProxQP_api.md index 592274d2e..fedebac47 100644 --- a/doc/2-ProxQP_api.md +++ b/doc/2-ProxQP_api.md @@ -388,7 +388,7 @@ In this table, you have the three columns from left to right: the name of the se | default_rho | 1.E-6 | Default rho parameter of result class (i.e., for each initial guess, except WARM_START_WITH_PREVIOUS_RESULT, after a new solve or update, the solver initializes rho to this value). | default_mu_eq | 1.E-3 | Default mu_eq parameter of result class (i.e., for each initial guess, except WARM_START_WITH_PREVIOUS_RESULT, after a new solve or update, the solver initializes mu_eq to this value). | default_mu_in | 1.E-1 | Default mu_in parameter of result class (i.e., for each initial guess, except WARM_START_WITH_PREVIOUS_RESULT, after a new solve or update, the solver initializes mu_in to this value). -| compute_timings | False | If set to true, timings will be computed by the solver (setup time, solving time, and run time = setup time + solving time). +| compute_timings | False | If set to true, timings in microseconds will be computed by the solver (setup time, solving time, and run time = setup time + solving time). | max_iter | 10.000 | Maximal number of authorized outer iterations. | max_iter_in | 1500 | Maximal number of authorized inner iterations. | initial_guess | EQUALITY_CONSTRAINED_INITIAL_GUESS | Sets the initial guess option for initilizing x, y and z. diff --git a/doc/3-ProxQP_solve.md b/doc/3-ProxQP_solve.md index 59371c87e..79223f605 100644 --- a/doc/3-ProxQP_solve.md +++ b/doc/3-ProxQP_solve.md @@ -113,7 +113,7 @@ Different options are available for the solve function. In the table below you h | rho | 1.E-6 | Proximal step size wrt primal variable. | VERBOSE | False | If set to true, the solver prints information at each loop. | compute_preconditioner | True | If set to true, the preconditioner will be derived. -| compute_timings | False | If set to true, timings will be computed by the solver (setup time, solving time, and run time = setup time + solving time). +| compute_timings | False | If set to true, timings in microseconds will be computed by the solver (setup time, solving time, and run time = setup time + solving time). | max_iter | 10.000 | Maximal number of authorized outer iterations. | initial_guess | EQUALITY_CONSTRAINED_INITIAL_GUESS | Sets the initial guess option for initilizing x, y and z. diff --git a/doc/5-installation.md b/doc/5-installation.md index 376f679c7..67dc810af 100644 --- a/doc/5-installation.md +++ b/doc/5-installation.md @@ -27,6 +27,8 @@ make make install ``` +Note: if you are building Proxsuite within a conda environment, consider passing `-DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX`. + 3. Build the Python interface You just need to ensure that Python3 is indeed present on your system and activate the cmake option `BUILD_PYTHON_INTERFACE=ON` by replacing: diff --git a/include/proxsuite/proxqp/dense/solver.hpp b/include/proxsuite/proxqp/dense/solver.hpp index 5710fe6db..0e544c3ac 100644 --- a/include/proxsuite/proxqp/dense/solver.hpp +++ b/include/proxsuite/proxqp/dense/solver.hpp @@ -1778,7 +1778,7 @@ qp_solve( // } if (qpsettings.compute_timings) { - qpresults.info.solve_time = qpwork.timer.elapsed().user; // in nanoseconds + qpresults.info.solve_time = qpwork.timer.elapsed().user; // in microseconds qpresults.info.run_time = qpresults.info.solve_time + qpresults.info.setup_time; } @@ -1786,46 +1786,46 @@ qp_solve( // if (qpsettings.verbose) { std::cout << "-------------------SOLVER STATISTICS-------------------" << std::endl; - std::cout << "outer iter: " << qpresults.info.iter_ext << std::endl; - std::cout << "total iter: " << qpresults.info.iter << std::endl; - std::cout << "mu updates: " << qpresults.info.mu_updates << std::endl; - std::cout << "rho updates: " << qpresults.info.rho_updates << std::endl; - std::cout << "objective: " << qpresults.info.objValue << std::endl; + std::cout << "outer iter: " << qpresults.info.iter_ext << std::endl; + std::cout << "total iter: " << qpresults.info.iter << std::endl; + std::cout << "mu updates: " << qpresults.info.mu_updates << std::endl; + std::cout << "rho updates: " << qpresults.info.rho_updates << std::endl; + std::cout << "objective: " << qpresults.info.objValue << std::endl; switch (qpresults.info.status) { case QPSolverOutput::PROXQP_SOLVED: { - std::cout << "status: " + std::cout << "status: " << "Solved" << std::endl; break; } case QPSolverOutput::PROXQP_MAX_ITER_REACHED: { - std::cout << "status: " + std::cout << "status: " << "Maximum number of iterations reached" << std::endl; break; } case QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE: { - std::cout << "status: " + std::cout << "status: " << "Primal infeasible" << std::endl; break; } case QPSolverOutput::PROXQP_DUAL_INFEASIBLE: { - std::cout << "status: " + std::cout << "status: " << "Dual infeasible" << std::endl; break; } case QPSolverOutput::PROXQP_SOLVED_CLOSEST_PRIMAL_FEASIBLE: { - std::cout << "status: " + std::cout << "status: " << "Solved closest primal feasible" << std::endl; break; } case QPSolverOutput::PROXQP_NOT_RUN: { - std::cout << "status: " + std::cout << "status: " << "Solver not run" << std::endl; break; } } if (qpsettings.compute_timings) - std::cout << "run time: " << qpresults.info.solve_time << std::endl; + std::cout << "run time [μs]: " << qpresults.info.solve_time << std::endl; std::cout << "--------------------------------------------------------" << std::endl; } diff --git a/include/proxsuite/proxqp/settings.hpp b/include/proxsuite/proxqp/settings.hpp index b3d7ce264..f455238b4 100644 --- a/include/proxsuite/proxqp/settings.hpp +++ b/include/proxsuite/proxqp/settings.hpp @@ -182,9 +182,9 @@ struct Settings * re-computed when calling the update method. * @param compute_preconditioner If set to true, the preconditioner will be * computed with the init method. - * @param compute_timings If set to true, timings will be computed by the - * solver (setup time, solving time, and run time = setup time + solving - * time). + * @param compute_timings If set to true, timings in microseconds will be + * computed by the solver (setup time, solving time, and run time = setup time + * + solving time). * @param check_duality_gap If set to true, duality gap will be calculated and * included in the stopping criterion. * @param eps_duality_gap_abs absolute duality-gap stopping criterion. diff --git a/include/proxsuite/proxqp/sparse/solver.hpp b/include/proxsuite/proxqp/sparse/solver.hpp index 609d2b84d..c2ecd56dd 100644 --- a/include/proxsuite/proxqp/sparse/solver.hpp +++ b/include/proxsuite/proxqp/sparse/solver.hpp @@ -1623,45 +1623,45 @@ qp_solve(Results& results, if (settings.verbose) { std::cout << "-------------------SOLVER STATISTICS-------------------" << std::endl; - std::cout << "outer iter: " << results.info.iter_ext << std::endl; - std::cout << "total iter: " << results.info.iter << std::endl; - std::cout << "mu updates: " << results.info.mu_updates << std::endl; - std::cout << "rho updates: " << results.info.rho_updates << std::endl; - std::cout << "objective: " << results.info.objValue << std::endl; + std::cout << "outer iter: " << results.info.iter_ext << std::endl; + std::cout << "total iter: " << results.info.iter << std::endl; + std::cout << "mu updates: " << results.info.mu_updates << std::endl; + std::cout << "rho updates: " << results.info.rho_updates << std::endl; + std::cout << "objective: " << results.info.objValue << std::endl; switch (results.info.status) { case QPSolverOutput::PROXQP_SOLVED: { - std::cout << "status: " + std::cout << "status: " << "Solved" << std::endl; break; } case QPSolverOutput::PROXQP_MAX_ITER_REACHED: { - std::cout << "status: " + std::cout << "status: " << "Maximum number of iterations reached" << std::endl; break; } case QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE: { - std::cout << "status: " + std::cout << "status: " << "Primal infeasible" << std::endl; break; } case QPSolverOutput::PROXQP_DUAL_INFEASIBLE: { - std::cout << "status: " + std::cout << "status: " << "Dual infeasible" << std::endl; break; } case QPSolverOutput::PROXQP_SOLVED_CLOSEST_PRIMAL_FEASIBLE: { - std::cout << "status: " + std::cout << "status: " << "Solved closest primal feasible" << std::endl; break; } case QPSolverOutput::PROXQP_NOT_RUN: { - std::cout << "status: " + std::cout << "status: " << "Solver not run" << std::endl; break; } } if (settings.compute_timings) - std::cout << "run time: " << results.info.solve_time << std::endl; + std::cout << "run time [μs]: " << results.info.solve_time << std::endl; std::cout << "--------------------------------------------------------" << std::endl; }