Module grid: create and transform multidimensional grids

Package teneva, module grid: functions to operate with grids.

This module contains a set of functions for creating and transforming multidimensional grids for discretization on uniform and Chebyshev grids.




teneva.grid.grid_flat(n)[source]

Compute the multi-indices for the full multidimensional grid.

Parameters:

n (int, float, list, np.ndarray) – number of grid points for each dimension (list or np.ndarray of length d, where d is a number of dimensions). It may be also a number, then the 1D grid will be returned.

Returns:

multi-indices for the full (flatten) grid (it is 2D array of the shape [d, n^d]).

Return type:

np.ndarray

Examples:

n = [2, 3, 4]           # This is the 3D grid 2 x 3 x 4
I = teneva.grid_flat(n) # This is the full list of indices (flatten grid)

print(I)

# >>> ----------------------------------------
# >>> Output:

# [[0 0 0]
#  [1 0 0]
#  [0 1 0]
#  [1 1 0]
#  [0 2 0]
#  [1 2 0]
#  [0 0 1]
#  [1 0 1]
#  [0 1 1]
#  [1 1 1]
#  [0 2 1]
#  [1 2 1]
#  [0 0 2]
#  [1 0 2]
#  [0 1 2]
#  [1 1 2]
#  [0 2 2]
#  [1 2 2]
#  [0 0 3]
#  [1 0 3]
#  [0 1 3]
#  [1 1 3]
#  [0 2 3]
#  [1 2 3]]
#


teneva.grid.grid_prep_opt(opt, d=None, kind=<class 'float'>, reps=None)[source]

Helper function that prepare grid parameter.

Parameters:
  • opt (int, float, list, np.ndarray) – grid parameter for each dimension.

  • d (int) – the dimension of the grid. If should be set if opt is scalar.

  • kind (class 'int', class 'float') – data type for option (int or float).

  • reps (int) – optional number of repetitions for option.

Returns:

prepared option. It is 1D np.ndarray of length d if reps is None, or np.ndarray of the shape [reps, d] (values repeated along the 1th axis) otherwise.

Return type:

np.ndarray

Examples:

teneva.grid_prep_opt(-5., d=3)

# >>> ----------------------------------------
# >>> Output:

# array([-5., -5., -5.])
#
teneva.grid_prep_opt([-5., +4])

# >>> ----------------------------------------
# >>> Output:

# array([-5.,  4.])
#
teneva.grid_prep_opt([5., +4.21], kind=int)

# >>> ----------------------------------------
# >>> Output:

# array([5, 4])
#
teneva.grid_prep_opt([-5., +4], reps=3)

# >>> ----------------------------------------
# >>> Output:

# array([[-5.,  4.],
#        [-5.,  4.],
#        [-5.,  4.]])
#


teneva.grid.grid_prep_opts(a=None, b=None, n=None, d=None, reps=None)[source]

Helper function that prepare grid parameters a, b, n.

Parameters:
  • a (float, list, np.ndarray) – grid lower bounds for each dimension (list or np.ndarray of length d or float).

  • b (float, list, np.ndarray) – grid upper bounds for each dimension (list or np.ndarray of length d or float).

  • n (int, float, list, np.ndarray) – grid size for each dimension (list or np.ndarray of length d or int/float).

  • d (int) – the dimension of the grid. If all a, b, n are numbers, then it should be set, otherwise it is optional (d will be recoverd fromv the given a / b / n).

  • reps (int) – optional number of repetitions for a, b, n.

Returns:

grid lower bounds a, grid upper bounds b and grid size n for each dimension. All opts will be 1D arrays of length d if reps is None, or np.ndarray of the shape [reps, d] (values repeated along the 1th axis) otherwise.

Return type:

(np.ndarray, np.ndarray, np.ndarray)

Note

In case of a mismatch in the size of the arrays a / b / n or the impossibility of restoring the dimension d, the function will generate the error (ValueError).

Examples:

d = 3           # Dimension of the tensor/grid
a = -5.         # Lower bounds for grid
b = +5.         # Upper bounds for grid
n = 7           # Shape of the tensor/grid

teneva.grid_prep_opts(a, b, n, d)

# >>> ----------------------------------------
# >>> Output:

