Skip to content

Conversation

@TolisChal
Copy link
Member

Add SuiteSparse Integration and Full Dimensional Polytope Support

Summary

This PR adds comprehensive support for the compute_full_dimensional_polytope function by integrating SuiteSparse (SPQR/CHOLMOD) into the VolEsti build system, along with extensive tests and educational examples.

Changes

1. SuiteSparse Integration

  • New: external/cmake-files/SuiteSparse.cmake - CMake module for automatic SuiteSparse download, build, and configuration

    • Clones from official GitHub repository at commit d558c83006d63d1dc62004f30042b3ca484f3f94
    • Builds static libraries: SPQR, CHOLMOD, AMD, COLAMD, CAMD, CCOLAMD, SuiteSparseConfig
    • Exports library paths and include directories for downstream use
    • Installs to external/_deps/suitesparse-build/install/
  • Updated: test/CMakeLists.txt - Added SuiteSparse dependency and linking for new test targets

2. Comprehensive Test Suite

  • New: test/full_dimensional_polytope_test.cpp (575 lines) - 9 test cases covering:
    • ✅ Canonical simplex (3D→2D) - standard probability simplex
    • ✅ Simple feasible cases (3D→2D) - planes intersecting cubes
    • ✅ Line segments (2D→1D) - extreme reduction
    • ✅ High-dimensional cases (10D→8D) - scalability
    • ✅ Multiple equality constraints (3D→1D, 4D→2D)
    • ✅ Hypercube intersections (3D→2D)
    • ✅ Sparse constraints (5D→4D) - efficient handling
    • ✅ Orthogonality properties (4D→3D) - QR factorization verification
    • ✅ Infeasible systems (3D→2D) - error handling

3. Examples

  • New: examples/full_dimensional_polytope/ directory with:

    full_dimensional_example.cpp (387 lines) - Interactive program with 6 examples:

    1. Canonical simplex (3D→2D) - probability distributions
    2. Plane-cube intersection (3D→2D) - geometric cross-sections
    3. Multiple constraints (4D→2D) - conservation laws
    4. Sparse constraints (5D→4D) - network flows
    5. Line segments (2D→1D) - extreme reductions
    6. Birkhoff polytope (9D→8D) - doubly stochastic matrices

    CMakeLists.txt - Proper build configuration with SuiteSparse linking

    README.md - Complete documentation with:

    • Building and running instructions
    • Output format description

Technical Details

Function: compute_full_dimensional_polytope(Aeq, beq, A, b)

Input: Polytope P = {x : Aeq*x = beq, A*x ≤ b} (lower-dimensional)

Output:

  • A_full: Transformed inequality matrix
  • b_full: Transformed inequality vector
  • shift: Point satisfying Aeq*shift = beq
  • N: Orthonormal nullspace basis satisfying Aeq*N = 0

Transformation: x = shift + N*y maps from reduced space to original space

Implementation:

  • Uses SuiteSparse SPQR for QR factorization of Aeq^T
  • Uses CHOLMOD for solving Aeq*x = beq
  • Fallback: Tries Eigen's SparseQR first, uses SuiteSparse if residual > 1e-9

Dependencies

  • SuiteSparse (SPQR, CHOLMOD) - automatically downloaded and built via CMake
  • Eigen3 - matrix operations
  • BLAS/LAPACK - required by SuiteSparse (pre-installed on macOS, easy install on Linux)

Building

Tests

cd test
mkdir build && cd build
cmake ..
make full_dimensional_polytope_test
ctest -R full_dimensional_polytope  # Run all tests
./full_dimensional_polytope_test    # Run directly

Examples

cd examples/full_dimensional_polytope
mkdir build && cd build
cmake ..
make
./full_dimensional_example

Testing Results

All 9 tests pass and verify:

  • ✅ Mathematical correctness (nullspace, orthogonality)
  • ✅ Feasibility preservation via sampling
  • ✅ Correct handling of edge cases (infeasible systems, sparse constraints)
  • ✅ Dimension reduction accuracy
  • ✅ Robust linear system solving (Eigen + SuiteSparse fallback)

Files Added/Modified

Added

  • external/cmake-files/SuiteSparse.cmake (151 lines)
  • external/cmake-files/README_SuiteSparse.md (66 lines)
  • test/full_dimensional_polytope_test.cpp (575 lines)
  • examples/full_dimensional_polytope/full_dimensional_example.cpp (387 lines)
  • examples/full_dimensional_polytope/CMakeLists.txt (112 lines)
  • examples/full_dimensional_polytope/README.md (80 lines)

Modified

  • test/CMakeLists.txt - Added SuiteSparse integration and test registration

Related

  • Implements support for: include/preprocess/full_dimensional_polytope.hpp
  • Documentation: external/cmake-files/README_SuiteSparse.md

Copy link
Member

@vissarion vissarion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition! Very useful for volesti workflows!

I started reviewing it. I have some comments but mainly I couldn't build the examples getting

-- The C compiler identification is GNU 12.3.0
...
-- Boost Library found: /usr/include
-- lp_solve library not found locally, downloading it.
-- Using downloaded lp_solve at: /home/vissarion/workspace/volesti/external/cmake-files/../_deps/lpsolve-src
-- SuiteSparse library not found locally, downloading it.
-- Configuring SuiteSparse...
CMake Error at /home/vissarion/workspace/volesti/external/cmake-files/SuiteSparse.cmake:49 (message):
  SuiteSparse configuration failed: CMake Error: The source directory
  "/home/vissarion/workspace/volesti/external/_deps/suitesparse-build/spqr""
  does not exist.

  Specify --help for usage, or press the help button on the CMake GUI.

Call Stack (most recent call first):
  CMakeLists.txt:66 (GetSuiteSparse)

I will continue reviewing.


### Commit Version

The integration uses SuiteSparse commit: `d558c83006d63d1dc62004f30042b3ca484f3f94`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::cout << " ALL EXAMPLES COMPLETED" << std::endl;
std::cout << std::string(70, '=') << std::endl;

std::cout << "\nKEY TAKEAWAYS:" << std::endl;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those can be removed ;)


// Run all examples
example_canonical_simplex();
std::cout << "\nPress Enter for next example...";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no similar cases in other examples I think it is simpler without user interference

Aqr.compute(Aeq);
VT shift = Aqr.solve(beq);

// If eigen fails try with SuiteSparse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why falling back to suitesparse? Is eigen expected to be faster than suitesparse?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants