mathpack 0.1.0 → 0.2.0

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: f2feda03bce968d1a492dd5c6cfa99bfe1d8796c
4
- data.tar.gz: 6b4908827c465f97ca042c266a393e8fb572ee94
3
+ metadata.gz: 8c14dffa0f11862781796118a019139c018cb2eb
4
+ data.tar.gz: b2be5e7d8b8bfdac4d40003a72109b6b0b9ea366
5
5
  SHA512:
6
- metadata.gz: e013b0cb1cb1339ca1b2572593b8d77dea7d4b11f678675a199125595b682f559a651d3d1ab807bb346e42084997b234bb1f969f503434be0ec5f69073adf6aa
7
- data.tar.gz: 56d13a5f3c6fea715fa823e21197ef368d4591f5d3b83c250d56174d122d762a1cf81e1446788a9d2a7e054f1e5cc21d300555844d54c265ea506de758e10055
6
+ metadata.gz: a4dcfdfcd380f2f3e23587210cfb594e533c0cc341b6a5862ec4e7891b8d72d72c8e6f09f7c7156f03bf74d87c204ee54f4baa16f76895ac55e3b62a5e964d01
7
+ data.tar.gz: edd6fce95f19953b01d6fc92a89b645fa52a855579c4136306e8b2e7ba33480a622d6b07abf3bb92f6772c5287f9e8d86a30ee6e0aebd8d1363f4fb4611ca7fe
data/.gitignore CHANGED
@@ -20,3 +20,4 @@ tmp
20
20
  *.o
21
21
  *.a
22
22
  mkmf.log
23
+ .rubocop.yml
data/.travis.yml CHANGED
@@ -4,6 +4,7 @@ rvm:
4
4
  - 2.0.0
5
5
  - 2.1.2
6
6
  - 2.1.3
7
+ - 2.2.0
7
8
  script: "bundle exec rspec"
8
9
  notifications:
9
10
  email: false
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem "rspec", :group => :test
3
+ gem 'rspec', group: :test
4
4
  gemspec
data/README.md CHANGED
@@ -18,8 +18,8 @@ Or install it yourself as:
18
18
 
19
19
  $ gem install mathpack
20
20
  ## Information
21
- Gem `mathpack` allows to count statistical functions through `Statistics` class, solving nonlinear equations through `Equation` module
22
- `solve` method
21
+ Gem `mathpack` allows to count statistical functions through `Statistics` class, solve nonlinear equations through `Equation` module
22
+ `solve` method, solve systems of linear equations through `SLE` module `solve` method.
23
23
  ## Statistics
24
24
  `Statistics` class have following methods
25
25
  - **number** - returns a number of elements in series
