compsci 0.3.0.1 → 0.3.1.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.
@@ -1,9 +1,9 @@
1
- require 'compsci'
2
-
3
1
  # note, this work is based on https://github.com/rickhull/simplex
4
2
  # which was forked in 2017 from https://github.com/danlucraft/simplex
5
3
  # which had its last commit in 2013
6
4
 
5
+ module CompSci; end
6
+
7
7
  class CompSci::Simplex
8
8
  DEFAULT_MAX_PIVOTS = 10_000
9
9
 
@@ -168,6 +168,4 @@ class CompSci::Simplex
168
168
  lines.insert(1, "-"*max_line_length)
169
169
  lines.join("\n")
170
170
  end
171
-
172
-
173
171
  end
@@ -84,16 +84,16 @@ class CompSci::Simplex
84
84
 
85
85
  def self.problem(maximize: nil, constraints: [], **kwargs)
86
86
  if maximize
87
- obj, maximize = maximize, true
87
+ expr, maximize = maximize, true
88
88
  elsif kwargs[:minimize]
89
- obj, maximize = kwargs[:minimize], false
89
+ expr, maximize = kwargs[:minimize], false
90
90
  else
91
91
  raise(ArgumentError, "one of maximize/minimize expected")
92
92
  end
93
- unless obj.is_a?(String)
93
+ unless expr.is_a?(String)
94
94
  raise(ArgumentError, "bad expr: #{expr} (#{expr.class})")
95
95
  end
96
- obj_cof = Parse.expression(obj)
96
+ obj_cof = Parse.expression(expr)
97
97
 
98
98
  c = [] # coefficients of objective expression
99
99
  a = [] # array (per constraint) of the inequality's lhs coefficients
@@ -1,143 +1,44 @@
1
1
  require 'compsci/fibonacci'
2
- require 'minitest/autorun'
3
- require 'minitest/benchmark'
2
+ require 'benchmark/ips'
4
3
 
5
4
  include CompSci
6
5
 
7
- # CLASSIC_RANGE = [3, 5, 10, 15, 20, 25, 30, 31, 32, 33, 34, 35]
8
- CLASSIC_RANGE = [10, 15, 20, 25, 30, 31, 32, 33, 34, 35]
9
- # RECURSIVE_RANGE = [10, 100, 1000, 2500, 5000, 7500]
10
- RECURSIVE_RANGE = [100, 1000, 2500, 5000, 7500]
11
- # CACHE_RANGE = [100, 1000, 10000, 100000, 112500, 125000]
12
- CACHE_RANGE = [100, 1000, 10000, 100000]
6
+ # recursive benchmarks with low N; iterative for comparison
7
+ Benchmark.ips do |b|
8
+ b.config time: 3, warmup: 0.5
9
+ num = 25
13
10
 
14
- # this causes churn at the process level and impacts other benchmarks
15
- # DYNAMIC_RANGE = [100, 1000, 10000, 100000, 200000, 500000]
16
- DYNAMIC_RANGE = [100, 1000, 10000, 100000]
17
- MATRIX_RANGE = [100, 1000, 10000, 100000]
11
+ b.report("Fibonacci.classic(#{num})") {
12
+ Fibonacci.classic(num)
13
+ }
18
14
 
19
- #SPEC_BENCHMARK = true
20
- #CLASS_BENCHMARK = true
21
- BENCHMARK_IPS = true
22
- SPEC_BENCHMARK = false
23
- CLASS_BENCHMARK = false
24
- #BENCHMARK_IPS = false
15
+ b.report("Fibonacci.cache_recursive(#{num})") {
16
+ Fibonacci.cache_recursive(num)
17
+ }
25
18
 
19
+ b.report("Fibonacci.cache_iterative(#{num})") {
20
+ Fibonacci.cache_iterative(num)
21
+ }
26
22
 
