Skip to content

Fix #492: Optimization and Stability Enhancements in Logit´s path follower#876

Open
AndresFerCervell wants to merge 5 commits into
gambitproject:masterfrom
AndresFerCervell:gsoc-hp-homotopy
Open

Fix #492: Optimization and Stability Enhancements in Logit´s path follower#876
AndresFerCervell wants to merge 5 commits into
gambitproject:masterfrom
AndresFerCervell:gsoc-hp-homotopy

Conversation

@AndresFerCervell
Copy link
Copy Markdown

Thanks for contributing to Gambit! Before you submitting or reviewing a pull request, check out our guidelines for contributing.

The person submitting the PR should ensure it has an informative title and update the headers below, before marking the PR as ready for review and assigning reviewers.

Issues closed by this PR

#492

Description of the changes in this PR

This PR introduces several mathematical and structural improvements to the QRE (Quantal Response Equilibrium) tracing algorithm to increase convergence stability and prevent crashes, particularly in edge-case games.

  • Implemented regret validation in efglogit.cc and nfglogit.cc to prevent false NE reporting by tracking the profile with the lowest regret.
  • Stabilized Predictor-Corrector in path.cc using alternating multidimensional perturbations at bifurcations.
  • Replaced strict orientation flip rejection with a lambda-based geometric safeguard to handle fold bifurcations.
  • Added a defensive programming shield in logit.cc to prevent std::out_of_range exceptions in games with 0 players decisions.

Validated the fix against the full Gambit game suite (196 games), resolving 7 previously failing cases including team_mp.txt and 2x2x2.nfg.

How to review this PR

-Review the symmetry-breaking logic and the updated default parameters in src/tools/logit/path.cc and src/tools/logit/path.h.
-Verify the defensive shield in src/tools/logit/logit.cc by running a degenerate game like tests/test_games/chance_root_5_moves_no_nonterm_player_nodes.efg. It should now exit cleanly with a warning instead of throwing a segmentation fault.
-Run gambit-logit on team_mp.txt to confirm it now reaches the Nash Equilibrium successfully without getting stuck in the bifurcation.
Note: A detailed PDF report containing the empirical Grid Search methodology used to tune the parameters can be found here: https://github.com/AndresFerCervell/GSoC-2026-Gambit-Portfolio/blob/main/1_Optimization_and_Stability_Enhancements_in_Gambit_s_QRE_Tracing_Algorithm.pdf
The mathematical explanation can be found here: https://github.com/AndresFerCervell/GSoC-2026-Gambit-Portfolio/blob/main/Gambit_Logit_Algorithm.pdf

…regret validation

- Task 1: Implemented regret validation in efglogit.cc and nfglogit.cc to prevent false NE reporting by tracking the profile with the lowest regret.
- Task 2: Stabilized Predictor-Corrector in path.cc using alternating multidimensional perturbations at bifurcations.
- Replaced strict orientation flip rejection with a lambda-based geometric safeguard to handle fold bifurcations.

Validated the fix against the full Gambit game suite (176 games), resolving 5 previously failing cases including team_mp.txt and 2x2x2.nfg.
@tturocy
Copy link
Copy Markdown
Member

tturocy commented May 22, 2026

These are generally good, but it is a bit more disciplined to keep logically-distinct changes separate.

There's three different matters being addressed here:

  1. The new perturbation approach
  2. Dealing correctly with the case that the tracer does terminate early due to getting "stuck"
  3. The issue with no player decisions

Each of these can be either own branch and PR because each of them is independent of the other.

Some specific notes on each:

  1. For the moment this looks good. We just need to have an entry in the ChangeLog to memorialise that we did change the way the perturbation is resolved, because this can (and will) change the behaviour of the method on games with a bifurcation. Given that we do not publicly make promises (yet!!!!) about how these are resolved that's all we really need to do (we will as part of the larger project have some public documentation of our approach)

  2. For this the most important change would seem to be that TracePath should return a value (or object) summarising the success/failure of the method, rather than void. This way we can flag in general when the method gets "stuck". Then we can pass that upstream. We generally want to avoid issuing warnings to cerr inside the library proper because user programs can't see those, so if you're running something in a script that's not useful. We want to return the relevant data on the failure and then it is left to calling code to decide what if anything to do about it.

I think it's OK to change the minimum step sizes/criteria for stopping when "stuck". I'm less convinced about changing any defaults, because that will again visibly change the behaviour of the program on existing examples that "work". Our existing sample of ~200 games actually isn't that big, nor has it been systematically curated for variety, so I wouldn't over-optimise changing defaults based on it.

  1. Handling the zero-dimension edge case is good. For this however rather than an error actually we can simply define the output to be the trivial mixed or behaviour profile with lambda = 0. This is by analogy to the case where players do have decisions but all payoffs are zero (or a constant); the method terminates with lambda = 0 and strategy profile = uniform randomisation everywhere.

I might suggest doing (2) before (1) because we have the existing examples that get stuck, so we can test out the return paths with them.

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: QRE tracing stalling at bifurcation, incorrectly reporting output as Nash

2 participants