Module act_two: operations with a pair of TT-tensors

Package teneva, module act_two: operations with a pair of TT-tensors.

This module contains the basic operations with a pair of TT-tensors “(Y1, Y2)”, including “add”, “mul”, “sub”, etc.




teneva.act_two.accuracy(Y1, Y2)[source]

Compute || Y1 - Y2 || / || Y2 || for tensors in the TT-format.

Parameters:
  • Y1 (list) – TT-tensor.

  • Y2 (list) – TT-tensor.

Returns:

the relative difference between two tensors.

Return type:

float

Note

Also, for convenience, tensors in numpy format can be passed, in this case the norm will be calculated using the function “linalg.norm”.

Examples:

Y1 = teneva.rand([5]*10, 2)   # 10-dim random TT-tensor with TT-rank 2
Z1 = teneva.mul(1.E-4, Y1)    # The TT-tensor Y1 + eps * Y1 (eps = 1.E-4)

Y2 = teneva.add(Y1, Z1)

eps = teneva.accuracy(Y1, Y2) # The relative difference ("accuracy")

print(f'Accuracy     : {eps:-8.2e}')

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

# Accuracy     : 1.00e-04
#

Note that this function works correctly even for very large dimension values due to the use of balancing in the scalar product:

for d in [10, 50, 100, 250, 1000, 10000]:
    Y1 = teneva.rand([10]*d, r=2)
    Y2 = teneva.add(Y1, Y1)

    eps = teneva.accuracy(Y1, Y2)

    print(f'd = {d:-5d} | eps = {eps:-8.1e} | expected value 0.5')

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

# d =    10 | eps =  5.0e-01 | expected value 0.5
# d =    50 | eps =  5.0e-01 | expected value 0.5
# d =   100 | eps =  5.0e-01 | expected value 0.5
# d =   250 | eps =  5.0e-01 | expected value 0.5
# d =  1000 | eps =  5.0e-01 | expected value 0.5
# d = 10000 | eps =  5.0e-01 | expected value 0.5
#


teneva.act_two.add(Y1, Y2)[source]

Compute Y1 + Y2 in the TT-format.

Parameters:
  • Y1 (int, float, list) – TT-tensor (or it may be int/float).

  • Y2 (int, float, list) – TT-tensor (or it may be int/float).

Returns:

TT-tensor, which represents the element wise sum of Y1 and Y2. If both Y1 and Y2 are numbers, then result will be int/float number.

Return type:

list

Examples:

Y1 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2
Y2 = teneva.rand([5]*10, 3) # 10-dim random TT-tensor with TT-rank 3

Y = teneva.add(Y1, Y2)      # Compute the sum of Y1 and Y2

# Print the resulting TT-tensor (note that it has TT-rank 2 + 3 = 5):
teneva.show(Y)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    5.0 :   \5/ \5/ \5/ \5/ \5/ \5/ \5/ \5/ \5/
#
Y1_full = teneva.full(Y1) # Compute tensors in the full format
Y2_full = teneva.full(Y2) # to check the result
Y_full = teneva.full(Y)

Z_full = Y1_full + Y2_full

# Compute error for TT-tensor vs full tensor:
e = np.linalg.norm(Y_full - Z_full)
e /= np.linalg.norm(Z_full)
print(f'Error     : {e:-8.2e}')

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

# Error     : 8.70e-17
#

This function also supports float argument:

Y1 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2
Y2 = 42.                    # Just a number

Y = teneva.add(Y1, Y2)      # Compute the sum of Y1 and Y2

# Print the resulting TT-tensor (note that it has TT-rank 2 + 1 = 3):
teneva.show(Y)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    3.0 :   \3/ \3/ \3/ \3/ \3/ \3/ \3/ \3/ \3/
#
Y1 = 42.                    # Just a number
Y2 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2

Y = teneva.add(Y1, Y2)      # Compute the sum of Y1 and Y2

# Print the resulting TT-tensor (note that it has TT-rank 2 + 1 = 3):
teneva.show(Y)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    3.0 :   \3/ \3/ \3/ \3/ \3/ \3/ \3/ \3/ \3/
#
Y1_full = 42.             # Compute tensors in the full format
Y2_full = teneva.full(Y2) # to check the result
Y_full = teneva.full(Y)

