This gem includes a collection of mathematical methods
Add this line to your application's Gemfile:
gem 'mathpack'
And then execute:
$ bundle
Or install it yourself as:
$ gem install mathpack
Mathpack
includes following modules:
- SLE. Solves system of linear equations
- Statistics. Provides methods to analyze data samples
- Functions. Collects mathematical functions
- Approximation. Allows to approximate table and analytical functions by polynom
- NonlinearEquations. Solves nonlinear mathematical equations
- IntegralEquations. Solves integral second order Fredholm and Volter equations
- DifferentialEquations. Solves system of differential equations with left border initial conditions
- Integration. Integrates functions
- IO. Prints data
- Functional. Lambda functions
Statistics
class have following methods
returns a number of elements in series
returns a mean of series
returns a variance of series
returns a skewness
returns a kurtosis
returns the minimal element of series
returns the maxinal element of series
returns the nth raw moment of series
returns the nth central moment of series
empirical distribution function value in x
returns empirical probability density function value in x
allows to print empirical_cdf table function to filename
allows to print empirical_pdf table function to filename
returns trend polynom coefficients
stat = Mathpack::Statistics.new([1, 2, 5, 6])
stat.number() #=> 4
stat.mean() #=> 3.5
stat.variance() #=> 4.25
stat.kurtosis() #=> -1.778546712802768
stat.skewness() #=> 0.0
stat.min() #=> 1
stat.max() #=> 6
stat.raw_moment(3) #=> 87.5
stat.central_moment(4) #=> 22.0625
stat.empirical_cdf(5.5) #=> 0.75
stat.empirical_pdf(3) #=> 0.07639393483317147
stat.print_empirical_cdf('cdf.csv') #=> nil
stat.print_empirical_pdf('pdf.csv') #=> nil
stat.trend(polynom_power: 1) #=> 1.7999999999999996*x - 0.9999999999999987
Functions
module includes a collection of popular functions.
returns solution of nonlinear equation.
- start - point to start iteration process
- eps - calculations accuraccy
Now you have no problems solving nonlinear equations. If you want, for example, to solve equation
You need to complete the following steps:
- Equation should look like
- For our equation
- Choose the calculations accurracy. For example
- Choose some point near the expected root of equation. For example
Then to solve equation you should call
Mathpack::NonlinearEquations.solve(start: 0, eps: 0.00001){|x| x**2 - Math.sin(x+1)})
Here is some other examples of solve usage
Mathpack::NonlinearEquations.solve(start: 0, eps: 0.00001){|x| x**2 - Math.sin(x+1)})
Mathpack::NonlinearEquations.solve(start: 0.01, eps: 0.00001){|x| 1/x - Math.log(x)})
Mathpack::NonlinearEquations.solve(start: 0.01, eps: 0.00001){|x| x**2 - 2*x + 1})
Mathpack::NonlinearEquations.solve(start: 0.01, eps: 0.00001){|x| Math.exp(x-2) - Math.sin(x)})
returns solution of system of nonlinear equations by Newton method
- start - vector to start iteration process
- eps - calculations accuraccy
- f - vector of right part lambdas
- w_matrix - matrix W in Newton method
If you have system of equations
For example, if you have system
W matrix and f vector is equal
f = -> x, y { [x + y - 3.0, x**2 + y**2 - 9.0] }
w = -> x, y { [[1, 1], [2 * x, 2 * y]] }
Mathpack::NonlinearEquations.solve_system(start: [1, 5], eps: 1e-4, f: f, w_matrix: w) #=> [-1.829420851037002e-12, 3.0000000000018296]
returns solution of integral equation as a hash of nodes and values arrays.
- from - left border
- to - right border
- lambda - lambda parameter
- k - kernel function (2 arguements)
- f - inhomogeneity function (1 arguement)
- eps - accuracy
Let we have the following integral equation
If you want to solve equation with accuracy 1e-5, you should call
k = -> x, t { 1.0 / (x + t**2)**0.5 }
f = -> x { 2*x + (x + 1)**0.5 - (x + 4)**0.5 }
Mathpack::IntegralEquations.solve_fredholm_2(from: 1.0, to: 2.0, lambda: 0.5, eps: 1e-5, k: k, f: f)
#=> {:x=>[1.0, 1.125, 1.25, 1.375, 1.5, 1.625, 1.75, 1.875, 2.0], :f=>[1.9999989550044168, 2.2499991010033416, 2.499999229316462, 2.7499993410739187, 2.9999994379022, 3.2499995215457123, 3.4999995936848047, 3.7499996558559117, 3.9999997094242845]}
returns solution of integral equation as a hash of nodes and values arrays.
- from - left border
- to - right border
- lambda - lambda parameter
- k - kernel function (2 arguements)
- f - inhomogeneity function (1 arguement)
- eps - accuracy
Let we have the following integral equation
If you want to solve equation with accuracy 1e-3, you should call
k = -> x, t { Math.cos(x - t) }
f = -> x { 0.75 * Math.exp(x) + 0.25 * Math.cos(x) - 0.25 * Math.sin(x) }
Mathpack::IntegralEquations.solve_volter_2(from: 0.0, to: 1.0, lambda: 0.5, eps: 1e-3, k: k, f: f)
#=> {:x=>[0.0, 0.0625, 0.125, 0.1875, 0.25, 0.3125, 0.375, 0.4375, 0.5, 0.5625, 0.625, 0.6875, 0.75, 0.8125, 0.875, 0.9375, 1.0], :f=>[1.0, 1.0644951210235056, 1.1331511709098798, 1.2062365414157485, 1.2840369296892897, 1.3668564541117094, 1.455018842114489, 1.5488686946157586, 1.6487728320186184, 1.755121727033003, 1.868331029922017, 1.9888431921348702, 2.117129194673052, 2.2536903879456665, 2.3990604503055315, 2.5538074729214233, 2.718536179135541]}
returns solution of differential equations system as a hash of nodes and values arrays for each function. For example, { x: [], u1: [], u2: [], ... }
- from - left border
- to - right border
- system - array of lambdas representing each row of system
- y0 - array of values of derivatives on left border. Starts with first derivative
- eps - accuracy
Let we have following system of differential equations
where
If you want to solve this system with accuracy 1e-6, you should call
cauchie_problem = [ ->(x, u1, u2) { u2 }, -> (x, u1, u2) { - 1.0 / x * u2 + 1.0 / x**2 * u1 + 3.0 }]
Mathpack::DifferentialEquations.solve_cauchie_system(from: 1.0, to: 2.0, eps: 1e-6, system: cauchie_problem, y0: [1.0, 1.0])
#=> {:x=>[1.0,..., 2.0], :u1=>[1,...], :u2=>[1,...] }
returns solution of system of linear equations.
- matrix - system matrix
- f - right part vector
Let's solve some system of linear equations. It can be written as
where A is n-n matrix, X - vector of unknown, B - vector
If you want to solve this system you should call
Mathpack::SLE.solve(matrix: A, f: B)
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.
a = [[1, 2, 3], [4, 5, 6],[3, 5, 2]]
b = [15, 30, 15]
Mathpack::SLE.solve(matrix: a, f: b) #=> [-1.0, 2.0, 4.0]
a = Matrix[[1, 2, 3], [4, 5, 6],[3, 5, 2]]
b = Matrix.row_vector [15, 30, 15]
Mathpack::SLE.solve(matrix: a, f: b) #=> Matrix[[-1.0, 2.0, 4.0]]
returns array of coefficients of polynom, approximating given function on [from, to] segment.
- x - array of approximation nodes
- polynom_power - power of approximation polynom
- f - functions values in x if you have table function
returns nodes for approximation with some step.
- from - first node
- to - last node
- step - step between nodes
returns a string representing polynom with given coefficients.
# Function to print polynom having it's coefficients
Mathpack::Approximation.print_polynom([1, -2, 1]) #=> x^2 - 2*x + 1
# Function to generate nodes for approximation. Only choose start value, end value and step
x = Mathpack::Approximation.generate_nodes(from: 0, to: 10, step: 0.25)
#=> [0, 0.25, ..., 10]
# Function that approximate given function by polynom with power polynom_power in approximation nodes x and returns coefficients of approximating polynom
result = Mathpack::Approximation.approximate_by_polynom(x: x, polynom_power: 5){ |x| Math.sin(x) }
#=> [0.0008009744982571882, -0.030619986086758588, 0.3805927651948083, -1.8481035413353888, 2.985465287759307, -0.3873066069630569]
# May be you want to print this polynom, let's call print_polynom function
Mathpack::Approximation.print_polynom(result)
#=> 0.0008009744982571882*x^5 - 0.030619986086758588*x^4 + 0.3805927651948083*x^3 - 1.8481035413353888*x^2 + 2.985465287759307*x - 0.3873066069630569
# 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
result = Mathpack::Approximation.approximate_by_polynom(x: [1, 2, 3], f: [1, 4, 9], polynom_power: 2) #=> [1, 0, 0]
Mathpack::Approximation.print_polynom(result) #=> x^2
returns integral value.
- from - start of integration
- to - end of integration
Let you have the following integral:
Where a can be finite or equal to , and b can be finite or equal to
. To find value of integral you should call integrate method of Integration module.
Mathpack::Integration.integrate(from: a, to: b){ |x| f(x) }
Let's demostrate some examples of Integration module practical usage:
Mathpack::Integration.integrate(from: 0, to: 3.6){ |x| Math.sin(x) / x } #=> 1.8219481156495034
Mathpack::Integration.integrate(from: 0, to: Float::INFINITY){ |x| Math.exp(-x) / (x + 1) } #=> 0.5963473623136091
Mathpack::Integration.integrate(from: -Float::INFINITY, to: Float::INFINITY){ |x| Math.exp(-x**2) * Math.cos(x) } #=> 1.3803884100161075
writes table function values to file
- filename - name of output file
- x - arguements array
- y - function values array
- labels - hash of labels names for x and y column
returns table function values hash, written to filename
If you have table function, represented by argument array and function values array, you should use print_table_function, that prints your data to filename file. If you have table function, written to filename file, you should use read_table_function, that
Mathpack::IO.print_table_function(filename: 'table.csv', x: [1, 2, 3], y: [2, 4, 6], labels: { x: 'x', y: 'f(x)'})
Mathpack::IO.read_table_function('table.csv') #=> { x: [1, 2, 3], y: [2, 4, 6] }
- Fork it ( https://github.com/[my-github-username]/mathpack/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request