Module: OpenSkill::Models::Common

Defined in:
lib/openskill/models/common.rb

Overview

Common utility functions shared across models

Class Method Summary collapse

Class Method Details

.matrix_transpose(matrix) ⇒ Array<Array>

Transpose a 2D matrix

Parameters:

  • matrix (Array<Array>)

    the input matrix

Returns:

  • (Array<Array>)

    the transposed matrix



34
35
36
37
38
# File 'lib/openskill/models/common.rb', line 34

def self.matrix_transpose(matrix)
  return [] if matrix.empty? || matrix[0].empty?

  matrix[0].zip(*matrix[1..])
end

.normalize(vector, target_min, target_max) ⇒ Array<Float>

Normalize a vector to a target range

Parameters:

  • vector (Array<Numeric>)

    the input vector

  • target_min (Numeric)

    the target minimum value

  • target_max (Numeric)

    the target maximum value

Returns:

  • (Array<Float>)

    the normalized vector



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/openskill/models/common.rb', line 13

def self.normalize(vector, target_min, target_max)
  return [] if vector.empty?

  source_min = vector.min
  source_max = vector.max
  source_range = source_max - source_min

  # If all values are the same, return target_min for all
  return Array.new(vector.size, target_min.to_f) if source_range.zero?

  target_range = target_max - target_min

  vector.map do |value|
    ((value - source_min) / source_range) * target_range + target_min
  end
end

.unwind(tenet, objects) ⇒ Array<(Array, Array<Numeric>)>

Sort objects by tenet and return both sorted objects and indices to restore order

Parameters:

  • tenet (Array<Numeric>)

    values to sort by

  • objects (Array)

    objects to sort

Returns:

  • (Array<(Array, Array<Numeric>)>)

    sorted objects and restoration indices



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/openskill/models/common.rb', line 45

def self.unwind(tenet, objects)
  return [[], []] if objects.empty?

  # Create array of [tenet_value, [object, original_index]]
  indexed = tenet.each_with_index.map { |t, i| [t, [objects[i], i]] }

  # Sort by tenet value
  sorted = indexed.sort_by { |t, _| t }

  # Extract sorted objects and their indices
  sorted_objects = sorted.map { |_, (obj, _)| obj }
  restoration_indices = sorted.map { |_, (_, idx)| idx }

  [sorted_objects, restoration_indices]
end

.v(x, t) ⇒ Float

The V function as defined in Weng-Lin 2011 Computes phi_minor(x-t) / phi_major(x-t)

Parameters:

  • x (Float)

    input value

  • t (Float)

    threshold value

Returns:

  • (Float)

    the V function result



67
68
69
70
71
72
73
74
# File 'lib/openskill/models/common.rb', line 67

def self.v(x, t)
  xt = x - t
  denominator = Statistics::Normal.cdf(xt)

  return -xt if denominator < Float::EPSILON

  Statistics::Normal.pdf(xt) / denominator
end

.vt(x, t) ⇒ Float

The V-tilde function for draws as defined in Weng-Lin 2011 Handles doubly truncated Gaussians

Parameters:

  • x (Float)

    input value

  • t (Float)

    threshold value

Returns:

  • (Float)

    the V-tilde function result



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/openskill/models/common.rb', line 100

def self.vt(x, t)
  xx = x.abs
  b = Statistics::Normal.cdf(t - xx) - Statistics::Normal.cdf(-t - xx)

  if b < 1e-5
    return x < 0 ? (-x - t) : (-x + t)
  end

  a = Statistics::Normal.pdf(-t - xx) - Statistics::Normal.pdf(t - xx)
  (x < 0 ? -a : a) / b
end

.w(x, t) ⇒ Float

The W function as defined in Weng-Lin 2011 Computes V(x,t) * (V(x,t) + (x-t))

Parameters:

  • x (Float)

    input value

  • t (Float)

    threshold value

Returns:

  • (Float)

    the W function result



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/openskill/models/common.rb', line 82

def self.w(x, t)
  xt = x - t
  denominator = Statistics::Normal.cdf(xt)

  if denominator < Float::EPSILON
    return x < 0 ? 1.0 : 0.0
  end

  v_val = v(x, t)
  v_val * (v_val + xt)
end

.wt(x, t) ⇒ Float

The W-tilde function for draws as defined in Weng-Lin 2011 Handles variance for doubly truncated Gaussians

Parameters:

  • x (Float)

    input value

  • t (Float)

    threshold value

Returns:

  • (Float)

    the W-tilde function result



118
119
120
121
122
123
124
125
126
127
128
# File 'lib/openskill/models/common.rb', line 118

def self.wt(x, t)
  xx = x.abs
  b = Statistics::Normal.cdf(t - xx) - Statistics::Normal.cdf(-t - xx)

  return 1.0 if b < Float::EPSILON

  numerator = ((t - xx) * Statistics::Normal.pdf(t - xx) +
              (t + xx) * Statistics::Normal.pdf(-t - xx))
  vt_val = vt(x, t)
  numerator / b + vt_val * vt_val
end