rubykov 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9827c73272cba93ae8557afe9cd9158175f5710c
4
- data.tar.gz: 3cafc24fa4870f60450dae6d2a5aa692ee3f72c7
3
+ metadata.gz: be1de15771cfa1694a274b2ad2659c565c0898f1
4
+ data.tar.gz: 1cc4d87fbacfeeaeebf0ad8c32e15cff7887e480
5
5
  SHA512:
6
- metadata.gz: b62a34df1580d94914ca0fe4bb171ba5d7449857e3f7323d72958930a912e9b69e67664eb23ce1b7562f14168890a8b46c549d754848951eaa94998ee875074f
7
- data.tar.gz: bc3f35303e83992f01ec220d032a70371682e4a173912807219a34cd924f1416defc62cdf014bb30ffccf9fbb3b2abb42cf8371b0264659ad0637f4490945545
6
+ metadata.gz: 0fcc4cd9b24f2185c2ee429fbf37de51c0ef8ec0efd5c117afb42632a0d34662131e48c056b01496d682f663ea636cee1b5774b1ea89ca1d06f854de5e19236b
7
+ data.tar.gz: bfa02c7f821816395aaf2266fdb85cd94ce798453121fda7d73ebd3fb3912ec9b44c48e8b6684920a3ac7cff20d55ef0ffd983644ae99b24da980d987434aed3
data/lib/rubykov.rb CHANGED
@@ -1,2 +1,4 @@
1
1
  require 'rubykov/markov_model'
2
2
  require 'rubykov/text_generator'
3
+ require 'rubykov/hidden_markov_model'
4
+ require 'rubykov/word_generator'
@@ -0,0 +1,58 @@
1
+ module Rubykov
2
+ class HiddenMarkovModel
3
+ def initialize(states, observations, start_probability, transition_probabilities, emission_probabilities)
4
+ @states = states
5
+ @observations = observations
6
+ @start_probability = start_probability
7
+ @transition_probabilities = transition_probabilities
8
+ @observation_probabilities = emission_probabilities
9
+ end
10
+
11
+ def most_likely_state_sequence(observation_sequence)
12
+ max_probabilities(observation_sequence).map(&:first)
13
+ end
14
+
15
+ def most_likely_state_sequence_probability(observation_sequence)
16
+ max_probabilities(observation_sequence).last.last
17
+ end
18
+
19
+ private
20
+
21
+ def max_probabilities(observation_sequence)
22
+ compute_viterbi_probabilities(observation_sequence.map(&:to_sym)).map do |probability|
23
+ probability.max_by { |k,v| v }
24
+ end
25
+ end
26
+
27
+ def compute_viterbi_probabilities(observations)
28
+ state_max_probabilities = []
29
+
30
+ observations.each_with_index do |observation, index|
31
+ state_max_probabilities[index] = {}
32
+ @states.each do |state|
33
+ state_max_probabilities[index][state] = 0
34
+ state_max_probabilities.first[state] = @start_probability[state] * @observation_probabilities[state][observations.first]
35
+ end
36
+ end
37
+
38
+ observations[1..-1].each_with_index do |observation, index|
39
+ @states.each do |state|
40
+ max_probability = state_max_probabilities[index].map { |previous_state, previous_probability| @transition_probabilities[previous_state][state] * previous_probability }.max
41
+ state_max_probabilities[index+1][state] = @observation_probabilities[state][observation] * max_probability
42
+ end
43
+ end
44
+
45
+ state_max_probabilities
46
+ end
47
+
48
+ def sample(probability_distribution)
49
+ random_value = rand
50
+
51
+ probability_ranges = probability_distribution.inject([0]) do |memo, p|
52
+ memo << p.last + memo.last
53
+ end
54
+
55
+ probability_distribution[probability_ranges.rindex { |x| x <= random_value }].first
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,44 @@
1
+ module Rubykov
2
+ class WordGenerator < MarkovModel
3
+ def initialize(order, training_data)
4
+ super(order, training_data)
5
+ end
6
+
7
+ def train(training_data)
8
+ add_data_to_model(training_data)
9
+ end
10
+
11
+ def word
12
+ chain.to_a.join('').capitalize
13
+ end
14
+
15
+ private
16
+
17
+ def massage_training_data(training_data)
18
+ training_data.map { |datum| datum.downcase.split('') + ['\n'] }
19
+ end
20
+
21
+ def add_data_to_model(training_data)
22
+ massage_training_data(training_data).each do |datum|
23
+ super(datum)
24
+ end
25
+ end
26
+
27
+ def chain_enumerator(seed_state = states.sample)
28
+ Enumerator.new do |output|
29
+ current_state = seed_state
30
+ current_state.each do |word|
31
+ output << word
32
+ end
33
+
34
+ loop do
35
+ break if @representation[current_state].nil?
36
+ next_letter = @representation[current_state].sample
37
+ break if next_letter == '\\n'
38
+ output << next_letter
39
+ current_state = current_state.last(@order-1) + [next_letter]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubykov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Hemsley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-10 00:00:00.000000000 Z
11
+ date: 2017-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -38,8 +38,10 @@ extra_rdoc_files: []
38
38
  files:
39
39
  - README.md
40
40
  - lib/rubykov.rb
41
+ - lib/rubykov/hidden_markov_model.rb
41
42
  - lib/rubykov/markov_model.rb
42
43
  - lib/rubykov/text_generator.rb
44
+ - lib/rubykov/word_generator.rb
43
45
  - license.md
44
46
  homepage: https://gitlab.com/ehemsley/rubykov
45
47
  licenses:
@@ -61,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
63
  version: '0'
62
64
  requirements: []
63
65
  rubyforge_project:
64
- rubygems_version: 2.2.2
66
+ rubygems_version: 2.5.1
65
67
  signing_key:
66
68
  specification_version: 4
67
69
  summary: Sensible, easy Markov models in Ruby.