weighted_sampler 1.0.3 → 1.1.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
  SHA256:
3
- metadata.gz: cf378756434bce6feff8b33723b735706d4324977a34f0f86e2c8ebb82bf33d2
4
- data.tar.gz: 3665445824ffe81a739c4fa3c67183bf217fee8233e7d33680e2cfdb0dbbacd0
3
+ metadata.gz: 418175c950561e4d8afe70b6d19be4c9957107d79416f6b5600dc83bb51f57f2
4
+ data.tar.gz: 1d1f5bac8a18c12fa86027ca024a3705fe39a1f65c0e39b69401854e34ea9626
5
5
  SHA512:
6
- metadata.gz: 3c90d9fb14d935b7bacb06965a10e31515b0cb4e44a535b08e5e4d93e8ff78e712913079f30fedb1bd0d588531f9cafba4008b05a25d2e8624133338bdc6ee01
7
- data.tar.gz: ec6ca14ac634db2989b08a8c35c4bb59c4bdfc00e554aa34dc7b99b2ee25c9ed66c96a9a64368b07ede953866ba77520fa4aba75890f68fdc8ccc875a54b92e1
6
+ metadata.gz: '0182411300d8c5e8355d376658b0d6cc58ac8ca973c9b06962ff45280c45b70ce4d32754f3d0afab212349e1dee0f05596805d462eecb302ddb7b66ee9426ab4'
7
+ data.tar.gz: 3df0c7ebecc6b17f2f12f58a059772889d93f852cee6ba302cd03969124be5ca3b2c5c694796077b0d705f38bae8060eec9a83ea5d8f9603767024c471e60e16
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'weighted_sampler/version'
4
+ # require 'pry'
5
+
4
6
  module WeightedSampler
5
7
 
6
8
  # sum of floats are never stable enough to guarantee exact equality to 1
@@ -12,33 +14,34 @@ module WeightedSampler
12
14
  @random = Random.new(seed) unless seed.nil?
13
15
 
14
16
  if enum.is_a?(Hash)
15
- @p_ranges = normalized_ranges(enum.values, skip_normalization)
17
+ @p_margins = normalized_margins(enum.values, skip_normalization)
16
18
  @keys = enum.keys
17
19
  elsif enum.is_a?(Array)
18
- @p_ranges = normalized_ranges(enum, skip_normalization)
20
+ @p_margins = normalized_margins(enum, skip_normalization)
19
21
  @keys = [*0...enum.size]
20
22
  end
21
23
 
22
- return unless @p_ranges.nil? || @keys.nil? || @keys.empty?
24
+ return unless @p_margins.nil? || @keys.nil? || @keys.empty?
25
+
23
26
  raise ArgumentError, 'input structure must be a non-empty Hash or Array'
24
27
  end
25
28
 
26
29
  def sample
27
30
  pick = @random ? @random.rand : rand
28
31
 
29
- idx = @p_ranges.index { |range| range.include? pick }
30
- @keys[idx] if idx
32
+ idx = @p_margins.find_index { |margin| pick < margin }
33
+ idx ||= @p_margins.count - 1 # safe assignment if last margin was not good enough
34
+
35
+ @keys[idx]
31
36
  end
32
37
 
33
38
  private
34
39
 
35
- def normalized_ranges(array, skip_normalization)
40
+ def normalized_margins(array, skip_normalization)
36
41
  raise ArgumentError, 'weights can be only positive' if array.any?(&:negative?)
37
42
 
38
- probabilities = array
39
- probabilities = normalize_probabilities(probabilities) unless skip_normalization
40
-
41
- array_to_ranges probabilities
43
+ probabilities = skip_normalization ? array : normalize_probabilities(array)
44
+ incremental_margins probabilities
42
45
  end
43
46
 
44
47
  def normalize_probabilities(array)
@@ -47,18 +50,20 @@ module WeightedSampler
47
50
  array.map { |el| el / sum }
48
51
  end
49
52
 
50
- def array_to_ranges(array)
53
+ # convert probs like [0.1, 0.2, 0.3, 0.4]
54
+ # to incremental margins [0.1, 0.3, 0.6, 1.0]
55
+ def incremental_margins(array)
51
56
  start = 0.0
52
- ranges = array.map do |v|
53
- p_start = start
54
- start += v
57
+ margins = array.map do |v|
58
+ res = v + start
59
+ start = res
55
60
 
56
- (p_start...v + p_start)
61
+ res
57
62
  end
58
63
 
59
64
  raise 'normalized probabilities total is not 1' if (start - 1.0).abs > ERROR_ALLOWANCE
60
65
 
61
- ranges
66
+ margins
62
67
  end
63
68
 
64
69
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WeightedSampler
4
- VERSION = '1.0.3'.freeze
4
+ VERSION = '1.1.0'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weighted_sampler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleksiy Babich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-26 00:00:00.000000000 Z
11
+ date: 2019-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,8 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
85
  - !ruby/object:Gem::Version
86
86
  version: '0'
87
87
  requirements: []
88
- rubyforge_project:
89
- rubygems_version: 2.7.6
88
+ rubygems_version: 3.0.1
90
89
  signing_key:
91
90
  specification_version: 4
92
91
  summary: Weighted Sampler helps you to pick a random samples from a collection with