require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom')) module Fathom class PlausibleRange < Fathom::Node include NumericMethods attr_reader :upper_bound, :lower_bound, :confidence_interval, :hard_lower_bound, :hard_upper_bound def initialize(opts={}) super(opts) opts = OptionsHash.new(opts) @hard_upper_bound = opts[:hard_upper_bound] @upper_bound = opts[:upper_bound] @upper_bound ||= opts[:max] @upper_bound ||= @hard_upper_bound @upper_bound = @hard_upper_bound if @upper_bound and @hard_upper_bound and @hard_upper_bound < @upper_bound raise ArgumentError, "Must provide an upper bound." unless @upper_bound @hard_lower_bound = opts[:hard_lower_bound] @lower_bound = opts[:lower_bound] @lower_bound ||= opts[:min] @lower_bound ||= @hard_lower_bound @lower_bound = @hard_lower_bound if @lower_bound and @hard_lower_bound and @hard_lower_bound > @lower_bound raise ArgumentError, "Must provide a lower bound." unless @lower_bound @confidence_interval = opts[:confidence_interval] @confidence_interval ||= opts[:ci] @confidence_interval ||= 0.9 end alias :min :lower_bound alias :max :upper_bound alias :ci :confidence_interval def midpoint @midpoint ||= lower_bound + (range / 2.0) end alias :mean :midpoint def range @range ||= upper_bound - lower_bound end def standard_deviation @standard_deviation ||= range / distribution.standard_deviations_under(confidence_interval) end alias :std :standard_deviation alias :sd :standard_deviation def rand value = get_rand until is_bounded?(value) do value = get_rand end value end def array_of_random_values(n=10) n.times.map {self.rand} end alias :to_a :array_of_random_values def vector_of_random_values(n=10) GSL::Vector.alloc(array_of_random_values(n)) end alias :to_v :vector_of_random_values protected def is_bounded?(value) return true unless hard_lower_bound or hard_upper_bound if hard_lower_bound and hard_upper_bound value >= hard_lower_bound and value <= hard_upper_bound elsif hard_lower_bound value >= hard_lower_bound elsif hard_upper_bound value <= hard_upper_bound end end # Uses the distribution system, but doesn't use a vector to determine the sd, mean, etc. # So keeping this part in-house. def get_rand distribution.rand(sd) + mean end end end if __FILE__ == $0 include Fathom # TODO: Is there anything you want to do to run this file on its own? # PlausibleRange.new end