Z_full = Y1_full + Y2_full

# Compute error for TT-tensor vs full tensor:
e = np.linalg.norm(Y_full - Z_full)
e /= np.linalg.norm(Z_full)
print(f'Error     : {e:-8.2e}')

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

# Error     : 5.14e-16
#

If both arguments are numbers, then function returns the sum of numbers:

Y1 = 40.               # Just a number
Y2 = 2                 # Just a number
Y = teneva.add(Y1, Y2) # Compute the sum of Y1 and Y2
print(Y)               # The result is a number

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

# 42.0
#


teneva.act_two.mul(Y1, Y2)[source]

Compute element wise product Y1 * Y2 in the TT-format.

Parameters:
  • Y1 (int, float, list) – TT-tensor (or it may be int/float).

  • Y2 (int, float, list) – TT-tensor (or it may be int/float).

Returns:

TT-tensor, which represents the element wise product of Y1 and Y2. If both Y1 and Y2 are numbers, then result will be float number.

Return type:

list

Examples:

Y1 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2
Y2 = teneva.rand([5]*10, 3) # 10-dim random TT-tensor with TT-rank 3
Y = teneva.mul(Y1, Y2) # Compute the product of Y1 and Y2
teneva.show(Y)         # Print the resulting TT-tensor (note that it has TT-rank 2 x 3 = 6)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    6.0 :   \6/ \6/ \6/ \6/ \6/ \6/ \6/ \6/ \6/
#
Y1_full = teneva.full(Y1) # Compute tensors in the full format
Y2_full = teneva.full(Y2) # to check the result
Y_full = teneva.full(Y)

Z_full = Y1_full * Y2_full

# Compute error for TT-tensor vs full tensor:
e = np.linalg.norm(Y_full - Z_full)
e /= np.linalg.norm(Z_full)
print(f'Error     : {e:-8.2e}')

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

# Error     : 4.00e-16
#

This function also supports float argument:

Y1 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2
Y2 = 42.                    # Just a number

Y = teneva.mul(Y1, Y2) # Compute the product of Y1 and Y2

# Print the resulting TT-tensor (note that it has TT-rank 2 x 1 = 2):
teneva.show(Y)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    2.0 :   \2/ \2/ \2/ \2/ \2/ \2/ \2/ \2/ \2/
#
Y1 = 42.                    # Just a number
Y2 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2

Y = teneva.mul(Y1, Y2) # Compute the product of Y1 and Y2

# Print the resulting TT-tensor (note that it has TT-rank 2 x 1 = 2):
teneva.show(Y)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    2.0 :   \2/ \2/ \2/ \2/ \2/ \2/ \2/ \2/ \2/
#
Y1 = 21.               # Just a number
Y2 = 2                 # Just a number

Y = teneva.mul(Y1, Y2) # Compute the product of Y1 and Y2
print(Y)               # The result is a number

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

# 42.0
#


teneva.act_two.mul_scalar(Y1, Y2, use_stab=False)[source]

Compute scalar product for Y1 and Y2 in the TT-format.

Parameters:
  • Y1 (list) – TT-tensor.

  • Y2 (list) – TT-tensor.

  • use_stab (bool) – if flag is set, then function will also return the second argument p, which is the factor of 2-power.

Returns:

the scalar product.

Return type:

float

Examples:

Y1 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2
Y2 = teneva.rand([5]*10, 3) # 10-dim random TT-tensor with TT-rank 3

v = teneva.mul_scalar(Y1, Y2) # Compute the product of Y1 and Y2

print(v)                      # Print the resulting value

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

# -3.460467948446013
#
Y1_full = teneva.full(Y1) # Compute tensors in the full format
Y2_full = teneva.full(Y2) # to check the result

v_full = np.sum(Y1_full * Y2_full)

print(v_full) # Print the resulting value from full tensor

# Compute error for TT-tensor vs full tensor :
e = abs((v - v_full)/v_full)
print(f'Error     : {e:-8.2e}')

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

# -3.4604679484459884
# Error     : 7.06e-15
#

We can also set a flag “use_stab”, in which case a value that is 2^p times smaller than the real value will be returned:

