Skip to content

Commit 157e26c

Browse files
committed
Fix bug in estimation
1 parent c7692c4 commit 157e26c

1 file changed

Lines changed: 42 additions & 18 deletions

File tree

src/solvers/logit/nfglogit.cc

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ Vector<double> ProfileToPoint(const LogitQREMixedStrategyProfile &p_profile)
5151

5252
double LogLike(const Vector<double> &p_frequencies, const Vector<double> &p_point)
5353
{
54-
return std::inner_product(p_frequencies.begin(), p_frequencies.end(), p_point.begin(), 0.0,
55-
std::plus<>(),
56-
[](double freq, double prob) { return freq * std::log(prob); });
54+
return std::inner_product(
55+
p_frequencies.begin(), p_frequencies.end(), p_point.begin(), 0.0, std::plus<>(),
56+
[](const double freq, const double prob) { return freq * std::log(prob); });
5757
}
5858

5959
double DiffLogLike(const Vector<double> &p_frequencies, const Vector<double> &p_tangent)
@@ -77,7 +77,9 @@ class Equation {
7777

7878
virtual double Value(const MixedStrategyProfile<double> &p_profile,
7979
const Vector<double> &p_strategyValues, double p_lambda) const = 0;
80-
virtual void Gradient(const MixedStrategyProfile<double> &p_profile, double p_lambda,
80+
virtual void Gradient(const MixedStrategyProfile<double> &p_profile,
81+
const Vector<double> &p_strategyValues,
82+
const Matrix<double> &p_strategyDerivs, double p_lambda,
8183
Vector<double> &p_gradient) const = 0;
8284
};
8385

@@ -94,6 +96,7 @@ class EquationSystem {
9496
const Game &m_game;
9597
mutable MixedStrategyProfile<double> m_profile;
9698
mutable Vector<double> m_strategyValues;
99+
mutable Matrix<double> m_strategyDerivs;
97100
};
98101

99102
class SumToOneEquation final : public Equation {
@@ -120,8 +123,9 @@ class SumToOneEquation final : public Equation {
120123
~SumToOneEquation() override = default;
121124
double Value(const MixedStrategyProfile<double> &p_profile,
122125
const Vector<double> &p_strategyValues, double p_lambda) const override;
123-
void Gradient(const MixedStrategyProfile<double> &p_profile, double p_lambda,
124-
Vector<double> &p_gradient) const override;
126+
void Gradient(const MixedStrategyProfile<double> &p_profile,
127+
const Vector<double> &p_strategyValues, const Matrix<double> &p_strategyDerivs,
128+
double p_lambda, Vector<double> &p_gradient) const override;
125129
};
126130

127131
double SumToOneEquation::Value(const MixedStrategyProfile<double> &p_profile,
@@ -134,7 +138,9 @@ double SumToOneEquation::Value(const MixedStrategyProfile<double> &p_profile,
134138
return value;
135139
}
136140

137-
void SumToOneEquation::Gradient(const MixedStrategyProfile<double> &p_profile, double p_lambda,
141+
void SumToOneEquation::Gradient(const MixedStrategyProfile<double> &p_profile,
142+
const Vector<double> &p_strategyValues,
143+
const Matrix<double> &p_strategyDerivs, double p_lambda,
138144
Vector<double> &p_gradient) const
139145
{
140146
p_gradient = 0.0;
@@ -169,8 +175,9 @@ class RatioEquation final : public Equation {
169175
~RatioEquation() override = default;
170176
double Value(const MixedStrategyProfile<double> &p_profile,
171177
const Vector<double> &p_strategyValues, double p_lambda) const override;
172-
void Gradient(const MixedStrategyProfile<double> &p_profile, double p_lambda,
173-
Vector<double> &p_gradient) const override;
178+
void Gradient(const MixedStrategyProfile<double> &p_profile,
179+
const Vector<double> &p_strategyValues, const Matrix<double> &p_strategyDerivs,
180+
double p_lambda, Vector<double> &p_gradient) const override;
174181
};
175182

176183
double RatioEquation::Value(const MixedStrategyProfile<double> &p_profile,
@@ -180,7 +187,9 @@ double RatioEquation::Value(const MixedStrategyProfile<double> &p_profile,
180187
p_lambda * (p_strategyValues[m_strategyIndex] - p_strategyValues[m_refStrategyIndex]));
181188
}
182189

183-
void RatioEquation::Gradient(const MixedStrategyProfile<double> &p_profile, double p_lambda,
190+
void RatioEquation::Gradient(const MixedStrategyProfile<double> &p_profile,
191+
const Vector<double> &p_strategyValues,
192+
const Matrix<double> &p_strategyDerivs, double p_lambda,
184193
Vector<double> &p_gradient) const
185194
{
186195
int col = 1;
@@ -197,20 +206,21 @@ void RatioEquation::Gradient(const MixedStrategyProfile<double> &p_profile, doub
197206
}
198207
else {
199208
p_gradient[col] =
200-
-p_lambda * p_profile[strategy] *
201-
(p_profile.GetPayoffDeriv(m_player->GetNumber(), m_strategy, strategy) -
202-
p_profile.GetPayoffDeriv(m_player->GetNumber(), m_refStrategy, strategy));
209+
-p_lambda * p_profile[col] *
210+
(p_strategyDerivs(m_strategyIndex, col) - p_strategyDerivs(m_refStrategyIndex, col));
203211
}
204212
col++;
205213
}
206214
}
207-
p_gradient[col] = (p_profile.GetPayoff(m_refStrategy) - p_profile.GetPayoff(m_strategy));
215+
p_gradient[col] = p_strategyValues[m_refStrategyIndex] - p_strategyValues[m_strategyIndex];
208216
}
209217

210218
EquationSystem::EquationSystem(const Game &p_game)
211219
: m_game(p_game), m_profile(p_game->NewMixedStrategyProfile(0.0)),
212-
m_strategyValues(m_profile.MixedProfileLength())
220+
m_strategyValues(m_profile.MixedProfileLength()),
221+
m_strategyDerivs(m_profile.MixedProfileLength(), m_profile.MixedProfileLength())
213222
{
223+
m_equations.reserve(m_profile.MixedProfileLength());
214224
for (const auto &player : m_game->GetPlayers()) {
215225
m_equations.push_back(std::make_shared<SumToOneEquation>(player));
216226
auto strategies = player->GetStrategies();
@@ -237,8 +247,22 @@ void EquationSystem::GetJacobian(const Vector<double> &p_point, Matrix<double> &
237247
PointToProfile(m_profile, p_point);
238248
const double lambda = p_point.back();
239249
Vector<double> column(p_point.size());
250+
m_strategyDerivs = 0.0;
251+
int row = 1;
252+
for (const auto &strategy1 : m_game->GetStrategies()) {
253+
m_strategyValues[row] = m_profile.GetPayoff(strategy1);
254+
int col = 1;
255+
for (const auto &strategy2 : m_game->GetStrategies()) {
256+
if (strategy1->GetPlayer() != strategy2->GetPlayer()) {
257+
m_strategyDerivs(row, col) =
258+
m_profile.GetPayoffDeriv(strategy1->GetPlayer()->GetNumber(), strategy1, strategy2);
259+
}
260+
col++;
261+
}
262+
row++;
263+
}
240264
for (size_t i = 1; i <= m_equations.size(); i++) {
241-
m_equations[i - 1]->Gradient(m_profile, lambda, column);
265+
m_equations[i - 1]->Gradient(m_profile, m_strategyValues, m_strategyDerivs, lambda, column);
242266
p_matrix.SetColumn(i, column);
243267
}
244268
}
@@ -384,10 +408,10 @@ LogitStrategyEstimate(const MixedStrategyProfile<double> &p_frequencies, double
384408
tracer.SetMaxDecel(p_maxAccel);
385409
tracer.SetStepsize(p_firstStep);
386410

387-
const Game game;
411+
const Game game = start.GetGame();
388412
Vector<double> x(ProfileToPoint(start)), restart(x);
389413
const Vector<double> freq_vector(p_frequencies.GetProbVector());
390-
EstimatorCallbackFunction callback(start.GetGame(), p_frequencies.GetProbVector(), p_observer);
414+
EstimatorCallbackFunction callback(game, p_frequencies.GetProbVector(), p_observer);
391415
EquationSystem system(game);
392416
while (true) {
393417
tracer.TracePath(

0 commit comments

Comments
 (0)