# (array([-5., -5., -5.]), array([5., 5., 5.]), array([7, 7, 7]))
#
d = None        # Dimension of the tensor/grid
a = -5.         # Lower bounds for grid
b = +5.         # Upper bounds for grid
n = [7, 4, 7]   # Shape of the tensor/grid

teneva.grid_prep_opts(a, b, n, d)

# >>> ----------------------------------------
# >>> Output:

# (array([-5., -5., -5.]), array([5., 5., 5.]), array([7, 4, 7]))
#
d = None        # Dimension of the tensor/grid
a = [-5., -4.]  # Lower bounds for grid
b = +5.         # Upper bounds for grid
n = 6           # Shape of the tensor/grid

teneva.grid_prep_opts(a, b, n, d)

# >>> ----------------------------------------
# >>> Output:

# (array([-5., -4.]), array([5., 5.]), array([6, 6]))
#
a = [-5., -4.]  # Lower bounds for grid
b = [+5., +4.]  # Upper bounds for grid
n = [100, 200]  # Shape of the tensor/grid

teneva.grid_prep_opts(a, b, n)

# >>> ----------------------------------------
# >>> Output:

# (array([-5., -4.]), array([5., 4.]), array([100, 200]))
#
a = [-5., -4., +3.]  # Lower bounds for grid
b = [+5., +4., +3.]  # Upper bounds for grid
n = [100, 200, 300]  # Shape of the tensor/grid

teneva.grid_prep_opts(a, b, n, reps=2)

# >>> ----------------------------------------
# >>> Output:

# (array([[-5., -4.,  3.],
#         [-5., -4.,  3.]]),
#  array([[5., 4., 3.],
#         [5., 4., 3.]]),
#  array([[100, 200, 300],
#         [100, 200, 300]]))
#


teneva.grid.ind_qtt_to_tt(I_qtt, q)[source]

Transform tensor multi-indices from QTT (long) to base TT (short) format.

Parameters:
  • I_qtt (list, np.ndarray) – QTT multi-indices for the tensor in the form of array of the shape [samples, d*q], where samples is the number of samples, d is the dimension of the TT-tensor and q is a quantization value. For the case of only one sample, it may be 1D array or list of the length d*q.

  • q (int) – quantization value (TT-tensor mode size will be n=2^q).

Returns:

TT multi-indices, which relates to the given QTT multi-indices in the form of array of the shape [samples, d]. If input I_qtt is 1D list or np.ndarray (the case of only one sample), then function will also return 1D np.ndarray of the length d.

Return type:

np.ndarray

Examples:

d = 4             # Dimension of the TT-tensor
q = 4             # Quantization value
                  # (note that TT mode size will be n=2^q)
i_qtt = [         # Multi-index in the QTT-format
    1, 0, 0, 0,   # -> 1 in TT
    0, 1, 0, 0,   # -> 2 in TT
    0, 0, 0, 1,   # -> 8 in TT
    1, 1, 1, 1]   # -> 2^q-1 in TT

i = teneva.ind_qtt_to_tt(i_qtt, q)

print(i)          # Multi-index in the TT-format

# >>> ----------------------------------------
# >>> Output:

# [ 1  2  8 15]
#

We can also calculate several multi-indices at once:

d = 3
q = 3

I_qtt = [         # Multi-indices in the QTT-format
    [1, 0, 0, 0, 1, 0, 0, 0, 1],
    [1, 1, 0, 0, 1, 1, 1, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1],
]

I = teneva.ind_qtt_to_tt(I_qtt, q)

print(I)          # Multi-indices in the TT-format

# >>> ----------------------------------------
# >>> Output:

# [[1 2 4]
#  [3 6 5]
#  [7 7 7]]
#


teneva.grid.ind_to_poi(I, a, b, n, kind='uni')[source]

Transform multi-indices (samples) into points of the spatial grid.

