From b0eaf78880f7a9f4f79c1342ebb21c51f275f347 Mon Sep 17 00:00:00 2001 From: Ted Turocy Date: Fri, 19 Jul 2024 16:16:31 +0100 Subject: [PATCH] Dropped support for Python 3.8. This drops support for Python 3.8. In addition, * Updates pre-commit actions * Updates Python style for 3.9/3.10 now that 3.8 is not supported. --- .github/workflows/python.yml | 2 +- .pre-commit-config.yaml | 8 ++++---- ChangeLog | 3 +++ pyproject.toml | 2 +- setup.py | 5 ++--- src/pygambit/nash.py | 26 +++++++++++++------------- src/pygambit/qre.py | 10 +++++----- 7 files changed, 29 insertions(+), 27 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 3cb531daa..b4c0a8155 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -10,7 +10,7 @@ jobs: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name strategy: matrix: - python-version: ['3.8', '3.12'] + python-version: ['3.9', '3.12'] steps: - uses: actions/checkout@v4 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c78b4416..3642c94b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,21 +1,21 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-added-large-files - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.13 + rev: v0.5.3 hooks: - id: ruff - repo: https://github.com/pycqa/flake8 - rev: 7.0.0 + rev: 7.1.0 hooks: - id: flake8 - repo: https://github.com/MarcoGorelli/cython-lint - rev: v0.16.0 + rev: v0.16.2 hooks: - id: cython-lint - id: double-quote-cython-strings diff --git a/ChangeLog b/ChangeLog index 7d05f3f67..a9a72d845 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,9 @@ ## [16.3.0] - unreleased +### General +- Dropped support for Python 3.8. + ### Added - Implemented maximum-likelihood estimation for agent logit QRE, to parallel existing support for strategic logit QRE. Strategic logit QRE function names have been modified to provide diff --git a/pyproject.toml b/pyproject.toml index 3c3ff6424..b71562d38 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ requires = ["setuptools", "wheel", "Cython"] [tool.ruff] line-length = 99 indent-width = 4 -target-version = "py38" +target-version = "py39" include = ["setup.py", "src/pygambit/**/*.py", "tests/**/*.py"] exclude = ["contrib/**.py"] diff --git a/setup.py b/setup.py index a3d66b661..94559c59d 100644 --- a/setup.py +++ b/setup.py @@ -111,14 +111,13 @@ def readme(): setuptools.setup( name="pygambit", - version="16.2.0", + version="16.3.0", description="The package for computation in game theory", long_description=readme(), classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -136,7 +135,7 @@ def readme(): "Source": "https://github.com/gambitproject/gambit", "Tracker": "https://github.com/gambitproject/gambit/issues", }, - python_requires=">=3.8", + python_requires=">=3.9", install_requires=[ "lxml", # used for reading/writing GTE files "numpy", diff --git a/src/pygambit/nash.py b/src/pygambit/nash.py index 2b6bda001..f6fe32d7b 100644 --- a/src/pygambit/nash.py +++ b/src/pygambit/nash.py @@ -23,13 +23,14 @@ A set of utilities for computing Nash equilibria """ +from __future__ import annotations + import dataclasses -import typing import pygambit.gambit as libgbt -MixedStrategyEquilibriumSet = typing.List[libgbt.MixedStrategyProfile] -MixedBehaviorEquilibriumSet = typing.List[libgbt.MixedBehaviorProfile] +MixedStrategyEquilibriumSet = list[libgbt.MixedStrategyProfile] +MixedBehaviorEquilibriumSet = list[libgbt.MixedBehaviorProfile] @dataclasses.dataclass(frozen=True) @@ -57,7 +58,7 @@ class NashComputationResult: method: str rational: bool use_strategic: bool - equilibria: typing.Union[MixedStrategyEquilibriumSet, MixedBehaviorEquilibriumSet] + equilibria: MixedStrategyEquilibriumSet | MixedBehaviorEquilibriumSet parameters: dict = dataclasses.field(default_factory=dict) @@ -143,8 +144,8 @@ def lcp_solve( game: libgbt.Game, rational: bool = True, use_strategic: bool = False, - stop_after: typing.Optional[int] = None, - max_depth: typing.Optional[int] = None + stop_after: int | None = None, + max_depth: int | None = None ) -> NashComputationResult: """Compute Nash equilibria of a two-player game using :ref:`linear complementarity programming `. @@ -247,8 +248,7 @@ def lp_solve( def liap_solve( - start: typing.Union[libgbt.MixedStrategyProfileDouble, - libgbt.MixedBehaviorProfileDouble], + start: libgbt.MixedStrategyProfileDouble | libgbt.MixedBehaviorProfileDouble, maxregret: float = 1.0e-4, maxiter: int = 1000 ) -> NashComputationResult: @@ -310,9 +310,9 @@ def liap_solve( def simpdiv_solve( start: libgbt.MixedStrategyProfileRational, - maxregret: libgbt.Rational = None, + maxregret: libgbt.Rational | None = None, refine: int = 2, - leash: typing.Optional[int] = None + leash: int | None = None ) -> NashComputationResult: """Compute Nash equilibria of a game using :ref:`simplicial subdivision `. @@ -371,7 +371,7 @@ def simpdiv_solve( def ipa_solve( - perturbation: typing.Union[libgbt.Game, libgbt.MixedStrategyProfileDouble] + perturbation: libgbt.Game | libgbt.MixedStrategyProfileDouble, ) -> NashComputationResult: """Compute Nash equilibria of a game using :ref:`iterated polymatrix approximation `. @@ -423,7 +423,7 @@ def ipa_solve( def gnm_solve( - perturbation: typing.Union[libgbt.Game, libgbt.MixedStrategyProfileDouble], + perturbation: libgbt.Game | libgbt.MixedStrategyProfileDouble, end_lambda: float = -10.0, steps: int = 100, local_newton_interval: int = 3, @@ -527,7 +527,7 @@ def gnm_solve( raise -def possible_nash_supports(game: libgbt.Game) -> typing.List[libgbt.StrategySupportProfile]: +def possible_nash_supports(game: libgbt.Game) -> list[libgbt.StrategySupportProfile]: """Compute the set of support profiles which could possibly form the support of a totally-mixed Nash equilibrium. diff --git a/src/pygambit/qre.py b/src/pygambit/qre.py index a11ee3c27..ea33e0189 100644 --- a/src/pygambit/qre.py +++ b/src/pygambit/qre.py @@ -22,8 +22,9 @@ """ A set of utilities for computing and analyzing quantal response equilbria """ +from __future__ import annotations + import math -import typing import scipy.optimize @@ -47,7 +48,7 @@ def logit_solve_branch( def logit_solve_lambda( game: libgbt.Game, - lam: typing.Union[float, typing.List[float]], + lam: float | list[float], use_strategic: bool = False, first_step: float = .03, max_accel: float = 1.1, @@ -238,13 +239,12 @@ def _estimate_behavior_empirical( def logit_estimate( - data: typing.Union[libgbt.MixedStrategyProfile, - libgbt.MixedBehaviorProfile], + data: libgbt.MixedStrategyProfile | libgbt.MixedBehaviorProfile, use_empirical: bool = False, local_max: bool = False, first_step: float = .03, max_accel: float = 1.1, -) -> typing.Union[LogitQREMixedStrategyFitResult, LogitQREMixedBehaviorFitResult]: +) -> LogitQREMixedStrategyFitResult | LogitQREMixedBehaviorFitResult: """Use maximum likelihood estimation to find the logit quantal response equilibrium which best fits empirical frequencies of play.