Giter Club home page Giter Club logo

elixir-numy's Introduction

Numy

hex.pm version Build Status Workflow hex.pm

Numy is LAPACK based scientific computing library. Online API documentation is here.

Table of contents

Example

See this example in LAPACK reference documentation.

iex(1)> a = Numy.Lapack.new_tensor([3,5])
iex(2)> Numy.Tz.assign(a, [
...(2)> [1,1,1],
...(2)> [2,3,4],
...(2)> [3,5,2],
...(2)> [4,2,5],
...(2)> [5,4,3]])
:ok
iex(3)> b = Numy.Lapack.new_tensor([2,5])
iex(4)> Numy.Tz.assign(b, [
...(4)> [-10,-3],
...(4)> [12,14],
...(4)> [14,12],
...(4)> [16,16],
...(4)> [18,16]])
:ok
iex(5)> Numy.Lapack.solve_lls(a,b)
0
iex(6)> solution = Numy.Lapack.data(b,2*3)
[1.9999999999999982, 0.9999999999999983, 0.9999999999999991, 0.9999999999999997,
 1.0000000000000024, 2.0000000000000018]
iex(7)> Numy.Float.equal?(solution, [[2,1], [1,1], [1,2]])
true

Comparison

The closest to Numy project (that I am aware of) is Matrex. Matrex is using immutable binaries and NIF code is calling enif_make_binary to return a result (matrix). enif_make_binary allocates memory space for the new binary. Numy on other hand is using mutable NIF resources and can reuse already allocated memory to store the result inside the context of NIF module.

Installation

Ubuntu 18.04, sudo apt install build-essential liblapacke-dev gfortran.

The package can be installed by adding numy to your list of dependencies in mix.exs:

def deps do
  [
    {:numy, "~> 0.1.5"}
  ]
end

Mutable internal state

For performance reasons, Numy NIF objects are mutable. That is, some API functions change internal state of an object. Two sets of APIs are provided, one has functions that change object's internal state and other that does not change it. In order to maintain that immutability, original input/output object is copied and it is its copy that gets mutated.

Example of immutable addition of two vectors

iex(1)> v = Numy.Lapack.Vector.new([1,2,3])
iex(2)> Numy.Vc.add(v,v) # Vc API functions do not mutate internal state
iex(3)> Numy.Vc.data(v)
[1.0, 2.0, 3.0]

Example of two vector addition when one of the vectors changes its state

iex(1)> v = Numy.Lapack.Vector.new([1,2,3])
iex(4)> Numy.Vcm.add!(v,v) # Vcm is API that mutates internal state, functions have suffix '!'
iex(5)> Numy.Vc.data(v)
[2.0, 4.0, 6.0]

Vector operations

Vector Jupyter tutorials:

