elo-ratings 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +22 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +23 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/elo-ratings.gemspec +148 -0
- data/ext/bayeselo/.gitignore +4 -0
- data/ext/bayeselo/CBradleyTerry.cpp +670 -0
- data/ext/bayeselo/CBradleyTerry.h +137 -0
- data/ext/bayeselo/CCDistribution.cpp +135 -0
- data/ext/bayeselo/CCDistribution.h +44 -0
- data/ext/bayeselo/CCDistributionCUI.cpp +104 -0
- data/ext/bayeselo/CCDistributionCUI.h +38 -0
- data/ext/bayeselo/CCondensedResults.cpp +253 -0
- data/ext/bayeselo/CCondensedResults.h +64 -0
- data/ext/bayeselo/CDiscretization.h +40 -0
- data/ext/bayeselo/CDistribution.cpp +123 -0
- data/ext/bayeselo/CDistribution.h +58 -0
- data/ext/bayeselo/CDistributionCollection.cpp +34 -0
- data/ext/bayeselo/CDistributionCollection.h +29 -0
- data/ext/bayeselo/CEloRatingCUI.cpp +1046 -0
- data/ext/bayeselo/CEloRatingCUI.h +67 -0
- data/ext/bayeselo/CIndirectCompare.h +28 -0
- data/ext/bayeselo/CJointBayesian.cpp +111 -0
- data/ext/bayeselo/CJointBayesian.h +38 -0
- data/ext/bayeselo/CLUDecomposition.cpp +154 -0
- data/ext/bayeselo/CLUDecomposition.h +36 -0
- data/ext/bayeselo/CMatrix.cpp +48 -0
- data/ext/bayeselo/CMatrix.h +35 -0
- data/ext/bayeselo/CMatrixIO.cpp +27 -0
- data/ext/bayeselo/CMatrixIO.h +17 -0
- data/ext/bayeselo/CPredictionCUI.cpp +393 -0
- data/ext/bayeselo/CPredictionCUI.h +50 -0
- data/ext/bayeselo/CResultSet.cpp +245 -0
- data/ext/bayeselo/CResultSet.h +50 -0
- data/ext/bayeselo/CResultSetCUI.cpp +355 -0
- data/ext/bayeselo/CResultSetCUI.h +44 -0
- data/ext/bayeselo/CTimeIO.cpp +58 -0
- data/ext/bayeselo/CTimeIO.h +19 -0
- data/ext/bayeselo/CVector.cpp +110 -0
- data/ext/bayeselo/CVector.h +42 -0
- data/ext/bayeselo/EloDataFromFile.cpp +120 -0
- data/ext/bayeselo/EloDataFromFile.h +21 -0
- data/ext/bayeselo/README +8 -0
- data/ext/bayeselo/ReadLineToString.cpp +32 -0
- data/ext/bayeselo/ReadLineToString.h +18 -0
- data/ext/bayeselo/chtime.cpp +56 -0
- data/ext/bayeselo/chtime.h +61 -0
- data/ext/bayeselo/chtimer.h +27 -0
- data/ext/bayeselo/clktimer.cpp +178 -0
- data/ext/bayeselo/clktimer.h +29 -0
- data/ext/bayeselo/consolui.cpp +538 -0
- data/ext/bayeselo/consolui.h +154 -0
- data/ext/bayeselo/const.cpp +79 -0
- data/ext/bayeselo/const.h +42 -0
- data/ext/bayeselo/date.cpp +96 -0
- data/ext/bayeselo/date.h +44 -0
- data/ext/bayeselo/debug.h +58 -0
- data/ext/bayeselo/elomain.cpp +26 -0
- data/ext/bayeselo/extconf.rb +6 -0
- data/ext/bayeselo/list.h +367 -0
- data/ext/bayeselo/listi.h +125 -0
- data/ext/bayeselo/move.cpp +249 -0
- data/ext/bayeselo/move.h +139 -0
- data/ext/bayeselo/pgn.h +62 -0
- data/ext/bayeselo/pgnlex.cpp +432 -0
- data/ext/bayeselo/pgnlex.h +105 -0
- data/ext/bayeselo/pgnstr.cpp +126 -0
- data/ext/bayeselo/piece.h +44 -0
- data/ext/bayeselo/player.h +31 -0
- data/ext/bayeselo/position.h +89 -0
- data/ext/bayeselo/random.cpp +114 -0
- data/ext/bayeselo/random.h +63 -0
- data/ext/bayeselo/rb_bayeselo.cpp +76 -0
- data/ext/bayeselo/readstr.cpp +51 -0
- data/ext/bayeselo/readstr.h +19 -0
- data/ext/bayeselo/square.h +61 -0
- data/ext/bayeselo/str.cpp +81 -0
- data/ext/bayeselo/str.h +71 -0
- data/ext/bayeselo/version.cpp +30 -0
- data/ext/bayeselo/version.h +28 -0
- data/ext/bayeselo/version_number.h +1 -0
- data/lib/bayeselo.rb +6 -0
- data/lib/bayeselo/bayeselo.rb +11 -0
- data/lib/bayeselo/c_bayeselo.rb +7 -0
- data/test/bayeselo/test_bayeselo.rb +33 -0
- data/test/bayeselo/test_c_bayeselo.rb +84 -0
- data/test/helper.rb +18 -0
- metadata +226 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// R�mi Coulom
|
|
4
|
+
//
|
|
5
|
+
// December, 2004
|
|
6
|
+
//
|
|
7
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
8
|
+
#ifndef CDistribution_Declared
|
|
9
|
+
#define CDistribution_Declared
|
|
10
|
+
|
|
11
|
+
#include <vector>
|
|
12
|
+
|
|
13
|
+
class CDistribution // dist
|
|
14
|
+
{
|
|
15
|
+
protected: ////////////////////////////////////////////////////////////////
|
|
16
|
+
std::vector<double> vDistribution;
|
|
17
|
+
|
|
18
|
+
int GetBoundIndex(double Confidence,
|
|
19
|
+
int Begin,
|
|
20
|
+
int End,
|
|
21
|
+
int Direction) const;
|
|
22
|
+
|
|
23
|
+
public: ///////////////////////////////////////////////////////////////////
|
|
24
|
+
CDistribution() : vDistribution(1) {vDistribution[0] = 1.0;}
|
|
25
|
+
CDistribution(int Size) : vDistribution(Size) {}
|
|
26
|
+
|
|
27
|
+
//
|
|
28
|
+
// Basic functions
|
|
29
|
+
//
|
|
30
|
+
int GetSize() const {return vDistribution.size();}
|
|
31
|
+
double GetProbability(int i) const {return vDistribution[i];}
|
|
32
|
+
void SetProbability(int i, double p) {vDistribution[i] = p;}
|
|
33
|
+
void Add(int i, double p) {vDistribution[i] += p;}
|
|
34
|
+
|
|
35
|
+
void Reset();
|
|
36
|
+
void SetUniform();
|
|
37
|
+
void Normalize();
|
|
38
|
+
void LogNormalize();
|
|
39
|
+
|
|
40
|
+
//
|
|
41
|
+
// Discrete bounds
|
|
42
|
+
//
|
|
43
|
+
int GetLowerIndex(double Confidence) const;
|
|
44
|
+
int GetUpperIndex(double Confidence) const;
|
|
45
|
+
|
|
46
|
+
//
|
|
47
|
+
// Functions to deal with result distributions
|
|
48
|
+
//
|
|
49
|
+
friend CDistribution BinomialDistribution(double p);
|
|
50
|
+
friend CDistribution SumDistribution(const CDistribution &dist1,
|
|
51
|
+
const CDistribution &dist2);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
CDistribution BinomialDistribution(double p);
|
|
55
|
+
CDistribution SumDistribution(const CDistribution &dist1,
|
|
56
|
+
const CDistribution &dist2);
|
|
57
|
+
|
|
58
|
+
#endif
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// R�mi Coulom
|
|
4
|
+
//
|
|
5
|
+
// December, 2004
|
|
6
|
+
//
|
|
7
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
8
|
+
#include "CDistributionCollection.h"
|
|
9
|
+
#include "CCDistribution.h"
|
|
10
|
+
|
|
11
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
12
|
+
// Constructor
|
|
13
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
14
|
+
CDistributionCollection::CDistributionCollection(int PlayersInit,
|
|
15
|
+
int Size,
|
|
16
|
+
double Min,
|
|
17
|
+
double Max):
|
|
18
|
+
CDiscretization(Size, Min, Max),
|
|
19
|
+
Players(PlayersInit)
|
|
20
|
+
{
|
|
21
|
+
ppDistribution = new CCDistribution*[Players];
|
|
22
|
+
for (int i = Players; --i >= 0;)
|
|
23
|
+
ppDistribution[i] = new CCDistribution(Size, Min, Max);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
27
|
+
// Destructor
|
|
28
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
29
|
+
CDistributionCollection::~CDistributionCollection()
|
|
30
|
+
{
|
|
31
|
+
for (int i = Players; --i >= 0;)
|
|
32
|
+
delete ppDistribution[i];
|
|
33
|
+
delete[] ppDistribution;
|
|
34
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// R�mi Coulom
|
|
4
|
+
//
|
|
5
|
+
// December, 2004
|
|
6
|
+
//
|
|
7
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
8
|
+
#ifndef CDistributionCollection_Declared
|
|
9
|
+
#define CDistributionCollection_Declared
|
|
10
|
+
|
|
11
|
+
#include "CDiscretization.h"
|
|
12
|
+
|
|
13
|
+
class CCDistribution;
|
|
14
|
+
|
|
15
|
+
class CDistributionCollection: public CDiscretization // dc
|
|
16
|
+
{
|
|
17
|
+
private: //////////////////////////////////////////////////////////////////
|
|
18
|
+
CCDistribution **ppDistribution;
|
|
19
|
+
int Players;
|
|
20
|
+
|
|
21
|
+
public: ///////////////////////////////////////////////////////////////////
|
|
22
|
+
CDistributionCollection(int PlayersInit, int Size, double Min, double Max);
|
|
23
|
+
|
|
24
|
+
CCDistribution &GetDistribution(int i) {return *ppDistribution[i];}
|
|
25
|
+
|
|
26
|
+
~CDistributionCollection();
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
#endif
|
|
@@ -0,0 +1,1046 @@
|
|
|
1
|
+
////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// Remi Coulom
|
|
4
|
+
//
|
|
5
|
+
// December, 2004
|
|
6
|
+
//
|
|
7
|
+
////////////////////////////////////////////////////////////////////////////
|
|
8
|
+
#include "CEloRatingCUI.h"
|
|
9
|
+
#include "CResultSet.h"
|
|
10
|
+
#include "CCDistribution.h"
|
|
11
|
+
#include "CCDistributionCUI.h"
|
|
12
|
+
#include "CDistributionCollection.h"
|
|
13
|
+
#include "CJointBayesian.h"
|
|
14
|
+
#include "clktimer.h"
|
|
15
|
+
#include "chtime.h"
|
|
16
|
+
#include "CTimeIO.h"
|
|
17
|
+
#include "CMatrix.h"
|
|
18
|
+
#include "CPredictionCUI.h"
|
|
19
|
+
#include "CIndirectCompare.h"
|
|
20
|
+
#include "ReadLineToString.h"
|
|
21
|
+
|
|
22
|
+
#include <iostream>
|
|
23
|
+
#include <iomanip>
|
|
24
|
+
#include <algorithm>
|
|
25
|
+
#include <sstream>
|
|
26
|
+
#include <fstream>
|
|
27
|
+
#include <set>
|
|
28
|
+
|
|
29
|
+
////////////////////////////////////////////////////////////////////////////
|
|
30
|
+
// Command strings
|
|
31
|
+
////////////////////////////////////////////////////////////////////////////
|
|
32
|
+
const char * const CEloRatingCUI::tszCommands[] =
|
|
33
|
+
{
|
|
34
|
+
"?",
|
|
35
|
+
"ratings",
|
|
36
|
+
"details",
|
|
37
|
+
"offset",
|
|
38
|
+
"scale",
|
|
39
|
+
"minelo",
|
|
40
|
+
"maxelo",
|
|
41
|
+
"advantage",
|
|
42
|
+
"drawelo",
|
|
43
|
+
"prior",
|
|
44
|
+
"resolution",
|
|
45
|
+
"confidence",
|
|
46
|
+
"p",
|
|
47
|
+
"likelihood",
|
|
48
|
+
"prediction",
|
|
49
|
+
"plotres",
|
|
50
|
+
"plotdraw",
|
|
51
|
+
"mm",
|
|
52
|
+
"elostat",
|
|
53
|
+
"elo",
|
|
54
|
+
"jointdist",
|
|
55
|
+
"exactdist",
|
|
56
|
+
"variance",
|
|
57
|
+
"covariance",
|
|
58
|
+
"los",
|
|
59
|
+
"advdist",
|
|
60
|
+
"drawdist",
|
|
61
|
+
"pairstats",
|
|
62
|
+
0
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
////////////////////////////////////////////////////////////////////////////
|
|
66
|
+
// Convert to closes int
|
|
67
|
+
////////////////////////////////////////////////////////////////////////////
|
|
68
|
+
static int RoundDouble(double x)
|
|
69
|
+
{
|
|
70
|
+
if (x > 0)
|
|
71
|
+
return int(x+0.5);
|
|
72
|
+
else
|
|
73
|
+
return int(x-0.5);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
////////////////////////////////////////////////////////////////////////////
|
|
77
|
+
// Constructor
|
|
78
|
+
////////////////////////////////////////////////////////////////////////////
|
|
79
|
+
CEloRatingCUI::CEloRatingCUI(const CResultSet &rsInit,
|
|
80
|
+
const std::vector<std::string> &vecNameInit,
|
|
81
|
+
CConsoleUI *pcui,
|
|
82
|
+
int openmode) :
|
|
83
|
+
CConsoleUI(pcui, openmode),
|
|
84
|
+
rs(rsInit),
|
|
85
|
+
crs(rsInit),
|
|
86
|
+
vecName(vecNameInit),
|
|
87
|
+
vPermutation(crs.GetPlayers()),
|
|
88
|
+
veloLower(crs.GetPlayers()),
|
|
89
|
+
veloUpper(crs.GetPlayers()),
|
|
90
|
+
Confidence(0.95),
|
|
91
|
+
eloMin(-1500),
|
|
92
|
+
eloMax(1500),
|
|
93
|
+
Resolution(1001),
|
|
94
|
+
eloOffset(0),
|
|
95
|
+
EloScale(1.0),
|
|
96
|
+
Prior(2.0),
|
|
97
|
+
bt(crs),
|
|
98
|
+
fLOSComputed(0)
|
|
99
|
+
{
|
|
100
|
+
for (int i = crs.GetPlayers(); --i >= 0;)
|
|
101
|
+
{
|
|
102
|
+
bt.SetElo(i, 0);
|
|
103
|
+
veloLower[i] = 0;
|
|
104
|
+
veloUpper[i] = 0;
|
|
105
|
+
vPermutation[i] = i;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
MaxNameLength = 0;
|
|
109
|
+
for (int i = crs.GetPlayers(); --i >= 0;)
|
|
110
|
+
if (vecName[i].length() > MaxNameLength)
|
|
111
|
+
MaxNameLength = vecName[i].length();
|
|
112
|
+
|
|
113
|
+
crs.AddPrior(Prior);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
////////////////////////////////////////////////////////////////////////////
|
|
117
|
+
// Local prompt
|
|
118
|
+
////////////////////////////////////////////////////////////////////////////
|
|
119
|
+
void CEloRatingCUI::PrintLocalPrompt(std::ostream &out)
|
|
120
|
+
{
|
|
121
|
+
out << "EloRating";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
////////////////////////////////////////////////////////////////////////////
|
|
125
|
+
// Inverse of normal distribution function
|
|
126
|
+
////////////////////////////////////////////////////////////////////////////
|
|
127
|
+
static double NormInv(double Confidence)
|
|
128
|
+
{
|
|
129
|
+
CCDistribution cdist(1000, -10, 10);
|
|
130
|
+
cdist.SetNormal(0, 1);
|
|
131
|
+
return cdist.GetUpperValue(Confidence);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
////////////////////////////////////////////////////////////////////////////
|
|
135
|
+
// Compute variance
|
|
136
|
+
////////////////////////////////////////////////////////////////////////////
|
|
137
|
+
void CEloRatingCUI::ComputeVariance()
|
|
138
|
+
{
|
|
139
|
+
std::vector<double> vVariance(crs.GetPlayers());
|
|
140
|
+
bt.GetVariance(&vVariance[0]);
|
|
141
|
+
|
|
142
|
+
double x = NormInv(Confidence);
|
|
143
|
+
|
|
144
|
+
for (int i = crs.GetPlayers(); --i >= 0;)
|
|
145
|
+
if (crs.GetOpponents(i) > 0)
|
|
146
|
+
veloLower[i] = veloUpper[i] = x * std::sqrt(vVariance[i]);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
////////////////////////////////////////////////////////////////////////////
|
|
150
|
+
// Process commands
|
|
151
|
+
////////////////////////////////////////////////////////////////////////////
|
|
152
|
+
int CEloRatingCUI::ProcessCommand(const char *pszCommand,
|
|
153
|
+
const char *pszParameters,
|
|
154
|
+
std::istream &in,
|
|
155
|
+
std::ostream &out)
|
|
156
|
+
{
|
|
157
|
+
enum
|
|
158
|
+
{
|
|
159
|
+
IDC_Help,
|
|
160
|
+
IDC_Ratings,
|
|
161
|
+
IDC_Details,
|
|
162
|
+
IDC_Offset,
|
|
163
|
+
IDC_Scale,
|
|
164
|
+
IDC_MinElo,
|
|
165
|
+
IDC_MaxElo,
|
|
166
|
+
IDC_Advantage,
|
|
167
|
+
IDC_DrawElo,
|
|
168
|
+
IDC_Prior,
|
|
169
|
+
IDC_Resolution,
|
|
170
|
+
IDC_Confidence,
|
|
171
|
+
IDC_P,
|
|
172
|
+
IDC_Likelihood,
|
|
173
|
+
IDC_Prediction,
|
|
174
|
+
IDC_PlotRes,
|
|
175
|
+
IDC_PlotDraw,
|
|
176
|
+
IDC_MM,
|
|
177
|
+
IDC_ELOstat,
|
|
178
|
+
IDC_Elo,
|
|
179
|
+
IDC_JointDist,
|
|
180
|
+
IDC_ExactDist,
|
|
181
|
+
IDC_Variance,
|
|
182
|
+
IDC_Covariance,
|
|
183
|
+
IDC_LOS,
|
|
184
|
+
IDC_AdvDist,
|
|
185
|
+
IDC_DrawDist,
|
|
186
|
+
IDC_PairStats
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
switch (ArrayLookup(pszCommand, tszCommands))
|
|
190
|
+
{
|
|
191
|
+
case IDC_Help: ///////////////////////////////////////////////////////////
|
|
192
|
+
CConsoleUI::ProcessCommand(pszCommand, pszParameters, in, out);
|
|
193
|
+
out << "EloRating commands\n";
|
|
194
|
+
out << "~~~~~~~~~~~~~~~~~~\n";
|
|
195
|
+
out << "advantage [x] ... get[set] advantage of playing first\n";
|
|
196
|
+
out << "drawelo [x] ..... get[set] draw Elo\n";
|
|
197
|
+
out << "prior [x] ....... get[set] prior (= number of virtual draws)\n";
|
|
198
|
+
out << "elo [p] [elo] ... get[set] Elo of player number p\n";
|
|
199
|
+
out << "mm [a] [d] ...... compute maximum-likelihood Elos:\n";
|
|
200
|
+
out << " a: flag to compute advantage (default = 0)\n";
|
|
201
|
+
out << " d: flag to compute elodraw (default = 0)\n";
|
|
202
|
+
out << "elostat ......... compute ratings with ELOstat algorithm\n";
|
|
203
|
+
out << '\n';
|
|
204
|
+
out << "ratings [min [f [F]]] list players and their ratings:\n";
|
|
205
|
+
out << " min: minimum number of games\n";
|
|
206
|
+
out << " f: file name that contains the list of names\n";
|
|
207
|
+
out << " F: Full-rank flag (0 or 1, default 0)\n";
|
|
208
|
+
out << "details ......... detailed list\n";
|
|
209
|
+
out << "offset [elo [pl]] get[set] Elo offset, or player (pl) elo\n";
|
|
210
|
+
out << "scale ........... get[set] Elo scale\n";
|
|
211
|
+
out << '\n';
|
|
212
|
+
out << "p <w> <b> <r> ... probability of result <r> with Elos <w> and <b>\n";
|
|
213
|
+
out << "likelihood ...... log-likelihood of the current Elo list\n";
|
|
214
|
+
out << "prediction ...... open prediction interface\n";
|
|
215
|
+
out << '\n';
|
|
216
|
+
out << "plotres [i] [M] . plot result likelihoods as a function of rating diff:\n";
|
|
217
|
+
out << " i: number of intervals (default = 21)\n";
|
|
218
|
+
out << " M: maximum rating difference (default = 500)\n";
|
|
219
|
+
out << "plotdraw [n] [d] plot draw frequency as a function of average rating\n";
|
|
220
|
+
out << " n: number of games per group (default = 100)\n";
|
|
221
|
+
out << " d: maximum rating difference (default = 100)\n";
|
|
222
|
+
out << '\n';
|
|
223
|
+
out << "confidence ...... get[set] level of confidence intervals\n";
|
|
224
|
+
out << "variance ........ compute intervals with the diagonal of the Hessian\n";
|
|
225
|
+
out << "covariance ...... compute intervals with the full Hessian\n";
|
|
226
|
+
out << "los [f] [p] [w] . likelihood of superiority (f=first,p=players,w=width)\n";
|
|
227
|
+
out << '\n';
|
|
228
|
+
out << "minelo [x] ...... get[set] minimum Elo\n";
|
|
229
|
+
out << "maxelo [x] ...... get[set] maximum Elo\n";
|
|
230
|
+
out << "resolution [n] .. get[set] resolution\n";
|
|
231
|
+
out << "jointdist [p] ... compute intervals from joint distribution\n";
|
|
232
|
+
out << "exactdist [p] ... compute intervals assuming exact opponent Elos\n";
|
|
233
|
+
out << "advdist ......... likelihood distribution of advantage\n";
|
|
234
|
+
out << "drawdist ........ likelihood distribution of drawelo\n";
|
|
235
|
+
out << '\n';
|
|
236
|
+
out << "pairstats i j ... get stats between players i and j\n";
|
|
237
|
+
out << '\n';
|
|
238
|
+
break;
|
|
239
|
+
|
|
240
|
+
case IDC_MinElo: /////////////////////////////////////////////////////////
|
|
241
|
+
GetSet<double>(eloMin, pszParameters, out);
|
|
242
|
+
break;
|
|
243
|
+
|
|
244
|
+
case IDC_MaxElo: /////////////////////////////////////////////////////////
|
|
245
|
+
GetSet<double>(eloMax, pszParameters, out);
|
|
246
|
+
break;
|
|
247
|
+
|
|
248
|
+
case IDC_Advantage: //////////////////////////////////////////////////////
|
|
249
|
+
{
|
|
250
|
+
double eloAdvantage = bt.GetAdvantage();
|
|
251
|
+
GetSet<double>(eloAdvantage, pszParameters, out);
|
|
252
|
+
bt.SetAdvantage(eloAdvantage);
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
|
|
256
|
+
case IDC_DrawElo: ////////////////////////////////////////////////////////
|
|
257
|
+
{
|
|
258
|
+
double eloDraw = bt.GetDrawElo();
|
|
259
|
+
GetSet<double>(eloDraw, pszParameters, out);
|
|
260
|
+
bt.SetDrawElo(eloDraw);
|
|
261
|
+
}
|
|
262
|
+
break;
|
|
263
|
+
|
|
264
|
+
case IDC_Prior: //////////////////////////////////////////////////////////
|
|
265
|
+
{
|
|
266
|
+
float NewPrior = Prior;
|
|
267
|
+
std::istringstream(pszParameters) >> NewPrior;
|
|
268
|
+
crs.AddPrior(NewPrior - Prior);
|
|
269
|
+
Prior = NewPrior;
|
|
270
|
+
out << Prior << '\n';
|
|
271
|
+
out << "With this prior, you will get the following Elo differences:\n";
|
|
272
|
+
CResultSet rs;
|
|
273
|
+
for (int i = 1; i < 6; i++)
|
|
274
|
+
{
|
|
275
|
+
rs.Append(0, 1, 2);
|
|
276
|
+
CCondensedResults crs(rs);
|
|
277
|
+
crs.AddPrior(Prior);
|
|
278
|
+
|
|
279
|
+
CBradleyTerry btLocal(crs);
|
|
280
|
+
btLocal.SetAdvantage(bt.GetAdvantage());
|
|
281
|
+
btLocal.SetDrawElo(bt.GetDrawElo());
|
|
282
|
+
|
|
283
|
+
btLocal.MinorizationMaximization(0, 0);
|
|
284
|
+
double Delta = btLocal.GetElo(0) - btLocal.GetElo(1);
|
|
285
|
+
out << i << "-0 : +" << Delta << '\n';
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
|
|
290
|
+
case IDC_Resolution: /////////////////////////////////////////////////////
|
|
291
|
+
GetSet<int>(Resolution, pszParameters, out);
|
|
292
|
+
break;
|
|
293
|
+
|
|
294
|
+
case IDC_Confidence: /////////////////////////////////////////////////////
|
|
295
|
+
GetSet<double>(Confidence, pszParameters, out);
|
|
296
|
+
break;
|
|
297
|
+
|
|
298
|
+
case IDC_P: //////////////////////////////////////////////////////////////
|
|
299
|
+
{
|
|
300
|
+
double eloWhite = 0;
|
|
301
|
+
double eloBlack = 0;
|
|
302
|
+
int Result = 0;
|
|
303
|
+
|
|
304
|
+
std::istringstream is(pszParameters);
|
|
305
|
+
is >> eloWhite >> eloBlack >> Result;
|
|
306
|
+
|
|
307
|
+
out << "White Elo: " << eloWhite << '\n';
|
|
308
|
+
out << "Black Elo: " << eloBlack << '\n';
|
|
309
|
+
out << "Result: " << Result << '\n';
|
|
310
|
+
|
|
311
|
+
out << bt.ResultProbability(eloWhite - eloBlack, Result) << '\n';
|
|
312
|
+
}
|
|
313
|
+
break;
|
|
314
|
+
|
|
315
|
+
case IDC_Likelihood: /////////////////////////////////////////////////////
|
|
316
|
+
out << bt.LogLikelihood() << '\n';
|
|
317
|
+
break;
|
|
318
|
+
|
|
319
|
+
case IDC_Prediction: /////////////////////////////////////////////////////
|
|
320
|
+
{
|
|
321
|
+
CPredictionCUI predcui(*this);
|
|
322
|
+
predcui.MainLoop(in, out);
|
|
323
|
+
}
|
|
324
|
+
break;
|
|
325
|
+
|
|
326
|
+
case IDC_PlotRes: ////////////////////////////////////////////////////////
|
|
327
|
+
{
|
|
328
|
+
//
|
|
329
|
+
// Parse parameters
|
|
330
|
+
//
|
|
331
|
+
int Intervals = 21;
|
|
332
|
+
double eloMaxDiff = 500;
|
|
333
|
+
{
|
|
334
|
+
std::istringstream is(pszParameters);
|
|
335
|
+
is >> Intervals;
|
|
336
|
+
is >> eloMaxDiff;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
#if 0 // Compute ratings with a half the games, and mesure predictions on the other half
|
|
340
|
+
unsigned Seed = 1;
|
|
341
|
+
CResultSet rsBT;
|
|
342
|
+
CResultSet rsRes;
|
|
343
|
+
rs.Extract(rsBT, rsRes, Seed);
|
|
344
|
+
|
|
345
|
+
CCondensedResults crsBT(rsBT);
|
|
346
|
+
CBradleyTerry btRes(crsBT);
|
|
347
|
+
for (int i = crsBT.GetPlayers(); --i >= 0;)
|
|
348
|
+
btRes.SetElo(i, 0);
|
|
349
|
+
crsBT.AddPrior(Prior);
|
|
350
|
+
// btRes.MinorizationMaximization(0, 0);
|
|
351
|
+
btRes.ELOstat();
|
|
352
|
+
#if 0 // compute log-likelihood for 100 priors
|
|
353
|
+
{
|
|
354
|
+
std::ofstream ofsCV("cv.dat");
|
|
355
|
+
for (int i = 0; i < 200; i++)
|
|
356
|
+
{
|
|
357
|
+
double Prior = 0.0000001 + i * 0.1;
|
|
358
|
+
CCondensedResults crsBT(rsBT);
|
|
359
|
+
crsBT.AddPrior(Prior);
|
|
360
|
+
CBradleyTerry btRes(crsBT);
|
|
361
|
+
for (int i = crsBT.GetPlayers(); --i >= 0;)
|
|
362
|
+
btRes.SetElo(i, 0);
|
|
363
|
+
btRes.MinorizationMaximization(0, 0);
|
|
364
|
+
double LL = btRes.LogLikelihood(rsRes);
|
|
365
|
+
ofsCV << Prior << ' ' << LL << '\n';
|
|
366
|
+
ofsCV.flush();
|
|
367
|
+
std::cerr << "Prior = " << Prior;
|
|
368
|
+
std::cerr << "; Loglikelihood = " << LL;
|
|
369
|
+
std::cerr << "\n\n";
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
#endif
|
|
373
|
+
#else
|
|
374
|
+
const CResultSet& rsRes = rs;
|
|
375
|
+
const CBradleyTerry& btRes = bt;
|
|
376
|
+
#endif
|
|
377
|
+
|
|
378
|
+
//
|
|
379
|
+
// Vector to store data for each interval
|
|
380
|
+
//
|
|
381
|
+
std::vector<int> vGames(Intervals);
|
|
382
|
+
std::vector<double> vEloDiff(Intervals);
|
|
383
|
+
std::vector<int> vWins(Intervals);
|
|
384
|
+
std::vector<int> vDraws(Intervals);
|
|
385
|
+
std::vector<int> vLosses(Intervals);
|
|
386
|
+
std::vector<double> vExpectedWins(Intervals);
|
|
387
|
+
std::vector<double> vExpectedDraws(Intervals);
|
|
388
|
+
std::vector<double> vExpectedLosses(Intervals);
|
|
389
|
+
std::vector<double> vExpectedElostat(Intervals);
|
|
390
|
+
|
|
391
|
+
//
|
|
392
|
+
// Initialization of data
|
|
393
|
+
//
|
|
394
|
+
for (int i = Intervals; --i >= 0;)
|
|
395
|
+
{
|
|
396
|
+
vGames[i] = 0;
|
|
397
|
+
vEloDiff[i] = 0.0;
|
|
398
|
+
vWins[i] = 0;
|
|
399
|
+
vDraws[i] = 0;
|
|
400
|
+
vLosses[i] = 0;
|
|
401
|
+
vExpectedWins[i] = 0.0;
|
|
402
|
+
vExpectedDraws[i] = 0.0;
|
|
403
|
+
vExpectedLosses[i] = 0.0;
|
|
404
|
+
vExpectedElostat[i] = 0.0;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
//
|
|
408
|
+
// Loop over games
|
|
409
|
+
//
|
|
410
|
+
for (int i = rsRes.GetGames(); --i >= 0;)
|
|
411
|
+
{
|
|
412
|
+
double eloDiff = btRes.GetElo(rsRes.GetWhite(i)) -
|
|
413
|
+
btRes.GetElo(rsRes.GetBlack(i));
|
|
414
|
+
double x = eloDiff + eloMaxDiff;
|
|
415
|
+
if (x > 0)
|
|
416
|
+
{
|
|
417
|
+
int Index = int(Intervals * x / (2 * eloMaxDiff));
|
|
418
|
+
if (Index < Intervals)
|
|
419
|
+
{
|
|
420
|
+
vGames[Index]++;
|
|
421
|
+
vEloDiff[Index] += eloDiff;
|
|
422
|
+
|
|
423
|
+
int res = rsRes.GetResult(i);
|
|
424
|
+
switch(res)
|
|
425
|
+
{
|
|
426
|
+
case 0: vLosses[Index]++; break;
|
|
427
|
+
case 1: vDraws[Index]++; break;
|
|
428
|
+
case 2: vWins[Index]++; break;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
double PLoss = btRes.ResultProbability(eloDiff, 0);
|
|
432
|
+
double PDraw = btRes.ResultProbability(eloDiff, 1);
|
|
433
|
+
double PWin = btRes.ResultProbability(eloDiff, 2);
|
|
434
|
+
double PElostat = btRes.ElostatProbability(eloDiff);
|
|
435
|
+
|
|
436
|
+
vExpectedLosses[Index] += PLoss;
|
|
437
|
+
vExpectedDraws[Index] += PDraw;
|
|
438
|
+
vExpectedWins[Index] += PWin;
|
|
439
|
+
vExpectedElostat[Index] += PElostat;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
//
|
|
445
|
+
// Integrals
|
|
446
|
+
//
|
|
447
|
+
double TotalLW = 0.0;
|
|
448
|
+
double TotalDD = 0.0;
|
|
449
|
+
double TotalD = 0.0;
|
|
450
|
+
|
|
451
|
+
for (int i = 0; i < Intervals; i++)
|
|
452
|
+
{
|
|
453
|
+
double g = vGames[i];
|
|
454
|
+
|
|
455
|
+
TotalLW += vLosses[i] * vWins[i] / (g * g);
|
|
456
|
+
TotalDD += vDraws[i] * vDraws[i] / (g * g);
|
|
457
|
+
TotalD += vDraws[i] / g;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
//
|
|
461
|
+
// Print histogram data
|
|
462
|
+
//
|
|
463
|
+
for (int i = 0; i < Intervals; i++)
|
|
464
|
+
if (vGames[i])
|
|
465
|
+
{
|
|
466
|
+
double g = vGames[i];
|
|
467
|
+
double L = vLosses[i] / g;
|
|
468
|
+
double D = vDraws[i] / g;
|
|
469
|
+
double W = vWins[i] / g;
|
|
470
|
+
|
|
471
|
+
out << vEloDiff[i] / g << ' ';
|
|
472
|
+
out << vGames[i] << ' ';
|
|
473
|
+
out << L << ' ';
|
|
474
|
+
out << D << ' ';
|
|
475
|
+
out << W << ' ';
|
|
476
|
+
out << W + 0.5 * D << ' ';
|
|
477
|
+
out << vExpectedLosses[i] / g << ' ';
|
|
478
|
+
out << vExpectedDraws[i] / g << ' ';
|
|
479
|
+
out << vExpectedWins[i] / g << ' ';
|
|
480
|
+
out << (vExpectedWins[i] + 0.5 * vExpectedDraws[i]) / g << ' ';
|
|
481
|
+
out << vExpectedElostat[i] / g << ' ';
|
|
482
|
+
|
|
483
|
+
double x = NormInv(Confidence);
|
|
484
|
+
double LDev = x * std::sqrt(L * (1 - L) / g);
|
|
485
|
+
double DDev = x * std::sqrt(D * (1 - D) / g);
|
|
486
|
+
double WDev = x * std::sqrt(D * (1 - D) / g);
|
|
487
|
+
|
|
488
|
+
out << L - LDev << ' ';
|
|
489
|
+
out << D - DDev << ' ';
|
|
490
|
+
out << W - WDev << ' ';
|
|
491
|
+
out << L + LDev << ' ';
|
|
492
|
+
out << D + DDev << ' ';
|
|
493
|
+
out << W + WDev << ' ';
|
|
494
|
+
|
|
495
|
+
out << L * W / TotalLW << ' ';
|
|
496
|
+
out << D * D / TotalDD << ' ';
|
|
497
|
+
out << D / TotalD << ' ';
|
|
498
|
+
|
|
499
|
+
out << '\n';
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
break;
|
|
503
|
+
|
|
504
|
+
case IDC_PlotDraw: ///////////////////////////////////////////////////////
|
|
505
|
+
{
|
|
506
|
+
int GroupSize = 100;
|
|
507
|
+
double MaxDiff = 100;
|
|
508
|
+
std::istringstream(pszParameters) >> GroupSize >> MaxDiff;
|
|
509
|
+
|
|
510
|
+
//
|
|
511
|
+
// Filter out games with a big rating difference
|
|
512
|
+
//
|
|
513
|
+
CResultSet rsFiltered;
|
|
514
|
+
for (int i = rs.GetGames(); --i >= 0;)
|
|
515
|
+
{
|
|
516
|
+
double Diff = bt.GetElo(rs.GetWhite(i)) - bt.GetElo(rs.GetBlack(i));
|
|
517
|
+
if (std::fabs(Diff) < MaxDiff)
|
|
518
|
+
rsFiltered.Append(rs.GetWhite(i), rs.GetBlack(i), rs.GetResult(i));
|
|
519
|
+
}
|
|
520
|
+
std::cerr << rsFiltered.GetGames() << " games left after filtering\n";
|
|
521
|
+
|
|
522
|
+
//
|
|
523
|
+
// Sort games according to average rating
|
|
524
|
+
//
|
|
525
|
+
std::vector<int> vOrder(rsFiltered.GetGames());
|
|
526
|
+
std::vector<double> vAverage(rsFiltered.GetGames());
|
|
527
|
+
{
|
|
528
|
+
for (int i = rsFiltered.GetGames(); --i >= 0;)
|
|
529
|
+
{
|
|
530
|
+
vOrder[i] = i;
|
|
531
|
+
vAverage[i] = bt.GetElo(rs.GetWhite(i)) + bt.GetElo(rs.GetBlack(i));
|
|
532
|
+
}
|
|
533
|
+
std::sort(vOrder.begin(), vOrder.end(), CIndirectCompare<double>(&vAverage[0]));
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
//
|
|
537
|
+
// Number of draws for each group of GroupSize players, starting
|
|
538
|
+
// from the top players
|
|
539
|
+
//
|
|
540
|
+
int Index = 0;
|
|
541
|
+
for (int Group = rsFiltered.GetGames() / GroupSize; --Group >= 0;)
|
|
542
|
+
{
|
|
543
|
+
int Draws = 0;
|
|
544
|
+
double TotalRating = 0;
|
|
545
|
+
for (int i = GroupSize; --i >= 0;)
|
|
546
|
+
{
|
|
547
|
+
int g = vOrder[Index++];
|
|
548
|
+
if (rsFiltered.GetResult(g) == 1)
|
|
549
|
+
Draws++;
|
|
550
|
+
TotalRating += vAverage[g];
|
|
551
|
+
}
|
|
552
|
+
CCDistribution cdist(Resolution, 0.0, 1.0);
|
|
553
|
+
cdist.SetBinomialPosterior(GroupSize, Draws);
|
|
554
|
+
out << TotalRating / (2 * GroupSize) << ' ';
|
|
555
|
+
out << double(Draws) / double(GroupSize) << ' ';
|
|
556
|
+
out << cdist.GetLowerValue(Confidence) << ' ';
|
|
557
|
+
out << cdist.GetUpperValue(Confidence) << '\n';
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
break;
|
|
561
|
+
|
|
562
|
+
case IDC_Ratings: ////////////////////////////////////////////////////////
|
|
563
|
+
{
|
|
564
|
+
int MinGames = 1;
|
|
565
|
+
std::string sFileName;
|
|
566
|
+
int fFullRank = 0;
|
|
567
|
+
|
|
568
|
+
std::istringstream(pszParameters) >> MinGames >> sFileName >> fFullRank;
|
|
569
|
+
if (MinGames < 1)
|
|
570
|
+
MinGames = 1;
|
|
571
|
+
|
|
572
|
+
//
|
|
573
|
+
// Read a list of player names
|
|
574
|
+
//
|
|
575
|
+
std::ifstream ifsNames(sFileName.c_str());
|
|
576
|
+
std::set<std::string> setNames;
|
|
577
|
+
while (1)
|
|
578
|
+
{
|
|
579
|
+
std::string s;
|
|
580
|
+
ReadLineToString(s, ifsNames);
|
|
581
|
+
if (ifsNames)
|
|
582
|
+
setNames.insert(s);
|
|
583
|
+
else
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
std::sort(vPermutation.begin(),
|
|
588
|
+
vPermutation.end(),
|
|
589
|
+
CIndirectCompare<double>(bt.GetElo()));
|
|
590
|
+
|
|
591
|
+
int Width = MaxNameLength;
|
|
592
|
+
if (Width < 4)
|
|
593
|
+
Width = 4;
|
|
594
|
+
|
|
595
|
+
CCondensedResults crsNoPrior(rs);
|
|
596
|
+
|
|
597
|
+
std::ios::fmtflags f = out.flags();
|
|
598
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
599
|
+
out << std::setw(3) << "Rank" << ' ';
|
|
600
|
+
out.setf(std::ios::left, std::ios::adjustfield);
|
|
601
|
+
out << std::setw(Width) << "Name" << ' ';
|
|
602
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
603
|
+
out << std::setw(5) << "Elo" << ' ';
|
|
604
|
+
out << std::setw(4) << " +" << ' ';
|
|
605
|
+
out << std::setw(4) << " -" << ' ';
|
|
606
|
+
out << std::setw(5) << "games" << ' ';
|
|
607
|
+
out << std::setw(5) << "score" << ' ';
|
|
608
|
+
out << std::setw(5) << "oppo." << ' ';
|
|
609
|
+
out << std::setw(5) << "draws" << ' ';
|
|
610
|
+
out << '\n';
|
|
611
|
+
|
|
612
|
+
const double *pElo = bt.GetElo();
|
|
613
|
+
for (int i = 0, Counter = 0; i < crs.GetPlayers(); i++)
|
|
614
|
+
{
|
|
615
|
+
int j = vPermutation[i];
|
|
616
|
+
float Games = crsNoPrior.CountGames(j);
|
|
617
|
+
if (Games >= MinGames &&
|
|
618
|
+
(setNames.size() == 0 || setNames.find(vecName[j]) != setNames.end()))
|
|
619
|
+
{
|
|
620
|
+
Counter++;
|
|
621
|
+
double Score = double(crsNoPrior.Score(j)) / 2;
|
|
622
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
623
|
+
if (fFullRank)
|
|
624
|
+
out << std::setw(4) << i + 1 << ' ';
|
|
625
|
+
else
|
|
626
|
+
out << std::setw(4) << Counter << ' ';
|
|
627
|
+
out.setf(std::ios::left, std::ios::adjustfield);
|
|
628
|
+
out << std::setw(Width) << vecName[j] << ' ';
|
|
629
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
630
|
+
out << std::setw(5) << RoundDouble(EloScale * bt.GetElo(j) + eloOffset) << ' ';
|
|
631
|
+
out << std::setw(4) << RoundDouble(EloScale * veloUpper[j]) << ' ';
|
|
632
|
+
out << std::setw(4) << RoundDouble(EloScale * veloLower[j]) << ' ';
|
|
633
|
+
out << std::setw(5) << Games << ' ';
|
|
634
|
+
out << std::setw(4) << RoundDouble(100 * Score / Games) << "% ";
|
|
635
|
+
out << std::setw(5) <<
|
|
636
|
+
RoundDouble(EloScale * crs.AverageOpponent(j, pElo) + eloOffset) << ' ';
|
|
637
|
+
out << std::setw(4) << RoundDouble(100 * crsNoPrior.CountDraws(j) /
|
|
638
|
+
double(Games)) << "% ";
|
|
639
|
+
out << '\n';
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
out.flags(f);
|
|
644
|
+
}
|
|
645
|
+
break;
|
|
646
|
+
|
|
647
|
+
case IDC_Details: ////////////////////////////////////////////////////////
|
|
648
|
+
{
|
|
649
|
+
std::sort(vPermutation.begin(),
|
|
650
|
+
vPermutation.end(),
|
|
651
|
+
CIndirectCompare<double>(bt.GetElo()));
|
|
652
|
+
|
|
653
|
+
std::ios::fmtflags f = out.flags();
|
|
654
|
+
int precision = out.precision();
|
|
655
|
+
|
|
656
|
+
out.setf(std::ios::fixed, std::ios::floatfield);
|
|
657
|
+
out.precision(1);
|
|
658
|
+
|
|
659
|
+
int Width = MaxNameLength;
|
|
660
|
+
if (Width < 4)
|
|
661
|
+
Width = 4;
|
|
662
|
+
|
|
663
|
+
CCondensedResults crsNoPrior(rs);
|
|
664
|
+
|
|
665
|
+
for (int i = 0, Counter = 0; i < crs.GetPlayers(); i++)
|
|
666
|
+
{
|
|
667
|
+
int j = vPermutation[i];
|
|
668
|
+
float Games = crsNoPrior.CountGames(j);
|
|
669
|
+
Counter++;
|
|
670
|
+
double Score = double(crsNoPrior.Score(j)) / 2;
|
|
671
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
672
|
+
out << std::setw(4) << Counter << ' ';
|
|
673
|
+
out.setf(std::ios::left, std::ios::adjustfield);
|
|
674
|
+
out << std::setw(Width) << vecName[j] << ' ';
|
|
675
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
676
|
+
out << std::setw(5) << RoundDouble(EloScale * bt.GetElo(j) + eloOffset) << ' ';
|
|
677
|
+
out << std::setw(5) << Games << " (";
|
|
678
|
+
out << std::setw(5) << Score << " : ";
|
|
679
|
+
out << std::setw(5) << Games-Score << ")\n";
|
|
680
|
+
|
|
681
|
+
//
|
|
682
|
+
// Sort opponents
|
|
683
|
+
//
|
|
684
|
+
std::vector<int> vOpponentIndex(crsNoPrior.GetOpponents(j));
|
|
685
|
+
std::vector<double> vOpponentElo(crsNoPrior.GetOpponents(j));
|
|
686
|
+
for (int k = crsNoPrior.GetOpponents(j); --k >= 0;)
|
|
687
|
+
{
|
|
688
|
+
const CCondensedResult &cr = crsNoPrior.GetCondensedResult(j, k);
|
|
689
|
+
vOpponentIndex[k] = k;
|
|
690
|
+
vOpponentElo[k] = bt.GetElo(cr.Opponent);
|
|
691
|
+
}
|
|
692
|
+
std::sort(vOpponentIndex.begin(),
|
|
693
|
+
vOpponentIndex.end(),
|
|
694
|
+
CIndirectCompare<double>(&vOpponentElo[0]));
|
|
695
|
+
|
|
696
|
+
//
|
|
697
|
+
// Print opponent data
|
|
698
|
+
//
|
|
699
|
+
for (int k = 0; k < crsNoPrior.GetOpponents(j); k++)
|
|
700
|
+
{
|
|
701
|
+
int l = vOpponentIndex[k];
|
|
702
|
+
const CCondensedResult &cr = crsNoPrior.GetCondensedResult(j, l);
|
|
703
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
704
|
+
out << std::setw(4) << ' ' << ' ';
|
|
705
|
+
out.setf(std::ios::left, std::ios::adjustfield);
|
|
706
|
+
out << std::setw(Width) << ' ' << ' ';
|
|
707
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
708
|
+
out << std::setw(5) << ' ' << ' ';
|
|
709
|
+
out << std::setw(5) << cr.Games() << " (";
|
|
710
|
+
out << std::setw(5) << cr.Score() << " : ";
|
|
711
|
+
out << std::setw(5) << cr.Games()-cr.Score() << ") ";
|
|
712
|
+
out.setf(std::ios::left, std::ios::adjustfield);
|
|
713
|
+
out << std::setw(Width) << vecName[cr.Opponent] << ' ';
|
|
714
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
715
|
+
out << std::setw(5) << RoundDouble(EloScale * bt.GetElo(cr.Opponent) + eloOffset) << '\n';
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
out.flags(f);
|
|
719
|
+
out.precision(precision);
|
|
720
|
+
}
|
|
721
|
+
break;
|
|
722
|
+
|
|
723
|
+
case IDC_Offset: /////////////////////////////////////////////////////////
|
|
724
|
+
{
|
|
725
|
+
std::istringstream iss(pszParameters);
|
|
726
|
+
float elo = eloOffset;
|
|
727
|
+
iss >> elo;
|
|
728
|
+
|
|
729
|
+
std::string sName;
|
|
730
|
+
iss >> sName; // ??? there must be a better way
|
|
731
|
+
if (sName != "")
|
|
732
|
+
{
|
|
733
|
+
char c = 0;
|
|
734
|
+
while (iss.get(c))
|
|
735
|
+
sName += c;
|
|
736
|
+
|
|
737
|
+
int fFound = 0;
|
|
738
|
+
for (int i = 0; i < crs.GetPlayers(); i++)
|
|
739
|
+
if (sName == vecName[i])
|
|
740
|
+
{
|
|
741
|
+
fFound = 1;
|
|
742
|
+
eloOffset = elo - EloScale * bt.GetElo(i);
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
if (!fFound)
|
|
747
|
+
out << "Error: unknow player " << sName << '\n';
|
|
748
|
+
}
|
|
749
|
+
else
|
|
750
|
+
GetSet<double>(eloOffset, pszParameters, out);
|
|
751
|
+
}
|
|
752
|
+
break;
|
|
753
|
+
|
|
754
|
+
case IDC_Scale: //////////////////////////////////////////////////////////
|
|
755
|
+
GetSet<double>(EloScale, pszParameters, out);
|
|
756
|
+
break;
|
|
757
|
+
|
|
758
|
+
case IDC_MM: /////////////////////////////////////////////////////////////
|
|
759
|
+
{
|
|
760
|
+
int fThetaW = 0;
|
|
761
|
+
int fThetaD = 0;
|
|
762
|
+
std::istringstream(pszParameters) >> fThetaW >> fThetaD;
|
|
763
|
+
CClockTimer timer;
|
|
764
|
+
bt.MinorizationMaximization(fThetaW, fThetaD);
|
|
765
|
+
out << timer.GetInterval() << '\n';
|
|
766
|
+
ComputeVariance();
|
|
767
|
+
{
|
|
768
|
+
double x = std::pow(10.0, -bt.GetDrawElo() / 400);
|
|
769
|
+
EloScale = x * 4.0 / ((1 + x) * (1 + x));
|
|
770
|
+
}
|
|
771
|
+
fLOSComputed = 0;
|
|
772
|
+
}
|
|
773
|
+
break;
|
|
774
|
+
|
|
775
|
+
case IDC_ELOstat: ////////////////////////////////////////////////////////
|
|
776
|
+
{
|
|
777
|
+
crs.AddPrior(-Prior);
|
|
778
|
+
CClockTimer timer;
|
|
779
|
+
bt.ELOstat();
|
|
780
|
+
bt.ELOstatIntervals(&veloLower[0], &veloUpper[0]);
|
|
781
|
+
out << timer.GetInterval() << '\n';
|
|
782
|
+
crs.AddPrior(Prior);
|
|
783
|
+
EloScale = 1.0;
|
|
784
|
+
fLOSComputed = 0;
|
|
785
|
+
}
|
|
786
|
+
break;
|
|
787
|
+
|
|
788
|
+
case IDC_Elo: ////////////////////////////////////////////////////////////
|
|
789
|
+
{
|
|
790
|
+
std::istringstream is(pszParameters);
|
|
791
|
+
unsigned Player = 0;
|
|
792
|
+
is >> Player;
|
|
793
|
+
if (Player < unsigned(crs.GetPlayers()))
|
|
794
|
+
{
|
|
795
|
+
double elo = EloScale * bt.GetElo(Player) + eloOffset;
|
|
796
|
+
is >> elo;
|
|
797
|
+
bt.SetElo(Player, elo);
|
|
798
|
+
out << "Rating of player " << Player << " (" << vecName[Player];
|
|
799
|
+
out << ") is " << elo << ".\n";
|
|
800
|
+
}
|
|
801
|
+
else
|
|
802
|
+
out << "Player out of range (should be in 0-" <<
|
|
803
|
+
crs.GetPlayers() - 1 << ")\n";
|
|
804
|
+
}
|
|
805
|
+
break;
|
|
806
|
+
|
|
807
|
+
case IDC_JointDist: //////////////////////////////////////////////////////
|
|
808
|
+
{
|
|
809
|
+
int Player = -1;
|
|
810
|
+
std::istringstream(pszParameters) >> Player;
|
|
811
|
+
|
|
812
|
+
CClockTimer timer;
|
|
813
|
+
CDistributionCollection dc(crs.GetPlayers(),
|
|
814
|
+
Resolution,
|
|
815
|
+
eloMin,
|
|
816
|
+
eloMax);
|
|
817
|
+
CJointBayesian jb(rs, dc, bt);
|
|
818
|
+
jb.RunComputation();
|
|
819
|
+
out << timer.GetInterval() << '\n';
|
|
820
|
+
for (int i = crs.GetPlayers(); --i >= 0;)
|
|
821
|
+
{
|
|
822
|
+
veloLower[i] = bt.GetElo(i) - dc.GetDistribution(i).
|
|
823
|
+
GetLowerValue(Confidence);
|
|
824
|
+
veloUpper[i] = dc.GetDistribution(i).
|
|
825
|
+
GetUpperValue(Confidence) - bt.GetElo(i);
|
|
826
|
+
if (i == Player)
|
|
827
|
+
{
|
|
828
|
+
CCDistributionCUI cdcui(dc.GetDistribution(i), this);
|
|
829
|
+
cdcui.MainLoop(in, out);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
break;
|
|
834
|
+
|
|
835
|
+
case IDC_ExactDist: //////////////////////////////////////////////////////
|
|
836
|
+
{
|
|
837
|
+
int Player = -1;
|
|
838
|
+
std::istringstream(pszParameters) >> Player;
|
|
839
|
+
|
|
840
|
+
CClockTimer timer;
|
|
841
|
+
CCDistribution cdist(Resolution, eloMin, eloMax);
|
|
842
|
+
|
|
843
|
+
for (int i = crs.GetPlayers(); --i >= 0;)
|
|
844
|
+
{
|
|
845
|
+
if (i % 10 == 0)
|
|
846
|
+
{
|
|
847
|
+
out << i << " left \r";
|
|
848
|
+
out.flush();
|
|
849
|
+
}
|
|
850
|
+
bt.GetPlayerDist(i, cdist);
|
|
851
|
+
veloLower[i] = bt.GetElo(i) - cdist.GetLowerValue(Confidence);
|
|
852
|
+
veloUpper[i] = cdist.GetUpperValue(Confidence) - bt.GetElo(i);
|
|
853
|
+
if (i == Player)
|
|
854
|
+
{
|
|
855
|
+
CCDistributionCUI cdcui(cdist, this);
|
|
856
|
+
cdcui.MainLoop(in, out);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
out << timer.GetInterval() << " \n";
|
|
861
|
+
}
|
|
862
|
+
break;
|
|
863
|
+
|
|
864
|
+
case IDC_Variance: ///////////////////////////////////////////////////////
|
|
865
|
+
ComputeVariance();
|
|
866
|
+
break;
|
|
867
|
+
|
|
868
|
+
case IDC_Covariance: /////////////////////////////////////////////////////
|
|
869
|
+
{
|
|
870
|
+
bt.ComputeCovariance();
|
|
871
|
+
bt.ComputeLikelihoodOfSuperiority();
|
|
872
|
+
|
|
873
|
+
const CMatrix &mCovariance = bt.GetCovariance();
|
|
874
|
+
CCDistribution cdist(1000, -10, 10);
|
|
875
|
+
cdist.SetNormal(0, 1);
|
|
876
|
+
double x = cdist.GetUpperValue(Confidence);
|
|
877
|
+
for (int i = crs.GetPlayers(); --i >= 0;)
|
|
878
|
+
veloLower[i] = veloUpper[i] = x * std::sqrt(mCovariance.GetElement(i, i));
|
|
879
|
+
|
|
880
|
+
fLOSComputed = 1;
|
|
881
|
+
}
|
|
882
|
+
break;
|
|
883
|
+
|
|
884
|
+
case IDC_LOS: ////////////////////////////////////////////////////////////
|
|
885
|
+
{
|
|
886
|
+
if (!fLOSComputed)
|
|
887
|
+
{
|
|
888
|
+
bt.ComputeCovariance();
|
|
889
|
+
bt.ComputeLikelihoodOfSuperiority();
|
|
890
|
+
}
|
|
891
|
+
const CMatrix &mLOS = bt.GetLikelihoodOfSuperiority();
|
|
892
|
+
|
|
893
|
+
//
|
|
894
|
+
// Parse command parameters
|
|
895
|
+
//
|
|
896
|
+
int First = 0;
|
|
897
|
+
int Players = mLOS.GetRows();
|
|
898
|
+
int Width = 3;
|
|
899
|
+
std::istringstream(pszParameters) >> First >> Players >> Width;
|
|
900
|
+
if (Width < 2)
|
|
901
|
+
Width = 2;
|
|
902
|
+
if (First < 0)
|
|
903
|
+
First = 0;
|
|
904
|
+
if (First + Players > mLOS.GetRows())
|
|
905
|
+
Players = mLOS.GetRows() - First;
|
|
906
|
+
if (Players <= 0)
|
|
907
|
+
{
|
|
908
|
+
First = 0;
|
|
909
|
+
Players = mLOS.GetRows();
|
|
910
|
+
}
|
|
911
|
+
const double Mult = std::pow(10.0, (Width > 8 ? 8 : Width) - 1);
|
|
912
|
+
|
|
913
|
+
//
|
|
914
|
+
// Sort players according to rating
|
|
915
|
+
//
|
|
916
|
+
std::sort(vPermutation.begin(),
|
|
917
|
+
vPermutation.end(),
|
|
918
|
+
CIndirectCompare<double>(bt.GetElo()));
|
|
919
|
+
|
|
920
|
+
//
|
|
921
|
+
// Column headers with Width-1 letters of each player
|
|
922
|
+
//
|
|
923
|
+
out << std::setw(MaxNameLength) << ' ' << ' ';
|
|
924
|
+
for (int p = First; p < First + Players; p++)
|
|
925
|
+
{
|
|
926
|
+
int i = vPermutation[p];
|
|
927
|
+
std::string s = vecName[i].substr(0, Width - 1);
|
|
928
|
+
out << std::setw(Width) << s;
|
|
929
|
+
}
|
|
930
|
+
out << '\n';
|
|
931
|
+
out.flush();
|
|
932
|
+
|
|
933
|
+
//
|
|
934
|
+
// Two nested loops to print the matrix
|
|
935
|
+
//
|
|
936
|
+
for (int p = First; p < First + Players; p++)
|
|
937
|
+
{
|
|
938
|
+
int i = vPermutation[p];
|
|
939
|
+
out.setf(std::ios::left, std::ios::adjustfield);
|
|
940
|
+
out << std::setw(MaxNameLength) << vecName[i] << ' ';
|
|
941
|
+
out.setf(std::ios::right, std::ios::adjustfield);
|
|
942
|
+
|
|
943
|
+
for (int q = First; q < First + Players; q++)
|
|
944
|
+
{
|
|
945
|
+
if (p != q)
|
|
946
|
+
{
|
|
947
|
+
int j = vPermutation[q];
|
|
948
|
+
out << std::setw(Width) << int(mLOS.GetElement(i, j) * Mult);
|
|
949
|
+
}
|
|
950
|
+
else
|
|
951
|
+
out << std::setw(Width) << ' ';
|
|
952
|
+
}
|
|
953
|
+
out << '\n';
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
break;
|
|
957
|
+
|
|
958
|
+
case IDC_AdvDist: ////////////////////////////////////////////////////////
|
|
959
|
+
{
|
|
960
|
+
CCDistribution cdist(Resolution, eloMin, eloMax);
|
|
961
|
+
bt.GetAdvantageDist(cdist);
|
|
962
|
+
out << cdist.GetLowerValue(Confidence);
|
|
963
|
+
out << " <= " << cdist.GetMostLikelyValue();
|
|
964
|
+
out << " <= " << cdist.GetUpperValue(Confidence) << '\n';
|
|
965
|
+
CCDistributionCUI cdcui(cdist, this);
|
|
966
|
+
cdcui.MainLoop(in, out);
|
|
967
|
+
}
|
|
968
|
+
break;
|
|
969
|
+
|
|
970
|
+
case IDC_DrawDist: ///////////////////////////////////////////////////////
|
|
971
|
+
{
|
|
972
|
+
CCDistribution cdist(Resolution, eloMin < 0 ? 0 : eloMin, eloMax);
|
|
973
|
+
bt.GetDrawEloDist(cdist);
|
|
974
|
+
out << cdist.GetLowerValue(Confidence);
|
|
975
|
+
out << " <= " << cdist.GetMostLikelyValue();
|
|
976
|
+
out << " <= " << cdist.GetUpperValue(Confidence) << '\n';
|
|
977
|
+
CCDistributionCUI cdcui(cdist, this);
|
|
978
|
+
cdcui.MainLoop(in, out);
|
|
979
|
+
}
|
|
980
|
+
break;
|
|
981
|
+
|
|
982
|
+
case IDC_PairStats: //////////////////////////////////////////////////////
|
|
983
|
+
{
|
|
984
|
+
//
|
|
985
|
+
// Read command parameters and print player names
|
|
986
|
+
//
|
|
987
|
+
int i = 0;
|
|
988
|
+
int j = 0;
|
|
989
|
+
std::istringstream(pszParameters) >> i >> j;
|
|
990
|
+
if (i < 0 || i >= crs.GetPlayers() ||
|
|
991
|
+
j < 0 || j >= crs.GetPlayers() ||
|
|
992
|
+
i == j)
|
|
993
|
+
out << "error: bad player numbers\n";
|
|
994
|
+
else
|
|
995
|
+
{
|
|
996
|
+
out << "-- pairstats between i = " << i << ", and j = " << j << '\n';
|
|
997
|
+
out << "Name[i] = " << vecName[i] << '\n';
|
|
998
|
+
out << "Name[j] = " << vecName[j] << '\n';
|
|
999
|
+
out << "elo[i] - elo[j] = ";
|
|
1000
|
+
out << EloScale * (bt.GetElo(i) - bt.GetElo(j)) << '\n';
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
//
|
|
1004
|
+
// Build the set of results between these two players
|
|
1005
|
+
//
|
|
1006
|
+
CResultSet rsLocal(rs, i, j);
|
|
1007
|
+
out << "Games = " << rsLocal.GetGames() << '\n';
|
|
1008
|
+
if (rsLocal.GetGames())
|
|
1009
|
+
{
|
|
1010
|
+
CCondensedResults crsLocal(rsLocal);
|
|
1011
|
+
{
|
|
1012
|
+
CCondensedResult &cr = crsLocal.GetCondensedResult(0, 0);
|
|
1013
|
+
out << "w_ij = " << cr.w_ij << '\n';
|
|
1014
|
+
out << "d_ij = " << cr.d_ij << '\n';
|
|
1015
|
+
out << "l_ij = " << cr.l_ij << '\n';
|
|
1016
|
+
out << "w_ji = " << cr.w_ji << '\n';
|
|
1017
|
+
out << "d_ji = " << cr.d_ji << '\n';
|
|
1018
|
+
out << "l_ji = " << cr.l_ji << '\n';
|
|
1019
|
+
cr = crs.FindOpponent(i, j);
|
|
1020
|
+
cr.Opponent = 1;
|
|
1021
|
+
}
|
|
1022
|
+
{
|
|
1023
|
+
CCondensedResult &cr = crsLocal.GetCondensedResult(1, 0);
|
|
1024
|
+
cr = crs.FindOpponent(j, i);
|
|
1025
|
+
cr.Opponent = 0;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
//
|
|
1029
|
+
// Compute and print elo ratings
|
|
1030
|
+
//
|
|
1031
|
+
CBradleyTerry btLocal(crsLocal);
|
|
1032
|
+
btLocal.SetAdvantage(bt.GetAdvantage());
|
|
1033
|
+
btLocal.SetDrawElo(bt.GetDrawElo());
|
|
1034
|
+
btLocal.MinorizationMaximization(0, 0);
|
|
1035
|
+
out << "elo[i] - elo[j] = ";
|
|
1036
|
+
out << EloScale * (btLocal.GetElo(0) - btLocal.GetElo(1)) << '\n';
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
break;
|
|
1040
|
+
|
|
1041
|
+
default: /////////////////////////////////////////////////////////////////
|
|
1042
|
+
return CConsoleUI::ProcessCommand(pszCommand, pszParameters, in, out);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
return PC_Continue;
|
|
1046
|
+
}
|