27
- if SPEC_BENCHMARK
28
- describe "Fibonacci.classic Benchmark" do
29
- bench_range do
30
- CLASSIC_RANGE
31
- end
32
-
33
- fc = ["Fibonacci.classic (exponential, 0.95)", 0.95]
34
- bench_performance_exponential(*fc) do |n|
35
- Fibonacci.classic(n)
36
- end
37
- end
38
-
39
- describe "Fibonacci.cache_recursive Benchmark" do
40
- bench_range do
41
- RECURSIVE_RANGE
42
- end
43
-
44
- fcr = ["Fibonacci.cache_recursive (linear, 0.95)", 0.95]
45
- bench_performance_linear(*fcr) do |n|
46
- Fibonacci.cache_recursive(n)
47
- end
48
- end
49
-
50
- describe "Fibonacci.cache_iterative Benchmark" do
51
- bench_range do
52
- CACHE_RANGE
53
- end
54
-
55
- fci = ["Fibonacci.cache_iterative (linear, 0.99)", 0.99]
56
- bench_performance_linear(*fci) do |n|
57
- Fibonacci.cache_iterative(n)
58
- end
59
- end
60
-
61
- describe "Fibonacci.dynamic Benchmark" do
62
- bench_range do
63
- DYNAMIC_RANGE
64
- end
65
-
66
- fd = ["Fibonacci.dynamic (linear, 0.99)", 0.99]
67
- bench_performance_linear(*fd) do |n|
68
- Fibonacci.dynamic(n)
69
- end
70
- end
71
-
72
- describe "Fibonacci.matrix Benchmark" do
73
- bench_range do
74
- MATRIX_RANGE
75
- end
76
-
77
- fd = ["Fibonacci.matrix (linear, 0.99)", 0.99]
78
- bench_performance_linear(*fd) do |n|
79
- Fibonacci.matrix(n)
80
- end
81
- end
23
+ b.compare!
82
24
  end
83
25
 
84
- if CLASS_BENCHMARK
85
- require 'compsci/timer'
86
-
87
- class BenchFib < Minitest::Benchmark
88
- def bench_fib
89
- times = CLASSIC_RANGE.map { |n|
90
- _answer, elapsed = Timer.elapsed { Fibonacci.classic(n) }
91
- elapsed
92
- }
93
- _a, _b, r2 = self.fit_exponential(CLASSIC_RANGE, times)
94
- puts
95
- puts "self-timed Fibonacci.classic(n) exponential fit: %0.3f" % r2
96
- puts
97
- end
98
- end
99
- end
100
-
101
- if BENCHMARK_IPS
102
- require 'benchmark/ips'
103
-
104
- # recursive benchmarks with low N; iterative for comparison
105
- Benchmark.ips do |b|
106
- b.config time: 3, warmup: 0.5
107
- num = 25
108
-
109
- b.report("Fibonacci.classic(#{num})") {
110
- Fibonacci.classic(num)
111
- }
112
-
113
- b.report("Fibonacci.cache_recursive(#{num})") {
114
- Fibonacci.cache_recursive(num)
115
- }
116
-
117
- b.report("Fibonacci.cache_iterative(#{num})") {
118
- Fibonacci.cache_iterative(num)
119
- }
120
-
121
- b.compare!
122
- end
123
-
124
- # nonrecursive benchmarks with high N
125
- Benchmark.ips do |b|
126
- b.config time: 3, warmup: 0.5
127
- num = 500
26
+ # nonrecursive benchmarks with high N
27
+ Benchmark.ips do |b|
28
+ b.config time: 3, warmup: 0.5
29
+ num = 500
128
30
 
129
- b.report("Fibonacci.cache_iterative(#{num})") {
130
- Fibonacci.cache_iterative(num)
131
- }
31
+ b.report("Fibonacci.cache_iterative(#{num})") {
32
+ Fibonacci.cache_iterative(num)
33
+ }
132
34
 
133
- b.report("Fibonacci.dynamic(#{num})") {
134
- Fibonacci.dynamic(num)
135
- }
35
+ b.report("Fibonacci.dynamic(#{num})") {
36
+ Fibonacci.dynamic(num)
37
+ }
136
38
 
137
- b.report("Fibonacci.matrix(#{num})") {
138
- Fibonacci.matrix(num)
139
- }
39
+ b.report("Fibonacci.matrix(#{num})") {
40
+ Fibonacci.matrix(num)
41
+ }
140
42
 
141
- b.compare!
142
- end
43
+ b.compare!
143
44
  end
