abba 0.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 +7 -0
- data/lib/abba.rb +6 -0
- data/lib/abba/ab_test.rb +84 -0
- data/lib/abba/bayes.rb +38 -0
- data/lib/abba/math.rb +40 -0
- data/lib/abba/version.rb +3 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 88201a4cd5a8b7ea2eb7a28e31b5a5cd7ac86fc9
|
4
|
+
data.tar.gz: c1f24a23ff75f646ee43f7da4368e807c40f7a73
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 76adccef44a5bb5697166d449d2a8bdd285c3bbada18dce1b884d61b84841ab30a3e22e9f11d0ec47338709ac804972277468f54f8e048ca64fd8455c1f0390d
|
7
|
+
data.tar.gz: b8922e2fa9e9678062e8d709b7171a482bd9e225381fec156a720fc9ab19ed64b01b17c971b8b9a8fa44dbf182ac2d96bbde28c27515489d0a55c8c911e054da
|
data/lib/abba.rb
ADDED
data/lib/abba/ab_test.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
module ABBA
|
2
|
+
class ABTest
|
3
|
+
def initialize(variant_a:, variant_b:, test: Bayes::BinaryOutcomeTest)
|
4
|
+
@variant_a = ABTest::Variant.new(variant_a)
|
5
|
+
@variant_b = ABTest::Variant.new(variant_b)
|
6
|
+
@test = test
|
7
|
+
end
|
8
|
+
|
9
|
+
def choose_a?
|
10
|
+
@test.new(@variant_a, @variant_b).call
|
11
|
+
end
|
12
|
+
|
13
|
+
def choose_b?
|
14
|
+
@test.new(@variant_b, @variant_a).call
|
15
|
+
end
|
16
|
+
|
17
|
+
def probabilities
|
18
|
+
p = choose_a?
|
19
|
+
[p, 1-p]
|
20
|
+
end
|
21
|
+
|
22
|
+
class Variant
|
23
|
+
def initialize(args={})
|
24
|
+
@successes = args[:successes]
|
25
|
+
@failures = args[:failures]
|
26
|
+
@size = args[:size]
|
27
|
+
raise ArgumentError, "Invalid ABTest variant, you must pass 2 or more of :successes, :failures, :size and successes + failures = size" unless validate
|
28
|
+
end
|
29
|
+
|
30
|
+
def successes
|
31
|
+
@successes ||= calculate_successes
|
32
|
+
end
|
33
|
+
|
34
|
+
def failures
|
35
|
+
@failures ||= calculate_failures
|
36
|
+
end
|
37
|
+
|
38
|
+
def size
|
39
|
+
@size ||= calculate_size
|
40
|
+
end
|
41
|
+
|
42
|
+
def success_rate
|
43
|
+
successes/size.to_f
|
44
|
+
end
|
45
|
+
|
46
|
+
def failure_rate
|
47
|
+
failures/size.to_f
|
48
|
+
end
|
49
|
+
|
50
|
+
def ==(other)
|
51
|
+
size == other.size && successes == other.successes && failures == other.failures
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def has_successes?
|
56
|
+
!!successes
|
57
|
+
end
|
58
|
+
|
59
|
+
def has_failures?
|
60
|
+
!!failures
|
61
|
+
end
|
62
|
+
|
63
|
+
def has_size?
|
64
|
+
!!size
|
65
|
+
end
|
66
|
+
|
67
|
+
def calculate_successes
|
68
|
+
@size - @failures if @size && @failures
|
69
|
+
end
|
70
|
+
|
71
|
+
def calculate_failures
|
72
|
+
@size - @successes if @size && @successes
|
73
|
+
end
|
74
|
+
|
75
|
+
def calculate_size
|
76
|
+
@successes + @failures if @successes && @failures
|
77
|
+
end
|
78
|
+
|
79
|
+
def validate
|
80
|
+
has_successes? && has_failures? && has_size? && (successes + failures == size)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/abba/bayes.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module ABBA
|
2
|
+
module Bayes
|
3
|
+
class BinaryOutcomeTest
|
4
|
+
def initialize(variant_a, variant_b)
|
5
|
+
@variant_a = variant_a
|
6
|
+
@variant_b = variant_b
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
total = 0.0
|
11
|
+
|
12
|
+
(0..(alpha_a-1)).each do |i|
|
13
|
+
log_contribution = Math.lbeta(alpha_b+i, beta_a+beta_b) - Math.log(beta_a+i) - Math.lbeta(1+i, beta_a) - Math.lbeta(alpha_b, beta_b)
|
14
|
+
total += Math.exp(log_contribution)
|
15
|
+
end
|
16
|
+
|
17
|
+
total
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def alpha_a
|
22
|
+
@variant_a.successes + 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def beta_a
|
26
|
+
@variant_a.failures + 1
|
27
|
+
end
|
28
|
+
|
29
|
+
def alpha_b
|
30
|
+
@variant_b.successes + 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def beta_b
|
34
|
+
@variant_b.failures + 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/abba/math.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module ABBA
|
4
|
+
module Math
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def exp(x)
|
8
|
+
::Math.exp(x)
|
9
|
+
end
|
10
|
+
|
11
|
+
def log(x)
|
12
|
+
::Math.log(x)
|
13
|
+
end
|
14
|
+
|
15
|
+
def gamma(x)
|
16
|
+
::Math.gamma(x)
|
17
|
+
end
|
18
|
+
|
19
|
+
def lgamma(x)
|
20
|
+
::Math.lgamma(x)
|
21
|
+
end
|
22
|
+
|
23
|
+
def beta(x,y)
|
24
|
+
(gamma(x)*gamma(y))/(gamma(x+y))
|
25
|
+
end
|
26
|
+
|
27
|
+
def lbeta(x,y)
|
28
|
+
lgamma_x, sign_gamma_x = lgamma(x)
|
29
|
+
lgamma_y, sign_gamma_y = lgamma(y)
|
30
|
+
lgamma_xy, sign_gamma_xy = lgamma(x+y)
|
31
|
+
|
32
|
+
if (sign_gamma_x * sign_gamma_y * sign_gamma_xy) == 1
|
33
|
+
lgamma_x + lgamma_y - lgamma_xy
|
34
|
+
else
|
35
|
+
raise ::Math::DomainError, 'Numerical argument is out of domain - "lbeta"'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/abba/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: abba
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kyle Tate
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.8'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description:
|
42
|
+
email: kbt.tate@gmail.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- lib/abba.rb
|
48
|
+
- lib/abba/ab_test.rb
|
49
|
+
- lib/abba/bayes.rb
|
50
|
+
- lib/abba/math.rb
|
51
|
+
- lib/abba/version.rb
|
52
|
+
homepage: http://github.com/infiton/abba
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata: {}
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 2.4.5.1
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: Bayesian A/B Testing
|
76
|
+
test_files: []
|