Parameters:
  • I (list, np.ndarray) – multi-indices for the tensor in the form of array of the shape [samples, d], where samples is the number of samples and d is the dimension of the tensor. For the case of only one sample, it may be 1D array or list of length d.

  • a (float, list, np.ndarray) – grid lower bounds for each dimension (list or np.ndarray of length d). It may be also float, then the lower bounds for each dimension will be the same.

  • b (float, list, np.ndarray) – grid upper bounds for each dimension (list or np.ndarray of length d). It may be also float, then the upper bounds for each dimension will be the same.

  • n (int, float, list, np.ndarray) – tensor size for each dimension (list or np.ndarray of length d). It may be also int/float, then the size for each dimension will be the same.

  • kind (str) – the grid type, it may be “uni” (uniform grid) and “cheb” (Chebyshev grid). In case of the uniform grid, index 0 relates to the spatial point a and index n-1 relates to the spatial point b. In case of the Chebyshev grid, index 0 relates to the spatial point b and index n-1 relates to the spatial point a.

Returns:

points of the grid in the form of array of the shape [samples, d]. If input I is 1D list or np.ndarray (the case of only one sample), then function will also return 1D np.ndarray of length d.

Return type:

np.ndarray

Note

This function may be used for function approximation by low rank tensor methods (requested tensor indices should be transformed into spatial grid points and then used as an argument for the target function).

Examples:

d = 3           # Dimension of the tensor/grid
a = [-5.] * d   # Lower bounds for grid
b = [+5.] * d   # Upper bounds for grid
n = [7] * d     # Shape of the tensor/grid
# Random multi-indices (samples x dimension):
I = np.vstack([np.random.choice(k, 50) for k in n]).T

print(I.shape)
print(I[0, :]) # The 1th sample

# >>> ----------------------------------------
# >>> Output:

# (50, 3)
# [6 4 5]
#
X = teneva.ind_to_poi(I, a, b, n)

print(X.shape)
print(X[0, :]) # The 1th point

# >>> ----------------------------------------
# >>> Output:

# (50, 3)
# [5.         1.66666667 3.33333333]
#

Grid bounds and tensor shape may be also numbers:

X = teneva.ind_to_poi(I, -5, 5, 7)

print(X.shape)
print(X[0, :]) # The 1th point

# >>> ----------------------------------------
# >>> Output:

# (50, 3)
# [5.         1.66666667 3.33333333]
#

We may also compute only one point while function call:

X = teneva.ind_to_poi(I[0, :], -5, 5, 7)

print(X)

# >>> ----------------------------------------
# >>> Output:

# [5.         1.66666667 3.33333333]
#

By default the uniform (kind=”uni”) grid is used. We may also use the Chebyshev grid:

X = teneva.ind_to_poi(I, a, b, n, 'cheb')

print(X.shape)
print(X[0, :]) # The 1th point

# >>> ----------------------------------------
# >>> Output:

# (50, 3)
# [-5.         -2.5        -4.33012702]
#


teneva.grid.ind_tt_to_qtt(I, n)[source]

Transform tensor multi-indices from base TT (short) to QTT (long) format.

Parameters:
  • I (list, np.ndarray) – TT multi-indices for the tensor in the form of array of the shape [samples, d], where samples is the number of samples and d is the dimension of the TT-tensor. For the case of only one sample, it may be 1D array or list of the length d.

  • n (int) – TT-tensor mode size. It should be like n=2^q, where q is a quantization value.

Returns:

QTT multi-indices, which relates to the given TT multi-indices in the form of array of the shape [samples, d*q]. If input I is 1D list or np.ndarray (the case of only one sample), then function will also return 1D np.ndarray of the length d*q.

Return type:

np.ndarray

Examples:

d = 4             # Dimension of the TT-tensor
n = 8             # Mode size of the TT-tensor
i = [ 1, 3, 5, 7] # Multi-index in the TT-format

i_qtt = teneva.ind_tt_to_qtt(i, n)

print(i_qtt)      # Multi-index in the QTT-format

# >>> ----------------------------------------
# >>> Output:

# [1 0 0 1 1 0 1 0 1 1 1 1]
#

We can also calculate several multi-indices at once:

d = 4
n = 8

I = [             # Multi-indices in the TT-format
    [1, 0, 0, 0],
    [1, 1, 0, 0],
    [1, 1, 1, 1],
    [2, 3, 4, 5],
    [7, 7, 7, 7],
]

I_qtt = teneva.ind_tt_to_qtt(I, n)

print(I_qtt)      # Multi-indices in the QTT-format

# >>> ----------------------------------------
# >>> Output:

