formatting updates

This commit is contained in:
swaits committed 2011-04-26 18:03:21 -07:00
1 parent 5b64f13b89
commit 723952b178
4 files changed
+329 -329

No files matched your search

+21 -21
View File
@@ -33,33 +33,33 @@
class Glicko2_impl class Glicko2_impl
{ {
public: public:
// constructors // constructors
Glicko2_impl(); Glicko2_impl();
Glicko2_impl(const Glicko2_impl& rhs); Glicko2_impl(const Glicko2_impl& rhs);
// copy assignment // copy assignment
Glicko2_impl& operator=(const Glicko2_impl& rhs); Glicko2_impl& operator=(const Glicko2_impl& rhs);
// destructor // destructor
virtual ~Glicko2_impl(); virtual ~Glicko2_impl();
// system constants // system constants
static const double dvolatility; static const double dvolatility;
// rating data // rating data
double rating; double rating;
double deviation; double deviation;
double volatility; double volatility;
// result data (copy of each opponent and results, 0.0, 0.5, or 1.0) // result data (copy of each opponent and results, 0.0, 0.5, or 1.0)
std::vector<Glicko2> opponents; std::vector<Glicko2> opponents;
std::vector<double> results; std::vector<double> results;
// utility functions // utility functions
double g(const double& deviation); double g(const double& deviation);
double E(const double& rating, const double& rating_opponent, const double& deviation_opponent); double E(const double& rating, const double& rating_opponent, const double& deviation_opponent);
}; };
@@ -116,7 +116,7 @@ Glicko2_impl::~Glicko2_impl()
double Glicko2_impl::g(const double& deviation) double Glicko2_impl::g(const double& deviation)
{ {
#define PI_SQUARED (9.86960440108935861883) #define PI_SQUARED (9.86960440108935861883)
return 1.0 / (sqrt(1.0 + 3.0 * deviation * deviation / PI_SQUARED)); return 1.0 / (sqrt(1.0 + 3.0 * deviation * deviation / PI_SQUARED));
} }
+148 -148
View File
@@ -47,195 +47,195 @@ class Glicko2_impl;
*/ */
class Glicko2 class Glicko2
{ {
public: public:
/**
* Enumeration of possible results.
*/
enum RESULT
{
/**
* A win result, internally 1.0.
*/
WIN,
/** /**
* A loss result, internally 0.0. * Enumeration of possible results.
*/ */
LOSS, enum RESULT
{
/**
* A win result, internally 1.0.
*/
WIN,
/**
* A loss result, internally 0.0.
*/
LOSS,
/**
* A draw result, internally 0.5.
*/
DRAW
};
/** /**
* A draw result, internally 0.5. * Default constructor. Initializes to a rating of 1500, a rating deviation
* of 350, and a volatility of 0.06.
*/ */
DRAW Glicko2();
};
/**
* Copy constructor.
*
* @param rhs Object to copy.
*/
Glicko2(const Glicko2& rhs);
/**
* Constructor with rating, rating deviation, and volatility specified.
*
* @param rating Initial rating.
* @param deviation Initial rating deviation.
* @param volatility Initial volatility.
*/
Glicko2(double rating, double deviation, double volatility);
/** /**
* Default constructor. Initializes to a rating of 1500, a rating deviation * Copy assignment operator.
* of 350, and a volatility of 0.06. *
*/ * @param rhs Object to copy.
Glicko2(); *
* @return Reference to self after copy assignment.
/** */
* Copy constructor. Glicko2& operator=(const Glicko2& rhs);
*
* @param rhs Object to copy.
*/
Glicko2(const Glicko2& rhs);
/**
* Constructor with rating, rating deviation, and volatility specified.
*
* @param rating Initial rating.
* @param deviation Initial rating deviation.
* @param volatility Initial volatility.
*/
Glicko2(double rating, double deviation, double volatility);
/** /**
* Copy assignment operator. * Destructor.
* */
* @param rhs Object to copy. virtual ~Glicko2();
*
* @return Reference to self after copy assignment.
*/
Glicko2& operator=(const Glicko2& rhs);
/** /**
* Destructor. * Less than comparison operator.
*/ *
virtual ~Glicko2(); * @param rhs Object to compare against.
*
* @return true if this object's rating is less than rhs's rating; false otherwise.
*/
bool operator< (const Glicko2& rhs);
/** /**
* Less than comparison operator. * Get the current rating. This rating is a Glicko rating, not a Glicko2 rating.
* * For details, please see http://www.glicko.com/
* @param rhs Object to compare against. *
* * @return
* @return true if this object's rating is less than rhs's rating; false otherwise. */
*/ double GetRating() const;
bool operator< (const Glicko2& rhs);
/**
* Get the current rating deviation. This is a Glicko rating deviation, not a
* Glicko-2 RD. For details, please see http://www.glicko.com/
*
* @return
*/
double GetDeviation() const;
/**
* Get the current rating volatility.
*
* @return
*/
double GetVolatility() const;
/** /**
* Get the current rating. This rating is a Glicko rating, not a Glicko2 rating. * Set Glicko rating. Internally this is converted to a Glicko2 rating.
* For details, please see http://www.glicko.com/ * For details, please see http://www.glicko.com/
* *
* @return * @param rating Rating.
*/ */
double GetRating() const; void SetRating(double rating);
/** /**
* Get the current rating deviation. This is a Glicko rating deviation, not a * Set Glicko rating deviation. Internally this is converted to a Glicko-2 RD.
* Glicko-2 RD. For details, please see http://www.glicko.com/ * For details, please see http://www.glicko.com/
* *
* @return * @param deviation Rating deviation.
*/ */
double GetDeviation() const; void SetDeviation(double deviation);
/** /**
* Get the current rating volatility. * Set rating volatility.
* *
* @return * @param volatility Rating volatility.
*/ */
double GetVolatility() const; void SetVolatility(double volatility);
/** /**
* Set Glicko rating. Internally this is converted to a Glicko2 rating. * Clear all results previously added via AddResult(), AddWin(), AddLoss(),
* For details, please see http://www.glicko.com/ * and/or AddDraw(). This method is called automatically whenever Update()
* * is called.
* @param rating Rating. */
*/ void ClearResults();
void SetRating(double rating);
/**
* Set Glicko rating deviation. Internally this is converted to a Glicko-2 RD.
* For details, please see http://www.glicko.com/
*
* @param deviation Rating deviation.
*/
void SetDeviation(double deviation);
/**
* Set rating volatility.
*
* @param volatility Rating volatility.
*/
void SetVolatility(double volatility);
/** /**
* Clear all results previously added via AddResult(), AddWin(), AddLoss(), * Add a result to this rating. Note that no calculation is performed until
* and/or AddDraw(). This method is called automatically whenever Update() * Update() is called.
* is called. *
*/ * @param opponent Other player in contest.
void ClearResults(); * @param result WIN, LOSS, or DRAW; from the point of view of this player.
*/
void AddResult(const Glicko2& opponent, RESULT result);
/** /**
* Add a result to this rating. Note that no calculation is performed until * Add a win result to this rating. Note that no calculation is performed until
* Update() is called. * Update() is called.
* *
* @param opponent Other player in contest. * @param opponent Other (losing) player in contest.
* @param result WIN, LOSS, or DRAW; from the point of view of this player. */
*/ void AddWin(const Glicko2& opponent);
void AddResult(const Glicko2& opponent, RESULT result);
/**
* Add a loss result to this rating. Note that no calculation is performed until
* Update() is called.
*
* @param opponent Other (winning) player in contest.
*/
void AddLoss(const Glicko2& opponent);
/**
* Add a draw result to this rating. Note that no calculation is performed until
* Update() is called.
*
* @param opponent Other (drawing) player in contest.
*/
void AddDraw(const Glicko2& opponent);
/** /**
* Add a win result to this rating. Note that no calculation is performed until * Update rating based on current results list, and clear results.
* Update() is called. */
* void Update();
* @param opponent Other (losing) player in contest.
*/
void AddWin(const Glicko2& opponent);
/**
* Add a loss result to this rating. Note that no calculation is performed until
* Update() is called.
*
* @param opponent Other (winning) player in contest.
*/
void AddLoss(const Glicko2& opponent);
/**
* Add a draw result to this rating. Note that no calculation is performed until
* Update() is called.
*
* @param opponent Other (drawing) player in contest.
*/
void AddDraw(const Glicko2& opponent);
/** private:
* Update rating based on current results list, and clear results.
*/
void Update();
/**
* Private Implementation.
private: */
Glicko2_impl* pimpl;
/**
* Private Implementation.
*/
Glicko2_impl* pimpl;
}; };
+143 -143
View File
@@ -38,179 +38,179 @@
# #
class Glicko2 class Glicko2
protected protected
# Glicko2 reprensentation (Glicko2 uses different scales from Glicko) # Glicko2 reprensentation (Glicko2 uses different scales from Glicko)
attr_accessor :g2rating, :g2deviation, :g2volatility attr_accessor :g2rating, :g2deviation, :g2volatility
# a nested Class to hold a single result # a nested Class to hold a single result
Result = Struct.new(:opponent, :result) Result = Struct.new(:opponent, :result)
public public
WIN = 1.0 WIN = 1.0
LOSS = 0.0 LOSS = 0.0
DRAW = 0.5 DRAW = 0.5
# Constructor with rating, rating deviation, and volatility optionally # Constructor with rating, rating deviation, and volatility optionally
# specified. If nothing specified, nitializes to a rating of 1500, a # specified. If nothing specified, nitializes to a rating of 1500, a
# rating deviation of 350, and a volatility of 0.06. # rating deviation of 350, and a volatility of 0.06.
def initialize(rating = 1500.0, deviation = 350.0, volatility = 0.06) def initialize(rating = 1500.0, deviation = 350.0, volatility = 0.06)
@dvolatility = 0.3 @dvolatility = 0.3
self.rating = rating self.rating = rating
self.deviation = deviation self.deviation = deviation
self.volatility = volatility self.volatility = volatility
clear_results clear_results
end end
include Comparable include Comparable
# Comparison operator # Comparison operator
def <=>(other) def <=>(other)
self.rating <=> other.rating self.rating <=> other.rating
end end
# Get the current rating. This rating is a Glicko rating, not a Glicko2 rating. # Get the current rating. This rating is a Glicko rating, not a Glicko2 rating.
# For details, please see http://www.glicko.com/ # For details, please see http://www.glicko.com/
def rating def rating
(@g2rating * 173.7178) + 1500.0 (@g2rating * 173.7178) + 1500.0
end end
# Set Glicko rating. Internally this is converted to a Glicko2 rating. # Set Glicko rating. Internally this is converted to a Glicko2 rating.
# For details, please see http://www.glicko.com/ # For details, please see http://www.glicko.com/
def rating=(r) def rating=(r)
@g2rating = (r - 1500.0) / 173.7178 @g2rating = (r - 1500.0) / 173.7178
end end
# Get the current rating deviation. This is a Glicko rating deviation, not a # Get the current rating deviation. This is a Glicko rating deviation, not a
# Glicko-2 RD. For details, please see http://www.glicko.com/ # Glicko-2 RD. For details, please see http://www.glicko.com/
def deviation def deviation
@g2deviation * 173.7178 @g2deviation * 173.7178
end end
# Set Glicko rating deviation. Internally this is converted to a Glicko-2 RD. # Set Glicko rating deviation. Internally this is converted to a Glicko-2 RD.
# For details, please see http://www.glicko.com/ # For details, please see http://www.glicko.com/
def deviation=(d) def deviation=(d)
@g2deviation = d / 173.7178 @g2deviation = d / 173.7178
end end
# Get the current rating volatility. # Get the current rating volatility.
def volatility def volatility
@g2volatility @g2volatility
end end
# Set rating volatility. # Set rating volatility.
def volatility=(v) def volatility=(v)
@g2volatility = v @g2volatility = v
end end
# Clear all results previously added via add_result(), add_win(), add_loss(), # Clear all results previously added via add_result(), add_win(), add_loss(),
# and/or add_draw(). This method is called automatically whenever update() # and/or add_draw(). This method is called automatically whenever update()
# is called. # is called.
def clear_results def clear_results
@opponents = [] @opponents = []
@results = [] @results = []
end end
# Add a result to this rating. Note that no calculation is performed until # Add a result to this rating. Note that no calculation is performed until
# update() is called. # update() is called.
def add_result(opponent,result) def add_result(opponent,result)
@results.push( Result.new(opponent.clone, result) ) @results.push( Result.new(opponent.clone, result) )
end end
# Add a win result to this rating. Note that no calculation is performed until # Add a win result to this rating. Note that no calculation is performed until
# update() is called. # update() is called.
def add_win(opponent) def add_win(opponent)
add_result(opponent,Glicko2::WIN) add_result(opponent,Glicko2::WIN)
end end
# Add a loss result to this rating. Note that no calculation is performed until # Add a loss result to this rating. Note that no calculation is performed until
# update() is called. # update() is called.
def add_loss(opponent) def add_loss(opponent)
add_result(opponent,Glicko2::LOSS) add_result(opponent,Glicko2::LOSS)
end end
# Add a draw result to this rating. Note that no calculation is performed until # Add a draw result to this rating. Note that no calculation is performed until
# update() is called. # update() is called.
def add_draw(opponent) def add_draw(opponent)
add_result(opponent,Glicko2::DRAW) add_result(opponent,Glicko2::DRAW)
end end
# Update rating based on current results list, and clear results. # Update rating based on current results list, and clear results.
def update def update
# util func # util func
def Glicko2.g(deviation) def Glicko2.g(deviation)
1.0 / (Math.sqrt(1.0 + 3.0 * deviation ** 2.0 / (Math::PI ** 2.0))) 1.0 / (Math.sqrt(1.0 + 3.0 * deviation ** 2.0 / (Math::PI ** 2.0)))
end end
# util func # util func
def Glicko2.E(rating, rating_opponent, deviation_opponent) def Glicko2.E(rating, rating_opponent, deviation_opponent)
1.0 / (1.0 + Math.exp(-Glicko2.g(deviation_opponent)*(rating - rating_opponent))); 1.0 / (1.0 + Math.exp(-Glicko2.g(deviation_opponent)*(rating - rating_opponent)));
end end
# bail if no opponents set # bail if no opponents set
if @results.empty? if @results.empty?
return nil return nil
end end
# compute variance # compute variance
#variance = 0.0 #variance = 0.0
#@results.inject(0.0) do |variance,r| #@results.inject(0.0) do |variance,r|
# g_i = Glicko2.g(r.opponent.g2deviation) # g_i = Glicko2.g(r.opponent.g2deviation)
# e_i = Glicko2.E(@g2rating,r.opponent.g2rating,r.opponent.g2deviation) # e_i = Glicko2.E(@g2rating,r.opponent.g2rating,r.opponent.g2deviation)
# g_i ** 2.0 * e_i * (1.0 - e_i) # g_i ** 2.0 * e_i * (1.0 - e_i)
#end #end
variance = 0.0 variance = 0.0
@results.each do |r| @results.each do |r|
g_i = Glicko2.g(r.opponent.g2deviation) g_i = Glicko2.g(r.opponent.g2deviation)
e_i = Glicko2.E(@g2rating,r.opponent.g2rating,r.opponent.g2deviation) e_i = Glicko2.E(@g2rating,r.opponent.g2rating,r.opponent.g2deviation)
variance += g_i ** 2.0 * e_i * (1.0 - e_i) variance += g_i ** 2.0 * e_i * (1.0 - e_i)
end end
variance = 1.0 / variance variance = 1.0 / variance
# compute delta # compute delta
delta = 0.0 delta = 0.0
@results.each do |r| @results.each do |r|
delta += Glicko2.g(r.opponent.g2deviation) * (r.result - Glicko2.E(@g2rating, r.opponent.g2rating, r.opponent.g2deviation)) delta += Glicko2.g(r.opponent.g2deviation) * (r.result - Glicko2.E(@g2rating, r.opponent.g2rating, r.opponent.g2deviation))
end end
delta *= variance delta *= variance
# determine new volatility # determine new volatility
new_volatility = 0.0 new_volatility = 0.0
a = Math.log( @g2volatility**2.0 ) a = Math.log( @g2volatility**2.0 )
x = 0.0 x = 0.0
x_new = a x_new = a
while ( (x - x_new).abs > 0.0000001 ) while ( (x - x_new).abs > 0.0000001 )
x = x_new x = x_new
d = @g2deviation**2.0 + variance + Math.exp(x) d = @g2deviation**2.0 + variance + Math.exp(x)
h1 = -(x - a)/(@dvolatility**2.0) - 0.5*Math.exp(x)/d + 0.5*Math.exp(x)*(delta/d)*(delta/d) h1 = -(x - a)/(@dvolatility**2.0) - 0.5*Math.exp(x)/d + 0.5*Math.exp(x)*(delta/d)*(delta/d)
h2 = -1.0/(@dvolatility**2.0) - 0.5*Math.exp(x)*(@g2deviation**2.0+variance)/(d**2.0) + 0.5*(delta**2.0)*Math.exp(x)*((@g2deviation**2.0) + variance - Math.exp(x))/(d**3.0) h2 = -1.0/(@dvolatility**2.0) - 0.5*Math.exp(x)*(@g2deviation**2.0+variance)/(d**2.0) + 0.5*(delta**2.0)*Math.exp(x)*((@g2deviation**2.0) + variance - Math.exp(x))/(d**3.0)
x_new = x - h1/h2 x_new = x - h1/h2
end end
new_volatility = Math.exp(x_new / 2.0) new_volatility = Math.exp(x_new / 2.0)
# update the rating deviation to the new pre-rating period value # update the rating deviation to the new pre-rating period value
pre_deviation = Math.sqrt( @g2deviation**2.0 + new_volatility**2.0 ) pre_deviation = Math.sqrt( @g2deviation**2.0 + new_volatility**2.0 )
# update the rating and deviation # update the rating and deviation
new_deviation = 1.0 / (Math.sqrt( 1.0/(pre_deviation**2.0) + 1.0 / variance)) new_deviation = 1.0 / (Math.sqrt( 1.0/(pre_deviation**2.0) + 1.0 / variance))
new_rating = 0.0 new_rating = 0.0
@results.each do |r| @results.each do |r|
new_rating += Glicko2.g(r.opponent.g2deviation) * (r.result - Glicko2.E(@g2rating, r.opponent.g2rating, r.opponent.g2deviation)) new_rating += Glicko2.g(r.opponent.g2deviation) * (r.result - Glicko2.E(@g2rating, r.opponent.g2rating, r.opponent.g2deviation))
end end
new_rating = new_rating * new_deviation**2.0 new_rating = new_rating * new_deviation**2.0
new_rating += @g2rating new_rating += @g2rating
# wipe our result lists # wipe our result lists
clear_results clear_results
# copy new values # copy new values
@g2deviation = new_deviation @g2deviation = new_deviation
@g2volatility = new_volatility @g2volatility = new_volatility
@g2rating = new_rating @g2rating = new_rating
end end
end end
+17 -17
View File
@@ -5,30 +5,30 @@ require 'test/unit'
class TestGlicko2 < Test::Unit::TestCase class TestGlicko2 < Test::Unit::TestCase
def test_simple def test_simple
a = Glicko2.new(1500.0, 200.0, 0.06) a = Glicko2.new(1500.0, 200.0, 0.06)
b = Glicko2.new(1400.0, 30.0, 0.06) b = Glicko2.new(1400.0, 30.0, 0.06)
c = Glicko2.new(1550.0, 100.0, 0.06) c = Glicko2.new(1550.0, 100.0, 0.06)
d = Glicko2.new(1700.0, 300.0, 0.06) d = Glicko2.new(1700.0, 300.0, 0.06)
a.add_win(b) a.add_win(b)
a.add_loss(c) a.add_loss(c)
a.add_result(d,0.0) a.add_result(d,0.0)
assert_equal(1500.0, a.rating) assert_equal(1500.0, a.rating)
assert_equal(200.0, a.deviation) assert_equal(200.0, a.deviation)
a.update() a.update()
assert_in_delta(1464.05,a.rating,0.01) assert_in_delta(1464.05,a.rating,0.01)
assert_in_delta(151.516,a.deviation,0.01) assert_in_delta(151.516,a.deviation,0.01)
a.update() a.update()
assert_in_delta(1464.05,a.rating,0.01) assert_in_delta(1464.05,a.rating,0.01)
assert_in_delta(151.516,a.deviation,0.01) assert_in_delta(151.516,a.deviation,0.01)
end end
end end