Import tests: Shayan1/Prod/tests/test_solver

Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
arsam
2026-09-18 23:14:55 +03:30
parent 6c5a95f3b4
commit 11160a6591
+145
View File
@@ -0,0 +1,145 @@
import numpy as np
import pytest
from nash import solver
from nash.game import Game
PRICING = Game.load_from_json("games/pricing.json")
MATCHING_PENNIES = Game.load_from_json("games/matching_pennies.json")
def test_pricing_has_one_pure_equilibrium_low_low():
equilibria = solver.find_pure_nash_equilibria(PRICING)
assert equilibria == [(1, 1)]
def test_matching_pennies_has_no_pure_equilibrium():
equilibria = solver.find_pure_nash_equilibria(MATCHING_PENNIES)
assert equilibria == []
def test_pricing_mixed_equilibrium_matches_pure_equilibrium():
equilibria = solver.find_mixed_nash_equilibria(PRICING)
assert len(equilibria) == 1
x, y = equilibria[0]
assert np.allclose(x, [0, 1], atol=1e-6)
assert np.allclose(y, [0, 1], atol=1e-6)
def test_matching_pennies_mixed_equilibrium_is_fifty_fifty():
equilibria = solver.find_mixed_nash_equilibria(MATCHING_PENNIES)
assert len(equilibria) == 1
x, y = equilibria[0]
assert np.allclose(x, [0.5, 0.5], atol=1e-6)
assert np.allclose(y, [0.5, 0.5], atol=1e-6)
def test_mixed_solver_rejects_more_than_two_players():
game = Game(
players=["A", "B", "C"],
strategies=[["x", "y"], ["x", "y"], ["x", "y"]],
payoffs=[np.zeros((2, 2, 2))] * 3,
)
with pytest.raises(NotImplementedError):
solver.find_mixed_nash_equilibria(game)
def test_pure_equilibrium_finder_supports_n_players():
# Simple 3-player coordination game: everyone matching strategy 0 is the
# unique pure Nash equilibrium (payoff 1 if all match, 0 otherwise).
payoff = np.zeros((2, 2, 2))
payoff[0, 0, 0] = 1
game = Game(
players=["A", "B", "C"],
strategies=[["x", "y"], ["x", "y"], ["x", "y"]],
payoffs=[payoff, payoff, payoff],
)
equilibria = solver.find_pure_nash_equilibria(game)
assert (0, 0, 0) in equilibria
def test_pricing_has_dominant_strategies():
result = solver.find_dominant_strategies(PRICING)
# Both companies have "Low" (index 1) as strictly dominant strategy:
# Company A: Low beats High vs any B strategy (10>8, 5>2)
# Company B: Low beats High vs any A strategy (10>8, 5>2)
assert result == {0: 1, 1: 1}
def test_matching_pennies_has_no_dominant_strategies():
result = solver.find_dominant_strategies(MATCHING_PENNIES)
assert result == {0: None, 1: None}
def test_dominant_strategies_supports_n_players():
# 3-player game: players 0,1 have strictly dominant strategy 0;
# player 2 has no dominant strategy.
payoffs_0 = np.zeros((2, 2, 2))
payoffs_1 = np.zeros((2, 2, 2))
payoffs_2 = np.zeros((2, 2, 2))
for profile in np.ndindex(2, 2, 2):
payoffs_0[profile] = 10.0 if profile[0] == 0 else 1.0
payoffs_1[profile] = 10.0 if profile[1] == 0 else 1.0
payoffs_2[profile] = float(profile[0] + profile[1])
game = Game(
players=["A", "B", "C"],
strategies=[["x", "y"], ["x", "y"], ["x", "y"]],
payoffs=[payoffs_0, payoffs_1, payoffs_2],
)
result = solver.find_dominant_strategies(game)
assert result[0] == 0
assert result[1] == 0
assert result[2] is None
def test_dominant_strategies_one_strategy_player():
# Player 0 has 1 strategy, Player 1 has 2 strategies
payoffs_0 = np.array([[5.0, 5.0]]) # 1x2 matrix
payoffs_1 = np.array([[10.0, 1.0]]) # 1x2 matrix
game = Game(
players=["A", "B"],
strategies=[["only"], ["x", "y"]],
payoffs=[payoffs_0, payoffs_1],
)
result = solver.find_dominant_strategies(game)
# Player 0 has no dominant strategy (None) because they only have 1 strategy.
# Player 1 has dominant strategy 0 (10.0 > 1.0).
assert result == {0: None, 1: 0}
def test_reduce_game_pricing():
reduced, logs = solver.reduce_game(PRICING)
assert len(logs) == 2
assert "Player 'Company A' eliminated dominated strategy 'High'" in logs[0]
assert "Player 'Company B' eliminated dominated strategy 'High'" in logs[1]
assert reduced.strategies == [["Low"], ["Low"]]
assert np.allclose(reduced.payoffs[0], [[5]])
assert np.allclose(reduced.payoffs[1], [[5]])
def test_reduce_game_matching_pennies():
reduced, logs = solver.reduce_game(MATCHING_PENNIES)
assert len(logs) == 0
assert reduced.strategies == MATCHING_PENNIES.strategies
assert np.allclose(reduced.payoffs[0], MATCHING_PENNIES.payoffs[0])
assert np.allclose(reduced.payoffs[1], MATCHING_PENNIES.payoffs[1])
def test_reduce_game_n_players():
payoffs_0 = np.zeros((2, 2, 2))
payoffs_1 = np.zeros((2, 2, 2))
payoffs_2 = np.zeros((2, 2, 2))
payoffs_0[0, :, :] = 1.0
payoffs_0[1, :, :] = 2.0
payoffs_1[:, 0, :] = 1.0
payoffs_1[:, 1, :] = 2.0
payoffs_2[:, :, 0] = 1.0
payoffs_2[:, :, 1] = 2.0
game = Game(
players=["P0", "P1", "P2"],
strategies=[["A", "B"], ["C", "D"], ["E", "F"]],
payoffs=[payoffs_0, payoffs_1, payoffs_2]
)
reduced, logs = solver.reduce_game(game)
assert len(logs) == 3
assert reduced.strategies == [["B"], ["D"], ["F"]]
assert np.allclose(reduced.payoffs[0], [[[2.0]]])