Skip to content

Release v0.3.1: Critical Bug Fixes

Choose a tag to compare

@Routhleck Routhleck released this 22 Aug 08:39
· 66 commits to master since this release

CANNS-Ripser v0.3.1 - Critical Bug Fixes

This release addresses two major stability issues that were causing problems in cocycle computation.

πŸ”§ Critical Bug Fixes

βœ… Matrix Reduction Infinite Loop (CRITICAL)

Problem: Matrix reduction algorithm entered infinite loops when processing certain topological structures with cocycle computation enabled, causing the program to hang indefinitely.

Root Cause:

  • Incorrect modular arithmetic leading to factor=0 situations
  • HashSet deduplication removing columns necessary for matrix reduction
  • H0 edge sorting incompatibility with C++ reference implementation

Solution:

  • Implemented proper modp() function for correct modular arithmetic
  • Fixed H0 edge sorting to use descending index order (matching C++ behavior)
  • Removed problematic HashSet deduplication in assemble_columns_to_reduce
  • Updated all coefficient calculations to use robust modular arithmetic

βœ… Empty Cocycle Output (HIGH)

Problem: Cocycle computation appeared to work internally (debug showed correct calculations) but returned empty results to the Python layer.

Root Cause: Python bindings were reading structured cocycle format while the API expected flat format compatible with original ripser.py.

Solution:

  • Added flat_cocycles_by_dim field to RipsResults struct
  • Updated copy_results() to populate flat format directly
  • Modified Python bindings to expose and use flat cocycle format
  • Maintained full backward compatibility with ripser.py API

πŸ§ͺ Test Results

All critical test cases now pass:

  • 6-point circle (previously infinite loop): βœ… Completes in <1 second with correct cocycles
  • 8-point circle (previously empty cocycles): βœ… Returns expected cocycle data
  • Core functionality: βœ… Remains stable and accurate
  • Sparse matrix support: βœ… Unaffected by changes
  • Performance: βœ… No regression in computation speed

πŸ—οΈ Implementation Details

  • All fixes follow the C++ reference implementation exactly
  • Maintains full API compatibility with existing code
  • Robust error handling prevents similar issues in the future
  • Comprehensive test coverage for regression prevention

πŸ“Š Before vs After

Before v0.3.1:

# This would hang indefinitely
result = canns_ripser.ripser(circle_6pts, do_cocycles=True)
# Program stuck in infinite loop...

# This would return empty cocycles  
result = canns_ripser.ripser(circle_8pts, do_cocycles=True)
print(len(result["cocycles"][1]))  # Output: 0 ❌

After v0.3.1:

# Fast and reliable
result = canns_ripser.ripser(circle_6pts, do_cocycles=True)
print(f"H1 cocycles: {len(result['cocycles'][1])}")  # Output: 1 βœ…

# Correct cocycle output
result = canns_ripser.ripser(circle_8pts, do_cocycles=True)  
print(len(result["cocycles"][1]))  # Output: 1 βœ…

πŸš€ Upgrade Guide

This is a recommended upgrade for all users, especially those using cocycle computation:

pip install --upgrade canns-ripser

Breaking Changes: None - full backward compatibility maintained.

New Features: Reliable cocycle computation for all topological structures.


Full Changelog: v0.3.0...v0.3.1