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: []
         
     |