diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index be89eee80c..b440d5d343 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -129,70 +129,73 @@ if (WITH_GUDHI_PYTHON) # Can be set with -DPYTHON_EXECUTABLE=/usr/bin/python3 or -DPython_ADDITIONAL_VERSIONS=3 for instance. find_package( PythonInterp ) - # find_python_module tries to import module in Python interpreter and to retrieve its version number - # returns ${PYTHON_MODULE_NAME_UP}_VERSION and ${PYTHON_MODULE_NAME_UP}_FOUND - function( find_python_module PYTHON_MODULE_NAME ) - string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}; print(${PYTHON_MODULE_NAME}.__version__)" - RESULT_VARIABLE PYTHON_MODULE_RESULT - OUTPUT_VARIABLE PYTHON_MODULE_VERSION - ERROR_VARIABLE PYTHON_MODULE_ERROR) - if(PYTHON_MODULE_RESULT EQUAL 0) - # Remove all carriage returns as it can be multiline - string(REGEX REPLACE "\n" " " PYTHON_MODULE_VERSION "${PYTHON_MODULE_VERSION}") - message ("++ Python module ${PYTHON_MODULE_NAME} - Version ${PYTHON_MODULE_VERSION} found") - - set(${PYTHON_MODULE_NAME_UP}_VERSION ${PYTHON_MODULE_VERSION} PARENT_SCOPE) - set(${PYTHON_MODULE_NAME_UP}_FOUND TRUE PARENT_SCOPE) - else() - message ("PYTHON_MODULE_NAME = ${PYTHON_MODULE_NAME} - - PYTHON_MODULE_RESULT = ${PYTHON_MODULE_RESULT} - - PYTHON_MODULE_VERSION = ${PYTHON_MODULE_VERSION} - - PYTHON_MODULE_ERROR = ${PYTHON_MODULE_ERROR}") - unset(${PYTHON_MODULE_NAME_UP}_VERSION PARENT_SCOPE) - set(${PYTHON_MODULE_NAME_UP}_FOUND FALSE PARENT_SCOPE) - endif() - endfunction( find_python_module ) - - # For modules that do not define module.__version__ - function( find_python_module_no_version PYTHON_MODULE_NAME ) - string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}" - RESULT_VARIABLE PYTHON_MODULE_RESULT - ERROR_VARIABLE PYTHON_MODULE_ERROR) - if(PYTHON_MODULE_RESULT EQUAL 0) - # Remove carriage return - message ("++ Python module ${PYTHON_MODULE_NAME} found") - set(${PYTHON_MODULE_NAME_UP}_FOUND TRUE PARENT_SCOPE) + if( PYTHONINTERP_FOUND ) + # GUDHI python run time third parties list, same syntax as detected by 'pip list', but in upper case + set(GUDHI_RUN_TIME_DEPENDENCIES "CYTHON;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "PYTEST;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "MATPLOTLIB;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "NUMPY;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "SCIPY;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "SPHINX;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "SCIKIT-LEARN;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "POT;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "PYBIND11;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "TORCH;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "PYKEOPS;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "EAGERPY;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "HNSWLIB;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "TENSORFLOW;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "SPHINX-PARAMLINKS;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "PYDATA-SPHINX-THEME;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "SPHINXCONTRIB-BIBTEX;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "NETWORKX;${GUDHI_RUN_TIME_DEPENDENCIES}") + set(GUDHI_RUN_TIME_DEPENDENCIES "POUET;${GUDHI_RUN_TIME_DEPENDENCIES}") + + # Get list of installed packages with 'python -m pip freeze' + execute_process(COMMAND ${PYTHON_EXECUTABLE} -m "pip" "freeze" + RESULT_VARIABLE PYTHON_MODULES_RESULT + OUTPUT_VARIABLE PYTHON_MODULES_LIST + ERROR_VARIABLE PYTHON_MODULES_ERROR) + if(PYTHON_MODULES_RESULT EQUAL 0) + string(REPLACE "\n" ";" PYTHON_MODULES_LIST ${PYTHON_MODULES_LIST}) else() - message ("PYTHON_MODULE_NAME = ${PYTHON_MODULE_NAME} - - PYTHON_MODULE_RESULT = ${PYTHON_MODULE_RESULT} - - PYTHON_MODULE_ERROR = ${PYTHON_MODULE_ERROR}") - set(${PYTHON_MODULE_NAME_UP}_FOUND FALSE PARENT_SCOPE) + message ("No pip installed") endif() - endfunction( find_python_module_no_version ) - if( PYTHONINTERP_FOUND ) - find_python_module("cython") - find_python_module("pytest") - find_python_module("matplotlib") - find_python_module("numpy") - find_python_module("scipy") - find_python_module("sphinx") - find_python_module("sklearn") - find_python_module("ot") - find_python_module("pybind11") - find_python_module("torch") - find_python_module("pykeops") - find_python_module("eagerpy") - find_python_module_no_version("hnswlib") - find_python_module("tensorflow") - find_python_module("sphinx_paramlinks") - find_python_module("pydata_sphinx_theme") - find_python_module_no_version("sphinxcontrib.bibtex") - find_python_module("networkx") + # Set Cmake variables ${PYTHON_MODULE}_FOUND and ${PYTHON_MODULE}_VERSION + # of GUDHI_RUN_TIME_DEPENDENCIES found in 'pip list' + foreach(PYTHON_MODULE_LIST ${PYTHON_MODULES_LIST}) + string(REPLACE "==" ";" PYTHON_MODULE ${PYTHON_MODULE_LIST}) + list(POP_FRONT PYTHON_MODULE PYTHON_MODULE_NAME PYTHON_MODULE_VERSION) + string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) + string(TOLOWER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_LOW) + if(PYTHON_MODULE_NAME_UP IN_LIST GUDHI_RUN_TIME_DEPENDENCIES) + message("++ Python module ${PYTHON_MODULE_NAME_LOW} - Version ${PYTHON_MODULE_VERSION} found") + set(${PYTHON_MODULE_NAME_UP}_FOUND TRUE) + set(${PYTHON_MODULE_NAME_UP}_VERSION ${PYTHON_MODULE_VERSION}) + else() + # message(" ## ${PYTHON_MODULE_NAME_UP} not found") + endif() + endforeach() + + # Set gudhi.__debug_info__ + # WARNING : to be done before setup.py.in configure_file + function( add_gudhi_debug_info DEBUG_INFO ) + set(GUDHI_PYTHON_DEBUG_INFO "${GUDHI_PYTHON_DEBUG_INFO} \"${DEBUG_INFO}\\n\" \\\n" PARENT_SCOPE) + endfunction( add_gudhi_debug_info ) + + add_gudhi_debug_info("Python version ${PYTHON_VERSION_STRING}") + foreach(GUDHI_RUN_TIME_DEPENDENCY ${GUDHI_RUN_TIME_DEPENDENCIES}) + string(TOLOWER ${GUDHI_RUN_TIME_DEPENDENCY} GUDHI_RUN_TIME_DEPENDENCY_LOW) + if(${GUDHI_RUN_TIME_DEPENDENCY}_FOUND) + set(GUDHI_RUN_TIME_DEPENDENCY_VERSION "${${GUDHI_RUN_TIME_DEPENDENCY}_VERSION}") + add_gudhi_debug_info("${GUDHI_RUN_TIME_DEPENDENCY_LOW} version ${GUDHI_RUN_TIME_DEPENDENCY_VERSION}") + else() + # Output GUDHI_RUN_TIME_DEPENDENCIES not found in 'pip list' + message("++ Python module ${GUDHI_RUN_TIME_DEPENDENCY_LOW} not found") + endif() + endforeach() + endif() if(NOT GUDHI_PYTHON_PATH) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 551df48cf3..9468829c6a 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -37,15 +37,8 @@ function( add_gudhi_py_test THE_TEST ) endif() endfunction( add_gudhi_py_test ) -# Set gudhi.__debug_info__ -# WARNING : to be done before setup.py.in configure_file -function( add_gudhi_debug_info DEBUG_INFO ) - set(GUDHI_PYTHON_DEBUG_INFO "${GUDHI_PYTHON_DEBUG_INFO} \"${DEBUG_INFO}\\n\" \\\n" PARENT_SCOPE) -endfunction( add_gudhi_debug_info ) - if(PYTHONINTERP_FOUND) if(NUMPY_FOUND AND PYBIND11_FOUND AND CYTHON_FOUND) - add_gudhi_debug_info("Pybind11 version ${PYBIND11_VERSION}") # PyBind11 modules set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'bottleneck', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'hera', ") @@ -79,59 +72,6 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'cover_complex', ") set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'flag_filtration', ") - add_gudhi_debug_info("Python version ${PYTHON_VERSION_STRING}") - add_gudhi_debug_info("Cython version ${CYTHON_VERSION}") - if(PYTEST_FOUND) - add_gudhi_debug_info("Pytest version ${PYTEST_VERSION}") - endif() - if(MATPLOTLIB_FOUND) - add_gudhi_debug_info("Matplotlib version ${MATPLOTLIB_VERSION}") - endif() - if(NUMPY_FOUND) - add_gudhi_debug_info("Numpy version ${NUMPY_VERSION}") - endif() - if(SCIPY_FOUND) - add_gudhi_debug_info("Scipy version ${SCIPY_VERSION}") - endif() - if(SKLEARN_FOUND) - add_gudhi_debug_info("Scikit-learn version ${SKLEARN_VERSION}") - endif() - if(OT_FOUND) - add_gudhi_debug_info("POT version ${OT_VERSION}") - endif() - if(HNSWLIB_FOUND) - # Does not have a version number... - add_gudhi_debug_info("HNSWlib found") - endif() - if(TORCH_FOUND) - add_gudhi_debug_info("PyTorch version ${TORCH_VERSION}") - endif() - if(PYKEOPS_FOUND) - add_gudhi_debug_info("PyKeOps version ${PYKEOPS_VERSION}") - endif() - if(EAGERPY_FOUND) - add_gudhi_debug_info("EagerPy version ${EAGERPY_VERSION}") - endif() - if(TENSORFLOW_FOUND) - add_gudhi_debug_info("TensorFlow version ${TENSORFLOW_VERSION}") - endif() - if(SPHINX_FOUND) - add_gudhi_debug_info("Sphinx version ${SPHINX_VERSION}") - endif() - if(SPHINX_PARAMLINKS_FOUND) - add_gudhi_debug_info("Sphinx-paramlinks version ${SPHINX_PARAMLINKS_VERSION}") - endif() - if(PYDATA_SPHINX_THEME_FOUND) - add_gudhi_debug_info("pydata_sphinx_theme version ${PYDATA_SPHINX_THEME_VERSION}") - endif() - if(SPHINXCONTRIB.BIBTEX_FOUND) - # Does not have a version number... - add_gudhi_debug_info("sphinxcontrib-bibtex found") - endif() - if(NETWORKX_FOUND) - add_gudhi_debug_info("NetworkX version ${NETWORKX_VERSION}") - endif() - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_SYSTEM_NO_DEPRECATED', ") @@ -353,14 +293,14 @@ if(PYTHONINTERP_FOUND) # Documentation generation is available through sphinx - requires all modules # Make it first as sphinx test is by far the longest test which is nice when testing in parallel if(SPHINX_PATH) - if(SPHINX_PARAMLINKS_FOUND) - if(SPHINXCONTRIB.BIBTEX_FOUND) - if(PYDATA_SPHINX_THEME_FOUND) + if(SPHINX-PARAMLINKS_FOUND) + if(SPHINXCONTRIB-BIBTEX_FOUND) + if(PYDATA-SPHINX-THEME_FOUND) if(MATPLOTLIB_FOUND) if(NUMPY_FOUND) if(SCIPY_FOUND) - if(SKLEARN_FOUND) - if(OT_FOUND) + if(SCIKIT-LEARN_FOUND) + if(POT_FOUND) if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/") # User warning - Sphinx is a static pages generator, and configured to work fine with user_version @@ -385,14 +325,14 @@ if(PYTHONINTERP_FOUND) message("++ Python documentation module will not be compiled because it requires a Eigen3 and CGAL version >= 5.1.0") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) - else(OT_FOUND) + else(POT_FOUND) message("++ Python documentation module will not be compiled because POT was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(OT_FOUND) - else(SKLEARN_FOUND) + endif(POT_FOUND) + else(SCIKIT-LEARN_FOUND) message("++ Python documentation module will not be compiled because scikit-learn was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(SKLEARN_FOUND) + endif(SCIKIT-LEARN_FOUND) else(SCIPY_FOUND) message("++ Python documentation module will not be compiled because scipy was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") @@ -405,18 +345,18 @@ if(PYTHONINTERP_FOUND) message("++ Python documentation module will not be compiled because matplotlib was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") endif(MATPLOTLIB_FOUND) - else(PYDATA_SPHINX_THEME_FOUND) + else(PYDATA-SPHINX-THEME_FOUND) message("++ Python documentation module will not be compiled because pydata_sphinx_theme was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(PYDATA_SPHINX_THEME_FOUND) - else(SPHINXCONTRIB.BIBTEX_FOUND) + endif(PYDATA-SPHINX-THEME_FOUND) + else(SPHINXCONTRIB-BIBTEX_FOUND) message("++ Python documentation module will not be compiled because sphinxcontrib-bibtex was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(SPHINXCONTRIB.BIBTEX_FOUND) - else(SPHINX_PARAMLINKS_FOUND) + endif(SPHINXCONTRIB-BIBTEX_FOUND) + else(SPHINX-PARAMLINKS_FOUND) message("++ Python documentation module will not be compiled because sphinxcontrib-paramlinks was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(SPHINX_PARAMLINKS_FOUND) + endif(SPHINX-PARAMLINKS_FOUND) else(SPHINX_PATH) message("++ Python documentation module will not be compiled because sphinx was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") @@ -438,7 +378,7 @@ if(PYTHONINTERP_FOUND) add_gudhi_py_test(test_cubical_complex) # Datasets are fetched for these tests - if(SKLEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) + if(SCIKIT-LEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) add_gudhi_py_test(test_sklearn_cubical_persistence) add_test(NAME cubical_complex_sklearn_itf_py_test @@ -566,7 +506,7 @@ if(PYTHONINTERP_FOUND) add_gudhi_py_test(test_rips_complex) - if(SKLEARN_FOUND) + if(SCIKIT-LEARN_FOUND) # test_sklearn_rips_persistence is using gudhi.datasets.generators if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_gudhi_py_test(test_sklearn_rips_persistence) @@ -612,7 +552,7 @@ if(PYTHONINTERP_FOUND) add_gudhi_py_test(test_off) # Wasserstein - if(OT_FOUND) + if(POT_FOUND) # EagerPy dependency because of enable_autodiff=True if(EAGERPY_FOUND) add_gudhi_py_test(test_wasserstein_distance) @@ -626,7 +566,7 @@ if(PYTHONINTERP_FOUND) endif() # Representations - if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND OT_FOUND AND NOT CGAL_VERSION VERSION_LESS 4.11.0) + if(SCIKIT-LEARN_FOUND AND MATPLOTLIB_FOUND AND POT_FOUND AND NOT CGAL_VERSION VERSION_LESS 4.11.0) add_gudhi_py_test(test_representations) endif() @@ -636,17 +576,17 @@ if(PYTHONINTERP_FOUND) endif() # Perslay - if(TENSORFLOW_FOUND AND SKLEARN_FOUND) + if(TENSORFLOW_FOUND AND SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_perslay) endif() # Betti curves - if(SKLEARN_FOUND AND SCIPY_FOUND) + if(SCIKIT-LEARN_FOUND AND SCIPY_FOUND) add_gudhi_py_test(test_betti_curve_representations) endif() # Representations preprocessing - if(SKLEARN_FOUND) + if(SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_representations_preprocessing) endif() @@ -654,13 +594,13 @@ if(PYTHONINTERP_FOUND) add_gudhi_py_test(test_time_delay) # DTM - if(SCIPY_FOUND AND SKLEARN_FOUND AND TORCH_FOUND AND HNSWLIB_FOUND AND PYKEOPS_FOUND AND EAGERPY_FOUND) + if(SCIPY_FOUND AND SCIKIT-LEARN_FOUND AND TORCH_FOUND AND HNSWLIB_FOUND AND PYKEOPS_FOUND AND EAGERPY_FOUND) add_gudhi_py_test(test_knn) add_gudhi_py_test(test_dtm) endif() # Tomato - if(SCIPY_FOUND AND SKLEARN_FOUND) + if(SCIPY_FOUND AND SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_tomato) endif() @@ -675,7 +615,7 @@ if(PYTHONINTERP_FOUND) endif() # Cover complex - if(SKLEARN_FOUND) + if(SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_cover_complex) endif() diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 59dba06ed5..cdd8534551 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -138,18 +138,18 @@ If :code:`import gudhi` succeeds, please have a look to debug information: import gudhi as gd print(gd.__debug_info__) - print("+ Installed modules are: " + gd.__available_modules) - print("+ Missing modules are: " + gd.__missing_modules) + print(f"+ Installed modules are: {gd.__available_modules}") + print(f"+ Missing modules are: {gd.__missing_modules}") You shall have something like: .. code-block:: none - Pybind11 version 2.8.1 Python version 3.7.12 - Cython version 0.29.25 - Numpy version 1.21.4 - Boost version 1.77.0 + pybind11 version 2.8.1 + numpy version 1.21.4 + cython version 0.29.25 + Boost version 1.77. + Installed modules are: off_utils;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; persistence_graphical_tools;reader_utils;witness_complex;strong_witness_complex; + Missing modules are: bottleneck;nerve_gic;subsampling;tangential_complex;alpha_complex;euclidean_witness_complex; @@ -165,23 +165,25 @@ A complete configuration would be : .. code-block:: none - Pybind11 version 2.8.1 - Python version 3.9.7 - Cython version 0.29.24 - Pytest version 6.2.5 - Matplotlib version 3.5.0 - Numpy version 1.21.4 - Scipy version 1.7.3 - Scikit-learn version 1.0.1 - POT version 0.8.0 - HNSWlib found - PyKeOps version [pyKeOps]: 2.1 - EagerPy version 0.30.0 - TensorFlow version 2.7.0 - Sphinx version 4.3.0 - Sphinx-paramlinks version 0.5.2 - pydata_sphinx_theme version 0.13.1 - NetworkX version 3.0 + Python version 3.9.16 + networkx version 3.0 + sphinxcontrib-bibtex version 2.5.0 + pydata-sphinx-theme version 0.13.1 + sphinx-paramlinks version 0.5.4 + tensorflow version 2.11.1 + hnswlib version 0.7.0 + eagerpy version 0.30.0 + pykeops version 2.1.2 + torch version 2.0.0 + pybind11 version 2.11.1 + pot version 0.9.1 + scikit-learn version 0.24.2 + sphinx version 6.1.3 + scipy version 1.10.1 + numpy version 1.22.4 + matplotlib version 3.6.3 + pytest version 7.2.2 + cython version 0.29.36 Eigen3 version 3.4.0 Boost version 1.74.0 CGAL version 5.3