class ABSplit::Functions::HeavisideWeightedSplit

Weighted split based on a modified Heaviside function. In case a numeric value is passed, it uses a sigmoid function applying a modified Heaviside to choose the experiment. In case a none numeric value is passed it uses SHA2 algorithm to get a value from the object, and after decide based on weights.

Persistent - Supports 256 bits as input

No collisions are possible

Constants

MAX_HASH_VALUE

Protected Class Methods

select_experiment_for(value, experiments) click to toggle source
# File lib/a_b_split/functions/heaviside_weighted_split.rb, line 22
def select_experiment_for(value, experiments)
  x = value.is_a?(Numeric) ? value : hash(value)

  heaviside(x, experiments)
end

Private Class Methods

hash(value) click to toggle source
# File lib/a_b_split/functions/heaviside_weighted_split.rb, line 30
def hash(value)
  (sha256(value) - (MAX_HASH_VALUE / 2)).to_f / (MAX_HASH_VALUE / 2)
end
heaviside(value, experiments) click to toggle source
# File lib/a_b_split/functions/heaviside_weighted_split.rb, line 38
def heaviside(value, experiments)
  x = sigmoid(value)
  accumulated_percentages = 0

  experiments.each do |experiment|
    accumulated_percentages += percentage(experiment)

    return experiment['name'] if x <= accumulated_percentages
  end
end
percentage(experiment) click to toggle source
# File lib/a_b_split/functions/heaviside_weighted_split.rb, line 49
def percentage(experiment)
  experiment['weight'].to_f / 100
end
sha256(value) click to toggle source
# File lib/a_b_split/functions/heaviside_weighted_split.rb, line 34
def sha256(value)
  Digest::SHA256.hexdigest(value.to_s).to_i(16)
end
sigmoid(value) click to toggle source
# File lib/a_b_split/functions/heaviside_weighted_split.rb, line 53
def sigmoid(value)
  BigDecimal((1.0 / (1 + Math.exp(-2 * value))).to_s)
end