compsci 0.3.0.1 → 0.3.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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