tiny_outcome 2.1.0 → 3.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 +4 -4
- data/lib/tiny_outcome.rb +58 -21
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e887122fe969136656c57bf1e8a240df3500f0120694891be4f9ba26cf9c694
|
4
|
+
data.tar.gz: 92e30c4c3c72afc4942181ede0badc1865b297c0444a1c7ec7cce272e4a7dac8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31bf45e93abd24309b440599f7006573dd6b2beb19a588234b6f15aaed4334bde062b252f8bdecf2a7f8b72fe3a42def7a55d38a225b8e37cb19af2dfc375977
|
7
|
+
data.tar.gz: b828c61ee05e08de9041bdb5b17a95005ef2cf315419bd3806dc9feec2efb5ba2138231bd8ff9d4bc74e5d02079848c4356d0dc779d02709a12623cccc6ce66d
|
data/lib/tiny_outcome.rb
CHANGED
@@ -30,7 +30,12 @@ class TinyOutcome
|
|
30
30
|
:samples,
|
31
31
|
:warmth,
|
32
32
|
:warmup,
|
33
|
-
:
|
33
|
+
:probability,
|
34
|
+
:one_count,
|
35
|
+
:value,
|
36
|
+
:min,
|
37
|
+
:max,
|
38
|
+
:avg
|
34
39
|
|
35
40
|
WARM_FULL = :full
|
36
41
|
WARM_TWO_THIRDS = :two_thirds
|
@@ -44,9 +49,15 @@ class TinyOutcome
|
|
44
49
|
# samples that we can trust the probability output
|
45
50
|
def initialize(precision, warmup=WARM_FULL)
|
46
51
|
@precision = precision
|
52
|
+
@probability = 0.0
|
53
|
+
@one_count = 0
|
47
54
|
@samples = 0
|
55
|
+
@min = -1.0
|
56
|
+
@max = -1.0
|
57
|
+
@avg = -1.0
|
48
58
|
@warmth = 0
|
49
|
-
@value = 0
|
59
|
+
@value = [0] * @precision
|
60
|
+
@value_index = 0
|
50
61
|
@warmup = case warmup
|
51
62
|
when WARM_FULL then precision
|
52
63
|
when WARM_TWO_THIRDS then (precision / 3) * 2
|
@@ -59,35 +70,37 @@ class TinyOutcome
|
|
59
70
|
end
|
60
71
|
end
|
61
72
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
73
|
+
def numeric_value
|
74
|
+
(full? ? @value.rotate(@value_index) : @value)[..(samples-1)].join.to_i(2)
|
75
|
+
end
|
76
|
+
|
77
|
+
# add a sample to the historic outcomes
|
66
78
|
def <<(sample)
|
67
79
|
raise "Invalid sample: #{sample}" unless sample == 0 || sample == 1
|
68
80
|
|
69
|
-
|
81
|
+
removing_one = full? && @value[(@value_index + 1) % @precision] == 1
|
82
|
+
|
83
|
+
@value[@value_index] = sample
|
84
|
+
@value_index = (@value_index + 1) % @precision
|
70
85
|
@warmth += 1 unless warmth == warmup
|
71
|
-
@samples += 1 unless
|
86
|
+
@samples += 1 unless full?
|
87
|
+
|
88
|
+
# percentage of 1s out of the existing samples
|
89
|
+
#
|
90
|
+
# number of 1s
|
91
|
+
# probabilty = ---------------
|
92
|
+
# total samples
|
93
|
+
@one_count -= 1 if removing_one
|
94
|
+
@one_count += 1 if sample == 1
|
95
|
+
@probability = @one_count / samples.to_f
|
72
96
|
|
73
|
-
value
|
97
|
+
@value
|
74
98
|
end
|
75
99
|
|
76
100
|
# true if #probability is >= percentage
|
77
101
|
# false otherwise
|
78
102
|
def winner_at?(percentage)
|
79
|
-
probability >= percentage
|
80
|
-
end
|
81
|
-
|
82
|
-
# float: 0.0-1.0
|
83
|
-
# percentage of 1s out of the existing samples
|
84
|
-
#
|
85
|
-
# number of 1s
|
86
|
-
# probabilty = ---------------
|
87
|
-
# total samples
|
88
|
-
def probability
|
89
|
-
return 0.0 if samples == 0
|
90
|
-
value.to_s(2).count('1') / samples.to_f
|
103
|
+
@probability >= percentage
|
91
104
|
end
|
92
105
|
|
93
106
|
# true if we've received at least warmup number of samples
|
@@ -107,6 +120,30 @@ class TinyOutcome
|
|
107
120
|
samples == precision
|
108
121
|
end
|
109
122
|
|
123
|
+
# updates, and memoizes, the min/max/avg numbers. if you read the min/max/avg
|
124
|
+
# attributes you are getting the MEMOIZED values.
|
125
|
+
def update_stats!
|
126
|
+
return if @samples == 0
|
127
|
+
|
128
|
+
@min = 1.0
|
129
|
+
@max = 0.0
|
130
|
+
@avg = 0.0
|
131
|
+
|
132
|
+
sum = 0.0
|
133
|
+
raw = (full? ? @value.rotate(@value_index) : @value)[..(samples-1)]
|
134
|
+
group_size = [@samples, 100].min
|
135
|
+
num_groups = @samples - group_size
|
136
|
+
raw.each_cons(group_size) do |samples_group|
|
137
|
+
curr = samples_group.count(1) / samples.to_f
|
138
|
+
sum += curr
|
139
|
+
|
140
|
+
@min = curr if curr < @min
|
141
|
+
@max = curr if curr > @max
|
142
|
+
end
|
143
|
+
|
144
|
+
@avg = sum / (@num_groups.to_f + 1.0)
|
145
|
+
end
|
146
|
+
|
110
147
|
# convenient way to see what's up
|
111
148
|
def to_hash
|
112
149
|
[:value,
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_outcome
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Lunt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: m
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: minitest
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|