Evaluate
evaluate(
assignment: str,
output_format: Format | str,
*,
**inputs: Tensor,
) -> Tensor
The main entry point for mathematical operations in Tensora is the evaluate function. It takes a tensor algebra assignment and a list of Tensor objects. It returns a new Tensor, having evaluated the expression according to the input Tensors.
-
assignmentis parsable as an algebraic tensor assignment. -
output_formatis the desired format of the output tensor. -
inputsis all the inputs to the expression. There must be one named argument for each variable name inassignment. The dimensions of the tensors ininputsmust be consistent withassignmentand with each other.
There is also evaluate_tensora and evaluate_taco that have identical interfaces, but use different tensor algebra compilers. evaluate is an alias for the default, which is currently evaluate_tensora. evaluate_taco is only available if the tensora[taco] extra is installed.
from tensora import Tensor, evaluate
A = Tensor.from_lol([[1,2,3], [4,5,6]])
x = Tensor.from_lol([1,2,3])
y = evaluate('y(i) = A(i,j) * x(j)', 'd', A=A, x=x)
assert y == Tensor.from_lol([14, 32])
Assignments
In a loose sense, the assignment strings use Einstein notation. The assignments are made of tensor names, index names, and operations. A tensor with its indexes is the target of the assignment on the left-hand side. Various tensors with their indexes are connected by elementary operations on the right-hand side.
Output indexes
Indexes that appear on both sides match an output dimension to the input dimensions sharing that index.
from tensora import Tensor, evaluate
a = Tensor.from_lol([1,2,3])
b = Tensor.from_lol([4,5,6])
c = evaluate('c(i) = a(i) * b(i)', 'd', a=a, b=b)
assert c == Tensor.from_lol([4, 10, 18])
Contraction indexes
Indexes that appear only on the right-hand side are summed over, also known as a contraction.
from tensora import Tensor, evaluate
A = Tensor.from_lol([[1,2,3], [4,5,6]])
a = evaluate('a(i) = A(i,j)', '', A=A)
assert a == Tensor.from_lol([6, 15])
b = evaluate('b(j) = A(i,j)', '', A=A)
assert b == Tensor.from_lol([5, 7, 9])
This commonly appears in the context of multiplication, in which it called an inner product.
from tensora import Tensor, evaluate
a = Tensor.from_lol([1,2,3])
b = Tensor.from_lol([4,5,6])
c = evaluate('c() = a(i) * b(i)', '', a=a, b=b)
assert c == 32
Broadcasting indexes
Indexes that appear only on the left-hand side would be interpreted as broadcasting the value of the right-hand side along that dimension.
This operation is not currently allowed by evaluate because that indicates that the expression should be broadcast along that target dimension, but there is currently no way to specify the size of that dimension. It is allowed by the tensora CLI, however.
from tensora import Tensor, evaluate
a = Tensor.from_lol(1)
b = evaluate('b(i) = a()', 'd', a=a)
# BroadcastTargetIndexError: Expected index variable i on the target variable
# to be mentioned on the right-hand side, but it was not: b(i) = a(). Such
# broadcasting makes sense in a kernel and those kernels can be generated, but
# they cannot be used in `evaluate` or `tensor_method` because those functions
# get the output dimensions from the the dimensions of the input tensors.
Reusing tensors
Tensor names may be repeated, possibly with different indexes. The tensor can and should only be provided once; it will be used for all occurrences of that tensor name in the assignment.
from tensora import Tensor, evaluate
x = Tensor.from_lol([1,2,3])
V = Tensor.from_lol([[1,2,3], [4,5,6], [7,8,9]])
y = evaluate('y() = x(i) * V(i,j) * x(j)', '', x=x, V=V)
assert y == 228
Diagonal indexes
Indexes may not be repeated within a tensor. Such syntax would represent a diagonal operation, which is currently not supported.
from tensora import Tensor, evaluate
V = Tensor.from_lol([[1,2,3], [4,5,4], [3,2,1]])
v = evaluate('v(i) = V(i,i)', 'd', V=V)
# DiagonalAccessError: Diagonal access to a tensor (i.e. repeating the same
# index within a tensor) is not currently supported: V(i, i)