From dd8fa9799a0335dc95bc9c0afb919cec24da3f40 Mon Sep 17 00:00:00 2001 From: Theodore Turocy Date: Mon, 20 Jul 2026 19:05:23 -0400 Subject: [PATCH] Correct `gnm_solve` to execute callback when equilibria are found rather than waiting until the end of the run. --- ChangeLog | 2 ++ src/solvers/gnm/gnm.cc | 3 +-- src/solvers/gtracer/gnm.cc | 2 +- src/solvers/gtracer/gtracer.h | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 18f6e94ca1..9704c98b4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ ### Changed - `lcp_solve` no longer silently absorbs internal exceptions if they occur, but instead these propagate out to match the behaviour of all other Nash equilibrium solvers. (#996) +- `gnm_solve` executes callback when equilibrium is found rather than emitting all equilibria at the end of + the run. (#998) - Implemented bespoke XML parser that handles the subset in the de-facto legacy XML workbook .gbt format; removes dependency on tinyxml. (#897) diff --git a/src/solvers/gnm/gnm.cc b/src/solvers/gnm/gnm.cc index d513e3aad6..a208b6db1e 100644 --- a/src/solvers/gnm/gnm.cc +++ b/src/solvers/gnm/gnm.cc @@ -58,9 +58,8 @@ Solve(const Game &p_game, const std::shared_ptr &p_rep, const cvector & }; GNM(*p_rep, norm_pert, answers, p_steps, FUZZ, p_localNewtonInterval, p_localNewtonMaxits, p_lambdaEnd, WOBBLE, THRESHOLD, callback, return_message); - for (auto answer : answers) { + for (const auto &answer : answers) { eqa.push_back(ToProfile(p_game, answer)); - p_callback(eqa.back(), "NE"); } return eqa; } diff --git a/src/solvers/gtracer/gnm.cc b/src/solvers/gtracer/gnm.cc index 93864cad8e..aa48a5c7d5 100644 --- a/src/solvers/gtracer/gnm.cc +++ b/src/solvers/gtracer/gnm.cc @@ -326,7 +326,7 @@ void GNM(gnmgame &A, cvector &g, std::list &Eq, int steps, double fuzz, if (ee < fuzz) { // only save high quality equilibria; // this restriction could be removed. Eq.push_back(sigma); - // PrintProfile(std::cout, "NE", sigma); + p_onStep("NE", Eq.back()); } Index = -Index; s_hat_old = -1; diff --git a/src/solvers/gtracer/gtracer.h b/src/solvers/gtracer/gtracer.h index e268bb9bf7..eb1edb291b 100644 --- a/src/solvers/gtracer/gtracer.h +++ b/src/solvers/gtracer/gtracer.h @@ -55,7 +55,8 @@ namespace Gambit::gametracer { /// @param threshold the equilibrium error threshold for doing a wobble. If /// wobbles are disabled, GNM will terminate if the error /// reaches this threshold. -/// @param p_onStep a callback function executed on each step of the algorithm +/// @param p_onStep a callback function executed on each step of the algorithm and whenever an +/// equilibrium is found (with label "NE") void GNM(gnmgame &A, cvector &g, std::list &Eq, int steps, double fuzz, int LNMFreq, int LNMMax, double LambdaMin, bool wobble, double threshold, std::function p_onStep,