Skip to content

Commit 0db2064

Browse files
committed
Develop Strategies for game and use in liap solver.
1 parent 788ed67 commit 0db2064

File tree

3 files changed

+45
-36
lines changed

3 files changed

+45
-36
lines changed

src/core/util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ auto minimize_function(const Container &p_container, const Func &p_function)
157157
[](const T &a, const T &b) -> T { return std::min(a, b); }, p_function);
158158
}
159159

160+
/// @brief Returns the sum of the function over the container
161+
template <class Container, class Func>
162+
auto sum_function(const Container &p_container, const Func &p_function)
163+
{
164+
using T = decltype(p_function(*(p_container.begin())));
165+
return std::transform_reduce(p_container.begin(), p_container.end(), static_cast<T>(0),
166+
std::plus<T>(), p_function);
167+
}
168+
160169
//========================================================================
161170
// Exception classes
162171
//========================================================================

src/games/game.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,18 @@ class GameRep : public std::enable_shared_from_this<GameRep> {
824824
virtual Array<int> NumStrategies() const = 0;
825825
/// Gets the i'th strategy in the game, numbered globally
826826
virtual GameStrategy GetStrategy(int p_index) const = 0;
827+
/// Gets the set of strategies in the game
828+
std::vector<GameStrategy> GetStrategies() const
829+
{
830+
BuildComputedValues();
831+
std::vector<GameStrategy> ret;
832+
for (const auto &player : m_players) {
833+
for (const auto &strategy : player->m_strategies) {
834+
ret.emplace_back(strategy);
835+
}
836+
}
837+
return ret;
838+
}
827839
/// Creates a new strategy for the player
828840
virtual GameStrategy NewStrategy(const GamePlayer &p_player, const std::string &p_label)
829841
{

src/solvers/liap/nfgliap.cc

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2121
//
2222

23-
#include <numeric>
24-
2523
#include "gambit.h"
2624
#include "core/function.h"
2725
#include "liap.h"
@@ -63,45 +61,41 @@ class StrategicLyapunovFunction : public FunctionOnSimplices {
6361
inline double sum_player_probs(const MixedStrategyProfile<double> &p_profile,
6462
const GamePlayer &p_player)
6563
{
66-
auto strategies = p_player->GetStrategies();
67-
return std::accumulate(
68-
strategies.cbegin(), strategies.cend(), 0.0,
69-
[p_profile](double t, const GameStrategy &s) { return t + p_profile[s]; });
64+
return sum_function(p_player->GetStrategies(),
65+
[&p_profile](const auto &s) -> double { return p_profile[s]; });
7066
}
7167

7268
double StrategicLyapunovFunction::Value(const Vector<double> &v) const
7369
{
7470
m_profile = v;
7571
double value = 0;
76-
// Liapunov function proper - should be replaced with call to profile once
77-
// the penalty is removed from that implementation.
78-
for (auto player : m_profile.GetGame()->GetPlayers()) {
79-
for (auto strategy : player->GetStrategies()) {
80-
value += sqr(
81-
std::max(m_scale * (m_profile.GetPayoff(strategy) - m_profile.GetPayoff(player)), 0.0));
82-
}
72+
// Liapunov function proper
73+
for (const auto &player : m_profile.GetGame()->GetPlayers()) {
74+
const auto payoff = m_profile.GetPayoff(player);
75+
value += sum_function(player->GetStrategies(), [this, &payoff](const auto &s) -> double {
76+
return sqr(std::max(m_scale * (m_profile.GetPayoff(s) - payoff), 0.0));
77+
});
8378
}
8479
// Penalty function for non-negativity constraint for each strategy
85-
for (auto player : m_profile.GetGame()->GetPlayers()) {
86-
for (auto strategy : player->GetStrategies()) {
87-
value += m_penalty * sqr(std::min(m_profile[strategy], 0.0));
88-
}
89-
}
80+
value += m_penalty * sum_function(m_profile.GetGame()->GetStrategies(), [&](const auto &s) {
81+
return sqr(std::min(m_profile[s], 0.0));
82+
});
9083
// Penalty function for sum-to-one constraint for each player
91-
for (auto player : m_profile.GetGame()->GetPlayers()) {
92-
value += m_penalty * sqr(sum_player_probs(m_profile, player) - 1.0);
93-
}
84+
value +=
85+
m_penalty * sum_function(m_profile.GetGame()->GetPlayers(), [this](const auto &p) -> double {
86+
return sqr(sum_player_probs(m_profile, p) - 1.0);
87+
});
9488
return value;
9589
}
9690

9791
double StrategicLyapunovFunction::LiapDerivValue(const MixedStrategyProfile<double> &p_profile,
9892
const GameStrategy &p_wrt_strategy) const
9993
{
10094
double deriv = 0.0;
101-
for (auto player : m_game->GetPlayers()) {
102-
for (auto strategy : player->GetStrategies()) {
103-
const double loss =
104-
sqr(m_scale) * (p_profile.GetPayoff(strategy) - p_profile.GetPayoff(player));
95+
for (const auto &player : m_game->GetPlayers()) {
96+
const auto payoff = p_profile.GetPayoff(player);
97+
for (const auto &strategy : player->GetStrategies()) {
98+
const double loss = sqr(m_scale) * (p_profile.GetPayoff(strategy) - payoff);
10599
if (loss <= 0.0) {
106100
continue;
107101
}
@@ -121,13 +115,9 @@ double StrategicLyapunovFunction::LiapDerivValue(const MixedStrategyProfile<doub
121115
bool StrategicLyapunovFunction::Gradient(const Vector<double> &v, Vector<double> &d) const
122116
{
123117
m_profile = v;
124-
auto element = d.begin();
125-
for (auto player : m_game->GetPlayers()) {
126-
for (auto strategy : player->GetStrategies()) {
127-
*element = LiapDerivValue(m_profile, strategy);
128-
++element;
129-
}
130-
}
118+
const auto strategies = m_profile.GetGame()->GetStrategies();
119+
std::transform(strategies.begin(), strategies.end(), d.begin(),
120+
[&](const auto &s) -> double { return LiapDerivValue(m_profile, s); });
131121
Project(d, m_game->NumStrategies());
132122
return true;
133123
}
@@ -137,10 +127,8 @@ namespace {
137127
MixedStrategyProfile<double> EnforceNonnegativity(const MixedStrategyProfile<double> &p_profile)
138128
{
139129
auto profile = p_profile;
140-
for (auto player : p_profile.GetGame()->GetPlayers()) {
141-
for (auto strategy : player->GetStrategies()) {
142-
profile[strategy] = std::max(profile[strategy], 0.0);
143-
}
130+
for (const auto &strategy : p_profile.GetGame()->GetStrategies()) {
131+
profile[strategy] = std::max(profile[strategy], 0.0);
144132
}
145133
return profile.Normalize();
146134
}

0 commit comments

Comments
 (0)