Class: Calyx::Syntax::WeightedChoices
- Inherits:
-
Object
- Object
- Calyx::Syntax::WeightedChoices
- Defined in:
- lib/calyx/syntax/weighted_choices.rb
Overview
A type of production rule representing a map of possible rules with associated weights that define the expected probability of a rule being chosen.
Class Method Summary collapse
-
.parse(productions, registry) ⇒ Calyx::Syntax::WeightedChoices
Parse a given list or hash of productions into a syntax tree of weighted choices.
Instance Method Summary collapse
-
#evaluate(options) ⇒ Array
Evaluate the choice by randomly picking one of its possible options, balanced according to the given weights.
-
#initialize(collection) ⇒ WeightedChoices
constructor
Initialize a new choice with a list of child nodes.
-
#size ⇒ Integer
The number of possible choices available for this rule.
Constructor Details
#initialize(collection) ⇒ WeightedChoices
Initialize a new choice with a list of child nodes.
62 63 64 |
# File 'lib/calyx/syntax/weighted_choices.rb', line 62 def initialize(collection) @collection = collection end |
Class Method Details
.parse(productions, registry) ⇒ Calyx::Syntax::WeightedChoices
Parse a given list or hash of productions into a syntax tree of weighted choices. Supports weights specified as Range, Fixnum and Float types.
All weights get normalized to a set of values in the 0..1 interval that sum to 1.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/calyx/syntax/weighted_choices.rb', line 16 def self.parse(productions, registry) if productions.first.last.is_a?(Range) range_max = productions.max { |a,b| a.last.max <=> b.last.max }.last.max weights_sum = productions.reduce(0) do |memo, choice| memo += choice.last.size end if range_max != weights_sum raise Errors::InvalidDefinition, "Weights must sum to total: #{range_max}" end normalized_productions = productions.map do |choice| weight = choice.last.size / range_max.to_f [choice.first, weight] end else weights_sum = productions.reduce(0) do |memo, choice| memo += choice.last end if productions.first.last.is_a?(Float) raise Errors::InvalidDefinition, 'Weights must sum to 1' if weights_sum != 1.0 normalized_productions = productions else normalized_productions = productions.map do |choice| weight = choice.last.to_f / weights_sum.to_f * 1.0 [choice.first, weight] end end end choices = normalized_productions.map do |choice, weight| if choice.is_a?(String) [Concat.parse(choice, registry), weight] elsif choice.is_a?(Symbol) [NonTerminal.new(choice, registry), weight] end end self.new(choices) end |
Instance Method Details
#evaluate(options) ⇒ Array
Evaluate the choice by randomly picking one of its possible options, balanced according to the given weights.
The method for selecting weighted probabilities is based on a snippet of code recommended in the Ruby standard library documentation.
81 82 83 84 85 86 87 |
# File 'lib/calyx/syntax/weighted_choices.rb', line 81 def evaluate() choice = @collection.max_by do |_, weight| .rand ** (1.0 / weight) end.first [:weighted_choice, choice.evaluate()] end |
#size ⇒ Integer
The number of possible choices available for this rule.
69 70 71 |
# File 'lib/calyx/syntax/weighted_choices.rb', line 69 def size @collection.size end |