Permalink
Browse files

rewrite based on the F# program by microsoft: http://blogs.technet.co…

  • Loading branch information...
1 parent 9c83c62 commit 7b4ab29251b23c44c729e9ca0c9cf1104415fc6a @larskuhnt larskuhnt committed Apr 12, 2010
View
@@ -1,42 +0,0 @@
-# Author: Lars Kuhnt
-# Copyright Saulabs
-
-module TrueSkill
-
- #
- #
- class Calculation
-
- # uncertainty of the skill’s standard deviation
- # TODO: valid values: ]0,???]
- # TODO: this should depend on the time the player did not play
- @@tau = 1.0
-
- # small beta value indicates a high-skill game (e.g. Go) since smaller
- # differences in points lead to the 80%:20% ratio. Likewise, a game based
- # on chance (e.g. Uno) is a low-skill game that would have a higher beta
- # and smaller skill chain.
- # TODO: valid values: ]0,???]
- @@beta = 10
-
- def initialize(game)
- @game = game
- end
-
-
- private
-
- # team must be an array of players with a minimum of one player
- def performance(team)
- rating = 0
- deviation = 0
- team.each do |player|
- rating += player.activity * player.rating
- deviation += player.activity * player.activity * player.deviation * player.deviation
- end
- return [rating, deviation]
- end
-
- end
-
-end
View
@@ -1,50 +0,0 @@
-module TrueSkill
-
- class Rating
-
- # gaussian normal distribution values
- attr_accessor :mean, :deviation, :variance, :precision, :precision_mean
-
- # how active was the player in the game
- # valid values: [0.0, 1.0]
- attr_accessor :activity
-
- def self.with_deviation(mean, deviation)
- rating = Rating.new
- rating.mean = mean
- rating.deviation = deviation
- rating.variance = deviation * deviation
- rating.precision = 1 / rating.variance.to_f
- rating.precision_mean = rating.precision * mean
- return rating
- end
-
- def self.with_precision(mean, precision)
- rating = Rating.new
- rating.precision = precision
- rating.precision_mean = mean
- rating.variance = 1 / precision
- rating.deviation = Math.sqrt(rating.variance)
- rating.mean = mean / precision
- return rating
- end
-
- def *(other)
-
- end
-
- def +(other)
-
- end
-
- def ==(other)
- self.mean == other.mean && self.variance == other.variance
- end
-
- def equals(other)
- self == other
- end
-
- end
-
-end
View
@@ -0,0 +1,3 @@
+require "#{File.dirname(__FILE__)}/gauss/functions.rb"
+require "#{File.dirname(__FILE__)}/gauss/distribution.rb"
+require "#{File.dirname(__FILE__)}/gauss/factor_graph.rb"
@@ -0,0 +1,81 @@
+module Saulabs
+ module Gauss
+ class Distribution
+
+ # gaussian normal distribution values
+ attr_accessor :mean, :deviation, :variance, :precision, :precision_mean
+
+ def initialize
+ @mean = 0.0
+ @deviation = 0.0
+ @variance = 0.0
+ @precision = 0.0
+ @precision_mean = 0.0
+ end
+
+ class << self
+
+ def with_deviation(mean, deviation)
+ dist = Distribution.new
+ dist.mean = mean
+ dist.deviation = deviation
+ dist.variance = deviation * deviation
+ dist.precision = 1 / dist.variance.to_f
+ dist.precision_mean = dist.precision * mean
+ return dist
+ end
+
+ def with_precision(mean, precision)
+ Distribution.with_deviation(mean / precision, Math.sqrt(1 / precision))
+ end
+
+ def absolute_difference(x, y)
+ [(x.precision_mean - y.precision_mean).abs, Math.sqrt((x.precision - y.precision).abs)].max
+ end
+
+ def log_product_normalisation(x, y)
+ return 0.0 if x.precision == 0.0 || y.precision == 0.0
+ vsum = x.variance + y.variance
+ mdiff = x.mean - y.mean
+ -0.91893853320467267 - Math.log(vsum) / 2.0 - mdiff * mdiff / 2.0 * vsum
+ end
+
+ def log_ratio_normalisation(x, y)
+ return 0.0 if x.precision == 0.0 || y.precision == 0.0
+ v2 = y.variance
+ vdiff = v2 - x.variance
+ return 0.0 if vdiff == 0.0
+ mdiff = x.mean - y.mean
+ Math.log(v2) + 0.91893853320467267 - Math.log(vdiff) / 2.0 + mdiff * mdiff / 2.0 * vdiff
+ end
+
+ end
+
+ def *(other)
+ Rating.with_precision(self.precision_mean + other.precision_mean, self.precision + other.precision)
+ end
+
+ def /(other)
+ Rating.with_precision(self.precision_mean - other.precision_mean, self.precision - other.precision)
+ end
+
+ # absolute difference
+ def -(other)
+ Distribution.absolute_difference(self, other)
+ end
+
+ def +(other)
+
+ end
+
+ def ==(other)
+ self.mean == other.mean && self.variance == other.variance
+ end
+
+ def equals(other)
+ self == other
+ end
+
+ end
+ end
+end
@@ -0,0 +1,7 @@
+module Saulabs
+ module Gauss
+ class FactorGraph
+
+ end
+ end
+end
@@ -0,0 +1,32 @@
+module Saulabs
+ module Gauss
+ class Functions
+
+ SQRT2 = Math.sqrt(2).freeze
+ INV_SQRT_2PI = (1 / Math.sqrt(2 * Math::PI)).freeze
+
+ class << self
+
+ # Computes the cummulative Gaussian distribution at a specified point of interest
+ def cumulative_distribution_function(x)
+ 0.5 * (1 + Math.erf(x / SQRT2))
+ end
+ alias_method :cdf, :cumulative_distribution_function
+
+ # Computes the Gaussian density at a specified point of interest
+ def probability_density_function(x)
+ INV_SQRT_2PI * Math.exp(-0.5 * (x**2))
+ end
+ alias_method :pdf, :probability_density_function
+
+ # The inverse of the cummulative Gaussian distribution function
+ def quantile_function(x)
+ -SQRT2 * Math.erfc(2.0 * x)
+ end
+ alias_method :inv_cdf, :quantile_function
+
+ end
+
+ end
+ end
+end
View
@@ -0,0 +1,22 @@
+require "#{File.dirname(__FILE__)}/gauss.rb"
+
+module Saulabs
+
+ module TrueSkill
+
+ # tau: uncertainty of the skill’s standard deviation TODO: interval???
+ # beta: chance factor (low for low-chance games like go and chess) TODO: interval???
+ # draw_prob: probalility of a draw game - [0,1(
+ # skills: the current skills of the participating players
+ #
+ def self.update_skills(tau, beta, draw_prob, skills)
+ tau2 = tau**2
+ beta2 = beta**2
+ num_players = skills.size
+ epsilon = -Math.sqrt(2.0 * beta2) * Gauss::Functions.inv_cdf((1.0 - draw_prob) / 2.0)
+ factors = []
+ end
+
+ end
+
+end
View
@@ -1,14 +0,0 @@
-require 'rubygems'
-require 'narray'
-
-Dir["#{File.dirname(__FILE__)}/**/*.rb"].each do |filename|
- require filename
-end
-
-module TrueSkill
-
- def self.evaluate
-
- end
-
-end
View
@@ -1,60 +0,0 @@
-require File.dirname(__FILE__) + '/../spec_helper'
-
-describe "Rating" do
-
- describe 'initialize with deviation' do
-
- before :each do
- @rating = TrueSkill::Rating.with_deviation(25.0, 8.333333)
- end
-
- it "should have a default mean value of 25.0" do
- @rating.mean.should == 25.0
- end
-
- it "should have a default deviation of 8.333333" do
- @rating.deviation.should be_close(8.333333, 0.000001)
- end
-
- it "should set the variance to 69.444438" do
- @rating.variance.should be_close(69.4444, 0.0001)
- end
-
- it "should set the precision to 0.0016" do
- @rating.precision.should be_close(0.0144, 0.0001)
- end
-
- it "should set the precision_mean to 0.04" do
- @rating.precision_mean.should be_close(0.36, 0.0001)
- end
-
- end
-
- describe 'initialize with precision' do
-
- before :each do
- @rating = TrueSkill::Rating.with_precision(0.36, 0.0144)
- end
-
- it "should have a default mean value of 25.0" do
- @rating.mean.should == 25.0
- end
-
- it "should have a default deviation of 8.333333" do
- @rating.deviation.should be_close(8.333333, 0.000001)
- end
-
- it "should set the variance to 69.444438" do
- @rating.variance.should be_close(69.4444, 0.0001)
- end
-
- it "should set the precision to 0.0016" do
- @rating.precision.should be_close(0.0144, 0.0001)
- end
-
- it "should set the precision_mean to 0.04" do
- @rating.precision_mean.should be_close(0.36, 0.0001)
- end
-
- end
-end
@@ -0,0 +1,73 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe Saulabs::Gauss::Distribution, "#with_deviation" do
+
+ before :each do
+ @dist = Saulabs::Gauss::Distribution.with_deviation(25.0, 8.333333)
+ end
+
+ it "should have a default mean value of 25.0" do
+ @dist.mean.should == 25.0
+ end
+
+ it "should have a default deviation of 8.333333" do
+ @dist.deviation.should be_close(8.333333, 0.000001)
+ end
+
+ it "should set the variance to 69.444438" do
+ @dist.variance.should be_close(69.4444, 0.0001)
+ end
+
+ it "should set the precision to 0.0144" do
+ @dist.precision.should be_close(0.0144, 0.0001)
+ end
+
+ it "should set the precision_mean to 0.36" do
+ @dist.precision_mean.should be_close(0.36, 0.0001)
+ end
+
+end
+
+describe Saulabs::Gauss::Distribution, "#with_precision" do
+
+ before :each do
+ @dist = Saulabs::Gauss::Distribution.with_precision(0.36, 0.0144)
+ end
+
+ it "should have a default mean value of 25.0" do
+ @dist.mean.should == 25.0
+ end
+
+ it "should have a default deviation of 8.333333" do
+ @dist.deviation.should be_close(8.333333, 0.000001)
+ end
+
+ it "should set the variance to 69.444438" do
+ @dist.variance.should be_close(69.4444, 0.0001)
+ end
+
+ it "should set the precision to 0.0144" do
+ @dist.precision.should be_close(0.0144, 0.0001)
+ end
+
+ it "should set the precision_mean to 0.36" do
+ @dist.precision_mean.should be_close(0.36, 0.0001)
+ end
+
+end
+
+describe Saulabs::Gauss::Distribution, "absolute difference (-)" do
+
+ before :each do
+ @dist = Saulabs::Gauss::Distribution.with_deviation(25.0, 8.333333)
+ end
+
+ it "should be 0.0 for the same distribution" do
+ (@dist - @dist).should == 0.0
+ end
+
+ it "should equal the precision mean if the 0-distribution is subtracted" do
+ (@dist - Saulabs::Gauss::Distribution.new).should == @dist.precision_mean
+ end
+
+end
No changes.
Oops, something went wrong.

0 comments on commit 7b4ab29

Please sign in to comment.