Skip to content

Commit 1dabf1e

Browse files
committed
Remove GameRep::Strategies based on dodgy iterator/range.
1 parent 388f0c2 commit 1dabf1e

File tree

3 files changed

+26
-149
lines changed

3 files changed

+26
-149
lines changed

src/games/game.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -820,19 +820,10 @@ class GameRep : public std::enable_shared_from_this<GameRep> {
820820

821821
/// @name Dimensions of the game
822822
//@{
823-
using Strategies =
824-
NestedElementCollection<&GameRep::m_players, &GamePlayerRep::m_strategies, GameStrategy>;
825-
826823
/// The number of strategies for each player
827824
virtual Array<int> NumStrategies() const = 0;
828825
/// Gets the i'th strategy in the game, numbered globally
829826
virtual GameStrategy GetStrategy(int p_index) const = 0;
830-
/// Gets the collection of all strategies in the game
831-
Strategies GetStrategies() const
832-
{
833-
BuildComputedValues();
834-
return Strategies(this);
835-
}
836827
/// Creates a new strategy for the player
837828
virtual GameStrategy NewStrategy(const GamePlayer &p_player, const std::string &p_label)
838829
{

src/games/gameobject.h

Lines changed: 0 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -214,124 +214,6 @@ template <class P, class T> class ElementCollection {
214214
iterator cend() const { return {m_owner, m_container, (m_owner) ? m_container->size() : 0}; }
215215
};
216216

217-
template <auto OuterMember, auto InnerMember, typename ValueType> class NestedElementCollection {
218-
template <typename MemberPtr> struct outer_element_of;
219-
220-
template <typename OuterClass, typename Elem>
221-
struct outer_element_of<std::vector<std::shared_ptr<Elem>> OuterClass::*> {
222-
using outer_class = OuterClass;
223-
using outer_elem = Elem;
224-
using container = std::vector<std::shared_ptr<Elem>>;
225-
};
226-
227-
template <typename MemberPtr> struct inner_element_of;
228-
229-
template <typename OuterElem, typename InnerElem>
230-
struct inner_element_of<std::vector<std::shared_ptr<InnerElem>> OuterElem::*> {
231-
using outer_elem = OuterElem;
232-
using inner_elem = InnerElem;
233-
using container = std::vector<std::shared_ptr<InnerElem>>;
234-
};
235-
236-
using OM = outer_element_of<decltype(OuterMember)>;
237-
using IM = inner_element_of<decltype(InnerMember)>;
238-
239-
using OuterClass = typename OM::outer_class;
240-
using OuterElem = typename OM::outer_elem;
241-
using InnerElem = typename IM::inner_elem;
242-
243-
public:
244-
class iterator {
245-
using outer_iter = typename OM::container::const_iterator;
246-
using inner_iter = typename IM::container::const_iterator;
247-
248-
outer_iter m_outer, m_outerEnd;
249-
inner_iter m_inner, m_innerEnd;
250-
mutable ValueType m_cache;
251-
252-
void advance()
253-
{
254-
while (m_outer != m_outerEnd && m_inner == m_innerEnd) {
255-
++m_outer;
256-
if (m_outer != m_outerEnd) {
257-
const auto &outerPtr = *m_outer;
258-
const auto &innerVec = outerPtr.get()->*InnerMember;
259-
m_inner = innerVec.begin();
260-
m_innerEnd = innerVec.end();
261-
}
262-
}
263-
}
264-
265-
public:
266-
using iterator_category = std::input_iterator_tag;
267-
using value_type = ValueType;
268-
using difference_type = std::ptrdiff_t;
269-
using reference = ValueType;
270-
using pointer = const ValueType *;
271-
272-
iterator() = default;
273-
274-
iterator(const OuterClass *p_obj, bool p_isEnd)
275-
{
276-
const auto &outerVec = p_obj->*OuterMember;
277-
278-
m_outer = outerVec.begin();
279-
m_outerEnd = outerVec.end();
280-
281-
if (p_isEnd || m_outer == m_outerEnd) {
282-
m_outer = m_outerEnd;
283-
return;
284-
}
285-
286-
const auto &outerPtr = *m_outer;
287-
const auto &innerVec = outerPtr.get()->*InnerMember;
288-
289-
m_inner = innerVec.begin();
290-
m_innerEnd = innerVec.end();
291-
292-
advance();
293-
}
294-
295-
reference operator*() const { return ValueType(*m_inner); }
296-
297-
pointer operator->() const
298-
{
299-
m_cache = ValueType(*m_inner);
300-
return &m_cache;
301-
}
302-
303-
iterator &operator++()
304-
{
305-
++m_inner;
306-
advance();
307-
return *this;
308-
}
309-
310-
iterator operator++(int)
311-
{
312-
iterator tmp = *this;
313-
++(*this);
314-
return tmp;
315-
}
316-
317-
bool operator==(const iterator &p_other) const
318-
{
319-
return m_outer == p_other.m_outer && (m_outer == m_outerEnd || m_inner == p_other.m_inner);
320-
}
321-
322-
bool operator!=(const iterator &p_other) const { return !(*this == p_other); }
323-
};
324-
325-
private:
326-
const OuterClass *m_obj;
327-
328-
public:
329-
explicit NestedElementCollection(const OuterClass *p_obj) : m_obj(p_obj) {}
330-
331-
iterator begin() const { return {m_obj, false}; }
332-
iterator end() const { return {m_obj, true}; }
333-
};
334-
335217
} // end namespace Gambit
336218

337219
#endif // GAMBIT_GAMES_GAMEOBJECT_H

src/solvers/liap/nfgliap.cc

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,43 +63,45 @@ class StrategicLyapunovFunction : public FunctionOnSimplices {
6363
inline double sum_player_probs(const MixedStrategyProfile<double> &p_profile,
6464
const GamePlayer &p_player)
6565
{
66-
return sum_function(p_player->GetStrategies(),
67-
[&p_profile](const auto &s) -> double { return p_profile[s]; });
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]; });
6870
}
6971

