Skip to content

fix: resolve numerical failures and premature caching in ComputeInnerBall#468

Open
devangpratap wants to merge 2 commits intoGeomScale:developfrom
devangpratap:develop
Open

fix: resolve numerical failures and premature caching in ComputeInnerBall#468
devangpratap wants to merge 2 commits intoGeomScale:developfrom
devangpratap:develop

Conversation

@devangpratap
Copy link
Copy Markdown

##Overview
This PR addresses three critical stability issues in ComputeInnerBall within the volesti core. These bugs previously allowed for garbage data propagation and segmentation faults when handling non-full-dimensional H-polytopes.

Root Causes Identified

  1. Premature State Flagging: has_ball = true was set before computation, allowing cached failures.
  2. Degeneracy Handling: Missing validation for lpsolve returning OPTIMAL with r=0 in degenerate cases (e.g., 2D in 3D).
  3. Uninitialized Sentinels: The DISABLE_LPSOLVE path left _inner_ball.second indeterminate.

Technical Fixes

  • Standardized failure return to {Point(_d), NT(-1)} to maintain ambient dimension consistency.
  • Implemented lp_result.second >= tol/2.0 validation (aligning with IP solver thresholds).
  • Deferred has_ball assignment until solver success is confirmed.

Regression Testing

Added a new test case in test/test_internal_points.cpp:

Devang Pratap added 2 commits March 3, 2026 21:30
GeomScale#463)

Three bugs caused garbage data to propagate when both max_inscribed_ball
and lpsolve fail on non-full-dimensional H-polytopes:

1. has_ball was set true before computation completed, so a subsequent
   lpsolve failure (exception_pair with Point(1) and radius -1) would be
   permanently cached as a valid result with a mismatched dimension.

2. ComputeChebychevBall's return value was stored without validation. For
   an exactly degenerate polytope lpsolve returns OPTIMAL with r=0, which
   callers checking (radius < 0.0) would not catch, leading to division by
   zero downstream. For numerical failures it returns exception_pair with
   radius -1 and a 1-dimensional center regardless of polytope dimension.

3. The DISABLE_LPSOLVE failure path reset has_ball to false but returned
   _inner_ball whose second member (NT/double) was never written, leaving
   the radius indeterminate.

Fix: validate the lpsolve result against tol/2.0 (mirroring the existing
check on max_inscribed_ball's output). On failure return {Point(_d), -1}
directly without caching, giving callers the proper-dimension zero center
and the -1 sentinel they already expect. has_ball is only set on success.

Add a regression test: a 2D square embedded in 3D space via x3=0 as a
pair of inequality constraints. Both solvers correctly find no positive-
radius ball; the fix ensures the returned pair has dimension 3 (not 1)
and radius -1 (not 0 or indeterminate), and that repeated calls do not
cache a false success.
Ran clang-format -style="{BasedOnStyle: LLVM, IndentWidth: 4}" on both
files to bring them in line with project style requirements. No logic
changes; only whitespace, brace placement, and line-wrapping adjustments.
Copy link
Copy Markdown
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.

Thanks for this PR. Could you please remove all changes related to style and reordering of commands to simplify review and focus on the real changes of the PR.

@devangpratap
Copy link
Copy Markdown
Author

Thanks for this PR. Could you please remove all changes related to style and reordering of commands to simplify review and focus on the real changes of the PR.

Understood, working on it.

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.

Bug: Numerical instability in max_inscribed_ball for degenerate polytopes

2 participants