diff --git a/Makefile.am b/Makefile.am index 5ef18af9b..f2ea3fda3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -313,6 +313,10 @@ gtracer_SOURCES = \ src/solvers/gtracer/gnm.cc \ src/solvers/gtracer/ipa.cc +hp_SOURCES = \ + src/solvers/hp/hp.h \ + src/solvers/hp/hp.cc + if IS_WIN32 AM_LDFLAGS = -static -static-libgcc -static-libstdc++ endif diff --git a/doc/references.bib b/doc/references.bib index f39c14834..36ae6110e 100644 --- a/doc/references.bib +++ b/doc/references.bib @@ -38,6 +38,16 @@ @article{GovWil04 category = {articles_equilibria} } +@article{HerPee01, + author = {Herings, P. J.-J. and Peeters, R. J. A. P.}, + title = {A differentiable homotopy to compute {N}ash equilibria of n-person games}, + journal = {Economic Theory}, + volume = {18}, + pages = {159--185}, + year = {2001}, + category = {articles_equilibria} +} + @article{HalPas21, author = {Halpern, J. Y. and Pass, R.}, title = {Sequential equilibrium in games of imperfect recall}, diff --git a/setup.py b/setup.py index 9b47eb533..945b82714 100644 --- a/setup.py +++ b/setup.py @@ -100,6 +100,7 @@ def run(self) -> None: cppgambit_gtracer = solver_library_config("cppgambit_gtracer", ["gtracer", "ipa", "gnm"]) cppgambit_simpdiv = solver_library_config("cppgambit_simpdiv", ["simpdiv"]) cppgambit_enumpoly = solver_library_config("cppgambit_enumpoly", ["nashsupport", "enumpoly"]) +cppgambit_hp = solver_library_config("cppgambit_hp", ["hp"]) libgambit = setuptools.Extension( @@ -117,7 +118,7 @@ def run(self) -> None: setuptools.setup( cmdclass={"build_py": GambitBuildPy}, libraries=[cppgambit_bimatrix, cppgambit_liap, cppgambit_logit, cppgambit_simpdiv, - cppgambit_gtracer, cppgambit_enumpoly, + cppgambit_gtracer, cppgambit_enumpoly, cppgambit_hp, cppgambit_games, cppgambit_core], ext_modules=Cython.Build.cythonize(libgambit, language_level="3str", diff --git a/src/pygambit/gambit.pxd b/src/pygambit/gambit.pxd index 099e4aa2a..644228734 100644 --- a/src/pygambit/gambit.pxd +++ b/src/pygambit/gambit.pxd @@ -621,6 +621,10 @@ cdef extern from "solvers/logit/logit.h": double getitem "operator[]"(int) except +IndexError +cdef extern from "solvers/hp/hp.h": + stdlist[c_MixedStrategyProfile[double]] HPStrategySolve(c_Game) except +RuntimeError + + cdef extern from "nash.h": stdlist[c_MixedBehaviorProfile[double]] LogitBehaviorSolveWrapper( c_Game, double, double, double diff --git a/src/pygambit/nash.pxi b/src/pygambit/nash.pxi index 00c74cf3b..881bd99e1 100644 --- a/src/pygambit/nash.pxi +++ b/src/pygambit/nash.pxi @@ -368,3 +368,7 @@ def _logit_behavior_branch(game: Game, p.thisptr = profile_ptr ret.append(p) return ret + + +def _hp_strategy_solve(game: Game) -> list[MixedStrategyProfileDouble]: + return _convert_mspd(HPStrategySolve(game.game)) diff --git a/src/pygambit/nash.py b/src/pygambit/nash.py index 96201df0b..a233448df 100644 --- a/src/pygambit/nash.py +++ b/src/pygambit/nash.py @@ -804,3 +804,32 @@ def logit_solve( equilibria=equilibria, parameters={"first_step": first_step, "max_accel": max_accel}, ) + + +def hp_solve( + game: libgbt.Game, +) -> NashComputationResult: + """Compute Nash equilibria of a game using :cite:p:`HerPee01` + + Returns an approximation to the limiting point on the principal branch of + the homotopy path for the game. + + Parameters + ---------- + game : Game + The game to compute equilibria in. + + Returns + ------- + res : NashComputationResult + The result represented as a ``NashComputationResult`` object. + """ + equilibria = libgbt._hp_strategy_solve(game) + return NashComputationResult( + game=game, + method="hp", + rational=False, + use_strategic=True, + equilibria=equilibria, + parameters={}, + ) diff --git a/src/solvers/hp/hp.cc b/src/solvers/hp/hp.cc new file mode 100644 index 000000000..15e57b6e3 --- /dev/null +++ b/src/solvers/hp/hp.cc @@ -0,0 +1,38 @@ +// +// This file is part of Gambit +// Copyright (c) 1994-2026, The Gambit Project (https://www.gambit-project.org) +// +// FILE: src/solvers/hp/hp.cc +// Computation of a Nash equilibria using a differentiable homotopy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// + +#include +#include "gambit.h" +#include "solvers/hp/hp.h" + +namespace Gambit { +std::list> HPStrategySolve(const Game &p_game) +{ + std::list> result; + const StrategySupportProfile support(p_game); + + const MixedStrategyProfile trivial_profile = support.NewMixedStrategyProfile(); + + result.push_back(trivial_profile); + return result; +} +} // namespace Gambit diff --git a/src/solvers/hp/hp.h b/src/solvers/hp/hp.h new file mode 100644 index 000000000..d51a0dc6c --- /dev/null +++ b/src/solvers/hp/hp.h @@ -0,0 +1,32 @@ +// +// This file is part of Gambit +// Copyright (c) 1994-2026, The Gambit Project (http://www.gambit-project.org) +// +// FILE: src/solvers/hp/hp.h +// Computation of a Nash equilibria using a differentiable homotopy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// + +#ifndef HP_H +#define HP_H + +#include + +namespace Gambit { +std::list> HPStrategySolve(const Game &p_game); +} // namespace Gambit + +#endif // HP_H