Skip to content

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

@DDDOH

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions