From a1b11278742d65e8484e5e2f8d11b2aa5889f68f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Fern=C3=A1ndez=20Cervell?= Date: Sun, 24 May 2026 20:41:36 +0200 Subject: [PATCH 1/2] Fix core dump on degenerate games by returning trivial zero-dimensional profile --- src/tools/logit/logit.cc | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/tools/logit/logit.cc b/src/tools/logit/logit.cc index a10fbebd2d..2a72a10878 100644 --- a/src/tools/logit/logit.cc +++ b/src/tools/logit/logit.cc @@ -211,6 +211,34 @@ int main(int argc, char *argv[]) return 0; } + bool has_decisions = false; + if (game->IsTree()) { + for (auto player : game->GetPlayers()) { + if (player->GetInfosets().size() > 0) { + has_decisions = true; + break; + } + } + } + else { + for (auto player : game->GetPlayers()) { + if (player->GetStrategies().size() > 0) { + has_decisions = true; + break; + } + } + } + if (!has_decisions) { + if (!game->IsTree() || useStrategic) { + const LogitQREMixedStrategyProfile trivial_profile(game); + PrintProfile(std::cout, decimals, trivial_profile, true); + } else { + const LogitQREMixedBehaviorProfile trivial_profile(game); + PrintProfile(std::cout, decimals, trivial_profile, true); + } + return 0; + } + if (!game->IsTree() || useStrategic) { auto printer = [fullGraph, decimals](const LogitQREMixedStrategyProfile &p) { if (fullGraph) { From 5b2c5c169482be8d846907883b2070911b5c208f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Fern=C3=A1ndez=20Cervell?= Date: Fri, 29 May 2026 20:54:27 +0200 Subject: [PATCH 2/2] Fix core dump on 0-dimension games in logit solvers --- src/solvers/logit/efglogit.cc | 10 +++++++++- src/solvers/logit/nfglogit.cc | 9 +++++++++ src/tools/logit/logit.cc | 28 ---------------------------- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/src/solvers/logit/efglogit.cc b/src/solvers/logit/efglogit.cc index 536677c895..cae2f769d6 100644 --- a/src/solvers/logit/efglogit.cc +++ b/src/solvers/logit/efglogit.cc @@ -313,6 +313,9 @@ LogitBehaviorSolve(const LogitQREMixedBehaviorProfile &p_start, double p_regret, double p_firstStep, double p_maxAccel, MixedBehaviorObserverFunctionType p_observer) { + if (p_start.size() == 0) { + return {p_start}; + } PathTracer tracer; tracer.SetMaxDecel(p_maxAccel); tracer.SetStepsize(p_firstStep); @@ -321,7 +324,6 @@ LogitBehaviorSolve(const LogitQREMixedBehaviorProfile &p_start, double p_regret, if (scale != 0.0) { p_regret *= scale; } - const Game game = p_start.GetGame(); Vector x(ProfileToPoint(p_start)); TracingCallbackFunction callback(game, p_observer); @@ -347,6 +349,9 @@ LogitBehaviorSolveLambda(const LogitQREMixedBehaviorProfile &p_start, double p_firstStep, double p_maxAccel, MixedBehaviorObserverFunctionType p_observer) { + if (p_start.size() == 0) { + return {p_start}; + } PathTracer tracer; tracer.SetMaxDecel(p_maxAccel); tracer.SetStepsize(p_firstStep); @@ -380,6 +385,9 @@ LogitBehaviorEstimate(const MixedBehaviorProfile &p_frequencies, double MixedBehaviorObserverFunctionType p_observer) { const LogitQREMixedBehaviorProfile start(p_frequencies.GetGame()); + if (start.size() == 0) { + return start; + } PathTracer tracer; tracer.SetMaxDecel(p_maxAccel); tracer.SetStepsize(p_firstStep); diff --git a/src/solvers/logit/nfglogit.cc b/src/solvers/logit/nfglogit.cc index 0187887bd6..e8e9f81679 100644 --- a/src/solvers/logit/nfglogit.cc +++ b/src/solvers/logit/nfglogit.cc @@ -351,6 +351,9 @@ LogitStrategySolve(const LogitQREMixedStrategyProfile &p_start, double p_regret, double p_firstStep, double p_maxAccel, const MixedStrategyObserverFunctionType &p_observer) { + if (p_start.size() == 0) { + return {p_start}; + } PathTracer tracer; tracer.SetMaxDecel(p_maxAccel); tracer.SetStepsize(p_firstStep); @@ -385,6 +388,9 @@ LogitStrategySolveLambda(const LogitQREMixedStrategyProfile &p_start, double p_firstStep, double p_maxAccel, const MixedStrategyObserverFunctionType &p_observer) { + if (p_start.size() == 0) { + return {p_start}; + } PathTracer tracer; tracer.SetMaxDecel(p_maxAccel); tracer.SetStepsize(p_firstStep); @@ -418,6 +424,9 @@ LogitStrategyEstimate(const MixedStrategyProfile &p_frequencies, double MixedStrategyObserverFunctionType p_observer) { const LogitQREMixedStrategyProfile start(p_frequencies.GetGame()); + if (start.size() == 0) { + return start; + } PathTracer tracer; tracer.SetMaxDecel(p_maxAccel); tracer.SetStepsize(p_firstStep); diff --git a/src/tools/logit/logit.cc b/src/tools/logit/logit.cc index 2a72a10878..a10fbebd2d 100644 --- a/src/tools/logit/logit.cc +++ b/src/tools/logit/logit.cc @@ -211,34 +211,6 @@ int main(int argc, char *argv[]) return 0; } - bool has_decisions = false; - if (game->IsTree()) { - for (auto player : game->GetPlayers()) { - if (player->GetInfosets().size() > 0) { - has_decisions = true; - break; - } - } - } - else { - for (auto player : game->GetPlayers()) { - if (player->GetStrategies().size() > 0) { - has_decisions = true; - break; - } - } - } - if (!has_decisions) { - if (!game->IsTree() || useStrategic) { - const LogitQREMixedStrategyProfile trivial_profile(game); - PrintProfile(std::cout, decimals, trivial_profile, true); - } else { - const LogitQREMixedBehaviorProfile trivial_profile(game); - PrintProfile(std::cout, decimals, trivial_profile, true); - } - return 0; - } - if (!game->IsTree() || useStrategic) { auto printer = [fullGraph, decimals](const LogitQREMixedStrategyProfile &p) { if (fullGraph) {