class RationalChoice::ManyDimensions

Performs an evaluation based on multiple dimensions. The dimensions will be first coerced into one (number of truthy evaluations vs. number of falsey evaluations) and then a true/false value will be deduced from that.

Public Class Methods

new(*dimensions, random: Random.new) click to toggle source

Initializes a new Dimension to evaluate values

@param random the RNG, defaults to a new Random

# File lib/rational_choice.rb, line 86
def initialize(*dimensions, random: Random.new)
  @dimensions = dimensions
  @random = random
  raise CardinalityError, '%s has no dimensions to evaluate' % inspect if @dimensions.empty?
end

Public Instance Methods

choose(*values) click to toggle source

Performs a weighted choice, by first collecting choice results from all the dimensions, and then by interpolating those results by the ratio of truthy values vs falsey values.

x = Dimension.new(0,1)
y = Dimension.new(0,1)
z = Dimension.new(0,1)

within_positive_3d_space = ManyDimensions.new(x, y, z)
within_positive_3d_space.choose(-1, -1, -0.5) #=> false
within_positive_3d_space.choose(1.1, 123, 1) #=> true
within_positive_3d_space.choose(1, 0.5, 0.7) #=> true or false depending on 3 probabilities

@param

# File lib/rational_choice.rb, line 106
def choose(*values)
  if @dimensions.length != values.length
    raise CardinalityError, '%s has %d dimensions but %d values were given' % [inspect, @dimensions.length, values.length]
  end

  evaluations = values.zip(@dimensions).map { |(v, d)| d.choose(v) }
  num_truthy_choices = evaluations.select { |e| e }.length

  Dimension.new(false_at_or_below: 0, true_at_or_above: evaluations.length, random: @random).choose(num_truthy_choices)
end