# [[1 0 0 0 0 0 0 0 0 0 0 0]
#  [1 0 0 1 0 0 0 0 0 0 0 0]
#  [1 0 0 1 0 0 1 0 0 1 0 0]
#  [0 1 0 1 1 0 0 0 1 1 0 1]
#  [1 1 1 1 1 1 1 1 1 1 1 1]]
#


teneva.grid.poi_scale(X, a, b, kind='uni')[source]

Scale points from [a, b] into unit interval.

Parameters:
  • X (list, np.ndarray) – points of the spatial grid in the form of array of the shape [samples, d], where samples is the number of samples and d is the dimension of the tensor. For the case of only one sample, it may be 1D array or list of length d.

  • a (float, list, np.ndarray) – grid lower bounds for each dimension (list or np.ndarray of length d). It may be also float, then the lower bounds for each dimension will be the same.

  • b (float, list, np.ndarray) – grid upper bounds for each dimension (list or np.ndarray of length d). It may be also float, then the upper bounds for each dimension will be the same.

  • kind (str) – the grid type, it may be “uni” (uniform grid) and “cheb” (Chebyshev grid). It may be also a list of new scalar limits [a_new, b_new]; in this case the linear scaling to these limits will be performed.

Returns:

scaled points of the spatial grid. It has the same shape as input array X. The interval will be [0, 1] in case of the uniform grid, and [-1, 1] in the case of the Chebyshev grid.

Return type:

np.ndarray

Examples:

d = 3                 # Dimension of the tensor/grid
a = [-5., -3., -1.]   # Lower bounds for grid
b = [+5., +3., +1.]   # Upper bounds for grid

X = np.array([       # We prepare 4 spatial points:
    [-5., -3., -1.], # Point near the lower bound
    [ 0.,  0.,  0.], # Zero point
    [-1., +2.,  0.], # Random point
    [+5., +3., +1.], # Point near the upper bound
])
Xsc = teneva.poi_scale(X, a, b)

print(Xsc)

# >>> ----------------------------------------
# >>> Output:

# [[0.         0.         0.        ]
#  [0.5        0.5        0.5       ]
#  [0.4        0.83333333 0.5       ]
#  [1.         1.         1.        ]]
#

We can also consider the Chebyshev grid:

Xsc = teneva.poi_scale(X, a, b, 'cheb')

print(Xsc)

# >>> ----------------------------------------
# >>> Output:

# [[-1.         -1.         -1.        ]
#  [ 0.          0.          0.        ]
#  [-0.2         0.66666667  0.        ]
#  [ 1.          1.          1.        ]]
#

For a uniform grid, scaling from an interval of [0, 1] will be the identical operation:

teneva.poi_scale(([
    [0., 0.5, 0.7, 1.0],
    [-2., 0.2, 0.4, 2.0],
]), 0., 1.)

# >>> ----------------------------------------
# >>> Output:

# array([[0. , 0.5, 0.7, 1. ],
#        [0. , 0.2, 0.4, 1. ]])
#

For a Chebyshev grid, scaling from an interval of [-1, 1] will be the identical operation:

teneva.poi_scale(([
    [-1., -0.2, 0., 0.7, 1.0],
    [-1., -0.4, 0., 0.4, 1.0],
]), -1., 1., 'cheb')

# >>> ----------------------------------------
# >>> Output:

# array([[-1. , -0.2,  0. ,  0.7,  1. ],
#        [-1. , -0.4,  0. ,  0.4,  1. ]])
#


teneva.grid.poi_to_ind(X, a, b, n, kind='uni')[source]

Transform points of the spatial grid (samples) into multi-indices.

Parameters:
  • X (list, np.ndarray) – points of the spatial grid in the form of array of the shape [samples, d], where samples is the number of samples and d is the dimension of the tensor. For the case of only one sample, it may be 1D array or list of length d.

  • a (float, list, np.ndarray) – grid lower bounds for each dimension (list or np.ndarray of length d). It may be also float, then the lower bounds for each dimension will be the same.

  • b (float, list, np.ndarray) – grid upper bounds for each dimension (list or np.ndarray of length d). It may be also float, then the upper bounds for each dimension will be the same.

  • n (int, float, list, np.ndarray) – tensor size for each dimension (list or np.ndarray of length d). It may be also int/float, then the size for each dimension will be the same.

  • kind (str) – the grid type, it may be “uni” (uniform grid) and “cheb” (Chebyshev grid). In case of the uniform grid, index 0 relates to the spatial point a and index n-1 relates to the spatial point b. In case of the Chebyshev grid, index 0 relates to the spatial point b and index n-1 relates to the spatial point a.

