Skip to content

Improve numerical stability and robustness of enumpoly - #1057

Merged
tturocy merged 4 commits into
masterfrom
issue_1055
Aug 20, 2026
Merged

tturocy merged 4 commits into
masterfrom
issue_1055

Conversation

@tturocy

@tturocy tturocy commented Aug 19, 2026

Copy link
Copy Markdown
Member

This makes two improvements:

  1. Adds a max_rectangles argument to the branch-and-bound equation solver, to prevent it from futilely subdividing down to rectangles of size 1e-8 everywhere;
  2. Rewrite the matrix inversion and solving in a dedicated LU decomposition object which should substantially improve reliability on poorly-condition systems.

Closes #1055.

The branch-and-bound subdivision in `enumpoly` is bounded by a minimum rectangle
size.  However, given that the number of rectangles that can be searched
goes up exponentially as the size is refined, this is not a very
good bound on the total amount of work allowed - and means pathological
cases can run more or less forever.

This introduces a `max_rectangles` parameter, which limits the total amount of searching on a given support.
It's set provisionally to 20000 as a first guess at a reasonable value.

If this budget is exhausted, a new event type (different from "singular" supports) is generated; this is emitted
in the command-line tool if the `-V` switch is specified.
This adds an LU factorisation class internally to the branch-and-bound equation solver
internal to `enumpoly_solve`.  The revised approach has much better numerical stability on less-well-conditioned systems.

This addresses the root cause of very long (and ultimately futile) searches on some supports, where equations would not solve due to numerical inaccuracy.

Closes #1055.
@tturocy tturocy linked an issue Aug 19, 2026 that may be closed by this pull request
@tturocy
tturocy requested a review from rahulsavani August 19, 2026 12:36

@rahulsavani rahulsavani left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Very happy with this.

I added the tests I had in mind for enumpoly. It runs too slow under behavior strategies to do too many equilibria, so only 2 there, and 10 for the original strategic form version.

One thing I recalled by accidentally setting stop_after to 0 is that it is equivalent to stop_after being None. I think that None corresponding to "all" equilibria is natural, but for 0 much less so, so I wonder if that should be mentioned in the docs for any methods that have stop_after as a param? If you agree I can create a separate issue and do that shortly.

@tturocy

tturocy commented Aug 20, 2026

Copy link
Copy Markdown
Member Author

stop_after = 0 working is accidental leakage from the convention in the C++ code. Please make an issue and we can discuss fixing it.

@tturocy
tturocy merged commit c0664ab into master Aug 20, 2026
26 checks passed
@tturocy
tturocy deleted the issue_1055 branch August 20, 2026 15:19
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]: enumpoly hanging on 6x6 bimatrix game

2 participants