mathpack 0.4.1 → 0.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d4149b86761de55b123f4feeef355ea0aa0051f2
4
- data.tar.gz: 3b5f7106a2354c0f3ac20e3500a2667f1879aeff
3
+ metadata.gz: 111c0ff1891e4a3c36c9b93e8f76c6e95e6d3daa
4
+ data.tar.gz: 3356428babcbf1b7031dc7dfbd4c03a397dc565c
5
5
  SHA512:
6
- metadata.gz: 6ff0997ccc70491bfb436075065e3e4d7eae4dbef76aff64d7969da9659cb76ff50e7ac2147fbe76dc272b8adfd5ebfddd60e64c43adb3a858acd43e83e770ba
7
- data.tar.gz: 7c6a0502aad9840247e3616982e97e9752597fa3741cc6cb1d0869c96a115ca12a620440042e9b63014d3179fab988efc48690e5543266f52c285f533576acd7
6
+ metadata.gz: 4f04c1e83d260b0376c79b7899092d878b8f5f3b9dedcc40963a931ca0a5b200a8770598164429678fb2d02d1af14d4d99569a4000c633ced33882f617e2fa6d
7
+ data.tar.gz: 39e0707d6eabb22509488221178fe14322d391934a248e8092ddef5050d0a1902755cba9af1698a01d1146046ad489c457b2b82ac2e82f75ae508df6444865d8
data/README.md CHANGED
@@ -34,7 +34,7 @@ Gem `mathpack` allows to count statistical functions through `Statistics` class,
34
34
  - **empirical_cdf** - returns *empirical distribution function* value in some point
35
35
  - **empirical_pdf** - returns *empirical probability density function* value in some point
36
36
  - **print_empirical_cdf_to_csv** - allows to print empirical_cdf line chart values to `.csv` file with name *filename*
37
- - **print_empirical_cdf_to_csv** - allows to print empirical_cdf line chart values to `.csv` file with name *filename*
37
+ - **print_empirical_pdf_to_csv** - allows to print empirical_pdf line chart values to `.csv` file with name *filename*
38
38
  - **trend** - returns trend polynom
39
39
 
40
40
  ### Usage
@@ -43,7 +43,7 @@ stat = Mathpack::Statistics.new([1, 2, 5, 6])
43
43
  stat.number() #=> 4
44
44
  stat.mean() #=> 3.5
45
45
  stat.variance() #=> 4.25
46
- stat.kurtosis() #=> 1.221453287197232
46
+ stat.kurtosis() #=> -1.778546712802768
47
47
  stat.skewness() #=> 0.0
48
48
  stat.min() #=> 1
49
49
  stat.max() #=> 6
@@ -117,23 +117,54 @@ manage with this problem using `Approximation` module. This module uses least sq
117
117
  ### Usage