Returns:

multi-indices for the tensor in the form of array of the shape [samples, d]. If input X is 1D list or np.ndarray (the case of only one sample), then function will also return 1D np.ndarray of the length d.

Return type:

np.ndarray

Note

Points that are outside the domain (a and b) will be transformed to the nearest grid indices (i.e., 0 or n-1).

Examples:

d = 3                 # Dimension of the tensor/grid
a = [-5., -3., -1.]   # Lower bounds for grid
b = [+5., +3., +1.]   # Upper bounds for grid
n = [9, 8, 7]         # Shape of the tensor/grid

X = np.array([       # We prepare 4 spatial points:
    [-5., -3., -1.], # Point near the lower bound
    [ 0.,  0.,  0.], # Zero point
    [-1., +2.,  0.], # Random point
    [+5., +3., +1.], # Point near the upper bound
])

We can build multi-indices for the uniform grid:

I = teneva.poi_to_ind(X, a, b, n)

print(I)

# >>> ----------------------------------------
# >>> Output:

# [[0 0 0]
#  [4 4 3]
#  [3 6 3]
#  [8 7 6]]
#

We can also build multi-indices for the Chebyshev grid:

I = teneva.poi_to_ind(X, a, b, n, 'cheb')

print(I)

# >>> ----------------------------------------
# >>> Output:

# [[8 7 6]
#  [4 4 3]
#  [5 2 3]
#  [0 0 0]]
#

Grid bounds and tensor shape may be also numbers:

I = teneva.poi_to_ind(X, -1., +1., 10, 'cheb')

print(I)

# >>> ----------------------------------------
# >>> Output:

# [[9 9 9]
#  [4 4 4]
#  [9 0 4]
#  [0 0 0]]
#

We may also compute only one point while function call:

x = [-5., -3., -1.]
I = teneva.poi_to_ind(x, -1., +1., 10, 'cheb')

print(I)

# >>> ----------------------------------------
# >>> Output:

# [9 9 9]
#

We can apply “ind_to_poi” function to the generated multi-indices and check the result:

d = 3                 # Dimension of the tensor/grid
a = [-5., -3., -1.]   # Lower bounds for grid
b = [+5., +3., +1.]   # Upper bounds for grid
n = [7, 5, 3]         # Shape of the tensor/grid

X = np.array([
    [-5., -3., -1.],  # Point near the lower bound
    [ 0.,  0.,  0.],  # Zero point
    [+5., +3., +1.],  # Point near the upper bound
])
I = teneva.poi_to_ind(X, a, b, n)
Z = teneva.ind_to_poi(I, a, b, n)

print(X) # Used spacial points
print(Z) # Generated spacial points
print(I) # Multi-indices

# >>> ----------------------------------------
# >>> Output:

# [[-5. -3. -1.]
#  [ 0.  0.  0.]
#  [ 5.  3.  1.]]
# [[-5. -3. -1.]
#  [ 0.  0.  0.]
#  [ 5.  3.  1.]]
# [[0 0 0]
#  [3 2 1]
#  [6 4 2]]
#
I = teneva.poi_to_ind(X, a, b, n, 'cheb')
Z = teneva.ind_to_poi(I, a, b, n, 'cheb')

print(X) # Used spacial points
print(Z) # Generated spacial points
print(I) # Multi-indices

# >>> ----------------------------------------
# >>> Output:

# [[-5. -3. -1.]
#  [ 0.  0.  0.]
#  [ 5.  3.  1.]]
# [[-5.0000000e+00 -3.0000000e+00 -1.0000000e+00]
#  [ 3.0616170e-16  1.8369702e-16  6.1232340e-17]
#  [ 5.0000000e+00  3.0000000e+00  1.0000000e+00]]
# [[6 4 2]
#  [3 2 1]
#  [0 0 0]]
#