From 623e5e065c809ccda9626c79df9c298c06a901b6 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 14 Aug 2026 11:00:13 +1000 Subject: [PATCH 1/4] BUG: Return -1 from best_response_2p instead of falling through to None When tol < 0, no action satisfies the tolerance condition and the function fell through to an implicit None despite documenting an int return. Return -1 in that case, as suggested by oyamad in the review discussion on #576, and document the behavior. Co-Authored-By: Claude Fable 5 --- quantecon/game_theory/normal_form_game.py | 10 +++++++--- quantecon/game_theory/tests/test_normal_form_game.py | 9 +++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/quantecon/game_theory/normal_form_game.py b/quantecon/game_theory/normal_form_game.py index 690e5bb37..d14b22713 100644 --- a/quantecon/game_theory/normal_form_game.py +++ b/quantecon/game_theory/normal_form_game.py @@ -909,13 +909,15 @@ def best_response_2p(payoff_matrix, opponent_mixed_action, tol=1e-8): Opponent's mixed action. Its length must be equal to `payoff_matrix.shape[1]`. - tol : scalar(float), optional(default=None) - Tolerance level used in determining best responses. + tol : scalar(float), optional(default=1e-8) + Tolerance level used in determining best responses. Must be + nonnegative. Returns ------- scalar(int) - Best response action. + Best response action; -1 if there is no action that satisfies + the tolerance condition, which occurs only if `tol` < 0. """ n, m = payoff_matrix.shape @@ -932,3 +934,5 @@ def best_response_2p(payoff_matrix, opponent_mixed_action, tol=1e-8): for a in range(n): if payoff_vector[a] >= payoff_max - tol: return a + + return -1 # Unreachable unless tol < 0 diff --git a/quantecon/game_theory/tests/test_normal_form_game.py b/quantecon/game_theory/tests/test_normal_form_game.py index 1b3bd30a0..a5d6afaca 100644 --- a/quantecon/game_theory/tests/test_normal_form_game.py +++ b/quantecon/game_theory/tests/test_normal_form_game.py @@ -556,3 +556,12 @@ def test_best_response_2p(): br_computed = \ best_response_2p(test_case['payoff_array'], mixed_action) assert_(br_computed == br_expected) + + +def test_best_response_2p_negative_tol(): + # With tol < 0 no action can satisfy the tolerance condition; + # -1 is returned rather than falling through to None + payoff_array = np.array([[4., 0.], [3., 2.]]) + mixed_action = np.array([0.5, 0.5]) + br_computed = best_response_2p(payoff_array, mixed_action, tol=-1e-8) + assert_(br_computed == -1) From 9e9a6c7925058c9b6ccb67c00a3ad78983749ee8 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 14 Aug 2026 11:07:40 +1000 Subject: [PATCH 2/4] DOC: Drop 'must be nonnegative' from best_response_2p tol docs The Returns section already documents the -1 sentinel for tol < 0, so the input restriction read as contradictory. Addresses Copilot review feedback on #936. Co-Authored-By: Claude Fable 5 --- quantecon/game_theory/normal_form_game.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/quantecon/game_theory/normal_form_game.py b/quantecon/game_theory/normal_form_game.py index d14b22713..739c9e386 100644 --- a/quantecon/game_theory/normal_form_game.py +++ b/quantecon/game_theory/normal_form_game.py @@ -910,8 +910,7 @@ def best_response_2p(payoff_matrix, opponent_mixed_action, tol=1e-8): `payoff_matrix.shape[1]`. tol : scalar(float), optional(default=1e-8) - Tolerance level used in determining best responses. Must be - nonnegative. + Tolerance level used in determining best responses. Returns ------- From 7556d02ef1d9e2399f46ca53fdb9972922e7c968 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 14 Aug 2026 11:09:45 +1000 Subject: [PATCH 3/4] DOC: Frame the -1 return of best_response_2p as an error condition Co-Authored-By: Claude Fable 5 --- quantecon/game_theory/normal_form_game.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/quantecon/game_theory/normal_form_game.py b/quantecon/game_theory/normal_form_game.py index 739c9e386..0cd55e541 100644 --- a/quantecon/game_theory/normal_form_game.py +++ b/quantecon/game_theory/normal_form_game.py @@ -915,8 +915,9 @@ def best_response_2p(payoff_matrix, opponent_mixed_action, tol=1e-8): Returns ------- scalar(int) - Best response action; -1 if there is no action that satisfies - the tolerance condition, which occurs only if `tol` < 0. + Best response action. -1 indicates an error condition: no + action satisfies the tolerance condition, which occurs only + if `tol` < 0. """ n, m = payoff_matrix.shape From 898bfb86d4ae7a4467c9f08bb19214f134d72fcc Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 14 Aug 2026 11:10:55 +1000 Subject: [PATCH 4/4] DOC: Restore the nonnegativity stipulation for best_response_2p tol With -1 now explicitly framed as an error condition in the Returns section, stating the valid domain in the parameter docs is complementary rather than contradictory: the parameter doc gives the precondition, the Returns doc gives the failure mode. Co-Authored-By: Claude Fable 5 --- quantecon/game_theory/normal_form_game.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quantecon/game_theory/normal_form_game.py b/quantecon/game_theory/normal_form_game.py index 0cd55e541..43cf3af63 100644 --- a/quantecon/game_theory/normal_form_game.py +++ b/quantecon/game_theory/normal_form_game.py @@ -910,7 +910,8 @@ def best_response_2p(payoff_matrix, opponent_mixed_action, tol=1e-8): `payoff_matrix.shape[1]`. tol : scalar(float), optional(default=1e-8) - Tolerance level used in determining best responses. + Tolerance level used in determining best responses. Must be + nonnegative. Returns -------