field_test 0.7.0 → 0.8.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: cb5a6ce72e7c8ac19e10ad432f9feb6f31a8cbcc31c8f57585cca0661b0ce66a
4
- data.tar.gz: 193c9cebdb015e685682c347ea83cccf91b9bf8ea429d74410c435dfdcaf8304
3
+ metadata.gz: 70d3fdf1a39390631baa12589f108d99852f02009daaaf9ca0d50756630bb3c9
4
+ data.tar.gz: ba0700b9b9eaed0610d7343e7dff096e6e0e3572919832e8deae189fe5833df8
5
5
  SHA512:
6
- metadata.gz: f7bc7a8c2ff54db35b0ebd5f243a150489e5cab41d0213fc0f8ac5b79aeb89bcfbddf49a9f8d64cd924d816521e01e871991d06fe5204e3ea16d178f44a93d14
7
- data.tar.gz: b37b79f2488a5d3dbc1aeaa5a588adde06d6f5c2dcd07f4390f8db24cdae7d53d879efb4e19451512e29b47cd0a96d8562992323c99fd68135143d9df10a4c11
6
+ metadata.gz: 4f6c1c6c82b05b4373ef899c1c53ee4d788eb5d9eabc90d827db7e04ee66ec8bc398047f2d080be14af031fd461632078cfa88dcbe9a776ef64d0647f7854cbe
7
+ data.tar.gz: 768f3018bbb87d22f4d39b41b09ec02914f2a7c4de679236675a2280fbee7bf90c64f09e4645f8966dbc79204ed267a2dcf03df6cfecc432b3103e15eeb5a4cd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.8.0 (2025-05-05)
2
+
3
+ - Dropped support for Ruby < 3.2 and Rails < 7.1
4
+
1
5
  ## 0.7.0 (2024-10-22)
2
6
 
3
7
  - Added support for Trilogy
data/README.md CHANGED
@@ -189,8 +189,8 @@ Keep track of when experiments started and ended. Use any format `Time.parse` ac
189
189
  ```yml
190
190
  experiments:
191
191
  button_color:
192
- started_at: Dec 1, 2016 8 am PST
193
- ended_at: Dec 8, 2016 2 pm PST
192
+ started_at: Dec 1, 2024 8 am PST
193
+ ended_at: Dec 8, 2024 2 pm PST
194
194
  ```
195
195
 
196
196
  Add a friendlier name and description with:
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * BayesTest C++ v0.1.0
2
+ * BayesTest C++ v0.1.2
3
3
  * https://github.com/ankane/bayestest-cpp
4
4
  * MIT License
5
5
  */
@@ -11,6 +11,8 @@
11
11
 