118
118
  ```ruby
119
119
  # Function to print polynom having it's coefficients
120
- Mathpack::Approximation::print_polynom([1, -2, 1]) #=> x^2 - 2*x + 1
120
+ Mathpack::Approximation.print_polynom([1, -2, 1]) #=> x^2 - 2*x + 1
121
121
 
122
122
  # Function to generate nodes for approximation. Only choose start value, end value and step
123
- x = Mathpack::Approximation::generate_nodes(start: 0, end: 10, step: 0.25)
123
+ x = Mathpack::Approximation.generate_nodes(from: 0, to: 10, step: 0.25)
124
124
  #=> [0, 0.25, ..., 10]
125
125
 
126
126
  # Function that approximate given function by polynom with power polynom_power in approximation nodes x and returns coefficients of approximating polynom
127
- result = Mathpack::Approximation::approximate_by_polynom(x: x, polynom_power: 5){ |x| Math.sin(x) }
127
+ result = Mathpack::Approximation.approximate_by_polynom(x: x, polynom_power: 5){ |x| Math.sin(x) }
128
128
  #=> [0.0008009744982571882, -0.030619986086758588, 0.3805927651948083, -1.8481035413353888, 2.985465287759307, -0.3873066069630569]
129
129
 
130
130
  # May be you want to print this polynom, let's call print_polynom function
131
- Mathpack::Approximation::print_polynom(result)
131
+ Mathpack::Approximation.print_polynom(result)
132
132
  #=> 0.0008009744982571882*x^5 - 0.030619986086758588*x^4 + 0.3805927651948083*x^3 - 1.8481035413353888*x^2 + 2.985465287759307*x - 0.3873066069630569
133
133
 
134
134
  # If you have a table of values, where x - array of arguement values and f - array of function values, call approximate by polynom function with parameter f instead of block
135
- result = Mathpack::Approximation::approximate_by_polynom(x: [1, 2, 3], f: [1, 4, 9], polynom_power: 2) #=> [1, 0, 0]
136
- Mathpack::Approximation::print_polynom(result) #=> x^2
135
+ result = Mathpack::Approximation.approximate_by_polynom(x: [1, 2, 3], f: [1, 4, 9], polynom_power: 2) #=> [1, 0, 0]
136
+ Mathpack::Approximation.print_polynom(result) #=> x^2
137
+ ```
138
+
139
+ ## Integration
140
+ `Integration` module has method `integrate`, which is used to integrate numericality various functions.
141
+
142
+ ### Usage
143
+ Let you have the following integral:
144
+
145
+ ![equation](http://latex.codecogs.com/gif.latex?%5Cint_%7Ba%7D%5E%7Bb%7Df%28x%29dx)
146
+
147
+ Where *a* can be finite or equal to ![equation](http://latex.codecogs.com/gif.latex?-%5Cinfty), and *b* can be finite or equal to ![equation](http://latex.codecogs.com/gif.latex?%5Cinfty). To find value of integral you should call **integrate** method of Integration module.
148
+ ```ruby
149
+ Mathpack::Integration.integrate(from: a, to: b){ |x| f(x) }
150
+ ```
151
+ Let's demostrate some examples of Integration module practical usage:
152
+ ```ruby
153
+ Mathpack::Integration.integrate(from: 0, to: 3.6){ |x| Math.sin(x) / x } #=> 1.8219481156495034
154
+ Mathpack::Integration.integrate(from: 0, to: Float::INFINITY){ |x| Math.exp(-x) / (x + 1) } #=> 0.5963473623136091
155
+ Mathpack::Integration.integrate(from: -Float::INFINITY, to: Float::INFINITY){ |x| Math.exp(-x**2) * Math.cos(x) } #=> 1.3803884100161075
156
+ ```
157
+
158
+ ## IO
159
+
160
+ `IO` module allows to output complex data
161
+
162
+ ### Usage
163
+
164
+ If you have table function, represented by argument array and function values array, you should use
165
+ `print_table_function`, that prints your data to `.csv` file.
166
+ ```ruby
167
+ Mathpack::IO.print_table_function(filename: 'table.csv', x: [1, 2, 3], y: [2, 4, 6], labels: { x: 'x', y: 'f(x)'}
137
168
  ```
138
169
 
139
170
  ## Contributing
@@ -57,11 +57,11 @@ module Mathpack
57
57
  nodes = []
58
58
  i = 0
59
59
  loop do
60
- nodes << params[:start] + i * params[:step]
60
+ nodes << params[:from] + i * params[:step]
61
61
  i += 1
62
- break if params[:start] + i * params[:step] > params[:end]
62
+ break if params[:from] + i * params[:step] > params[:to]
63
63
  end
64
- nodes << params[:end] if nodes.last != params[:end]
64
+ nodes << params[:to] if nodes.last != params[:to]
65
65
  nodes
66
66
  end
67
67
 
@@ -5,7 +5,10 @@ module Mathpack
5
5
 
6
6
  def self.integrate(params = {}, &f)
7
7
  if params[:from] == -Float::INFINITY && params[:to] == Float::INFINITY
8
- result = solve_ni_2(&f)
8
+ result = solve_oi(-INTEGRATION_LIMIT, INTEGRATION_LIMIT, &f)
9
+ g = ->(x) { f.call(-x) }
10
+ result += solve_ni_1(INTEGRATION_LIMIT, &g)
11
+ result += solve_ni_1(INTEGRATION_LIMIT, &f)
9
12
  elsif params[:to] == Float::INFINITY || params[:from] == -Float::INFINITY
10
13
  if params[:from] == -Float::INFINITY
11
14
  params[:from] = -params[:to]
@@ -29,7 +32,7 @@ module Mathpack
29
32
 
30
33
  def self.solve_oi(from, to, &f)
31
34
  result = 0.0
32
- nodes = Mathpack::Approximation.generate_nodes(start: from, end: to, step: STEP)
35
+ nodes = Mathpack::Approximation.generate_nodes(from: from, to: to, step: STEP)
33
36
  for i in 0...nodes.length - 1 do
34
37
  result += basic_integrate(nodes[i], nodes[i + 1], &f)
35
38
  end
@@ -46,15 +49,5 @@ module Mathpack
46
49
  end
47
50
  result
48
51
  end
49
-
50
- def self.solve_ni_2(&f)
51
- result = 0.0
52
- coefficients_array = [0.004530009906, 0.1570673203, 0.7246295952, 0.7246295952, 0.1570673203, 0.004530009906]
53
- nodes_array = [-2.3506049737, -1.3358490740, -0.4360774119, 0.4360774119, 1.3358490740, 2.3506049737]
54
- nodes_array.each_index do |i|
55
- result += coefficients_array[i] * Math.exp(nodes_array[i]**2) * f.call(nodes_array[i])
56
- end
57
- result
58
- end
59
52
  end
60
53
  end
@@ -0,0 +1,13 @@
1
+ module Mathpack
2
+ module IO
3
+ def self.print_table_function(params = {})
4
+ fail 'Arrays length dismatch' if params[:x].length != params[:y].length
5
+ File.open(params[:filename] || 'table_function.csv', 'w+') do |file|
6
+ file.write("#{params[:labels][:x]};#{params[:labels][:y]}\n") if params[:labels] && params[:labels][:x] && params[:labels][:y]
7
+ params[:x].each_index do |i|
8
+ file.write("#{params[:x][i]};#{params[:y][i]}\n")
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/mathpack/sle.rb CHANGED
@@ -6,11 +6,12 @@ module Mathpack
6
6
 
7
7
  def self.solve(params)
8
8
  type = params[:f].class
9
- @matrix = params[:matrix].dup.to_a
10
- @f = params[:f].dup.to_a.flatten
9
+ @matrix = Marshal.load(Marshal.dump(params[:matrix])).to_a
10
+ @f = params[:f].to_a.flatten
11
+ fail 'Incorrect size of array or vector' unless @matrix.length == @matrix.first.length && @matrix.length == @f.length
11
12
  @number = @f.length
12
13
  @x = Array.new(@number) { |i| i + 1 }
13
- fail 'SLE can\'t be solved' unless solve_direct
14
+ fail 'Matrix is singular' unless solve_direct
14
15
  type == Matrix ? Matrix.row_vector(solve_reverse) : solve_reverse
15
16
  end
16
17
 
@@ -2,6 +2,7 @@ module Mathpack
2
2
  class Statistics
3
3
  def initialize(series)
4
4
  @series = series
5
+ @data_set, @frequency = parse_series(series)
5
6
  end
6
7
 
7
8
  def number
@@ -21,27 +22,31 @@ module Mathpack
21
22
  end
22
23
 
23
24
  def kurtosis
24
- central_moment(4) / variance**2
25
+ central_moment(4) / variance**2 - 3.0
25
26
  end
26
27
 
27
28
  def max
28
- @series.max
29
+ @data_set.max
29
30
  end
30
31
 
31
32
  def min
32
- @series.min
33
+ @data_set.min
33
34
  end
34
35
 
35
36
  def raw_moment(power)
36
37
  raw_moment = 0.0
37
- @series.each { |x| raw_moment += x**power }
38
+ @data_set.each_index do |i|
39
+ raw_moment += @frequency[i] * @data_set[i]**power
40
+ end
38
41
  raw_moment / number
39
42
  end
40
43
 
41
44
  def central_moment(power)
42
45
  central_moment = 0.0
43
46
  m = mean
44
- @series.each { |x| central_moment += (x - m)**power }
47
+ @data_set.each_index do |i|
48
+ central_moment += @frequency[i] * (@data_set[i] - m)**power
49
+ end
45
50
  central_moment / number
46
51
  end
47
52
 
@@ -53,14 +58,9 @@ module Mathpack
53
58
 
54
59
  def print_empirical_cdf_to_csv(filename)
55
60
  step = 0.5 * (max - min) / number
56
- val = min - step
57
- File.open(filename, 'w+') do |file|
58
- while val <= max + step
59
- file.write("#{val};")
60
- file.write("#{empirical_cdf(val)}\n")
61
- val += step
62
- end
63
- end
61
+ nodes = Mathpack::Approximation.generate_nodes(from: min - step, to: max + step, step: step)
62
+ values = nodes.map { |x| empirical_cdf(x) }
63
+ Mathpack::IO.print_table_function(filename: filename, x: nodes, y: values)
64
64
  end
65
65
 
66
66
  def empirical_pdf(x)
@@ -72,14 +72,9 @@ module Mathpack
72
72
 
73
73
  def print_empirical_pdf_to_csv(filename)
74
74
  step = 0.5 * (max - min) / number
75
- val = min - 10 * step
76
- File.open(filename, 'w+') do |file|
77
- while val <= max + 10 * step
78
- file.write("#{val};")
79
- file.write("#{empirical_pdf(val)}\n")
80
- val += step
81
- end
82
- end
75
+ nodes = Mathpack::Approximation.generate_nodes(from: min - 10 * step, to: max + 10 * step, step: step)
76
+ values = nodes.map { |x| empirical_pdf(x) }
77
+ Mathpack::IO.print_table_function(filename: filename, x: nodes, y: values)
83
78
  end
84
79
 
85
80
  def trend(params = {})
@@ -93,5 +88,19 @@ module Mathpack
93
88
  def heaviside(x)
94
89
  x <= 0 ? 0 : 1
95
90
  end
91
+
92
+ def parse_series(series)
93
+ data_set = []
94
+ frequency = []
95
+ series.each do |element|
96
+ if data_set.include? element
97
+ frequency[data_set.index(element)] += 1
98
+ else
99
+ data_set << element
100
+ frequency[data_set.index(element)] = 1
101
+ end
102
+ end
103
+ [data_set, frequency]
104
+ end
96
105
  end
97
106
  end
@@ -1,3 +1,3 @@
1
1
  module Mathpack
2
- VERSION = '0.4.1'
2
+ VERSION = '0.4.2'
3
3
  end
data/lib/mathpack.rb CHANGED
@@ -4,3 +4,4 @@ require 'mathpack/equation'
4
4
  require 'mathpack/sle'
5
5
  require 'mathpack/approximation'
6
6
  require 'mathpack/integration'
7
+ require 'mathpack/io'
@@ -5,7 +5,7 @@ describe 'Approximation' do
5
5
  let(:x_start) { 0.0 }
6
6
  let(:x_end) { 10.0 }
7
7
  let(:step) { 0.25 }
8
- let(:nodes) { Mathpack::Approximation.generate_nodes(start: x_start, end: x_end, step: step) }
8
+ let(:nodes) { Mathpack::Approximation.generate_nodes(from: x_start, to: x_end, step: step) }
9
9
  let(:values) { Mathpack::Approximation.fill_f(nodes){ |val| val**2 } }
10
10
 
11
11
  it 'should generate nodes' do
@@ -15,7 +15,7 @@ describe 'Approximation' do
15
15
  end
16
16
 
17
17
  it 'should generate correct nodes' do
18
- nodes = Mathpack::Approximation.generate_nodes(start: 0, end: 1, step: 0.001)
18
+ nodes = Mathpack::Approximation.generate_nodes(from: 0, to: 1, step: 0.001)
19
19
  expect(nodes.last).to eq(1.0)
20
20
  end
21
21
 
data/spec/sle_spec.rb CHANGED
@@ -12,12 +12,26 @@ describe 'SLE' do
12
12
  expect(Mathpack::SLE.solve(matrix: a, f: b)).to eq([-1.0, 2.0, 4.0])
13
13
  end
14
14
 
15
- it 'should raise error' do
15
+ it 'should raise error when matrix is singular' do
16
16
  expect { Mathpack::SLE.solve(matrix: unsolved, f: b) }.to raise_error
17
17
  end
18
18
 
19
+ it 'should raise error when matrix has incorrect size' do
20
+ b << 1
21
+ expect { Mathpack::SLE.solve(matrix: a, f: b) }.to raise_error
22
+ b.pop
23
+ a << [1, 2, 3, 4]
24
+ expect { Mathpack::SLE.solve(matrix: a, f: b) }.to raise_error
25
+ end
26
+
19
27
  it 'should return vector if matrix class is given' do
20
28
  expect(Mathpack::SLE.solve(matrix: matrix_a, f: vector_b)).to eq(Matrix.row_vector [-1.0, 2.0, 4.0])
21
29
  end
30
+
31
+ it 'should not change source data' do
32
+ Mathpack::SLE.solve(matrix: a, f: b)
33
+ expect(a).to eq([[1, 2, 3], [4, 5, 6], [3, 5, 2]])
34
+ expect(b).to eq([15, 30, 15])
35
+ end
22
36
  end
23
37
  end
@@ -3,35 +3,43 @@ describe 'Statistics' do
3
3
 
4
4
  describe '#calculate statistics functions' do
5
5
 
6
- let(:data) { [1, 5, 4, 2, 3, 4, 5, 7, 2, 7] }
6
+ let(:data) do
7
+ array = []
8
+ array << [0]*50
9
+ array << [1]*35
10
+ array << [2]*10
11
+ array << [3]*4
12
+ array << [4]*1
13
+ array.flatten
14
+ end
7
15
  let(:stat) { Mathpack::Statistics.new(data) }
8
16
 
9
17
  it 'should calculate number of elements' do
10
- expect(stat.number).to eq(10)
18
+ expect(stat.number).to eq(100)
11
19
  end
12
20
 
13
21
  it 'should calculate mean' do
14
- expect(stat.mean).to eq(4.0)
22
+ expect(stat.mean).to eq(0.71)
15
23
  end
16
24
 
17
25
  it 'should calculate variance' do
18
- expect(stat.variance).to eq(3.8)
26
+ expect(stat.variance).to eq(0.7659)
19
27
  end
20
28
 
21
29
  it 'should calculate skewness' do
22
- expect(stat.skewness).to eq(0.16199658190818222)
30
+ expect(stat.skewness).to eq(1.3139557526940238)
23
31
  end
24
32
 
25
33
  it 'should calculate kurtosis' do
26
- expect(stat.kurtosis).to eq(1.925207756232687)
34
+ expect(stat.kurtosis).to eq(1.5654257435282322)
27
35
  end
28
36
 
29
37
  it 'should calculate the minimal element' do
30
- expect(stat.min).to eq(1)
38
+ expect(stat.min).to eq(0)
31
39
  end
32
40
 
33
41
  it 'should calculate the maximal element' do
34
- expect(stat.max).to eq(7)
42
+ expect(stat.max).to eq(4)
35
43
  end
36
44
 
37
45
  it 'should calculate first raw moment equal to mean' do
@@ -43,25 +51,25 @@ describe 'Statistics' do
43
51
  end
44
52
 
45
53
  it 'should calculate raw moments' do
46
- expect(stat.raw_moment(3)).to eq(110.8)
54
+ expect(stat.raw_moment(3)).to eq(2.87)
47
55
  end
48
56
 
49
57
  it 'should calculate central moments' do
50
- expect(stat.central_moment(5)).to eq(18.0)
58
+ expect(stat.central_moment(5)).to eq(6.641392040400001)
51
59
  end
52
60
 
53
61
  it 'should calculate empirical cdf values in points' do
54
62
  expect(stat.empirical_cdf(stat.min - 0.1)).to eq(0.0)
55
63
  expect(stat.empirical_cdf(stat.max + 0.1)).to eq(1.0)
56
- expect(stat.empirical_cdf(stat.mean)).to eq(0.4)
64
+ expect(stat.empirical_cdf(stat.mean)).to eq(0.5)
57
65
  end
58
66
 
59
67
  it 'should calculate empirical pdf values in points' do
60
- expect(stat.empirical_pdf(stat.mean)).to eq(0.1882412842233359)
68
+ expect(stat.empirical_pdf(stat.mean)).to eq( 0.4308095750697591)
61
69
  end
62
70
 
63
71
  it 'should find trend' do
64
- expect(stat.trend(polynom_power: 2)).to eq('0.0075757575757576055*x^2 + 0.2681818181818179*x + 2.233333333333334')
72
+ expect(stat.trend(polynom_power: 2)).to eq('0.00042531864230840915*x^2 - 0.016860573212183233*x + 0.12239332096475111')
65
73
  end
66
74
  end
67
75
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mathpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - maxmilan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-22 00:00:00.000000000 Z
11
+ date: 2015-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -55,6 +55,7 @@ files:
55
55
  - lib/mathpack/approximation.rb
56
56
  - lib/mathpack/equation.rb
57
57
  - lib/mathpack/integration.rb
58
+ - lib/mathpack/io.rb
58
59
  - lib/mathpack/sle.rb
59
60
  - lib/mathpack/statistics.rb
60
61
  - lib/mathpack/version.rb