class Panini::DerivationStrategy::RandomDampened

This derivation strategy uses a dampening factor to reduce the liklihood of hitting either too-deep or infinite traversals through the grammar. This is based on material presented here:

eli.thegreenplace.net/2010/01/28/generating-random-sentences-from-a-context-free-grammar

Public Class Methods

new(grammar, damping = 0.25) click to toggle source

Initializes the derivator. The damping factor is a number betweeon 0.0 and 1.0. In general, the smaller the number the shorter the senetence generated by the derivator. If the number is close to 1.0, it is possible that you will encounter stack errors!

Calls superclass method Panini::DerivationStrategy::Base::new
# File lib/derivation_strategy/random_dampened.rb, line 69
def initialize(grammar, damping = 0.25)
  if (damping <= 0.0) || (damping >= 1.0)
    raise ArgumentError, "The damping factor must be greater than 0.0 and less than 1.0."
  end
  build_production_proxies(grammar, damping)
  super(grammar)
end

Public Instance Methods

sentence() click to toggle source

Generates a sentence.

# File lib/derivation_strategy/random_dampened.rb, line 86
def sentence
  substitute_nonterminal(@grammar.start, @production_proxies, 0)
end

Private Instance Methods

build_production_proxies(grammar, damping) click to toggle source
# File lib/derivation_strategy/random_dampened.rb, line 77
def build_production_proxies(grammar, damping)
  @production_proxies = {}
  grammar.nonterminals.each do |nonterminal|
    @production_proxies[nonterminal] = DampenedProbabilityProductionChoiceProxy.new(nonterminal, damping)
  end
end
substitute_nonterminal(nonterminal, production_proxies, depth) click to toggle source
# File lib/derivation_strategy/random_dampened.rb, line 90
def substitute_nonterminal(nonterminal, production_proxies, depth)

  # production_proxies_copy = {}
  #  production_proxies_copy = production_proxies.each do |key, value|
  #    production_proxies_copy[key] = value.dup
  #  end
  #
  production_proxies_copy = production_proxies.update_values do |value|
    value.dup
  end

  production_proxies_copy[nonterminal].production.flat_map do |term|
    if (term.class == Nonterminal)
      substitute_nonterminal(term, production_proxies_copy, depth + 1)
    else
      term
    end
  end

end