7072
double StrategicLyapunovFunction::Value(const Vector<double> &v) const
7173
{
7274
m_profile = v;
7375
double value = 0;
74-
// Liapunov function proper
75-
for (const auto &player : m_profile.GetGame()->GetPlayers()) {
76-
const auto payoff = m_profile.GetPayoff(player);
77-
for (const auto strategy : player->GetStrategies()) {
78-
value += sqr(std::max(m_scale * (m_profile.GetPayoff(strategy) - payoff), 0.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));
7982
}
8083
}
8184
// Penalty function for non-negativity constraint for each strategy
82-
value += m_penalty *
83-
sum_function(m_profile.GetGame()->GetStrategies(), [this](const auto &s) -> double {
84-
return sqr(std::min(m_profile[s], 0.0));
85-
});
86-
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+
}
8790
// Penalty function for sum-to-one constraint for each player
88-
value +=
89-
m_penalty * sum_function(m_profile.GetGame()->GetPlayers(), [this](const auto &p) -> double {
90-
return sqr(sum_player_probs(m_profile, p) - 1.0);
91-
});
91+
for (auto player : m_profile.GetGame()->GetPlayers()) {
92+
value += m_penalty * sqr(sum_player_probs(m_profile, player) - 1.0);
93+
}
9294
return value;
9395
}
9496

9597
double StrategicLyapunovFunction::LiapDerivValue(const MixedStrategyProfile<double> &p_profile,
9698
const GameStrategy &p_wrt_strategy) const
9799
{
98100
double deriv = 0.0;
99-
for (const auto &player : m_game->GetPlayers()) {
100-
const auto payoff = p_profile.GetPayoff(player);
101-
for (const auto &strategy : player->GetStrategies()) {
102-
const double loss = sqr(m_scale) * (p_profile.GetPayoff(strategy) - payoff);
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));
103105
if (loss <= 0.0) {
104106
continue;
105107
}
@@ -135,8 +137,10 @@ namespace {
135137
MixedStrategyProfile<double> EnforceNonnegativity(const MixedStrategyProfile<double> &p_profile)
136138
{
137139
auto profile = p_profile;
138-
for (const auto &strategy : p_profile.GetGame()->GetStrategies()) {
139-
profile[strategy] = std::max(profile[strategy], 0.0);
140+
for (auto player : p_profile.GetGame()->GetPlayers()) {
141+
for (auto strategy : player->GetStrategies()) {
142+
profile[strategy] = std::max(profile[strategy], 0.0);
143+
}
140144
}
141145
return profile.Normalize();
142146
}

0 commit comments

Comments
 (0)