Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement/dependency #3

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ TAGS
*.m~
python/*.egg-info/
/doc/_build/
/build/

18 changes: 6 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.18)
project(robin
VERSION 0.1
VERSION 1.2.0
DESCRIPTION "Robust outlier rejection based on measurement compatibility graphs"
LANGUAGES CXX
)
Expand Down Expand Up @@ -32,9 +32,9 @@ include(DownloadExternal)
#
option(BUILD_DOCS "Build documentation." OFF)
option(BUILD_TESTS "Enable testing with ctest." ON)
option(BUILD_PYTHON_BINDINGS "Build python bindings." ON)
option(BUILD_MATLAB_BINDINGS "Build MATLAB bindings" OFF)
option(USE_ASAN "Enable address sanitizer" OFF)
option(USE_SYSTEM_EIGEN3 "Use system pre-installed Eigen" ON)
option(ENABLE_DIAGNOSTIC_PRINT "Enable printing of diagnostic messages" OFF)

if (ENABLE_DIAGNOSTIC_PRINT)
Expand All @@ -46,7 +46,7 @@ endif ()
# Dependencies
#
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
find_package(Eigen3 3.3 QUIET REQUIRED NO_MODULE)
find_external_dependency("Eigen3" "Eigen3::Eigen" "${CMAKE_CURRENT_LIST_DIR}/cmake/DownloadEigen.cmake")
find_package(OpenMP QUIET REQUIRED)
robin_download_pmc()
robin_download_xenium()
Expand Down Expand Up @@ -89,6 +89,7 @@ include(CMakePackageConfigHelpers)
install(
TARGETS robin
EXPORT robinTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

Expand All @@ -113,6 +114,7 @@ export(
install(
TARGETS xenium pmc
EXPORT robinTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

Expand Down Expand Up @@ -146,13 +148,6 @@ if (BUILD_TESTS)
add_subdirectory(tests)
endif ()

# Python bindings
if (BUILD_PYTHON_BINDINGS)
robin_download_pybind11()
add_subdirectory(${pybind11_SOURCE_DIR} ${pybind11_BINARY_DIR})
add_subdirectory(python)
endif ()

# MATLAB bindings
if (BUILD_MATLAB_BINDINGS)
if (USE_ASAN)
Expand All @@ -177,7 +172,6 @@ message(STATUS "==============================================================="
message(STATUS "============= Robin Configuration Options =====================")
message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
message(STATUS "BUILD_DOCS: ${BUILD_DOCS}")
message(STATUS "BUILD_PYTHON_BINDINGS: ${BUILD_PYTHON_BINDINGS}")
message(STATUS "BUILD_MATLAB_BINDINGS: ${BUILD_MATLAB_BINDINGS}")
message(STATUS "USE_ASAN: ${USE_ASAN}")
message(STATUS "ENABLE_DIAGNOSTIC_PRINT: ${ENABLE_DIAGNOSTIC_PRINT}")
Expand Down
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,24 @@ and

If you are interested in more works from us, please visit our lab page [here](http://web.mit.edu/sparklab/).

# Build and Install
---

# :gear: Build & Installation

## :package: Dependency

ROBIN has the following dependencies:
1. OpenMP
2. Eigen3

Thus, follow the below commandline:

```bash
sudo apt-get install gcc g++ build-essential libeigen3-dev cmake python3-pip python3-dev git ninja-build -y
```

## C++ Installation

Run the following to build the library using CMake (inside the repo root directory):
```bash
mkdir build && cd build
Expand All @@ -41,16 +54,21 @@ The following CMake options are provided:
```
BUILD_DOCS: Build documentation. Default: OFF
BUILD_TESTS: Enable testing with ctest. Default: ON
BUILD_PYTHON_BINDINGS: Build python bindings. Default: ON
BUILD_MATLAB_BINDINGS: Build MATLAB bindings. Default: OFF
USE_ASAN: Enable address sanitizer. Default: OFF
ENABLE_DIAGNOSTIC_PRINT: Enable printing of diagnostic messages. Default: OFF
```
To install Python bindings, after building the library (with `BUILD_PYTHON_BINDINGS=ON`), run:

## Python Installation

It's simple! To install Python bindings, just run:

```bash
cd build/python && pip install .
pip3 install -e python/
```

---

# Third-party Data
Some of the testing data are from the [Network Repository](http://networkrepository.com/index.php).
For more information, please refer to:
Expand Down
17 changes: 17 additions & 0 deletions cmake/DownloadEigen.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
include(FetchContent)
FetchContent_Declare(eigen URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_LIST_DIR}/eigen.patch UPDATE_DISCONNECTED 1)
FetchContent_GetProperties(eigen)
if(NOT eigen_POPULATED)
FetchContent_Populate(eigen)
if(${CMAKE_VERSION} GREATER_EQUAL 3.25)
add_subdirectory(${eigen_SOURCE_DIR} ${eigen_BINARY_DIR} SYSTEM EXCLUDE_FROM_ALL)
else()
# Emulate the SYSTEM flag introduced in CMake 3.25. Withouth this flag the compiler will
# consider this 3rdparty headers as source code and fail due the -Werror flag.
add_subdirectory(${eigen_SOURCE_DIR} ${eigen_BINARY_DIR} EXCLUDE_FROM_ALL)
get_target_property(eigen_include_dirs eigen INTERFACE_INCLUDE_DIRECTORIES)
set_target_properties(eigen PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${eigen_include_dirs}")
endif()
endif()

16 changes: 15 additions & 1 deletion cmake/DownloadExternal.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ include(GNUInstallDirs)
function(robin_download_pybind11)
download_project(PROJ pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG v2.5.0
GIT_TAG v2.13.6
QUIET
)
set(pybind11_SOURCE_DIR "${pybind11_SOURCE_DIR}" PARENT_SCOPE)
Expand Down Expand Up @@ -89,3 +89,17 @@ function(robin_download_xenium)
)
install(DIRECTORY ${xenium_SOURCE_DIR}/xenium DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endfunction()

# For handling Eigen3 library
function(find_external_dependency PACKAGE_NAME TARGET_NAME INCLUDED_CMAKE_PATH)
string(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UP)
set(USE_FROM_SYSTEM_OPTION "USE_SYSTEM_${PACKAGE_NAME_UP}")
if(${${USE_FROM_SYSTEM_OPTION}})
find_package(${PACKAGE_NAME} QUIET NO_MODULE)
endif()
if(NOT ${${USE_FROM_SYSTEM_OPTION}} OR NOT TARGET ${TARGET_NAME})
set(${USE_FROM_SYSTEM_OPTION} OFF PARENT_SCOPE)
include(${INCLUDED_CMAKE_PATH})
endif()
endfunction()

74 changes: 74 additions & 0 deletions cmake/eigen.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
commit cf82186416d04ea5df2a397d8fe09dc78d40ca65
Author: Antonio Sánchez <[email protected]>
Date: Sat Mar 5 05:49:45 2022 +0000

Adds new CMake Options for controlling build components.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index de1c23e91..0af36a53a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -477,6 +477,9 @@ if(EIGEN_BUILD_TESTING)
add_subdirectory(failtest)
endif()

+include(CMakeDetermineFortranCompiler)
+option(EIGEN_BUILD_BLAS "Toggles the building of the Eigen Blas library" ${CMAKE_Fortran_COMPILER})
+option(EIGEN_BUILD_LAPACK "Toggles the building of the included Eigen LAPACK library" ${CMAKE_Fortran_COMPILER})
if(EIGEN_LEAVE_TEST_IN_ALL_TARGET)
add_subdirectory(blas)
add_subdirectory(lapack)
@@ -611,6 +614,8 @@ set_target_properties (eigen PROPERTIES EXPORT_NAME Eigen)

install (TARGETS eigen EXPORT Eigen3Targets)

+option(EIGEN_BUILD_CMAKE_PACKAGE "Enables the creation of EigenConfig.cmake and related files" ON)
+if(EIGEN_BUILD_CMAKE_PACKAGE)
configure_package_config_file (
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Eigen3Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake
@@ -655,6 +660,7 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake
# Add uninstall target
add_custom_target ( uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/EigenUninstall.cmake)
+endif()

if (EIGEN_SPLIT_TESTSUITE)
ei_split_testsuite("${EIGEN_SPLIT_TESTSUITE}")
diff --git a/blas/CMakeLists.txt b/blas/CMakeLists.txt
index 8d3cb86dc..c530957fb 100644
--- a/blas/CMakeLists.txt
+++ b/blas/CMakeLists.txt
@@ -1,6 +1,7 @@

project(EigenBlas CXX)

+if(EIGEN_BUILD_BLAS)
include(CheckLanguage)
check_language(Fortran)
if(CMAKE_Fortran_COMPILER)
@@ -59,4 +60,4 @@ if(EIGEN_BUILD_TESTING)
endif()

endif()
-
+endif()
diff --git a/lapack/CMakeLists.txt b/lapack/CMakeLists.txt
index c8ca64001..8d6d75401 100644
--- a/lapack/CMakeLists.txt
+++ b/lapack/CMakeLists.txt
@@ -1,5 +1,7 @@
project(EigenLapack CXX)

+if(EIGEN_BUILD_LAPACK AND EIGEN_BUILD_BLAS)
+
include(CheckLanguage)
check_language(Fortran)
if(CMAKE_Fortran_COMPILER)
@@ -457,3 +459,6 @@ if(EXISTS ${eigen_full_path_to_testing_lapack})

endif()

+elseif(EIGEN_BUILD_LAPACK AND NOT EIGEN_BUILD_BLAS)
+ message(FATAL_ERROR "EIGEN_BUILD_LAPACK requires EIGEN_BUILD_BLAS")
+endif() #EIGEN_BUILD_LAPACK
55 changes: 29 additions & 26 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.18)

project(robin_python_bindings)

pybind11_add_module(robin_py robin_py/robin_py.cpp)
# Set build type
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

message(STATUS "Python Interpreter Version: ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}")
find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
find_package(pybind11 CONFIG REQUIRED)

target_link_libraries(robin_py PUBLIC robin)
message(STATUS "Python Interpreter Version: ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}")

# fix for clang
# see: https://github.com/pybind/pybind11/issues/1818
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(robin_py PUBLIC -fsized-deallocation)
target_compile_options(spark_robin PUBLIC -fsized-deallocation)
endif ()

if (DEFINED SKBUILD)
message(STATUS "Building with Scikit-Build")
endif ()

# make sure to output the build file to robin_py folder
SET_TARGET_PROPERTIES(robin_py
PROPERTIES
PREFIX ""
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/robin_py"
)

# copy package __init__.py file
configure_file(robin_py/__init__.py
${CMAKE_CURRENT_BINARY_DIR}/robin_py/__init__.py
)

# copy setup.py file
configure_file(setup.py.in
${CMAKE_CURRENT_BINARY_DIR}/setup.py
)

file(COPY .
DESTINATION .
FILES_MATCHING
PATTERN *.py)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../)
# 'robin_cpp': user-defined build directory
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_BINARY_DIR}/robin_cpp)
else()
message(STATUS "Performing out-of-tree build, fetching ROBIN v${CMAKE_PROJECT_VERSION} Release from Github")
include(FetchContent)
FetchContent_Declare(
ext_robin PREFIX robin
URL https://github.com/MIT-SPARK/ROBIN/archive/refs/tags/v${CMAKE_PROJECT_VERSION}.tar.gz)
FetchContent_MakeAvailable(ext_robin)
endif()

pybind11_add_module(spark_robin robin_py/robin_py.cpp)

target_link_libraries(spark_robin PUBLIC robin::robin pmc)

install(TARGETS spark_robin DESTINATION .)
12 changes: 6 additions & 6 deletions python/example.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import robin_py
import spark_robin

if __name__ == "__main__":
print("Examples showing usage of robin_py")

# creating a Graph in robin
g = robin_py.AdjListGraph()
g = spark_robin.AdjListGraph()

for i in range(10):
g.AddVertex(i)
g.AddVertex(i+10)
g.AddEdge(i, i+10)

# find the corresponding inlier structures
max_core_indices = robin_py.FindInlierStructure(
g, robin_py.InlierGraphStructure.MAX_CORE
max_core_indices = spark_robin.FindInlierStructure(
g, spark_robin.InlierGraphStructure.MAX_CORE
)
max_clique_indices = robin_py.FindInlierStructure(
g, robin_py.InlierGraphStructure.MAX_CLIQUE
max_clique_indices = spark_robin.FindInlierStructure(
g, spark_robin.InlierGraphStructure.MAX_CLIQUE
)


Expand Down
35 changes: 35 additions & 0 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[build-system]
requires = ["scikit_build_core", "pybind11"]
build-backend = "scikit_build_core.build"

[project]
name = "spark_robin"
version = "1.2.0"
requires-python = ">=3.8"
description ='Python binding for Robin'
authors = [
{ name = "Jingnan Shi", email = "[email protected]" },
]
classifiers = [
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Intended Audience :: Other Audience",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: Unix",
"Programming Language :: C++",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]

[tool.scikit-build]

2 changes: 1 addition & 1 deletion python/robin_py/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .robin_py import *
from .spark_robin import *
2 changes: 1 addition & 1 deletion python/robin_py/robin_py.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace py = pybind11;
/**
* Python interface with pybind11
*/
PYBIND11_MODULE(robin_py, m) {
PYBIND11_MODULE(spark_robin, m) {
m.doc() = "Python binding for Robin";

// GraphStorageType
Expand Down
Loading