Source code for teneva.tensors

"""Package teneva, module tensors: various useful TT-tensors.

This module contains the collection of functions for explicit construction of
various useful TT-tensors (random tensor, delta function, polynomial
function and others).

"""
import numpy as np
import teneva


[docs]def const(n, v=1., I_zero=None, i_non_zero=None): """Build a TT-tensor with all values equal to the given number. Note that constructed TT-tensor will have all TT-ranks equal to 1. Args: n (list, np.ndarray): shape of the tensor. It should be a list or a np.ndarray of the length d, where d is a number of dimensions. v (float): all elements of the tensor will be equal to this value. I_zero (list, np.ndarray): optional list of lists or a np.ndarray of the shape samples x d, which relates to multi-indices, where tensor should be zero (but this ensures that the value at index i_non_zero, if provided, is not affected). i_non_zero (list, np.ndarray): optional multi-index in the form of a list or a np.ndarray of the shape d, which is not affected by zero multi-indices (I_zero). Returns: list: TT-tensor. """ d = len(n) s = abs(v) / v if abs(v) > 1.E-16 else v v = abs(v)**(1./d) if abs(v) > 1.E-16 else 1. Y = [np.ones([1, k, 1]) * v for k in n] Y[-1] *= s if I_zero is not None: k = 0 for i_zero in I_zero: skiped = 0 while True: if i_non_zero is None or i_zero[k] != i_non_zero[k]: Y[k][0, i_zero[k], 0] = 0. k += 1 break else: k += 1 skiped += 1 if skiped > d: raise ValueError('Can not set zero items') if k >= d: k = 0 if k >= d: k = 0 return Y
[docs]def delta(n, i, v=1.): """Build a TT-tensor that is zero everywhere except for a given multi-index. Args: n (list, np.ndarray): shape of the tensor. It should be a list or a np.ndarray of the length d, where d is a number of dimensions. i (list, np.ndarray): the multi-index for nonzero element. It should be a list or a np.ndarray of the length d. v (float): the value of the tensor at the multi-index i. Returns: list: TT-tensor. """ d = len(n) s = abs(v) / v if abs(v) > 1.E-16 else v v = abs(v)**(1./d) if abs(v) > 1.E-16 else 1. Y = [np.zeros([1, k, 1]) for k in n] for k in range(d): Y[k][0, i[k], 0] = v Y[-1] *= s return Y
[docs]def poly(n, shift=0., power=2, scale=1.): """Build a TT-tensor that is a polynomial like scale * (index+shift)^power. Args: n (list, np.ndarray): shape of the tensor. It should be a list or a np.ndarray of the length d, where d is a number of dimensions. shift (float, list, np.ndarray): the shift value. It should be a list or a np.ndarray of the length d. It may be also float value. power (int): the power of the polynomial. scale (float): the scale for the polynomial. Returns: list: TT-tensor. """ d = len(n) Y = [] shift = teneva.grid_prep_opt(shift, d) def _get(m, j): return (m + shift[j])**power for j, k in enumerate(n): if j == 0: G = np.zeros((1, k, 2)) for m in range(k): G[0, m, :] = np.array([1., _get(m, j)]) if j > 0 and j < d-1: G = np.zeros((2, k, 2)) for m in range(k): G[:, m, :] = np.array([ [1., _get(m, j)], [0., 1.]]) if j == d - 1: G = np.zeros((2, k, 1)) for m in range(k): G[:, m, 0] = np.array([_get(m, j) * scale, scale]) Y.append(G) return Y
[docs]def rand(n, r, a=-1., b=1., seed=None): """Construct a random TT-tensor from the uniform distribution. Args: n (list, np.ndarray): shape of the tensor. It should be a list or a np.ndarray of the length d, where d is a number of dimensions. r (int, list, np.ndarray): TT-ranks of the tensor. It should be a list or a np.ndarray of the length d+1 with outer elements (first and last) equals to 1. If all inner TT-ranks are equal, it may be the number, which relates to the inner TT-rank. a (float): minimum value for random items of the TT-cores. b (float): maximum value for random items of the TT-cores. seed (int): random seed. It should be an integer number or a numpy Generator class instance. Returns: list: TT-tensor. """ rand = teneva._rand(seed) def f(size): return rand.uniform(a, b, size=size) return rand_custom(n, r, f)
[docs]def rand_custom(n, r, f=np.random.randn): """Construct a random TT-tensor from provided distribution f. Args: n (list, np.ndarray): shape of the tensor. It should be a list or a np.ndarray of the length d, where d is a number of dimensions. r (int, list, np.ndarray): TT-ranks of the tensor. It should be a list or a np.ndarray of the length d+1 with outer elements (first and last) equals to 1. If all inner TT-ranks are equal, it may be the number, which relates to the inner TT-rank. f (function): sampling function. You can use any function that returns a set of random values given the required number of samples. Returns: list: TT-tensor. """ n = np.asanyarray(n, dtype=int) d = n.size if isinstance(r, (int, float)): r = [1] + [int(r)] * (d - 1) + [1] r = np.asanyarray(r, dtype=int) ps = np.cumsum(np.concatenate(([1], n * r[0:d] * r[1:d+1]))) ps = ps.astype(int) cores = np.asanyarray(f(ps[d] - 1), dtype=float) Y = [] for i in range(d): G = cores[ps[i]-1:ps[i+1]-1] Y.append(G.reshape((r[i], n[i], r[i+1]), order='F')) return Y
[docs]def rand_norm(n, r, m=0., s=1., seed=None): """Construct a random TT-tensor from the normal distribution. Args: n (list, np.ndarray): shape of the tensor. It should be a list or a np.ndarray of the length d, where d is a number of dimensions. r (int, list, np.ndarray): TT-ranks of the tensor. It should be a list or a np.ndarray of the length d+1 with outer elements (first and last) equals to 1. If all inner TT-ranks are equal, it may be the number, which relates to the inner TT-rank. m (float): mean ("centre") of the distribution. s (float): standard deviation of the distribution (>0). seed (int): random seed. It should be an integer number or a numpy Generator class instance. Returns: list: TT-tensor. """ rand = teneva._rand(seed) def f(size): return rand.normal(m, s, size=size) return rand_custom(n, r, f)
[docs]def rand_stab(n, r, noise=1.E-15, seed=None): """Construct a random TT-tensor which is stable for large dimensions. Args: n (list, np.ndarray): shape of the tensor. It should be a list or a np.ndarray of the length d, where d is a number of dimensions. r (int, list, np.ndarray): TT-ranks of the tensor. It should be a list or a np.ndarray of the length d+1 with outer elements (first and last) equals to 1. If all inner TT-ranks are equal, it may be the number, which relates to the inner TT-rank. noise (float): small noise for diagonal and off-diagonal elements. seed (int): random seed. It should be an integer number or a numpy Generator class instance. Returns: list: TT-tensor. """ n = np.asanyarray(n, dtype=int) d = n.size if isinstance(r, (int, float)): r = [1] + [int(r)] * (d - 1) + [1] r = np.asanyarray(r, dtype=int) rand = teneva._rand(seed) Y = [] for k in range(d): G = rand.normal(0., noise, size=(r[k], n[k], r[k+1])) for p in range(n[k]): G[:, p, :] += np.eye(r[k], r[k+1]) Y.append(G) return Y