-
Notifications
You must be signed in to change notification settings - Fork 0
/
sentence_generator.rb
44 lines (40 loc) · 1.21 KB
/
sentence_generator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
class SentenceGenerator
def initialize(grammar, conv_factor)
@grammar = grammar.freeze
@convergence = conv_factor.freeze
end
def get_random(symbol = @grammar.start_sym,
c = @convergence,
rule_count = Hash.new(0))
sentence = ''
weights = []
applicable_rules = @grammar.rules.filter { |rule| rule.lhs == symbol }
applicable_rules.each { |rule|
if rule_count.key?(rule)
weights << c ** rule_count[rule]
else
weights << 1.0
end
}
rand_rule = applicable_rules[weighted_choice(weights)]
rule_count[rand_rule] += 1
rand_rule.rhs.each { |sym|
if sym.type == :nonterminal
sentence << get_random(sym, c, rule_count)
else
sentence << "#{sym}"
end
}
# backtrack
rule_count[rand_rule] -= 1
return sentence
end
private
def weighted_choice(weights)
rnd = rand() * weights.reduce(:+)
weights.each_with_index { |w, i|
rnd -= w
return i if rnd < 0
}
end
end