trueskill 0.9.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.md CHANGED
@@ -1,3 +1,9 @@
1
+ v1.0.0
2
+ ------
3
+
4
+ * made draws work
5
+ * fixed source file loading
6
+
1
7
  v0.1.0
2
8
  ------
3
9
 
@@ -1,4 +1,7 @@
1
1
  # -*- encoding : utf-8 -*-
2
- Dir.glob("#{File.dirname(__FILE__)}/gauss/**/*.rb").each do |src|
3
- require src
2
+ %w(
3
+ distribution
4
+ truncated_correction
5
+ ).each do |name|
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "gauss", "#{name}.rb"))
4
7
  end
@@ -74,10 +74,29 @@ module Saulabs
74
74
 
75
75
  # The inverse of the cummulative Gaussian distribution function
76
76
  def quantile_function(x)
77
- -@@sqrt2 * Math.erfc(2.0 * x)
77
+ -@@sqrt2 * inv_erf(2.0 * x)
78
78
  end
79
79
  alias_method :inv_cdf, :quantile_function
80
80
 
81
+ def inv_erf(p)
82
+ return -100 if p >= 2.0
83
+ return 100 if p <= 0.0
84
+
85
+ pp = p < 1.0 ? p : 2 - p
86
+ t = Math.sqrt(-2*Math.log(pp/2.0)) # Initial guess
87
+ x = -0.70711*((2.30753 + t*0.27061)/(1.0 + t*(0.99229 + t*0.04481)) - t)
88
+
89
+ [0,1].each do |j|
90
+ err = erf(x) - pp
91
+ x += err/(1.12837916709551257*Math.exp(-(x*x)) - x*err) # Halley
92
+ end
93
+ p < 1.0 ? x : -x
94
+ end
95
+
96
+ def erf(x)
97
+ Math.erfc(x)
98
+ end
99
+
81
100
  end
82
101
 
83
102
  def value_at(x)
@@ -1,8 +1,42 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  require 'pp'
3
3
 
4
- require "#{File.dirname(__FILE__)}/gauss.rb"
4
+ require File.expand_path(File.join(File.dirname(__FILE__), "gauss.rb"))
5
5
 
6
- Dir.glob("#{File.dirname(__FILE__)}/trueskill/**/*.rb").sort.each do |src|
7
- require src
6
+ %w(
7
+ base greater_than
8
+ likelihood
9
+ prior
10
+ weighted_sum
11
+ within
12
+ ).each do |name|
13
+ require File.expand_path(File.join(File.dirname(__FILE__), "trueskill", "factors", "#{name}.rb"))
14
+ end
15
+
16
+ %w(
17
+ base
18
+ iterated_team_performances
19
+ performances_to_team_performances
20
+ prior_to_skills
21
+ skills_to_performances
22
+ team_difference_comparision
23
+ team_performance_differences
24
+ ).each do |name|
25
+ require File.expand_path(File.join(File.dirname(__FILE__), "trueskill", "layers", "#{name}.rb"))
26
+ end
27
+
28
+ %w(
29
+ base
30
+ loop
31
+ sequence
32
+ step
33
+ ).each do |name|
34
+ require File.expand_path(File.join(File.dirname(__FILE__), "trueskill", "schedules", "#{name}.rb"))
35
+ end
36
+
37
+ %w(
38
+ rating
39
+ factor_graph
40
+ ).each do |name|
41
+ require File.expand_path(File.join(File.dirname(__FILE__), "trueskill", "#{name}.rb"))
8
42
  end
@@ -46,7 +46,7 @@ module Saulabs
46
46
  # include Saulabs::TrueSkill
47
47
  #
48
48
  # # team 1 has just one player with a mean skill of 27.1, a skill-deviation of 2.13
49
- # # and an play activity of 100 %
49
+ # # and a play activity of 100 %
50
50
  # team1 = [Rating.new(27.1, 2.13, 1.0)]
51
51
  #
52
52
  # # team 2 has two players
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe Gauss::Distribution, "#initialize" do
5
5
 
@@ -130,7 +130,7 @@ describe Gauss::Distribution, "functions" do
130
130
 
131
131
  describe 'value = 0.27' do
132
132
 