Function Vc Vcm Description
new(nelm) Create new vector of size nelm
new(list) Create new vector from Elixir list
new(v) Create new vector as copy of another vector
clone(v) x Make a clone of original vector
new(v1,v2) Create new vector as concatenation of 2 other vectors
save_to_file(v) Save vectors to a file
load_from_file(fn) Load vecotr from a file
assign_zeros(v) x Assign 0.0 to all elements
assign_ones(v) x Assign 1.0 to all elements
assign_random(v) x Assign random values to the elements
assign_all(v,val) x Assign certain values to all elements
empty?(v) x Return true if vector is empty
data(v) x Get data as a list
at(v,pos) x Get value of N-th element
set_at!(v,pos,val) x Set value of N-th element
contains?(v,val) x Check if value exists in the vector
find(v,val) x Find value in vector and return its position, -1 if can't find
equal?(v1,v2) x Compare 2 vectors
add(v1,v2) x Add 2 vectors, cᵢ ← aᵢ + bᵢ
add!(v1,v2) x aᵢ ← aᵢ + bᵢ
sub(v1,v2) x Subtract one vector from other, cᵢ ← aᵢ - bᵢ
sub!(v1,v2) x aᵢ ← aᵢ - bᵢ
mul(v1,v2) x Multiply 2 vectors, cᵢ ← aᵢ×bᵢ
mul!(v1,v2) x aᵢ ← aᵢ×bᵢ
div(v1,v2) x Divide 2 vectors, cᵢ ← aᵢ÷bᵢ
div!(v1,v2) x aᵢ ← aᵢ÷bᵢ
scale(v,factor) x Multiply each element by a constant, aᵢ ← aᵢ×scale_factor
scale!(v,factor) x aᵢ ← aᵢ×scale_factor
offset(v,off) x Add a constant to each element, aᵢ ← aᵢ + offset
offset!(c,off) x aᵢ ← aᵢ + offset
negate(v) x Change sign of each element, aᵢ ← -aᵢ
negate!(v) x aᵢ ← -aᵢ
dot(v1,v2) x Dot product of 2 vectors, ∑aᵢ×bᵢ
sum(v) x Sum of all elements, ∑aᵢ
average(v) x Average (∑aᵢ)/length
max(v) x Get max value
min(v) x Get min value
max_index(v) x Get index of max value
min_index(v) x Get index of min value
apply_heaviside(v) x Step function, aᵢ ← 0 if aᵢ < 0 else 1
apply_heaviside!(v) x
apply_sigmoid(v) x f(x) = 1/(1 + e⁻ˣ)
apply_sigmoid!(v) x
sort(v) x Sort elements of array
sort!(v) x Sort elements of array in-place
reverse(v) x Reverse order of elements
reverse!(v) x Reverse in-place
axpby(v) x cᵢ ← aᵢ×factor_a + bᵢ×factor_b
axpby!(v) x aᵢ ← aᵢ×factor_a + bᵢ×factor_b
swap_ranges(a,b,n) swap values between 2 vectors
abs(v) x
abs!(v) x
pow(v) x
pow!(v) x
pow2(v) x cᵢ ← aᵢ²
pow2!(v) x aᵢ ← aᵢ²
norm2(v) x √x₀² + x₁² + ... + xₙ²

Set operations

Numy.Lapack.Vector implements Numy.Set protocol with base Set operations: union, intersection, diff, symm_diff, jaccard_index.

Note: order of elements of input vector can change (they get sorted) when Numy.Set functions are invoked. In other words, Set functions mutate inputs.

iex(6)> a = Numy.Lapack.Vector.new(1..5)
#Vector<size=5, [1.0, 2.0, 3.0, 4.0, 5.0]>
iex(7)> b = Numy.Lapack.Vector.new(5..10)
#Vector<size=6, [5.0, 6.0, 7.0, 8.0, 9.0, 10.0]>
iex(8)> Numy.Set.union(a,b)
#Vector<size=10, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]>
iex(9)> Numy.Set.intersection(a,b)
#Vector<size=1, [5.0]>
iex(10)> Numy.Set.diff(a,b)
#Vector<size=4, [1.0, 2.0, 3.0, 4.0]>
iex(11)> Numy.Set.symm_diff(a,b)
#Vector<size=9, [1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0, 9.0, 10.0]>

Simple Linear Regression

Basic vector operation like mean, offset, pow2 and sum allow to implement simple Linear Regression in Elixir. Module Numy.Fit.SimpleLinear is Elixir code that finds the line that fits input data by calculating variance and covariance.

iex(34)> x = Numy.Lapack.Vector.new(0..9)
#Vector<size=10, [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]>
iex(35)> y = Vc.scale(x,2) |> Vcm.offset!(-3.0) # make slope=2 and intercept=-3
#Vector<size=10, [-3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0]>
iex(36)> err = Numy.Lapack.Vector.new(10) |> Vc.assign_random |> Vcm.offset!(-0.5) |> Vcm.scale!(0.1)
iex(37)> Vcm.add!(y,err) # add errors to the ideal line
iex(38)> line = Numy.Fit.SimpleLinear.fit(x,y)
{-2.9939933270609496, 1.9966330251198818} # got intercept=-3 and slope=2 as expected

See tutorial.

elixir-numy's People

Contributors

curoles avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.