@@ -62,11 +62,10 @@ stat.print_empirical_pdf_to_csv('pdf.csv') #=> nil
62
62
  Now you have no problems solving **nonlinear equations**. If you want, for example, to solve equation ![equation](http://latex.codecogs.com/gif.latex?x%5E%7B2%7D%20%3D%20%5Csin%28%7Bx+1%7D%29)
63
63
 
64
64
  You need to complete the following steps:
65
- 1. Equation should look like
66
- ![equation](http://latex.codecogs.com/gif.latex?%5Ctiny%20f%28x%29%20%3D%200)
67
- 2. For our equation ![equation](http://latex.codecogs.com/gif.latex?%5Csmall%20f%28x%29%20%3D%20x%5E%7B2%7D%20-%20%5Csin%28x+1%29)
68
- 3. Choose the calculations accurracy. For example ![equation](http://latex.codecogs.com/gif.latex?%5Csmall%200.00001)
69
- 4. Choose some point near the expected root of equation. For example ![equation](http://latex.codecogs.com/gif.latex?%5Csmall%200)
65
+ - Equation should look like ![equation](http://latex.codecogs.com/gif.latex?%5Ctiny%20f%28x%29%20%3D%200)
66
+ - For our equation ![equation](http://latex.codecogs.com/gif.latex?%5Csmall%20f%28x%29%20%3D%20x%5E%7B2%7D%20-%20%5Csin%28x+1%29)
67
+ - Choose the calculations accurracy. For example ![equation](http://latex.codecogs.com/gif.latex?%5Csmall%200.00001)
68
+ - Choose some point near the expected root of equation. For example ![equation](http://latex.codecogs.com/gif.latex?%5Csmall%200)
70
69
 
71
70
  Then to solve equation you should call
72
71
  ```ruby
@@ -80,6 +79,31 @@ Mathpack::Equation.solve(start: 0.01, eps: 0.00001){|x| x**2 - 2*x + 1})
80
79
  Mathpack::Equation.solve(start: 0.01, eps: 0.00001){|x| Math.exp(x-2) - Math.sin(x)})
81
80
  ```
82
81
 
82
+ ## SLE
83
+ `SLE` module has only one method
84
+ - **solve** - method, which allows to solve *system of linear equations*. Neccessary params are `matrix` representing system matrix and `f`. Params can be **Array** or **Matrix** class. If the system can't be solved, method raise exception
85
+
86
+ ## Usage
87
+ Let's solve some system of linear equations. It can be written as
88
+
89
+ ![equation](http://latex.codecogs.com/gif.latex?%5Csmall%20AX%20%3D%20B)
90
+
91
+ where A is n*n matrix, X - vector of unknown, B - vector
92
+
93
+ If you want to solve this system you should call
94
+ ```ruby
95
+ Mathpack::SLE.solve(matrix: A, f: B)
96
+ ```
97
+ Parameter A can be Array or Matrix class. If Array is given result will be Array class. If Matrix is given result will be Matrix class.
98
+ ```ruby
99
+ a = [[1, 2, 3], [4, 5, 6],[3, 5, 2]]
100
+ b = [15, 30, 15]
101
+ Mathpack::SLE.solve(matrix: a, f: b) #=> [-1.0, 2.0, 4.0]
102
+ a = Matrix[[1, 2, 3], [4, 5, 6],[3, 5, 2]]
103
+ b = Matrix.row_vector [15, 30, 15]
104
+ Mathpack::SLE.solve(matrix: a, f: b) #=> Matrix[[-1.0, 2.0, 4.0]]
105
+ ```
106
+
83
107
  ## Contributing
84
108
 
85
109
  1. Fork it ( https://github.com/[my-github-username]/mathpack/fork )
data/Rakefile CHANGED
@@ -1,2 +1 @@
1
- require "bundler/gem_tasks"
2
-
1
+ require 'bundler/gem_tasks'
@@ -1,14 +1,18 @@
1
1
  module Mathpack
2
2
  module Equation
3
- def self.solve(param = {}, &function)
4
- derivate_eps = 1e-5
5
- xk1 = param[:start]
3
+ def self.solve(params = {}, &function)
4
+ xk1 = params[:start]
6
5
  loop do
7
6
  xk = xk1
8
- xk1 = xk - function.call(xk)/((function.call(xk + derivate_eps) - function.call(xk - derivate_eps))/(2*derivate_eps))
9
- break if (xk1 - xk).abs < param[:eps]
7
+ xk1 = xk - function.call(xk) / derivative(xk, &function)
8
+ break if (xk1 - xk).abs < params[:eps]
10
9
  end
11
- return xk1
10
+ xk1
11
+ end
12
+
13
+ def self.derivative(xk, &function)
14
+ eps = 1e-5
15
+ (function.call(xk + eps) - function.call(xk - eps)) / (2 * eps)
12
16
  end
13
17
  end
14
18
  end
@@ -0,0 +1,75 @@
1
+ require 'matrix'
2
+
3
+ module Mathpack
4
+ module SLE
5
+ EPS = 1e-14
6
+
7
+ def self.solve(params)
8
+ type = params[:f].class
9
+ @matrix = params[:matrix].to_a
10
+ @f = params[:f].to_a.flatten
11
+ @number = @f.length
12
+ @x = Array.new(@number) { |i| i + 1 }
13
+ fail 'SLE can\'t be solved' unless solve_direct
14
+ type == Matrix ? Matrix.row_vector(solve_reverse) : solve_reverse
15
+ end
16
+
17
+ def self.swap_lines(first_line, second_line)
18
+ 0.upto(@number - 1) do |j|
19
+ @matrix[first_line][j], @matrix[second_line][j] = @matrix[second_line][j], @matrix[first_line][j]
20
+ end
21
+ @f[first_line], @f[second_line] = @f[second_line], @f[first_line]
22
+ end
23
+
24
+ def self.swap_columns(first_column, second_column)
25
+ 0.upto(@number - 1) do |i|
26
+ @matrix[i][first_column], @matrix[i][second_column] = @matrix[i][second_column], @matrix[i][first_column]
27
+ end
28
+ @x[first_column], @x[second_column] = @x[second_column], @x[first_column]
29
+ end
30
+
31
+ def self.make_null_column(step)
32
+ (step + 1).upto(@number - 1) do |i|
33
+ alpha = -@matrix[i][step] / @matrix[step][step].to_f
34
+ step.upto(@number - 1) do |j|
35
+ @matrix[i][j] += @matrix[step][j] * alpha
36
+ end
37
+ @f[i] += @f[step] * alpha
38
+ end
39
+ end
40
+
41
+ def self.solve_direct
42
+ 0.upto(@number - 1) do |i|
43
+ maximum = 0.0
44
+ max_line = i
45
+ max_column = i
46
+ i.upto(@number - 1) do |line|
47
+ i.upto(@number - 1) do |column|
48
+ maximum, max_line, max_column = @matrix[line][column].abs, line, column if @matrix[line][column].abs > maximum
49
+ end
50
+ end
51
+ return false if maximum < EPS
52
+ swap_lines(i, max_line) if (max_line != i)
53
+ swap_columns(i, max_column) if (max_column != i)
54
+ make_null_column(i)
55
+ end
56
+ true
57
+ end
58
+
59
+ def self.solve_reverse
60
+ result_vector = Array.new(@number)
61
+ (@number - 1).downto(0) do |i|
62
+ if i == (@number - 1)
63
+ result_vector[@x[i] - 1] = @f[i] / @matrix[i][i]
64
+ else
65
+ sum = 0.0
66
+ (i + 1).upto(@number - 1) do |j|
67
+ sum += @matrix[i][j] * result_vector[@x[j] - 1]
68
+ end
69
+ result_vector[@x[i] - 1] = (@f[i] - sum) / @matrix[i][i]
70
+ end
71
+ end
72
+ result_vector
73
+ end
74
+ end
75
+ end
@@ -34,28 +34,28 @@ module Mathpack
34
34
 
35
35
  def raw_moment(power)
36
36
  raw_moment = 0.0
37
- @series.each{ |x| raw_moment += x**power }
37
+ @series.each { |x| raw_moment += x**power }
38
38
  raw_moment / number
39
39
  end
40
40
 
41
41
  def central_moment(power)
42
42
  central_moment = 0.0
43
43
  m = mean
44
- @series.each{ |x| central_moment += (x - m)**power }
44
+ @series.each { |x| central_moment += (x - m)**power }
45
45
  central_moment / number
46
46
  end
47
47
 
48
48
  def empirical_cdf(x)
49
49
  result = 0.0
50
- @series.each{ |val| result += e(x - val) }
50
+ @series.each { |val| result += heaviside(x - val) }
51
51
  result / number
52
52
  end
53
53
 
54
54
  def print_empirical_cdf_to_csv(filename)
55
- step = 0.25
55
+ step = 0.5 * (max - min) / number
56
56
  val = min - step
57
57
  File.open(filename, 'w+') do |file|
58
- while val <= max + step do
58
+ while val <= max + step
59
59
  file.write("#{val};")
60
60
  file.write("#{empirical_cdf(val)}\n")
61
61
  val += step
@@ -64,17 +64,17 @@ module Mathpack
64
64
  end
65
65
 
66
66
  def empirical_pdf(x)
67
- h = variance**0.5 * number**(-1.0/6)
67
+ h = variance**0.5 * number**(-1.0 / 6)
68
68
  result = 0.0
69
- @series.each{ |val| result += (e(x - val + h) - e(x - val - h))/(2*h) }
69
+ @series.each { |val| result += (heaviside(x - val + h) - heaviside(x - val - h)) / (2 * h) }
70
70
  result / number
71
71
  end
72
72
 
73
73
  def print_empirical_pdf_to_csv(filename)
74
- step = 0.25
75
- val = min - 2*step
74
+ step = 0.5 * (max - min) / number
75
+ val = min - 10 * step
76
76
  File.open(filename, 'w+') do |file|
77
- while val <= max + 2*step do
77
+ while val <= max + 10 * step
78
78
  file.write("#{val};")
79
79
  file.write("#{empirical_pdf(val)}\n")
80
80
  val += step
@@ -84,7 +84,7 @@ module Mathpack
84
84
 
85
85
  private
86
86
 
87
- def e(x)
87
+ def heaviside(x)
88
88
  x <= 0 ? 0 : 1
89
89
  end
90
90
  end
@@ -1,3 +1,3 @@
1
1
  module Mathpack
2
- VERSION = "0.1.0"
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/mathpack.rb CHANGED
@@ -1,3 +1,4 @@
1
- require "mathpack/version"
1
+ require 'mathpack/version'
2
2
  require 'mathpack/statistics'
3
3
  require 'mathpack/equation'
4
+ require 'mathpack/sle'
data/mathpack.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'mathpack/version'
4
+ require "mathpack/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "mathpack"
@@ -9,13 +9,13 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["maxmilan"]
10
10
  spec.email = ["max231194@gmail.com"]
11
11
  spec.summary = "Summary"
12
- spec.description ="Includes collection of mathematical methods"
12
+ spec.description = "Includes collection of mathematical methods"
13
13
  spec.homepage = ""
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.executables = spec.files.grep(%r{^bin/$}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/$})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
@@ -1,14 +1,14 @@
1
1
  describe 'Equations' do
2
2
  require 'mathpack/equation'
3
3
 
4
- context 'calculate nonlinear equations' do
4
+ context '#solve nonlinear equations' do
5
+ let(:eps) { 0.00001 }
5
6
 
6
- it 'should solve equation' do
7
- eps = 0.00001
8
- expect(Mathpack::Equation.solve(start: 0, eps: eps){|x| x**2 - Math.sin(x+1)}).to be_between(-0.613763 - eps, -0.613763 + eps)
9
- expect(Mathpack::Equation.solve(start: 0.01, eps: eps){|x| 1/x - Math.log(x)}).to be_between(1.76322 - eps, 1.76322 + eps)
10
- expect(Mathpack::Equation.solve(start: 0.01, eps: eps){|x| x**2 - 2*x + 1}).to be_between(1.0 - eps, 1.0 + eps)
11
- expect(Mathpack::Equation.solve(start: 0.01, eps: eps){|x| Math.exp(x-2) - Math.sin(x)}).to be_between(0.159396 - eps, 0.159396 + eps)
7
+ it 'should give correct results' do
8
+ expect(Mathpack::Equation.solve(start: 0, eps: eps) { |x| x**2 - Math.sin(x + 1) }).to be_between(-0.613763 - eps, -0.613763 + eps)
9
+ expect(Mathpack::Equation.solve(start: 0.01, eps: eps) { |x| 1 / x - Math.log(x) }).to be_between(1.76322 - eps, 1.76322 + eps)
10
+ expect(Mathpack::Equation.solve(start: 0.01, eps: eps) { |x| x**2 - 2 * x + 1 }).to be_between(1.0 - eps, 1.0 + eps)
11
+ expect(Mathpack::Equation.solve(start: 0.01, eps: eps) { |x| Math.exp(x - 2) - Math.sin(x) }).to be_between(0.159396 - eps, 0.159396 + eps)
12
12
  end
13
13
  end
14
14
  end
data/spec/sle_spec.rb ADDED
@@ -0,0 +1,23 @@
1
+ describe 'SLE' do
2
+ require 'mathpack/sle'
3
+
4
+ context '#solve systems of linear equations' do
5
+ let(:a) { [[1, 2, 3], [4, 5, 6], [3, 5, 2]] }
6
+ let(:unsolved) { [[1, 2, 3], [1, 2, 3], [3, 5, 2]] }
7
+ let(:b) { [15, 30, 15] }
8
+ let(:matrix_a) { Matrix[[1, 2, 3], [4, 5, 6], [3, 5, 2]] }
9
+ let(:vector_b) { Matrix.row_vector([15, 30, 15]) }
10
+
11
+ it 'should give correct answer' do
12
+ expect(Mathpack::SLE.solve(matrix: a, f: b)).to eql([-1.0, 2.0, 4.0])
13
+ end
14
+
15
+ it 'should raise error' do
16
+ expect { Mathpack::SLE.solve(matrix: unsolved, f: b) }.to raise_error
17
+ end
18
+
19
+ it 'should return vector if matrix class is given' do
20
+ expect(Mathpack::SLE.solve(matrix: matrix_a, f: vector_b)).to eql(Matrix.row_vector [-1.0, 2.0, 4.0])
21
+ end
22
+ end
23
+ end
@@ -1,62 +1,62 @@
1
1
  describe 'Statistics' do
2
2
  require 'mathpack/statistics'
3
3
 
4
- describe "calculated statistics functions" do
4
+ describe '#calculate statistics functions' do
5
5
 
6
- let(:data) { [1,5,4,2,3,4,5,7,2,7] }
6
+ let(:data) { [1, 5, 4, 2, 3, 4, 5, 7, 2, 7] }
7
7
  let(:stat) { Mathpack::Statistics.new(data) }
8
8
 
9
- it "calculates the number" do
9
+ it 'should calculate number of elements' do
10
10
  expect(stat.number).to eql(10)
11
11
  end
12
12
 
13
- it "calculates the mean" do
13
+ it 'should calculate mean' do
14
14
  expect(stat.mean).to eql(4.0)
15
15
  end
16
16
 
17
- it "calculates the variance" do
17
+ it 'should calculate variance' do
18
18
  expect(stat.variance).to eql(3.8)
19
19
  end
20
20
 
21
- it "calculates the skewness" do
21
+ it 'should calculate skewness' do
22
22
  expect(stat.skewness).to eql(0.16199658190818222)
23
23
  end
24
24
 
25
- it "calculates the kurtosis" do
25
+ it 'should calculate kurtosis' do
26
26
  expect(stat.kurtosis).to eql(1.925207756232687)
27
27
  end
28
28
 
29
- it "calculates the minimal element" do
29
+ it 'should calculate the minimal element' do
30
30
  expect(stat.min).to eql(1)
31
31
  end
32
32
 
33
- it "calculates maximal element" do
33
+ it 'should calculate the maximal element' do
34
34
  expect(stat.max).to eql(7)
35
35
  end
36
36
 
37
- it "calculates first raw moment equal to mean" do
37
+ it 'should calculate first raw moment equal to mean' do
38
38
  expect(stat.raw_moment(1)).to eql(stat.mean)
39
39
  end
40
40
 
41
- it "calculates second central moment equal to variance" do
41
+ it 'should calculate second central moment equal to variance' do
42
42
  expect(stat.central_moment(2)).to eql(stat.variance)
43
43
  end
44
44
 
45
- it "calculates raw moment" do
45
+ it 'should calculate raw moments' do
46
46
  expect(stat.raw_moment(3)).to eql(110.8)
47
47
  end
48
48
 
49
- it "calculates central moment" do
49
+ it 'should calculate central moments' do
50
50
  expect(stat.central_moment(5)).to eql(18.0)
51
51
  end
52
52
 
53
- it "calculates empirical cdf" do
53
+ it 'should calculate empirical cdf values in points' do
54
54
  expect(stat.empirical_cdf(stat.min - 0.1)).to eql(0.0)
55
55
  expect(stat.empirical_cdf(stat.max + 0.1)).to eql(1.0)
56
56
  expect(stat.empirical_cdf(stat.mean)).to eql(0.4)
57
57
  end
58
58
 
59
- it "calculates empirical pdf" do
59
+ it 'should calculate empirical pdf values in points' do
60
60
  expect(stat.empirical_pdf(stat.mean)).to eql(0.1882412842233359)
61
61
  end
62
62
  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.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - maxmilan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-30 00:00:00.000000000 Z
11
+ date: 2014-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,10 +53,12 @@ files:
53
53
  - Rakefile
54
54
  - lib/mathpack.rb
55
55
  - lib/mathpack/equation.rb
56
+ - lib/mathpack/sle.rb
56
57
  - lib/mathpack/statistics.rb
57
58
  - lib/mathpack/version.rb
58
59
  - mathpack.gemspec
59
60
  - spec/equation_spec.rb
61
+ - spec/sle_spec.rb
60
62
  - spec/statistics_spec.rb
61
63
  homepage: ''
62
64
  licenses:
@@ -82,6 +84,4 @@ rubygems_version: 2.2.2
82
84
  signing_key:
83
85
  specification_version: 4
84
86
  summary: Summary
85
- test_files:
86
- - spec/equation_spec.rb
87
- - spec/statistics_spec.rb
87
+ test_files: []