Class: Saulabs::TrueSkill::FactorGraph

Inherits:
Object
  • Object
show all
Defined in:
lib/saulabs/trueskill/factor_graph.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(teams, ranks, options = {}) ⇒ FactorGraph

Creates a new trueskill factor graph for calculating the new skills based on the given game parameters

Examples:

Calculating new skills of a two team game, where one team has one player and the other two


require 'rubygems'
require 'saulabs/trueskill'

include Saulabs::TrueSkill

# team 1 has just one player with a mean skill of 27.1, a skill-deviation of 2.13
# and an play activity of 100 %
team1 = [Rating.new(27.1, 2.13, 1.0)]

# team 2 has two players
team2 = [Rating.new(22.0, 0.98, 0.8), Rating.new(31.1, 5.33, 0.9)]

# team 1 finished first and team 2 second
graph = FactorGraph.new([team1, team2], [1,2])

# update the Ratings
graph.update_skills

Parameters:

  • teams (Array<Array<TrueSkill::Rating>>)

    player-ratings grouped in Arrays by teams

  • ranks (Array<Integer>)

    team rankings, example: [2,1,3] first team in teams finished 2nd, second team 1st and third team 3rd

  • options (Hash) (defaults to: {})

    the options hash to configure the factor graph constants beta and draw_probability

Options Hash (options):

  • :beta (Float) — default: 4.166667

    the length of the skill-chain. Use a low value for games with a small amount of chance (Go, Chess, etc.) and a high value for games with a high amount of chance (Uno, Bridge, etc.)

  • :draw_probability (Float) — default: 0.1

    how probable is a draw in the game outcome [0.0,1.0]



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/saulabs/trueskill/factor_graph.rb', line 60

def initialize(teams, ranks, options = {})
  @teams = teams
  @ranks = ranks
  @beta = options[:beta] || 25/6.0
  @draw_probability = options[:draw_probability] || 0.1
  @beta_squared = @beta**2
  @epsilon = -Math.sqrt(2.0 * @beta_squared) * Gauss::Distribution.inv_cdf((1.0 - @draw_probability) / 2.0)
  
  @prior_layer = Layers::PriorToSkills.new(self, @teams)
  @layers = [
    @prior_layer,
    Layers::SkillsToPerformances.new(self),
    Layers::PerformancesToTeamPerformances.new(self),
    Layers::IteratedTeamPerformances.new(self,
      Layers::TeamPerformanceDifferences.new(self),
      Layers::TeamDifferenceComparision.new(self, ranks)
    )
  ]
end

Instance Attribute Details

#betaFloat (readonly)

Returns:

  • (Float)


10
11
12
# File 'lib/saulabs/trueskill/factor_graph.rb', line 10

def beta
  @beta
end

#beta_squaredFloat (readonly)

Returns:

  • (Float)


13
14
15
# File 'lib/saulabs/trueskill/factor_graph.rb', line 13

def beta_squared
  @beta_squared
end

#draw_probabilityFloat (readonly)

Returns:

  • (Float)


16
17
18
# File 'lib/saulabs/trueskill/factor_graph.rb', line 16

def draw_probability
  @draw_probability
end

#epsilonFloat (readonly)

Returns:

  • (Float)


19
20
21
# File 'lib/saulabs/trueskill/factor_graph.rb', line 19

def epsilon
  @epsilon
end

#layersObject (readonly)



22
23
24
# File 'lib/saulabs/trueskill/factor_graph.rb', line 22

def layers
  @layers
end

#teamsArray<Array<TrueSkill::Rating>> (readonly)

Returns:



7
8
9
# File 'lib/saulabs/trueskill/factor_graph.rb', line 7

def teams
  @teams
end

Instance Method Details

#draw_marginObject



80
81
82
# File 'lib/saulabs/trueskill/factor_graph.rb', line 80

def draw_margin
  Gauss::Distribution.inv_cdf(0.5*(@draw_probability + 1)) * Math.sqrt(1 + 1) * @beta
end

#update_skillsFloat

Updates the skills of the players inplace

Returns:

  • (Float)

    the probability of the games outcome



87
88
89
90
91
92
93
94
95
96
# File 'lib/saulabs/trueskill/factor_graph.rb', line 87

def update_skills
  build_layers
  run_schedule
  @teams.each_with_index do |team, i|
    team.each_with_index do |player, j|
      player.replace(@prior_layer.output[i][j])
    end
  end
  ranking_probability
end