12
12
  namespace bayestest {
13
13
 
14
+ namespace {
15
+
14
16
  double logbeta(double a, double b) {
15
17
  return std::lgamma(a) + std::lgamma(b) - std::lgamma(a + b);
16
18
  }
@@ -21,7 +23,7 @@ double prob_b_beats_a(int alpha_a, int beta_a, int alpha_b, int beta_b) {
21
23
  double beta_ba = beta_b + beta_a;
22
24
 
23
25
  for (auto i = 0; i < alpha_b; i++) {
24
- total += exp(logbeta(alpha_a + i, beta_ba) - log(beta_b + i) - logbeta(1 + i, beta_b) - logbeta_aa_ba);
26
+ total += std::exp(logbeta(alpha_a + i, beta_ba) - std::log(beta_b + i) - logbeta(1 + i, beta_b) - logbeta_aa_ba);
25
27
  }
26
28
 
27
29
  return total;
@@ -36,7 +38,7 @@ double prob_c_beats_ab(int alpha_a, int beta_a, int alpha_b, int beta_b, int alp
36
38
  log_bb_j_logbeta_j_bb.reserve(alpha_b);
37
39
 
38
40
  for (auto j = 0; j < alpha_b; j++) {
39
- log_bb_j_logbeta_j_bb.push_back(log(beta_b + j) + logbeta(1 + j, beta_b));
41
+ log_bb_j_logbeta_j_bb.push_back(std::log(beta_b + j) + logbeta(1 + j, beta_b));
40
42
  }
41
43
 
42
44
  double abc = beta_a + beta_b + beta_c;
@@ -48,15 +50,17 @@ double prob_c_beats_ab(int alpha_a, int beta_a, int alpha_b, int beta_b, int alp
48
50
  }
49
51
 
50
52
  for (auto i = 0; i < alpha_a; i++) {
51
- double sum_i = -log(beta_a + i) - logbeta(1 + i, beta_a) - logbeta_ac_bc;
53
+ double sum_i = -std::log(beta_a + i) - logbeta(1 + i, beta_a) - logbeta_ac_bc;
52
54
 
53
55
  for (auto j = 0; j < alpha_b; j++) {
54
- total += exp(sum_i + logbeta_ac_i_j[i + j] - log_bb_j_logbeta_j_bb[j]);
56
+ total += std::exp(sum_i + logbeta_ac_i_j[i + j] - log_bb_j_logbeta_j_bb[j]);
55
57
  }
56
58
  }
57
59
 
58
- return 1 - prob_b_beats_a(alpha_c, beta_c, alpha_a, beta_a) -
59
- prob_b_beats_a(alpha_c, beta_c, alpha_b, beta_b) + total;
60
+ return 1
61
+ - prob_b_beats_a(alpha_c, beta_c, alpha_a, beta_a)
62
+ - prob_b_beats_a(alpha_c, beta_c, alpha_b, beta_b)
63
+ + total;
60
64
  }
61
65
 
62
66
  double prob_d_beats_abc(int alpha_a, int beta_a, int alpha_b, int beta_b, int alpha_c, int beta_c, int alpha_d, int beta_d) {
@@ -68,14 +72,14 @@ double prob_d_beats_abc(int alpha_a, int beta_a, int alpha_b, int beta_b, int al
68
72
  log_bb_j_logbeta_j_bb.reserve(alpha_b);
69
73
 
70
74
  for (auto j = 0; j < alpha_b; j++) {
71
- log_bb_j_logbeta_j_bb.push_back(log(beta_b + j) + logbeta(1 + j, beta_b));
75
+ log_bb_j_logbeta_j_bb.push_back(std::log(beta_b + j) + logbeta(1 + j, beta_b));
72
76
  }
73
77
 
74
78
  std::vector<double> log_bc_k_logbeta_k_bc;
75
79
  log_bc_k_logbeta_k_bc.reserve(alpha_c);
76
80
 
77
81
  for (auto k = 0; k < alpha_c; k++) {
78
- log_bc_k_logbeta_k_bc.push_back(log(beta_c + k) + logbeta(1 + k, beta_c));
82
+ log_bc_k_logbeta_k_bc.push_back(std::log(beta_c + k) + logbeta(1 + k, beta_c));
79
83
  }
80
84
 
81
85
  double abcd = beta_a + beta_b + beta_c + beta_d;
@@ -87,36 +91,38 @@ double prob_d_beats_abc(int alpha_a, int beta_a, int alpha_b, int beta_b, int al
87
91
  }
88
92
 
89
93
  for (auto i = 0; i < alpha_a; i++) {
90
- double sum_i = -log(beta_a + i) - logbeta(1 + i, beta_a) - logbeta_ad_bd;
94
+ double sum_i = -std::log(beta_a + i) - logbeta(1 + i, beta_a) - logbeta_ad_bd;
91
95
 
92
96
  for (auto j = 0; j < alpha_b; j++) {
93
97
  double sum_j = sum_i - log_bb_j_logbeta_j_bb[j];
94
98
 
95
99
  for (auto k = 0; k < alpha_c; k++) {
96
- total += exp(sum_j + logbeta_bd_i_j_k[i + j + k] - log_bc_k_logbeta_k_bc[k]);
100
+ total += std::exp(sum_j + logbeta_bd_i_j_k[i + j + k] - log_bc_k_logbeta_k_bc[k]);
97
101
  }
98
102
  }
99
103
  }
100
104
 
101
- return 1 - prob_b_beats_a(alpha_a, beta_a, alpha_d, beta_d) -
102
- prob_b_beats_a(alpha_b, beta_b, alpha_d, beta_d) -
103
- prob_b_beats_a(alpha_c, beta_c, alpha_d, beta_d) +
104
- prob_c_beats_ab(alpha_a, beta_a, alpha_b, beta_b, alpha_d, beta_d) +
105
- prob_c_beats_ab(alpha_a, beta_a, alpha_c, beta_c, alpha_d, beta_d) +
106
- prob_c_beats_ab(alpha_b, beta_b, alpha_c, beta_c, alpha_d, beta_d) - total;
105
+ return 1
106
+ - prob_b_beats_a(alpha_a, beta_a, alpha_d, beta_d)
107
+ - prob_b_beats_a(alpha_b, beta_b, alpha_d, beta_d)
108
+ - prob_b_beats_a(alpha_c, beta_c, alpha_d, beta_d)
109
+ + prob_c_beats_ab(alpha_a, beta_a, alpha_b, beta_b, alpha_d, beta_d)
110
+ + prob_c_beats_ab(alpha_a, beta_a, alpha_c, beta_c, alpha_d, beta_d)
111
+ + prob_c_beats_ab(alpha_b, beta_b, alpha_c, beta_c, alpha_d, beta_d)
112
+ - total;
107
113
  }
108
114
 
109
115
  double prob_1_beats_2(int alpha_1, int beta_1, int alpha_2, int beta_2) {
110
116
  double total = 0.0;
111
- double log_b1 = log(beta_1);
112
- double a2_log_b2 = alpha_2 * log(beta_2);
113
- double log_b1_b2 = log(beta_1 + beta_2);
117
+ double log_b1 = std::log(beta_1);
118
+ double a2_log_b2 = alpha_2 * std::log(beta_2);
119
+ double log_b1_b2 = std::log(beta_1 + beta_2);
114
120
 
115
121
  for (auto k = 0; k < alpha_1; k++) {
116
- total += exp(k * log_b1 +
122
+ total += std::exp(k * log_b1 +
117
123
  a2_log_b2 -
118
124
  (k + alpha_2) * log_b1_b2 -
119
- log(k + alpha_2) -
125
+ std::log(k + alpha_2) -
120
126
  logbeta(k + 1, alpha_2));
121
127
  }
122
128
 
@@ -126,33 +132,40 @@ double prob_1_beats_2(int alpha_1, int beta_1, int alpha_2, int beta_2) {
126
132
  double prob_1_beats_23(int alpha_1, int beta_1, int alpha_2, int beta_2, int alpha_3, int beta_3) {
127
133
  double total = 0.0;
128
134
 
129
- double log_b1_b2_b3 = log(beta_1 + beta_2 + beta_3);
130
- double a1_log_b1 = alpha_1 * log(beta_1);
131
- double log_b2 = log(beta_2);
132
- double log_b3 = log(beta_3);
135
+ double log_b1_b2_b3 = std::log(beta_1 + beta_2 + beta_3);
136
+ double a1_log_b1 = alpha_1 * std::log(beta_1);
137
+ double log_b2 = std::log(beta_2);
138
+ double log_b3 = std::log(beta_3);
133
139
  double loggamma_a1 = std::lgamma(alpha_1);
134
140
 
135
141
  for (auto k = 0; k < alpha_2; k++) {
136
142
  double sum_k = a1_log_b1 + k * log_b2 - std::lgamma(k + 1);
137
143
 
138
144
  for (auto l = 0; l < alpha_3; l++) {
139
- total += exp(sum_k + l * log_b3
145
+ total += std::exp(sum_k + l * log_b3
140
146
  - (k + l + alpha_1) * log_b1_b2_b3
141
147
  + std::lgamma(k + l + alpha_1) - std::lgamma(l + 1) - loggamma_a1);
142
148
  }
143
149
  }
144
150
 
145
- return 1.0 - prob_1_beats_2(alpha_2, beta_2, alpha_1, beta_1)
146
- - prob_1_beats_2(alpha_3, beta_3, alpha_1, beta_1) + total;
151
+ return 1
152
+ - prob_1_beats_2(alpha_2, beta_2, alpha_1, beta_1)
153
+ - prob_1_beats_2(alpha_3, beta_3, alpha_1, beta_1)
154
+ + total;
155
+ }
156
+
147
157
  }
148
158
 
159
+ /// A test for binary outcomes.
149
160
  class BinaryTest {
150
161
  public:
162
+ /// Adds a new variant.
151
163
  void add(int participants, int conversions) {
152
164
  variants.emplace_back(participants, conversions);
153
165
  }
154
166
 
155
- std::vector<double> probabilities() {
167
+ /// Returns the winning probability of each variant.
168
+ std::vector<double> probabilities() const {
156
169
  std::vector<double> probs;
157
170
  probs.reserve(variants.size());
158
171
 
@@ -233,7 +246,7 @@ public:
233
246
 
234
247
  private:
235
248
  struct Variant {
236
- Variant(int participants, int conversions) : participants(participants), conversions(conversions) {};
249
+ Variant(int participants, int conversions) : participants(participants), conversions(conversions) {}
237
250
  int participants;
238
251
  int conversions;
239
252
  };
@@ -241,13 +254,16 @@ private:
241
254
  std::vector<Variant> variants;
242
255
  };
243
256
 
257
+ /// A test for count data.
244
258
  class CountTest {
245
259
  public:
260
+ /// Adds a new variant.
246
261
  void add(int events, int exposure) {
247
262
  variants.emplace_back(events, exposure);
248
263
  }
249
264
 
250
- std::vector<double> probabilities() {
265
+ /// Returns the winning probability of each variant.
266
+ std::vector<double> probabilities() const {
251
267
  std::vector<double> probs;
252
268
  probs.reserve(variants.size());
253
269
 
@@ -302,7 +318,7 @@ public:
302
318
 
303
319
  private:
304
320
  struct Variant {
305
- Variant(int events, int exposure) : events(events), exposure(exposure) {};
321
+ Variant(int events, int exposure) : events(events), exposure(exposure) {}
306
322
  int events;
307
323
  int exposure;
308
324
  };
@@ -1,3 +1,3 @@
1
1
  module FieldTest
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: field_test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-10-22 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: railties
@@ -16,28 +15,28 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '7'
18
+ version: '7.1'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '7'
25
+ version: '7.1'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: activerecord
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - ">="
32
31
  - !ruby/object:Gem::Version
33
- version: '7'
32
+ version: '7.1'
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
- version: '7'
39
+ version: '7.1'
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: browser
43
42
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +65,6 @@ dependencies:
66
65
  - - ">="
67
66
  - !ruby/object:Gem::Version
68
67
  version: 4.3.3
69
- description:
70
68
  email: andrew@ankane.org
71
69
  executables: []
72
70
  extensions:
@@ -109,7 +107,6 @@ homepage: https://github.com/ankane/field_test
109
107
  licenses:
110
108
  - MIT
111
109
  metadata: {}
112
- post_install_message:
113
110
  rdoc_options: []
114
111
  require_paths:
115
112
  - lib
@@ -117,15 +114,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
114
  requirements:
118
115
  - - ">="
119
116
  - !ruby/object:Gem::Version
120
- version: '3.1'
117
+ version: '3.2'
121
118
  required_rubygems_version: !ruby/object:Gem::Requirement
122
119
  requirements:
123
120
  - - ">="
124
121
  - !ruby/object:Gem::Version
125
122
  version: '0'
126
123
  requirements: []
127
- rubygems_version: 3.5.16
128
- signing_key:
124
+ rubygems_version: 3.6.7
129
125
  specification_version: 4
130
126
  summary: A/B testing for Rails
131
127
  test_files: []