@@ -0,0 +1,30 @@
1
+ require 'compsci/flex_node'
2
+ require 'benchmark/ips'
3
+
4
+ include CompSci
5
+
6
+ Benchmark.ips do |b|
7
+ b.config time: 3, warmup: 0.5
8
+
9
+ b.report("99x Binary ChildFlexNode#push") do
10
+ @root = ChildFlexNode.new 42
11
+ 99.times { @root.push rand(99), 2 }
12
+ end
13
+
14
+ b.report("99x Binary FlexNode#push") do
15
+ @root = FlexNode.new 42
16
+ 99.times { @root.push rand(99), 2 }
17
+ end
18
+
19
+ b.report("99x Ternary ChildFlexNode#push") do
20
+ @root = ChildFlexNode.new 42
21
+ 99.times { @root.push rand(99), 3 }
22
+ end
23
+
24
+ b.report("99x Ternary FlexNode#push") do
25
+ @root = FlexNode.new 42
26
+ 99.times { @root.push rand(99), 3 }
27
+ end
28
+
29
+ b.compare!
30
+ end
@@ -1,9 +1,11 @@
1
1
  require 'compsci/complete_tree'
2
2
  require 'minitest/autorun'
3
3
 
4
+ Minitest::Test.parallelize_me!
5
+
4
6
  include CompSci
5
7
 
6
- describe CompleteNaryTree do
8
+ describe CompleteTree do
7
9
  it "must calculate a parent index for N=2" do
8
10
  valid = {
9
11
  1 => 0,
@@ -24,10 +26,10 @@ describe CompleteNaryTree do
24
26
  -2 => -2,
25
27
  }
26
28
  valid.each { |idx, pidx|
27
- CompleteNaryTree.parent_idx(idx, 2).must_equal pidx
29
+ expect(CompleteTree.parent_idx(idx, 2)).must_equal pidx
28
30
  }
29
31
  invalid.each { |idx, pidx|
30
- CompleteNaryTree.parent_idx(idx, 2).must_equal pidx
32
+ expect(CompleteTree.parent_idx(idx, 2)).must_equal pidx
31
33
  }
32
34
  end
33
35
 
@@ -53,10 +55,10 @@ describe CompleteNaryTree do
53
55
  }
54
56
 
55
57
  valid.each { |idx, cidx|
56
- CompleteNaryTree.children_idx(idx, 2).must_equal cidx
58
+ expect(CompleteTree.children_idx(idx, 2)).must_equal cidx
57
59
  }
58
60
  invalid.each { |idx, cidx|
59
- CompleteNaryTree.children_idx(idx, 2).must_equal cidx
61
+ expect(CompleteTree.children_idx(idx, 2)).must_equal cidx
60
62
  }
61
63
  end
62
64
 
@@ -80,10 +82,10 @@ describe CompleteNaryTree do
80
82
  -2 => -1,
81
83
  }
82
84
  valid.each { |idx, pidx|
83
- CompleteNaryTree.parent_idx(idx, 3).must_equal pidx
85
+ expect(CompleteTree.parent_idx(idx, 3)).must_equal pidx
84
86
  }
85
87
  invalid.each { |idx, pidx|
86
- CompleteNaryTree.parent_idx(idx, 3).must_equal pidx
88
+ expect(CompleteTree.parent_idx(idx, 3)).must_equal pidx
87
89
  }
88
90
  end
89
91
 
@@ -102,28 +104,28 @@ describe CompleteNaryTree do
102
104
  }
103
105
 
104
106
  valid.each { |idx, cidx|
105
- CompleteNaryTree.children_idx(idx, 3).must_equal cidx
107
+ expect(CompleteTree.children_idx(idx, 3)).must_equal cidx
106
108
  }
107
109
  invalid.each { |idx, cidx|
108
- CompleteNaryTree.children_idx(idx, 3).must_equal cidx
110
+ expect(CompleteTree.children_idx(idx, 3)).must_equal cidx
109
111
  }
110
112
  end
111
113
 
112
114
  describe "instance" do
113
115
  before do
114
116
  @array = (0..99).sort_by { rand }
115
- @empty = CompleteNaryTree.new(child_slots: 5)
117
+ @empty = CompleteTree.new(child_slots: 5)
116
118
  @nonempty = CompleteQuaternaryTree.new(array: @array)
117
119
  end
118
120
 
119
121
  it "must have a size" do
120
- @empty.size.must_equal 0
121
- @nonempty.size.must_equal @array.size
122
+ expect(@empty.size).must_equal 0
123
+ expect(@nonempty.size).must_equal @array.size
122
124
  end
123
125
 
124
126
  it "must have a last_idx, nil when empty" do
125
- @empty.last_idx.nil?.must_equal true
126
- @nonempty.last_idx.must_equal 99
127
+ expect(@empty.last_idx.nil?).must_equal true
128
+ expect(@nonempty.last_idx).must_equal 99
127
129
  end