133
- it "#cumulative_distribution_function should return 0.6064198" do
133
+ it "#cumulative_distribution_function should return 0.6064198 for 0.27" do
134
134
  Gauss::Distribution.cumulative_distribution_function(0.27).should be_close(0.6064198, 0.00001)
135
135
  Gauss::Distribution.cdf(2.0).should be_close(0.9772498, 0.00001)
136
136
  end
@@ -139,8 +139,36 @@ describe Gauss::Distribution, "functions" do
139
139
  Gauss::Distribution.probability_density_function(0.27).should be_close(0.384662, 0.0001)
140
140
  end
141
141
 
142
- it "#quantile_function should return -0.62941" do
143
- Gauss::Distribution.quantile_function(0.27).should be_close(-0.62941, 0.00001)
142
+ it "#quantile_function should return ~ -0.6128123 at 0.27" do
143
+ Gauss::Distribution.quantile_function(0.27).should be_close(-0.6128123, 0.00001)
144
+ end
145
+
146
+ it "#quantile_function should return ~ 1.281551 at 0.9" do
147
+ Gauss::Distribution.quantile_function(0.9).should be_close(1.281551, 0.00001)
148
+ end
149
+
150
+ it "#erf_inv should return 0.0888559 at 0.9" do
151
+ Gauss::Distribution.inv_erf(0.9).should be_close(0.0888559, 0.00001)
152
+ end
153
+
154
+ it "#erf_inv should return 0.779983 at 0.27" do
155
+ Gauss::Distribution.inv_erf(0.27).should be_close(0.779983, 0.00001)
156
+ end
157
+
158
+ it "#erf_inv should return 100 at -0.5" do
159
+ Gauss::Distribution.inv_erf(-0.5).should be_close(100, 0.00001)
160
+ end
161
+
162
+ it "#erf should return 0.203091 at 0.9" do
163
+ Gauss::Distribution.erf(0.9).should be_close(0.203091, 0.00001)
164
+ end
165
+
166
+ it "#erf should return 0.702581 at 0.27" do
167
+ Gauss::Distribution.erf(0.27).should be_close(0.702581, 0.00001)
168
+ end
169
+
170
+ it "#erf should return 1.520499 at -0.5" do
171
+ Gauss::Distribution.erf(-0.5).should be_close(1.520499, 0.00001)
144
172
  end
145
173
 
146
174
  end
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe Gauss::TruncatedCorrection do
5
5
 
@@ -24,6 +24,7 @@ describe Gauss::TruncatedCorrection do
24
24
  describe "#w_exceeds_margin" do
25
25
 
26
26
  it "should return 0.657847 for (0.2, 0.3)" do
27
+ Gauss::TruncatedCorrection.w_exceeds_margin(0.0, 0.740466).should be_close(0.76774506, tolerance)
27
28
  Gauss::TruncatedCorrection.w_exceeds_margin(0.2, 0.3).should be_close(0.657847, tolerance)
28
29
  Gauss::TruncatedCorrection.w_exceeds_margin(0.1, 0.03).should be_close(0.621078, tolerance)
29
30
  end
@@ -33,6 +34,7 @@ describe Gauss::TruncatedCorrection do
33
34
  describe "#v_exceeds_margin" do
34
35
 
35
36
  it "should return 0.8626174 for (0.2, 0.3)" do
37
+ Gauss::TruncatedCorrection.v_exceeds_margin(0.0, 0.740466).should be_close(1.32145197, tolerance)
36
38
  Gauss::TruncatedCorrection.v_exceeds_margin(0.2, 0.3).should be_close(0.8626174, tolerance)
37
39
  Gauss::TruncatedCorrection.v_exceeds_margin(0.1, 0.03).should be_close(0.753861, tolerance)
38
40
  end
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe Saulabs::TrueSkill::FactorGraph do
5
5
 
@@ -11,48 +11,100 @@ describe Saulabs::TrueSkill::FactorGraph do
11
11
 
12
12
  describe "#update_skills" do
13
13
 
14
- it "should update the mean of the first player in team1 to 29.61452" do
14
+ it "should update the mean of the first player in team1 to 30.38345" do
15
15
  @graph.update_skills
