Skip to content

BUG: simpdiv_solve raises "Index out of range in RectArray" on some strategic games #868

Description

@DDDOH

pygambit.nash.simpdiv_solve raises a C++ backend exception on some normal-form games created via Game.from_arrays.

I saw issue #480 about refactoring the internals of simpdiv_solve; this may be related. I am opening this as a concrete reproducible crash case.

Minimal reproducer

import numpy as np
import pygambit as gbt

rng = np.random.default_rng(0)

payoffs = [
    rng.normal(size=(8, 8)),
    rng.normal(size=(8, 8)),
]

game = gbt.Game.from_arrays(*payoffs)
start = game.mixed_strategy_profile(rational=True)

print("pygambit:", gbt.__version__)
print("players:", len(game.players))
print("strategies:", [len(player.strategies) for player in game.players])
print("start:", [[start[strategy] for strategy in player.strategies] for player in game.players])

result = gbt.nash.simpdiv_solve(start)
print(result)

Actual behavior

On my machine this raises:

RuntimeError: Index out of range in RectArray

The start profile is a valid rational mixed strategy profile:

players: 2
strategies: [8, 8]
start: [[Rational(1, 8), ..., Rational(1, 8)],
        [Rational(1, 8), ..., Rational(1, 8)]]

I also reproduced the same error on some 3-player and 4-player strategic games, for example random payoff arrays with shapes (4, 4, 4) and (4, 4, 4, 4).

Expected behavior

simpdiv_solve should either return a NashComputationResult, or fail with a user-facing algorithm error explaining why the method cannot proceed from the given starting profile. It should not expose an internal RectArray bounds error.

Environment

Python: 3.11.15
Platform: macOS 26.4.1 arm64
Machine: arm64
pygambit: 16.6.0
numpy: 2.4.4

Notes / possible cause

The exception string appears to come from Gambit's C++ RectArray bounds checks. Looking at src/solvers/simpdiv/simpdiv.cc, NashSimpdivStrategySolver::Simplex maintains path-tracking state in arrays such as:

RectArray<int> labels(y.MixedProfileLength(), 2), pi(y.MixedProfileLength(), 2);

The crash may indicate that the simpdiv path-following logic reaches an invalid row index for labels or pi under some game/start-profile combinations.

This does not appear to be specific to the Python wrapper or to a custom game conversion layer: the reproducer above uses only numpy, Game.from_arrays, mixed_strategy_profile(rational=True), and simpdiv_solve.

Metadata

Metadata

Assignees

Labels

bugc++Items which involve writing in C++nashItems which involve Nash equilibrium computation methods

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions