compsci 0.3.1.1 → 0.3.2.1
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 +4 -4
 - data/README.md +3 -3
 - data/VERSION +1 -1
 - data/compsci.gemspec +3 -3
 - data/lib/compsci/fit.rb +17 -0
 - data/lib/compsci/names/pokemon.rb +2 -2
 - data/lib/compsci/simplex/parse.rb +6 -2
 - data/lib/compsci/simplex.rb +17 -16
 - data/lib/compsci/timer.rb +61 -1
 - data/test/fit.rb +54 -16
 - metadata +14 -14
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 5a7f1f7282649dec4f08ef08ce3eb3b5b3b97183137624deaa9f20567650185a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 57081ef332e9adc6d3dbdc06b3ff2c9c76955d26b4fdd90402b7547b5544e0fd
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: cdb60b8e1230cdc175ac43afca1efe51bb163ce71dfb2cdd29ffa8ff8ab586456ec181dd46389d54b768edb360f5f9f56d6729bbd65ee86fcd7fa7acee0f417e
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 3f20b69bd337aebc862a7f40e1e1177386979f71065200fa18e4dd69bdefb3a382dd8cbd066903d2ba5793cf5c71acd9cd09b79088c4c15b38982b8196bfb0c2
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,7 +1,5 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            [](https://github.com/rickhull/compsci/actions/workflows/ci.yaml)
         
     | 
| 
       2 
2 
     | 
    
         
             
            [](https://badge.fury.io/rb/compsci)
         
     | 
| 
       3 
     | 
    
         
            -
            [](https://gemnasium.com/rickhull/compsci)
         
     | 
| 
       4 
     | 
    
         
            -
            [](https://hakiri.io/github/rickhull/compsci/master)
         
     | 
| 
       5 
3 
     | 
    
         | 
| 
       6 
4 
     | 
    
         
             
            # CompSci
         
     | 
| 
       7 
5 
     | 
    
         | 
| 
         @@ -213,6 +211,8 @@ alphabetical order. 
     | 
|
| 
       213 
211 
     | 
    
         | 
| 
       214 
212 
     | 
    
         
             
            ## [`Simplex`](lib/compsci/simplex.rb) class
         
     | 
| 
       215 
213 
     | 
    
         | 
| 
      
 214 
     | 
    
         
            +
            ### WORK IN PROGRESS; DO NOT USE
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
       216 
216 
     | 
    
         
             
            The [Simplex algorithm](https://en.wikipedia.org/wiki/Simplex_algorithm)
         
     | 
| 
       217 
217 
     | 
    
         
             
            is a technique for
         
     | 
| 
       218 
218 
     | 
    
         
             
            [Linear programming](https://en.wikipedia.org/wiki/Linear_programming).
         
     | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0.3. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.3.2.1
         
     | 
    
        data/compsci.gemspec
    CHANGED
    
    | 
         @@ -6,7 +6,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       6 
6 
     | 
    
         
             
              s.homepage = "https://github.com/rickhull/compsci"
         
     | 
| 
       7 
7 
     | 
    
         
             
              s.license = "LGPL-3.0"
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
              s.required_ruby_version = "~>  
     | 
| 
      
 9 
     | 
    
         
            +
              s.required_ruby_version = "~> 3.0"
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
              s.version = File.read(File.join(__dir__, 'VERSION')).chomp
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
         @@ -16,8 +16,8 @@ Gem::Specification.new do |s| 
     | 
|
| 
       16 
16 
     | 
    
         
             
              s.files += Dir['examples/**/*.rb']
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
              s.add_development_dependency "buildar", "~> 3.0"
         
     | 
| 
       19 
     | 
    
         
            -
              s.add_development_dependency "minitest", " 
     | 
| 
       20 
     | 
    
         
            -
              s.add_development_dependency "rake", " 
     | 
| 
      
 19 
     | 
    
         
            +
              s.add_development_dependency "minitest", "~> 5.0"
         
     | 
| 
      
 20 
     | 
    
         
            +
              s.add_development_dependency "rake", "~> 12.3" # CVE-2020-8130
         
     | 
| 
       21 
21 
     | 
    
         
             
              s.add_development_dependency "flog", "~> 0"
         
     | 
| 
       22 
22 
     | 
    
         
             
              s.add_development_dependency "flay", "~> 0"
         
     | 
| 
       23 
23 
     | 
    
         
             
              s.add_development_dependency "roodi", "~> 0"
         
     | 
    
        data/lib/compsci/fit.rb
    CHANGED
    
    | 
         @@ -153,5 +153,22 @@ module CompSci 
     | 
|
| 
       153 
153 
     | 
    
         | 
| 
       154 
154 
     | 
    
         
             
                  return Math.exp(a), b, self.error(xys) { |x| (Math.exp(a) * (x ** b)) }
         
     | 
| 
       155 
155 
     | 
    
         
             
                end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                def self.predict(model, a, b, x)
         
     | 
| 
      
 158 
     | 
    
         
            +
                  case model
         
     | 
| 
      
 159 
     | 
    
         
            +
                  when :constant
         
     | 
| 
      
 160 
     | 
    
         
            +
                    a
         
     | 
| 
      
 161 
     | 
    
         
            +
                  when :logarithmic
         
     | 
| 
      
 162 
     | 
    
         
            +
                    a + b * Math.log(x)
         
     | 
| 
      
 163 
     | 
    
         
            +
                  when :linear
         
     | 
| 
      
 164 
     | 
    
         
            +
                    a + b * x
         
     | 
| 
      
 165 
     | 
    
         
            +
                  when :exponential
         
     | 
| 
      
 166 
     | 
    
         
            +
                    a * Math::E ** (b * x)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  when :power
         
     | 
| 
      
 168 
     | 
    
         
            +
                    a * x ** b
         
     | 
| 
      
 169 
     | 
    
         
            +
                  else
         
     | 
| 
      
 170 
     | 
    
         
            +
                    raise("unknown model: #{model}")
         
     | 
| 
      
 171 
     | 
    
         
            +
                  end
         
     | 
| 
      
 172 
     | 
    
         
            +
                end
         
     | 
| 
       156 
173 
     | 
    
         
             
              end
         
     | 
| 
       157 
174 
     | 
    
         
             
            end
         
     | 
| 
         @@ -34,8 +34,8 @@ module CompSci::Names::Pokemon 
     | 
|
| 
       34 
34 
     | 
    
         
             
              # a hash of all the names, keyed by the first letter
         
     | 
| 
       35 
35 
     | 
    
         
             
              def self.read_hash(path: DATAFILE)
         
     | 
| 
       36 
36 
     | 
    
         
             
                hsh = Hash.new { |h, k| h[k] = [] }
         
     | 
| 
       37 
     | 
    
         
            -
                File.open(path).each_line { | 
     | 
| 
       38 
     | 
    
         
            -
                  hsh[ 
     | 
| 
      
 37 
     | 
    
         
            +
                File.open(path).each_line { |line|
         
     | 
| 
      
 38 
     | 
    
         
            +
                  hsh[line.chr] << line.chomp
         
     | 
| 
       39 
39 
     | 
    
         
             
                }
         
     | 
| 
       40 
40 
     | 
    
         
             
                hsh
         
     | 
| 
       41 
41 
     | 
    
         
             
              end
         
     | 
| 
         @@ -82,7 +82,11 @@ class CompSci::Simplex 
     | 
|
| 
       82 
82 
     | 
    
         
             
                end
         
     | 
| 
       83 
83 
     | 
    
         
             
              end
         
     | 
| 
       84 
84 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
              def self.problem( 
     | 
| 
      
 85 
     | 
    
         
            +
              def self.problem(**kwargs)
         
     | 
| 
      
 86 
     | 
    
         
            +
                self.new(*self.get_params(**kwargs))
         
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
              def self.get_params(maximize: nil, constraints: [], **kwargs)
         
     | 
| 
       86 
90 
     | 
    
         
             
                if maximize
         
     | 
| 
       87 
91 
     | 
    
         
             
                  expr, maximize = maximize, true
         
     | 
| 
       88 
92 
     | 
    
         
             
                elsif kwargs[:minimize]
         
     | 
| 
         @@ -116,7 +120,7 @@ class CompSci::Simplex 
     | 
|
| 
       116 
120 
     | 
    
         
             
                  a.push cofs
         
     | 
| 
       117 
121 
     | 
    
         
             
                  b.push rhs
         
     | 
| 
       118 
122 
     | 
    
         
             
                }
         
     | 
| 
       119 
     | 
    
         
            -
                 
     | 
| 
      
 123 
     | 
    
         
            +
                [c, a, b]
         
     | 
| 
       120 
124 
     | 
    
         
             
              end
         
     | 
| 
       121 
125 
     | 
    
         | 
| 
       122 
126 
     | 
    
         
             
              def self.maximize(expression, *ineqs)
         
     | 
    
        data/lib/compsci/simplex.rb
    CHANGED
    
    | 
         @@ -26,35 +26,36 @@ class CompSci::Simplex 
     | 
|
| 
       26 
26 
     | 
    
         
             
                @max_pivots = DEFAULT_MAX_PIVOTS
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
28 
     | 
    
         
             
                # Problem dimensions; these never change
         
     | 
| 
       29 
     | 
    
         
            -
                @ 
     | 
| 
       30 
     | 
    
         
            -
                @ 
     | 
| 
       31 
     | 
    
         
            -
                @ 
     | 
| 
      
 29 
     | 
    
         
            +
                @num_free_vars   = num_vars
         
     | 
| 
      
 30 
     | 
    
         
            +
                @num_basic_vars = num_inequalities
         
     | 
| 
      
 31 
     | 
    
         
            +
                @total_vars      = @num_free_vars + @num_basic_vars
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
                # Set up initial matrix A and vectors b, c
         
     | 
| 
       34 
     | 
    
         
            -
                 
     | 
| 
      
 34 
     | 
    
         
            +
                # store all input values as Rational (via #rationalize)
         
     | 
| 
      
 35 
     | 
    
         
            +
                @c = c.map { |flt| -1 * flt.rationalize } + Array.new(@num_basic_vars, 0)
         
     | 
| 
       35 
36 
     | 
    
         
             
                @a = a.map.with_index { |ary, i|
         
     | 
| 
       36 
     | 
    
         
            -
                  if ary.size != @ 
     | 
| 
      
 37 
     | 
    
         
            +
                  if ary.size != @num_free_vars
         
     | 
| 
       37 
38 
     | 
    
         
             
                    raise ArgumentError, "a is inconsistent"
         
     | 
| 
       38 
39 
     | 
    
         
             
                  end
         
     | 
| 
       39 
     | 
    
         
            -
                  #  
     | 
| 
       40 
     | 
    
         
            -
                  ary 
     | 
| 
      
 40 
     | 
    
         
            +
                  # add identity matrix
         
     | 
| 
      
 41 
     | 
    
         
            +
                  ary.map { |flt| flt.rationalize } +
         
     | 
| 
      
 42 
     | 
    
         
            +
                    Array.new(@num_basic_vars) { |ci| ci == i ? 1 : 0 }
         
     | 
| 
       41 
43 
     | 
    
         
             
                }
         
     | 
| 
       42 
     | 
    
         
            -
                @b = b
         
     | 
| 
      
 44 
     | 
    
         
            +
                @b = b.map { |flt| flt.rationalize }
         
     | 
| 
       43 
45 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                 
     | 
| 
       45 
     | 
    
         
            -
                @basic_vars = (@num_non_slack_vars...@num_vars).to_a
         
     | 
| 
      
 46 
     | 
    
         
            +
                @basic_vars = (@num_free_vars...@total_vars).to_a
         
     | 
| 
       46 
47 
     | 
    
         
             
                self.update_solution
         
     | 
| 
       47 
48 
     | 
    
         
             
              end
         
     | 
| 
       48 
49 
     | 
    
         | 
| 
       49 
50 
     | 
    
         
             
              # does not modify vector / matrix
         
     | 
| 
       50 
51 
     | 
    
         
             
              def update_solution
         
     | 
| 
       51 
     | 
    
         
            -
                @x = Array.new(@ 
     | 
| 
      
 52 
     | 
    
         
            +
                @x = Array.new(@total_vars, 0)
         
     | 
| 
       52 
53 
     | 
    
         | 
| 
       53 
54 
     | 
    
         
             
                @basic_vars.each { |basic_var|
         
     | 
| 
       54 
55 
     | 
    
         
             
                  idx = nil
         
     | 
| 
       55 
     | 
    
         
            -
                  @ 
     | 
| 
      
 56 
     | 
    
         
            +
                  @num_basic_vars.times { |i|
         
     | 
| 
       56 
57 
     | 
    
         
             
                    if @a[i][basic_var] == 1
         
     | 
| 
       57 
     | 
    
         
            -
                      idx =i
         
     | 
| 
      
 58 
     | 
    
         
            +
                      idx = i
         
     | 
| 
       58 
59 
     | 
    
         
             
                      break
         
     | 
| 
       59 
60 
     | 
    
         
             
                    end
         
     | 
| 
       60 
61 
     | 
    
         
             
                  }
         
     | 
| 
         @@ -78,7 +79,7 @@ class CompSci::Simplex 
     | 
|
| 
       78 
79 
     | 
    
         
             
              end
         
     | 
| 
       79 
80 
     | 
    
         | 
| 
       80 
81 
     | 
    
         
             
              def current_solution
         
     | 
| 
       81 
     | 
    
         
            -
                @x[0...@ 
     | 
| 
      
 82 
     | 
    
         
            +
                @x[0...@num_free_vars]
         
     | 
| 
       82 
83 
     | 
    
         
             
              end
         
     | 
| 
       83 
84 
     | 
    
         | 
| 
       84 
85 
     | 
    
         
             
              def can_improve?
         
     | 
| 
         @@ -121,7 +122,7 @@ class CompSci::Simplex 
     | 
|
| 
       121 
122 
     | 
    
         
             
                }
         
     | 
| 
       122 
123 
     | 
    
         | 
| 
       123 
124 
     | 
    
         
             
                # update A and B
         
     | 
| 
       124 
     | 
    
         
            -
                @ 
     | 
| 
      
 125 
     | 
    
         
            +
                @num_basic_vars.times { |i|
         
     | 
| 
       125 
126 
     | 
    
         
             
                  next if i == pivot_row
         
     | 
| 
       126 
127 
     | 
    
         
             
                  r = @a[i][pivot_column]
         
     | 
| 
       127 
128 
     | 
    
         
             
                  @a[i] = @a[i].map.with_index { |val, j| val - r * @a[pivot_row][j] }
         
     | 
| 
         @@ -134,7 +135,7 @@ class CompSci::Simplex 
     | 
|
| 
       134 
135 
     | 
    
         
             
              def pivot_row(column_ix)
         
     | 
| 
       135 
136 
     | 
    
         
             
                min_ratio = nil
         
     | 
| 
       136 
137 
     | 
    
         
             
                idx = nil
         
     | 
| 
       137 
     | 
    
         
            -
                @ 
     | 
| 
      
 138 
     | 
    
         
            +
                @num_basic_vars.times { |i|
         
     | 
| 
       138 
139 
     | 
    
         
             
                  a, b = @a[i][column_ix], @b[i]
         
     | 
| 
       139 
140 
     | 
    
         
             
                  next if a == 0 or (b < 0) ^ (a < 0)
         
     | 
| 
       140 
141 
     | 
    
         
             
                  ratio = Rational(b, a)
         
     | 
    
        data/lib/compsci/timer.rb
    CHANGED
    
    | 
         @@ -1,5 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module CompSci
         
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
      
 2 
     | 
    
         
            +
              class Timer
         
     | 
| 
      
 3 
     | 
    
         
            +
                SECS_PER_MIN = 60
         
     | 
| 
      
 4 
     | 
    
         
            +
                MINS_PER_HOUR = 60
         
     | 
| 
      
 5 
     | 
    
         
            +
                SECS_PER_HOUR = SECS_PER_MIN * MINS_PER_HOUR
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       3 
7 
     | 
    
         
             
                # lifted from seattlerb/minitest
         
     | 
| 
       4 
8 
     | 
    
         
             
                if defined? Process::CLOCK_MONOTONIC
         
     | 
| 
       5 
9 
     | 
    
         
             
                  def self.now
         
     | 
| 
         @@ -32,5 +36,61 @@ module CompSci 
     | 
|
| 
       32 
36 
     | 
    
         
             
                  }
         
     | 
| 
       33 
37 
     | 
    
         
             
                  return val, self.since(start) / i.to_f
         
     | 
| 
       34 
38 
     | 
    
         
             
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # YYYY-MM-DD HH::MM::SS.mmm
         
     | 
| 
      
 41 
     | 
    
         
            +
                def self.timestamp(t)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  t.strftime "%Y-%m-%d %H:%M:%S.%L"
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                # HH::MM::SS.mmm.uuuuuuuu
         
     | 
| 
      
 46 
     | 
    
         
            +
                def self.elapsed_display(elapsed_ms, show_us: false)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  elapsed_s, ms = elapsed_ms.divmod 1000
         
     | 
| 
      
 48 
     | 
    
         
            +
                  ms_only, ms_fraction = ms.round(8).divmod 1
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  h = elapsed_s / SECS_PER_HOUR
         
     | 
| 
      
 51 
     | 
    
         
            +
                  elapsed_s -= h * SECS_PER_HOUR
         
     | 
| 
      
 52 
     | 
    
         
            +
                  m, s = elapsed_s.divmod SECS_PER_MIN
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  hmsms = [[h, m, s].map { |i| i.to_s.rjust(2, '0') }.join(':'),
         
     | 
| 
      
 55 
     | 
    
         
            +
                           ms_only.to_s.rjust(3, '0')]
         
     | 
| 
      
 56 
     | 
    
         
            +
                  hmsms << (ms_fraction * 10 ** 8).round.to_s.ljust(8, '0') if show_us
         
     | 
| 
      
 57 
     | 
    
         
            +
                  hmsms.join('.')
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def restart(t = Time.now)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @start = t
         
     | 
| 
      
 62 
     | 
    
         
            +
                  self
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
                alias_method :initialize, :restart
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def timestamp(t = Time.now)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  self.class.timestamp t
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def timestamp!(t = Time.now)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  puts '-' * 70, timestamp(t), '-' * 70
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def elapsed(t = Time.now)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  t - @start
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def elapsed_ms(t = Time.now)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  elapsed(t) * 1000
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def elapsed_display(t = Time.now)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  self.class.elapsed_display(elapsed_ms(t))
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
                alias_method :to_s, :elapsed_display
         
     | 
| 
      
 86 
     | 
    
         
            +
                alias_method :inspect, :elapsed_display
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                def stamp(msg = '', t = Time.now)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  format("%s %s", elapsed_display(t), msg)
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                def stamp!(msg = '', t = Time.now)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  puts stamp(msg, t)
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
       35 
95 
     | 
    
         
             
              end
         
     | 
| 
       36 
96 
     | 
    
         
             
            end
         
     | 
    
        data/test/fit.rb
    CHANGED
    
    | 
         @@ -15,14 +15,14 @@ describe Fit do 
     | 
|
| 
       15 
15 
     | 
    
         
             
              end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
              describe "Fit.sigma" do
         
     | 
| 
       18 
     | 
    
         
            -
                it " 
     | 
| 
      
 18 
     | 
    
         
            +
                it "answers correctly" do
         
     | 
| 
       19 
19 
     | 
    
         
             
                  expect(Fit.sigma([1, 2, 3])).must_equal 6
         
     | 
| 
       20 
20 
     | 
    
         
             
                  expect(Fit.sigma([1, 2, 3]) { |n| n ** 2 }).must_equal 14
         
     | 
| 
       21 
21 
     | 
    
         
             
                end
         
     | 
| 
       22 
22 
     | 
    
         
             
              end
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
              describe "Fit.error" do
         
     | 
| 
       25 
     | 
    
         
            -
                it " 
     | 
| 
      
 25 
     | 
    
         
            +
                it "calculates r^2" do
         
     | 
| 
       26 
26 
     | 
    
         
             
                  expect(Fit.error([[1, 1], [2, 2], [3, 3]]) { |x| x }).must_equal 1.0
         
     | 
| 
       27 
27 
     | 
    
         
             
                  expect(Fit.error([[1, 1], [2, 2], [3, 4]]) { |x|
         
     | 
| 
       28 
28 
     | 
    
         
             
                           x
         
     | 
| 
         @@ -36,7 +36,7 @@ describe Fit do 
     | 
|
| 
       36 
36 
     | 
    
         
             
              #       alternate measure.  A low slope and r2 for linear fit, maybe.
         
     | 
| 
       37 
37 
     | 
    
         
             
              #
         
     | 
| 
       38 
38 
     | 
    
         
             
              describe "Fit.constant" do
         
     | 
| 
       39 
     | 
    
         
            -
                it " 
     | 
| 
      
 39 
     | 
    
         
            +
                it "returns zero variance with truly constant inputs" do
         
     | 
| 
       40 
40 
     | 
    
         
             
                  [0, 1, 10, 100, 1000, 9999].each { |a|
         
     | 
| 
       41 
41 
     | 
    
         
             
                    y_bar, variance = Fit.constant(@xs, @xs.map { |x| a })
         
     | 
| 
       42 
42 
     | 
    
         
             
                    expect(y_bar).must_equal a
         
     | 
| 
         @@ -47,7 +47,7 @@ describe Fit do 
     | 
|
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
              # y = a + b*ln(x)
         
     | 
| 
       49 
49 
     | 
    
         
             
              describe "Fit.logarithmic" do
         
     | 
| 
       50 
     | 
    
         
            -
                it " 
     | 
| 
      
 50 
     | 
    
         
            +
                it "accepts logarithmic data" do
         
     | 
| 
       51 
51 
     | 
    
         
             
                  [-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |a|
         
     | 
| 
       52 
52 
     | 
    
         
             
                    [-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |b|
         
     | 
| 
       53 
53 
     | 
    
         
             
                      ary = Fit.logarithmic(@xs, @xs.map { |x| a + b * Math.log(x) })
         
     | 
| 
         @@ -61,7 +61,7 @@ describe Fit do 
     | 
|
| 
       61 
61 
     | 
    
         | 
| 
       62 
62 
     | 
    
         
             
              # y = a + bx
         
     | 
| 
       63 
63 
     | 
    
         
             
              describe "Fit.linear" do
         
     | 
| 
       64 
     | 
    
         
            -
                it " 
     | 
| 
      
 64 
     | 
    
         
            +
                it "accepts linear data" do
         
     | 
| 
       65 
65 
     | 
    
         
             
                  [-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |a|
         
     | 
| 
       66 
66 
     | 
    
         
             
                    [-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |b|
         
     | 
| 
       67 
67 
     | 
    
         
             
                      ary = Fit.linear(@xs, @xs.map { |x| a + b * x })
         
     | 
| 
         @@ -72,7 +72,7 @@ describe Fit do 
     | 
|
| 
       72 
72 
     | 
    
         
             
                  }
         
     | 
| 
       73 
73 
     | 
    
         
             
                end
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
                it " 
     | 
| 
      
 75 
     | 
    
         
            +
                it "accepts constant data" do
         
     | 
| 
       76 
76 
     | 
    
         
             
                  [0, 1, 10, 100, 1000, 9999].each { |a|
         
     | 
| 
       77 
77 
     | 
    
         
             
                    ary = Fit.linear(@xs, @xs.map { |x| a })
         
     | 
| 
       78 
78 
     | 
    
         
             
                    expect(ary[0]).must_equal a
         
     | 
| 
         @@ -84,7 +84,7 @@ describe Fit do 
     | 
|
| 
       84 
84 
     | 
    
         
             
                # note, this test can possibly fail depending on the uniformity of
         
     | 
| 
       85 
85 
     | 
    
         
             
                # rand's output for our sample
         
     | 
| 
       86 
86 
     | 
    
         
             
                #
         
     | 
| 
       87 
     | 
    
         
            -
                it " 
     | 
| 
      
 87 
     | 
    
         
            +
                it "accepts noisy constant data" do
         
     | 
| 
       88 
88 
     | 
    
         
             
                  r2s = []
         
     | 
| 
       89 
89 
     | 
    
         
             
                  [0, 1, 10, 100, 1000, 9999].each { |a|
         
     | 
| 
       90 
90 
     | 
    
         
             
                    ary = Fit.linear(@xs, @xs.map { |x| a + noise() })
         
     | 
| 
         @@ -96,16 +96,14 @@ describe Fit do 
     | 
|
| 
       96 
96 
     | 
    
         
             
                  expect(mean_r2).must_be_close_to 0.15, 0.15
         
     | 
| 
       97 
97 
     | 
    
         
             
                end
         
     | 
| 
       98 
98 
     | 
    
         | 
| 
       99 
     | 
    
         
            -
                it " 
     | 
| 
       100 
     | 
    
         
            -
                   
     | 
| 
       101 
     | 
    
         
            -
                  xs = [1, 10, 100, 1000]
         
     | 
| 
      
 99 
     | 
    
         
            +
                it "rejects x^2" do
         
     | 
| 
      
 100 
     | 
    
         
            +
                  xs = Array.new(99) { |i| i }
         
     | 
| 
       102 
101 
     | 
    
         
             
                  _a, _b, r2 = Fit.linear(xs, xs.map { |x| x**2 })
         
     | 
| 
       103 
102 
     | 
    
         
             
                  expect(r2).must_be :<, 0.99
         
     | 
| 
       104 
103 
     | 
    
         
             
                end
         
     | 
| 
       105 
104 
     | 
    
         | 
| 
       106 
     | 
    
         
            -
                it " 
     | 
| 
       107 
     | 
    
         
            -
                   
     | 
| 
       108 
     | 
    
         
            -
                  xs = [1, 10, 100, 1000]
         
     | 
| 
      
 105 
     | 
    
         
            +
                it "rejects x^3" do
         
     | 
| 
      
 106 
     | 
    
         
            +
                  xs = Array.new(99) { |i| i }
         
     | 
| 
       109 
107 
     | 
    
         
             
                  _a, _b, r2 = Fit.linear(xs, xs.map { |x| x**3 })
         
     | 
| 
       110 
108 
     | 
    
         
             
                  expect(r2).must_be :<, 0.99
         
     | 
| 
       111 
109 
     | 
    
         
             
                end
         
     | 
| 
         @@ -113,7 +111,7 @@ describe Fit do 
     | 
|
| 
       113 
111 
     | 
    
         | 
| 
       114 
112 
     | 
    
         
             
              # y = ae^(bx)
         
     | 
| 
       115 
113 
     | 
    
         
             
              describe "Fit.exponential" do
         
     | 
| 
       116 
     | 
    
         
            -
                it " 
     | 
| 
      
 114 
     | 
    
         
            +
                it "accepts exponential data" do
         
     | 
| 
       117 
115 
     | 
    
         
             
                  [0.001, 7.5, 500, 1000, 5000, 9999].each { |a|
         
     | 
| 
       118 
116 
     | 
    
         
             
                    [-1.4, -1.1, -0.1, 0.01, 0.5, 0.75].each { |b|
         
     | 
| 
       119 
117 
     | 
    
         
             
                      ary = Fit.exponential(@xs, @xs.map { |x| a * Math::E**(b * x) })
         
     | 
| 
         @@ -127,10 +125,13 @@ describe Fit do 
     | 
|
| 
       127 
125 
     | 
    
         | 
| 
       128 
126 
     | 
    
         
             
              # y = ax^b
         
     | 
| 
       129 
127 
     | 
    
         
             
              describe "Fit.power" do
         
     | 
| 
       130 
     | 
    
         
            -
                it " 
     | 
| 
      
 128 
     | 
    
         
            +
                it "accepts power data" do
         
     | 
| 
       131 
129 
     | 
    
         
             
                  [0.01, 7.5, 500, 1000, 5000, 9999].each { |a|
         
     | 
| 
       132 
130 
     | 
    
         
             
                    [-114, -100, -10, -0.5, -0.1, 0.1, 0.75, 10, 50, 60].each { |b|
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
      
 131 
     | 
    
         
            +
                    # [    -100, -10, -0.5, -0.1, 0.1, 0.75, 10, 50, 60].each { |b|
         
     | 
| 
      
 132 
     | 
    
         
            +
                      # note: on Ruby 2.4.x and older, b == -114 throws
         
     | 
| 
      
 133 
     | 
    
         
            +
                      # warning: Bignum out of Float range
         
     | 
| 
      
 134 
     | 
    
         
            +
                      # also: TruffleRuby as of Jan '22: ary[2] is NaN rather than 1.0
         
     | 
| 
       134 
135 
     | 
    
         
             
                      ary = Fit.power(@xs, @xs.map { |x| a * x**b })
         
     | 
| 
       135 
136 
     | 
    
         
             
                      expect(ary[0]).must_be_close_to a
         
     | 
| 
       136 
137 
     | 
    
         
             
                      expect(ary[1]).must_be_close_to b
         
     | 
| 
         @@ -139,4 +140,41 @@ describe Fit do 
     | 
|
| 
       139 
140 
     | 
    
         
             
                  }
         
     | 
| 
       140 
141 
     | 
    
         
             
                end
         
     | 
| 
       141 
142 
     | 
    
         
             
              end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
              describe "Fit.predict" do
         
     | 
| 
      
 145 
     | 
    
         
            +
                before do
         
     | 
| 
      
 146 
     | 
    
         
            +
                  @a, @b, @x = 1, 2, 3
         
     | 
| 
      
 147 
     | 
    
         
            +
                end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                it "accepts a few different models" do
         
     | 
| 
      
 150 
     | 
    
         
            +
                  [:constant, :logarithmic, :linear, :exponential, :power].each { |model|
         
     | 
| 
      
 151 
     | 
    
         
            +
                    expect(Fit.predict(model, @a, @b, @x)).must_be_kind_of(Numeric)
         
     | 
| 
      
 152 
     | 
    
         
            +
                  }
         
     | 
| 
      
 153 
     | 
    
         
            +
                  expect { Fit.predict(:invalid, @a, @b, @x) }.must_raise RuntimeError
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                it "predicts constant relationships" do
         
     | 
| 
      
 157 
     | 
    
         
            +
                  expect(Fit.predict(:constant, @a, @b, @x)).must_equal @a
         
     | 
| 
      
 158 
     | 
    
         
            +
                  expect(Fit.predict(:constant, @a, @x, @b)).must_equal @a
         
     | 
| 
      
 159 
     | 
    
         
            +
                  expect(Fit.predict(:constant, @x, @a, @b)).must_equal @x
         
     | 
| 
      
 160 
     | 
    
         
            +
                end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                it "predicts logarithmic relationships" do
         
     | 
| 
      
 163 
     | 
    
         
            +
                  expect(Fit.predict(:logarithmic, @a, @b, @x)
         
     | 
| 
      
 164 
     | 
    
         
            +
                        ).must_equal @a + @b * Math.log(@x)
         
     | 
| 
      
 165 
     | 
    
         
            +
                end
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                it "predicts linear relationships" do
         
     | 
| 
      
 168 
     | 
    
         
            +
                  expect(Fit.predict(:linear, @a, @b, @x)).must_equal @a + @b * @x
         
     | 
| 
      
 169 
     | 
    
         
            +
                end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                it "predicts exponential relationships" do
         
     | 
| 
      
 172 
     | 
    
         
            +
                  expect(Fit.predict(:exponential, @a, @b, @x)
         
     | 
| 
      
 173 
     | 
    
         
            +
                        ).must_equal @a * Math::E ** (@b * @x)
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                it "predicts power relationships" do
         
     | 
| 
      
 177 
     | 
    
         
            +
                  expect(Fit.predict(:power, @a, @b, @x)).must_equal @a * @x ** @b
         
     | 
| 
      
 178 
     | 
    
         
            +
                end
         
     | 
| 
      
 179 
     | 
    
         
            +
              end
         
     | 
| 
       142 
180 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: compsci
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.3. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.3.2.1
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Rick Hull
         
     | 
| 
       8 
     | 
    
         
            -
            autorequire: 
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 1980-01-01 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: buildar
         
     | 
| 
         @@ -28,30 +28,30 @@ dependencies: 
     | 
|
| 
       28 
28 
     | 
    
         
             
              name: minitest
         
     | 
| 
       29 
29 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       30 
30 
     | 
    
         
             
                requirements:
         
     | 
| 
       31 
     | 
    
         
            -
                - - " 
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       32 
32 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       33 
33 
     | 
    
         
             
                    version: '5.0'
         
     | 
| 
       34 
34 
     | 
    
         
             
              type: :development
         
     | 
| 
       35 
35 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       36 
36 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       37 
37 
     | 
    
         
             
                requirements:
         
     | 
| 
       38 
     | 
    
         
            -
                - - " 
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       39 
39 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       40 
40 
     | 
    
         
             
                    version: '5.0'
         
     | 
| 
       41 
41 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       42 
42 
     | 
    
         
             
              name: rake
         
     | 
| 
       43 
43 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       44 
44 
     | 
    
         
             
                requirements:
         
     | 
| 
       45 
     | 
    
         
            -
                - - " 
     | 
| 
      
 45 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       46 
46 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       47 
     | 
    
         
            -
                    version: 12.3 
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '12.3'
         
     | 
| 
       48 
48 
     | 
    
         
             
              type: :development
         
     | 
| 
       49 
49 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       50 
50 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       51 
51 
     | 
    
         
             
                requirements:
         
     | 
| 
       52 
     | 
    
         
            -
                - - " 
     | 
| 
      
 52 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       53 
53 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       54 
     | 
    
         
            -
                    version: 12.3 
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '12.3'
         
     | 
| 
       55 
55 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       56 
56 
     | 
    
         
             
              name: flog
         
     | 
| 
       57 
57 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -123,7 +123,7 @@ dependencies: 
     | 
|
| 
       123 
123 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       124 
124 
     | 
    
         
             
                    version: '2.0'
         
     | 
| 
       125 
125 
     | 
    
         
             
            description: Trees, Heaps, Timers, Error fitting, etc
         
     | 
| 
       126 
     | 
    
         
            -
            email: 
     | 
| 
      
 126 
     | 
    
         
            +
            email:
         
     | 
| 
       127 
127 
     | 
    
         
             
            executables: []
         
     | 
| 
       128 
128 
     | 
    
         
             
            extensions: []
         
     | 
| 
       129 
129 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
         @@ -172,7 +172,7 @@ homepage: https://github.com/rickhull/compsci 
     | 
|
| 
       172 
172 
     | 
    
         
             
            licenses:
         
     | 
| 
       173 
173 
     | 
    
         
             
            - LGPL-3.0
         
     | 
| 
       174 
174 
     | 
    
         
             
            metadata: {}
         
     | 
| 
       175 
     | 
    
         
            -
            post_install_message: 
     | 
| 
      
 175 
     | 
    
         
            +
            post_install_message:
         
     | 
| 
       176 
176 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
       177 
177 
     | 
    
         
             
            require_paths:
         
     | 
| 
       178 
178 
     | 
    
         
             
            - lib
         
     | 
| 
         @@ -180,15 +180,15 @@ required_ruby_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       180 
180 
     | 
    
         
             
              requirements:
         
     | 
| 
       181 
181 
     | 
    
         
             
              - - "~>"
         
     | 
| 
       182 
182 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       183 
     | 
    
         
            -
                  version: ' 
     | 
| 
      
 183 
     | 
    
         
            +
                  version: '3.0'
         
     | 
| 
       184 
184 
     | 
    
         
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
       185 
185 
     | 
    
         
             
              requirements:
         
     | 
| 
       186 
186 
     | 
    
         
             
              - - ">="
         
     | 
| 
       187 
187 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       188 
188 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       189 
189 
     | 
    
         
             
            requirements: []
         
     | 
| 
       190 
     | 
    
         
            -
            rubygems_version: 3. 
     | 
| 
       191 
     | 
    
         
            -
            signing_key: 
     | 
| 
      
 190 
     | 
    
         
            +
            rubygems_version: 3.2.26
         
     | 
| 
      
 191 
     | 
    
         
            +
            signing_key:
         
     | 
| 
       192 
192 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       193 
193 
     | 
    
         
             
            summary: Toy implementations for some basic computer science problems
         
     | 
| 
       194 
194 
     | 
    
         
             
            test_files: []
         
     |