16
- @skill.mean.should be_close(29.61452, tolerance)
16
+ @skill.mean.should be_close(30.38345, tolerance)
17
17
  end
18
18
 
19
- it "should update the deviation of the first player in team1 to 3.5036" do
19
+ it "should update the deviation of the first player in team1 to 3.46421" do
20
20
  @graph.update_skills
21
- @skill.deviation.should be_close(3.5036, tolerance)
21
+ @skill.deviation.should be_close(3.46421, tolerance)
22
22
  end
23
23
 
24
24
  end
25
25
 
26
26
  describe "#draw_margin" do
27
27
 
28
- it "should be -0.998291" do
29
- @graph.draw_margin.should be_close(-0.998291, tolerance)
28
+ it "should be -0.998291 for diff 0.740466" do
29
+ @graph.draw_margin.should be_close(0.740466, tolerance)
30
30
  end
31
31
 
32
32
  end
33
33
 
34
34
  end
35
35
 
36
- describe Saulabs::TrueSkill::FactorGraph do
36
+ describe Saulabs::TrueSkill::FactorGraph, "two players" do
37
+
38
+ before :each do
39
+ @teams = [
40
+ [TrueSkill::Rating.new(25.0, 25.0/3.0, 1.0, 25.0/300.0)],
41
+ [TrueSkill::Rating.new(25.0, 25.0/3.0, 1.0, 25.0/300.0)]
42
+ ]
43
+ end
44
+
45
+ describe 'win with standard rating' do
46
+
47
+ before :each do
48
+ TrueSkill::FactorGraph.new(@teams, [1,2]).update_skills
49
+ end
50
+
51
+ it "should change first players rating to [29.395832, 7.1714755]" do
52
+ @teams[0][0].should eql_rating(29.395832, 7.1714755)
53
+ end
54
+
55
+ it "should change second players rating to [20.6041679, 7.1714755]" do
56
+ @teams[1][0].should eql_rating(20.6041679, 7.1714755)
57
+ end
58
+
59
+ end
60
+
61
+ describe 'draw with standard rating' do
62
+
63
+ before :each do
64
+ TrueSkill::FactorGraph.new(@teams, [1,1]).update_skills
65
+ end
66
+
67
+ it "should change first players rating to [25.0, 6.4575196]" do
68
+ @teams[0][0].should eql_rating(25.0, 6.4575196)
69
+ end
70
+
71
+ it "should change second players rating to [25.0, 6.4575196]" do
72
+ @teams[1][0].should eql_rating(25.0, 6.4575196)
73
+ end
74
+
75
+ end
76
+
77
+ describe 'draw with different ratings' do
78
+
79
+ before :each do
80
+ @teams[1][0] = TrueSkill::Rating.new(50.0, 12.5, 1.0, 25.0/300.0)
81
+ TrueSkill::FactorGraph.new(@teams, [1,1]).update_skills
82
+ end
83
+
84
+ it "should change first players rating to [31.6623, 7.1374]" do
85
+ @teams[0][0].should eql_rating(31.662301, 7.1374459)
86
+ end
87
+
88
+ it "should change second players mean to [35.0107, 7.9101]" do
89
+ @teams[1][0].should eql_rating(35.010653, 7.910077)
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+
96
+ describe Saulabs::TrueSkill::FactorGraph, "two on two" do
37
97
 
38
98
  before :each do
39
99
  @teams = [
40
- [
41
- TrueSkill::Rating.new(8.3, 3.1, 0.8, 0.02),
42
- TrueSkill::Rating.new(3.0, 3.1, 0.8, 0.02),
43
- TrueSkill::Rating.new(2.2, 3.2, 0.8, 0.02)
44
- ],
45
- [
46
- TrueSkill::Rating.new(25.0, 8.3333, 0.8, 0.02)
47
- ]
100
+ [TrueSkill::Rating.new(25.0, 25.0/3.0, 1.0, 25.0/300.0),TrueSkill::Rating.new(25.0, 25.0/3.0, 1.0, 25.0/300.0)],
101
+ [TrueSkill::Rating.new(25.0, 25.0/3.0, 1.0, 25.0/300.0),TrueSkill::Rating.new(25.0, 25.0/3.0, 1.0, 25.0/300.0)]
48
102
  ]
