From 2bcadd4993a9940c545136faa71bf1e97a972735 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Tue, 18 Jun 2024 18:09:56 +0200 Subject: [PATCH 001/109] CMake: allow use of installed jrl-cmakemodules --- CMakeLists.txt | 57 +++++++++++++++++++++++----------- bindings/python/CMakeLists.txt | 4 +-- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d22c3ed7..a8b7bb54e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,37 @@ set(PROJECT_CUSTOM_HEADER_EXTENSION "hpp") set(PROJECT_USE_CMAKE_EXPORT TRUE) set(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE) +# Check if the submodule cmake have been initialized +set(JRL_CMAKE_MODULES "${CMAKE_CURRENT_LIST_DIR}/cmake-module") +if(EXISTS "${JRL_CMAKE_MODULES}/base.cmake") + message(STATUS "JRL cmakemodules found in 'cmake/' git submodule") +else() + find_package(jrl-cmakemodules QUIET CONFIG) + if(jrl-cmakemodules_FOUND) + get_property( + JRL_CMAKE_MODULES + TARGET jrl-cmakemodules::jrl-cmakemodules + PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + message(STATUS "JRL cmakemodules found on system at ${JRL_CMAKE_MODULES}") + elseif(${CMAKE_VERSION} VERSION_LESS "3.14.0") + message( + FATAL_ERROR + "\nCan't find jrl-cmakemodules. Please either:\n" + " - use git submodule: 'git submodule update --init'\n" + " - or install https://github.com/jrl-umi3218/jrl-cmakemodules\n" + " - or upgrade your CMake version to >= 3.14 to allow automatic fetching\n" + ) + else() + message(STATUS "JRL cmakemodules not found. Let's fetch it.") + include(FetchContent) + FetchContent_Declare( + "jrl-cmakemodules" + GIT_REPOSITORY "https://github.com/jrl-umi3218/jrl-cmakemodules.git") + FetchContent_MakeAvailable("jrl-cmakemodules") + FetchContent_GetProperties("jrl-cmakemodules" SOURCE_DIR JRL_CMAKE_MODULES) + endif() +endif() + # Disable -Werror on Unix for now. set(CXX_DISABLE_WERROR True) set(CMAKE_VERBOSE_MAKEFILE True) @@ -24,14 +55,6 @@ if(POLICY CMP0068) cmake_policy(SET CMP0068 NEW) endif(POLICY CMP0068) -# Check if the submodule cmake have been initialized -if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/cmake-module/base.cmake") - message( - FATAL_ERROR - "\nPlease run the following command first:\ngit submodule update --init\n" - ) -endif() - # ---------------------------------------------------- # --- OPTIONS --------------------------------------- # Need to be set before including base.cmake @@ -42,19 +65,18 @@ option(INSTALL_DOCUMENTATION "Install the documentation" OFF) set(DOXYGEN_USE_MATHJAX YES) set(DOXYGEN_USE_TEMPLATE_CSS YES) -include(${CMAKE_CURRENT_LIST_DIR}/cmake-module/base.cmake) +include(${JRL_CMAKE_MODULES}/base.cmake) compute_project_args(PROJECT_ARGS LANGUAGES CXX) project(${PROJECT_NAME} ${PROJECT_ARGS}) -include(${CMAKE_CURRENT_LIST_DIR}/cmake-module/ide.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/cmake-module/apple.cmake) +include(${JRL_CMAKE_MODULES}/ide.cmake) +include(${JRL_CMAKE_MODULES}/apple.cmake) if(NOT ${CMAKE_VERSION} VERSION_GREATER "3.26.0" OR WIN32) - set(CMAKE_MODULE_PATH - ${CMAKE_CURRENT_LIST_DIR}/cmake-module/find-external/OpenMP - ${CMAKE_MODULE_PATH}) + set(CMAKE_MODULE_PATH ${JRL_CMAKE_MODULES}/find-external/OpenMP + ${CMAKE_MODULE_PATH}) endif() -include(${CMAKE_CURRENT_LIST_DIR}/cmake-module/julia.cmake) +include(${JRL_CMAKE_MODULES}/julia.cmake) include(CMakeDependentOption) # If needed, set CMake policy for APPLE systems @@ -85,9 +107,8 @@ if(BUILD_WITH_OPENMP_SUPPORT) separate_arguments(OpenMP_CXX_FLAGS UNIX_COMMAND "${OpenMP_CXX_FLAGS}") endif(BUILD_WITH_OPENMP_SUPPORT) -set(CMAKE_MODULE_PATH - "${CMAKE_CURRENT_LIST_DIR}/cmake-module/find-external/Julia" - ${CMAKE_MODULE_PATH}) +set(CMAKE_MODULE_PATH "${JRL_CMAKE_MODULES}/find-external/Julia" + ${CMAKE_MODULE_PATH}) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake-external" ${CMAKE_MODULE_PATH}) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 4e3d927fd..da6d4d892 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -2,8 +2,8 @@ if(UNIX) set(PYTHON_COMPONENTS Development.Module) endif() -include(../../cmake-module/python.cmake) -include(../../cmake-module/python-helpers.cmake) +include(${JRL_CMAKE_MODULES}/python.cmake) +include(${JRL_CMAKE_MODULES}/python-helpers.cmake) findpython(REQUIRED Development.Module) From 878337c6284c9fd73b19f1f80d5fa802def8cdc6 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Tue, 18 Jun 2024 18:21:24 +0200 Subject: [PATCH 002/109] CMake: allow use of installed cereal --- CMakeLists.txt | 17 +- bindings/python/CMakeLists.txt | 9 +- doc/rankupdate/rankupdate.aux | 9 - doc/rankupdate/rankupdate.fdb_latexmk | 68 -------- doc/rankupdate/rankupdate.fls | 239 -------------------------- test/CMakeLists.txt | 10 +- 6 files changed, 24 insertions(+), 328 deletions(-) delete mode 100644 doc/rankupdate/rankupdate.aux delete mode 100644 doc/rankupdate/rankupdate.fdb_latexmk delete mode 100644 doc/rankupdate/rankupdate.fls diff --git a/CMakeLists.txt b/CMakeLists.txt index a8b7bb54e..3e1f47aac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,13 +184,16 @@ endif() if(BUILD_TESTING OR BUILD_PYTHON_INTERFACE) # Download cereal for pything bindings and unittests - set(cereal_dir ${PROJECT_SOURCE_DIR}/external/cereal) - set(cereal ${cereal_dir}/README.md) - find_package(Git REQUIRED) - if(NOT EXISTS ${cereal}) - execute_process( - COMMAND ${GIT_EXECUTABLE} submodule update --init ${cereal_dir} - WORKING_DIRECTORY ${cereal_dir} COMMAND_ERROR_IS_FATAL ANY) + find_package(cereal QUIET CONFIG) + if(NOT cereal_FOUND) + set(cereal_dir ${PROJECT_SOURCE_DIR}/external/cereal) + set(cereal ${cereal_dir}/README.md) + find_package(Git REQUIRED) + if(NOT EXISTS ${cereal}) + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init ${cereal_dir} + WORKING_DIRECTORY ${cereal_dir} COMMAND_ERROR_IS_FATAL ANY) + endif() endif() endif() diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index da6d4d892..c27344875 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -91,8 +91,13 @@ function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) list_filter("${PYWRAP_HEADERS}" "expose-parallel" PYWRAP_HEADERS) endif(BUILD_WITH_OPENMP_SUPPORT) - target_include_directories( - ${target_name} SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/external/cereal/include) + if(cereal_FOUND) + target_link_libraries(${target_name} SYSTEM PRIVATE cereal) + else() + target_include_directories( + ${target_name} SYSTEM + PRIVATE ${PROJECT_SOURCE_DIR}/external/cereal/include) + endif() set_target_properties( ${target_name} PROPERTIES OUTPUT_NAME ${target_name} diff --git a/doc/rankupdate/rankupdate.aux b/doc/rankupdate/rankupdate.aux deleted file mode 100644 index 64a75506e..000000000 --- a/doc/rankupdate/rankupdate.aux +++ /dev/null @@ -1,9 +0,0 @@ -\relax -\newlabel{eq:rank_update_definition}{{1}{1}} -\@writefile{toc}{\contentsline {section}{\numberline {1}Rank-one update:}{1}{}\protected@file@percent } -\newlabel{sec:Rank-one_update}{{1}{1}} -\newlabel{eq:unfold}{{3}{1}} -\newlabel{eq:lincomb}{{6}{2}} -\@writefile{toc}{\contentsline {section}{\numberline {2}Rank-$m$ update}{2}{}\protected@file@percent } -\newlabel{sec:Rank-$m$_update}{{2}{2}} -\gdef \@abspage@last{3} diff --git a/doc/rankupdate/rankupdate.fdb_latexmk b/doc/rankupdate/rankupdate.fdb_latexmk deleted file mode 100644 index c653edf04..000000000 --- a/doc/rankupdate/rankupdate.fdb_latexmk +++ /dev/null @@ -1,68 +0,0 @@ -# Fdb version 3 -["pdflatex"] 1641376399 "rankupdate.tex" "rankupdate.pdf" "rankupdate" 1641376399 - "/etc/texmf/web2c/texmf.cnf" 1640843101 475 c0e671620eb5563b2130f56340a5fde8 "" - "/usr/share/texlive/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/jknappen/ec/tcrm1000.tfm" 1136768653 1536 e07581a4bb3136ece9eeb4c3ffab8233 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm" 1246382020 988 bdf658c3bfc2d96d3c8b02cfc1c94c20 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm" 1246382020 916 f87d7c45f9c908e672703b83b72241a3 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam5.tfm" 1246382020 924 9904cf1d39e9767e7a3622f2a125a565 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm" 1246382020 928 2dc8d444221b7a635bb58038579b861a "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm" 1246382020 908 2921f8a10601f252058503cc6570e581 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm" 1246382020 940 75ac932a52f80982a9f8ea75d03a34cf "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm" 1246382020 940 228d6584342e91276bf566bcf9716b83 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm" 1136768653 1324 c910af8c371558dc20f2d7822f66fe64 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmex10.tfm" 1136768653 992 662f679a0b3d2d53c1b94050fdaa3f50 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm" 1136768653 1524 4414a8315f39513458b80dfc63bff03a "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi6.tfm" 1136768653 1512 f21f83efb36853c0b70002322c1ab3ad "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi8.tfm" 1136768653 1520 eccf95517727cb11801f4f1aee3a21b4 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr12.tfm" 1136768653 1288 655e228510b4c2a1abe905c368440826 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr17.tfm" 1136768653 1292 296a67155bdbfc32aa9c636f21e91433 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr6.tfm" 1136768653 1300 b62933e007d01cfd073f79b963c01526 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr8.tfm" 1136768653 1292 21c1c5bfeaebccffdb478fd231a0997d "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm" 1136768653 1124 6c73e740cf17375f03eec0ee63599741 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm" 1136768653 1116 933a60c408fc0a863a92debe84b2d294 "" - "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy8.tfm" 1136768653 1120 8b7d695260f3cff42e636090a8002094 "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb" 1248133631 32080 340ef9bf63678554ee606688e7b5339d "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb" 1248133631 30251 6afa5cb1d0204815a708a080681d4674 "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb" 1248133631 36299 5f9df58c2139e7edcf37c8fca4bd384d "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi12.pfb" 1248133631 36741 fa121aac0049305630cf160b86157ee4 "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb" 1248133631 36281 c355509802a035cadc5f15869451dcee "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb" 1248133631 35752 024fb6c41858982481f6968b5fc26508 "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr17.pfb" 1248133631 32362 179c33bbf43f19adbb3825bb4e36e57a "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr5.pfb" 1248133631 31809 8670ca339bf94e56da1fc21c80635e2a "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb" 1248133631 32762 224316ccc9ad3ca0423a14971cfa7fc1 "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb" 1248133631 32569 5e5ddc8df908dea60932f3c484a54c0d "" - "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.pfb" 1248133631 32716 08e384dc442464e7285e891af9f45947 "" - "/usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty" 1591045760 12594 0d51ac3a545aaaa555021326ff22a6cc "" - "/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty" 1359763108 5949 3f3fd50a8cc94c3d4cbf4fc66cd3df1c "" - "/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty" 1359763108 13829 94730e64147574077f8ecfea9bb69af4 "" - "/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd" 1359763108 961 6518c6525a34feb5e8250ffa91731cff "" - "/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd" 1359763108 961 d02606146ba5601b5645f987c92e6193 "" - "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty" 1523134290 2211 ca7ce284ab93c8eecdc6029dc5ccbd73 "" - "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty" 1523134290 4161 7f6eb9092061a11f87d08ed13515b48d "" - "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty" 1601675358 87353 2c21ff5f2e32e1bf714e600924d810db "" - "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty" 1523134290 4116 32e6abd27229755a83a8b7f18e583890 "" - "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty" 1523134290 2432 8ff93b1137020e8f21930562a874ae66 "" - "/usr/share/texlive/texmf-dist/tex/latex/base/article.cls" 1601675358 20145 aad8c3dd3bc36e260347b84002182bc2 "" - "/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo" 1601675358 8449 a72d5d4e612221b46000c3d71724e0ef "" - "/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty" 1580683321 2590 e3b24ff953e5b58d924f163d25380312 "" - "/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def" 1611959857 27097 58278863d97b10ab86e334b8da33df7a "" - "/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype-pdftex.def" 1607465040 49121 4911f21dad8c1eb79a63aebba9643ece "" - "/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg" 1607465040 24929 baec9b115829e21e1ba4dfcaf6260d24 "" - "/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty" 1607465040 71807 0724aff58b422fcce3421aebcd5fc631 "" - "/usr/share/texlive/texmf-dist/tex/latex/microtype/mt-cmr.cfg" 1607465040 22870 85ef48580eb35bcb3beca9130657ae3b "" - "/usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msa.cfg" 1607465040 5893 a60144fa9c61ba60cd8c1fe66baa02b3 "" - "/usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msb.cfg" 1607465040 5558 997b28f7d84cccc5fd6d2e3162e09e1e "" - "/usr/share/texlive/texmf-dist/web2c/texmf.cnf" 1613593815 38841 799d1dd9682a55ce442e10c99777ecc1 "" - "/usr/share/texmf/fonts/enc/dvips/cm-super/cm-super-ts1.enc" 1565080000 2900 1537cc8184ad1792082cd229ecc269f4 "" - "/usr/share/texmf/fonts/type1/public/cm-super/sfrm1000.pfb" 1565080000 138258 6525c253f16cededa14c7fd0da7f67b2 "" - "/usr/share/texmf/web2c/texmf.cnf" 1613593815 38841 799d1dd9682a55ce442e10c99777ecc1 "" - "/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map" 1640843127 5160710 ecf427ae8fa19139d8691f526e47bb9b "" - "/var/lib/texmf/web2c/pdftex/pdflatex.fmt" 1640843148 2571203 eb8afda0270e9970b44064aadd8ed7f2 "" - "rankupdate.aux" 1641376399 421 e4ea47dcf05024e543bb4c3c57eb39e3 "pdflatex" - "rankupdate.tex" 1641376398 4930 d4fb108de9084263a9e28c65147a235d "" - (generated) - "rankupdate.aux" - "rankupdate.log" - "rankupdate.pdf" diff --git a/doc/rankupdate/rankupdate.fls b/doc/rankupdate/rankupdate.fls deleted file mode 100644 index 51eee1ce8..000000000 --- a/doc/rankupdate/rankupdate.fls +++ /dev/null @@ -1,239 +0,0 @@ -PWD /home/sarah/projects/inria_ldlt/rankupdate -INPUT /etc/texmf/web2c/texmf.cnf -INPUT /usr/share/texmf/web2c/texmf.cnf -INPUT /usr/share/texlive/texmf-dist/web2c/texmf.cnf -INPUT /var/lib/texmf/web2c/pdftex/pdflatex.fmt -INPUT rankupdate.tex -OUTPUT rankupdate.log -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/article.cls -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/size10.clo -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/size10.clo -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/size10.clo -INPUT /usr/share/texlive/texmf-dist/tex/latex/base/size10.clo -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/amscls/amsthm.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def -INPUT ./rankupdate.aux -INPUT rankupdate.aux -INPUT rankupdate.aux -OUTPUT rankupdate.aux -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-cmr.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-cmr.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-cmr.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-cmr.cfg -INPUT /usr/share/texlive/texmf-dist/fonts/map/fontname/texfonts.map -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr17.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr12.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmex10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmex10.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msa.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msa.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msa.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msa.cfg -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd -INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msb.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msb.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msb.cfg -INPUT /usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msb.cfg -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr8.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr6.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi8.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi6.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy8.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam5.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr12.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm -OUTPUT rankupdate.pdf -INPUT /var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmex10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/jknappen/ec/tcrm1000.tfm -INPUT rankupdate.aux -INPUT /usr/share/texmf/fonts/enc/dvips/cm-super/cm-super-ts1.enc -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi12.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr17.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr5.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb -INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.pfb -INPUT /usr/share/texmf/fonts/type1/public/cm-super/sfrm1000.pfb diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 052b38080..a86bed82b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -62,9 +62,13 @@ add_test_cflags( test-cpp-serialization "-DTEST_SERIALIZATION_FOLDER=\\\\\"${CMAKE_CURRENT_BINARY_DIR}/serialization-data\\\\\"" ) -target_include_directories( - test-cpp-serialization SYSTEM - PRIVATE ${PROJECT_SOURCE_DIR}/external/cereal/include) +if(cereal_FOUND) + target_link_libraries(test-cpp-serialization PRIVATE cereal) +else() + target_include_directories( + test-cpp-serialization SYSTEM + PRIVATE ${PROJECT_SOURCE_DIR}/external/cereal/include) +endif() if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT MSVC) proxsuite_test(dense_maros_meszaros src/dense_maros_meszaros.cpp) From 6c98a74ed36d6addf3416fc00463b578f6883a20 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Wed, 19 Jun 2024 14:56:15 +0200 Subject: [PATCH 003/109] python: fix compatibility with Numpy 2 --- test/src/dense_qp_solve.py | 2 +- test/src/dense_qp_wrapper.py | 2 +- test/src/sparse_qp_solve.py | 2 +- test/src/sparse_qp_wrapper.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/src/dense_qp_solve.py b/test/src/dense_qp_solve.py index d8fe30736..6475da821 100644 --- a/test/src/dense_qp_solve.py +++ b/test/src/dense_qp_solve.py @@ -315,7 +315,7 @@ def test_sparse_problem_with_exact_solution_known(self): b = None C = spa.csc_matrix(spa.eye(n)).toarray() l = 2.0 * np.ones((n,)) - u = np.full(l.shape, +np.infty) + u = np.full(l.shape, +np.inf) results = proxsuite.proxqp.dense.solve(H, g, A, b, C, l, u) x_theoretically_optimal = np.array([2.0] * 149 + [3.0]) diff --git a/test/src/dense_qp_wrapper.py b/test/src/dense_qp_wrapper.py index 429f5fb80..0bda2f085 100644 --- a/test/src/dense_qp_wrapper.py +++ b/test/src/dense_qp_wrapper.py @@ -3930,7 +3930,7 @@ def test_sparse_problem_with_exact_solution_known(self): b = None C = spa.csc_matrix(spa.eye(n)).toarray() l = 2.0 * np.ones((n,)) - u = np.full(l.shape, +np.infty) + u = np.full(l.shape, +np.inf) qp = proxsuite.proxqp.dense.QP(n, 0, n) qp.init(H, g, A, b, C, l, u) diff --git a/test/src/sparse_qp_solve.py b/test/src/sparse_qp_solve.py index a8949ec1c..f882b50e3 100644 --- a/test/src/sparse_qp_solve.py +++ b/test/src/sparse_qp_solve.py @@ -347,7 +347,7 @@ def test_sparse_problem_with_exact_solution_known(self): b = None C = spa.csc_matrix(spa.eye(n)) l = 2.0 * np.ones((n,)) - u = np.full(l.shape, +np.infty) + u = np.full(l.shape, +np.inf) results = proxsuite.proxqp.sparse.solve(H, g, A, b, C, l, u) x_theoretically_optimal = np.array([2.0] * 149 + [3.0]) diff --git a/test/src/sparse_qp_wrapper.py b/test/src/sparse_qp_wrapper.py index 5b702a36f..d9e9eae8c 100644 --- a/test/src/sparse_qp_wrapper.py +++ b/test/src/sparse_qp_wrapper.py @@ -4523,7 +4523,7 @@ def test_sparse_problem_with_exact_solution_known(self): b = None C = spa.csc_matrix(spa.eye(n)) l = 2.0 * np.ones((n,)) - u = np.full(l.shape, +np.infty) + u = np.full(l.shape, +np.inf) qp = proxsuite.proxqp.sparse.QP(n, 0, n) qp.init(H, g, A, b, C, l, u) From 0d3a27d624e6fd55608315a800c5d4668d64ef57 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Wed, 19 Jun 2024 15:03:05 +0200 Subject: [PATCH 004/109] changelog: sync --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27925e586..3fcef102b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Added +* Allow use of installed cereal and jrl-cmakemodules via cmake + ## [0.6.6] - 2024-06-15 ### Fixed From f8f4c15c4ee2eaa4a8131fcb90f6778713f89b89 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 23:09:51 +0000 Subject: [PATCH 005/109] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-clang-format: v18.1.6 → v18.1.7](https://github.com/pre-commit/mirrors-clang-format/compare/v18.1.6...v18.1.7) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f1e0ff0df..80916a3da 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ ci: autoupdate_branch: 'devel' repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v18.1.6 + rev: v18.1.7 hooks: - id: clang-format args: ['--style={BasedOnStyle: Mozilla, SortIncludes: false}'] From 02cdafd18b3a245ab3352f22b66d2e2c34303f4e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 01:22:19 +0000 Subject: [PATCH 006/109] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-clang-format: v18.1.7 → v18.1.8](https://github.com/pre-commit/mirrors-clang-format/compare/v18.1.7...v18.1.8) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 80916a3da..ecf6c8a21 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ ci: autoupdate_branch: 'devel' repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v18.1.7 + rev: v18.1.8 hooks: - id: clang-format args: ['--style={BasedOnStyle: Mozilla, SortIncludes: false}'] From 878713040968c491f8cbcf370aa216b62d1936e7 Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Tue, 9 Jul 2024 15:25:10 +0200 Subject: [PATCH 007/109] pre-commit: Don't autofix PR and update quarterly --- .pre-commit-config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ecf6c8a21..7cec081c7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,7 @@ ci: autoupdate_branch: 'devel' + autofix_prs: false + autoupdate_schedule: quarterly repos: - repo: https://github.com/pre-commit/mirrors-clang-format rev: v18.1.8 From 0953d3079799f2be4e3bbe9ff4b3a9ad4ae67beb Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Mon, 15 Jul 2024 17:08:18 +0200 Subject: [PATCH 008/109] cmake: Apply change to be compatible with workspace --- CMakeLists.txt | 3 +++ benchmark/CMakeLists.txt | 4 ++-- bindings/python/CMakeLists.txt | 32 ++++++++++++++++---------------- doc/Doxyfile.extra.in | 6 +++--- examples/cpp/CMakeLists.txt | 8 ++++---- examples/julia/CMakeLists.txt | 5 +++-- examples/python/CMakeLists.txt | 6 +++--- test/CMakeLists.txt | 32 +++++++++++++++++--------------- 8 files changed, 51 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e1f47aac..b9ab33e70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ set(PROJECT_URL "http://github.com/Simple-Robotics/proxsuite") set(PROJECT_CUSTOM_HEADER_EXTENSION "hpp") set(PROJECT_USE_CMAKE_EXPORT TRUE) set(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE) +set(PROJECT_AUTO_RUN_FINALIZE FALSE) # Check if the submodule cmake have been initialized set(JRL_CMAKE_MODULES "${CMAKE_CURRENT_LIST_DIR}/cmake-module") @@ -241,3 +242,5 @@ if(BUILD_PYTHON_INTERFACE) FILES ${CMAKE_CURRENT_BINARY_DIR}/share/${PROJECT_NAME}/hook/python_path.dsv DESTINATION share/${PROJECT_NAME}/hook) endif(BUILD_PYTHON_INTERFACE) + +setup_project_finalize() diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 0c4f00a43..6f6ea47ef 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -1,4 +1,4 @@ -add_custom_target(bench) +add_custom_target(${PROJECT_NAME}_bench) macro(proxsuite_benchmark bench_name) if(BUILD_BENCHMARK) @@ -12,7 +12,7 @@ macro(proxsuite_benchmark bench_name) else() target_link_libraries(${bench_name} PUBLIC proxsuite) endif() - add_dependencies(bench ${bench_name}) + add_dependencies(${PROJECT_NAME}_bench ${bench_name}) endmacro(proxsuite_benchmark) proxsuite_benchmark(timings-lp) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index c27344875..02e94c2cc 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -18,7 +18,7 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11) add_subdirectory(external/pybind11 ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11) -add_custom_target(python) +add_custom_target(${PROJECT_NAME}_python) # Collect files file(GLOB_RECURSE PYWRAP_HEADERS ${CMAKE_CURRENT_LIST_DIR}/src/*.hpp) @@ -27,7 +27,7 @@ file(GLOB_RECURSE PYWRAP_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp) # Add simd feature detectors for current intel CPU if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)") python3_add_library(instructionset MODULE helpers/instruction-set.cpp) - add_dependencies(python instructionset) + add_dependencies(${PROJECT_NAME}_python instructionset) target_link_libraries(instructionset PRIVATE proxsuite pybind11::module) set_target_properties( instructionset @@ -35,18 +35,18 @@ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)") PREFIX "" SUFFIX ${PYTHON_EXT_SUFFIX} LIBRARY_OUTPUT_DIRECTORY - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" LIBRARY_OUTPUT_DIRECTORY_RELEASE - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" LIBRARY_OUTPUT_DIRECTORY_DEBUG - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" # On Windows, shared library are treat as binary RUNTIME_OUTPUT_DIRECTORY - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" RUNTIME_OUTPUT_DIRECTORY_RELEASE - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" RUNTIME_OUTPUT_DIRECTORY_DEBUG - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}") + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}") if(UNIX AND NOT APPLE) set_target_properties(instructionset PROPERTIES INSTALL_RPATH "\$ORIGIN/../../..") @@ -70,7 +70,7 @@ endfunction(list_filter) function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) python3_add_library(${target_name} MODULE ${PYWRAP_SOURCES} ${PYWRAP_HEADERS}) - add_dependencies(python ${target_name}) + add_dependencies(${PROJECT_NAME}_python ${target_name}) target_link_libraries(${target_name} PUBLIC ${dependencies} pybind11::module) target_compile_options(${target_name} PRIVATE ${COMPILE_OPTIONS}) @@ -104,18 +104,18 @@ function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) PREFIX "" SUFFIX ${PYTHON_EXT_SUFFIX} LIBRARY_OUTPUT_DIRECTORY - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" LIBRARY_OUTPUT_DIRECTORY_RELEASE - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" LIBRARY_OUTPUT_DIRECTORY_DEBUG - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" # On Windows, shared library are treat as binary RUNTIME_OUTPUT_DIRECTORY - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" RUNTIME_OUTPUT_DIRECTORY_RELEASE - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}" + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" RUNTIME_OUTPUT_DIRECTORY_DEBUG - "${CMAKE_BINARY_DIR}/bindings/python/${PROJECT_NAME}") + "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}") if(UNIX AND NOT APPLE) set_target_properties(${target_name} PROPERTIES INSTALL_RPATH @@ -195,7 +195,7 @@ else() endif() python_build_get_target(compile_pyc) -add_dependencies(python ${compile_pyc}) +add_dependencies(${PROJECT_NAME}_python ${compile_pyc}) set(PYTHON_FILES torch/__init__.py torch/qplayer.py torch/utils.py) diff --git a/doc/Doxyfile.extra.in b/doc/Doxyfile.extra.in index 13eef9ae3..db68df82d 100644 --- a/doc/Doxyfile.extra.in +++ b/doc/Doxyfile.extra.in @@ -1,5 +1,5 @@ -INPUT = @CMAKE_SOURCE_DIR@/doc \ - @CMAKE_SOURCE_DIR@/include \ +INPUT = @PROJECT_SOURCE_DIR@/doc \ + @PROJECT_SOURCE_DIR@/include \ RECURSIVE = YES @@ -54,7 +54,7 @@ SOURCE_BROWSER = YES ALPHABETICAL_INDEX = YES -USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/doc/1-Overview.md +USE_MDFILE_AS_MAINPAGE = @PROJECT_SOURCE_DIR@/doc/1-Overview.md BUILTIN_STL_SUPPORT = YES HAVE_DOT = YES diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index d26c446af..fc055fc2e 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -2,19 +2,19 @@ # Copyright (c) 2022 INRIA # -add_custom_target(example-cpp) +add_custom_target(${PROJECT_NAME}-example-cpp) function(ADD_PROXSUITE_CPP_EXAMPLE EXAMPLE) get_filename_component(EXAMPLE_NAME ${EXAMPLE} NAME_WE) - set(EXAMPLE_TARGET "example-cpp-${EXAMPLE_NAME}") + set(EXAMPLE_TARGET "${PROJECT_NAME}-example-cpp-${EXAMPLE_NAME}") add_unit_test(${EXAMPLE_TARGET} "${EXAMPLE}") target_link_libraries(${EXAMPLE_TARGET} PRIVATE proxsuite-test-util) - add_dependencies(example-cpp ${EXAMPLE_TARGET}) + add_dependencies(${PROJECT_NAME}-example-cpp ${EXAMPLE_TARGET}) endfunction() file(GLOB_RECURSE ${PROJECT_NAME}_CPP_EXAMPLES *.cpp) foreach(EXAMPLE ${${PROJECT_NAME}_CPP_EXAMPLES}) add_proxsuite_cpp_example(${EXAMPLE}) -endforeach(EXAMPLE ${${PROJECT_NAME}_CPP_EXAMPLES}) +endforeach() diff --git a/examples/julia/CMakeLists.txt b/examples/julia/CMakeLists.txt index dd654f27a..e7022ade0 100644 --- a/examples/julia/CMakeLists.txt +++ b/examples/julia/CMakeLists.txt @@ -3,5 +3,6 @@ file(GLOB_RECURSE ${PROJECT_NAME}_JULIA_EXAMPLES *.jl) foreach(EXAMPLE ${${PROJECT_NAME}_JULIA_EXAMPLES}) string(REGEX REPLACE "${PROJECT_SOURCE_DIR}/examples/julia/" "" EXAMPLE ${EXAMPLE}) - add_julia_unit_test("example-jl-${EXAMPLE}" "examples/julia/${EXAMPLE}") -endforeach(EXAMPLE ${${PROJECT_NAME}_JULIA_EXAMPLES}) + add_julia_unit_test("${PROJECT_NAME}-example-jl-${EXAMPLE}" + "examples/julia/${EXAMPLE}") +endforeach() diff --git a/examples/python/CMakeLists.txt b/examples/python/CMakeLists.txt index 16e4e3bd1..fb26dcb3c 100644 --- a/examples/python/CMakeLists.txt +++ b/examples/python/CMakeLists.txt @@ -3,6 +3,6 @@ file(GLOB_RECURSE ${PROJECT_NAME}_PYTHON_EXAMPLES *.py) foreach(EXAMPLE_FILE ${${PROJECT_NAME}_PYTHON_EXAMPLES}) get_filename_component(EXAMPLE_NAME ${EXAMPLE_FILE} NAME_WE) string(REGEX REPLACE "${PROJECT_SOURCE_DIR}" "" EXAMPLE_FILE ${EXAMPLE_FILE}) - add_python_unit_test("example-py-${EXAMPLE_NAME}" "${EXAMPLE_FILE}" - "bindings/python") -endforeach(EXAMPLE_FILE ${${PROJECT_NAME}_PYTHON_EXAMPLES}) + add_python_unit_test("${PROJECT_NAME}-example-py-${EXAMPLE_NAME}" + "${EXAMPLE_FILE}" "bindings/python") +endforeach() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a86bed82b..2bdc74162 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,8 +1,8 @@ include(../cmake-external/doctest.cmake) find_package(Matio REQUIRED) -add_library(doctest STATIC doctest/doctest.cpp) -target_include_directories(doctest PUBLIC ./doctest) +add_library(${PROJECT_NAME}-doctest STATIC doctest/doctest.cpp) +target_include_directories(${PROJECT_NAME}-doctest PUBLIC ./doctest) add_library(cnpy OBJECT src/cnpy.cpp) target_link_libraries(cnpy Eigen3::Eigen) target_include_directories(cnpy PUBLIC ./include) @@ -20,13 +20,14 @@ else() endif() macro(proxsuite_test name path) - add_executable(test-cpp-${name} ${path}) - doctest_discover_tests(test-cpp-${name}) - target_link_libraries(test-cpp-${name} PUBLIC proxsuite doctest - proxsuite-test-util) - target_compile_definitions(test-cpp-${name} + set(target_name ${PROJECT_NAME}-test-cpp-${name}) + add_executable(${target_name} ${path}) + # doctest_discover_tests(${target_name}) + target_link_libraries(${target_name} PUBLIC proxsuite ${PROJECT_NAME}-doctest + proxsuite-test-util) + target_compile_definitions(${target_name} PRIVATE PROBLEM_PATH="${CMAKE_CURRENT_SOURCE_DIR}") - add_dependencies(build_tests test-cpp-${name}) + add_dependencies(build_tests ${target_name}) endmacro() proxsuite_test(dense_ruiz_equilibration src/dense_ruiz_equilibration.cpp) @@ -45,7 +46,8 @@ proxsuite_test(cvxpy src/cvxpy.cpp) if(BUILD_WITH_OPENMP_SUPPORT) proxsuite_test(parallel src/parallel_qp_solve.cpp) - target_link_libraries(test-cpp-parallel PRIVATE OpenMP::OpenMP_CXX) + target_link_libraries(${PROJECT_NAME}-test-cpp-parallel + PRIVATE OpenMP::OpenMP_CXX) endif() # Test serialization @@ -54,19 +56,19 @@ macro(ADD_TEST_CFLAGS target flag) TARGET ${target} APPEND_STRING PROPERTY COMPILE_FLAGS " ${flag}") -endmacro(ADD_TEST_CFLAGS) +endmacro() make_directory("${CMAKE_CURRENT_BINARY_DIR}/serialization-data") proxsuite_test(serialization src/serialization.cpp) add_test_cflags( - test-cpp-serialization + ${PROJECT_NAME}-test-cpp-serialization "-DTEST_SERIALIZATION_FOLDER=\\\\\"${CMAKE_CURRENT_BINARY_DIR}/serialization-data\\\\\"" ) if(cereal_FOUND) - target_link_libraries(test-cpp-serialization PRIVATE cereal) + target_link_libraries(${PROJECT_NAME}-test-cpp-serialization PRIVATE cereal) else() target_include_directories( - test-cpp-serialization SYSTEM + ${PROJECT_NAME}-test-cpp-serialization SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/external/cereal/include) endif() @@ -87,7 +89,7 @@ if(BUILD_PYTHON_INTERFACE) foreach(TEST_FILE ${${PROJECT_NAME}_PYTHON_UNITTEST}) get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) string(REGEX REPLACE "${PROJECT_SOURCE_DIR}/" "" TEST_FILE ${TEST_FILE}) - add_python_unit_test("test-py-${TEST_NAME}" "${TEST_FILE}" + add_python_unit_test("${PROJECT_NAME}-test-py-${TEST_NAME}" "${TEST_FILE}" "bindings/python") - endforeach(TEST_FILE ${${PROJECT_NAME}_PYTHON_UNITTEST}) + endforeach() endif(BUILD_PYTHON_INTERFACE) From 566aa0d46c7a552d766c062b76712a4186c9e2ac Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Tue, 16 Jul 2024 16:42:32 +0200 Subject: [PATCH 009/109] cmake: Configure PROJECT_SOURCE_DIR --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9ab33e70..7f305d3a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.10) -if(DEFINED PROJECT_NAME) +if(DEFINED PROJECT_NAME AND NOT PROJECT_WORKSPACE) set(PROXSUITE_AS_SUBPROJECT ON) endif() @@ -14,7 +14,10 @@ set(PROJECT_URL "http://github.com/Simple-Robotics/proxsuite") set(PROJECT_CUSTOM_HEADER_EXTENSION "hpp") set(PROJECT_USE_CMAKE_EXPORT TRUE) set(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE) +# To enable jrl-cmakemodules compatibility with workspace we must define the two +# following lines set(PROJECT_AUTO_RUN_FINALIZE FALSE) +set(PROJECT_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) # Check if the submodule cmake have been initialized set(JRL_CMAKE_MODULES "${CMAKE_CURRENT_LIST_DIR}/cmake-module") From e07ef0fb8ce56c7fcf0f3bd090c698014ef9b9c4 Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Tue, 16 Jul 2024 16:43:24 +0200 Subject: [PATCH 010/109] cmake: Use topic/workspace jrl-cmakemodules --- .gitmodules | 4 +--- cmake-module | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index ce4fc4593..426d1223f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,9 +3,7 @@ url = https://github.com/pybind/pybind11 [submodule "cmake-module"] path = cmake-module - url = https://github.com/jrl-umi3218/jrl-cmakemodules.git + url = https://github.com/jorisv/jrl-cmakemodules.git [submodule "external/cereal"] path = external/cereal url = https://github.com/USCiLab/cereal.git -[submodule "cmake"] - url = https://github.com/jrl-umi3218/jrl-cmakemodules.git diff --git a/cmake-module b/cmake-module index 2bea127e8..b03972c2a 160000 --- a/cmake-module +++ b/cmake-module @@ -1 +1 @@ -Subproject commit 2bea127e8113a32f216ae7a7201e36a6e7c56cc2 +Subproject commit b03972c2aab5d4ed63bc7cc596d29328f388ef83 From 8f99186c00eccb74e305b74c5dac026f305d0bd2 Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Tue, 16 Jul 2024 16:44:57 +0200 Subject: [PATCH 011/109] changelog: Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fcef102b..7b563420a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ 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)) ## [0.6.6] - 2024-06-15 From f733f5c50fd42ea965f3bb557b9258969a8782a7 Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Wed, 24 Jul 2024 10:40:59 +0200 Subject: [PATCH 012/109] cmake: Switch to upstream jrl-cmakemodules --- .gitmodules | 2 +- cmake-module | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 426d1223f..69ac5fe4e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/pybind/pybind11 [submodule "cmake-module"] path = cmake-module - url = https://github.com/jorisv/jrl-cmakemodules.git + url = https://github.com/jrl-umi3218/jrl-cmakemodules.git [submodule "external/cereal"] path = external/cereal url = https://github.com/USCiLab/cereal.git diff --git a/cmake-module b/cmake-module index b03972c2a..91b8f5f21 160000 --- a/cmake-module +++ b/cmake-module @@ -1 +1 @@ -Subproject commit b03972c2aab5d4ed63bc7cc596d29328f388ef83 +Subproject commit 91b8f5f2168b123a198da079b8e6c09fd1f60285 From 81a44532b0240de54ecca242f0be0ae63b05b730 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:30:59 +0200 Subject: [PATCH 013/109] specify timings in microseconds --- bindings/python/src/expose-solve.hpp | 9 +++++--- doc/2-ProxQP_api.md | 2 +- doc/3-ProxQP_solve.md | 2 +- include/proxsuite/proxqp/dense/solver.hpp | 26 +++++++++++----------- include/proxsuite/proxqp/settings.hpp | 6 ++--- include/proxsuite/proxqp/sparse/solver.hpp | 24 ++++++++++---------- 6 files changed, 36 insertions(+), 33 deletions(-) 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/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; } From 9a447e7a0e42a90d4389b9b58024db059619c245 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:08:42 +0200 Subject: [PATCH 014/109] add hint to pass `-DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX` for build - discussed with @Bambade --- doc/5-installation.md | 2 ++ 1 file changed, 2 insertions(+) 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: From 1c693475323b524453be7bb47c211bcc6a34fc1c Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:14:26 +0200 Subject: [PATCH 015/109] fix cereal include directories in cmake --- bindings/python/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 From c42274937f7001aaba46af36b13fd1e9cea1a6f6 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:17:55 +0200 Subject: [PATCH 016/109] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) 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 From 89c647c6b34e041508b0ebc7323a8e54992f4f13 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 00:10:42 +0000 Subject: [PATCH 017/109] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 24.4.2 → 24.8.0](https://github.com/psf/black/compare/24.4.2...24.8.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7cec081c7..8c69882f7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: hooks: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 24.4.2 + rev: 24.8.0 hooks: - id: black - repo: https://github.com/cheshirekow/cmake-format-precommit From 7d8cc7301c54a1593469f74dbf985846ca23fe17 Mon Sep 17 00:00:00 2001 From: abambade Date: Mon, 29 Jul 2024 16:26:55 +0200 Subject: [PATCH 018/109] qplayer - infeasible case : fix dimensional typo for double sided inequalities --- bindings/python/proxsuite/torch/qplayer.py | 40 ++++++++++++++++------ 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/bindings/python/proxsuite/torch/qplayer.py b/bindings/python/proxsuite/torch/qplayer.py index 1c9955946..c7076eaa5 100644 --- a/bindings/python/proxsuite/torch/qplayer.py +++ b/bindings/python/proxsuite/torch/qplayer.py @@ -256,6 +256,7 @@ def backward(ctx, dl_dzhat, dl_dlams, dl_dnus): class QPFunctionFn_infeas(Function): @staticmethod def forward(ctx, Q_, p_, A_, b_, G_, l_, u_): + n_in, nz = G_.size() # true double-sided inequality size nBatch = extract_nBatch(Q_, p_, A_, b_, G_, l_, u_) Q, _ = expandParam(Q_, nBatch, 3) @@ -276,6 +277,7 @@ def forward(ctx, Q_, p_, A_, b_, G_, l_, u_): zhats = torch.empty((nBatch, ctx.nz), dtype=Q.dtype) nus = torch.empty((nBatch, ctx.nineq), dtype=Q.dtype) + nus_sol = torch.empty((nBatch, n_in), dtype=Q.dtype) # double-sided inequality multiplier lams = ( torch.empty(nBatch, ctx.neq, dtype=Q.dtype) if ctx.neq > 0 @@ -287,7 +289,7 @@ def forward(ctx, Q_, p_, A_, b_, G_, l_, u_): else torch.empty() ) slacks = torch.empty((nBatch, ctx.nineq), dtype=Q.dtype) - s_i = torch.empty((nBatch, ctx.nineq), dtype=Q.dtype) + s_i = torch.empty((nBatch, n_in), dtype=Q.dtype) # this one is of size the one of the original n_in vector_of_qps = proxsuite.proxqp.dense.BatchQP() @@ -339,20 +341,23 @@ def forward(ctx, Q_, p_, A_, b_, G_, l_, u_): vector_of_qps.get(i).solve() for i in range(nBatch): - si = -h[i] + G[i] @ vector_of_qps.get(i).results.x zhats[i] = torch.tensor(vector_of_qps.get(i).results.x) - nus[i] = torch.tensor(vector_of_qps.get(i).results.z) - slacks[i] = si.clone().detach() + if nineq>0: + # we re-convert the solution to a double sided inequality QP + slack = -h[i] + G[i] @ vector_of_qps.get(i).results.x + nus_sol[i] = torch.Tensor(-vector_of_qps.get(i).results.z[:n_in]+vector_of_qps.get(i).results.z[n_in:]) # de-projecting this one may provoke loss of information when using inexact solution + nus[i] = torch.tensor(vector_of_qps.get(i).results.z) + slacks[i] = slack.clone().detach() + s_i[i] = torch.tensor(-vector_of_qps.get(i).results.si[:n_in]+vector_of_qps.get(i).results.si[n_in:]) if neq > 0: lams[i] = torch.tensor(vector_of_qps.get(i).results.y) s_e[i] = torch.tensor(vector_of_qps.get(i).results.se) - s_i[i] = torch.tensor(vector_of_qps.get(i).results.si) - + ctx.lams = lams ctx.nus = nus ctx.slacks = slacks ctx.save_for_backward(zhats, s_e, Q_, p_, G_, l_, u_, A_, b_) - return zhats, lams, nus, s_e, s_i + return zhats, lams, nus_sol, s_e, s_i @staticmethod def backward(ctx, dl_dzhat, dl_dlams, dl_dnus, dl_ds_e, dl_ds_i): @@ -371,6 +376,8 @@ def backward(ctx, dl_dzhat, dl_dlams, dl_dnus, dl_ds_e, dl_ds_i): G = torch.cat((-G, G), axis=1) neq, nineq = ctx.neq, ctx.nineq + # true size + n_in_sol = int(nineq/2) dx = torch.zeros((nBatch, Q.shape[1])) dnu = None b_5 = None @@ -457,15 +464,26 @@ def backward(ctx, dl_dzhat, dl_dlams, dl_dnus, dl_ds_e, dl_ds_i): rhs = np.zeros(kkt.shape[0]) rhs[:dim] = -dl_dzhat[i] if dl_dlams != None: - rhs[dim : dim + n_eq] = -dl_dlams[i] + if n_eq!= 0: + rhs[dim : dim + n_eq] = -dl_dlams[i] + active_set = None + if n_in!=0: + active_set = -z_i[:n_in_sol]+z_i[n_in_sol:] >= 0 if dl_dnus != None: - rhs[dim + n_eq : dim + n_eq + n_in] = -dl_dnus[i] + if n_in !=0: + # we must convert dl_dnus to a uni sided version + # to do so we reconstitute the active set + rhs[dim + n_eq : dim + n_eq + n_in_sol][~active_set] = dl_dnus[i][~active_set] + rhs[dim + n_eq + n_in_sol: dim + n_eq + n_in][active_set] = -dl_dnus[i][active_set] if dl_ds_e != None: if dl_ds_e.shape[0] != 0: rhs[dim + n_eq + n_in : dim + 2 * n_eq + n_in] = -dl_ds_e[i] if dl_ds_i != None: if dl_ds_i.shape[0] != 0: - rhs[dim + 2 * n_eq + n_in :] = -dl_ds_i[i] + # we must convert dl_dnus to a uni sided version + # to do so we reconstitute the active set + rhs[dim + 2 * n_eq + n_in : dim + 2 * n_eq + n_in + n_in_sol][~active_set] = dl_ds_i[i][~active_set] + rhs[dim + 2 * n_eq + n_in + n_in_sol:][active_set] = -dl_ds_i[i][active_set] l = np.zeros(0) u = np.zeros(0) @@ -562,7 +580,7 @@ def backward(ctx, dl_dzhat, dl_dlams, dl_dnus, dl_ds_e, dl_ds_i): if p_e: dps = dps.mean(0) - grads = (dQs, dps, dAs, dbs, dGs[nineq:, :], -dhs[:nineq], dhs[nineq:]) + grads = (dQs, dps, dAs, dbs, dGs[n_in_sol:, :], -dhs[:n_in_sol], dhs[n_in_sol:]) return grads From fd23b2134051585224a861552d0467b75e4b99a1 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Wed, 7 Aug 2024 10:11:35 +0200 Subject: [PATCH 019/109] changelog: sync --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 867375bff..7d2870e3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * 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)) +### Fixed +* Fix inequality constraints return in QPLayer ([#343](https://github.com/Simple-Robotics/proxsuite/pull/343)) + ## [0.6.6] - 2024-06-15 ### Fixed From 25827f61f11ca3348288c1406ba9cf8392ef04d1 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Thu, 8 Aug 2024 15:14:29 +0200 Subject: [PATCH 020/109] CMake: allow use of installed dependencies, take 2 (#337) * CMake: allow use of installed pybind11 * CMake: modernize cereal use * changelog: sync --- CHANGELOG.md | 2 +- bindings/python/CMakeLists.txt | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 867375bff..2f1395f0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added -* Allow use of installed cereal and jrl-cmakemodules via cmake +* Allow use of installed pybind11, 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)) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 252063b87..9f2f93d30 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -14,9 +14,12 @@ else() ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}/${PROJECT_NAME}) endif() -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11) -add_subdirectory(external/pybind11 - ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11) +find_package(pybind11 CONFIG) +if(NOT pybind11_FOUND) + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11) + add_subdirectory(external/pybind11 + ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11) +endif() add_custom_target(${PROJECT_NAME}_python) @@ -92,8 +95,7 @@ function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) endif(BUILD_WITH_OPENMP_SUPPORT) if(cereal_FOUND) - target_include_directories(${target_name} SYSTEM - PRIVATE ${CEREAL_INCLUDE_DIRS}) + target_link_libraries(${target_name} PRIVATE cereal::cereal) else() target_include_directories( ${target_name} SYSTEM From 315f4d301fb1e9666108737f36c22996cae1785e Mon Sep 17 00:00:00 2001 From: Wilson Date: Wed, 14 Aug 2024 13:27:46 +0200 Subject: [PATCH 021/109] Refactor Python examples with a new "util.py" file (#347) * [examples/python] Add util.py file, move "generate_mixed_qp" function to it give reg a meaning * update CHANGELOG * apply suggestion --- CHANGELOG.md | 4 +++ .../python/estimate_nonconvex_eigenvalue.py | 27 +--------------- examples/python/init_dense_qp.py | 27 +--------------- examples/python/init_dense_qp_with_box.py | 27 +--------------- .../init_dense_qp_with_other_options.py | 27 +--------------- examples/python/init_dense_qp_with_timings.py | 27 +--------------- examples/python/init_with_default_options.py | 27 +--------------- examples/python/loading_sparse_qp.py | 29 ++--------------- examples/python/overview-simple.py | 27 +--------------- examples/python/solve_dense_qp.py | 27 +--------------- .../python/solve_dense_qp_with_setting.py | 27 +--------------- examples/python/solve_without_api.py | 29 ++--------------- .../python/solve_without_api_and_option.py | 27 +--------------- examples/python/update_dense_qp.py | 28 +--------------- .../update_dense_qp_ws_previous_result.py | 28 +--------------- examples/python/update_sparse_qp.py | 32 ++----------------- examples/python/util.py | 31 ++++++++++++++++++ 17 files changed, 54 insertions(+), 397 deletions(-) create mode 100644 examples/python/util.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f1395f0b..c95665016 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * 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)) +### Changed + +* Refactor Python examples with a new "util.py" file ([#347](https://github.com/Simple-Robotics/proxsuite/pull/347)) + ## [0.6.6] - 2024-06-15 ### Fixed diff --git a/examples/python/estimate_nonconvex_eigenvalue.py b/examples/python/estimate_nonconvex_eigenvalue.py index 21e2e54ef..7b6ecac59 100644 --- a/examples/python/estimate_nonconvex_eigenvalue.py +++ b/examples/python/estimate_nonconvex_eigenvalue.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1, reg=-2.0): - # A function for generating sparse random convex qps in dense format - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/init_dense_qp.py b/examples/python/init_dense_qp.py index d76736360..4408870f4 100644 --- a/examples/python/init_dense_qp.py +++ b/examples/python/init_dense_qp.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating random convex qps - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/init_dense_qp_with_box.py b/examples/python/init_dense_qp_with_box.py index 268e96e8b..15aa61c69 100644 --- a/examples/python/init_dense_qp_with_box.py +++ b/examples/python/init_dense_qp_with_box.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating random convex qps - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/init_dense_qp_with_other_options.py b/examples/python/init_dense_qp_with_other_options.py index 8b3faa97a..dbc9b4ab4 100644 --- a/examples/python/init_dense_qp_with_other_options.py +++ b/examples/python/init_dense_qp_with_other_options.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating random convex qps - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/init_dense_qp_with_timings.py b/examples/python/init_dense_qp_with_timings.py index 09cb66e2c..b156bd4c5 100644 --- a/examples/python/init_dense_qp_with_timings.py +++ b/examples/python/init_dense_qp_with_timings.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating random convex qps - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/init_with_default_options.py b/examples/python/init_with_default_options.py index caf2929c5..133cbb6cf 100644 --- a/examples/python/init_with_default_options.py +++ b/examples/python/init_with_default_options.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating random convex qps - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/loading_sparse_qp.py b/examples/python/loading_sparse_qp.py index f762fb096..7b8b3f880 100644 --- a/examples/python/loading_sparse_qp.py +++ b/examples/python/loading_sparse_qp.py @@ -8,36 +8,11 @@ import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating random convex qps - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc") - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P, q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp2 object using matrix masks -H, g, A, b, C, u, l = generate_mixed_qp(n) +H, g, A, b, C, u, l = generate_mixed_qp(n, True) H_ = H != 0.0 A_ = A != 0.0 diff --git a/examples/python/overview-simple.py b/examples/python/overview-simple.py index cc0fbb438..e220efb8b 100644 --- a/examples/python/overview-simple.py +++ b/examples/python/overview-simple.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating sparse random convex qps in dense format - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # generate a qp problem diff --git a/examples/python/solve_dense_qp.py b/examples/python/solve_dense_qp.py index 4eb04547c..d3cd330bc 100644 --- a/examples/python/solve_dense_qp.py +++ b/examples/python/solve_dense_qp.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating sparse random convex qps in dense format - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/solve_dense_qp_with_setting.py b/examples/python/solve_dense_qp_with_setting.py index 5999037e1..0673a0f99 100644 --- a/examples/python/solve_dense_qp_with_setting.py +++ b/examples/python/solve_dense_qp_with_setting.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating sparse random convex qps in dense format - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/solve_without_api.py b/examples/python/solve_without_api.py index 9e84676fc..3a489203a 100644 --- a/examples/python/solve_without_api.py +++ b/examples/python/solve_without_api.py @@ -1,39 +1,14 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating sparse random convex qps in dense format - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc") - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P, q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions n = 10 n_eq = 2 n_in = 2 -H, g, A, b, C, u, l = generate_mixed_qp(n) +H, g, A, b, C, u, l = generate_mixed_qp(n, True) # solve the problem using the sparse backend results = proxsuite.proxqp.sparse.solve(H, g, A, b, C, l, u) diff --git a/examples/python/solve_without_api_and_option.py b/examples/python/solve_without_api_and_option.py index 9e1cea272..930715dc8 100644 --- a/examples/python/solve_without_api_and_option.py +++ b/examples/python/solve_without_api_and_option.py @@ -1,32 +1,7 @@ import proxsuite import numpy as np import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating sparse random convex qps in dense format - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/update_dense_qp.py b/examples/python/update_dense_qp.py index 106d8f544..5ceab125f 100644 --- a/examples/python/update_dense_qp.py +++ b/examples/python/update_dense_qp.py @@ -1,32 +1,6 @@ import proxsuite import numpy as np -import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating sparse random convex qps in dense format - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/update_dense_qp_ws_previous_result.py b/examples/python/update_dense_qp_ws_previous_result.py index e8289490b..3e9b995a8 100644 --- a/examples/python/update_dense_qp_ws_previous_result.py +++ b/examples/python/update_dense_qp_ws_previous_result.py @@ -1,32 +1,6 @@ import proxsuite import numpy as np -import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating sparse random convex qps in dense format - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions diff --git a/examples/python/update_sparse_qp.py b/examples/python/update_sparse_qp.py index 12bfe7886..f52319139 100644 --- a/examples/python/update_sparse_qp.py +++ b/examples/python/update_sparse_qp.py @@ -1,32 +1,6 @@ import proxsuite import numpy as np -import scipy.sparse as spa - - -def generate_mixed_qp(n, seed=1): - # A function for generating random convex qps - - np.random.seed(seed) - n_eq = int(n / 4) - n_in = int(n / 4) - m = n_eq + n_in - - P = spa.random( - n, n, density=0.075, data_rvs=np.random.randn, format="csc" - ).toarray() - P = (P + P.T) / 2.0 - - s = max(np.absolute(np.linalg.eigvals(P))) - P += (abs(s) + 1e-02) * spa.eye(n) - P = spa.coo_matrix(P) - q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc") - v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality - u = A @ v - l = -1.0e20 * np.ones(m) - - return P, q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] +from util import generate_mixed_qp # load a qp object using qp problem dimensions @@ -35,7 +9,7 @@ def generate_mixed_qp(n, seed=1): n_in = 2 qp = proxsuite.proxqp.sparse.QP(n, n_eq, n_in) # generate a random QP -H, g, A, b, C, u, l = generate_mixed_qp(n) +H, g, A, b, C, u, l = generate_mixed_qp(n, True) # initialize the model of the problem to solve qp.init(H, g, A, b, C, l, u) qp.solve() @@ -44,7 +18,7 @@ def generate_mixed_qp(n, seed=1): qp.solve() # generate a QP with another sparsity structure # create a new problem and update qp -H2, g_new, A_new, b_new, C_new, u_new, l_new = generate_mixed_qp(n) +H2, g_new, A_new, b_new, C_new, u_new, l_new = generate_mixed_qp(n, True) qp.update(H=H2) # nothing will happen qp.update(g=g_new) # if only a vector changes, then the update takes effect qp.solve() # it solves the problem with the QP H,g_new,A,b,C,u,l diff --git a/examples/python/util.py b/examples/python/util.py new file mode 100644 index 000000000..53c0c53da --- /dev/null +++ b/examples/python/util.py @@ -0,0 +1,31 @@ +import numpy as np +import scipy.sparse as spa + + +def generate_mixed_qp(n, sparse=False, seed=1, reg=1e-2, dens1=0.075): + # A function for generating sparse random convex qps + + np.random.seed(seed) + n_eq = int(n / 4) + n_in = int(n / 4) + m = n_eq + n_in + + P = spa.random( + n, n, density=dens1, data_rvs=np.random.randn, format="csc" + ).toarray() + P = (P + P.T) / 2.0 + + s = max(np.absolute(np.linalg.eigvals(P))) + P += (abs(s) + reg) * spa.eye(n) + P = spa.coo_matrix(P) + q = np.random.randn(n) + A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc") + if not sparse: + A = A.toarray() + P = P.toarray() + v = np.random.randn(n) # Fictitious solution + delta = np.random.rand(m) # To get inequality + u = A @ v + l = -1.0e20 * np.ones(m) + + return P, q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] From 22d0d91d1b3178a47578dfc988431e6b5cdfcb4a Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 20 Aug 2024 17:34:44 +0200 Subject: [PATCH 022/109] [examples/python] minor fix --- examples/python/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/python/util.py b/examples/python/util.py index 53c0c53da..75efea225 100644 --- a/examples/python/util.py +++ b/examples/python/util.py @@ -28,4 +28,4 @@ def generate_mixed_qp(n, sparse=False, seed=1, reg=1e-2, dens1=0.075): u = A @ v l = -1.0e20 * np.ones(m) - return P, q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] + return P, q, A[:n_eq, :], u[:n_eq], A[n_eq:, :], u[n_eq:], l[n_eq:] From 0021dbc5a6161d24748f7ce7aedf1b74d8473dc0 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 20 Aug 2024 14:51:27 +0200 Subject: [PATCH 023/109] fix `mu_update` for `PrimalLDLT` backend --- include/proxsuite/proxqp/dense/solver.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/proxsuite/proxqp/dense/solver.hpp b/include/proxsuite/proxqp/dense/solver.hpp index 0e544c3ac..e2ec81633 100644 --- a/include/proxsuite/proxqp/dense/solver.hpp +++ b/include/proxsuite/proxqp/dense/solver.hpp @@ -212,14 +212,14 @@ mu_update(const Model& qpmodel, } } qpwork.ldl.rank_r_update( - new_cols, qpwork.dw_aug.head(qpmodel.dim), stack); + new_cols, qpwork.dw_aug.head(qpwork.n_c), stack); } // mu update for A { LDLT_TEMP_MAT_UNINIT(T, new_cols, qpmodel.dim, qpmodel.n_eq, stack); new_cols = qpwork.A_scaled.transpose(); qpwork.ldl.rank_r_update( - new_cols, qpwork.dw_aug.head(qpmodel.dim), stack); + new_cols, qpwork.dw_aug.head(qpmodel.n_eq), stack); } } break; case DenseBackend::Automatic: From ddd876655c46e6cfdcf4d502ef4b995d611bb5ed Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 20 Aug 2024 14:51:44 +0200 Subject: [PATCH 024/109] fix typo in `mu_update` --- include/proxsuite/proxqp/dense/solver.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/proxsuite/proxqp/dense/solver.hpp b/include/proxsuite/proxqp/dense/solver.hpp index e2ec81633..9a3c1a5cf 100644 --- a/include/proxsuite/proxqp/dense/solver.hpp +++ b/include/proxsuite/proxqp/dense/solver.hpp @@ -195,7 +195,7 @@ mu_update(const Model& qpmodel, { LDLT_TEMP_MAT_UNINIT(T, new_cols, qpmodel.dim, qpwork.n_c, stack); qpwork.dw_aug.head(qpmodel.dim).setOnes(); - T delta_mu(mu_in_new - qpresults.info.mu_in_inv); + T delta_mu(1 / mu_in_new - qpresults.info.mu_in_inv); qpwork.dw_aug.head(qpmodel.dim).array() *= delta_mu; for (isize i = 0; i < n_constraints; ++i) { isize j = qpwork.current_bijection_map[i]; From fa9066ec39746ccc0baff93a5d745db27120a2a9 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 20 Aug 2024 14:52:38 +0200 Subject: [PATCH 025/109] update dw for eq. constraints --- include/proxsuite/proxqp/dense/solver.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/proxsuite/proxqp/dense/solver.hpp b/include/proxsuite/proxqp/dense/solver.hpp index 9a3c1a5cf..9bc5bc002 100644 --- a/include/proxsuite/proxqp/dense/solver.hpp +++ b/include/proxsuite/proxqp/dense/solver.hpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // /** * @file solver.hpp @@ -217,6 +217,9 @@ mu_update(const Model& qpmodel, // mu update for A { LDLT_TEMP_MAT_UNINIT(T, new_cols, qpmodel.dim, qpmodel.n_eq, stack); + qpwork.dw_aug.head(qpmodel.n_eq).setOnes(); + T delta_mu(1 / mu_eq_new - qpresults.info.mu_eq_inv); + qpwork.dw_aug.head(qpmodel.n_eq).array() *= delta_mu; new_cols = qpwork.A_scaled.transpose(); qpwork.ldl.rank_r_update( new_cols, qpwork.dw_aug.head(qpmodel.n_eq), stack); From 2507ef7f2e6eb469e176c89b2b7e90f67bc5bad0 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:41:41 +0200 Subject: [PATCH 026/109] add unittest for mu_update with PrimalLDLT --- test/src/dense_qp_wrapper.cpp | 59 ++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/test/src/dense_qp_wrapper.cpp b/test/src/dense_qp_wrapper.cpp index d51f8609a..353fb7dce 100644 --- a/test/src/dense_qp_wrapper.cpp +++ b/test/src/dense_qp_wrapper.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // #include #include @@ -7614,3 +7614,60 @@ TEST_CASE("ProxQP::dense: test memory allocation when estimating biggest " dense::power_iteration(H, dw, rhs, err_v, 1.E-6, 10000); PROXSUITE_EIGEN_MALLOC_ALLOWED(); } + +TEST_CASE("ProxQP::dense: sparse random strongly convex qp with" + "inequality constraints: test PrimalLDLT backend mu update") +{ + + std::cout << "---testing sparse random strongly convex qp with" + "inequality constraints: test PrimalLDLT backend mu update---" + << std::endl; + double sparsity_factor = 1; + utils::rand::set_seed(1); + isize dim = 3; + isize n_eq(0); + isize n_in(9); + T strong_convexity_factor(1.e-2); + proxqp::dense::Model qp_random = proxqp::utils::dense_strongly_convex_qp( + dim, n_eq, n_in, sparsity_factor, strong_convexity_factor); + dense::QP qp{ + dim, + n_eq, + n_in, + false, + proxsuite::proxqp::HessianType::Dense, + proxsuite::proxqp::DenseBackend::PrimalLDLT + }; // creating QP object + T eps_abs = T(1e-7); + qp.settings.eps_abs = eps_abs; + qp.settings.eps_rel = 0; + qp.settings.compute_timings = true; + qp.settings.verbose = true; + qp.init(qp_random.H, + qp_random.g, + nullopt, + nullopt, + qp_random.C, + nullopt, + qp_random.u); + qp.solve(); + + DOCTEST_CHECK(qp.results.info.mu_updates > 0); + + T pri_res = (helpers::negative_part(qp_random.C * qp.results.x - qp_random.l)) + .lpNorm(); + T dua_res = (qp_random.H * qp.results.x + qp_random.g + + qp_random.C.transpose() * qp.results.z) + .lpNorm(); + DOCTEST_CHECK(pri_res <= eps_abs); + DOCTEST_CHECK(dua_res <= eps_abs); + + std::cout << "------using API solving qp with dim: " << dim + << " neq: " << n_eq << " nin: " << n_in << std::endl; + std::cout << "primal residual: " << pri_res << std::endl; + std::cout << "dual residual: " << dua_res << std::endl; + std::cout << "total number of iteration: " << qp.results.info.iter + << std::endl; + std::cout << "setup timing " << qp.results.info.setup_time << " solve time " + << qp.results.info.solve_time << std::endl; +} From c5f734b410bebd594c68a9a9a41ee2aed154b393 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:13:22 +0200 Subject: [PATCH 027/109] update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c95665016..0df499d8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added +* Fix mu update function for PrimalLDLT backend ([#349](https://github.com/Simple-Robotics/proxsuite/pull/349)) * Allow use of installed pybind11, 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)) From bc54ff3011f03d0e9fdfa0fddc62db76c2c5c401 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:44:32 +0200 Subject: [PATCH 028/109] Update include/proxsuite/proxqp/dense/solver.hpp Co-authored-by: Justin Carpentier --- include/proxsuite/proxqp/dense/solver.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/proxsuite/proxqp/dense/solver.hpp b/include/proxsuite/proxqp/dense/solver.hpp index 9bc5bc002..6d428ae64 100644 --- a/include/proxsuite/proxqp/dense/solver.hpp +++ b/include/proxsuite/proxqp/dense/solver.hpp @@ -195,7 +195,7 @@ mu_update(const Model& qpmodel, { LDLT_TEMP_MAT_UNINIT(T, new_cols, qpmodel.dim, qpwork.n_c, stack); qpwork.dw_aug.head(qpmodel.dim).setOnes(); - T delta_mu(1 / mu_in_new - qpresults.info.mu_in_inv); + T delta_mu(T(1) / mu_in_new - qpresults.info.mu_in_inv); qpwork.dw_aug.head(qpmodel.dim).array() *= delta_mu; for (isize i = 0; i < n_constraints; ++i) { isize j = qpwork.current_bijection_map[i]; From 769e4501be747c37749265ff72525be01edfabff Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Sat, 15 Jun 2024 10:02:31 +0200 Subject: [PATCH 029/109] cmake: sync submodule --- cmake-module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake-module b/cmake-module index 91b8f5f21..b3c2af1b6 160000 --- a/cmake-module +++ b/cmake-module @@ -1 +1 @@ -Subproject commit 91b8f5f2168b123a198da079b8e6c09fd1f60285 +Subproject commit b3c2af1b68686dc9d5f459fb617647e37a15a76d From c66e6662296e19ab17d35327d76ddc7f2ceafba7 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Tue, 27 Aug 2024 10:21:06 +0200 Subject: [PATCH 030/109] pre-commit: format --- bindings/python/proxsuite/torch/qplayer.py | 66 +++++++++++++++------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/bindings/python/proxsuite/torch/qplayer.py b/bindings/python/proxsuite/torch/qplayer.py index c7076eaa5..f3cee2b1b 100644 --- a/bindings/python/proxsuite/torch/qplayer.py +++ b/bindings/python/proxsuite/torch/qplayer.py @@ -256,7 +256,7 @@ def backward(ctx, dl_dzhat, dl_dlams, dl_dnus): class QPFunctionFn_infeas(Function): @staticmethod def forward(ctx, Q_, p_, A_, b_, G_, l_, u_): - n_in, nz = G_.size() # true double-sided inequality size + n_in, nz = G_.size() # true double-sided inequality size nBatch = extract_nBatch(Q_, p_, A_, b_, G_, l_, u_) Q, _ = expandParam(Q_, nBatch, 3) @@ -277,7 +277,9 @@ def forward(ctx, Q_, p_, A_, b_, G_, l_, u_): zhats = torch.empty((nBatch, ctx.nz), dtype=Q.dtype) nus = torch.empty((nBatch, ctx.nineq), dtype=Q.dtype) - nus_sol = torch.empty((nBatch, n_in), dtype=Q.dtype) # double-sided inequality multiplier + nus_sol = torch.empty( + (nBatch, n_in), dtype=Q.dtype + ) # double-sided inequality multiplier lams = ( torch.empty(nBatch, ctx.neq, dtype=Q.dtype) if ctx.neq > 0 @@ -289,7 +291,9 @@ def forward(ctx, Q_, p_, A_, b_, G_, l_, u_): else torch.empty() ) slacks = torch.empty((nBatch, ctx.nineq), dtype=Q.dtype) - s_i = torch.empty((nBatch, n_in), dtype=Q.dtype) # this one is of size the one of the original n_in + s_i = torch.empty( + (nBatch, n_in), dtype=Q.dtype + ) # this one is of size the one of the original n_in vector_of_qps = proxsuite.proxqp.dense.BatchQP() @@ -342,17 +346,23 @@ def forward(ctx, Q_, p_, A_, b_, G_, l_, u_): for i in range(nBatch): zhats[i] = torch.tensor(vector_of_qps.get(i).results.x) - if nineq>0: + if nineq > 0: # we re-convert the solution to a double sided inequality QP slack = -h[i] + G[i] @ vector_of_qps.get(i).results.x - nus_sol[i] = torch.Tensor(-vector_of_qps.get(i).results.z[:n_in]+vector_of_qps.get(i).results.z[n_in:]) # de-projecting this one may provoke loss of information when using inexact solution + nus_sol[i] = torch.Tensor( + -vector_of_qps.get(i).results.z[:n_in] + + vector_of_qps.get(i).results.z[n_in:] + ) # de-projecting this one may provoke loss of information when using inexact solution nus[i] = torch.tensor(vector_of_qps.get(i).results.z) slacks[i] = slack.clone().detach() - s_i[i] = torch.tensor(-vector_of_qps.get(i).results.si[:n_in]+vector_of_qps.get(i).results.si[n_in:]) + s_i[i] = torch.tensor( + -vector_of_qps.get(i).results.si[:n_in] + + vector_of_qps.get(i).results.si[n_in:] + ) if neq > 0: lams[i] = torch.tensor(vector_of_qps.get(i).results.y) s_e[i] = torch.tensor(vector_of_qps.get(i).results.se) - + ctx.lams = lams ctx.nus = nus ctx.slacks = slacks @@ -377,7 +387,7 @@ def backward(ctx, dl_dzhat, dl_dlams, dl_dnus, dl_ds_e, dl_ds_i): neq, nineq = ctx.neq, ctx.nineq # true size - n_in_sol = int(nineq/2) + n_in_sol = int(nineq / 2) dx = torch.zeros((nBatch, Q.shape[1])) dnu = None b_5 = None @@ -464,26 +474,34 @@ def backward(ctx, dl_dzhat, dl_dlams, dl_dnus, dl_ds_e, dl_ds_i): rhs = np.zeros(kkt.shape[0]) rhs[:dim] = -dl_dzhat[i] if dl_dlams != None: - if n_eq!= 0: + if n_eq != 0: rhs[dim : dim + n_eq] = -dl_dlams[i] - active_set = None - if n_in!=0: - active_set = -z_i[:n_in_sol]+z_i[n_in_sol:] >= 0 + active_set = None + if n_in != 0: + active_set = -z_i[:n_in_sol] + z_i[n_in_sol:] >= 0 if dl_dnus != None: - if n_in !=0: + if n_in != 0: # we must convert dl_dnus to a uni sided version - # to do so we reconstitute the active set - rhs[dim + n_eq : dim + n_eq + n_in_sol][~active_set] = dl_dnus[i][~active_set] - rhs[dim + n_eq + n_in_sol: dim + n_eq + n_in][active_set] = -dl_dnus[i][active_set] + # to do so we reconstitute the active set + rhs[dim + n_eq : dim + n_eq + n_in_sol][~active_set] = dl_dnus[ + i + ][~active_set] + rhs[dim + n_eq + n_in_sol : dim + n_eq + n_in][active_set] = ( + -dl_dnus[i][active_set] + ) if dl_ds_e != None: if dl_ds_e.shape[0] != 0: rhs[dim + n_eq + n_in : dim + 2 * n_eq + n_in] = -dl_ds_e[i] if dl_ds_i != None: if dl_ds_i.shape[0] != 0: # we must convert dl_dnus to a uni sided version - # to do so we reconstitute the active set - rhs[dim + 2 * n_eq + n_in : dim + 2 * n_eq + n_in + n_in_sol][~active_set] = dl_ds_i[i][~active_set] - rhs[dim + 2 * n_eq + n_in + n_in_sol:][active_set] = -dl_ds_i[i][active_set] + # to do so we reconstitute the active set + rhs[dim + 2 * n_eq + n_in : dim + 2 * n_eq + n_in + n_in_sol][ + ~active_set + ] = dl_ds_i[i][~active_set] + rhs[dim + 2 * n_eq + n_in + n_in_sol :][active_set] = -dl_ds_i[ + i + ][active_set] l = np.zeros(0) u = np.zeros(0) @@ -580,7 +598,15 @@ def backward(ctx, dl_dzhat, dl_dlams, dl_dnus, dl_ds_e, dl_ds_i): if p_e: dps = dps.mean(0) - grads = (dQs, dps, dAs, dbs, dGs[n_in_sol:, :], -dhs[:n_in_sol], dhs[n_in_sol:]) + grads = ( + dQs, + dps, + dAs, + dbs, + dGs[n_in_sol:, :], + -dhs[:n_in_sol], + dhs[n_in_sol:], + ) return grads From 29f96083e21d18c879f5a732336ec19e557580b2 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Tue, 27 Aug 2024 11:08:14 +0200 Subject: [PATCH 031/109] release: Update package.xml version to 0.6.7 --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 9fe309bed..4aa4539ae 100644 --- a/package.xml +++ b/package.xml @@ -1,7 +1,7 @@ proxsuite - 0.6.6 + 0.6.7 The Advanced Proximal Optimization Toolbox Justin Carpentier From 9a90f97364cb1c0dfc51ebb7c531b1ce22a2ea89 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Tue, 27 Aug 2024 11:08:17 +0200 Subject: [PATCH 032/109] release: Update pyproject.toml version to 0.6.7 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 186eaf6d6..e40bd4616 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "proxsuite" -version = "0.6.6" +version = "0.6.7" description = "Quadratic Programming Solver for Robotics and beyond." readme = "README.md" requires-python = ">= 3.7" From c90564b68b5d3205b0fe3e232c7cec5e79f69360 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Tue, 27 Aug 2024 11:08:19 +0200 Subject: [PATCH 033/109] release: Update CHANGELOG.md for 0.6.7 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9703885fc..e7f6fad16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +## [0.6.7] - 2024-08-27 + ### Added * Fix mu update function for PrimalLDLT backend ([#349](https://github.com/Simple-Robotics/proxsuite/pull/349)) * Allow use of installed pybind11, cereal and jrl-cmakemodules via cmake @@ -429,7 +431,8 @@ More to come ([#](a forthcoming release.)) The first release of ProxSuite. -[Unreleased]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.6...HEAD +[Unreleased]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.7...HEAD +[0.6.7]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.6...v0.6.7 [0.6.6]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.5...v0.6.6 [0.6.5]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.4...v0.6.5 [0.6.4]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.3...v0.6.4 From 72f8c3b13e4c5929f1767bd0ebb4718b1fa3e9a7 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Tue, 27 Aug 2024 11:08:21 +0200 Subject: [PATCH 034/109] release: Update CITATION.cff version to 0.6.7 --- CITATION.cff | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 2def662cd..fd84309e6 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -14,7 +14,7 @@ authors: - family-names: Carpentier given-names: Justin orcid: "https://orcid.org/0000-0001-6585-2894" -version: 0.6.6 -date-released: "2024-06-15" +version: 0.6.7 +date-released: "2024-08-27" license: BSD-2-Clause repository-code: "https://github.com/Simple-Robotics/proxsuite" From f004de9da9c5a6d860e569a38190ec9c38cd8107 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 15:38:38 +0200 Subject: [PATCH 035/109] [python/external] swap out pybind11 for nanobind --- .gitmodules | 6 +++--- bindings/python/external/nanobind | 1 + bindings/python/external/pybind11 | 1 - 3 files changed, 4 insertions(+), 4 deletions(-) create mode 160000 bindings/python/external/nanobind delete mode 160000 bindings/python/external/pybind11 diff --git a/.gitmodules b/.gitmodules index 69ac5fe4e..2867bf33b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ -[submodule "external/pybind11"] - path = bindings/python/external/pybind11 - url = https://github.com/pybind/pybind11 +[submodule "bindings/python/external/nanobind"] + path = bindings/python/external/nanobind + url = https://github.com/wjakob/nanobind [submodule "cmake-module"] path = cmake-module url = https://github.com/jrl-umi3218/jrl-cmakemodules.git diff --git a/bindings/python/external/nanobind b/bindings/python/external/nanobind new file mode 160000 index 000000000..8d7f1ee06 --- /dev/null +++ b/bindings/python/external/nanobind @@ -0,0 +1 @@ +Subproject commit 8d7f1ee0621c17fa370b704b2100ffa0243d5bfb diff --git a/bindings/python/external/pybind11 b/bindings/python/external/pybind11 deleted file mode 160000 index 849322806..000000000 --- a/bindings/python/external/pybind11 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 849322806cd4b3697ad1d35eedd6d0352c5f267a From d28e4ebbd4b65dbfab00d74840259f6e588d7c71 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 18:11:00 +0200 Subject: [PATCH 036/109] [bindings/python] update CMake listfile, targets and instruction-set.cpp for nanobind [bindings/python] cmake : nanobind's helper function already sets prefix and suffix for us. --- bindings/python/CMakeLists.txt | 25 +++++++++------------ bindings/python/helpers/instruction-set.cpp | 4 ++-- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 9f2f93d30..d6b3cf216 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -6,6 +6,7 @@ include(${JRL_CMAKE_MODULES}/python.cmake) include(${JRL_CMAKE_MODULES}/python-helpers.cmake) findpython(REQUIRED Development.Module) +find_package(Python 3.8 COMPONENTS ${PYTHON_COMPONENTS}) if(IS_ABSOLUTE ${PYTHON_SITELIB}) set(${PYWRAP}_INSTALL_DIR ${PYTHON_SITELIB}/${PROJECT_NAME}) @@ -14,12 +15,9 @@ else() ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}/${PROJECT_NAME}) endif() -find_package(pybind11 CONFIG) -if(NOT pybind11_FOUND) - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11) - add_subdirectory(external/pybind11 - ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11) -endif() +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/nanobind) +add_subdirectory(external/nanobind + ${CMAKE_CURRENT_BINARY_DIR}/external/nanobind) add_custom_target(${PROJECT_NAME}_python) @@ -29,14 +27,12 @@ file(GLOB_RECURSE PYWRAP_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp) # Add simd feature detectors for current intel CPU if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)") - python3_add_library(instructionset MODULE helpers/instruction-set.cpp) + nanobind_add_module(instructionset helpers/instruction-set.cpp) add_dependencies(${PROJECT_NAME}_python instructionset) - target_link_libraries(instructionset PRIVATE proxsuite pybind11::module) + target_link_libraries(instructionset PRIVATE proxsuite) set_target_properties( instructionset PROPERTIES OUTPUT_NAME instructionset - PREFIX "" - SUFFIX ${PYTHON_EXT_SUFFIX} LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" LIBRARY_OUTPUT_DIRECTORY_RELEASE @@ -72,12 +68,13 @@ function(list_filter list regular_expression dest_list) endfunction(list_filter) function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) - python3_add_library(${target_name} MODULE ${PYWRAP_SOURCES} ${PYWRAP_HEADERS}) + nanobind_add_module(${target_name} ${PYWRAP_SOURCES} + ${PYWRAP_HEADERS}) add_dependencies(${PROJECT_NAME}_python ${target_name}) - target_link_libraries(${target_name} PUBLIC ${dependencies} pybind11::module) + target_link_libraries(${target_name} PUBLIC ${dependencies}) target_compile_options(${target_name} PRIVATE ${COMPILE_OPTIONS}) - target_link_libraries(${target_name} PRIVATE proxsuite pybind11::module) + target_link_libraries(${target_name} PRIVATE proxsuite) target_compile_definitions(${target_name} PRIVATE PYTHON_MODULE_NAME=${target_name}) @@ -104,8 +101,6 @@ function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) set_target_properties( ${target_name} PROPERTIES OUTPUT_NAME ${target_name} - PREFIX "" - SUFFIX ${PYTHON_EXT_SUFFIX} LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bindings/python/${PROJECT_NAME}" LIBRARY_OUTPUT_DIRECTORY_RELEASE diff --git a/bindings/python/helpers/instruction-set.cpp b/bindings/python/helpers/instruction-set.cpp index c99c43672..40342bb85 100644 --- a/bindings/python/helpers/instruction-set.cpp +++ b/bindings/python/helpers/instruction-set.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2022 INRIA // -#include +#include #include @@ -10,7 +10,7 @@ namespace proxsuite { namespace helpers { namespace python { -PYBIND11_MODULE(instructionset, m) +NB_MODULE(instructionset, m) { m.doc() = R"pbdoc( CPU info library From 7168637f2d27e7a467875b2dce92210b7d10cf6d Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 19:59:01 +0200 Subject: [PATCH 037/109] [bindings/python] instruction-set.cpp : fix crashes because of lack of std::string support + add relevant nanobind stl support header --- bindings/python/helpers/instruction-set.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/bindings/python/helpers/instruction-set.cpp b/bindings/python/helpers/instruction-set.cpp index 40342bb85..cc92bf214 100644 --- a/bindings/python/helpers/instruction-set.cpp +++ b/bindings/python/helpers/instruction-set.cpp @@ -3,6 +3,7 @@ // #include +#include #include From 14ab3a38fdb69d4633be06c72c3fa4b55d4cc3b3 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:00:02 +0200 Subject: [PATCH 038/109] [proxqp/sparse] explicitly delete copy ctor and operator, fixing confusion with is_copy_constructible-type traits --- include/proxsuite/proxqp/sparse/wrapper.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/proxsuite/proxqp/sparse/wrapper.hpp b/include/proxsuite/proxqp/sparse/wrapper.hpp index b9884bc7e..6cfa48641 100644 --- a/include/proxsuite/proxqp/sparse/wrapper.hpp +++ b/include/proxsuite/proxqp/sparse/wrapper.hpp @@ -147,6 +147,11 @@ struct QP } } + QP(const QP&) = delete; + QP& operator=(const QP&) = delete; + QP(QP&&) = default; + QP& operator=(QP&&) = default; + /*! * Setups the QP model (with sparse matrix format) and equilibrates it. * @param H quadratic cost input defining the QP model. @@ -814,6 +819,10 @@ struct BatchQP } m_size = 0; } + BatchQP(const BatchQP&) = delete; + BatchQP& operator=(const BatchQP&) = delete; + BatchQP(BatchQP&&) = default; + BatchQP& operator=(BatchQP&&) = default; /*! * Init a QP in place and return a reference to it From a0a97fa7d65630ade9da5b42b7127e06910d64cb Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:01:15 +0200 Subject: [PATCH 039/109] [bindings/python] expose-all.cpp : do pybind11 -> nanobind swap --- bindings/python/src/expose-all.cpp | 38 ++++++++++++++++-------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/bindings/python/src/expose-all.cpp b/bindings/python/src/expose-all.cpp index 78545620b..cdfc4f87c 100644 --- a/bindings/python/src/expose-all.cpp +++ b/bindings/python/src/expose-all.cpp @@ -1,10 +1,12 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // #include -#include -#include +#include +#include +#include +#include #include "algorithms.hpp" #include @@ -16,7 +18,7 @@ namespace python { template void -exposeCommon(pybind11::module_ m) +exposeCommon(nanobind::module_ m) { exposeResults(m); exposeSettings(m); @@ -29,7 +31,7 @@ exposeCommon(pybind11::module_ m) template void -exposeSparseAlgorithms(pybind11::module_ m) +exposeSparseAlgorithms(nanobind::module_ m) { sparse::python::exposeSparseModel(m); sparse::python::exposeQpObjectSparse(m); @@ -40,7 +42,7 @@ exposeSparseAlgorithms(pybind11::module_ m) template void -exposeDenseAlgorithms(pybind11::module_ m) +exposeDenseAlgorithms(nanobind::module_ m) { dense::python::exposeWorkspaceDense(m); dense::python::exposeDenseModel(m); @@ -51,7 +53,7 @@ exposeDenseAlgorithms(pybind11::module_ m) } template void -exposeBackward(pybind11::module_ m) +exposeBackward(nanobind::module_ m) { dense::python::backward(m); } @@ -59,19 +61,19 @@ exposeBackward(pybind11::module_ m) #ifdef PROXSUITE_PYTHON_INTERFACE_WITH_OPENMP template void -exposeDenseParallel(pybind11::module_ m) +exposeDenseParallel(nanobind::module_ m) { dense::python::solveDenseQpParallel(m); } template void -exposeSparseParallel(pybind11::module_ m) +exposeSparseParallel(nanobind::module_ m) { sparse::python::solveSparseQpParallel(m); } #endif -PYBIND11_MODULE(PYTHON_MODULE_NAME, m) +NB_MODULE(PYTHON_MODULE_NAME, m) { m.doc() = R"pbdoc( The proxSuite library @@ -84,17 +86,17 @@ PYBIND11_MODULE(PYTHON_MODULE_NAME, m) proxsuite )pbdoc"; - pybind11::module_ proxqp_module = + nanobind::module_ proxqp_module = m.def_submodule("proxqp", "The proxQP solvers of the proxSuite library"); exposeCommon(proxqp_module); - pybind11::module_ dense_module = + nanobind::module_ dense_module = proxqp_module.def_submodule("dense", "Dense solver of proxQP"); exposeDenseAlgorithms(dense_module); exposeBackward(dense_module); #ifdef PROXSUITE_PYTHON_INTERFACE_WITH_OPENMP exposeDenseParallel(dense_module); #endif - pybind11::module_ sparse_module = + nanobind::module_ sparse_module = proxqp_module.def_submodule("sparse", "Sparse solver of proxQP"); exposeSparseAlgorithms(sparse_module); #ifdef PROXSUITE_PYTHON_INTERFACE_WITH_OPENMP @@ -105,17 +107,17 @@ PYBIND11_MODULE(PYTHON_MODULE_NAME, m) m.attr("__version__") = helpers::printVersion(); // Add helpers - pybind11::module_ helpers_module = + nanobind::module_ helpers_module = m.def_submodule("helpers", "Helper module"); helpers_module.def("printVersion", helpers::printVersion, - pybind11::arg("delimiter") = ".", + nanobind::arg("delimiter") = ".", "Print the current version of the package."); helpers_module.def("checkVersionAtLeast", helpers::checkVersionAtLeast, - pybind11::arg("major_version"), - pybind11::arg("minor_version"), - pybind11::arg("patch_version"), + nanobind::arg("major_version"), + nanobind::arg("minor_version"), + nanobind::arg("patch_version"), "Check version of the package is at least greater than " "the one provided as input."); } From 86863f25792ce44db659d392c58eb50a36c32566 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:02:27 +0200 Subject: [PATCH 040/109] [bindings/python] expose-workspace.hpp : do pybind11 -> nanobind swap + only concerns def_* methods and pickling (now managed manually through setting the relevant special methods) --- bindings/python/src/expose-workspace.hpp | 130 +++++++++++------------ 1 file changed, 62 insertions(+), 68 deletions(-) diff --git a/bindings/python/src/expose-workspace.hpp b/bindings/python/src/expose-workspace.hpp index f827f4f34..9fa9fde65 100644 --- a/bindings/python/src/expose-workspace.hpp +++ b/bindings/python/src/expose-workspace.hpp @@ -1,87 +1,81 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // -#include -#include +#include +#include +#include #include #include #include #include #include -#include "helpers.hpp" + namespace proxsuite { namespace proxqp { namespace dense { namespace python { template void -exposeWorkspaceDense(pybind11::module_ m) +exposeWorkspaceDense(nanobind::module_ m) { - ::pybind11::class_>( - m, "workspace", pybind11::module_local()) - .def(::pybind11::init(), - pybind11::arg_v("n", 0, "primal dimension."), - pybind11::arg_v("n_eq", 0, "number of equality constraints."), - pybind11::arg_v("n_in", 0, "number of inequality constraints."), + ::nanobind::class_>(m, "workspace") + .def(::nanobind::init(), + nanobind::arg("n") = 0, + nanobind::arg("n_eq") = 0, + nanobind::arg("n_in") = 0, "Constructor using QP model dimensions.") // constructor) - .def_readonly("H_scaled", &Workspace::H_scaled) - .def_readonly("g_scaled", &Workspace::g_scaled) - .def_readonly("A_scaled", &Workspace::A_scaled) - .def_readonly("C_scaled", &Workspace::C_scaled) - .def_readonly("b_scaled", &Workspace::b_scaled) - .def_readonly("u_scaled", &Workspace::u_scaled) - .def_readonly("l_scaled", &Workspace::l_scaled) - .def_readonly("x_prev", &Workspace::x_prev) - .def_readonly("y_prev", &Workspace::y_prev) - .def_readonly("z_prev", &Workspace::z_prev) - .def_readonly("kkt", &Workspace::kkt) - .def_readonly("current_bijection_map", &Workspace::current_bijection_map) - .def_readonly("new_bijection_map", &Workspace::new_bijection_map) - .def_readonly("active_set_up", &Workspace::active_set_up) - .def_readonly("active_set_low", &Workspace::active_set_low) - .def_readonly("active_inequalities", &Workspace::active_inequalities) - .def_readonly("Hdx", &Workspace::Hdx) - .def_readonly("Cdx", &Workspace::Cdx) - .def_readonly("Adx", &Workspace::Adx) - .def_readonly("active_part_z", &Workspace::active_part_z) - .def_readonly("alphas", &Workspace::alphas) - .def_readonly("dw_aug", &Workspace::dw_aug) - .def_readonly("rhs", &Workspace::rhs) - .def_readonly("err", &Workspace::err) - .def_readonly("dual_feasibility_rhs_2", - &Workspace::dual_feasibility_rhs_2) - .def_readonly("correction_guess_rhs_g", - &Workspace::correction_guess_rhs_g) - .def_readonly("correction_guess_rhs_b", - &Workspace::correction_guess_rhs_b) - .def_readonly("alpha", &Workspace::alpha) - .def_readonly("dual_residual_scaled", &Workspace::dual_residual_scaled) - .def_readonly("primal_residual_in_scaled_up", - &Workspace::primal_residual_in_scaled_up) - .def_readonly("primal_residual_in_scaled_up_plus_alphaCdx", - &Workspace::primal_residual_in_scaled_up_plus_alphaCdx) - .def_readonly("primal_residual_in_scaled_low_plus_alphaCdx", - &Workspace::primal_residual_in_scaled_low_plus_alphaCdx) - .def_readonly("CTz", &Workspace::CTz) - .def_readonly("constraints_changed", &Workspace::constraints_changed) - .def_readonly("dirty", &Workspace::dirty) - .def_readonly("refactorize", &Workspace::refactorize) - .def_readonly("proximal_parameter_update", - &Workspace::proximal_parameter_update) - .def_readonly("is_initialized", &Workspace::is_initialized) - .def_readonly("n_c", &Workspace::n_c) - .def(pybind11::pickle( - - [](const Workspace& workspace) { - return pybind11::bytes( - proxsuite::serialization::saveToString(workspace)); - }, - [](pybind11::bytes& s) { - Workspace workspace; - proxsuite::serialization::loadFromString(workspace, s); - return workspace; - })); + .def_ro("H_scaled", &Workspace::H_scaled) + .def_ro("g_scaled", &Workspace::g_scaled) + .def_ro("A_scaled", &Workspace::A_scaled) + .def_ro("C_scaled", &Workspace::C_scaled) + .def_ro("b_scaled", &Workspace::b_scaled) + .def_ro("u_scaled", &Workspace::u_scaled) + .def_ro("l_scaled", &Workspace::l_scaled) + .def_ro("x_prev", &Workspace::x_prev) + .def_ro("y_prev", &Workspace::y_prev) + .def_ro("z_prev", &Workspace::z_prev) + .def_ro("kkt", &Workspace::kkt) + .def_ro("current_bijection_map", &Workspace::current_bijection_map) + .def_ro("new_bijection_map", &Workspace::new_bijection_map) + .def_ro("active_set_up", &Workspace::active_set_up) + .def_ro("active_set_low", &Workspace::active_set_low) + .def_ro("active_inequalities", &Workspace::active_inequalities) + .def_ro("Hdx", &Workspace::Hdx) + .def_ro("Cdx", &Workspace::Cdx) + .def_ro("Adx", &Workspace::Adx) + .def_ro("active_part_z", &Workspace::active_part_z) + .def_ro("alphas", &Workspace::alphas) + .def_ro("dw_aug", &Workspace::dw_aug) + .def_ro("rhs", &Workspace::rhs) + .def_ro("err", &Workspace::err) + .def_ro("dual_feasibility_rhs_2", &Workspace::dual_feasibility_rhs_2) + .def_ro("correction_guess_rhs_g", &Workspace::correction_guess_rhs_g) + .def_ro("correction_guess_rhs_b", &Workspace::correction_guess_rhs_b) + .def_ro("alpha", &Workspace::alpha) + .def_ro("dual_residual_scaled", &Workspace::dual_residual_scaled) + .def_ro("primal_residual_in_scaled_up", + &Workspace::primal_residual_in_scaled_up) + .def_ro("primal_residual_in_scaled_up_plus_alphaCdx", + &Workspace::primal_residual_in_scaled_up_plus_alphaCdx) + .def_ro("primal_residual_in_scaled_low_plus_alphaCdx", + &Workspace::primal_residual_in_scaled_low_plus_alphaCdx) + .def_ro("CTz", &Workspace::CTz) + .def_ro("constraints_changed", &Workspace::constraints_changed) + .def_ro("dirty", &Workspace::dirty) + .def_ro("refactorize", &Workspace::refactorize) + .def_ro("proximal_parameter_update", + &Workspace::proximal_parameter_update) + .def_ro("is_initialized", &Workspace::is_initialized) + .def_ro("n_c", &Workspace::n_c) + .def("__getstate__", + [](const Workspace& workspace) { + return proxsuite::serialization::saveToString(workspace); + }) + .def("__setstate__", [](Workspace& workspace, nanobind::bytes& s) { + new (&workspace) Workspace{}; + proxsuite::serialization::loadFromString(workspace, s.c_str()); + }); ; } From 82d372fced20b26da6ac1a805f40dca5c52f26c1 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:03:28 +0200 Subject: [PATCH 041/109] [bindings/python] helpers.hpp : do pybind11 -> nanobind swap --- bindings/python/src/helpers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/src/helpers.hpp b/bindings/python/src/helpers.hpp index cd0fe716a..fc7c37de6 100644 --- a/bindings/python/src/helpers.hpp +++ b/bindings/python/src/helpers.hpp @@ -5,7 +5,7 @@ #define proxsuite_python_helpers_hpp #define PROXSUITE_PYTHON_EIGEN_READWRITE(class, field_name, doc) \ - def_property( \ + def_prop_rw( \ #field_name, \ [](class& self) { return self.field_name; }, \ [](class& self, const decltype(class ::field_name)& value) { \ From 887b5c3b03ddd790992db26c57b78177fd6069c3 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:04:42 +0200 Subject: [PATCH 042/109] [bindings/python] expose-settings.hpp : do pybind11 -> nanobind swap + concerns def_* methods and pickling (now managed manually through setting the relevant special methods) + remove module_local(), as it is not supported in nanobind: https://nanobind.readthedocs.io/en/latest/porting.html#removed-features --- bindings/python/src/expose-settings.hpp | 139 +++++++++++------------- 1 file changed, 65 insertions(+), 74 deletions(-) diff --git a/bindings/python/src/expose-settings.hpp b/bindings/python/src/expose-settings.hpp index c9188ca1d..4569f7d3e 100644 --- a/bindings/python/src/expose-settings.hpp +++ b/bindings/python/src/expose-settings.hpp @@ -1,9 +1,10 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // -#include -#include -#include +#include +#include +#include +#include #include #include @@ -15,11 +16,10 @@ namespace proxqp { namespace python { template void -exposeSettings(pybind11::module_ m) +exposeSettings(nanobind::module_ m) { - ::pybind11::enum_( - m, "InitialGuess", pybind11::module_local()) + ::nanobind::enum_(m, "InitialGuess") .value("NO_INITIAL_GUESS", InitialGuessStatus::NO_INITIAL_GUESS) .value("EQUALITY_CONSTRAINED_INITIAL_GUESS", InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS) @@ -30,85 +30,76 @@ exposeSettings(pybind11::module_ m) InitialGuessStatus::COLD_START_WITH_PREVIOUS_RESULT) .export_values(); - ::pybind11::enum_( - m, "MeritFunctionType", pybind11::module_local()) + ::nanobind::enum_(m, "MeritFunctionType") .value("GPDAL", MeritFunctionType::GPDAL) .value("PDAL", MeritFunctionType::PDAL) .export_values(); - ::pybind11::enum_(m, "SparseBackend", pybind11::module_local()) + ::nanobind::enum_(m, "SparseBackend") .value("Automatic", SparseBackend::Automatic) .value("MatrixFree", SparseBackend::MatrixFree) .value("SparseCholesky", SparseBackend::SparseCholesky) .export_values(); - ::pybind11::enum_( - m, "EigenValueEstimateMethodOption", pybind11::module_local()) + ::nanobind::enum_( + m, "EigenValueEstimateMethodOption") .value("PowerIteration", EigenValueEstimateMethodOption::PowerIteration) .value("ExactMethod", EigenValueEstimateMethodOption::ExactMethod) .export_values(); - ::pybind11::class_>(m, "Settings", pybind11::module_local()) - .def(::pybind11::init(), "Default constructor.") // constructor - .def_readwrite("default_rho", &Settings::default_rho) - .def_readwrite("default_mu_eq", &Settings::default_mu_eq) - .def_readwrite("default_mu_in", &Settings::default_mu_in) - .def_readwrite("alpha_bcl", &Settings::alpha_bcl) - .def_readwrite("beta_bcl", &Settings::beta_bcl) - .def_readwrite("refactor_dual_feasibility_threshold", - &Settings::refactor_dual_feasibility_threshold) - .def_readwrite("refactor_rho_threshold", - &Settings::refactor_rho_threshold) - .def_readwrite("mu_min_eq", &Settings::mu_min_eq) - .def_readwrite("mu_min_in", &Settings::mu_min_in) - .def_readwrite("mu_max_eq_inv", &Settings::mu_max_eq_inv) - .def_readwrite("mu_max_in_inv", &Settings::mu_max_in_inv) - .def_readwrite("mu_update_factor", &Settings::mu_update_factor) - .def_readwrite("cold_reset_mu_eq", &Settings::cold_reset_mu_eq) - .def_readwrite("cold_reset_mu_in", &Settings::cold_reset_mu_in) - .def_readwrite("max_iter", &Settings::max_iter) - .def_readwrite("max_iter_in", &Settings::max_iter_in) - .def_readwrite("eps_abs", &Settings::eps_abs) - .def_readwrite("eps_rel", &Settings::eps_rel) - .def_readwrite("eps_primal_inf", &Settings::eps_primal_inf) - .def_readwrite("eps_dual_inf", &Settings::eps_dual_inf) - .def_readwrite("nb_iterative_refinement", - &Settings::nb_iterative_refinement) - .def_readwrite("initial_guess", &Settings::initial_guess) - .def_readwrite("sparse_backend", &Settings::sparse_backend) - .def_readwrite("preconditioner_accuracy", - &Settings::preconditioner_accuracy) - .def_readwrite("preconditioner_max_iter", - &Settings::preconditioner_max_iter) - .def_readwrite("compute_timings", &Settings::compute_timings) - .def_readwrite("compute_preconditioner", - &Settings::compute_preconditioner) - .def_readwrite("update_preconditioner", &Settings::update_preconditioner) - .def_readwrite("check_duality_gap", &Settings::check_duality_gap) - .def_readwrite("eps_duality_gap_abs", &Settings::eps_duality_gap_abs) - .def_readwrite("eps_duality_gap_rel", &Settings::eps_duality_gap_rel) - .def_readwrite("verbose", &Settings::verbose) - .def_readwrite("bcl_update", &Settings::bcl_update) - .def_readwrite("merit_function_type", &Settings::merit_function_type) - .def_readwrite("alpha_gpdal", &Settings::alpha_gpdal) - .def_readwrite("primal_infeasibility_solving", - &Settings::primal_infeasibility_solving) - .def_readwrite("frequence_infeasibility_check", - &Settings::frequence_infeasibility_check) - .def_readwrite("default_H_eigenvalue_estimate", - &Settings::default_H_eigenvalue_estimate) - .def(pybind11::self == pybind11::self) - .def(pybind11::self != pybind11::self) - .def(pybind11::pickle( - - [](const Settings& settings) { - return pybind11::bytes( - proxsuite::serialization::saveToString(settings)); - }, - [](pybind11::bytes& s) { - Settings settings; - proxsuite::serialization::loadFromString(settings, s); - return settings; - })); + ::nanobind::class_>(m, "Settings") + .def(::nanobind::init(), "Default constructor.") // constructor + .def_rw("default_rho", &Settings::default_rho) + .def_rw("default_mu_eq", &Settings::default_mu_eq) + .def_rw("default_mu_in", &Settings::default_mu_in) + .def_rw("alpha_bcl", &Settings::alpha_bcl) + .def_rw("beta_bcl", &Settings::beta_bcl) + .def_rw("refactor_dual_feasibility_threshold", + &Settings::refactor_dual_feasibility_threshold) + .def_rw("refactor_rho_threshold", &Settings::refactor_rho_threshold) + .def_rw("mu_min_eq", &Settings::mu_min_eq) + .def_rw("mu_min_in", &Settings::mu_min_in) + .def_rw("mu_max_eq_inv", &Settings::mu_max_eq_inv) + .def_rw("mu_max_in_inv", &Settings::mu_max_in_inv) + .def_rw("mu_update_factor", &Settings::mu_update_factor) + .def_rw("cold_reset_mu_eq", &Settings::cold_reset_mu_eq) + .def_rw("cold_reset_mu_in", &Settings::cold_reset_mu_in) + .def_rw("max_iter", &Settings::max_iter) + .def_rw("max_iter_in", &Settings::max_iter_in) + .def_rw("eps_abs", &Settings::eps_abs) + .def_rw("eps_rel", &Settings::eps_rel) + .def_rw("eps_primal_inf", &Settings::eps_primal_inf) + .def_rw("eps_dual_inf", &Settings::eps_dual_inf) + .def_rw("nb_iterative_refinement", &Settings::nb_iterative_refinement) + .def_rw("initial_guess", &Settings::initial_guess) + .def_rw("sparse_backend", &Settings::sparse_backend) + .def_rw("preconditioner_accuracy", &Settings::preconditioner_accuracy) + .def_rw("preconditioner_max_iter", &Settings::preconditioner_max_iter) + .def_rw("compute_timings", &Settings::compute_timings) + .def_rw("compute_preconditioner", &Settings::compute_preconditioner) + .def_rw("update_preconditioner", &Settings::update_preconditioner) + .def_rw("check_duality_gap", &Settings::check_duality_gap) + .def_rw("eps_duality_gap_abs", &Settings::eps_duality_gap_abs) + .def_rw("eps_duality_gap_rel", &Settings::eps_duality_gap_rel) + .def_rw("verbose", &Settings::verbose) + .def_rw("bcl_update", &Settings::bcl_update) + .def_rw("merit_function_type", &Settings::merit_function_type) + .def_rw("alpha_gpdal", &Settings::alpha_gpdal) + .def_rw("primal_infeasibility_solving", + &Settings::primal_infeasibility_solving) + .def_rw("frequence_infeasibility_check", + &Settings::frequence_infeasibility_check) + .def_rw("default_H_eigenvalue_estimate", + &Settings::default_H_eigenvalue_estimate) + .def(nanobind::self == nanobind::self) + .def(nanobind::self != nanobind::self) + .def("__getstate__", + [](const Settings& settings) { + return proxsuite::serialization::saveToString(settings); + }) + .def("__setstate__", [](Settings& settings, nanobind::bytes& s) { + new (&settings) Settings{}; + proxsuite::serialization::loadFromString(settings, s.c_str()); + }); ; } } // namespace python From ad7e215a13bdd0d0874255e303d18276cae2802f Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:06:11 +0200 Subject: [PATCH 043/109] [bindings/python] workspace, model : do pybind11 -> nanobind swap + concerns def_* methods and pickling (now managed manually through setting the relevant special methods) + remove module_local(), as it is not supported in nanobind: https://nanobind.readthedocs.io/en/latest/porting.html#removed-features + ::arg_v() no longer behaves the same. had to strip per-argument docstrings --- bindings/python/src/expose-helpers.hpp | 35 +++---- bindings/python/src/expose-model.hpp | 133 ++++++++++++------------- bindings/python/src/expose-results.hpp | 105 ++++++++++--------- 3 files changed, 130 insertions(+), 143 deletions(-) diff --git a/bindings/python/src/expose-helpers.hpp b/bindings/python/src/expose-helpers.hpp index 6dc8768e5..76cba0e70 100644 --- a/bindings/python/src/expose-helpers.hpp +++ b/bindings/python/src/expose-helpers.hpp @@ -2,9 +2,9 @@ // Copyright (c) 2022 INRIA // -#include -#include -#include +#include +#include +#include #include #include @@ -18,7 +18,7 @@ namespace python { template void -exposeDenseHelpers(pybind11::module_ m) +exposeDenseHelpers(nanobind::module_ m) { m.def( "estimate_minimal_eigen_value_of_symmetric_matrix", @@ -38,17 +38,11 @@ exposeDenseHelpers(pybind11::module_ m) "SelfAdjointEigenSolver from Eigen, " "or a Power Iteration algorithm (with parameters : " "power_iteration_accuracy and nb_power_iteration).", - pybind11::arg("H"), - pybind11::arg_v("estimate_method_option", - EigenValueEstimateMethodOption::ExactMethod, - "Two options are available for " - "estimating smallest eigenvalue: either a power " - "iteration algorithm, or an exact method from Eigen."), - pybind11::arg_v( - "power_iteration_accuracy", T(1.E-3), "power iteration accuracy."), - pybind11::arg_v("nb_power_iteration", - 1000, - "maximal number of power iteration executed.")); + nanobind::arg("H"), + nanobind::arg("estimate_method_option") = + EigenValueEstimateMethodOption::ExactMethod, + nanobind::arg("power_iteration_accuracy") = T(1.E-3), + nanobind::arg("nb_power_iteration") = 1000); } } // namespace python } // namespace dense @@ -59,7 +53,7 @@ namespace python { template void -exposeSparseHelpers(pybind11::module_ m) +exposeSparseHelpers(nanobind::module_ m) { m.def("estimate_minimal_eigen_value_of_symmetric_matrix", &sparse::estimate_minimal_eigen_value_of_symmetric_matrix, @@ -67,12 +61,9 @@ exposeSparseHelpers(pybind11::module_ m) "matrix, " " using aPower Iteration algorithm (with parameters : " "power_iteration_accuracy and nb_power_iteration).", - pybind11::arg("H"), - pybind11::arg_v( - "power_iteration_accuracy", T(1.E-3), "power iteration accuracy."), - pybind11::arg_v("nb_power_iteration", - 1000, - "maximal number of power iteration executed.")); + nanobind::arg("H"), + nanobind::arg("power_iteration_accuracy") = T(1.E-3), + nanobind::arg("nb_power_iteration") = 1000); } } // namespace python diff --git a/bindings/python/src/expose-model.hpp b/bindings/python/src/expose-model.hpp index 7e6da20a8..2b4a37d4a 100644 --- a/bindings/python/src/expose-model.hpp +++ b/bindings/python/src/expose-model.hpp @@ -1,10 +1,10 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // -#include -#include -#include +#include +#include +#include #include #include @@ -19,18 +19,18 @@ namespace dense { namespace python { template void -exposeDenseModel(pybind11::module_ m) +exposeDenseModel(nanobind::module_ m) { - ::pybind11::class_>( - m, "BackwardData", pybind11::module_local()) - .def(::pybind11::init(), "Default constructor.") + ::nanobind::class_>(m, + "BackwardData") + .def(::nanobind::init(), "Default constructor.") .def( "initialize", &proxsuite::proxqp::dense::BackwardData::initialize, - pybind11::arg_v("n", 0, "primal dimension."), - pybind11::arg_v("n_eq", 0, "number of equality constraints."), - pybind11::arg_v("n_in", 0, "number of inequality constraints."), + nanobind::arg("n") = 0, + nanobind::arg("n_eq") = 0, + nanobind::arg("n_in") = 0, "Initialize the jacobians (allocate memory if not already done) and set" " by default their value to zero.") .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dH, "dL_dH.") @@ -41,56 +41,53 @@ exposeDenseModel(pybind11::module_ m) .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_du, "dL_du.") .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dl, "dL_dl.") .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dl, "dL_dl."); - // .def_readonly("dL_dH", &proxsuite::proxqp::dense::BackwardData::dL_dH) - // .def_readonly("dL_dg", &proxsuite::proxqp::dense::BackwardData::dL_dg) - // .def_readonly("dL_dA", &proxsuite::proxqp::dense::BackwardData::dL_dA) - // .def_readonly("dL_db", + // .def_ro("dL_dH", &proxsuite::proxqp::dense::BackwardData::dL_dH) + // .def_ro("dL_dg", &proxsuite::proxqp::dense::BackwardData::dL_dg) + // .def_ro("dL_dA", &proxsuite::proxqp::dense::BackwardData::dL_dA) + // .def_ro("dL_db", // &proxsuite::proxqp::dense::BackwardData::dL_db) - // .def_readonly("dL_dC", + // .def_ro("dL_dC", // &proxsuite::proxqp::dense::BackwardData::dL_dC) - // .def_readonly("dL_du", &proxsuite::proxqp::dense::BackwardData::dL_du) - // .def_readonly("dL_dl", + // .def_ro("dL_du", &proxsuite::proxqp::dense::BackwardData::dL_du) + // .def_ro("dL_dl", // &proxsuite::proxqp::dense::BackwardData::dL_dl) - // .def_readonly("dL_du", &proxsuite::proxqp::dense::BackwardData::dL_du); - // .def_readonly("dL_dse", &proxsuite::proxqp::dense::BackwardData::dL_dse) - // .def_readonly("dL_dsi", + // .def_ro("dL_du", &proxsuite::proxqp::dense::BackwardData::dL_du); + // .def_ro("dL_dse", &proxsuite::proxqp::dense::BackwardData::dL_dse) + // .def_ro("dL_dsi", // &proxsuite::proxqp::dense::BackwardData::dL_dsi); - ::pybind11::class_>(m, "model") - .def(::pybind11::init(), - pybind11::arg_v("n", 0, "primal dimension."), - pybind11::arg_v("n_eq", 0, "number of equality constraints."), - pybind11::arg_v("n_in", 0, "number of inequality constraints."), + ::nanobind::class_>(m, "model") + .def(::nanobind::init(), + nanobind::arg("n") = 0, + nanobind::arg("n_eq") = 0, + nanobind::arg("n_in") = 0, "Constructor using QP model dimensions.") // constructor) - .def_readonly("H", &Model::H) - .def_readonly("g", &Model::g) - .def_readonly("A", &Model::A) - .def_readonly("b", &Model::b) - .def_readonly("C", &Model::C) - .def_readonly("l", &Model::l) - .def_readonly("u", &Model::u) - .def_readonly("dim", &Model::dim) - .def_readonly("n_eq", &Model::n_eq) - .def_readonly("n_in", &Model::n_in) - .def_readonly("n_total", &Model::n_total) - .def_readwrite("backward_data", &Model::backward_data) + .def_ro("H", &Model::H) + .def_ro("g", &Model::g) + .def_ro("A", &Model::A) + .def_ro("b", &Model::b) + .def_ro("C", &Model::C) + .def_ro("l", &Model::l) + .def_ro("u", &Model::u) + .def_ro("dim", &Model::dim) + .def_ro("n_eq", &Model::n_eq) + .def_ro("n_in", &Model::n_in) + .def_ro("n_total", &Model::n_total) + .def_rw("backward_data", &Model::backward_data) .def("is_valid", &Model::is_valid, "Check if model is containing valid data.") - .def(pybind11::self == pybind11::self) - .def(pybind11::self != pybind11::self) - .def(pybind11::pickle( - - [](const proxsuite::proxqp::dense::Model& model) { - return pybind11::bytes(proxsuite::serialization::saveToString(model)); - }, - [](pybind11::bytes& s) { - // create qp model which will be updated by loaded data - proxsuite::proxqp::dense::Model model(1, 1, 1); - proxsuite::serialization::loadFromString(model, s); - - return model; - })); + .def(nanobind::self == nanobind::self) + .def(nanobind::self != nanobind::self) + .def("__getstate__", + [](const proxsuite::proxqp::dense::Model& model) { + return proxsuite::serialization::saveToString(model); + }) + .def("__setstate__", [](dense::Model& model, nanobind::bytes& s) { + // create qp model which will be updated by loaded data + new (&model) dense::Model(1, 1, 1); + proxsuite::serialization::loadFromString(model, s.c_str()); + }); } } // namespace python } // namespace dense @@ -99,24 +96,24 @@ namespace sparse { namespace python { template void -exposeSparseModel(pybind11::module_ m) +exposeSparseModel(nanobind::module_ m) { - ::pybind11::class_>(m, "model") - .def(::pybind11::init(), - pybind11::arg_v("n", 0, "primal dimension."), - pybind11::arg_v("n_eq", 0, "number of equality constraints."), - pybind11::arg_v("n_in", 0, "number of inequality constraints."), + ::nanobind::class_>(m, "model") + .def(::nanobind::init(), + nanobind::arg("n") = 0, + nanobind::arg("n_eq") = 0, + nanobind::arg("n_in") = 0, "Constructor using QP model dimensions.") // constructor) - .def_readonly("g", &Model::g) - .def_readonly("b", &Model::b) - .def_readonly("l", &Model::l) - .def_readonly("u", &Model::u) - .def_readonly("dim", &Model::dim) - .def_readonly("n_eq", &Model::n_eq) - .def_readonly("n_in", &Model::n_in) - .def_readonly("H_nnz", &Model::H_nnz) - .def_readonly("A_nnz", &Model::A_nnz) - .def_readonly("C_nnz", &Model::C_nnz); + .def_ro("g", &Model::g) + .def_ro("b", &Model::b) + .def_ro("l", &Model::l) + .def_ro("u", &Model::u) + .def_ro("dim", &Model::dim) + .def_ro("n_eq", &Model::n_eq) + .def_ro("n_in", &Model::n_in) + .def_ro("H_nnz", &Model::H_nnz) + .def_ro("A_nnz", &Model::A_nnz) + .def_ro("C_nnz", &Model::C_nnz); } } // namespace python } // namespace sparse diff --git a/bindings/python/src/expose-results.hpp b/bindings/python/src/expose-results.hpp index 941cd32b5..a882bfa91 100644 --- a/bindings/python/src/expose-results.hpp +++ b/bindings/python/src/expose-results.hpp @@ -2,15 +2,17 @@ // Copyright (c) 2022-2023 INRIA // #include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include "helpers.hpp" -#include "optional.hpp" namespace proxsuite { namespace proxqp { @@ -18,10 +20,9 @@ namespace python { template void -exposeResults(pybind11::module_ m) +exposeResults(nanobind::module_ m) { - ::pybind11::enum_( - m, "QPSolverOutput", pybind11::module_local()) + ::nanobind::enum_(m, "QPSolverOutput") .value("PROXQP_SOLVED", QPSolverOutput::PROXQP_SOLVED) .value("PROXQP_MAX_ITER_REACHED", QPSolverOutput::PROXQP_MAX_ITER_REACHED) .value("PROXQP_PRIMAL_INFEASIBLE", QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE) @@ -31,40 +32,40 @@ exposeResults(pybind11::module_ m) .value("PROXQP_NOT_RUN", QPSolverOutput::PROXQP_NOT_RUN) .export_values(); - ::pybind11::class_>(m, "Info", pybind11::module_local()) - .def(::pybind11::init(), "Default constructor.") - .def_readwrite("mu_eq", &Info::mu_eq) - .def_readwrite("mu_in", &Info::mu_in) - .def_readwrite("rho", &Info::rho) - .def_readwrite("iter", &Info::iter) - .def_readwrite("iter_ext", &Info::iter_ext) - .def_readwrite("run_time", &Info::run_time) - .def_readwrite("setup_time", &Info::setup_time) - .def_readwrite("solve_time", &Info::solve_time) - .def_readwrite("duality_gap", &Info::duality_gap) - .def_readwrite("pri_res", &Info::pri_res) - .def_readwrite("dua_res", &Info::dua_res) - .def_readwrite("duality_gap", &Info::duality_gap) - .def_readwrite("iterative_residual", &Info::iterative_residual) - .def_readwrite("objValue", &Info::objValue) - .def_readwrite("status", &Info::status) - .def_readwrite("rho_updates", &Info::rho_updates) - .def_readwrite("mu_updates", &Info::mu_updates) - .def_readwrite("sparse_backend", - &Info::sparse_backend, - "Sparse backend used to solve the qp, either SparseCholesky " - "or MatrixFree.") - .def_readwrite("minimal_H_eigenvalue_estimate", - &Info::minimal_H_eigenvalue_estimate, - "By default it equals 0, in order to get an estimate, set " - "appropriately the setting option " - "find_H_minimal_eigenvalue."); + ::nanobind::class_>(m, "Info") + .def(::nanobind::init(), "Default constructor.") + .def_rw("mu_eq", &Info::mu_eq) + .def_rw("mu_in", &Info::mu_in) + .def_rw("rho", &Info::rho) + .def_rw("iter", &Info::iter) + .def_rw("iter_ext", &Info::iter_ext) + .def_rw("run_time", &Info::run_time) + .def_rw("setup_time", &Info::setup_time) + .def_rw("solve_time", &Info::solve_time) + .def_rw("duality_gap", &Info::duality_gap) + .def_rw("pri_res", &Info::pri_res) + .def_rw("dua_res", &Info::dua_res) + .def_rw("duality_gap", &Info::duality_gap) + .def_rw("iterative_residual", &Info::iterative_residual) + .def_rw("objValue", &Info::objValue) + .def_rw("status", &Info::status) + .def_rw("rho_updates", &Info::rho_updates) + .def_rw("mu_updates", &Info::mu_updates) + .def_rw("sparse_backend", + &Info::sparse_backend, + "Sparse backend used to solve the qp, either SparseCholesky " + "or MatrixFree.") + .def_rw("minimal_H_eigenvalue_estimate", + &Info::minimal_H_eigenvalue_estimate, + "By default it equals 0, in order to get an estimate, set " + "appropriately the setting option " + "find_H_minimal_eigenvalue."); - ::pybind11::class_>(m, "Results", pybind11::module_local()) - .def(::pybind11::init(), - pybind11::arg_v("n", 0, "primal dimension."), - pybind11::arg_v("n_eq", 0, "number of equality constraints."), - pybind11::arg_v("n_in", 0, "number of inequality constraints."), + ::nanobind::class_>(m, "Results") + .def(::nanobind::init(), + nanobind::arg("n") = 0, + nanobind::arg("n_eq") = 0, + nanobind::arg("n_in") = 0, "Constructor from QP model dimensions.") // constructor .PROXSUITE_PYTHON_EIGEN_READWRITE(Results, x, "The primal solution.") .PROXSUITE_PYTHON_EIGEN_READWRITE( @@ -83,19 +84,17 @@ exposeResults(pybind11::module_ m) si, "Pptimal shift to the closest feasible " "problem wrt inequality constraints.") - .def_readwrite("info", &Results::info) - .def(pybind11::self == pybind11::self) - .def(pybind11::self != pybind11::self) - .def(pybind11::pickle( - - [](const Results& results) { - return pybind11::bytes(proxsuite::serialization::saveToString(results)); - }, - [](pybind11::bytes& s) { - Results results; - proxsuite::serialization::loadFromString(results, s); - return results; - })); + .def_rw("info", &Results::info) + .def(nanobind::self == nanobind::self) + .def(nanobind::self != nanobind::self) + .def("__getstate__", + [](const Results& results) { + return proxsuite::serialization::saveToString(results); + }) + .def("__setstate__", [](Results& results, nanobind::bytes& s) { + new (&results) Results{}; + proxsuite::serialization::loadFromString(results, s.c_str()); + }); ; } } // namespace python From 54040cd45764fc5f5b53779baedfb06687bf26f9 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:08:34 +0200 Subject: [PATCH 044/109] [bindings/python] remove optional.hpp + nanobind has no out-of-the-box utility for tl::optional AFAIK + nanobind requires C++17 - hence proxsuite will be using std::optional anyway --- bindings/python/src/optional.hpp | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 bindings/python/src/optional.hpp diff --git a/bindings/python/src/optional.hpp b/bindings/python/src/optional.hpp deleted file mode 100644 index bbdd5a153..000000000 --- a/bindings/python/src/optional.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2022 INRIA -// -#ifndef proxsuite_python_optional_hpp -#define proxsuite_python_optional_hpp - -#include -#include -#include - -#if __cplusplus < 201703L -template -struct pybind11::detail::type_caster> - : public pybind11::detail::optional_caster> -{}; - -template<> -struct pybind11::detail::type_caster - : public pybind11::detail::void_caster -{}; -#endif - -#endif // ifndef proxsuite_python_optional_hpp From 16a882528a2880a16fa8206bca8cebd9f9824e36 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:09:08 +0200 Subject: [PATCH 045/109] [bindings/python] expose-solver.hpp : switch to nanobind + this nuked a bunch of argument docstrings... --- bindings/python/src/expose-solve.hpp | 275 +++++++++------------------ 1 file changed, 89 insertions(+), 186 deletions(-) diff --git a/bindings/python/src/expose-solve.hpp b/bindings/python/src/expose-solve.hpp index 038bccaec..8721ba570 100644 --- a/bindings/python/src/expose-solve.hpp +++ b/bindings/python/src/expose-solve.hpp @@ -1,11 +1,12 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // #include #include -#include -#include -#include +#include +#include +#include +#include namespace proxsuite { namespace proxqp { @@ -16,11 +17,11 @@ namespace python { template void -solveDenseQp(pybind11::module_ m) +solveDenseQp(nanobind::module_ m) { m.def( "solve", - pybind11::overload_cast>, + nanobind::overload_cast>, optional>, optional>, optional>, @@ -50,69 +51,36 @@ solveDenseQp(pybind11::module_ m) "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " "preconditioner execution).", - pybind11::arg_v("H", nullopt, "quadratic cost with dense format."), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v( - "A", nullopt, "equality constraint matrix with dense format."), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v( - "C", nullopt, "inequality constraint matrix with dense format."), - pybind11::arg_v("l", nullopt, "lower inequality constraint vector"), - pybind11::arg_v("u", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("x", nullopt, "primal warm start"), - pybind11::arg_v("y", nullopt, "dual equality warm start"), - pybind11::arg_v("z", nullopt, "dual inequality warm start"), - pybind11::arg_v( - "eps_abs", - nullopt, - "absolute accuracy level used for the solver stopping criterion."), - pybind11::arg_v("eps_rel", - nullopt, - "relative accuracy level used for the solver stopping " - "criterion. Deactivated in standard settings."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("verbose", - nullopt, - "verbose option to print information at each iteration."), - pybind11::arg_v("compute_preconditioner", - true, - "executes the default preconditioner for reducing ill " - "conditioning and speeding up the solver."), - 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::EQUALITY_CONSTRAINED_INITIAL_GUESS, - "maximum number of iteration."), - pybind11::arg_v( - "check_duality_gap", - false, - "if set to true, include the duality gap in absolute and relative " - "stopping criteria."), - pybind11::arg_v("eps_duality_gap_abs", - nullopt, - "absolute accuracy threshold used for the duality-gap " - "stopping criterion."), - pybind11::arg_v("eps_duality_gap_rel", - nullopt, - "relative accuracy threshold used for the duality-gap " - "stopping criterion."), - pybind11::arg_v("primal_infeasibility_solving", - false, - "solves the closest feasible problem in L2 sense " - "if the QP problem appears to be infeasible."), - pybind11::arg_v("default_H_eigenvalue_estimate", - 0., - "Default estimate of the minimal eigen value of H.")); + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("x") = nullopt, + nanobind::arg("y") = nullopt, + nanobind::arg("z") = nullopt, + nanobind::arg("eps_abs") = nullopt, + nanobind::arg("eps_rel") = nullopt, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("verbose") = nullopt, + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("compute_timings") = false, + nanobind::arg("max_iter") = nullopt, + nanobind::arg("initial_guess") = + InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, + nanobind::arg("check_duality_gap") = false, + nanobind::arg("eps_duality_gap_abs") = nullopt, + nanobind::arg("eps_duality_gap_rel") = nullopt, + nanobind::arg("primal_infeasibility_solving") = false, + nanobind::arg("default_H_eigenvalue_estimate") = 0.); m.def( "solve", - pybind11::overload_cast>, + nanobind::overload_cast>, optional>, optional>, optional>, @@ -144,67 +112,34 @@ solveDenseQp(pybind11::module_ m) "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " "preconditioner execution).", - pybind11::arg_v("H", nullopt, "quadratic cost with dense format."), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v( - "A", nullopt, "equality constraint matrix with dense format."), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v( - "C", nullopt, "inequality constraint matrix with dense format."), - pybind11::arg_v("l", nullopt, "lower inequality constraint vector"), - pybind11::arg_v("u", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("l_box", nullopt, "lower box inequality constraint vector"), - pybind11::arg_v("u_box", nullopt, "upper box inequality constraint vector"), - pybind11::arg_v("x", nullopt, "primal warm start"), - pybind11::arg_v("y", nullopt, "dual equality warm start"), - pybind11::arg_v("z", nullopt, "dual inequality warm start"), - pybind11::arg_v( - "eps_abs", - nullopt, - "absolute accuracy level used for the solver stopping criterion."), - pybind11::arg_v("eps_rel", - nullopt, - "relative accuracy level used for the solver stopping " - "criterion. Deactivated in standard settings."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("verbose", - nullopt, - "verbose option to print information at each iteration."), - pybind11::arg_v("compute_preconditioner", - true, - "executes the default preconditioner for reducing ill " - "conditioning and speeding up the solver."), - 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", + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("l_box") = nullopt, + nanobind::arg("u_box") = nullopt, + nanobind::arg("x") = nullopt, + nanobind::arg("y") = nullopt, + nanobind::arg("z") = nullopt, + nanobind::arg("eps_abs") = nullopt, + nanobind::arg("eps_rel") = nullopt, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("verbose") = nullopt, + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("compute_timings") = false, + nanobind::arg("max_iter") = nullopt, + nanobind::arg("initial_guess") = proxsuite::proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, - "maximum number of iteration."), - pybind11::arg_v( - "check_duality_gap", - false, - "if set to true, include the duality gap in absolute and relative " - "stopping criteria."), - pybind11::arg_v("eps_duality_gap_abs", - nullopt, - "absolute accuracy threshold used for the duality-gap " - "stopping criterion."), - pybind11::arg_v("eps_duality_gap_rel", - nullopt, - "relative accuracy threshold used for the duality-gap " - "stopping criterion."), - pybind11::arg_v("primal_infeasibility_solving", - false, - "solves the closest feasible problem in L2 sense " - "if the QP problem appears to be infeasible."), - pybind11::arg_v("default_H_eigenvalue_estimate", - 0., - "Default estimate of the minimal eigen value of H.")); + nanobind::arg("check_duality_gap") = false, + nanobind::arg("eps_duality_gap_abs") = nullopt, + nanobind::arg("eps_duality_gap_rel") = nullopt, + nanobind::arg("primal_infeasibility_solving") = false, + nanobind::arg("default_H_eigenvalue_estimate") = 0.); } } // namespace python @@ -215,7 +150,7 @@ namespace python { template void -solveSparseQp(pybind11::module_ m) +solveSparseQp(nanobind::module_ m) { m.def( "solve", @@ -225,65 +160,33 @@ solveSparseQp(pybind11::module_ m) "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " "preconditioner execution).", - pybind11::arg_v("H", nullopt, "quadratic cost with sparse format."), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v( - "A", nullopt, "equality constraint matrix with sparse format."), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v( - "C", nullopt, "inequality constraint matrix with sparse format."), - pybind11::arg_v("l", nullopt, "lower inequality constraint vector"), - pybind11::arg_v("u", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("x", nullopt, "primal warm start"), - pybind11::arg_v("y", nullopt, "dual equality warm start"), - pybind11::arg_v("z", nullopt, "dual inequality warm start"), - pybind11::arg_v( - "eps_abs", - nullopt, - "absolute accuracy level used for the solver stopping criterion."), - pybind11::arg_v("eps_rel", - nullopt, - "relative accuracy level used for the solver stopping " - "criterion. Deactivated in standard settings."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("verbose", - nullopt, - "verbose option to print information at each iteration."), - pybind11::arg_v("compute_preconditioner", - true, - "executes the default preconditioner for reducing ill " - "conditioning and speeding up the solver."), - 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:: - EQUALITY_CONSTRAINED_INITIAL_GUESS), - pybind11::arg_v("sparse_backend", - proxsuite::proxqp::SparseBackend::Automatic), - pybind11::arg_v("check_duality_gap", - false, - "if set to true, include the duality gap in absolute and " - "relative stopping criteria."), - pybind11::arg_v("eps_duality_gap_abs", - nullopt, - "absolute accuracy threshold used for the duality-gap " - "stopping criterion."), - pybind11::arg_v("eps_duality_gap_rel", - nullopt, - "relative accuracy threshold used for the duality-gap " - "stopping criterion."), - pybind11::arg_v("primal_infeasibility_solving", - false, - "solves the closest feasible problem in L2 sense " - "if the QP problem appears to be infeasible."), - pybind11::arg_v("default_H_eigenvalue_estimate", - 0., - "Default estimate of the minimal eigen value of H.")); + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("x") = nullopt, + nanobind::arg("y") = nullopt, + nanobind::arg("z") = nullopt, + nanobind::arg("eps_abs") = nullopt, + nanobind::arg("eps_rel") = nullopt, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("verbose") = nullopt, + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("compute_timings") = false, + nanobind::arg("max_iter") = nullopt, + nanobind::arg("initial_guess") = + InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, + nanobind::arg("sparse_backend") = SparseBackend::Automatic, + nanobind::arg("check_duality_gap") = false, + nanobind::arg("eps_duality_gap_abs") = nullopt, + nanobind::arg("eps_duality_gap_rel") = nullopt, + nanobind::arg("primal_infeasibility_solving") = false, + nanobind::arg("default_H_eigenvalue_estimate") = 0.); } } // namespace python From 97909b416d4f9d26372ab4137d0d0cee70e630cd Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:09:42 +0200 Subject: [PATCH 046/109] [bindings/python] expose-{backward,parallel,qpobject}.hpp : switch to nanobind + this nuked a bunch of argument docstrings... --- bindings/python/src/expose-backward.hpp | 31 +- bindings/python/src/expose-parallel.hpp | 120 +++----- bindings/python/src/expose-qpobject.hpp | 381 ++++++++++-------------- 3 files changed, 215 insertions(+), 317 deletions(-) diff --git a/bindings/python/src/expose-backward.hpp b/bindings/python/src/expose-backward.hpp index 85716ece7..29db4b553 100644 --- a/bindings/python/src/expose-backward.hpp +++ b/bindings/python/src/expose-backward.hpp @@ -5,9 +5,9 @@ #include #include #include "proxsuite/proxqp/dense/compute_ECJ.hpp" -#include -#include -#include +#include +#include +#include namespace proxsuite { namespace proxqp { @@ -18,23 +18,16 @@ namespace python { template void -backward(pybind11::module_ m) +backward(nanobind::module_ m) { - m.def( - "compute_backward", - &compute_backward, - "Function for computing derivatives of solved QP.", - pybind11::arg_v("qp", "Solved dense QP."), - pybind11::arg_v("loss_derivative", "Derivate of loss wrt to qp solution."), - pybind11::arg_v( - "eps", 1e-4, "Backward pass accuracy for deriving solution Jacobians."), - pybind11::arg_v("rho_backward", - 1e-6, - "New primal proximal parameter for iterative refinement."), - pybind11::arg_v("mu_backward", - 1e-6, - "New dual proximal parameter used both for inequality and " - "equality for iterative refinement.")); + m.def("compute_backward", + &compute_backward, + "Function for computing derivatives of solved QP.", + nanobind::arg("qp"), + nanobind::arg("loss_derivative"), + nanobind::arg("eps") = 1e-4, + nanobind::arg("rho_backward") = 1e-6, + nanobind::arg("mu_backward") = 1e-6); } } // namespace python diff --git a/bindings/python/src/expose-parallel.hpp b/bindings/python/src/expose-parallel.hpp index 9b90186b7..11ffaa2d0 100644 --- a/bindings/python/src/expose-parallel.hpp +++ b/bindings/python/src/expose-parallel.hpp @@ -5,13 +5,13 @@ #include #include #include -#include -#include -#include -#include // For binding STL containers +#include +#include +#include +#include -PYBIND11_MAKE_OPAQUE(std::vector>) -PYBIND11_MAKE_OPAQUE(std::vector>) +NB_MAKE_OPAQUE(std::vector>) +NB_MAKE_OPAQUE(std::vector>) namespace proxsuite { namespace proxqp { using proxsuite::linalg::veg::isize; @@ -21,86 +21,65 @@ namespace python { template void -solveDenseQpParallel(pybind11::module_ m) +solveDenseQpParallel(nanobind::module_ m) { - pybind11::bind_vector>>( + nanobind::bind_vector>>( m, "VectorLossDerivatives"); - pybind11::bind_vector>>( + nanobind::bind_vector>>( m, "VectorQP"); m.def("solve_in_parallel", - pybind11::overload_cast>&, + nanobind::overload_cast>&, const optional>(&solve_in_parallel), "Function for solving a list of dense QPs in parallel.", - pybind11::arg_v("qps", "List of initialized dense Qps."), - pybind11::arg_v("num_threads", - nullopt, - "number of threads used for the computation.")); + nanobind::arg("qps"), + nanobind::arg("num_threads") = nullopt); m.def( "solve_in_parallel", - pybind11::overload_cast&, const optional>( + nanobind::overload_cast&, const optional>( &solve_in_parallel), "Function for solving a list of dense QPs in parallel.", - pybind11::arg_v("qps", "List of initialized dense Qps."), - pybind11::arg_v( - "num_threads", nullopt, "number of threads used for the computation.")); + nanobind::arg("qps"), + nanobind::arg("num_threads") = nullopt); // m.def("solve_in_parallel", // &qp_solve_in_parallel, // "Function for solving a list of dense QPs in parallel.", - // pybind11::arg_v("num_threads", - // nullopt, - // "number of threads used for the computation."), - // pybind11::arg_v("qps", "List of initialized dense Qps.")); + // nanobind::arg("num_threads") = nullopt, + // nanobind::arg("qps")); - m.def( - "solve_backward_in_parallel", - pybind11::overload_cast, - proxqp::dense::BatchQP&, - std::vector>&, - T, - T, - T>(&qp_solve_backward_in_parallel), - "Function for solving a list of dense QPs in parallel.", - pybind11::arg_v( - "num_threads", nullopt, "number of threads used for the computation."), - pybind11::arg_v("qps", "List of initialized dense Qps."), - pybind11::arg_v("loss_derivatives", "List of loss derivatives."), - pybind11::arg_v( - "eps", 1e-4, "Backward pass accuracy for deriving solution Jacobians."), - pybind11::arg_v("rho_backward", - 1e-6, - "New primal proximal parameter for iterative refinement."), - pybind11::arg_v("mu_backward", - 1e-6, - "New dual proximal parameter used both for inequality " - "and equality for iterative refinement.")); + m.def("solve_backward_in_parallel", + nanobind::overload_cast, + proxqp::dense::BatchQP&, + std::vector>&, + T, + T, + T>(&qp_solve_backward_in_parallel), + "Function for solving a list of dense QPs in parallel.", + nanobind::arg("num_threads") = nullopt, + nanobind::arg("qps"), + nanobind::arg("loss_derivatives"), + nanobind::arg("eps") = 1e-4, + nanobind::arg("rho_backward") = 1e-6, + nanobind::arg("mu_backward") = 1e-6); - m.def( - "solve_backward_in_parallel", - pybind11::overload_cast, - std::vector>&, - std::vector>&, - T, - T, - T>(&qp_solve_backward_in_parallel), - "Function for solving a list of dense QPs in parallel.", - pybind11::arg_v( - "num_threads", nullopt, "number of threads used for the computation."), - pybind11::arg_v("qps", "List of initialized dense Qps."), - pybind11::arg_v("loss_derivatives", "List of loss derivatives."), - pybind11::arg_v( - "eps", 1e-4, "Backward pass accuracy for deriving solution Jacobians."), - pybind11::arg_v("rho_backward", - 1e-6, - "New primal proximal parameter for iterative refinement."), - pybind11::arg_v("mu_backward", - 1e-6, - "New dual proximal parameter used both for inequality and " - "equality for iterative refinement.")); + m.def("solve_backward_in_parallel", + nanobind::overload_cast, + std::vector>&, + std::vector>&, + T, + T, + T>(&qp_solve_backward_in_parallel), + "Function for solving a list of dense QPs in parallel.", + nanobind::arg("num_threads") = nullopt, + nanobind::arg("qps"), + nanobind::arg("loss_derivatives"), + nanobind::arg("eps") = 1e-4, + nanobind::arg("rho_backward") = 1e-6, + nanobind::arg("mu_backward") = 1e-6); } } // namespace python @@ -110,16 +89,15 @@ namespace sparse { namespace python { template void -solveSparseQpParallel(pybind11::module_ m) +solveSparseQpParallel(nanobind::module_ m) { m.def( "solve_in_parallel", - pybind11::overload_cast&, + nanobind::overload_cast&, const optional>(&solve_in_parallel), "Function for solving a list of sparse QPs in parallel.", - pybind11::arg_v("qps", "List of initialized sparse Qps."), - pybind11::arg_v( - "num_threads", nullopt, "number of threads used for the computation.")); + nanobind::arg("qps"), + nanobind::arg("num_threads") = nullopt); } } // namespace python diff --git a/bindings/python/src/expose-qpobject.hpp b/bindings/python/src/expose-qpobject.hpp index f6824ed26..70e22f2b6 100644 --- a/bindings/python/src/expose-qpobject.hpp +++ b/bindings/python/src/expose-qpobject.hpp @@ -1,10 +1,11 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // -#include -#include -#include +#include +#include +#include +#include #include #include @@ -22,72 +23,62 @@ namespace python { template void -exposeQpObjectDense(pybind11::module_ m) +exposeQpObjectDense(nanobind::module_ m) { - ::pybind11::enum_(m, "DenseBackend", pybind11::module_local()) + ::nanobind::enum_(m, "DenseBackend") .value("Automatic", DenseBackend::Automatic) .value("PrimalDualLDLT", DenseBackend::PrimalDualLDLT) .value("PrimalLDLT", DenseBackend::PrimalLDLT) .export_values(); - ::pybind11::enum_(m, "HessianType", pybind11::module_local()) + ::nanobind::enum_(m, "HessianType") .value("Dense", proxsuite::proxqp::HessianType::Dense) .value("Zero", proxsuite::proxqp::HessianType::Zero) .value("Diagonal", proxsuite::proxqp::HessianType::Diagonal) .export_values(); - // ::pybind11::class_>(m, - // "ruiz", pybind11::module_local()) - // .def(::pybind11::init(), "Default constructor.") - // .def_readwrite("mu_eq", &RuizEquilibration::delta) - // .def_readwrite("mu_in", &RuizEquilibration::c) - // .def_readwrite("rho", &RuizEquilibration::dim) - // .def_readwrite("iter", &RuizEquilibration::epsilon) - // .def_readwrite("iter_ext", &RuizEquilibration::max_iter) - // .def_readwrite("run_time", &RuizEquilibration::sym); + // ::nanobind::class_>(m, + // "ruiz") + // .def(::nanobind::init(), "Default constructor.") + // .def_rw("mu_eq", &RuizEquilibration::delta) + // .def_rw("mu_in", &RuizEquilibration::c) + // .def_rw("rho", &RuizEquilibration::dim) + // .def_rw("iter", &RuizEquilibration::epsilon) + // .def_rw("iter_ext", &RuizEquilibration::max_iter) + // .def_rw("run_time", &RuizEquilibration::sym); - // ::pybind11::class_>(m, - // "ruiz", pybind11::module_local()) - // .def(::pybind11::init(), "Default constructor.") - // .def_readwrite("mu_eq", &RuizEquilibration::delta) - // .def_readwrite("mu_in", &RuizEquilibration::c) - // .def_readwrite("rho", &RuizEquilibration::dim) - // .def_readwrite("iter", &RuizEquilibration::epsilon) - // .def_readwrite("iter_ext", &RuizEquilibration::max_iter) - // .def_readwrite("run_time", &RuizEquilibration::sym); + // ::nanobind::class_>(m, + // "ruiz") + // .def(::nanobind::init(), "Default constructor.") + // .def_rw("mu_eq", &RuizEquilibration::delta) + // .def_rw("mu_in", &RuizEquilibration::c) + // .def_rw("rho", &RuizEquilibration::dim) + // .def_rw("iter", &RuizEquilibration::epsilon) + // .def_rw("iter_ext", &RuizEquilibration::max_iter) + // .def_rw("run_time", &RuizEquilibration::sym); - ::pybind11::class_>(m, "QP") - .def( - ::pybind11::init(), - pybind11::arg_v("n", 0, "primal dimension."), - pybind11::arg_v("n_eq", 0, "number of equality constraints."), - pybind11::arg_v("n_in", 0, "number of inequality constraints."), - pybind11::arg_v( - "box_constraints", - false, - "specify or not that the QP has box inequality constraints."), - pybind11::arg_v("hessian_type", - proxsuite::proxqp::HessianType::Dense, - "specify the problem type to be solved."), - pybind11::arg_v("dense_backend", - proxsuite::proxqp::DenseBackend::Automatic, - "specify which backend using for solving the problem."), - "Default constructor using QP model dimensions.") // constructor - .def_readwrite( - "results", - &dense::QP::results, - "class containing the solution or certificate of infeasibility, " - "and " - "information statistics in an info subclass.") - .def_readwrite( - "settings", &dense::QP::settings, "Settings of the solver.") - .def_readwrite( - "model", &dense::QP::model, "class containing the QP model") + ::nanobind::class_>(m, "QP") + .def(::nanobind::init(), + nanobind::arg("n") = 0, + nanobind::arg("n_eq") = 0, + nanobind::arg("n_in") = 0, + nanobind::arg("box_constraints") = false, + nanobind::arg("hessian_type") = proxsuite::proxqp::HessianType::Dense, + nanobind::arg("dense_backend") = + proxsuite::proxqp::DenseBackend::Automatic, + "Default constructor using QP model dimensions.") // constructor + .def_rw("results", + &dense::QP::results, + "class containing the solution or certificate of infeasibility, " + "and " + "information statistics in an info subclass.") + .def_rw("settings", &dense::QP::settings, "Settings of the solver.") + .def_rw("model", &dense::QP::model, "class containing the QP model") .def("is_box_constrained", &dense::QP::is_box_constrained, "precise whether or not the QP is designed with box constraints.") @@ -111,26 +102,18 @@ exposeQpObjectDense(pybind11::module_ m) optional, optional)>(&dense::QP::init), "function for initialize the QP model.", - pybind11::arg_v("H", nullopt, "quadratic cost"), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v("A", nullopt, "equality constraint matrix"), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v("C", nullopt, "inequality constraint matrix"), - pybind11::arg_v("l", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("u", nullopt, "lower inequality constraint vector"), - pybind11::arg_v("compute_preconditioner", - true, - "execute the preconditioner for reducing " - "ill-conditioning and speeding up solver execution."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("manual_minimal_H_eigenvalue", - nullopt, - "manual minimal H eigenvalue proposed to regularize H" - " in case it is non convex.")) + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) .def("init", static_cast::*)(optional>, optional>, @@ -147,30 +130,20 @@ exposeQpObjectDense(pybind11::module_ m) optional, optional)>(&dense::QP::init), "function for initialize the QP model.", - pybind11::arg_v("H", nullopt, "quadratic cost"), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v("A", nullopt, "equality constraint matrix"), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v("C", nullopt, "inequality constraint matrix"), - pybind11::arg_v("l", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("u", nullopt, "lower inequality constraint vector"), - pybind11::arg_v( - "l_box", nullopt, "upper box inequality constraint vector"), - pybind11::arg_v( - "u_box", nullopt, "lower box inequality constraint vector"), - pybind11::arg_v("compute_preconditioner", - true, - "execute the preconditioner for reducing " - "ill-conditioning and speeding up solver execution."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("manual_minimal_H_eigenvalue", - nullopt, - "manual minimal H eigenvalue proposed to regularize H" - " in case it is non convex.")) + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("l_box") = nullopt, + nanobind::arg("u_box") = nullopt, + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) .def("solve", static_cast::*)()>(&dense::QP::solve), "function used for solving the QP problem, using default parameters.") @@ -197,28 +170,18 @@ exposeQpObjectDense(pybind11::module_ m) optional)>(&dense::QP::update), "function used for updating matrix or vector entry of the model using " "dense matrix entries.", - pybind11::arg_v("H", nullopt, "quadratic cost"), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v("A", nullopt, "equality constraint matrix"), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v("C", nullopt, "inequality constraint matrix"), - pybind11::arg_v("l", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("u", nullopt, "lower inequality constraint vector"), - pybind11::arg_v( - "update_preconditioner", - false, - "update the preconditioner considering new matrices entries for " - "reducing ill-conditioning and speeding up solver execution. If set up " - "to false, use previous derived preconditioner."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("manual_minimal_H_eigenvalue", - nullopt, - "manual minimal H eigenvalue proposed to regularize H" - " in case it is non convex.")) + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("update_preconditioner") = false, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) .def( "update", static_cast::*)(optional>, @@ -237,48 +200,34 @@ exposeQpObjectDense(pybind11::module_ m) optional)>(&dense::QP::update), "function used for updating matrix or vector entry of the model using " "dense matrix entries.", - pybind11::arg_v("H", nullopt, "quadratic cost"), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v("A", nullopt, "equality constraint matrix"), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v("C", nullopt, "inequality constraint matrix"), - pybind11::arg_v("l", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("u", nullopt, "lower inequality constraint vector"), - pybind11::arg_v( - "l_box", nullopt, "upper box inequality constraint vector"), - pybind11::arg_v( - "u_box", nullopt, "lower box inequality constraint vector"), - pybind11::arg_v( - "update_preconditioner", - false, - "update the preconditioner considering new matrices entries for " - "reducing ill-conditioning and speeding up solver execution. If set up " - "to false, use previous derived preconditioner."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("manual_minimal_H_eigenvalue", - nullopt, - "manual minimal H eigenvalue proposed to regularize H" - " in case it is non convex.")) + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("l_box") = nullopt, + nanobind::arg("u_box") = nullopt, + nanobind::arg("update_preconditioner") = false, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) .def("cleanup", &dense::QP::cleanup, "function used for cleaning the workspace and result " "classes.") - .def(pybind11::self == pybind11::self) - .def(pybind11::self != pybind11::self) - .def(pybind11::pickle( - - [](const dense::QP& qp) { - return pybind11::bytes(proxsuite::serialization::saveToString(qp)); - }, - [](pybind11::bytes& s) { - proxsuite::proxqp::dense::QP qp(1, 1, 1); - proxsuite::serialization::loadFromString(qp, s); - return qp; - })); + .def(nanobind::self == nanobind::self) + .def(nanobind::self != nanobind::self) + .def("__getstate__", + [](const dense::QP& qp) { + return proxsuite::serialization::saveToString(qp); + }) + .def("__setstate__", [](dense::QP& qp, nanobind::bytes& s) { + new (&qp) dense::QP(1, 1, 1); + proxsuite::serialization::loadFromString(qp, s.c_str()); + }); ; } } // namespace python @@ -290,84 +239,62 @@ namespace python { template void -exposeQpObjectSparse(pybind11::module_ m) +exposeQpObjectSparse(nanobind::module_ m) { - ::pybind11::class_>(m, "QP") //,pybind11::module_local() - .def(::pybind11::init(), - pybind11::arg_v("n", 0, "primal dimension."), - pybind11::arg_v("n_eq", 0, "number of equality constraints."), - pybind11::arg_v("n_in", 0, "number of inequality constraints."), + ::nanobind::class_>(m, "QP") + .def(::nanobind::init(), + nanobind::arg("n") = 0, + nanobind::arg("n_eq") = 0, + nanobind::arg("n_in") = 0, "Constructor using QP model dimensions.") // constructor - .def( - ::pybind11::init&, - const sparse::SparseMat&, - const sparse::SparseMat&>(), - pybind11::arg_v("H_mask", nullopt, "mask of the quadratic cost."), - pybind11::arg_v( - "A_mask", nullopt, "mask of the equality constraint matrix."), - pybind11::arg_v("C_mask", 0, "mask of the inequality constraint matrix."), - "Constructor using QP model sparsity structure.") // constructor - .def_readwrite( - "model", &sparse::QP::model, "class containing the QP model") - .def_readwrite( - "results", - &sparse::QP::results, - "class containing the solution or certificate of infeasibility, " - "and " - "information statistics in an info subclass.") - .def_readwrite( - "settings", &sparse::QP::settings, "Settings of the solver.") + .def(::nanobind::init&, + const sparse::SparseMat&, + const sparse::SparseMat&>(), + nanobind::arg("H_mask") = nullopt, + nanobind::arg("A_mask") = nullopt, + nanobind::arg("C_mask") = 0, + "Constructor using QP model sparsity structure.") // constructor + .def_ro("model", &sparse::QP::model, "class containing the QP model") + .def_rw("results", + &sparse::QP::results, + "class containing the solution or certificate of infeasibility, " + "and " + "information statistics in an info subclass.") + .def_rw("settings", &sparse::QP::settings, "Settings of the solver.") .def("init", &sparse::QP::init, "function for initializing the model when passing sparse matrices in " "entry.", - pybind11::arg_v("H", nullopt, "quadratic cost"), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v("A", nullopt, "equality constraint matrix"), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v("C", nullopt, "inequality constraint matrix"), - pybind11::arg_v("l", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("u", nullopt, "lower inequality constraint vector"), - pybind11::arg_v("compute_preconditioner", - true, - "execute the preconditioner for reducing " - "ill-conditioning and speeding up solver execution."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("manual_minimal_H_eigenvalue", - nullopt, - "manual minimal H eigenvalue proposed to regularize H" - " in case it is non convex.")) + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) .def("update", &sparse::QP::update, "function for updating the model when passing sparse matrices in " "entry.", - pybind11::arg_v("H", nullopt, "quadratic cost"), - pybind11::arg_v("g", nullopt, "linear cost"), - pybind11::arg_v("A", nullopt, "equality constraint matrix"), - pybind11::arg_v("b", nullopt, "equality constraint vector"), - pybind11::arg_v("C", nullopt, "inequality constraint matrix"), - pybind11::arg_v("l", nullopt, "upper inequality constraint vector"), - pybind11::arg_v("u", nullopt, "lower inequality constraint vector"), - pybind11::arg_v( - "update_preconditioner", - false, - "update the preconditioner or re-use previous derived for reducing " - "ill-conditioning and speeding up solver execution."), - pybind11::arg_v("rho", nullopt, "primal proximal parameter"), - pybind11::arg_v( - "mu_eq", nullopt, "dual equality constraint proximal parameter"), - pybind11::arg_v( - "mu_in", nullopt, "dual inequality constraint proximal parameter"), - pybind11::arg_v("manual_minimal_H_eigenvalue", - nullopt, - "manual minimal H eigenvalue proposed to regularize H" - " in case it is non convex.")) + nanobind::arg("H") = nullopt, + nanobind::arg("g") = nullopt, + nanobind::arg("A") = nullopt, + nanobind::arg("b") = nullopt, + nanobind::arg("C") = nullopt, + nanobind::arg("l") = nullopt, + nanobind::arg("u") = nullopt, + nanobind::arg("update_preconditioner") = false, + nanobind::arg("rho") = nullopt, + nanobind::arg("mu_eq") = nullopt, + nanobind::arg("mu_in") = nullopt, + nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) .def("solve", static_cast::*)()>(&sparse::QP::solve), "function used for solving the QP problem, using default parameters.") From 520afabdb218f04a328b7ca0229c0840fa4b3473 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 5 Aug 2024 20:10:51 +0200 Subject: [PATCH 047/109] [bindings/python] expose-qpvector.hpp : upgrade to nanobind + change pybind11::return_value_policy to nanobind::rv_policy when relevant + include the nanobind header here (helps for IDEs) + change ctor init types from i64 to u64 -> nanobind is STRICT when it comes to integer signedness conversions --- bindings/python/src/expose-qpvector.hpp | 27 ++++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/bindings/python/src/expose-qpvector.hpp b/bindings/python/src/expose-qpvector.hpp index 06abf8b35..1b077a4af 100644 --- a/bindings/python/src/expose-qpvector.hpp +++ b/bindings/python/src/expose-qpvector.hpp @@ -3,6 +3,9 @@ // #include +#include + +#include namespace proxsuite { namespace proxqp { @@ -13,17 +16,17 @@ namespace python { template void -exposeQPVectorDense(pybind11::module_ m) +exposeQPVectorDense(nanobind::module_ m) { - ::pybind11::class_>(m, "BatchQP") + ::nanobind::class_>(m, "BatchQP") .def( - ::pybind11::init(), - pybind11::arg_v("batch_size", 0, "number of QPs to be stored."), + ::nanobind::init(), + nanobind::arg("batch_size") = 0, "Default constructor using the BatchSize of qp models to store.") // constructor .def("init_qp_in_place", &dense::BatchQP::init_qp_in_place, - pybind11::return_value_policy::reference, + nanobind::rv_policy::reference, "init a dense QP in place and return a reference to it.") .def("insert", &dense::BatchQP::insert, @@ -32,7 +35,7 @@ exposeQPVectorDense(pybind11::module_ m) .def("get", (dense::QP & (dense::BatchQP::*)(isize)) & dense::BatchQP::get, - pybind11::return_value_policy::reference, + nanobind::rv_policy::reference, "get the qp."); } } // namespace python @@ -43,23 +46,23 @@ namespace python { template void -exposeQPVectorSparse(pybind11::module_ m) +exposeQPVectorSparse(nanobind::module_ m) { - ::pybind11::class_>(m, "BatchQP") + ::nanobind::class_>(m, "BatchQP") .def( - ::pybind11::init(), - pybind11::arg_v("batch_size", 0, "number of QPs to be stored."), + ::nanobind::init(), + nanobind::arg("batch_size") = 0, "Default constructor using the BatchSize of qp models to store.") // constructor .def("init_qp_in_place", &sparse::BatchQP::init_qp_in_place, - pybind11::return_value_policy::reference, + nanobind::rv_policy::reference, "init a sparse QP in place and return a reference to it.") .def("size", &sparse::BatchQP::size) .def("get", (sparse::QP & (sparse::BatchQP::*)(isize)) & sparse::BatchQP::get, - pybind11::return_value_policy::reference, + nanobind::rv_policy::reference, "get the qp."); } From 783d88f011d976331b9643851129e839ff178a0f Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 6 Aug 2024 10:12:17 +0200 Subject: [PATCH 048/109] [ci] checkout submodule recursive --- .github/workflows/ci-arch.yml | 2 +- .github/workflows/ci-linux-osx-win-conda.yml | 4 +++- .github/workflows/gh-pages.yml | 4 +++- .github/workflows/release-linux.yml | 4 ++-- .github/workflows/release-osx-win.yml | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-arch.yml b/.github/workflows/ci-arch.yml index 18e21d371..af0cfd2ad 100644 --- a/.github/workflows/ci-arch.yml +++ b/.github/workflows/ci-arch.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v4 with: - submodules: true + submodules: recursive - run: cmake -B build -S . -DBUILD_PYTHON_INTERFACE=ON - run: cmake --build build diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index bdf3af56f..48f32ad21 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -55,7 +55,9 @@ jobs: continue_on_error: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + submodules: recursive - uses: conda-incubator/setup-miniconda@v2 if: matrix.os != 'macos-14' diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index cf9ae190e..c096bd318 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -8,7 +8,9 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + submodules: recursive - uses: conda-incubator/setup-miniconda@v2 with: diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index a47c2526d..54125cbc8 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -33,9 +33,9 @@ jobs: build: "cp312-manylinux*" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: - submodules: 'true' + submodules: recursive - uses: actions/setup-python@v4 with: python-version: "3.10" diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index 351cee208..65f4f91de 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -21,7 +21,7 @@ jobs: toolset: v143 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive From 7de7adf72705f42f89b7d2259ef9babdf6675ddc Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 13:47:05 +0200 Subject: [PATCH 049/109] [bindings/python] cmake : add stub generation (basic) pyproject.toml: add dependency on typing-extensions (required for stubgen on python<3.11) Make stub generation optional --- bindings/python/CMakeLists.txt | 33 +++++++++++++++++++++++++++++++-- pyproject.toml | 1 + 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index d6b3cf216..30d49293e 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -5,6 +5,8 @@ endif() include(${JRL_CMAKE_MODULES}/python.cmake) include(${JRL_CMAKE_MODULES}/python-helpers.cmake) +option(GENERATE_PYTHON_STUBS "Generate Python stubs" OFF) + findpython(REQUIRED Development.Module) find_package(Python 3.8 COMPONENTS ${PYTHON_COMPONENTS}) @@ -54,6 +56,20 @@ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)") TARGETS instructionset EXPORT ${TARGETS_EXPORT_NAME} DESTINATION ${${PYWRAP}_INSTALL_DIR}) + if(GENERATE_PYTHON_STUBS) + nanobind_add_stub( + instructionset_stub + MODULE + instructionset + OUTPUT + instructionset.pyi + PYTHON_PATH + $ + DEPENDS + instructionset) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/instructionset.pyi + DESTINATION ${${PYWRAP}_INSTALL_DIR}) + endif() endif() function(list_filter list regular_expression dest_list) @@ -68,8 +84,7 @@ function(list_filter list regular_expression dest_list) endfunction(list_filter) function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) - nanobind_add_module(${target_name} ${PYWRAP_SOURCES} - ${PYWRAP_HEADERS}) + nanobind_add_module(${target_name} ${PYWRAP_SOURCES} ${PYWRAP_HEADERS}) add_dependencies(${PROJECT_NAME}_python ${target_name}) target_link_libraries(${target_name} PUBLIC ${dependencies}) @@ -121,6 +136,20 @@ function(CREATE_PYTHON_TARGET target_name COMPILE_OPTIONS dependencies) endif() install(TARGETS ${target_name} DESTINATION ${${PYWRAP}_INSTALL_DIR}) + if(GENERATE_PYTHON_STUBS) + nanobind_add_stub( + ${target_name}_stub + MODULE + ${target_name} + OUTPUT + ${target_name}.pyi + PYTHON_PATH + $ + DEPENDS + ${target_name}) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${target_name}.pyi + DESTINATION ${${PYWRAP}_INSTALL_DIR}) + endif() endfunction() if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) diff --git a/pyproject.toml b/pyproject.toml index e40bd4616..3aa236457 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ requires = [ "cmeel[build]", "cmeel-eigen", "cmeel-simde", + "typing-extensions", ] build-backend = "cmeel.build" configure-args = ["-DBUILD_TESTING:BOOL=OFF","-DBUILD_PYTHON_INTERFACE:BOOL=ON","-DBUILD_WITH_VECTORIZATION_SUPPORT:BOOL=ON","-DINSTALL_DOCUMENTATION:BOOL=OFF","-DBUILD_WITH_OPENMP_SUPPORT=OFF"] From bc0e35ab835f8b1f8e382884736f493d94cc4a0f Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 13:50:49 +0200 Subject: [PATCH 050/109] Update CHANGELOG --- CHANGELOG.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7f6fad16..0953075b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Added + +* Stub files for Python bindings, using [nanobind's native support](https://nanobind.readthedocs.io/en/latest/typing.html#stub-generation) ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) + +### Changed + +* Change Python bindings to use nanobind instead of pybind11 ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) + ## [0.6.7] - 2024-08-27 ### Added * Fix mu update function for PrimalLDLT backend ([#349](https://github.com/Simple-Robotics/proxsuite/pull/349)) * Allow use of installed pybind11, 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)) +* Specifically mention that timings are in microseconds ([#342](https://github.com/Simple-Robotics/proxsuite/pull/342)) +* Fix cereal include directory in cmake ([#342](https://github.com/Simple-Robotics/proxsuite/pull/342)) +* Extend doc with hint for conda installation from source ([#342](https://github.com/Simple-Robotics/proxsuite/pull/342)) ### Fixed * Fix inequality constraints return in QPLayer ([#343](https://github.com/Simple-Robotics/proxsuite/pull/343)) From 3ea4718dd5022ff34506509ef8bb2f082496586b Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 18:31:37 +0200 Subject: [PATCH 051/109] [test] dense_qp_solve.py : remove useless line --- test/src/dense_qp_solve.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/src/dense_qp_solve.py b/test/src/dense_qp_solve.py index 6475da821..b26896fd8 100644 --- a/test/src/dense_qp_solve.py +++ b/test/src/dense_qp_solve.py @@ -39,7 +39,6 @@ def generate_mixed_qp(n, seed=1): q = np.random.randn(n) A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality u = A @ v l = -1.0e20 * np.ones(m) From a8256bf1e6f731a343a75f0e73a8824baf6d4446 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 21:58:15 +0200 Subject: [PATCH 052/109] [bindings/python] remove macro PROXSUITE_PYTHON_EIGEN_READWRITE + nanobind handles things well already --- bindings/python/src/expose-model.hpp | 33 +++++------------ bindings/python/src/expose-results.hpp | 51 +++++++++++++++++--------- bindings/python/src/helpers.hpp | 16 -------- 3 files changed, 43 insertions(+), 57 deletions(-) delete mode 100644 bindings/python/src/helpers.hpp diff --git a/bindings/python/src/expose-model.hpp b/bindings/python/src/expose-model.hpp index 2b4a37d4a..3739f26b3 100644 --- a/bindings/python/src/expose-model.hpp +++ b/bindings/python/src/expose-model.hpp @@ -12,7 +12,7 @@ #include #include #include -#include "helpers.hpp" + namespace proxsuite { namespace proxqp { namespace dense { @@ -22,36 +22,23 @@ void exposeDenseModel(nanobind::module_ m) { - ::nanobind::class_>(m, - "BackwardData") + ::nanobind::class_>(m, "BackwardData") .def(::nanobind::init(), "Default constructor.") .def( "initialize", - &proxsuite::proxqp::dense::BackwardData::initialize, + &BackwardData::initialize, nanobind::arg("n") = 0, nanobind::arg("n_eq") = 0, nanobind::arg("n_in") = 0, "Initialize the jacobians (allocate memory if not already done) and set" " by default their value to zero.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dH, "dL_dH.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dg, "dL_dg.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dA, "dL_dA.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_db, "dL_db.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dC, "dL_dC.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_du, "dL_du.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dl, "dL_dl.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(BackwardData, dL_dl, "dL_dl."); - // .def_ro("dL_dH", &proxsuite::proxqp::dense::BackwardData::dL_dH) - // .def_ro("dL_dg", &proxsuite::proxqp::dense::BackwardData::dL_dg) - // .def_ro("dL_dA", &proxsuite::proxqp::dense::BackwardData::dL_dA) - // .def_ro("dL_db", - // &proxsuite::proxqp::dense::BackwardData::dL_db) - // .def_ro("dL_dC", - // &proxsuite::proxqp::dense::BackwardData::dL_dC) - // .def_ro("dL_du", &proxsuite::proxqp::dense::BackwardData::dL_du) - // .def_ro("dL_dl", - // &proxsuite::proxqp::dense::BackwardData::dL_dl) - // .def_ro("dL_du", &proxsuite::proxqp::dense::BackwardData::dL_du); + .def_ro("dL_dH", &BackwardData::dL_dH) + .def_ro("dL_dg", &BackwardData::dL_dg) + .def_ro("dL_dA", &BackwardData::dL_dA) + .def_ro("dL_db", &BackwardData::dL_db) + .def_ro("dL_dC", &BackwardData::dL_dC) + .def_ro("dL_du", &BackwardData::dL_du) + .def_ro("dL_dl", &BackwardData::dL_dl); // .def_ro("dL_dse", &proxsuite::proxqp::dense::BackwardData::dL_dse) // .def_ro("dL_dsi", // &proxsuite::proxqp::dense::BackwardData::dL_dsi); diff --git a/bindings/python/src/expose-results.hpp b/bindings/python/src/expose-results.hpp index a882bfa91..10b2135bd 100644 --- a/bindings/python/src/expose-results.hpp +++ b/bindings/python/src/expose-results.hpp @@ -12,8 +12,6 @@ #include #include -#include "helpers.hpp" - namespace proxsuite { namespace proxqp { namespace python { @@ -67,23 +65,40 @@ exposeResults(nanobind::module_ m) nanobind::arg("n_eq") = 0, nanobind::arg("n_in") = 0, "Constructor from QP model dimensions.") // constructor - .PROXSUITE_PYTHON_EIGEN_READWRITE(Results, x, "The primal solution.") - .PROXSUITE_PYTHON_EIGEN_READWRITE( - Results, - y, - "The dual solution associated to the equality constraints.") - .PROXSUITE_PYTHON_EIGEN_READWRITE( - Results, - z, - "The dual solution associated to the inequality constraints.") - .PROXSUITE_PYTHON_EIGEN_READWRITE( - Results, - se, + // .PROXSUITE_PYTHON_EIGEN_READWRITE(Results, x, "The primal solution.") + // .PROXSUITE_PYTHON_EIGEN_READWRITE( + // Results, + // y, + // "The dual solution associated to the equality constraints.") + // .PROXSUITE_PYTHON_EIGEN_READWRITE( + // Results, + // z, + // "The dual solution associated to the inequality constraints.") + // .PROXSUITE_PYTHON_EIGEN_READWRITE( + // Results, + // se, + // "Optimal shift to the closest feasible problem wrt equality + // constraints.") + // .PROXSUITE_PYTHON_EIGEN_READWRITE(Results, + // si, + // "Optimal shift to the closest feasible + // " "problem wrt inequality + // constraints.") + .def_rw("x", &Results::x, "The primal solution.") + .def_rw("y", + &Results::y, + "The dual solution associated to the equality constraints.") + .def_rw("z", + &Results::z, + "The dual solution associated to the inequality constraints.") + .def_rw( + "se", + &Results::se, "Optimal shift to the closest feasible problem wrt equality constraints.") - .PROXSUITE_PYTHON_EIGEN_READWRITE(Results, - si, - "Pptimal shift to the closest feasible " - "problem wrt inequality constraints.") + .def_rw("si", + &Results::si, + "Optimal shift to the closest feasible problem wrt inequality " + "constraints.") .def_rw("info", &Results::info) .def(nanobind::self == nanobind::self) .def(nanobind::self != nanobind::self) diff --git a/bindings/python/src/helpers.hpp b/bindings/python/src/helpers.hpp deleted file mode 100644 index fc7c37de6..000000000 --- a/bindings/python/src/helpers.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (c) 2022 INRIA -// -#ifndef proxsuite_python_helpers_hpp -#define proxsuite_python_helpers_hpp - -#define PROXSUITE_PYTHON_EIGEN_READWRITE(class, field_name, doc) \ - def_prop_rw( \ - #field_name, \ - [](class& self) { return self.field_name; }, \ - [](class& self, const decltype(class ::field_name)& value) { \ - self.field_name = value; \ - }, \ - doc) - -#endif // ifndef proxsuite_python_helpers_hpp From aaeca09f7e19b4b0fcf4bd056b9eed00d05ae0c2 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 22:08:19 +0200 Subject: [PATCH 053/109] [test] fix bare except --- test/src/serialization.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/src/serialization.py b/test/src/serialization.py index 0fd4c5770..0c72298e2 100644 --- a/test/src/serialization.py +++ b/test/src/serialization.py @@ -42,7 +42,7 @@ def generic_test(object, filename): try: with open(filename, "wb") as f: pickle.dump(object, f) - except: + except pickle.PickleError: dump_success = False else: dump_success = True @@ -52,7 +52,7 @@ def generic_test(object, filename): try: with open(filename, "rb") as f: loaded_object = pickle.load(f) - except: + except pickle.PickleError: read_success = False else: read_success = True From 54f42c6d8de399c967588dc93741995e85694288 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 22:22:13 +0200 Subject: [PATCH 054/109] [test] Fix serialization + pickle expects to be loading a str instead of bytes --- bindings/python/src/expose-model.hpp | 4 ++-- bindings/python/src/expose-qpobject.hpp | 4 ++-- bindings/python/src/expose-results.hpp | 4 ++-- bindings/python/src/expose-settings.hpp | 4 ++-- test/src/serialization.py | 5 +---- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/bindings/python/src/expose-model.hpp b/bindings/python/src/expose-model.hpp index 3739f26b3..92ea5c6ce 100644 --- a/bindings/python/src/expose-model.hpp +++ b/bindings/python/src/expose-model.hpp @@ -70,10 +70,10 @@ exposeDenseModel(nanobind::module_ m) [](const proxsuite::proxqp::dense::Model& model) { return proxsuite::serialization::saveToString(model); }) - .def("__setstate__", [](dense::Model& model, nanobind::bytes& s) { + .def("__setstate__", [](dense::Model& model, const std::string& s) { // create qp model which will be updated by loaded data new (&model) dense::Model(1, 1, 1); - proxsuite::serialization::loadFromString(model, s.c_str()); + proxsuite::serialization::loadFromString(model, s); }); } } // namespace python diff --git a/bindings/python/src/expose-qpobject.hpp b/bindings/python/src/expose-qpobject.hpp index 70e22f2b6..3f37d3b72 100644 --- a/bindings/python/src/expose-qpobject.hpp +++ b/bindings/python/src/expose-qpobject.hpp @@ -224,9 +224,9 @@ exposeQpObjectDense(nanobind::module_ m) [](const dense::QP& qp) { return proxsuite::serialization::saveToString(qp); }) - .def("__setstate__", [](dense::QP& qp, nanobind::bytes& s) { + .def("__setstate__", [](dense::QP& qp, const std::string& s) { new (&qp) dense::QP(1, 1, 1); - proxsuite::serialization::loadFromString(qp, s.c_str()); + proxsuite::serialization::loadFromString(qp, s); }); ; } diff --git a/bindings/python/src/expose-results.hpp b/bindings/python/src/expose-results.hpp index 10b2135bd..73440dd33 100644 --- a/bindings/python/src/expose-results.hpp +++ b/bindings/python/src/expose-results.hpp @@ -106,9 +106,9 @@ exposeResults(nanobind::module_ m) [](const Results& results) { return proxsuite::serialization::saveToString(results); }) - .def("__setstate__", [](Results& results, nanobind::bytes& s) { + .def("__setstate__", [](Results& results, const std::string& s) { new (&results) Results{}; - proxsuite::serialization::loadFromString(results, s.c_str()); + proxsuite::serialization::loadFromString(results, s); }); ; } diff --git a/bindings/python/src/expose-settings.hpp b/bindings/python/src/expose-settings.hpp index 4569f7d3e..c99d8767d 100644 --- a/bindings/python/src/expose-settings.hpp +++ b/bindings/python/src/expose-settings.hpp @@ -96,9 +96,9 @@ exposeSettings(nanobind::module_ m) [](const Settings& settings) { return proxsuite::serialization::saveToString(settings); }) - .def("__setstate__", [](Settings& settings, nanobind::bytes& s) { + .def("__setstate__", [](Settings& settings, const std::string& s) { new (&settings) Settings{}; - proxsuite::serialization::loadFromString(settings, s.c_str()); + proxsuite::serialization::loadFromString(settings, s); }); ; } diff --git a/test/src/serialization.py b/test/src/serialization.py index 0c72298e2..4dd935ef8 100644 --- a/test/src/serialization.py +++ b/test/src/serialization.py @@ -29,9 +29,8 @@ def generate_mixed_qp(n, seed=1): P = spa.coo_matrix(P) # print("sparsity of P : {}".format((P.nnz) / (n**2))) q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() + A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray(order='C') v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality u = A @ v l = -1.0e20 * np.ones(m) @@ -63,8 +62,6 @@ def generic_test(object, filename): class DenseqpWrapperSerialization(unittest.TestCase): def test_pickle(self): - import pickle - print("------------------------test pickle") n = 10 H, g, A, b, C, u, l = generate_mixed_qp(n) From 029767647b733e817e1ef333adbdfdf32939ba25 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 22:22:46 +0200 Subject: [PATCH 055/109] [test] Force C-order (row-major) for all matrices in the tests --- test/src/dense_qp_solve.py | 12 ++++++++---- test/src/dense_qp_wrapper.py | 9 ++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/test/src/dense_qp_solve.py b/test/src/dense_qp_solve.py index b26896fd8..3920199d6 100644 --- a/test/src/dense_qp_solve.py +++ b/test/src/dense_qp_solve.py @@ -37,7 +37,9 @@ def generate_mixed_qp(n, seed=1): P = spa.coo_matrix(P) # print("sparsity of P : {}".format((P.nnz) / (n**2))) q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() + A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray( + order="C" + ) # row-major v = np.random.randn(n) # Fictitious solution u = A @ v l = -1.0e20 * np.ones(m) @@ -309,10 +311,12 @@ def test_sparse_problem_with_exact_solution_known(self): M[i, i - 1] = 1 H = spa.csc_matrix(M.dot(M.transpose())).toarray() + H = np.ascontiguousarray(H) g = -np.ones((n,)) A = None b = None C = spa.csc_matrix(spa.eye(n)).toarray() + C = np.ascontiguousarray(C) l = 2.0 * np.ones((n,)) u = np.full(l.shape, +np.inf) @@ -378,11 +382,11 @@ def test_solve_qpsolvers_problem(self): os.path.join(data_path, "simple_qp_with_inifinity_lower_bound.mat"), squeeze_me=True, ) - P = m["P"].astype(float) + P = np.ascontiguousarray(m["P"].astype(float)) q = m["q"].astype(float) - A = m["A"].astype(float).reshape((1, 3)) + A = np.ascontiguousarray(m["A"].astype(float).reshape((1, 3))) b = np.array([m["b"]]).reshape((1,)) - C = m["C"].astype(float) + C = np.ascontiguousarray(m["C"].astype(float)) l = m["l"].astype(float) u = m["u"].astype(float) diff --git a/test/src/dense_qp_wrapper.py b/test/src/dense_qp_wrapper.py index 0bda2f085..4f3810bae 100644 --- a/test/src/dense_qp_wrapper.py +++ b/test/src/dense_qp_wrapper.py @@ -37,7 +37,7 @@ def generate_mixed_qp(n, seed=1, reg=0.01): P = spa.coo_matrix(P) # print("sparsity of P : {}".format((P.nnz) / (n**2))) q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() + A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray(order='C') v = np.random.randn(n) # Fictitious solution delta = np.random.rand(m) # To get inequality u = A @ v @@ -67,9 +67,8 @@ def generate_mixed_qp_with_box(n, seed=1): P = spa.coo_matrix(P) # print("sparsity of P : {}".format((P.nnz) / (n**2))) q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray() + A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray(order='C') v = np.random.randn(n) # Fictitious solution - delta = np.random.rand(m) # To get inequality u = A @ v l = -1.0e20 * np.ones(m) delta_box = np.random.rand(n) @@ -3924,11 +3923,11 @@ def test_sparse_problem_with_exact_solution_known(self): M[i, i + 1] = -1 M[i, i - 1] = 1 - H = spa.csc_matrix(M.dot(M.transpose())).toarray() + H = spa.csc_matrix(M.dot(M.transpose())).toarray(order='C') g = -np.ones((n,)) A = None b = None - C = spa.csc_matrix(spa.eye(n)).toarray() + C = spa.csc_matrix(spa.eye(n)).toarray(order='C') l = 2.0 * np.ones((n,)) u = np.full(l.shape, +np.inf) From 8dccf3b1b5c0dec08d2116b0e2e37ea90ca06911 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 22:23:25 +0200 Subject: [PATCH 056/109] [bindings/python] Fix overloaded dense.solve() signatures, switch nullopt for nanobind::none() --- bindings/python/src/expose-solve.hpp | 118 +++++++++++++-------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/bindings/python/src/expose-solve.hpp b/bindings/python/src/expose-solve.hpp index 8721ba570..c89faad1b 100644 --- a/bindings/python/src/expose-solve.hpp +++ b/bindings/python/src/expose-solve.hpp @@ -51,30 +51,30 @@ solveDenseQp(nanobind::module_ m) "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " "preconditioner execution).", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, - nanobind::arg("x") = nullopt, - nanobind::arg("y") = nullopt, - nanobind::arg("z") = nullopt, - nanobind::arg("eps_abs") = nullopt, - nanobind::arg("eps_rel") = nullopt, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("verbose") = nullopt, + nanobind::arg("H"), + nanobind::arg("g"), + nanobind::arg("A").none(), + nanobind::arg("b").none(), + nanobind::arg("C").none(), + nanobind::arg("l").none(), + nanobind::arg("u").none(), + nanobind::arg("x") = nanobind::none(), + nanobind::arg("y") = nanobind::none(), + nanobind::arg("z") = nanobind::none(), + nanobind::arg("eps_abs") = nanobind::none(), + nanobind::arg("eps_rel") = nanobind::none(), + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("verbose") = nanobind::none(), nanobind::arg("compute_preconditioner") = true, nanobind::arg("compute_timings") = false, - nanobind::arg("max_iter") = nullopt, + nanobind::arg("max_iter") = nanobind::none(), nanobind::arg("initial_guess") = InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, nanobind::arg("check_duality_gap") = false, - nanobind::arg("eps_duality_gap_abs") = nullopt, - nanobind::arg("eps_duality_gap_rel") = nullopt, + nanobind::arg("eps_duality_gap_abs") = nanobind::none(), + nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, nanobind::arg("default_H_eigenvalue_estimate") = 0.); @@ -112,32 +112,32 @@ solveDenseQp(nanobind::module_ m) "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " "preconditioner execution).", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, - nanobind::arg("l_box") = nullopt, - nanobind::arg("u_box") = nullopt, - nanobind::arg("x") = nullopt, - nanobind::arg("y") = nullopt, - nanobind::arg("z") = nullopt, - nanobind::arg("eps_abs") = nullopt, - nanobind::arg("eps_rel") = nullopt, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("verbose") = nullopt, + nanobind::arg("H"), + nanobind::arg("g"), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), + nanobind::arg("l_box") = nanobind::none(), + nanobind::arg("u_box") = nanobind::none(), + nanobind::arg("x") = nanobind::none(), + nanobind::arg("y") = nanobind::none(), + nanobind::arg("z") = nanobind::none(), + nanobind::arg("eps_abs") = nanobind::none(), + nanobind::arg("eps_rel") = nanobind::none(), + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("verbose") = nanobind::none(), nanobind::arg("compute_preconditioner") = true, nanobind::arg("compute_timings") = false, - nanobind::arg("max_iter") = nullopt, + nanobind::arg("max_iter") = nanobind::none(), nanobind::arg("initial_guess") = proxsuite::proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, nanobind::arg("check_duality_gap") = false, - nanobind::arg("eps_duality_gap_abs") = nullopt, - nanobind::arg("eps_duality_gap_rel") = nullopt, + nanobind::arg("eps_duality_gap_abs") = nanobind::none(), + nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, nanobind::arg("default_H_eigenvalue_estimate") = 0.); } @@ -160,31 +160,31 @@ solveSparseQp(nanobind::module_ m) "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " "preconditioner execution).", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, - nanobind::arg("x") = nullopt, - nanobind::arg("y") = nullopt, - nanobind::arg("z") = nullopt, - nanobind::arg("eps_abs") = nullopt, - nanobind::arg("eps_rel") = nullopt, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("verbose") = nullopt, + nanobind::arg("H") = nanobind::none(), + nanobind::arg("g") = nanobind::none(), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), + nanobind::arg("x") = nanobind::none(), + nanobind::arg("y") = nanobind::none(), + nanobind::arg("z") = nanobind::none(), + nanobind::arg("eps_abs") = nanobind::none(), + nanobind::arg("eps_rel") = nanobind::none(), + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("verbose") = nanobind::none(), nanobind::arg("compute_preconditioner") = true, nanobind::arg("compute_timings") = false, - nanobind::arg("max_iter") = nullopt, + nanobind::arg("max_iter") = nanobind::none(), nanobind::arg("initial_guess") = InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, nanobind::arg("sparse_backend") = SparseBackend::Automatic, nanobind::arg("check_duality_gap") = false, - nanobind::arg("eps_duality_gap_abs") = nullopt, - nanobind::arg("eps_duality_gap_rel") = nullopt, + nanobind::arg("eps_duality_gap_abs") = nanobind::none(), + nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, nanobind::arg("default_H_eigenvalue_estimate") = 0.); } From 395933c85f82193fa88ece54184c92401f31b542 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 22:29:17 +0200 Subject: [PATCH 057/109] [test] reformat using black --- test/src/dense_qp_wrapper.py | 12 ++++++++---- test/src/serialization.py | 4 +++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/test/src/dense_qp_wrapper.py b/test/src/dense_qp_wrapper.py index 4f3810bae..871f0a612 100644 --- a/test/src/dense_qp_wrapper.py +++ b/test/src/dense_qp_wrapper.py @@ -37,7 +37,9 @@ def generate_mixed_qp(n, seed=1, reg=0.01): P = spa.coo_matrix(P) # print("sparsity of P : {}".format((P.nnz) / (n**2))) q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray(order='C') + A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray( + order="C" + ) v = np.random.randn(n) # Fictitious solution delta = np.random.rand(m) # To get inequality u = A @ v @@ -67,7 +69,9 @@ def generate_mixed_qp_with_box(n, seed=1): P = spa.coo_matrix(P) # print("sparsity of P : {}".format((P.nnz) / (n**2))) q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray(order='C') + A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray( + order="C" + ) v = np.random.randn(n) # Fictitious solution u = A @ v l = -1.0e20 * np.ones(m) @@ -3923,11 +3927,11 @@ def test_sparse_problem_with_exact_solution_known(self): M[i, i + 1] = -1 M[i, i - 1] = 1 - H = spa.csc_matrix(M.dot(M.transpose())).toarray(order='C') + H = spa.csc_matrix(M.dot(M.transpose())).toarray(order="C") g = -np.ones((n,)) A = None b = None - C = spa.csc_matrix(spa.eye(n)).toarray(order='C') + C = spa.csc_matrix(spa.eye(n)).toarray(order="C") l = 2.0 * np.ones((n,)) u = np.full(l.shape, +np.inf) diff --git a/test/src/serialization.py b/test/src/serialization.py index 4dd935ef8..4c03725e9 100644 --- a/test/src/serialization.py +++ b/test/src/serialization.py @@ -29,7 +29,9 @@ def generate_mixed_qp(n, seed=1): P = spa.coo_matrix(P) # print("sparsity of P : {}".format((P.nnz) / (n**2))) q = np.random.randn(n) - A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray(order='C') + A = spa.random(m, n, density=0.15, data_rvs=np.random.randn, format="csc").toarray( + order="C" + ) v = np.random.randn(n) # Fictitious solution u = A @ v l = -1.0e20 * np.ones(m) From 9008bf95ed5118f42f1d75dac97e483cfc9f2608 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 6 Aug 2024 23:07:15 +0200 Subject: [PATCH 058/109] [workflows] also install typing_extensions package --- .github/workflows/ci-linux-osx-win-conda.yml | 2 +- .github/workflows/release-osx-win.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index 48f32ad21..a17df614e 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -82,7 +82,7 @@ jobs: # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 conda config --remove channels defaults # Compilation related dependencies - mamba install cmake compilers make pkg-config doxygen ninja graphviz + mamba install cmake compilers make pkg-config doxygen ninja graphviz typing_extensions # Main dependencies mamba install eigen simde # Test dependencies diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index 65f4f91de..8437eac91 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -57,7 +57,7 @@ jobs: run: | # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 conda config --remove channels defaults - mamba install doxygen graphviz eigen simde cmake compilers + mamba install doxygen graphviz eigen simde cmake compilers typing_extensions - name: Print environment [Conda] if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows') From 22fcd22483bb2ae3b050f0162bbd84f063737ea4 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Wed, 7 Aug 2024 12:03:01 +0200 Subject: [PATCH 059/109] [examples/python] fix toarray() for C order --- examples/python/solve_without_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/python/solve_without_api.py b/examples/python/solve_without_api.py index 3a489203a..1ba2c166d 100644 --- a/examples/python/solve_without_api.py +++ b/examples/python/solve_without_api.py @@ -16,7 +16,7 @@ # solve the problem using the dense backend results2 = proxsuite.proxqp.dense.solve( - H.toarray(), g, A.toarray(), b, C.toarray(), l, u + H.toarray(order="C"), g, A.toarray(order="C"), b, C.toarray(order="C"), l, u ) # Note finally, that the matrices are in sparse format, when using the dense backend you # should convert them in dense format From 603e208d866d92b6050d19556056d385f8d96288 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Wed, 7 Aug 2024 12:19:33 +0200 Subject: [PATCH 060/109] [test] parallel_qp_solve : .toarray() to C order --- test/src/parallel_qp_solve.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/src/parallel_qp_solve.py b/test/src/parallel_qp_solve.py index 4ea203569..11654c753 100644 --- a/test/src/parallel_qp_solve.py +++ b/test/src/parallel_qp_solve.py @@ -33,13 +33,23 @@ def generate_mixed_qp(n, seed=1): P = spa.coo_matrix(P) # print("sparsity of P : {}".format((P.nnz) / (n**2))) q = np.random.randn(n) - A = spa.random(m, n, density=0.95, data_rvs=np.random.randn, format="csc").toarray() + A = spa.random(m, n, density=0.95, data_rvs=np.random.randn, format="csc").toarray( + order="C" + ) v = np.random.randn(n) # Fictitious solution delta = np.random.rand(m) # To get inequality u = A @ v l = -1.0e20 * np.ones(m) - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] + return ( + P.toarray(order="C"), + q, + A[:n_eq, :], + u[:n_eq], + A[n_in:, :], + u[n_in:], + l[n_in:], + ) class ParallelWrapper(unittest.TestCase): From 856e0571a0b13e09b8229d005264a79e50a79be4 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Wed, 7 Aug 2024 17:39:50 +0200 Subject: [PATCH 061/109] Update minimum Python to 3.8 (3.7 has been EOL for a year) --- bindings/python/CMakeLists.txt | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 30d49293e..2e41019a5 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -8,7 +8,7 @@ include(${JRL_CMAKE_MODULES}/python-helpers.cmake) option(GENERATE_PYTHON_STUBS "Generate Python stubs" OFF) findpython(REQUIRED Development.Module) -find_package(Python 3.8 COMPONENTS ${PYTHON_COMPONENTS}) +find_package(Python 3.7 COMPONENTS ${PYTHON_COMPONENTS}) if(IS_ABSOLUTE ${PYTHON_SITELIB}) set(${PYWRAP}_INSTALL_DIR ${PYTHON_SITELIB}/${PROJECT_NAME}) diff --git a/pyproject.toml b/pyproject.toml index 3aa236457..9f65cf1c1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "proxsuite" version = "0.6.7" description = "Quadratic Programming Solver for Robotics and beyond." readme = "README.md" -requires-python = ">= 3.7" +requires-python = ">= 3.8" license = "BSD-2-Clause" dependencies = ["numpy","scipy"] From 4882f59d70edc003e157607fba3c5e1e63c1a9ef Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Thu, 8 Aug 2024 12:11:15 +0200 Subject: [PATCH 062/109] [test] cvxpy.py : ensure matrix and gradient are float64 --- test/src/cvxpy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/src/cvxpy.py b/test/src/cvxpy.py index d4e609e16..cd45496cf 100644 --- a/test/src/cvxpy.py +++ b/test/src/cvxpy.py @@ -56,8 +56,8 @@ def test_trigger_infeasibility_with_exact_solution_known(self): def test_one_dim_with_exact_solution_known(self): print("------------------------ test_one_dim_with_exact_solution_known") n = 1 - H = np.array([[20]]) - g = np.array([-10]) + H = np.array([[20.0]]) + g = np.array([-10.0]) A = None b = None C = np.array([[1.0]]) From b810caf506d5b9da894092cc3d78d3259873465b Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Thu, 8 Aug 2024 14:37:45 +0200 Subject: [PATCH 063/109] [bindings/python] cmake : fix the bloody include dirs variable ?? --- bindings/python/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 2e41019a5..93d8d3b91 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -8,7 +8,7 @@ include(${JRL_CMAKE_MODULES}/python-helpers.cmake) option(GENERATE_PYTHON_STUBS "Generate Python stubs" OFF) findpython(REQUIRED Development.Module) -find_package(Python 3.7 COMPONENTS ${PYTHON_COMPONENTS}) +set(Python_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) if(IS_ABSOLUTE ${PYTHON_SITELIB}) set(${PYWRAP}_INSTALL_DIR ${PYTHON_SITELIB}/${PROJECT_NAME}) From e7394b3cb1002fb4314ec5d05e50115102698bb3 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Thu, 8 Aug 2024 18:03:48 +0200 Subject: [PATCH 064/109] [examples/python] fix some more C orders --- examples/python/solve_without_api.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/python/solve_without_api.py b/examples/python/solve_without_api.py index 1ba2c166d..53904c718 100644 --- a/examples/python/solve_without_api.py +++ b/examples/python/solve_without_api.py @@ -34,7 +34,15 @@ # make sure to specify l_box=l_box, u_box=u_box in order to make work the # overloading results_dense_solver_box = proxsuite.proxqp.dense.solve( - H.toarray(), g, A.toarray(), b, C.toarray(), l, u, l_box=l_box, u_box=u_box + H.toarray(order="C"), + g, + A.toarray(order="C"), + b, + C.toarray(order="C"), + l, + u, + l_box=l_box, + u_box=u_box, ) # print an optimal solution print("optimal x: {}".format(results_dense_solver_box.x)) From f004f5d303893ca1a08aa77f80c114e26033871b Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Fri, 9 Aug 2024 11:42:00 +0200 Subject: [PATCH 065/109] cmake : alias some targets to Python::* --- bindings/python/CMakeLists.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index 93d8d3b91..a58b39df6 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -1,5 +1,5 @@ if(UNIX) - set(PYTHON_COMPONENTS Development.Module) + set(PYTHON_COMPONENTS Interpreter Development.Module) endif() include(${JRL_CMAKE_MODULES}/python.cmake) @@ -7,8 +7,12 @@ include(${JRL_CMAKE_MODULES}/python-helpers.cmake) option(GENERATE_PYTHON_STUBS "Generate Python stubs" OFF) -findpython(REQUIRED Development.Module) -set(Python_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) +findpython(REQUIRED) +set(Python_INCLUDE_DIRS ${Python3_INCLUDE_DIRS}) +# Nanobind expects these targets instead of Python3::* +# https://github.com/jrl-umi3218/jrl-cmakemodules/issues/708 +add_library(Python::Module ALIAS Python3::Module) +add_executable(Python::Interpreter ALIAS Python3::Interpreter) if(IS_ABSOLUTE ${PYTHON_SITELIB}) set(${PYWRAP}_INSTALL_DIR ${PYTHON_SITELIB}/${PROJECT_NAME}) From 05632d223b8707ee79f8a106bb5a44ac27b7ab6d Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Fri, 9 Aug 2024 12:07:49 +0200 Subject: [PATCH 066/109] [workflows] remove macOS C++14 --- .github/workflows/ci-linux-osx-win-conda.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index a17df614e..be2bec460 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -29,10 +29,6 @@ jobs: compiler: clang-cl - name: windows-latest os: windows-latest - - name: macos-latest - os: macos-latest - build_type: Release - cxx_std: 14 - name: macos-latest os: macos-latest build_type: Debug From 27238729482744425f05c0c2ca8a7fa4d2f38dc8 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Fri, 9 Aug 2024 13:23:49 +0200 Subject: [PATCH 067/109] [bindings/python] use nanobind::none() instead of nullopt --- bindings/python/src/expose-qpobject.hpp | 144 ++++++++++++------------ 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/bindings/python/src/expose-qpobject.hpp b/bindings/python/src/expose-qpobject.hpp index 3f37d3b72..84237b640 100644 --- a/bindings/python/src/expose-qpobject.hpp +++ b/bindings/python/src/expose-qpobject.hpp @@ -102,18 +102,18 @@ exposeQpObjectDense(nanobind::module_ m) optional, optional)>(&dense::QP::init), "function for initialize the QP model.", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, + nanobind::arg("H"), + nanobind::arg("g"), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), nanobind::arg("compute_preconditioner") = true, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("manual_minimal_H_eigenvalue") = nanobind::none()) .def("init", static_cast::*)(optional>, optional>, @@ -130,20 +130,20 @@ exposeQpObjectDense(nanobind::module_ m) optional, optional)>(&dense::QP::init), "function for initialize the QP model.", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, - nanobind::arg("l_box") = nullopt, - nanobind::arg("u_box") = nullopt, + nanobind::arg("H") = nanobind::none(), + nanobind::arg("g") = nanobind::none(), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), + nanobind::arg("l_box") = nanobind::none(), + nanobind::arg("u_box") = nanobind::none(), nanobind::arg("compute_preconditioner") = true, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("manual_minimal_H_eigenvalue") = nanobind::none()) .def("solve", static_cast::*)()>(&dense::QP::solve), "function used for solving the QP problem, using default parameters.") @@ -170,18 +170,18 @@ exposeQpObjectDense(nanobind::module_ m) optional)>(&dense::QP::update), "function used for updating matrix or vector entry of the model using " "dense matrix entries.", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, + nanobind::arg("H") = nanobind::none(), + nanobind::arg("g") = nanobind::none(), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), nanobind::arg("update_preconditioner") = false, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("manual_minimal_H_eigenvalue") = nanobind::none()) .def( "update", static_cast::*)(optional>, @@ -200,20 +200,20 @@ exposeQpObjectDense(nanobind::module_ m) optional)>(&dense::QP::update), "function used for updating matrix or vector entry of the model using " "dense matrix entries.", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, - nanobind::arg("l_box") = nullopt, - nanobind::arg("u_box") = nullopt, + nanobind::arg("H") = nanobind::none(), + nanobind::arg("g") = nanobind::none(), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), + nanobind::arg("l_box") = nanobind::none(), + nanobind::arg("u_box") = nanobind::none(), nanobind::arg("update_preconditioner") = false, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("manual_minimal_H_eigenvalue") = nanobind::none()) .def("cleanup", &dense::QP::cleanup, "function used for cleaning the workspace and result " @@ -251,8 +251,8 @@ exposeQpObjectSparse(nanobind::module_ m) .def(::nanobind::init&, const sparse::SparseMat&, const sparse::SparseMat&>(), - nanobind::arg("H_mask") = nullopt, - nanobind::arg("A_mask") = nullopt, + nanobind::arg("H_mask") = nanobind::none(), + nanobind::arg("A_mask") = nanobind::none(), nanobind::arg("C_mask") = 0, "Constructor using QP model sparsity structure.") // constructor .def_ro("model", &sparse::QP::model, "class containing the QP model") @@ -266,35 +266,35 @@ exposeQpObjectSparse(nanobind::module_ m) &sparse::QP::init, "function for initializing the model when passing sparse matrices in " "entry.", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, + nanobind::arg("H") = nanobind::none(), + nanobind::arg("g") = nanobind::none(), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), nanobind::arg("compute_preconditioner") = true, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("manual_minimal_H_eigenvalue") = nanobind::none()) .def("update", &sparse::QP::update, "function for updating the model when passing sparse matrices in " "entry.", - nanobind::arg("H") = nullopt, - nanobind::arg("g") = nullopt, - nanobind::arg("A") = nullopt, - nanobind::arg("b") = nullopt, - nanobind::arg("C") = nullopt, - nanobind::arg("l") = nullopt, - nanobind::arg("u") = nullopt, + nanobind::arg("H") = nanobind::none(), + nanobind::arg("g") = nanobind::none(), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), nanobind::arg("update_preconditioner") = false, - nanobind::arg("rho") = nullopt, - nanobind::arg("mu_eq") = nullopt, - nanobind::arg("mu_in") = nullopt, - nanobind::arg("manual_minimal_H_eigenvalue") = nullopt) + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("manual_minimal_H_eigenvalue") = nanobind::none()) .def("solve", static_cast::*)()>(&sparse::QP::solve), "function used for solving the QP problem, using default parameters.") From 94f13f1898a1f66fea2ec30c7aa18b3dc2481df8 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 20 Aug 2024 17:50:00 +0200 Subject: [PATCH 068/109] [bindings] point nanobind to latest master --- .gitmodules | 2 +- bindings/python/external/nanobind | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 2867bf33b..0556288d9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "bindings/python/external/nanobind"] path = bindings/python/external/nanobind - url = https://github.com/wjakob/nanobind + url = https://github.com/ManifoldFR/nanobind [submodule "cmake-module"] path = cmake-module url = https://github.com/jrl-umi3218/jrl-cmakemodules.git diff --git a/bindings/python/external/nanobind b/bindings/python/external/nanobind index 8d7f1ee06..8a65e0e39 160000 --- a/bindings/python/external/nanobind +++ b/bindings/python/external/nanobind @@ -1 +1 @@ -Subproject commit 8d7f1ee0621c17fa370b704b2100ffa0243d5bfb +Subproject commit 8a65e0e39ca1621fdf20130e94bccb5850ca0f81 From 6d167e899256bbc69b10c9cb4f920d8dd82524d8 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 27 Aug 2024 13:14:22 +0200 Subject: [PATCH 069/109] Add fix for std::optional> --- bindings/python/src/expose-results.hpp | 2 +- bindings/python/src/expose-solve.hpp | 2 +- bindings/python/src/optional-eigen-fix.hpp | 45 ++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 bindings/python/src/optional-eigen-fix.hpp diff --git a/bindings/python/src/expose-results.hpp b/bindings/python/src/expose-results.hpp index 73440dd33..f4bd8c492 100644 --- a/bindings/python/src/expose-results.hpp +++ b/bindings/python/src/expose-results.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include "optional-eigen-fix.hpp" #include #include diff --git a/bindings/python/src/expose-solve.hpp b/bindings/python/src/expose-solve.hpp index c89faad1b..25befc0bd 100644 --- a/bindings/python/src/expose-solve.hpp +++ b/bindings/python/src/expose-solve.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include "optional-eigen-fix.hpp" namespace proxsuite { namespace proxqp { diff --git a/bindings/python/src/optional-eigen-fix.hpp b/bindings/python/src/optional-eigen-fix.hpp new file mode 100644 index 000000000..3a09564d7 --- /dev/null +++ b/bindings/python/src/optional-eigen-fix.hpp @@ -0,0 +1,45 @@ +// +// Copyright (c) 2024 INRIA +// +#pragma once + +#include +#include + +NAMESPACE_BEGIN(NB_NAMESPACE) +NAMESPACE_BEGIN(detail) + +/// Fix std::optional for Eigen::Ref +/// Credit to github.com/WKarel for this suggestion! +/// https://github.com/wjakob/nanobind/issues/682#issuecomment-2310746145 +template +struct type_caster>> + : optional_caster>> +{ + using Ref = Eigen::Ref; + using Optional = std::optional; + using Caster = typename type_caster::optional_caster::Caster; + using Map = typename Caster::Map; + using DMap = typename Caster::DMap; + NB_TYPE_CASTER(Optional, optional_name(Caster::Name)) + + bool from_python(handle src, uint8_t flags, cleanup_list* cleanup) noexcept + { + if (src.is_none()) + return true; + Caster caster; + if (!caster.from_python(src, flags_for_local_caster(flags), cleanup) || + !caster.template can_cast()) + return false; + /// This allows us to bypass the type_caster for Eigen::Ref + /// which is broken due to lack of NRVO + move ctor in latest Eigen release. + if (caster.dcaster.caster.value.is_valid()) + value.emplace(caster.dcaster.operator DMap()); + else + value.emplace(caster.caster.operator Map()); + return true; + } +}; + +NAMESPACE_END(detail) +NAMESPACE_END(NB_NAMESPACE) From 3d637fd951876204c97698c51e064d3f699f8d90 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 27 Aug 2024 13:27:00 +0200 Subject: [PATCH 070/109] apparently i64/u64 and isize/size_t are not the same thing on the Windows --- bindings/python/src/expose-qpobject.hpp | 8 ++++---- bindings/python/src/expose-qpvector.hpp | 4 ++-- bindings/python/src/expose-results.hpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bindings/python/src/expose-qpobject.hpp b/bindings/python/src/expose-qpobject.hpp index 84237b640..288c1a7d2 100644 --- a/bindings/python/src/expose-qpobject.hpp +++ b/bindings/python/src/expose-qpobject.hpp @@ -58,9 +58,9 @@ exposeQpObjectDense(nanobind::module_ m) // .def_rw("run_time", &RuizEquilibration::sym); ::nanobind::class_>(m, "QP") - .def(::nanobind::init(), @@ -243,7 +243,7 @@ exposeQpObjectSparse(nanobind::module_ m) { ::nanobind::class_>(m, "QP") - .def(::nanobind::init(), + .def(::nanobind::init(), nanobind::arg("n") = 0, nanobind::arg("n_eq") = 0, nanobind::arg("n_in") = 0, diff --git a/bindings/python/src/expose-qpvector.hpp b/bindings/python/src/expose-qpvector.hpp index 1b077a4af..0530ac41a 100644 --- a/bindings/python/src/expose-qpvector.hpp +++ b/bindings/python/src/expose-qpvector.hpp @@ -21,7 +21,7 @@ exposeQPVectorDense(nanobind::module_ m) ::nanobind::class_>(m, "BatchQP") .def( - ::nanobind::init(), + ::nanobind::init(), nanobind::arg("batch_size") = 0, "Default constructor using the BatchSize of qp models to store.") // constructor .def("init_qp_in_place", @@ -51,7 +51,7 @@ exposeQPVectorSparse(nanobind::module_ m) ::nanobind::class_>(m, "BatchQP") .def( - ::nanobind::init(), + ::nanobind::init(), nanobind::arg("batch_size") = 0, "Default constructor using the BatchSize of qp models to store.") // constructor .def("init_qp_in_place", diff --git a/bindings/python/src/expose-results.hpp b/bindings/python/src/expose-results.hpp index f4bd8c492..bab63daba 100644 --- a/bindings/python/src/expose-results.hpp +++ b/bindings/python/src/expose-results.hpp @@ -60,7 +60,7 @@ exposeResults(nanobind::module_ m) "find_H_minimal_eigenvalue."); ::nanobind::class_>(m, "Results") - .def(::nanobind::init(), + .def(::nanobind::init(), nanobind::arg("n") = 0, nanobind::arg("n_eq") = 0, nanobind::arg("n_in") = 0, From 3804bae16d47fd007217f8347f9f876b3b7c0185 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 27 Aug 2024 16:29:09 +0200 Subject: [PATCH 071/109] Change back URL of nanobind submodule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 0556288d9..2867bf33b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "bindings/python/external/nanobind"] path = bindings/python/external/nanobind - url = https://github.com/ManifoldFR/nanobind + url = https://github.com/wjakob/nanobind [submodule "cmake-module"] path = cmake-module url = https://github.com/jrl-umi3218/jrl-cmakemodules.git From bfc2bea1ac52ffa87f86bd5cca440ed69a7d00bb Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 27 Aug 2024 17:29:28 +0200 Subject: [PATCH 072/109] Allow use of installed nanobind --- bindings/python/CMakeLists.txt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt index a58b39df6..29487b9a9 100644 --- a/bindings/python/CMakeLists.txt +++ b/bindings/python/CMakeLists.txt @@ -21,9 +21,22 @@ else() ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}/${PROJECT_NAME}) endif() -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/nanobind) -add_subdirectory(external/nanobind - ${CMAKE_CURRENT_BINARY_DIR}/external/nanobind) +cmake_policy(PUSH) +cmake_policy(SET CMP0074 NEW) +# Detect the installed nanobind package and import it into CMake +execute_process( + COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE nanobind_ROOT) +find_package(nanobind CONFIG) +cmake_policy(POP) +if(NOT nanobind_FOUND) + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/nanobind) + add_subdirectory(external/nanobind + ${CMAKE_CURRENT_BINARY_DIR}/external/nanobind) +else() + message(STATUS "Found installed nanobind.") +endif() add_custom_target(${PROJECT_NAME}_python) From 0e4db0af171b02c0f5c11f814c65262bd567e571 Mon Sep 17 00:00:00 2001 From: Wilson Date: Tue, 27 Aug 2024 19:14:04 +0200 Subject: [PATCH 073/109] Update bindings/python/helpers/instruction-set.cpp Co-authored-by: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> --- bindings/python/helpers/instruction-set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/helpers/instruction-set.cpp b/bindings/python/helpers/instruction-set.cpp index cc92bf214..64035c447 100644 --- a/bindings/python/helpers/instruction-set.cpp +++ b/bindings/python/helpers/instruction-set.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // #include From 449267f60a68f14bcea7203f5863817acde4b009 Mon Sep 17 00:00:00 2001 From: Wilson Date: Tue, 27 Aug 2024 19:16:28 +0200 Subject: [PATCH 074/109] Update bindings/python/src/expose-results.hpp Co-authored-by: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> --- bindings/python/src/expose-results.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/src/expose-results.hpp b/bindings/python/src/expose-results.hpp index bab63daba..fa1e63160 100644 --- a/bindings/python/src/expose-results.hpp +++ b/bindings/python/src/expose-results.hpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2022-2023 INRIA +// Copyright (c) 2022-2024 INRIA // #include #include From d509b5e373f5993ac473e06731fe886589c647f0 Mon Sep 17 00:00:00 2001 From: Wilson Date: Tue, 27 Aug 2024 19:18:51 +0200 Subject: [PATCH 075/109] Update bindings/python/src/expose-helpers.hpp Co-authored-by: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> --- bindings/python/src/expose-helpers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/src/expose-helpers.hpp b/bindings/python/src/expose-helpers.hpp index 76cba0e70..872a60fdd 100644 --- a/bindings/python/src/expose-helpers.hpp +++ b/bindings/python/src/expose-helpers.hpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 INRIA +// Copyright (c) 2022-2024 INRIA // #include From 519a6246437420b4be25ab13c5a3b16920248046 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Tue, 27 Aug 2024 19:52:51 +0200 Subject: [PATCH 076/109] [workflows] do not re-run linux, osx, win, arch CI and release CI when updating CHANGELOG.md --- .github/workflows/ci-arch.yml | 2 ++ .github/workflows/ci-linux-osx-win-conda.yml | 2 ++ .github/workflows/ci-linux-ros.yml | 6 +++++- .github/workflows/release-linux.yml | 2 ++ .github/workflows/release-osx-win.yml | 2 ++ 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-arch.yml b/.github/workflows/ci-arch.yml index af0cfd2ad..b9d2866d4 100644 --- a/.github/workflows/ci-arch.yml +++ b/.github/workflows/ci-arch.yml @@ -3,6 +3,8 @@ name: CI - ArchLinux on: push: pull_request: + paths-ignore: + - CHANGELOG.md jobs: build-with-arch: diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index be2bec460..ac7ed0e53 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -3,6 +3,8 @@ name: CI - Linux/OSX/Windows - Conda on: push: pull_request: + paths-ignore: + - CHANGELOG.md jobs: build-with-conda: diff --git a/.github/workflows/ci-linux-ros.yml b/.github/workflows/ci-linux-ros.yml index 49c54f1bd..c24478bc9 100644 --- a/.github/workflows/ci-linux-ros.yml +++ b/.github/workflows/ci-linux-ros.yml @@ -1,5 +1,9 @@ name: CI - Linux - ROS -on: [push, pull_request] +on: + push: + pull_request: + paths-ignore: + - CHANGELOG.md jobs: CI: diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index 54125cbc8..84bcc72b3 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -2,6 +2,8 @@ name: Release on PyPI [Linux] on: pull_request: + paths-ignore: + - CHANGELOG.md release: types: - published diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index 8437eac91..845a980e6 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -2,6 +2,8 @@ name: Release on PyPI [Windows, Mac] on: pull_request: + paths-ignore: + - CHANGELOG.md release: types: - published From 8305864f13ca7dff7210f89004a56652b71f8891 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Fri, 30 Aug 2024 11:54:32 +0200 Subject: [PATCH 077/109] CMake: fix cereal link --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2bdc74162..bc6ba4a0b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -65,7 +65,7 @@ add_test_cflags( "-DTEST_SERIALIZATION_FOLDER=\\\\\"${CMAKE_CURRENT_BINARY_DIR}/serialization-data\\\\\"" ) if(cereal_FOUND) - target_link_libraries(${PROJECT_NAME}-test-cpp-serialization PRIVATE cereal) + target_link_libraries(${PROJECT_NAME}-test-cpp-serialization PRIVATE cereal::cereal) else() target_include_directories( ${PROJECT_NAME}-test-cpp-serialization SYSTEM From c7c2b2a504398dae27895e76b81df2460b71a551 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Fri, 30 Aug 2024 11:55:34 +0200 Subject: [PATCH 078/109] Set version of nanobind submodule to release v2.1.0 --- bindings/python/external/nanobind | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/external/nanobind b/bindings/python/external/nanobind index 8a65e0e39..9641bb715 160000 --- a/bindings/python/external/nanobind +++ b/bindings/python/external/nanobind @@ -1 +1 @@ -Subproject commit 8a65e0e39ca1621fdf20130e94bccb5850ca0f81 +Subproject commit 9641bb7151f04120013b812789b3ebdfa7e7324f From d8b56b92acce87cddf745aec4cad220e002e9fb2 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Fri, 30 Aug 2024 11:55:49 +0200 Subject: [PATCH 079/109] add changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7f6fad16..59987ad57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Fixed +* CMake: Fix link to system cereal in tests ([#353](https://github.com/Simple-Robotics/proxsuite/pull/352)) + ## [0.6.7] - 2024-08-27 ### Added From d71966317a12ec943ce4702135c3d90828924899 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Fri, 30 Aug 2024 12:05:15 +0200 Subject: [PATCH 080/109] Fix for nanobind v2.1.0 release --- bindings/python/src/optional-eigen-fix.hpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/bindings/python/src/optional-eigen-fix.hpp b/bindings/python/src/optional-eigen-fix.hpp index 3a09564d7..cedd91103 100644 --- a/bindings/python/src/optional-eigen-fix.hpp +++ b/bindings/python/src/optional-eigen-fix.hpp @@ -14,15 +14,19 @@ NAMESPACE_BEGIN(detail) /// https://github.com/wjakob/nanobind/issues/682#issuecomment-2310746145 template struct type_caster>> - : optional_caster>> { using Ref = Eigen::Ref; using Optional = std::optional; - using Caster = typename type_caster::optional_caster::Caster; + using Caster = make_caster; using Map = typename Caster::Map; using DMap = typename Caster::DMap; NB_TYPE_CASTER(Optional, optional_name(Caster::Name)) + type_caster() + : value(std::nullopt) + { + } + bool from_python(handle src, uint8_t flags, cleanup_list* cleanup) noexcept { if (src.is_none()) @@ -39,6 +43,17 @@ struct type_caster>> value.emplace(caster.caster.operator Map()); return true; } + + template + static handle from_cpp(T_&& value, + rv_policy policy, + cleanup_list* cleanup) noexcept + { + if (!value) + return none().release(); + + return Caster::from_cpp(forward_like_(*value), policy, cleanup); + } }; NAMESPACE_END(detail) From dd63c04735a1d49959eb9e5ecbc3289bd16fa63f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 00:22:21 +0000 Subject: [PATCH 081/109] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-clang-format: v18.1.8 → v19.1.3](https://github.com/pre-commit/mirrors-clang-format/compare/v18.1.8...v19.1.3) - [github.com/pre-commit/pre-commit-hooks: v4.6.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.6.0...v5.0.0) - [github.com/psf/black: 24.8.0 → 24.10.0](https://github.com/psf/black/compare/24.8.0...24.10.0) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8c69882f7..65aeabd18 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,16 +4,16 @@ ci: autoupdate_schedule: quarterly repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v18.1.8 + rev: v19.1.3 hooks: - id: clang-format args: ['--style={BasedOnStyle: Mozilla, SortIncludes: false}'] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 24.8.0 + rev: 24.10.0 hooks: - id: black - repo: https://github.com/cheshirekow/cmake-format-precommit From 46461795b4cf189d228d988d7db5a05d825b0e9a Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:32:23 +0100 Subject: [PATCH 082/109] fix windows build error --- include/proxsuite/linalg/veg/tuple.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/proxsuite/linalg/veg/tuple.hpp b/include/proxsuite/linalg/veg/tuple.hpp index 8fe3ca1a9..36fea520d 100644 --- a/include/proxsuite/linalg/veg/tuple.hpp +++ b/include/proxsuite/linalg/veg/tuple.hpp @@ -754,9 +754,15 @@ struct cat proxsuite::linalg::veg::meta::false_type /*unused*/, Tuples&&... tups) VEG_NOEXCEPT -> Concat { - return cat::template from_ref_to_result( - Tag>{}, - cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); +#ifdef _MSC_VER +return cat::from_ref_to_result( + Tag>{}, + cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); +#else +return cat::template from_ref_to_result( + Tag>{}, + cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); +#endif } template From 1dd0c2b40da31b8b3812781af33a29e8b435a7ee Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Thu, 28 Nov 2024 12:04:14 +0100 Subject: [PATCH 083/109] discover cpp tests --- .github/workflows/ci-linux-osx-win-conda.yml | 2 +- test/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index ac7ed0e53..f111ac0d0 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -80,7 +80,7 @@ jobs: # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 conda config --remove channels defaults # Compilation related dependencies - mamba install cmake compilers make pkg-config doxygen ninja graphviz typing_extensions + mamba install cmake compilers make pkg-config doxygen ninja graphviz typing_extensions llvm-openmp # Main dependencies mamba install eigen simde # Test dependencies diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bc6ba4a0b..1d0960d46 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,7 +22,7 @@ endif() macro(proxsuite_test name path) set(target_name ${PROJECT_NAME}-test-cpp-${name}) add_executable(${target_name} ${path}) - # doctest_discover_tests(${target_name}) + doctest_discover_tests(${target_name}) target_link_libraries(${target_name} PUBLIC proxsuite ${PROJECT_NAME}-doctest proxsuite-test-util) target_compile_definitions(${target_name} From 7b9c3260df2b1fb9f2abc1c2670203d4156054c8 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:26:29 +0100 Subject: [PATCH 084/109] do not run julia example --- .github/workflows/ci-linux-osx-win-conda.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index f111ac0d0..1b74bd091 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -114,7 +114,7 @@ jobs: git submodule update --init mkdir build cd build - cmake .. -GNinja -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_EXECUTABLE=$(which python3) -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON -DTEST_JULIA_INTERFACE:BOOL=ON -DOpenMP_ROOT=$CONDA_PREFIX + cmake .. -GNinja -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_EXECUTABLE=$(which python3) -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON -DTEST_JULIA_INTERFACE:BOOL=OFF -DOpenMP_ROOT=$CONDA_PREFIX - name: Configure [Conda/macOS14] if: contains(matrix.os, 'macos-14') @@ -135,7 +135,7 @@ jobs: echo $(whereis ccache) echo $(which ccache) cd build - cmake .. -GNinja -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCHECK_RUNTIME_MALLOC:BOOL=ON -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_EXECUTABLE=$(which python3) -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON -DTEST_JULIA_INTERFACE:BOOL=ON -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DOpenMP_ROOT=$CONDA_PREFIX + cmake .. -GNinja -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCHECK_RUNTIME_MALLOC:BOOL=ON -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_EXECUTABLE=$(which python3) -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON -DTEST_JULIA_INTERFACE:BOOL=OFF -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DOpenMP_ROOT=$CONDA_PREFIX - name: Configure [Conda/Windows-2019] if: contains(matrix.os, 'windows-2019') From 124100f7885be0cb66a62331872297ec0426d296 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:05:08 +0100 Subject: [PATCH 085/109] edit changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f546a3f5..dacdbf799 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed * CMake: Fix link to system cereal in tests ([#353](https://github.com/Simple-Robotics/proxsuite/pull/352)) +* Fix windows build error related to template usage in veg ([#357](https://github.com/Simple-Robotics/proxsuite/pull/357)) ### Added * Stub files for Python bindings, using [nanobind's native support](https://nanobind.readthedocs.io/en/latest/typing.html#stub-generation) ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) From da71abf7bd8094dc158b3fd1a26b99d12c6fe969 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:14:40 +0100 Subject: [PATCH 086/109] apply pre-commit --- include/proxsuite/linalg/dense/core.hpp | 121 ++++++++---------- include/proxsuite/linalg/dense/factorize.hpp | 4 +- include/proxsuite/linalg/dense/ldlt.hpp | 24 ++-- include/proxsuite/linalg/sparse/factorize.hpp | 13 +- .../linalg/veg/internal/dyn_index.hpp | 8 +- .../veg/internal/external/hedley.ext.hpp | 2 +- .../proxsuite/linalg/veg/internal/macros.hpp | 24 ++-- .../linalg/veg/memory/dynamic_stack.hpp | 4 +- .../linalg/veg/memory/stack_alloc.hpp | 16 +-- include/proxsuite/linalg/veg/slice.hpp | 8 +- include/proxsuite/linalg/veg/tuple.hpp | 34 ++--- .../linalg/veg/type_traits/constructible.hpp | 2 +- include/proxsuite/linalg/veg/util/get.hpp | 4 +- include/proxsuite/linalg/veg/vec.hpp | 6 +- include/proxsuite/proxqp/dense/views.hpp | 31 ++--- include/proxsuite/proxqp/sparse/utils.hpp | 43 ++++--- .../proxqp/utils/random_qp_problems.hpp | 25 ++-- test/CMakeLists.txt | 3 +- test/doctest/doctest.hpp | 3 +- 19 files changed, 176 insertions(+), 199 deletions(-) diff --git a/include/proxsuite/linalg/dense/core.hpp b/include/proxsuite/linalg/dense/core.hpp index a5f1dffc2..5c43d5005 100644 --- a/include/proxsuite/linalg/dense/core.hpp +++ b/include/proxsuite/linalg/dense/core.hpp @@ -117,8 +117,8 @@ static_assert(sizeof(f64) == 8, "f64 should be 64 bits"); LDLT_FN_IMPL3(fnmadd, Prefix, Suffix); /* (-a * b + c) */ #define LDLT_LOAD_STORE(Prefix, Suffix) \ - VEG_INLINE static auto load_unaligned( \ - ScalarType const* ptr) noexcept -> Pack \ + VEG_INLINE static auto load_unaligned(ScalarType const* ptr) noexcept \ + -> Pack \ { \ return Pack{ simde_mm##Prefix##_loadu_##Suffix(ptr) }; \ } \ @@ -560,9 +560,8 @@ elem_addr(T* ptr, template auto -matrix_elem_addr(Mat&& mat, - isize row, - isize col) noexcept -> decltype(mat.data()) +matrix_elem_addr(Mat&& mat, isize row, isize col) noexcept + -> decltype(mat.data()) { return util::elem_addr::IsRowMajor)>( // @@ -575,18 +574,16 @@ matrix_elem_addr(Mat&& mat, template auto -col(T&& mat, isize col_idx) noexcept -> - typename _detail::RowColAccessImpl< - !bool(proxsuite::linalg::veg::uncvref_t::IsRowMajor)>::template Col +col(T&& mat, isize col_idx) noexcept -> typename _detail::RowColAccessImpl< + !bool(proxsuite::linalg::veg::uncvref_t::IsRowMajor)>::template Col { return _detail::RowColAccessImpl::IsRowMajor)>::col(mat, col_idx); } template auto -row(T&& mat, isize row_idx) noexcept -> - typename _detail::RowColAccessImpl< - !bool(proxsuite::linalg::veg::uncvref_t::IsRowMajor)>::template Row +row(T&& mat, isize row_idx) noexcept -> typename _detail::RowColAccessImpl< + !bool(proxsuite::linalg::veg::uncvref_t::IsRowMajor)>::template Row { return _detail::RowColAccessImpl::IsRowMajor)>::row(mat, row_idx); @@ -594,19 +591,17 @@ row(T&& mat, isize row_idx) noexcept -> template auto -trans(Mat&& mat) noexcept - -> Eigen::Map< // - _detail::const_if< - _detail::ptr_is_const::value, - Eigen::Matrix< // - typename proxsuite::linalg::veg::uncvref_t::Scalar, - proxsuite::linalg::veg::uncvref_t::ColsAtCompileTime, - proxsuite::linalg::veg::uncvref_t::RowsAtCompileTime, - bool(proxsuite::linalg::veg::uncvref_t::IsRowMajor) - ? Eigen::ColMajor - : Eigen::RowMajor>>, - Eigen::Unaligned, - _detail::StrideOf>> +trans(Mat&& mat) noexcept -> Eigen::Map< // + _detail::const_if<_detail::ptr_is_const::value, + Eigen::Matrix< // + typename proxsuite::linalg::veg::uncvref_t::Scalar, + proxsuite::linalg::veg::uncvref_t::ColsAtCompileTime, + proxsuite::linalg::veg::uncvref_t::RowsAtCompileTime, + bool(proxsuite::linalg::veg::uncvref_t::IsRowMajor) + ? Eigen::ColMajor + : Eigen::RowMajor>>, + Eigen::Unaligned, + _detail::StrideOf>> { return { mat.data(), @@ -621,16 +616,15 @@ trans(Mat&& mat) noexcept template auto -diagonal(Mat&& mat) noexcept - -> Eigen::Map< // - _detail::const_if<_detail::ptr_is_const::value, - Eigen::Matrix< // - typename proxsuite::linalg::veg::uncvref_t::Scalar, - Eigen::Dynamic, - 1, - Eigen::ColMajor>>, - Eigen::Unaligned, - Eigen::InnerStride> +diagonal(Mat&& mat) noexcept -> Eigen::Map< // + _detail::const_if<_detail::ptr_is_const::value, + Eigen::Matrix< // + typename proxsuite::linalg::veg::uncvref_t::Scalar, + Eigen::Dynamic, + 1, + Eigen::ColMajor>>, + Eigen::Unaligned, + Eigen::InnerStride> { VEG_DEBUG_ASSERT( // mat.rows() == mat.cols()); @@ -667,12 +661,11 @@ submatrix(Mat&& mat, template auto -to_view(Mat&& mat) noexcept - -> Eigen::Map<_detail::const_if< - _detail::ptr_is_const::value, - _detail::OwnedAll>>, - Eigen::Unaligned, - _detail::StrideOf>> +to_view(Mat&& mat) noexcept -> Eigen::Map< + _detail::const_if<_detail::ptr_is_const::value, + _detail::OwnedAll>>, + Eigen::Unaligned, + _detail::StrideOf>> { return { mat.data(), @@ -687,12 +680,11 @@ to_view(Mat&& mat) noexcept template auto -to_view_dyn_rows(Mat&& mat) noexcept - -> Eigen::Map<_detail::const_if< - _detail::ptr_is_const::value, - _detail::OwnedRows>>, - Eigen::Unaligned, - _detail::StrideOf>> +to_view_dyn_rows(Mat&& mat) noexcept -> Eigen::Map< + _detail::const_if<_detail::ptr_is_const::value, + _detail::OwnedRows>>, + Eigen::Unaligned, + _detail::StrideOf>> { return { mat.data(), @@ -707,12 +699,11 @@ to_view_dyn_rows(Mat&& mat) noexcept template auto -to_view_dyn_cols(Mat&& mat) noexcept - -> Eigen::Map<_detail::const_if< - _detail::ptr_is_const::value, - _detail::OwnedCols>>, - Eigen::Unaligned, - _detail::StrideOf>> +to_view_dyn_cols(Mat&& mat) noexcept -> Eigen::Map< + _detail::const_if<_detail::ptr_is_const::value, + _detail::OwnedCols>>, + Eigen::Unaligned, + _detail::StrideOf>> { return { mat.data(), @@ -747,12 +738,11 @@ to_view_dyn(Mat&& mat) noexcept template auto -subrows(Mat&& mat, isize row_start, isize nrows) noexcept - -> Eigen::Map<_detail::const_if< - _detail::ptr_is_const::value, - _detail::OwnedRows>>, - Eigen::Unaligned, - _detail::StrideOf>> +subrows(Mat&& mat, isize row_start, isize nrows) noexcept -> Eigen::Map< + _detail::const_if<_detail::ptr_is_const::value, + _detail::OwnedRows>>, + Eigen::Unaligned, + _detail::StrideOf>> { return { util::elem_addr::IsRowMajor)>( @@ -768,12 +758,11 @@ subrows(Mat&& mat, isize row_start, isize nrows) noexcept template auto -subcols(Mat&& mat, isize col_start, isize ncols) noexcept - -> Eigen::Map<_detail::const_if< - _detail::ptr_is_const::value, - _detail::OwnedCols>>, - Eigen::Unaligned, - _detail::StrideOf>> +subcols(Mat&& mat, isize col_start, isize ncols) noexcept -> Eigen::Map< + _detail::const_if<_detail::ptr_is_const::value, + _detail::OwnedCols>>, + Eigen::Unaligned, + _detail::StrideOf>> { return { util::elem_addr::IsRowMajor)>( @@ -859,8 +848,8 @@ temp_mat_req(proxsuite::linalg::veg::Tag /*tag*/, template auto -temp_vec_req(proxsuite::linalg::veg::Tag /*tag*/, - isize rows) noexcept -> proxsuite::linalg::veg::dynstack::StackReq +temp_vec_req(proxsuite::linalg::veg::Tag /*tag*/, isize rows) noexcept + -> proxsuite::linalg::veg::dynstack::StackReq { return { rows * isize{ sizeof(T) }, diff --git a/include/proxsuite/linalg/dense/factorize.hpp b/include/proxsuite/linalg/dense/factorize.hpp index c11f2368b..1f3c20e3f 100644 --- a/include/proxsuite/linalg/dense/factorize.hpp +++ b/include/proxsuite/linalg/dense/factorize.hpp @@ -350,8 +350,8 @@ factorize_recursive(Mat&& mat, template auto -factorize_req(proxsuite::linalg::veg::Tag tag, - isize n) noexcept -> proxsuite::linalg::veg::dynstack::StackReq +factorize_req(proxsuite::linalg::veg::Tag tag, isize n) noexcept + -> proxsuite::linalg::veg::dynstack::StackReq { return proxsuite::linalg::dense::factorize_blocked_req(tag, n, 128) | proxsuite::linalg::dense::factorize_recursive_req(tag, n); diff --git a/include/proxsuite/linalg/dense/ldlt.hpp b/include/proxsuite/linalg/dense/ldlt.hpp index 1a64dfd23..b74bde51a 100644 --- a/include/proxsuite/linalg/dense/ldlt.hpp +++ b/include/proxsuite/linalg/dense/ldlt.hpp @@ -614,23 +614,23 @@ struct Ldlt auto dim() const noexcept -> isize { return perm.len(); } auto ld_col() const noexcept -> Eigen::Map< // - ColMat const, - Eigen::Unaligned, - Eigen::OuterStride> + ColMat const, + Eigen::Unaligned, + Eigen::OuterStride> { return { ld_storage.ptr(), dim(), dim(), stride }; } auto ld_col_mut() noexcept -> Eigen::Map< // - ColMat, - Eigen::Unaligned, - Eigen::OuterStride> + ColMat, + Eigen::Unaligned, + Eigen::OuterStride> { return { ld_storage.ptr_mut(), dim(), dim(), stride }; } auto ld_row() const noexcept -> Eigen::Map< // - RowMat const, - Eigen::Unaligned, - Eigen::OuterStride> + RowMat const, + Eigen::Unaligned, + Eigen::OuterStride> { return { ld_storage.ptr(), @@ -640,9 +640,9 @@ struct Ldlt }; } auto ld_row_mut() noexcept -> Eigen::Map< // - RowMat, - Eigen::Unaligned, - Eigen::OuterStride> + RowMat, + Eigen::Unaligned, + Eigen::OuterStride> { return { ld_storage.ptr_mut(), diff --git a/include/proxsuite/linalg/sparse/factorize.hpp b/include/proxsuite/linalg/sparse/factorize.hpp index 46451dd1c..225a82f7b 100644 --- a/include/proxsuite/linalg/sparse/factorize.hpp +++ b/include/proxsuite/linalg/sparse/factorize.hpp @@ -249,8 +249,8 @@ dense_ltsolve(DenseVecMut x, MatRef l) noexcept(false) */ template auto -etree_req(proxsuite::linalg::veg::Tag /*tag*/, - isize n) noexcept -> proxsuite::linalg::veg::dynstack::StackReq +etree_req(proxsuite::linalg::veg::Tag /*tag*/, isize n) noexcept + -> proxsuite::linalg::veg::dynstack::StackReq { return { n * isize{ sizeof(I) }, alignof(I) }; } @@ -456,8 +456,8 @@ postorder_depth_first_search( // */ template auto -postorder_req(proxsuite::linalg::veg::Tag /*tag*/, - isize n) noexcept -> proxsuite::linalg::veg::dynstack::StackReq +postorder_req(proxsuite::linalg::veg::Tag /*tag*/, isize n) noexcept + -> proxsuite::linalg::veg::dynstack::StackReq { return { (3 * n) * isize(sizeof(I)), alignof(I) }; } @@ -716,9 +716,8 @@ column_counts(I* counts, template auto -amd_req(proxsuite::linalg::veg::Tag /*tag*/, - isize /*n*/, - isize nnz) noexcept -> proxsuite::linalg::veg::dynstack::StackReq +amd_req(proxsuite::linalg::veg::Tag /*tag*/, isize /*n*/, isize nnz) noexcept + -> proxsuite::linalg::veg::dynstack::StackReq { return { nnz * isize{ sizeof(char) }, alignof(char) }; } diff --git a/include/proxsuite/linalg/veg/internal/dyn_index.hpp b/include/proxsuite/linalg/veg/internal/dyn_index.hpp index ce3c4050b..5b208293b 100644 --- a/include/proxsuite/linalg/veg/internal/dyn_index.hpp +++ b/include/proxsuite/linalg/veg/internal/dyn_index.hpp @@ -223,8 +223,8 @@ struct binary_traits, Dyn> : binary_traits { using Mul = Fix<0>; VEG_NODISCARD - constexpr VEG_INLINE static auto mul_fn(Fix<0> /*a*/, - Dyn /*b*/) VEG_NOEXCEPT -> Mul + constexpr VEG_INLINE static auto mul_fn(Fix<0> /*a*/, Dyn /*b*/) VEG_NOEXCEPT + -> Mul { return {}; } @@ -234,8 +234,8 @@ template struct binary_traits> : binary_traits { using Mul = typename binary_traits, Dyn>::Mul; - VEG_INLINE static constexpr auto mul_fn(Dyn a, - Fix /*b*/) VEG_NOEXCEPT -> Mul + VEG_INLINE static constexpr auto mul_fn(Dyn a, Fix /*b*/) VEG_NOEXCEPT + -> Mul { return binary_traits, Dyn>::mul_fn({}, a); } diff --git a/include/proxsuite/linalg/veg/internal/external/hedley.ext.hpp b/include/proxsuite/linalg/veg/internal/external/hedley.ext.hpp index 91a3edf63..af3872e25 100644 --- a/include/proxsuite/linalg/veg/internal/external/hedley.ext.hpp +++ b/include/proxsuite/linalg/veg/internal/external/hedley.ext.hpp @@ -1838,7 +1838,7 @@ HEDLEY_DIAGNOSTIC_POP #else #include #define HEDLEY_IS_CONSTEXPR_(expr) \ - _Generic((1 ? (void*)((intptr_t) * 0) : (int*)0), int*: 1, void*: 0) + _Generic((1 ? (void*)((intptr_t)*0) : (int*)0), int*: 1, void*: 0) #endif #elif defined(HEDLEY_GCC_VERSION) || defined(HEDLEY_INTEL_VERSION) || \ defined(HEDLEY_TINYC_VERSION) || defined(HEDLEY_TI_ARMCL_VERSION) || \ diff --git a/include/proxsuite/linalg/veg/internal/macros.hpp b/include/proxsuite/linalg/veg/internal/macros.hpp index eed6354a3..5f277f443 100644 --- a/include/proxsuite/linalg/veg/internal/macros.hpp +++ b/include/proxsuite/linalg/veg/internal/macros.hpp @@ -324,11 +324,11 @@ Name, \ (__VA_ARGS__), \ ::proxsuite::linalg::veg::meta::bool_constant<__VA_ARGS__>); \ - VEG_TEMPLATE( \ - Tpl, \ - requires(__VA_ARGS__), \ - constexpr auto check_##Name, \ - (_ = 0, int)) noexcept -> ::proxsuite::linalg::veg::meta::true_type + VEG_TEMPLATE(Tpl, \ + requires(__VA_ARGS__), \ + constexpr auto check_##Name, \ + (_ = 0, int)) noexcept \ + -> ::proxsuite::linalg::veg::meta::true_type #define __VEG_IMPL_SFINAE(_, Param) \ , ::proxsuite::linalg::veg::meta:: \ @@ -1195,20 +1195,18 @@ struct ExtractCharsImplExpr> template auto -extract_chars(LiteralType /*unused*/) -> - typename ExtractCharsImpl< - LiteralType, - _meta::make_index_sequence>::Type +extract_chars(LiteralType /*unused*/) -> typename ExtractCharsImpl< + LiteralType, + _meta::make_index_sequence>::Type { return {}; } template auto -extract_chars_expr(LiteralType /*unused*/) -> - typename ExtractCharsImplExpr< - LiteralType, - _meta::make_index_sequence>::Type +extract_chars_expr(LiteralType /*unused*/) -> typename ExtractCharsImplExpr< + LiteralType, + _meta::make_index_sequence>::Type { return {}; } diff --git a/include/proxsuite/linalg/veg/memory/dynamic_stack.hpp b/include/proxsuite/linalg/veg/memory/dynamic_stack.hpp index b6110d1ed..528d6e900 100644 --- a/include/proxsuite/linalg/veg/memory/dynamic_stack.hpp +++ b/include/proxsuite/linalg/veg/memory/dynamic_stack.hpp @@ -279,8 +279,8 @@ struct DynStackMut template VEG_NODISCARD auto make_alloc(Tag /*unused*/, isize len, - isize align = alignof(T)) - VEG_NOEXCEPT -> DynStackAlloc + isize align = alignof(T)) VEG_NOEXCEPT + -> DynStackAlloc { assert_valid_len(len); DynStackAlloc get{ diff --git a/include/proxsuite/linalg/veg/memory/stack_alloc.hpp b/include/proxsuite/linalg/veg/memory/stack_alloc.hpp index a0affffb9..becb39cb6 100644 --- a/include/proxsuite/linalg/veg/memory/stack_alloc.hpp +++ b/include/proxsuite/linalg/veg/memory/stack_alloc.hpp @@ -76,8 +76,8 @@ struct BumpAllocLayout return blk; } - auto _grow_last_unchecked(void* ptr, - usize new_byte_size) noexcept -> mem::AllocBlock + auto _grow_last_unchecked(void* ptr, usize new_byte_size) noexcept + -> mem::AllocBlock { auto rem_bytes = usize(end_ptr - static_cast(ptr)); auto given_bytes = _align(new_byte_size); @@ -157,8 +157,8 @@ struct Alloc> using ImplMut = _detail::_mem::BumpAllocLayout&; using RefMut = proxsuite::linalg::veg::RefMut>; - VEG_INLINE static auto alloc(RefMut ref, - mem::Layout layout) noexcept -> AllocBlock + VEG_INLINE static auto alloc(RefMut ref, mem::Layout layout) noexcept + -> AllocBlock { return ImplMut(ref.get())._alloc(layout); } @@ -184,8 +184,8 @@ struct Alloc> using ImplMut = _detail::_mem::BumpAllocLayout&; using RefMut = proxsuite::linalg::veg::RefMut>; - VEG_INLINE static auto alloc(RefMut ref, - mem::Layout layout) noexcept -> AllocBlock + VEG_INLINE static auto alloc(RefMut ref, mem::Layout layout) noexcept + -> AllocBlock { return ImplMut(ref.get())._alloc(layout); } @@ -211,8 +211,8 @@ struct Alloc> using ImplMut = _detail::_mem::BumpAllocLayout&; using RefMut = proxsuite::linalg::veg::RefMut>; - VEG_INLINE static auto alloc(RefMut ref, - mem::Layout layout) noexcept -> AllocBlock + VEG_INLINE static auto alloc(RefMut ref, mem::Layout layout) noexcept + -> AllocBlock { return ImplMut(ref.get())._alloc(layout); } diff --git a/include/proxsuite/linalg/veg/slice.hpp b/include/proxsuite/linalg/veg/slice.hpp index 965875619..8abb3f0ee 100644 --- a/include/proxsuite/linalg/veg/slice.hpp +++ b/include/proxsuite/linalg/veg/slice.hpp @@ -60,8 +60,8 @@ struct Slice : _detail::_slice::adl::AdlBase } VEG_NODISCARD VEG_INLINE - constexpr auto get_unchecked(Unsafe /*tag*/, - isize idx) const VEG_NOEXCEPT -> Ref + constexpr auto get_unchecked(Unsafe /*tag*/, isize idx) const VEG_NOEXCEPT + -> Ref { return ref(*(data + idx)); } @@ -149,8 +149,8 @@ struct SliceMut : private Slice { return mut(const_cast(*(this->data + idx))); } - VEG_NODISCARD VEG_INLINE auto as_mut_bytes() - VEG_NOEXCEPT -> SliceMut + VEG_NODISCARD VEG_INLINE auto as_mut_bytes() VEG_NOEXCEPT + -> SliceMut { return { unsafe, diff --git a/include/proxsuite/linalg/veg/tuple.hpp b/include/proxsuite/linalg/veg/tuple.hpp index 36fea520d..d0104bd47 100644 --- a/include/proxsuite/linalg/veg/tuple.hpp +++ b/include/proxsuite/linalg/veg/tuple.hpp @@ -401,7 +401,7 @@ struct IndexedTuple, Ts...> (/*arg*/, Fix)) && VEG_NOEXCEPT_IF( VEG_CONCEPT(nothrow_movable(I), Ts...>>)) - -> ith(I), Ts...> + -> ith(I), Ts...> { return __VEG_IMPL_LEAF_ONCE( *this, static_cast(I), ith(I), Ts...>); @@ -535,8 +535,8 @@ get(tuple::IndexedTuple, template VEG_NODISCARD VEG_INLINE constexpr auto get(tuple::IndexedTuple, - Ts...> const&& tup) - VEG_NOEXCEPT -> ith const&& + Ts...> const&& tup) VEG_NOEXCEPT + -> ith const&& { return static_cast const&&>( __VEG_IMPL_LEAF(tup, I, ith)); @@ -659,9 +659,9 @@ struct zip VEG_INLINE static constexpr auto apply( IndexedTuple, Ts...> first, - Tuples... rest) VEG_NOEXCEPT -> Tuple< // - typename Helper:: // - template Type...> + Tuples... rest) VEG_NOEXCEPT -> Tuple< // + typename Helper:: // + template Type...> { return { ((void)first, tuplify{}), @@ -755,13 +755,13 @@ struct cat Tuples&&... tups) VEG_NOEXCEPT -> Concat { #ifdef _MSC_VER -return cat::from_ref_to_result( - Tag>{}, - cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); + return cat::from_ref_to_result( + Tag>{}, + cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); #else -return cat::template from_ref_to_result( - Tag>{}, - cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); + return cat::template from_ref_to_result( + Tag>{}, + cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); #endif } @@ -783,11 +783,11 @@ return cat::template from_ref_to_result( VEG_INLINE static constexpr auto apply( IndexedTuple, Ts...>&& first, - Tuples&&... rest) - VEG_NOEXCEPT -> proxsuite::linalg::veg::meta::type_sequence_cat< - Tuple, - Tuple, - typename _detail::meta_::IndexedToTuple::Type...> + Tuples&&... rest) VEG_NOEXCEPT + -> proxsuite::linalg::veg::meta::type_sequence_cat< + Tuple, + Tuple, + typename _detail::meta_::IndexedToTuple::Type...> { return cat::apply2(VEG_FWD(first), cat::apply(VEG_FWD(rest)...)); } diff --git a/include/proxsuite/linalg/veg/type_traits/constructible.hpp b/include/proxsuite/linalg/veg/type_traits/constructible.hpp index ce1ed6396..1872b3e59 100644 --- a/include/proxsuite/linalg/veg/type_traits/constructible.hpp +++ b/include/proxsuite/linalg/veg/type_traits/constructible.hpp @@ -189,7 +189,7 @@ struct WithArg Fn&& fn; T&& arg; VEG_INLINE constexpr auto operator()() const&& -> decltype(VEG_FWD(fn)( - VEG_FWD(arg))) + VEG_FWD(arg))) { return VEG_FWD(fn)(VEG_FWD(arg)); } diff --git a/include/proxsuite/linalg/veg/util/get.hpp b/include/proxsuite/linalg/veg/util/get.hpp index df0f3789e..453e63c9a 100644 --- a/include/proxsuite/linalg/veg/util/get.hpp +++ b/include/proxsuite/linalg/veg/util/get.hpp @@ -36,8 +36,8 @@ struct array_get using result_type = decltype(VEG_DECLVAL(T&&)[I::value]); template - VEG_INLINE static constexpr auto apply(T&& arr) - VEG_NOEXCEPT -> decltype(VEG_FWD(arr)[I]) + VEG_INLINE static constexpr auto apply(T&& arr) VEG_NOEXCEPT + -> decltype(VEG_FWD(arr)[I]) { return VEG_FWD(arr)[I]; } diff --git a/include/proxsuite/linalg/veg/vec.hpp b/include/proxsuite/linalg/veg/vec.hpp index eb409c3e6..f6166208d 100644 --- a/include/proxsuite/linalg/veg/vec.hpp +++ b/include/proxsuite/linalg/veg/vec.hpp @@ -277,9 +277,9 @@ realloc_and_append( // mem::AllocBlock out, usize out_len, T const* in, - usize in_len) - VEG_NOEXCEPT_IF(VEG_CONCEPT(alloc::nothrow_grow) && - VEG_CONCEPT(alloc::nothrow_clone)) -> mem::AllocBlock + usize in_len) VEG_NOEXCEPT_IF(VEG_CONCEPT(alloc::nothrow_grow) && + VEG_CONCEPT(alloc::nothrow_clone)) + -> mem::AllocBlock { if (in_len == 0) { diff --git a/include/proxsuite/proxqp/dense/views.hpp b/include/proxsuite/proxqp/dense/views.hpp index c8cc22c6e..c43c8cae9 100644 --- a/include/proxsuite/proxqp/dense/views.hpp +++ b/include/proxsuite/proxqp/dense/views.hpp @@ -395,8 +395,7 @@ using DataExpr = decltype(static_cast(VEG_DECLVAL(Mat&).data())); template - class F, + template class F, typename... Ts> struct DetectedImpl : proxsuite::linalg::veg::meta::false_type { @@ -717,8 +716,8 @@ struct StridedVectorView { return *ptr(index); } - VEG_INLINE auto segment(isize i, - isize size) const noexcept -> StridedVectorView + VEG_INLINE auto segment(isize i, isize size) const noexcept + -> StridedVectorView { return { from_ptr_size_stride, @@ -784,8 +783,8 @@ struct StridedVectorViewMut { return *ptr(index); } - VEG_INLINE auto segment(isize i, - isize size) const noexcept -> StridedVectorViewMut + VEG_INLINE auto segment(isize i, isize size) const noexcept + -> StridedVectorViewMut { return { from_ptr_size_stride, @@ -884,15 +883,13 @@ struct MatrixView } public: - VEG_INLINE auto col(isize c) const noexcept - -> proxsuite::linalg::veg::meta:: - if_t<(L == colmajor), VectorView, StridedVectorView> + VEG_INLINE auto col(isize c) const noexcept -> proxsuite::linalg::veg::meta:: + if_t<(L == colmajor), VectorView, StridedVectorView> { return col_impl(proxsuite::linalg::veg::meta::constant{}, c); } - VEG_INLINE auto row(isize r) const noexcept - -> proxsuite::linalg::veg::meta:: - if_t<(L == rowmajor), VectorView, StridedVectorView> + VEG_INLINE auto row(isize r) const noexcept -> proxsuite::linalg::veg::meta:: + if_t<(L == rowmajor), VectorView, StridedVectorView> { return trans().col(r); } @@ -992,15 +989,13 @@ struct MatrixViewMut } public: - VEG_INLINE auto col(isize c) const noexcept - -> proxsuite::linalg::veg::meta:: - if_t<(L == colmajor), VectorViewMut, StridedVectorViewMut> + VEG_INLINE auto col(isize c) const noexcept -> proxsuite::linalg::veg::meta:: + if_t<(L == colmajor), VectorViewMut, StridedVectorViewMut> { return col_impl(proxsuite::linalg::veg::meta::constant{}, c); } - VEG_INLINE auto row(isize r) const noexcept - -> proxsuite::linalg::veg::meta:: - if_t<(L == rowmajor), VectorViewMut, StridedVectorViewMut> + VEG_INLINE auto row(isize r) const noexcept -> proxsuite::linalg::veg::meta:: + if_t<(L == rowmajor), VectorViewMut, StridedVectorViewMut> { return trans().col(r); } diff --git a/include/proxsuite/proxqp/sparse/utils.hpp b/include/proxsuite/proxqp/sparse/utils.hpp index 62e55413b..fe1e4b275 100644 --- a/include/proxsuite/proxqp/sparse/utils.hpp +++ b/include/proxsuite/proxqp/sparse/utils.hpp @@ -613,27 +613,28 @@ global_dual_residual_infeasibility(VectorViewMut Adx, */ template auto -unscaled_primal_dual_residual(Workspace& work, - Results& results, - const Settings& settings, - VecMapMut primal_residual_eq_scaled, - VecMapMut primal_residual_in_scaled_lo, - VecMapMut primal_residual_in_scaled_up, - VecMapMut dual_residual_scaled, - T& primal_feasibility_eq_rhs_0, - T& primal_feasibility_in_rhs_0, - T& dual_feasibility_rhs_0, - T& dual_feasibility_rhs_1, - T& dual_feasibility_rhs_3, - T& rhs_duality_gap, - const P& precond, - Model const& data, - const QpView qp_scaled, - VecMapMut x_e, - VecMapMut y_e, - VecMapMut z_e, - proxsuite::linalg::veg::dynstack::DynStackMut - stack) -> proxsuite::linalg::veg::Tuple +unscaled_primal_dual_residual( + Workspace& work, + Results& results, + const Settings& settings, + VecMapMut primal_residual_eq_scaled, + VecMapMut primal_residual_in_scaled_lo, + VecMapMut primal_residual_in_scaled_up, + VecMapMut dual_residual_scaled, + T& primal_feasibility_eq_rhs_0, + T& primal_feasibility_in_rhs_0, + T& dual_feasibility_rhs_0, + T& dual_feasibility_rhs_1, + T& dual_feasibility_rhs_3, + T& rhs_duality_gap, + const P& precond, + Model const& data, + const QpView qp_scaled, + VecMapMut x_e, + VecMapMut y_e, + VecMapMut z_e, + proxsuite::linalg::veg::dynstack::DynStackMut stack) + -> proxsuite::linalg::veg::Tuple { isize n = x_e.rows(); diff --git a/include/proxsuite/proxqp/utils/random_qp_problems.hpp b/include/proxsuite/proxqp/utils/random_qp_problems.hpp index 2a13423c6..e08641d47 100644 --- a/include/proxsuite/proxqp/utils/random_qp_problems.hpp +++ b/include/proxsuite/proxqp/utils/random_qp_problems.hpp @@ -226,9 +226,8 @@ positive_definite_rand(isize n, Scalar cond) -> Mat template auto -sparse_positive_definite_rand(isize n, - Scalar cond, - Scalar p) -> SparseMat +sparse_positive_definite_rand(isize n, Scalar cond, Scalar p) + -> SparseMat { auto H = SparseMat(n, n); @@ -277,9 +276,8 @@ sparse_positive_definite_rand(isize n, template auto -sparse_positive_definite_rand_compressed(isize n, - Scalar rho, - Scalar p) -> SparseMat +sparse_positive_definite_rand_compressed(isize n, Scalar rho, Scalar p) + -> SparseMat { auto H = SparseMat(n, n); @@ -308,9 +306,8 @@ sparse_positive_definite_rand_compressed(isize n, template auto -sparse_positive_definite_rand_not_compressed(isize n, - Scalar rho, - Scalar p) -> Mat +sparse_positive_definite_rand_not_compressed(isize n, Scalar rho, Scalar p) + -> Mat { auto H = Mat(n, n); H.setZero(); @@ -355,9 +352,8 @@ sparse_matrix_rand(isize nrows, isize ncols, Scalar p) -> SparseMat template auto -sparse_matrix_rand_not_compressed(isize nrows, - isize ncols, - Scalar p) -> Mat +sparse_matrix_rand_not_compressed(isize nrows, isize ncols, Scalar p) + -> Mat { auto A = Mat(nrows, ncols); A.setZero(); @@ -416,9 +412,8 @@ template auto -matmul3(MatLhs const& a, - MatMid const& b, - MatRhs const& c) -> Mat +matmul3(MatLhs const& a, MatMid const& b, MatRhs const& c) + -> Mat { return matmul(matmul(a, b), c); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1d0960d46..f1fcd7a95 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -65,7 +65,8 @@ add_test_cflags( "-DTEST_SERIALIZATION_FOLDER=\\\\\"${CMAKE_CURRENT_BINARY_DIR}/serialization-data\\\\\"" ) if(cereal_FOUND) - target_link_libraries(${PROJECT_NAME}-test-cpp-serialization PRIVATE cereal::cereal) + target_link_libraries(${PROJECT_NAME}-test-cpp-serialization + PRIVATE cereal::cereal) else() target_include_directories( ${PROJECT_NAME}-test-cpp-serialization SYSTEM diff --git a/test/doctest/doctest.hpp b/test/doctest/doctest.hpp index 3aa1418e0..f44173193 100644 --- a/test/doctest/doctest.hpp +++ b/test/doctest/doctest.hpp @@ -1563,8 +1563,7 @@ namespace detail { #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING // clang-format on -struct DOCTEST_INTERFACE TestFailureException -{}; +struct DOCTEST_INTERFACE TestFailureException{}; DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); From c0664d5aeb8b403a9c07b49d11f4ff649cb2c6df Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Wed, 4 Dec 2024 10:29:21 +0100 Subject: [PATCH 087/109] ci: Use conda-forge clang --- .github/workflows/ci-linux-osx-win-conda.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index 1b74bd091..8c0f163ae 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -80,7 +80,7 @@ jobs: # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 conda config --remove channels defaults # Compilation related dependencies - mamba install cmake compilers make pkg-config doxygen ninja graphviz typing_extensions llvm-openmp + mamba install cmake compilers make pkg-config doxygen ninja graphviz typing_extensions llvm-openmp clang # Main dependencies mamba install eigen simde # Test dependencies From 645acb1117cdf87dc263df60598755f40d0f856a Mon Sep 17 00:00:00 2001 From: Joris Vaillant Date: Wed, 4 Dec 2024 10:43:14 +0100 Subject: [PATCH 088/109] ci: Use Ninja CMake generator to try to find conda-forge clang-cl --- .github/workflows/ci-linux-osx-win-conda.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index 8c0f163ae..8ec76678e 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -146,7 +146,9 @@ jobs: git submodule update --init mkdir build cd build - cmake .. -G"Visual Studio 16 2019" -T "ClangCl" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON + export CXX=clang-cl + export CC=clang-cl + cmake .. -G"Ninja" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON - name: Configure [Conda/Windows-latest] if: contains(matrix.os, 'windows-latest') && contains(matrix.cxx_std, '20') @@ -157,7 +159,9 @@ jobs: git submodule update --init mkdir build cd build - cmake .. -G"Visual Studio 17 2022" -T "ClangCl" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON + export CXX=clang-cl + export CC=clang-cl + cmake .. -G"Ninja" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON - name: Configure [Conda/Windows-latest] if: contains(matrix.os, 'windows-latest') && contains(matrix.cxx_std, '17') @@ -168,7 +172,9 @@ jobs: git submodule update --init mkdir build cd build - cmake .. -G"Visual Studio 17 2022" -T "v143" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON + export CXX=clang-cl + export CC=clang-cl + cmake .. -G"Ninja" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON - name: Build [Conda] shell: bash -l {0} From 87a2b1a1bc1a1c433c496e842140657bde11791c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 23:54:57 +0000 Subject: [PATCH 089/109] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-clang-format: v19.1.3 → v19.1.5](https://github.com/pre-commit/mirrors-clang-format/compare/v19.1.3...v19.1.5) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 65aeabd18..63974c525 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: autoupdate_schedule: quarterly repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v19.1.3 + rev: v19.1.5 hooks: - id: clang-format args: ['--style={BasedOnStyle: Mozilla, SortIncludes: false}'] From cabbf35cfe9ad637d974415c15e3b16ea8b5570d Mon Sep 17 00:00:00 2001 From: J Berg Date: Sat, 4 Jan 2025 18:28:45 +0000 Subject: [PATCH 090/109] disable GIL --- benchmark/timings-parallel.py | 43 ++++++++++++++++++++++------ bindings/python/src/expose-solve.hpp | 9 ++++-- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/benchmark/timings-parallel.py b/benchmark/timings-parallel.py index 018347612..66a4cd4f7 100644 --- a/benchmark/timings-parallel.py +++ b/benchmark/timings-parallel.py @@ -2,6 +2,10 @@ import numpy as np import scipy.sparse as spa from time import perf_counter_ns +from concurrent.futures import ThreadPoolExecutor + + +num_threads = proxsuite.proxqp.omp_get_max_threads() def generate_mixed_qp(n, n_eq, n_in, seed=1): @@ -23,7 +27,7 @@ def generate_mixed_qp(n, n_eq, n_in, seed=1): u = A @ v l = -1.0e20 * np.ones(m) - return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], u[n_in:], l[n_in:] + return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], l[n_in:], u[n_in:] n = 500 @@ -32,36 +36,57 @@ def generate_mixed_qp(n, n_eq, n_in, seed=1): num_qps = 128 +print(f"Problem specs: {n=} {n_eq=} {n_in=}. Generating {num_qps} such problems.") +problems = [generate_mixed_qp(n, n_eq, n_in, seed=j) for j in range(num_qps)] +print(f"Generated problems. Solving {num_qps} problems with proxsuite.proxqp.omp_get_max_threads()={num_threads} threads.") + # qps = [] timings = {} qps = proxsuite.proxqp.dense.VectorQP() tic = perf_counter_ns() -for j in range(num_qps): +print("Setting up problem vector") +for H, g, A, b, C, l, u in problems: qp = proxsuite.proxqp.dense.QP(n, n_eq, n_in) - H, g, A, b, C, u, l = generate_mixed_qp(n, n_eq, n_in, seed=j) qp.init(H, g, A, b, C, l, u) qp.settings.eps_abs = 1e-9 qp.settings.verbose = False qp.settings.initial_guess = proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS qps.append(qp) -timings["problem_data"] = (perf_counter_ns() - tic) * 1e-6 +timings["setup_vector_of_qps"] = (perf_counter_ns() - tic) * 1e-6 +print("Solving problem vector in parallel with default thread config") +tic = perf_counter_ns() +proxsuite.proxqp.dense.solve_in_parallel(qps=qps) +timings[f"solve_parallel_heuristics_threads"] = (perf_counter_ns() - tic) * 1e-6 + +print("Solving problem vector serially") tic = perf_counter_ns() for qp in qps: qp.solve() timings["solve_serial"] = (perf_counter_ns() - tic) * 1e-6 -num_threads = proxsuite.proxqp.omp_get_max_threads() +print("Solving problem vector in parallel with various thread configs") for j in range(1, num_threads): tic = perf_counter_ns() - proxsuite.proxqp.dense.solve_in_parallel(j, qps) + proxsuite.proxqp.dense.solve_in_parallel(qps=qps, num_threads=j) timings[f"solve_parallel_{j}_threads"] = (perf_counter_ns() - tic) * 1e-6 +print("Solving each problem serially with dense backend.") +tic = perf_counter_ns() +for H, g, A, b, C, l, u in problems: + proxsuite.proxqp.dense.solve(H, g, A, b, C, l, u, initial_guess=proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS, eps_abs=1e-9) +timings["solve_serial_dense"] = (perf_counter_ns() - tic) * 1e-6 + +print("Solving each problem in parallel (with a ThreadPoolExecutor) with dense backend.") +def solve_problem(problem): # just a little helper function to keep things clean + H, g, A, b, C, l, u = problem + return proxsuite.proxqp.dense.solve(H, g, A, b, C, l, u, initial_guess=proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS, eps_abs=1e-9) tic = perf_counter_ns() -proxsuite.proxqp.dense.solve_in_parallel(qps=qps) -timings[f"solve_parallel_heuristics_threads"] = (perf_counter_ns() - tic) * 1e-6 +with ThreadPoolExecutor(max_workers=num_threads) as executor: + results = list(executor.map(solve_problem, problems)) +timings["solve_parallel_dense"] = (perf_counter_ns() - tic) * 1e-6 for k, v in timings.items(): - print(f"{k}: {v}ms") + print(f"{k}: {v:.3f}ms") diff --git a/bindings/python/src/expose-solve.hpp b/bindings/python/src/expose-solve.hpp index 25befc0bd..f514902e0 100644 --- a/bindings/python/src/expose-solve.hpp +++ b/bindings/python/src/expose-solve.hpp @@ -76,7 +76,8 @@ solveDenseQp(nanobind::module_ m) nanobind::arg("eps_duality_gap_abs") = nanobind::none(), nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, - nanobind::arg("default_H_eigenvalue_estimate") = 0.); + nanobind::arg("default_H_eigenvalue_estimate") = 0., + nanobind::call_guard()); m.def( "solve", @@ -139,7 +140,8 @@ solveDenseQp(nanobind::module_ m) nanobind::arg("eps_duality_gap_abs") = nanobind::none(), nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, - nanobind::arg("default_H_eigenvalue_estimate") = 0.); + nanobind::arg("default_H_eigenvalue_estimate") = 0., + nanobind::call_guard()); } } // namespace python @@ -186,7 +188,8 @@ solveSparseQp(nanobind::module_ m) nanobind::arg("eps_duality_gap_abs") = nanobind::none(), nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, - nanobind::arg("default_H_eigenvalue_estimate") = 0.); + nanobind::arg("default_H_eigenvalue_estimate") = 0., + nanobind::call_guard()); } } // namespace python From 03083884554e08268b7d709f45b9dd3bba4a1e39 Mon Sep 17 00:00:00 2001 From: J Berg Date: Sun, 5 Jan 2025 00:18:19 +0000 Subject: [PATCH 091/109] format --- benchmark/timings-parallel.py | 36 ++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/benchmark/timings-parallel.py b/benchmark/timings-parallel.py index 66a4cd4f7..c01164506 100644 --- a/benchmark/timings-parallel.py +++ b/benchmark/timings-parallel.py @@ -38,7 +38,9 @@ def generate_mixed_qp(n, n_eq, n_in, seed=1): print(f"Problem specs: {n=} {n_eq=} {n_in=}. Generating {num_qps} such problems.") problems = [generate_mixed_qp(n, n_eq, n_in, seed=j) for j in range(num_qps)] -print(f"Generated problems. Solving {num_qps} problems with proxsuite.proxqp.omp_get_max_threads()={num_threads} threads.") +print( + f"Generated problems. Solving {num_qps} problems with proxsuite.proxqp.omp_get_max_threads()={num_threads} threads." +) # qps = [] timings = {} @@ -72,20 +74,36 @@ def generate_mixed_qp(n, n_eq, n_in, seed=1): proxsuite.proxqp.dense.solve_in_parallel(qps=qps, num_threads=j) timings[f"solve_parallel_{j}_threads"] = (perf_counter_ns() - tic) * 1e-6 + +def solve_problem_with_dense_backend( + problem, +): # just a little helper function to keep things clean + H, g, A, b, C, l, u = problem + return proxsuite.proxqp.dense.solve( + H, + g, + A, + b, + C, + l, + u, + initial_guess=proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS, + eps_abs=1e-9, + ) + + print("Solving each problem serially with dense backend.") tic = perf_counter_ns() -for H, g, A, b, C, l, u in problems: - proxsuite.proxqp.dense.solve(H, g, A, b, C, l, u, initial_guess=proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS, eps_abs=1e-9) +for problem in problems: + solve_problem_with_dense_backend(problem) timings["solve_serial_dense"] = (perf_counter_ns() - tic) * 1e-6 -print("Solving each problem in parallel (with a ThreadPoolExecutor) with dense backend.") -def solve_problem(problem): # just a little helper function to keep things clean - H, g, A, b, C, l, u = problem - return proxsuite.proxqp.dense.solve(H, g, A, b, C, l, u, initial_guess=proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS, eps_abs=1e-9) - +print( + "Solving each problem in parallel (with a ThreadPoolExecutor) with dense backend." +) tic = perf_counter_ns() with ThreadPoolExecutor(max_workers=num_threads) as executor: - results = list(executor.map(solve_problem, problems)) + results = list(executor.map(solve_problem_with_dense_backend, problems)) timings["solve_parallel_dense"] = (perf_counter_ns() - tic) * 1e-6 for k, v in timings.items(): From 530d61b7b9ddba123c72278f58f7d934a9c09fbf Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:46:39 +0100 Subject: [PATCH 092/109] benchmark parallel: add comments and several prob spec --- benchmark/timings-parallel.py | 172 ++++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 70 deletions(-) diff --git a/benchmark/timings-parallel.py b/benchmark/timings-parallel.py index c01164506..c7bc0d695 100644 --- a/benchmark/timings-parallel.py +++ b/benchmark/timings-parallel.py @@ -4,6 +4,13 @@ from time import perf_counter_ns from concurrent.futures import ThreadPoolExecutor +""" +There are two interfaces to solve a QP problem with the dense backend. a) create a qp object by passing the problem data (matrices, vectors) to the qp.init method (this does memory allocation and the preconditioning) and then calling qp.solve or b) use the solve function directly taking the problem data as input (this does everything in one go). + +Currently, only the qp.solve method (a) is parallelized (using openmp). Therefore the memory alloc + preconditioning is done in serial when building a batch of qps that is then passed to the `solve_in_parallel` function. The solve function (b) is not parallelized but can easily be parallelized in Python using ThreadPoolExecutor. + +Here we do some timings to compare the two approaches. We generate a batch of QP problems and solve them in parallel using the `solve_in_parallel` function and compare the timings (need to add the timings for building the batch of qps + the parallel solving) with solving each problem in parallel using ThreadPoolExecutor for the solve function. +""" num_threads = proxsuite.proxqp.omp_get_max_threads() @@ -30,81 +37,106 @@ def generate_mixed_qp(n, n_eq, n_in, seed=1): return P.toarray(), q, A[:n_eq, :], u[:n_eq], A[n_in:, :], l[n_in:], u[n_in:] -n = 500 -n_eq = 200 -n_in = 200 +problem_specs = [ + # (n, n_eq, n_in), + (50, 20, 20), + (100, 40, 40), + (200, 80, 80), + (500, 200, 200), + (1000, 200, 200), +] num_qps = 128 -print(f"Problem specs: {n=} {n_eq=} {n_in=}. Generating {num_qps} such problems.") -problems = [generate_mixed_qp(n, n_eq, n_in, seed=j) for j in range(num_qps)] -print( - f"Generated problems. Solving {num_qps} problems with proxsuite.proxqp.omp_get_max_threads()={num_threads} threads." -) - -# qps = [] -timings = {} -qps = proxsuite.proxqp.dense.VectorQP() - -tic = perf_counter_ns() -print("Setting up problem vector") -for H, g, A, b, C, l, u in problems: - qp = proxsuite.proxqp.dense.QP(n, n_eq, n_in) - qp.init(H, g, A, b, C, l, u) - qp.settings.eps_abs = 1e-9 - qp.settings.verbose = False - qp.settings.initial_guess = proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS - qps.append(qp) -timings["setup_vector_of_qps"] = (perf_counter_ns() - tic) * 1e-6 - -print("Solving problem vector in parallel with default thread config") -tic = perf_counter_ns() -proxsuite.proxqp.dense.solve_in_parallel(qps=qps) -timings[f"solve_parallel_heuristics_threads"] = (perf_counter_ns() - tic) * 1e-6 - -print("Solving problem vector serially") -tic = perf_counter_ns() -for qp in qps: - qp.solve() -timings["solve_serial"] = (perf_counter_ns() - tic) * 1e-6 - -print("Solving problem vector in parallel with various thread configs") -for j in range(1, num_threads): - tic = perf_counter_ns() - proxsuite.proxqp.dense.solve_in_parallel(qps=qps, num_threads=j) - timings[f"solve_parallel_{j}_threads"] = (perf_counter_ns() - tic) * 1e-6 - - -def solve_problem_with_dense_backend( - problem, -): # just a little helper function to keep things clean - H, g, A, b, C, l, u = problem - return proxsuite.proxqp.dense.solve( - H, - g, - A, - b, - C, - l, - u, - initial_guess=proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS, - eps_abs=1e-9, +for n, n_eq, n_in in problem_specs: + + print(f"\nProblem specs: {n=} {n_eq=} {n_in=}. Generating {num_qps} such problems.") + problems = [generate_mixed_qp(n, n_eq, n_in, seed=j) for j in range(num_qps)] + print( + f"Generated problems. Solving {num_qps} problems with proxsuite.proxqp.omp_get_max_threads()={num_threads} threads." ) + timings = {} + + # create a vector of QP objects. This is not efficient because memory is allocated when creating the qp object + when it is appended to the vector which creates a copy of the object. + qps_vector = proxsuite.proxqp.dense.VectorQP() + tic = perf_counter_ns() + print("\nSetting up vector of qps") + for H, g, A, b, C, l, u in problems: + qp = proxsuite.proxqp.dense.QP(n, n_eq, n_in) + qp.init(H, g, A, b, C, l, u) + qp.settings.eps_abs = 1e-9 + qp.settings.verbose = False + qp.settings.initial_guess = proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS + qps_vector.append(qp) + timings["setup_vector_of_qps"] = (perf_counter_ns() - tic) * 1e-6 + + # use BatchQP, which can initialize the qp objects in place and is more efficient + qps_batch = proxsuite.proxqp.dense.BatchQP() + tic = perf_counter_ns() + print("Setting up batch of qps") + for H, g, A, b, C, l, u in problems: + qp = qps_batch.init_qp_in_place(n, n_eq, n_in) + qp.init(H, g, A, b, C, l, u) + qp.settings.eps_abs = 1e-9 + qp.settings.verbose = False + qp.settings.initial_guess = proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS + timings["setup_batch_of_qps"] = (perf_counter_ns() - tic) * 1e-6 + + print("Solving batch of qps using solve_in_parallel with default thread config") + tic = perf_counter_ns() + proxsuite.proxqp.dense.solve_in_parallel(qps=qps_batch) + timings[f"solve_in_parallel_heuristics_threads"] = (perf_counter_ns() - tic) * 1e-6 -print("Solving each problem serially with dense backend.") -tic = perf_counter_ns() -for problem in problems: - solve_problem_with_dense_backend(problem) -timings["solve_serial_dense"] = (perf_counter_ns() - tic) * 1e-6 + print("Solving vector of qps serially") + tic = perf_counter_ns() + for qp in qps_vector: + qp.solve() + timings["qp_solve_serial"] = (perf_counter_ns() - tic) * 1e-6 + + print("Solving batch of qps using solve_in_parallel with various thread configs") + for j in range(1, num_threads, 2): + tic = perf_counter_ns() + proxsuite.proxqp.dense.solve_in_parallel(qps=qps_batch, num_threads=j) + timings[f"solve_in_parallel_{j}_threads"] = (perf_counter_ns() - tic) * 1e-6 + + def solve_problem_with_dense_backend( + problem, + ): # just a little helper function to keep things clean + H, g, A, b, C, l, u = problem + return proxsuite.proxqp.dense.solve( + H, + g, + A, + b, + C, + l, + u, + initial_guess=proxsuite.proxqp.InitialGuess.NO_INITIAL_GUESS, + eps_abs=1e-9, + ) + + # add final timings for the solve_in_parallel function considering setup time for batch of qps + for k, v in list(timings.items()): + if "solve_in_parallel" in k: + k_init = k + "_and_setup_batch_of_qps" + timings[k_init] = timings["setup_batch_of_qps"] + v + + print("Solving each problem serially with solve function.") + # Note: here we just pass the problem data to the solve function. This does not require running the init method separately. + tic = perf_counter_ns() + for problem in problems: + solve_problem_with_dense_backend(problem) + timings["solve_fun_serial"] = (perf_counter_ns() - tic) * 1e-6 -print( - "Solving each problem in parallel (with a ThreadPoolExecutor) with dense backend." -) -tic = perf_counter_ns() -with ThreadPoolExecutor(max_workers=num_threads) as executor: - results = list(executor.map(solve_problem_with_dense_backend, problems)) -timings["solve_parallel_dense"] = (perf_counter_ns() - tic) * 1e-6 + print( + "Solving each problem in parallel (with a ThreadPoolExecutor) with solve function." + ) + tic = perf_counter_ns() + with ThreadPoolExecutor(max_workers=num_threads) as executor: + results = list(executor.map(solve_problem_with_dense_backend, problems)) + timings["solve_fun_parallel"] = (perf_counter_ns() - tic) * 1e-6 -for k, v in timings.items(): - print(f"{k}: {v:.3f}ms") + print("\nTimings:") + for k, v in timings.items(): + print(f"{k}: {v:.3f}ms") From d58746b2dd0d77ac1190e5ac9176ac8867e6d4a8 Mon Sep 17 00:00:00 2001 From: J Berg Date: Thu, 9 Jan 2025 22:52:32 +0000 Subject: [PATCH 093/109] separate _no_gil interface --- benchmark/timings-parallel.py | 4 +- bindings/python/src/expose-solve.hpp | 169 ++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 6 deletions(-) diff --git a/benchmark/timings-parallel.py b/benchmark/timings-parallel.py index c7bc0d695..0beef2a70 100644 --- a/benchmark/timings-parallel.py +++ b/benchmark/timings-parallel.py @@ -102,9 +102,9 @@ def generate_mixed_qp(n, n_eq, n_in, seed=1): def solve_problem_with_dense_backend( problem, - ): # just a little helper function to keep things clean + ): H, g, A, b, C, l, u = problem - return proxsuite.proxqp.dense.solve( + return proxsuite.proxqp.dense.solve_no_gil( H, g, A, diff --git a/bindings/python/src/expose-solve.hpp b/bindings/python/src/expose-solve.hpp index f514902e0..ccc33c072 100644 --- a/bindings/python/src/expose-solve.hpp +++ b/bindings/python/src/expose-solve.hpp @@ -46,7 +46,7 @@ solveDenseQp(nanobind::module_ m) optional, bool, optional>(&dense::solve), - "Function for solving a QP problem using PROXQP sparse backend directly " + "Function for solving a QP problem using PROXQP dense backend directly " "without defining a QP object. It is possible to set up some of the solver " "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " @@ -76,8 +76,7 @@ solveDenseQp(nanobind::module_ m) nanobind::arg("eps_duality_gap_abs") = nanobind::none(), nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, - nanobind::arg("default_H_eigenvalue_estimate") = 0., - nanobind::call_guard()); + nanobind::arg("default_H_eigenvalue_estimate") = 0.); m.def( "solve", @@ -108,7 +107,7 @@ solveDenseQp(nanobind::module_ m) optional, bool, optional>(&dense::solve), - "Function for solving a QP problem using PROXQP sparse backend directly " + "Function for solving a QP problem using PROXQP dense backend directly " "without defining a QP object. It is possible to set up some of the solver " "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " @@ -140,6 +139,131 @@ solveDenseQp(nanobind::module_ m) nanobind::arg("eps_duality_gap_abs") = nanobind::none(), nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, + nanobind::arg("default_H_eigenvalue_estimate") = 0.); + + m.def( + "solve_no_gil", + nanobind::overload_cast>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional, + optional, + optional, + optional, + optional, + optional, + bool, + bool, + optional, + proxsuite::proxqp::InitialGuessStatus, + bool, + optional, + optional, + bool, + optional>(&dense::solve), + "Function for solving a QP problem using PROXQP dense backend directly " + "without defining a QP object and while releasing the Global Interpreter Lock (GIL). " + "It is possible to set up some of the solver " + "parameters (warm start, initial guess option, proximal step sizes, " + "absolute and relative accuracies, maximum number of iterations, " + "preconditioner execution).", + nanobind::arg("H"), + nanobind::arg("g"), + nanobind::arg("A").none(), + nanobind::arg("b").none(), + nanobind::arg("C").none(), + nanobind::arg("l").none(), + nanobind::arg("u").none(), + nanobind::arg("x") = nanobind::none(), + nanobind::arg("y") = nanobind::none(), + nanobind::arg("z") = nanobind::none(), + nanobind::arg("eps_abs") = nanobind::none(), + nanobind::arg("eps_rel") = nanobind::none(), + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("verbose") = nanobind::none(), + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("compute_timings") = false, + nanobind::arg("max_iter") = nanobind::none(), + nanobind::arg("initial_guess") = + InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, + nanobind::arg("check_duality_gap") = false, + nanobind::arg("eps_duality_gap_abs") = nanobind::none(), + nanobind::arg("eps_duality_gap_rel") = nanobind::none(), + nanobind::arg("primal_infeasibility_solving") = false, + nanobind::arg("default_H_eigenvalue_estimate") = 0., + nanobind::call_guard()); + + m.def( + "solve_no_gil", + nanobind::overload_cast>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional, + optional, + optional, + optional, + optional, + optional, + bool, + bool, + optional, + proxsuite::proxqp::InitialGuessStatus, + bool, + optional, + optional, + bool, + optional>(&dense::solve), + "Function for solving a QP problem using PROXQP dense backend directly " + "without defining a QP object and while releasing the Global Interpreter Lock (GIL). " + "It is possible to set up some of the solver " + "parameters (warm start, initial guess option, proximal step sizes, " + "absolute and relative accuracies, maximum number of iterations, " + "preconditioner execution).", + nanobind::arg("H"), + nanobind::arg("g"), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), + nanobind::arg("l_box") = nanobind::none(), + nanobind::arg("u_box") = nanobind::none(), + nanobind::arg("x") = nanobind::none(), + nanobind::arg("y") = nanobind::none(), + nanobind::arg("z") = nanobind::none(), + nanobind::arg("eps_abs") = nanobind::none(), + nanobind::arg("eps_rel") = nanobind::none(), + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("verbose") = nanobind::none(), + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("compute_timings") = false, + nanobind::arg("max_iter") = nanobind::none(), + nanobind::arg("initial_guess") = + proxsuite::proxqp::InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, + nanobind::arg("check_duality_gap") = false, + nanobind::arg("eps_duality_gap_abs") = nanobind::none(), + nanobind::arg("eps_duality_gap_rel") = nanobind::none(), + nanobind::arg("primal_infeasibility_solving") = false, nanobind::arg("default_H_eigenvalue_estimate") = 0., nanobind::call_guard()); } @@ -188,6 +312,43 @@ solveSparseQp(nanobind::module_ m) nanobind::arg("eps_duality_gap_abs") = nanobind::none(), nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, + nanobind::arg("default_H_eigenvalue_estimate") = 0.); + + m.def( + "solve_no_gil", + &sparse::solve, + "Function for solving a QP problem using PROXQP sparse backend directly " + "without defining a QP object and while releasing the Global Interpreter Lock (GIL). " + "It is possible to set up some of the solver " + "parameters (warm start, initial guess option, proximal step sizes, " + "absolute and relative accuracies, maximum number of iterations, " + "preconditioner execution).", + nanobind::arg("H") = nanobind::none(), + nanobind::arg("g") = nanobind::none(), + nanobind::arg("A") = nanobind::none(), + nanobind::arg("b") = nanobind::none(), + nanobind::arg("C") = nanobind::none(), + nanobind::arg("l") = nanobind::none(), + nanobind::arg("u") = nanobind::none(), + nanobind::arg("x") = nanobind::none(), + nanobind::arg("y") = nanobind::none(), + nanobind::arg("z") = nanobind::none(), + nanobind::arg("eps_abs") = nanobind::none(), + nanobind::arg("eps_rel") = nanobind::none(), + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("verbose") = nanobind::none(), + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("compute_timings") = false, + nanobind::arg("max_iter") = nanobind::none(), + nanobind::arg("initial_guess") = + InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, + nanobind::arg("sparse_backend") = SparseBackend::Automatic, + nanobind::arg("check_duality_gap") = false, + nanobind::arg("eps_duality_gap_abs") = nanobind::none(), + nanobind::arg("eps_duality_gap_rel") = nanobind::none(), + nanobind::arg("primal_infeasibility_solving") = false, nanobind::arg("default_H_eigenvalue_estimate") = 0., nanobind::call_guard()); } From b72e27ff5204965f0b486d0118d52cd7b38fad4d Mon Sep 17 00:00:00 2001 From: J Berg Date: Thu, 9 Jan 2025 23:03:34 +0000 Subject: [PATCH 094/109] format --- bindings/python/src/expose-solve.hpp | 128 ++++++++++++++------------- 1 file changed, 65 insertions(+), 63 deletions(-) diff --git a/bindings/python/src/expose-solve.hpp b/bindings/python/src/expose-solve.hpp index ccc33c072..89004cc8b 100644 --- a/bindings/python/src/expose-solve.hpp +++ b/bindings/python/src/expose-solve.hpp @@ -140,67 +140,67 @@ solveDenseQp(nanobind::module_ m) nanobind::arg("eps_duality_gap_rel") = nanobind::none(), nanobind::arg("primal_infeasibility_solving") = false, nanobind::arg("default_H_eigenvalue_estimate") = 0.); - - m.def( - "solve_no_gil", - nanobind::overload_cast>, - optional>, - optional>, - optional>, - optional>, - optional>, - optional>, - optional>, - optional>, - optional>, - optional, - optional, - optional, - optional, - optional, - optional, - bool, - bool, - optional, - proxsuite::proxqp::InitialGuessStatus, - bool, - optional, - optional, - bool, - optional>(&dense::solve), - "Function for solving a QP problem using PROXQP dense backend directly " - "without defining a QP object and while releasing the Global Interpreter Lock (GIL). " - "It is possible to set up some of the solver " - "parameters (warm start, initial guess option, proximal step sizes, " - "absolute and relative accuracies, maximum number of iterations, " - "preconditioner execution).", - nanobind::arg("H"), - nanobind::arg("g"), - nanobind::arg("A").none(), - nanobind::arg("b").none(), - nanobind::arg("C").none(), - nanobind::arg("l").none(), - nanobind::arg("u").none(), - nanobind::arg("x") = nanobind::none(), - nanobind::arg("y") = nanobind::none(), - nanobind::arg("z") = nanobind::none(), - nanobind::arg("eps_abs") = nanobind::none(), - nanobind::arg("eps_rel") = nanobind::none(), - nanobind::arg("rho") = nanobind::none(), - nanobind::arg("mu_eq") = nanobind::none(), - nanobind::arg("mu_in") = nanobind::none(), - nanobind::arg("verbose") = nanobind::none(), - nanobind::arg("compute_preconditioner") = true, - nanobind::arg("compute_timings") = false, - nanobind::arg("max_iter") = nanobind::none(), - nanobind::arg("initial_guess") = - InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, - nanobind::arg("check_duality_gap") = false, - nanobind::arg("eps_duality_gap_abs") = nanobind::none(), - nanobind::arg("eps_duality_gap_rel") = nanobind::none(), - nanobind::arg("primal_infeasibility_solving") = false, - nanobind::arg("default_H_eigenvalue_estimate") = 0., - nanobind::call_guard()); + + m.def("solve_no_gil", + nanobind::overload_cast>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional>, + optional, + optional, + optional, + optional, + optional, + optional, + bool, + bool, + optional, + proxsuite::proxqp::InitialGuessStatus, + bool, + optional, + optional, + bool, + optional>(&dense::solve), + "Function for solving a QP problem using PROXQP dense backend directly " + "without defining a QP object and while releasing the Global " + "Interpreter Lock (GIL). " + "It is possible to set up some of the solver " + "parameters (warm start, initial guess option, proximal step sizes, " + "absolute and relative accuracies, maximum number of iterations, " + "preconditioner execution).", + nanobind::arg("H"), + nanobind::arg("g"), + nanobind::arg("A").none(), + nanobind::arg("b").none(), + nanobind::arg("C").none(), + nanobind::arg("l").none(), + nanobind::arg("u").none(), + nanobind::arg("x") = nanobind::none(), + nanobind::arg("y") = nanobind::none(), + nanobind::arg("z") = nanobind::none(), + nanobind::arg("eps_abs") = nanobind::none(), + nanobind::arg("eps_rel") = nanobind::none(), + nanobind::arg("rho") = nanobind::none(), + nanobind::arg("mu_eq") = nanobind::none(), + nanobind::arg("mu_in") = nanobind::none(), + nanobind::arg("verbose") = nanobind::none(), + nanobind::arg("compute_preconditioner") = true, + nanobind::arg("compute_timings") = false, + nanobind::arg("max_iter") = nanobind::none(), + nanobind::arg("initial_guess") = + InitialGuessStatus::EQUALITY_CONSTRAINED_INITIAL_GUESS, + nanobind::arg("check_duality_gap") = false, + nanobind::arg("eps_duality_gap_abs") = nanobind::none(), + nanobind::arg("eps_duality_gap_rel") = nanobind::none(), + nanobind::arg("primal_infeasibility_solving") = false, + nanobind::arg("default_H_eigenvalue_estimate") = 0., + nanobind::call_guard()); m.def( "solve_no_gil", @@ -232,7 +232,8 @@ solveDenseQp(nanobind::module_ m) bool, optional>(&dense::solve), "Function for solving a QP problem using PROXQP dense backend directly " - "without defining a QP object and while releasing the Global Interpreter Lock (GIL). " + "without defining a QP object and while releasing the Global Interpreter " + "Lock (GIL). " "It is possible to set up some of the solver " "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " @@ -318,7 +319,8 @@ solveSparseQp(nanobind::module_ m) "solve_no_gil", &sparse::solve, "Function for solving a QP problem using PROXQP sparse backend directly " - "without defining a QP object and while releasing the Global Interpreter Lock (GIL). " + "without defining a QP object and while releasing the Global Interpreter " + "Lock (GIL). " "It is possible to set up some of the solver " "parameters (warm start, initial guess option, proximal step sizes, " "absolute and relative accuracies, maximum number of iterations, " From 2301f33b08d90c330c7ea97860ca249b140eb2ef Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:57:10 +0100 Subject: [PATCH 095/109] ci: use setup-miniconda@v3 --- .github/workflows/ci-linux-osx-win-conda.yml | 30 ++++++-------------- .github/workflows/gh-pages.yml | 10 +++---- .github/workflows/release-osx-win.yml | 19 ++----------- 3 files changed, 15 insertions(+), 44 deletions(-) diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index 8ec76678e..4b1913383 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -57,22 +57,11 @@ jobs: with: submodules: recursive - - uses: conda-incubator/setup-miniconda@v2 - if: matrix.os != 'macos-14' + - uses: conda-incubator/setup-miniconda@v3 with: - miniforge-variant: Mambaforge miniforge-version: latest - channels: conda-forge - python-version: "3.10" activate-environment: proxsuite - - uses: conda-incubator/setup-miniconda@v3 - if: matrix.os == 'macos-14' - with: - channels: conda-forge - python-version: "3.10" - activate-environment: proxsuite - installer-url: https://github.com/conda-forge/miniforge/releases/download/23.11.0-0/Mambaforge-23.11.0-0-MacOSX-arm64.sh - name: Install dependencies [Conda] shell: bash -l {0} @@ -80,17 +69,17 @@ jobs: # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 conda config --remove channels defaults # Compilation related dependencies - mamba install cmake compilers make pkg-config doxygen ninja graphviz typing_extensions llvm-openmp clang + conda install cmake compilers make pkg-config doxygen ninja graphviz typing_extensions llvm-openmp clang # Main dependencies - mamba install eigen simde + conda install eigen simde # Test dependencies - mamba install libmatio numpy scipy + conda install libmatio numpy scipy - - name: Install julia [macOS/Linux] - if: contains(matrix.os, 'macos-latest') || contains(matrix.os, 'ubuntu') + - name: Install julia [Linux] + if: contains(matrix.os, 'ubuntu') shell: bash -l {0} run: | - mamba install julia + conda install julia - name: Activate ccache [Conda] uses: hendrikmuhs/ccache-action@v1.2 @@ -102,7 +91,7 @@ jobs: shell: bash -l {0} run: | conda info - mamba list + conda list env - name: Configure [Conda/Linux&macOS] @@ -142,7 +131,6 @@ jobs: shell: bash -l {0} run: | echo $(where ccache) - ls C:\\Miniconda3\\envs\\proxsuite\\Library\\lib git submodule update --init mkdir build cd build @@ -155,7 +143,6 @@ jobs: shell: bash -l {0} run: | echo $(where ccache) - ls C:\\Miniconda3\\envs\\proxsuite\\Library\\lib git submodule update --init mkdir build cd build @@ -168,7 +155,6 @@ jobs: shell: bash -l {0} run: | echo $(where ccache) - ls C:\\Miniconda3\\envs\\proxsuite\\Library\\lib git submodule update --init mkdir build cd build diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index c096bd318..e23c64418 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -12,11 +12,9 @@ jobs: with: submodules: recursive - - uses: conda-incubator/setup-miniconda@v2 + - uses: conda-incubator/setup-miniconda@v3 with: - miniforge-variant: Mambaforge miniforge-version: latest - channels: conda-forge python-version: "3.10" activate-environment: doc @@ -27,16 +25,16 @@ jobs: conda config --remove channels defaults # Compilation related dependencies - mamba install cmake make pkg-config doxygen graphviz + conda install cmake make pkg-config doxygen graphviz # Main dependencies - mamba install eigen + conda install eigen - name: Print environment shell: bash -l {0} run: | conda info - mamba list + conda list env - name: Configure diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index 845a980e6..d19755881 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -35,23 +35,11 @@ jobs: git submodule update - name: Setup conda - if: contains(matrix.os, 'macos-13') || contains(matrix.os, 'windows') - uses: conda-incubator/setup-miniconda@v2 - with: - miniforge-variant: Mambaforge - miniforge-version: latest - channels: conda-forge - python-version: ${{ matrix.python-version }} - activate-environment: proxsuite - - - name: Setup conda - if: matrix.os == 'macos-14' uses: conda-incubator/setup-miniconda@v3 with: - channels: conda-forge + miniforge-version: latest python-version: ${{ matrix.python-version }} activate-environment: proxsuite - installer-url: https://github.com/conda-forge/miniforge/releases/download/23.11.0-0/Mambaforge-23.11.0-0-MacOSX-arm64.sh - name: Install dependencies [Conda] if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows') @@ -59,14 +47,13 @@ jobs: run: | # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 conda config --remove channels defaults - mamba install doxygen graphviz eigen simde cmake compilers typing_extensions + conda install doxygen graphviz eigen simde cmake compilers typing_extensions - name: Print environment [Conda] - if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows') shell: bash -l {0} run: | conda info - mamba list + conda list env - name: Build wheel From 3169275113898b470b8dcda1a78cad1ca8c7d859 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:20:55 +0100 Subject: [PATCH 096/109] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dacdbf799..9281c4299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added * Stub files for Python bindings, using [nanobind's native support](https://nanobind.readthedocs.io/en/latest/typing.html#stub-generation) ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) +* Add `solve_no_gil` for dense backend (multithreading via python) ([#363](https://github.com/Simple-Robotics/proxsuite/pull/363)) +* Add benchmarks for `solve_no_gil` vs `solve_in_parallel` (openmp) ([#363](https://github.com/Simple-Robotics/proxsuite/pull/363)) ### Changed * Change Python bindings to use nanobind instead of pybind11 ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) +* Update setup-minicondav2 to v3 ([#363](https://github.com/Simple-Robotics/proxsuite/pull/363)) ## [0.6.7] - 2024-08-27 From 8f52f6e3cae15a13d7acce07dc3d8e91ed3a274c Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Wed, 8 Jan 2025 18:37:12 +0100 Subject: [PATCH 097/109] release: updates --- .github/workflows/release-linux.yml | 38 +++++++++------------------ .github/workflows/release-osx-win.yml | 8 +++--- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index 84bcc72b3..8f8a252f7 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -10,37 +10,25 @@ on: jobs: build-wheel: - name: "Build ${{ matrix.build }} wheels on ${{ matrix.os }} ${{ matrix.arch }}" - runs-on: "${{ matrix.os }}-latest" + name: "Build ${{ matrix.build }} wheels on ${{ matrix.arch }}" + runs-on: "ubuntu-latest" strategy: matrix: - os: ["ubuntu"] - arch: ["x86_64"] - build: ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*", "pp38-*", "pp39-*"] - include: + arch: ["x86_64", "aarch64"] + build: ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*", "cp313-*", "pp38-*", "pp39-*"] + exclude: - arch: "aarch64" - os: "ubuntu" - build: "cp38-manylinux*" + build: "pp38-*" - arch: "aarch64" - os: "ubuntu" - build: "cp39-manylinux*" - - arch: "aarch64" - os: "ubuntu" - build: "cp310-manylinux*" - - arch: "aarch64" - os: "ubuntu" - build: "cp311-manylinux*" - - arch: "aarch64" - os: "ubuntu" - build: "cp312-manylinux*" + build: "pp39-*" steps: - uses: actions/checkout@v4 with: submodules: recursive - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" - name: Set up QEMU if: matrix.arch == 'aarch64' uses: docker/setup-qemu-action@v2 @@ -58,7 +46,7 @@ jobs: CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "quay.io/pypa/manylinux2014_x86_64" CIBW_MANYLINUX_AARCH64_IMAGE: "quay.io/pypa/manylinux_2_28_aarch64" CIBW_REPAIR_WHEEL_COMMAND: "" - CIBW_ENVIRONMENT: "CMEEL_JOBS=2 CMEEL_RUN_TESTS=OFF" + CIBW_ENVIRONMENT: "CMEEL_JOBS=2 CMEEL_RUN_TESTS=OFF CMEEL_CMAKE_ARGS=-DBUILD_WITH_OPENMP_SUPPORT=ON" - uses: actions/upload-artifact@v3 with: @@ -69,10 +57,10 @@ jobs: needs: "build-wheel" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" - uses: actions/download-artifact@v3 - name: Publish package to PyPI diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index d19755881..c6c0204b1 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -14,7 +14,7 @@ jobs: name: Build ${{ matrix.os }} ${{ matrix.python-version }} strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] os: [macos-13, macos-14, windows-2019, windows-latest] include: - os: windows-2019 @@ -89,10 +89,10 @@ jobs: needs: "build-wheel" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" - uses: actions/download-artifact@v3 - name: Publish package to PyPI From 26469b42522d47e151226de601c56dc6e9f2718f Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Wed, 8 Jan 2025 18:42:39 +0100 Subject: [PATCH 098/109] add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9281c4299..3fec46c03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added * Stub files for Python bindings, using [nanobind's native support](https://nanobind.readthedocs.io/en/latest/typing.html#stub-generation) ([#340](https://github.com/Simple-Robotics/proxsuite/pull/340)) +* Python 3.13 support on PyPI ([#361](https://github.com/Simple-Robotics/proxsuite/pull/361)) * Add `solve_no_gil` for dense backend (multithreading via python) ([#363](https://github.com/Simple-Robotics/proxsuite/pull/363)) * Add benchmarks for `solve_no_gil` vs `solve_in_parallel` (openmp) ([#363](https://github.com/Simple-Robotics/proxsuite/pull/363)) From 055882da9c4fd5e40d875a0c667d70f3aebfece0 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Mon, 20 Jan 2025 11:38:08 +0100 Subject: [PATCH 099/109] release: remove use of PYPI_TOKEN --- .github/workflows/release-linux.yml | 3 --- .github/workflows/release-osx-win.yml | 3 --- 2 files changed, 6 deletions(-) diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index 8f8a252f7..c626dc3ee 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -68,9 +68,6 @@ jobs: if: | github.repository == 'Simple-Robotics/proxsuite' && (github.event_name == 'release' && github.event.action == 'published') - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} check: if: always() diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index c6c0204b1..febc4b136 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -100,9 +100,6 @@ jobs: if: | github.repository == 'Simple-Robotics/proxsuite' && (github.event_name == 'release' && github.event.action == 'published') - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} check: if: always() From 8496fedb5ad2dcc149b094ad9b899035f0a7e63a Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Mon, 20 Jan 2025 11:42:20 +0100 Subject: [PATCH 100/109] release: add pp310 --- .github/workflows/release-linux.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index c626dc3ee..3e03535c8 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -15,12 +15,14 @@ jobs: strategy: matrix: arch: ["x86_64", "aarch64"] - build: ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*", "cp313-*", "pp38-*", "pp39-*"] + build: ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*", "cp313-*", "pp38-*", "pp39-*", "pp310-*"] exclude: - arch: "aarch64" build: "pp38-*" - arch: "aarch64" build: "pp39-*" + - arch: "aarch64" + build: "pp310-*" steps: - uses: actions/checkout@v4 From 2a2665aeb9830415a8fbb319434998629c650611 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 00:01:35 +0000 Subject: [PATCH 101/109] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-clang-format: v19.1.5 → v19.1.7](https://github.com/pre-commit/mirrors-clang-format/compare/v19.1.5...v19.1.7) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 63974c525..cd6b420c2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: autoupdate_schedule: quarterly repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v19.1.5 + rev: v19.1.7 hooks: - id: clang-format args: ['--style={BasedOnStyle: Mozilla, SortIncludes: false}'] From 6eff9c479983306eadee250b2b3ee8cb533a830a Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:00:36 +0100 Subject: [PATCH 102/109] ci: setup miniconda with conda-forge and remove defaults --- .github/workflows/ci-linux-osx-win-conda.yml | 4 ++-- .github/workflows/gh-pages.yml | 6 ++---- .github/workflows/release-osx-win.yml | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-linux-osx-win-conda.yml b/.github/workflows/ci-linux-osx-win-conda.yml index 4b1913383..eac917f76 100644 --- a/.github/workflows/ci-linux-osx-win-conda.yml +++ b/.github/workflows/ci-linux-osx-win-conda.yml @@ -61,13 +61,13 @@ jobs: with: miniforge-version: latest activate-environment: proxsuite + channels: conda-forge + conda-remove-defaults: "true" - name: Install dependencies [Conda] shell: bash -l {0} run: | - # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 - conda config --remove channels defaults # Compilation related dependencies conda install cmake compilers make pkg-config doxygen ninja graphviz typing_extensions llvm-openmp clang # Main dependencies diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index e23c64418..a79c0edeb 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -15,15 +15,13 @@ jobs: - uses: conda-incubator/setup-miniconda@v3 with: miniforge-version: latest - python-version: "3.10" activate-environment: doc + channels: conda-forge + conda-remove-defaults: "true" - name: Dependencies shell: bash -l {0} run: | - # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 - conda config --remove channels defaults - # Compilation related dependencies conda install cmake make pkg-config doxygen graphviz diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index d19755881..254ae6cc9 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -40,13 +40,13 @@ jobs: miniforge-version: latest python-version: ${{ matrix.python-version }} activate-environment: proxsuite + channels: conda-forge + conda-remove-defaults: "true" - name: Install dependencies [Conda] if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows') shell: bash -l {0} run: | - # Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186 - conda config --remove channels defaults conda install doxygen graphviz eigen simde cmake compilers typing_extensions - name: Print environment [Conda] From d17c91174bef351c1eb9331684908e0a4443d5dc Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:46:41 +0100 Subject: [PATCH 103/109] release: Update package.xml version to 0.7.0 --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 4aa4539ae..62dfa634d 100644 --- a/package.xml +++ b/package.xml @@ -1,7 +1,7 @@ proxsuite - 0.6.7 + 0.7.0 The Advanced Proximal Optimization Toolbox Justin Carpentier From aab451761b49cc620adbb1610a862d553cca8b55 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:46:42 +0100 Subject: [PATCH 104/109] release: Update pyproject.toml version to 0.7.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9f65cf1c1..607dccdf8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "proxsuite" -version = "0.6.7" +version = "0.7.0" description = "Quadratic Programming Solver for Robotics and beyond." readme = "README.md" requires-python = ">= 3.8" From 7dc1ff1ecf4ba3d779d59960fbfad4cb120e04b2 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:46:42 +0100 Subject: [PATCH 105/109] release: Update CHANGELOG.md for 0.7.0 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fec46c03..a4f120080 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +## [0.7.0] - 2025-01-21 + ### Fixed * CMake: Fix link to system cereal in tests ([#353](https://github.com/Simple-Robotics/proxsuite/pull/352)) * Fix windows build error related to template usage in veg ([#357](https://github.com/Simple-Robotics/proxsuite/pull/357)) @@ -446,7 +448,8 @@ More to come ([#](a forthcoming release.)) The first release of ProxSuite. -[Unreleased]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.7...HEAD +[Unreleased]: https://github.com/Simple-Robotics/proxsuite/compare/v0.7.0...HEAD +[0.7.0]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.7...v0.7.0 [0.6.7]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.6...v0.6.7 [0.6.6]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.5...v0.6.6 [0.6.5]: https://github.com/Simple-Robotics/proxsuite/compare/v0.6.4...v0.6.5 From b239d4745198595b602ff0ed4ab82e8f5e74f5e5 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:46:42 +0100 Subject: [PATCH 106/109] release: Update CITATION.cff version to 0.7.0 --- CITATION.cff | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index fd84309e6..58e1ac252 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -14,7 +14,7 @@ authors: - family-names: Carpentier given-names: Justin orcid: "https://orcid.org/0000-0001-6585-2894" -version: 0.6.7 -date-released: "2024-08-27" +version: 0.7.0 +date-released: "2025-01-21" license: BSD-2-Clause repository-code: "https://github.com/Simple-Robotics/proxsuite" From b204306f87ff406d88478c2c82cfdff8b9dbc371 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 21 Jan 2025 18:15:18 +0100 Subject: [PATCH 107/109] ci: give release workflow write permission - as stated here https://github.com/pypa/gh-action-pypi-publish?tab=readme-ov-file#trusted-publishing --- .github/workflows/release-linux.yml | 2 ++ .github/workflows/release-osx-win.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index 3e03535c8..f6175f95e 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -58,6 +58,8 @@ jobs: release: needs: "build-wheel" runs-on: ubuntu-latest + permissions: + id-token: write steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index 786169bb1..64fae5fca 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -88,6 +88,8 @@ jobs: release: needs: "build-wheel" runs-on: ubuntu-latest + permissions: + id-token: write steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 From 145e8dc70c300c321258bec1b71e043332add1a6 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Tue, 21 Jan 2025 18:17:51 +0100 Subject: [PATCH 108/109] ci: use upload/download-artifact v4 - handle immutable artifacts --- .github/workflows/gh-pages.yml | 4 ++-- .github/workflows/release-linux.yml | 12 +++++++++--- .github/workflows/release-osx-win.yml | 10 +++++++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index a79c0edeb..faae183ac 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -50,7 +50,7 @@ jobs: cmake --build . --config Release --target doc - name: Archive artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: site path: build/doc/doxygen-html @@ -60,7 +60,7 @@ jobs: needs: [build] steps: - name: Download artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: site path: site diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index f6175f95e..d958ea374 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -50,9 +50,11 @@ jobs: CIBW_REPAIR_WHEEL_COMMAND: "" CIBW_ENVIRONMENT: "CMEEL_JOBS=2 CMEEL_RUN_TESTS=OFF CMEEL_CMAKE_ARGS=-DBUILD_WITH_OPENMP_SUPPORT=ON" - - uses: actions/upload-artifact@v3 + - run: echo "ARTIFACT_NAME=dist-${{ matrix.arch }}-${{ matrix.build }}" | sed 's/\*/_/g' >> $GITHUB_ENV + + - uses: actions/upload-artifact@v4 with: - name: dist + name: ${{ env.ARTIFACT_NAME }} path: dist release: @@ -65,7 +67,11 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.12" - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 + with: + pattern: dist-* + merge-multiple: true + path: dist - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/release-osx-win.yml b/.github/workflows/release-osx-win.yml index 64fae5fca..8240218c5 100644 --- a/.github/workflows/release-osx-win.yml +++ b/.github/workflows/release-osx-win.yml @@ -80,9 +80,9 @@ jobs: mv dist/proxsuite*.whl dist_proxsuite - name: Archive artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: dist + name: dist-${{ matrix.os }}-${{ matrix.python-version }} path: dist_proxsuite release: @@ -95,7 +95,11 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.12" - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 + with: + pattern: dist-* + merge-multiple: true + path: dist - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 From 293068e7ac85e1bad07222b871f0f90bf8c9b9d6 Mon Sep 17 00:00:00 2001 From: Fabian Schramm <55981657+fabinsch@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:40:11 +0100 Subject: [PATCH 109/109] ci: deactivate ros tsid downstream --- .github/workflows/ci-linux-ros.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-linux-ros.yml b/.github/workflows/ci-linux-ros.yml index c24478bc9..5c453cc82 100644 --- a/.github/workflows/ci-linux-ros.yml +++ b/.github/workflows/ci-linux-ros.yml @@ -31,7 +31,7 @@ jobs: - {name: "Rolling / Debug / Vectorization", ROS_DISTRO: rolling, CMAKE_BUILD_TYPE: Debug, VECTORIZATION_SUPPORT: ON} - {name: "Rolling / Release / Vectorization", ROS_DISTRO: rolling, CMAKE_BUILD_TYPE: Release, VECTORIZATION_SUPPORT: ON} # - {name: "Rolling / Pre-Release", ROS_DISTRO: rolling, PRERELEASE: true} - - {name: "Rolling / TSID-Downstream", ROS_DISTRO: rolling, CMAKE_BUILD_TYPE: Release, VECTORIZATION_SUPPORT: ON, DOWNSTREAM_WORKSPACE: "github:stack-of-tasks/tsid#devel github:stack-of-tasks/eiquadprog#devel", DOWNSTREAM_CMAKE_ARGS: -DBUILD_WITH_PROXQP=ON} + # - {name: "Rolling / TSID-Downstream", ROS_DISTRO: rolling, CMAKE_BUILD_TYPE: Release, VECTORIZATION_SUPPORT: ON, DOWNSTREAM_WORKSPACE: "github:stack-of-tasks/tsid#devel github:stack-of-tasks/eiquadprog#devel", DOWNSTREAM_CMAKE_ARGS: -DBUILD_WITH_PROXQP=ON} name: ${{ matrix.env.name }} env: CMAKE_ARGS: -DBUILD_WITH_VECTORIZATION_SUPPORT=${{ matrix.env.VECTORIZATION_SUPPORT }} # Simde is available since humble