3 ms·
In mathematics, there are two ways to deal with tensors: 1. You come up with notation for tensor spaces, and tensor product operations, and a way to specify th
by dan-robertson 5y ago
In mathematics, there are two ways to deal with tensors:
1. You come up with notation for tensor spaces, and tensor product operations, and a way to specify the indexes of pairs of dimensions you would like to contract, either using algebra or many-argument linear maps.
2. You write down a symbol for the tensors and one suffix for each of the indices. For an arbitrary rank tensor you write something like $T_{ij\cdots k}$. You write tensor operations using the summation convention: every index variable must appear exactly once in a term (indicating that it is free) or twice (indicating that it should be contracted – that is you should take the sum of the values for each possible value of the index). Special tensors are used to express special things.
So for the product of two matrices C = AB, you could write:
c_{ik} = a_{ij} b_{jk}
Or a matrix times a vector:
v_i = a_{ij} u_j
Or the trace of A:
t = a_{ij} \delta_{ij}
(delta is the name of the identity matrix, aka the Kroenecker delta). For the determinant of a matrix you could write:
d = a_{1i} a_{2j} \cdots a_{(n)k} \epsilon_{ij\cdots k}
(Epsilon is the antisymmetric tensor, a rank n, n-dimensional tensor where the element at i, j, …, k is 1 if those indicted are an even permutation of 1, 2, …, n, -1 if they are an odd permutation, and 0 otherwise).
The great advantage is that you don’t spend lots of time faffing around with bounds for the indices or their positions in the tensor product. But to some extent this is only possible because the dimension (ie the bounds) tends to have a physical or geometric meaning. This is also why when the notation is used in physics you also have subscripts and superscripts and you must contract one subscript index with a corresponding superscript index.
I wonder if it is possible to achieve a similarly concise convenient notation for expressing these kinds of vector computations.
You can imagine abusing the notation a bit but leaving most loops and ranges implicit, e.g.
let buf[i] = f(x[i]);
let buf' = buf or 0;
let out[i] = buf'[i-1] + buf[i];
out
(With this having a declarative meaning and not specifying how iteration should be done).
A convolution with 5x5 kernel could be something like:
/* in library */
indicator(p) = if p then 1 else 0
delta[[is]][[js]] = indicator(is == js)
windows(radii)[[is]][[js]][[ks : (-radii..radii)]] = delta[[is]][[js + ks]]
/* in user code */
out[i,j] = in[p,q] * windows([2, 2])[p,q,i,j,k,l] * weight[k,l]
/* implicit sun over all k, l, p, q, but only loops over k, l as p, q values implied */
Where I’ve invented the syntax [[is]] to refer to multiple indices at once.
I don’t know if it would be possible to sufficiently generalise it and avoid having to specify the size of everything everywhere, or whether a computer could recognise enough patterns to convert it to efficient computation.
- hedgehog 5y agoBasically feasible, my previous company wrote a compiler that did that. There are other efforts I'm less familiar with but here's a link for ours: https://arxiv.org/abs/1903.06498 https://arxiv.org/abs/1903.06498