49
- @skill = @teams.last.first
50
- @graph = TrueSkill::FactorGraph.new(@teams, [1,2], :beta => 25.0, :draw_probability => 0.0)
51
103
  end
52
104
 
53
- it "should do something" do
54
- 40.times { TrueSkill::FactorGraph.new(@teams, [1,2], :beta => 15.0, :draw_probability => 0.0).update_skills }
55
- puts "#{@skill.to_s}"
105
+ describe 'win with standard rating' do
106
+
107
+
56
108
  end
57
109
 
58
110
  end
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe TrueSkill::Factors::GreaterThan do
5
5
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe TrueSkill::Factors::Likelihood do
5
5
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe TrueSkill::Factors::Prior do
5
5
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe TrueSkill::Factors::Prior do
5
5
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe TrueSkill::Factors::Within do
5
5
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe TrueSkill::Layers::PriorToSkills do
5
5
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.expand_path('spec/spec_helper.rb')
3
3
 
4
4
  describe "Schedules" do
5
5
 
@@ -2,12 +2,13 @@
2
2
  require 'rubygems'
3
3
  require 'spec'
4
4
  require 'spec/autorun'
5
- require "#{File.dirname(__FILE__)}/../lib/saulabs/trueskill.rb"
5
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "saulabs", "trueskill.rb"))
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "true_skill_matchers.rb"))
6
7
 
7
8
  include Saulabs
8
9
 
9
10
  Spec::Runner.configure do |config|
10
-
11
+ config.include(TrueSkillMatchers)
11
12
  end
12
13
 
13
14
  def tolerance
@@ -0,0 +1,39 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module TrueSkillMatchers
3
+
4
+ class EqualRating
5
+
6
+ def initialize(mean, deviation, precision)
7
+ @expected = TrueSkill::Rating.new(mean, deviation)
8
+ @precision = 10**precision
9
+ end
10
+
11
+ def matches?(target)
12
+ @target = target
13
+ @mean_diff = @expected.mean - @target.mean
14
+ @deviation_diff = @expected.deviation - @target.deviation
15
+ (@mean_diff*@precision).to_i + (@deviation_diff*@precision).to_i == 0
16
+ end
17
+
18
+ def failure_message
19
+ "expected rating #{@target.to_s} to be equal to #{@expected.to_s} #{failure_info}"
20
+ end
21
+
22
+ def negative_failure_message
23
+ "expected rating #{@target.to_s} not to be equal to #{@expected.to_s} #{failure_info}"
24
+ end
25
+
26
+ def failure_info
27
+ msg = []
28
+ msg << "mean differs by #{@mean_diff}" if @mean_diff != 0.0
29
+ msg << "deviation differs by #{@deviation_diff}" if @deviation_diff != 0.0
30
+ " (#{msg.join(', ')})"
31
+ end
32
+
33
+ end
34
+
35
+ def eql_rating(target_mean, target_deviation, precision = 5)
36
+ EqualRating.new(target_mean, target_deviation, precision)
37
+ end
38
+
39
+ end
metadata CHANGED
@@ -3,10 +3,10 @@ name: trueskill
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
+ - 1
6
7
  - 0
7
- - 9
8
- - 2
9
- version: 0.9.2
8
+ - 0
9
+ version: 1.0.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Lars Kuhnt
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-07-20 00:00:00 +02:00
17
+ date: 2011-01-19 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -65,8 +65,9 @@ files:
65
65
  - spec/saulabs/trueskill/layers/prior_to_skills_spec.rb
66
66
  - spec/saulabs/trueskill/schedules_spec.rb
67
67
  - spec/spec_helper.rb
68
+ - spec/true_skill_matchers.rb
68
69
  - spec/spec.opts
69
- has_rdoc: true
70
+ has_rdoc: false
70
71
  homepage: http://github.com/saulabs/trueskill
71
72
  licenses: []
72
73
 
@@ -110,4 +111,5 @@ test_files:
110
111
  - spec/saulabs/trueskill/layers/prior_to_skills_spec.rb
111
112
  - spec/saulabs/trueskill/schedules_spec.rb
112
113
  - spec/spec_helper.rb
114
+ - spec/true_skill_matchers.rb
113
115
  - spec/spec.opts