Tensorex (tensorex v0.1.0) View Source

Functions to operate basic commands with tensors.

Link to this section Summary

Types

t()

Represents a tensor.

Functions

Checks if the given tensor is diagonal or not.

Returns a tensor or a number stored at the index.

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 a 2-rank tensor with all diagonal elements of 1.

Pops the tensor or the number stored at the index out of the tensor.

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/0s or Range.t/0s. See fetch/2 for concrete examples.

Link to this section Functions

Specs

diagonal?(t()) :: boolean()

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
Link to this function

fetch(tensorex, indices)

View Source

Specs

fetch(t(), [integer() | Range.t(), ...]) :: {:ok, t() | number()} | :error

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

from_list(Enum.t()) :: t()

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]}
Link to this function

get_and_update(tensor, indices, fun)

View Source

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]}}
Link to this function

kronecker_delta(dimension)

View Source

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

pop(t(), [integer() | Range.t(), ...]) :: {t() | number(), t()}

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

triangular?(t()) :: boolean()

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]}