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.
@@ -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
@@ -0,0 +1,6 @@
1
+ module ABBA
2
+ end
3
+
4
+ require 'abba/bayes'
5
+ require 'abba/math'
6
+ require 'abba/ab_test'
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module ABBA
2
+ VERSION = '0.1.0'
3
+ end
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: []