128
130
 
129
131
  # TODO: push, pop, display
@@ -0,0 +1,25 @@
1
+ require 'compsci'
2
+ require 'minitest/autorun'
3
+
4
+ Minitest::Test.parallelize_me!
5
+
6
+ describe CompSci do
7
+ it "must determine if num is a power of base" do
8
+ powers = {}
9
+ basemax = 12
10
+ expmax = 10
11
+ 2.upto(basemax) { |base|
12
+ 0.upto(expmax) { |exp|
13
+ powers[base] ||= []
14
+ powers[base] << base**exp
15
+ }
16
+ }
17
+
18
+ # 12k assertions below!
19
+ 2.upto(basemax) { |base|
20
+ 1.upto(2**expmax) { |num|
21
+ expect(CompSci.power_of?(num, base)).must_equal powers[base].include?(num)
22
+ }
23
+ }
24
+ end
25
+ end
@@ -1,6 +1,8 @@
1
1
  require 'compsci/fibonacci'
2
2
  require 'minitest/autorun'
3
3
 
4
+ Minitest::Test.parallelize_me!
5
+
4
6
  include CompSci
5
7
 
6
8
  describe Fibonacci do
@@ -10,11 +12,10 @@ describe Fibonacci do
10
12
 
11
13
  it "must calculate fib(0..10)" do
12
14
  @answers.each_with_index { |ans, i|
13
- Fibonacci.classic(i).must_equal ans
14
- Fibonacci.cache_recursive(i).must_equal ans
15
- Fibonacci.cache_iterative(i).must_equal ans
16
- Fibonacci.dynamic(i).must_equal ans
17
- Fibonacci.matrix(i).must_equal ans
15
+ [:classic, :cache_recursive, :cache_iterative,
16
+ :dynamic, :matrix].each { |m|
17
+ expect(Fibonacci.send(m, i)).must_equal ans
18
+ }
18
19
  }
19
20
  end
20
21
  end
@@ -1,6 +1,8 @@
1
1
  require 'compsci/fit'
2
2
  require 'minitest/autorun'
3
3
 
4
+ Minitest::Test.parallelize_me!
5
+
4
6
  include CompSci
5
7
 
6
8
  def noise # range: -0.5 to 0.5
@@ -14,15 +16,17 @@ describe Fit do
14
16
 
15
17
  describe "Fit.sigma" do
16
18
  it "must answer correctly" do
17
- Fit.sigma([1, 2, 3]).must_equal 6
18
- Fit.sigma([1, 2, 3]) { |n| n ** 2 }.must_equal 14
19
+ expect(Fit.sigma([1, 2, 3])).must_equal 6
20
+ expect(Fit.sigma([1, 2, 3]) { |n| n ** 2 }).must_equal 14
19
21
  end
20
22
  end
21
23
 
22
24
  describe "Fit.error" do
23
25
  it "must calculate r^2" do
24
- Fit.error([[1, 1], [2, 2], [3, 3]]) { |x| x }.must_equal 1.0
25
- Fit.error([[1, 1], [2, 2], [3, 4]]) { |x| x }.must_be_close_to 0.785
26
+ expect(Fit.error([[1, 1], [2, 2], [3, 3]]) { |x| x }).must_equal 1.0
27
+ expect(Fit.error([[1, 1], [2, 2], [3, 4]]) { |x|
28
+ x
29
+ }).must_be_close_to 0.785
26
30
  end
27
31
  end
28
32
 
@@ -35,8 +39,8 @@ describe Fit do
35
39
  it "must stuff" do
36
40
  [0, 1, 10, 100, 1000, 9999].each { |a|
37
41
  y_bar, variance = Fit.constant(@xs, @xs.map { |x| a })
38
- y_bar.must_equal a
39
- variance.must_equal 0
42
+ expect(y_bar).must_equal a
43
+ expect(variance).must_equal 0
40
44
  }
41
45
  end
42
46
  end
@@ -47,9 +51,9 @@ describe Fit do
47
51
  [-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |a|
48
52
  [-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |b|
49
53
  ary = Fit.logarithmic(@xs, @xs.map { |x| a + b * Math.log(x) })
50
- ary[0].must_be_close_to a
51
- ary[1].must_be_close_to b
52
- ary[2].must_equal 1.0
54
+ expect(ary[0]).must_be_close_to a
55
+ expect(ary[1]).must_be_close_to b
56
+ expect(ary[2]).must_equal 1.0
53
57
  }
54
58
  }
