Tensorex (tensorex v0.5.1) View Source
Functions to operate basic commands with tensors.
Link to this section Summary
Functions
Checks if the given tensor is diagonal or not.
Returns a tensor or a number stored at the index.
Returns a tensor where all of elements are the given value.
Creates a new tensor from a list (of lists (of lists of ...)).
Returns a tensor or a number stored at the index and update it at the same time.
Returns if all corresponding elements are in (relative) tolerance or not.
Returns a 2-rank tensor with all diagonal elements of 1.
Returns a tensor where each element is the result of invoking mapper
on each corresponding
element of the given tensor.
Pops the tensor or the number stored at the index out of the tensor.
Updates dimensions of each order.
Checks if the given tensor is upper triangular or not.
Returns a tensor with all of zero elements.
Link to this section Types
Specs
t() :: %Tensorex{ data: %{optional([non_neg_integer(), ...]) => number()}, shape: [pos_integer(), ...] }
Represents a tensor.
The data structure is a map with list of indices keys and numeric values. Zero values are omitted. The shape is a list of each dimension at the order.
This module implements the Access
behaviour. So that you can access elements of the tensor via
tensor[indices]
syntax, where indices
must be a list of integer/0
s or Range.t/0
s. See
fetch/2
for concrete examples.
Link to this section Functions
Specs
Checks if the given tensor is diagonal or not.
iex> Tensorex.diagonal?(Tensorex.from_list([[2, 0, 0],
...> [0, 3, 0],
...> [0, 0, -9]]))
true
iex> Tensorex.diagonal?(Tensorex.from_list([[ 2 , 0, 0],
...> [ 0 , 3, 0],
...> [-5.3, 0, -9]]))
false
Specs
Returns a tensor or a number stored at the index.
The key can be a list of indices or ranges. If integer indices are given, it returns a tensor or a numeric value specified by the index. If ranges are given, it returns a tensor consisting partial elements.
Negative indices are counted from the end.
iex> Tensorex.from_list([[[ 1 , -3.1, 2 ],
...> [ 4 , 5 , -6.1],
...> [ 0.9 , -91.2, 11 ]],
...> [[10 , -30.1, 20 ],
...> [40 , 50 , -60.1],
...> [ 0.09, -910.2, 110 ]]])[[0, 0, 0]]
1
iex> Tensorex.from_list([[[ 1 , -3.1, 2 ],
...> [ 4 , 5 , -6.1],
...> [ 0.9 , -91.2, 11 ]],
...> [[10 , -30.1, 20 ],
...> [40 , 50 , -60.1],
...> [ 0.09, -910.2, 110 ]]])[[0, 0]]
%Tensorex{data: %{[0] => 1, [1] => -3.1, [2] => 2}, shape: [3]}
iex> Tensorex.from_list([[[ 1 , -3.1, 2 ],
...> [ 4 , 5 , -6.1],
...> [ 0.9 , -91.2, 11 ]],
...> [[10 , -30.1, 20 ],
...> [40 , 50 , -60.1],
...> [ 0.09, -910.2, 110 ]]])[[0]]
%Tensorex{data: %{[0, 0] => 1 , [0, 1] => -3.1, [0, 2] => 2 ,
[1, 0] => 4 , [1, 1] => 5 , [1, 2] => -6.1,
[2, 0] => 0.9, [2, 1] => -91.2, [2, 2] => 11 }, shape: [3, 3]}
iex> Tensorex.from_list([[[ 1 , -3.1, 2 ],
...> [ 4 , 5 , -6.1],
...> [ 0.9 , -91.2, 11 ]],
...> [[10 , -30.1, 20 ],
...> [40 , 50 , -60.1],
...> [ 0.09, -910.2, 110 ]]])[[2]]
nil
iex> Tensorex.from_list([[ 1, 2, 3],
...> [ 4, 5, 6],
...> [ 7, 8, 9],
...> [10, 11, 12]])[[1..2]]
%Tensorex{data: %{[0, 0] => 4, [0, 1] => 5, [0, 2] => 6,
[1, 0] => 7, [1, 1] => 8, [1, 2] => 9}, shape: [2, 3]}
iex> Tensorex.from_list([[ 1, 2, 3],
...> [ 4, 5, 6],
...> [ 7, 8, 9],
...> [10, 11, 12]])[[-2..-1]]
%Tensorex{data: %{[0, 0] => 7, [0, 1] => 8, [0, 2] => 9,
[1, 0] => 10, [1, 1] => 11, [1, 2] => 12}, shape: [2, 3]}
iex> Tensorex.from_list([[ 1, 2, 3],
...> [ 4, 5, 6],
...> [ 7, 8, 9],
...> [10, 11, 12]])[[1..2, 1..-1]]
%Tensorex{data: %{[0, 0] => 5, [0, 1] => 6,
[1, 0] => 8, [1, 1] => 9}, shape: [2, 2]}
iex> Tensorex.from_list([[ 1, 2, 3],
...> [ 4, 0, 6],
...> [ 7, 8, 9],
...> [10, 11, 12]])[[1, 1]]
0.0
Specs
fill([pos_integer(), ...], number()) :: t()
Returns a tensor where all of elements are the given value.
iex> Tensorex.fill([3, 4, 2], 2)
%Tensorex{data: %{[0, 0, 0] => 2, [0, 0, 1] => 2,
[0, 1, 0] => 2, [0, 1, 1] => 2,
[0, 2, 0] => 2, [0, 2, 1] => 2,
[0, 3, 0] => 2, [0, 3, 1] => 2,
[1, 0, 0] => 2, [1, 0, 1] => 2,
[1, 1, 0] => 2, [1, 1, 1] => 2,
[1, 2, 0] => 2, [1, 2, 1] => 2,
[1, 3, 0] => 2, [1, 3, 1] => 2,
[2, 0, 0] => 2, [2, 0, 1] => 2,
[2, 1, 0] => 2, [2, 1, 1] => 2,
[2, 2, 0] => 2, [2, 2, 1] => 2,
[2, 3, 0] => 2, [2, 3, 1] => 2}, shape: [3, 4, 2]}
iex> Tensorex.fill([2, 2, 5], 0.0)
%Tensorex{data: %{}, shape: [2, 2, 5]}
Specs
Creates a new tensor from a list (of lists (of lists of ...)).
iex> Tensorex.from_list([1.1, 2.1, -5.3, 4])
%Tensorex{data: %{[0] => 1.1, [1] => 2.1, [2] => -5.3, [3] => 4}, shape: [4]}
iex> Tensorex.from_list([[1.1, 2.1, -5.3, 4 ],
...> [0.8, -8, 21.4, 3.3]])
%Tensorex{data: %{[0, 0] => 1.1, [0, 1] => 2.1, [0, 2] => -5.3, [0, 3] => 4 ,
[1, 0] => 0.8, [1, 1] => -8, [1, 2] => 21.4, [1, 3] => 3.3}, shape: [2, 4]}
iex> Tensorex.from_list([[[0.0, 0.0, 0.0],
...> [0.0, 0.0, 0.0]],
...> [[0.0, 0.0, 0.0],
...> [0.0, 0.0, 0.0]]])
%Tensorex{data: %{}, shape: [2, 2, 3]}
Specs
get_and_update( t(), [integer() | Range.t(), ...], (t() -> :pop | {any(), t()}) | (number() -> :pop | {any(), number()}) ) :: {any(), t()}
Returns a tensor or a number stored at the index and update it at the same time.
iex> get_and_update_in(
...> Tensorex.from_list([[[ 1 , -3.1, 2 ],
...> [ 4 , 5 , -6.1],
...> [ 0.9 , -91.2, 11 ]],
...> [[10 , -30.1, 20 ],
...> [40 , 50 , -60.1],
...> [ 0.09, -910.2, 110 ]]])[[0, 1, 0]], &{&1, &1 * 3.5})
{4, %Tensorex{data: %{[0, 0, 0] => 1 , [0, 0, 1] => -3.1, [0, 0, 2] => 2 ,
[0, 1, 0] => 14.0 , [0, 1, 1] => 5 , [0, 1, 2] => -6.1,
[0, 2, 0] => 0.9 , [0, 2, 1] => -91.2, [0, 2, 2] => 11 ,
[1, 0, 0] => 10 , [1, 0, 1] => -30.1, [1, 0, 2] => 20 ,
[1, 1, 0] => 40 , [1, 1, 1] => 50 , [1, 1, 2] => -60.1,
[1, 2, 0] => 0.09, [1, 2, 1] => -910.2, [1, 2, 2] => 110 }, shape: [2, 3, 3]}}
iex> get_and_update_in(
...> Tensorex.from_list([[ 1, 2, 3],
...> [ 4, 5, 6],
...> [ 7, 8, 9],
...> [10, 11, 12]])[[1..2, 1..2]],
...> &{&1, Tensorex.from_list([[13, 14],
...> [15, 16]])})
{%Tensorex{data: %{[0, 0] => 5, [0, 1] => 6,
[1, 0] => 8, [1, 1] => 9}, shape: [2, 2]},
%Tensorex{data: %{[0, 0] => 1, [0, 1] => 2, [0, 2] => 3,
[1, 0] => 4, [1, 1] => 13, [1, 2] => 14,
[2, 0] => 7, [2, 1] => 15, [2, 2] => 16,
[3, 0] => 10, [3, 1] => 11, [3, 2] => 12}, shape: [4, 3]}}
iex> get_and_update_in(
...> Tensorex.from_list([[ 1, 2, 3],
...> [ 4, 5, 6],
...> [ 7, 8, 9],
...> [10, 11, 12]])[[2]],
...> &{&1, Tensorex.from_list([0, 0, 16])})
{%Tensorex{data: %{[0] => 7, [1] => 8, [2] => 9}, shape: [3]},
%Tensorex{data: %{[0, 0] => 1, [0, 1] => 2, [0, 2] => 3,
[1, 0] => 4, [1, 1] => 5, [1, 2] => 6,
[2, 2] => 16,
[3, 0] => 10, [3, 1] => 11, [3, 2] => 12}, shape: [4, 3]}}
iex> get_and_update_in(
...> Tensorex.from_list([[ 1, 2],
...> [ 3, 4]])[[0..-1, 0..-1]],
...> &{&1, Tensorex.from_list([[-2, 0],
...> [ 0, -3]])})
{%Tensorex{data: %{[0, 0] => 1, [0, 1] => 2,
[1, 0] => 3, [1, 1] => 4}, shape: [2, 2]},
%Tensorex{data: %{[0, 0] => -2,
[1, 1] => -3}, shape: [2, 2]}}
iex> get_and_update_in(
...> Tensorex.zero([3, 2])[[1..-1, 1..-1]],
...> &{&1, Tensorex.from_list([[ 1],
...> [-1]])})
{%Tensorex{data: %{}, shape: [2, 1]},
%Tensorex{data: %{[1, 1] => 1,
[2, 1] => -1}, shape: [3, 2]}}
Specs
Returns if all corresponding elements are in (relative) tolerance or not.
iex> Tensorex.in_tolerance?(Tensorex.from_list([[0.0000001, 0.9999998],
...> [2.0 , -0.0000003]]),
...> Tensorex.from_list([[0 , 1 ],
...> [2 , 0 ]]), 1.0e-6)
true
iex> Tensorex.in_tolerance?(Tensorex.from_list([[0, 1],
...> [2, -1],
...> [3, 2]]),
...> Tensorex.from_list([[0, 1],
...> [2, -1]]), 1.0e-8)
false
iex> Tensorex.in_tolerance?(Tensorex.from_list([[0 , 1],
...> [2.0 , 0]]),
...> Tensorex.from_list([[0 , 1],
...> [2.000003 , 0]]), 1.0e-6)
false
iex> Tensorex.in_tolerance?(Tensorex.from_list([[1.8200340109e62, 1.0e-52 ],
...> [2.335142153e-41, 0 ]]),
...> Tensorex.from_list([[1.8200338243e62, 1.0000009e-52],
...> [2.335142296e-41, 3.242e-7 ]]), 1.0e-6)
true
iex> Tensorex.in_tolerance?(Tensorex.from_list([[1.8200440109e62, 1.0e-52 ],
...> [2.335142296e-41, 0 ]]),
...> Tensorex.from_list([[1.8200440109e62, 1.000002e-52],
...> [2.335142296e-41, 0 ]]), 1.0e-6)
false
iex> Tensorex.in_tolerance?(Tensorex.from_list([[1, 3],
...> [2, 0]]),
...> Tensorex.from_list([[1, 3],
...> [2, -5]]), 1.0e-6)
false
Specs
kronecker_delta(pos_integer()) :: t()
Returns a 2-rank tensor with all diagonal elements of 1.
iex> Tensorex.kronecker_delta(3)
%Tensorex{data: %{[0, 0] => 1,
[1, 1] => 1,
[2, 2] => 1}, shape: [3, 3]}
Specs
Returns a tensor where each element is the result of invoking mapper
on each corresponding
element of the given tensor.
iex> Tensorex.map(Tensorex.from_list([[[ 0, 1, 2], [-3, -1, 1]],
...> [[-4, -2, 0], [ 1, 0, -1]]]), &(&1 * &1))
%Tensorex{data: %{ [0, 0, 1] => 1, [0, 0, 2] => 4, [0, 1, 0] => 9, [0, 1, 1] => 1, [0, 1, 2] => 1,
[1, 0, 0] => 16, [1, 0, 1] => 4, [1, 1, 0] => 1, [1, 1, 2] => 1}, shape: [2, 2, 3]}
iex> Tensorex.map(Tensorex.from_list([[[ 0, 1, 2], [-3, -1, 1]],
...> [[-4, -2, 0], [ 1, 0, -1]]]), &(&1 + 3))
%Tensorex{data: %{[0, 0, 0] => 3.0, [0, 0, 1] => 4, [0, 0, 2] => 5 , [0, 1, 1] => 2 , [0, 1, 2] => 4,
[1, 0, 0] => -1 , [1, 0, 1] => 1, [1, 0, 2] => 3.0, [1, 1, 0] => 4, [1, 1, 1] => 3.0, [1, 1, 2] => 2}, shape: [2, 2, 3]}
iex> Tensorex.map(Tensorex.from_list([[-3, -1, 1],
...> [-4, -2, 0],
...> [ 1, 0, -1]]),
...> fn
...> value, [index, index] -> value * value
...> value, _ -> value
...> end)
%Tensorex{data: %{[0, 0] => 9, [0, 1] => -1, [0, 2] => 1,
[1, 0] => -4, [1, 1] => 4,
[2, 0] => 1, [2, 2] => 1}, shape: [3, 3]}
Specs
Pops the tensor or the number stored at the index out of the tensor.
iex> pop_in(
...> Tensorex.from_list([[[ 1 , -3.1, 2 ],
...> [ 4 , 5 , -6.1],
...> [ 0.9 , -91.2, 11 ]],
...> [[10 , -30.1, 20 ],
...> [40 , 50 , -60.1],
...> [ 0.09, -910.2, 110 ]]])[[0]])
{%Tensorex{data: %{[0, 0] => 1, [0, 1] => -3.1 , [0, 2] => 2 ,
[1, 0] => 4, [1, 1] => 5 , [1, 2] => -6.1,
[2, 0] => 0.9, [2, 1] => -91.2, [2, 2] => 11 }, shape: [3, 3]},
%Tensorex{data: %{[1, 0, 0] => 10 , [1, 0, 1] => -30.1, [1, 0, 2] => 20 ,
[1, 1, 0] => 40 , [1, 1, 1] => 50 , [1, 1, 2] => -60.1,
[1, 2, 0] => 0.09, [1, 2, 1] => -910.2, [1, 2, 2] => 110 }, shape: [2, 3, 3]}}
iex> pop_in(
...> Tensorex.from_list([[[ 1 , -3.1, 2 ],
...> [ 4 , 5 , -6.1],
...> [ 0.9 , -91.2, 11 ]],
...> [[10 , -30.1, 20 ],
...> [40 , 50 , -60.1],
...> [ 0.09, -910.2, 110 ]]])[[0, 1, 2]])
{-6.1, %Tensorex{data: %{[0, 0, 0] => 1 , [0, 0, 1] => -3.1, [0, 0, 2] => 2 ,
[0, 1, 0] => 4 , [0, 1, 1] => 5 ,
[0, 2, 0] => 0.9 , [0, 2, 1] => -91.2, [0, 2, 2] => 11 ,
[1, 0, 0] => 10 , [1, 0, 1] => -30.1, [1, 0, 2] => 20 ,
[1, 1, 0] => 40 , [1, 1, 1] => 50 , [1, 1, 2] => -60.1,
[1, 2, 0] => 0.09, [1, 2, 1] => -910.2, [1, 2, 2] => 110 }, shape: [2, 3, 3]}}
Specs
reshape(t(), [pos_integer(), ...]) :: t()
Updates dimensions of each order.
If new shape has larger dimension than previous one, values at the increased indices are considered to be zero. Otherwise if new shape has less dimension, it discards values at the removed indices.
iex> Tensorex.reshape(Tensorex.from_list([[[ 1, 2, 3],
...> [ 4, 5, 6],
...> [ 7, 8, 9]],
...> [[-1, -2, -3],
...> [-4, -5, -6],
...> [-7, -8, -9]]]), [2, 2, 3])
%Tensorex{data: %{[0, 0, 0] => 1, [0, 0, 1] => 2, [0, 0, 2] => 3,
[0, 1, 0] => 4, [0, 1, 1] => 5, [0, 1, 2] => 6,
[1, 0, 0] => -1, [1, 0, 1] => -2, [1, 0, 2] => -3,
[1, 1, 0] => -4, [1, 1, 1] => -5, [1, 1, 2] => -6}, shape: [2, 2, 3]}
iex> Tensorex.reshape(Tensorex.from_list([[[ 1, 2, 3],
...> [ 4, 5, 6],
...> [ 7, 8, 9]],
...> [[-1, -2, -3],
...> [-4, -5, -6],
...> [-7, -8, -9]]]), [3, 3, 3])
%Tensorex{data: %{[0, 0, 0] => 1, [0, 0, 1] => 2, [0, 0, 2] => 3,
[0, 1, 0] => 4, [0, 1, 1] => 5, [0, 1, 2] => 6,
[0, 2, 0] => 7, [0, 2, 1] => 8, [0, 2, 2] => 9,
[1, 0, 0] => -1, [1, 0, 1] => -2, [1, 0, 2] => -3,
[1, 1, 0] => -4, [1, 1, 1] => -5, [1, 1, 2] => -6,
[1, 2, 0] => -7, [1, 2, 1] => -8, [1, 2, 2] => -9}, shape: [3, 3, 3]}
iex> Tensorex.reshape(Tensorex.from_list([[[ 1, 2, 3],
...> [ 4, 5, 6],
...> [ 7, 8, 9]],
...> [[-1, -2, -3],
...> [-4, -5, -6],
...> [-7, -8, -9]]]), [3, 2, 2])
%Tensorex{data: %{[0, 0, 0] => 1, [0, 0, 1] => 2,
[0, 1, 0] => 4, [0, 1, 1] => 5,
[1, 0, 0] => -1, [1, 0, 1] => -2,
[1, 1, 0] => -4, [1, 1, 1] => -5}, shape: [3, 2, 2]}
Specs
Checks if the given tensor is upper triangular or not.
iex> Tensorex.triangular?(Tensorex.from_list([[2, 1, 3],
...> [0, 3, 6],
...> [0, 0, -9]]))
true
iex> Tensorex.triangular?(Tensorex.from_list([[2, 0, 0],
...> [0, 3, 0],
...> [3, 0, -9]]))
false
iex> Tensorex.triangular?(Tensorex.from_list([[[2, 5], [0, 1]],
...> [[0, 0], [0, -2]],
...> [[0, 0], [0, 0]]]))
true
iex> Tensorex.triangular?(Tensorex.from_list([[[2, 5], [0, 1]],
...> [[6, 0], [0, -2]],
...> [[0, 0], [0, 0]]]))
false
Specs
zero([pos_integer(), ...]) :: t()
Returns a tensor with all of zero elements.
iex> Tensorex.zero([4, 4, 2])
%Tensorex{data: %{}, shape: [4, 4, 2]}
iex> Tensorex.zero([-5])
** (ArgumentError) expected a list of positive integers, got: [-5]