v, p = teneva.mul_scalar(Y1, Y2, use_stab=True)
print(v)
print(p)
print(v * 2**p)

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

# -1.7302339742230064
# 1
# -3.460467948446013
#


teneva.act_two.outer(Y1, Y2)[source]

Compute outer product of two TT-tensors.

Parameters:
  • Y1 (list) – TT-tensor.

  • Y2 (list) – TT-tensor.

Returns:

TT-tensor, which is the outer product of Y1 and Y2.

Return type:

list

Note

See also “outer_many” function, which computes outer product of many given TT-tensors.

Examples:

Y1 = teneva.rand([4]*5, 2) # 5-dim random TT-tensor with TT-rank 2
Y2 = teneva.rand([3]*5, 3) # 5-dim random TT-tensor with TT-rank 3
Y = teneva.outer(Y1, Y2) # Compute the outer product of Y1 and Y2
teneva.show(Y)           # Print the resulting TT-tensor

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

# TT-tensor    10D : |4| |4| |4| |4| |4| |3| |3| |3| |3| |3|
# <rank>  =    2.3 :   \2/ \2/ \2/ \2/ \1/ \3/ \3/ \3/ \3/
#
Y1_full = teneva.full(Y1) # Compute tensors in the full format
Y2_full = teneva.full(Y2) # to check the result
Y_full = teneva.full(Y)

Z_full = np.tensordot(Y1_full, Y2_full, 0)

# Compute error for TT-tensor vs full tensor:
e = np.linalg.norm(Y_full - Z_full)
e /= np.linalg.norm(Z_full)
print(f'Error     : {e:-8.2e}')

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

# Error     : 2.09e-16
#


teneva.act_two.sub(Y1, Y2)[source]

Compute Y1 - Y2 in the TT-format.

Parameters:
  • Y1 (int, float, list) – TT-tensor (or it may be int/float).

  • Y2 (int, float, list) – TT-tensor (or it may be int/float).

Returns:

TT-tensor, which represents the result of the operation Y1-Y2. If both Y1 and Y2 are numbers, then result will be float number.

Return type:

list

Examples:

Y1 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2
Y2 = teneva.rand([5]*10, 3) # 10-dim random TT-tensor with TT-rank 3
Y = teneva.sub(Y1, Y2) # Compute the difference between Y1 and Y2
teneva.show(Y)         # Print the resulting TT-tensor (note that it has TT-rank 2 + 3 = 5)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    5.0 :   \5/ \5/ \5/ \5/ \5/ \5/ \5/ \5/ \5/
#
Y1_full = teneva.full(Y1) # Compute tensors in the full format
Y2_full = teneva.full(Y2) # to check the result
Y_full = teneva.full(Y)

Z_full = Y1_full - Y2_full

# Compute error for TT-tensor vs full tensor:
e = np.linalg.norm(Y_full - Z_full)
e /= np.linalg.norm(Z_full)
print(f'Error     : {e:-8.2e}')

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

# Error     : 8.65e-17
#

This function also supports float argument:

Y1 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2
Y2 = 42.                    # Just a number

Y = teneva.sub(Y1, Y2)     # Compute the difference between Y1 and Y2

# Print the resulting TT-tensor (note that it has TT-rank 2 + 1 = 3):
teneva.show(Y)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    3.0 :   \3/ \3/ \3/ \3/ \3/ \3/ \3/ \3/ \3/
#
Y1 = 42.                    # Just a number
Y2 = teneva.rand([5]*10, 2) # 10-dim random TT-tensor with TT-rank 2

Y = teneva.sub(Y1, Y2)      # Compute the difference between Y1 and Y2

# Print the resulting TT-tensor (note that it has TT-rank 2 + 1 = 3):
teneva.show(Y)

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

# TT-tensor    10D : |5| |5| |5| |5| |5| |5| |5| |5| |5| |5|
# <rank>  =    3.0 :   \3/ \3/ \3/ \3/ \3/ \3/ \3/ \3/ \3/
#
Y1 = 44.               # Just a number
Y2 = 2                 # Just a number

Y = teneva.sub(Y1, Y2) # Compute the difference between Y1 and Y2

print(Y)               # The result is a number

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

# 42.0
#