55
59
  end
@@ -61,9 +65,9 @@ describe Fit do
61
65
  [-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |a|
62
66
  [-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |b|
63
67
  ary = Fit.linear(@xs, @xs.map { |x| a + b * x })
64
- ary[0].must_be_close_to a
65
- ary[1].must_be_close_to b
66
- ary[2].must_equal 1.0
68
+ expect(ary[0]).must_be_close_to a
69
+ expect(ary[1]).must_be_close_to b
70
+ expect(ary[2]).must_equal 1.0
67
71
  }
68
72
  }
69
73
  end
@@ -71,9 +75,9 @@ describe Fit do
71
75
  it "must accept constant data" do
72
76
  [0, 1, 10, 100, 1000, 9999].each { |a|
73
77
  ary = Fit.linear(@xs, @xs.map { |x| a })
74
- ary[0].must_equal a
75
- ary[1].must_equal 0
76
- ary[2].nan?.must_equal true
78
+ expect(ary[0]).must_equal a
79
+ expect(ary[1]).must_equal 0
80
+ expect(ary[2].nan?).must_equal true
77
81
  }
78
82
  end
79
83
 
@@ -84,26 +88,26 @@ describe Fit do
84
88
  r2s = []
85
89
  [0, 1, 10, 100, 1000, 9999].each { |a|
86
90
  ary = Fit.linear(@xs, @xs.map { |x| a + noise() })
87
- ary[0].must_be_close_to a, 0.4
88
- ary[1].must_be_close_to 0, 0.05
91
+ expect(ary[0]).must_be_close_to a, 0.4
92
+ expect(ary[1]).must_be_close_to 0, 0.05
89
93
  r2s << ary[2]
90
94
  }
91
95
  mean_r2 = Fit.sigma(r2s) / r2s.size
92
- mean_r2.must_be_close_to 0.15, 0.15
96
+ expect(mean_r2).must_be_close_to 0.15, 0.15
93
97
  end
94
98
 
95
99
  it "must reject x^2" do
96
100
  skip "it does not reject x^2 at r^2 < 0.99"
97
101
  xs = [1, 10, 100, 1000]
98
102
  _a, _b, r2 = Fit.linear(xs, xs.map { |x| x**2 })
99
- r2.must_be :<, 0.99
103
+ expect(r2).must_be :<, 0.99
100
104
  end
101
105
 
102
106
  it "must reject x^3" do
103
107
  skip "it does not reject x^3 at r^2 < 0.99"
104
108
  xs = [1, 10, 100, 1000]
105
109
  _a, _b, r2 = Fit.linear(xs, xs.map { |x| x**3 })
106
- r2.must_be :<, 0.99
110
+ expect(r2).must_be :<, 0.99
107
111
  end
108
112
  end
109
113
 
@@ -113,9 +117,9 @@ describe Fit do
113
117
  [0.001, 7.5, 500, 1000, 5000, 9999].each { |a|
114
118
  [-1.4, -1.1, -0.1, 0.01, 0.5, 0.75].each { |b|
115
119
  ary = Fit.exponential(@xs, @xs.map { |x| a * Math::E**(b * x) })
116
- ary[0].must_be_close_to a
117
- ary[1].must_be_close_to b
118
- ary[2].must_equal 1.0
120
+ expect(ary[0]).must_be_close_to a
121
+ expect(ary[1]).must_be_close_to b
122
+ expect(ary[2]).must_equal 1.0
119
123
  }
120
124
  }
121
125
  end
@@ -128,9 +132,9 @@ describe Fit do
128
132
  [-114, -100, -10, -0.5, -0.1, 0.1, 0.75, 10, 50, 60].each { |b|
129
133
  next if b == -114 # Fit.error warning: Bignum out of Float range
130
134
  ary = Fit.power(@xs, @xs.map { |x| a * x**b })
131
- ary[0].must_be_close_to a
132
- ary[1].must_be_close_to b
133
- ary[2].must_equal 1.0
135
+ expect(ary[0]).must_be_close_to a
136
+ expect(ary[1]).must_be_close_to b
137
+ expect(ary[2]).must_equal 1.0
134
138
  }
135
139
  }
136
140
  end