/// <summary> /// Creates a new axis that is put backward /// and then sets all elements as children /// e. g. /// say you have a bunch of tensors {t1, t2, t3} with shape of [2 x 4] /// Stack(t1, t2, t3) => T /// where T is a tensor of shape of [3 x 2 x 4] /// /// O(V) /// </summary> public static GenTensor <T> Stack(params GenTensor <T>[] elements) { #if ALLOW_EXCEPTIONS if (elements.Length < 1) { throw new InvalidShapeException("Shoud be at least one element to stack"); } #endif var desiredShape = elements[0].Shape; #if ALLOW_EXCEPTIONS for (int i = 1; i < elements.Length; i++) { if (elements[i].Shape != desiredShape) { throw new InvalidShapeException($"Tensors in {nameof(elements)} should be of the same shape"); } } #endif var newShape = new int[desiredShape.Count + 1]; newShape[0] = elements.Length; for (int i = 1; i < newShape.Length; i++) { newShape[i] = desiredShape[i - 1]; } var res = new GenTensor <T>(newShape); for (int i = 0; i < elements.Length; i++) { res.SetSubtensor(elements[i], i); } return(res); }
/// <summary> /// Applies matrix dot product operation for /// all matrices in tensors /// /// O(N^3) /// </summary> public static GenTensor <T> TensorMatrixMultiply(GenTensor <T> a, GenTensor <T> b) { #if ALLOW_EXCEPTIONS if (a.Shape.Count < 2 || b.Shape.Count < 2) { throw new InvalidShapeException($"Arguments should be at least matrices while their shapes are {a.Shape} and {b.Shape}"); } if (a.Shape.SubShape(0, 2) != b.Shape.SubShape(0, 2)) { throw new InvalidShapeException("Other dimensions of tensors should be equal"); } #endif var oldShape = a.Shape.SubShape(0, 2).ToArray(); var newShape = new int[oldShape.Length + 2]; for (int i = 0; i < oldShape.Length; i++) { newShape[i] = oldShape[i]; } newShape[newShape.Length - 2] = a.Shape[a.Shape.Length - 2]; newShape[newShape.Length - 1] = b.Shape[b.Shape.Length - 1]; var resTensor = new GenTensor <T>(newShape); foreach (var subDimensions in a.IterateOverMatrices()) { var product = MatrixMultiply(a.GetSubtensor(subDimensions), b.GetSubtensor(subDimensions)); resTensor.SetSubtensor(product, subDimensions); } return(resTensor); }
public static GenTensor <T> Concat(GenTensor <T> a, GenTensor <T> b) { #if ALLOW_EXCEPTIONS if (a.Shape.SubShape(1, 0) != b.Shape.SubShape(1, 0)) { throw new InvalidShapeException("Excluding the first dimension, all others should match"); } #endif if (a.IsVector) { var resultingVector = GenTensor <T> .CreateVector(a.Shape.shape[0] + b.Shape.shape[0]); for (int i = 0; i < a.Shape.shape[0]; i++) { resultingVector.SetValueNoCheck(ConstantsAndFunctions <T> .Forward(a.GetValueNoCheck(i)), i); } for (int i = 0; i < b.Shape.shape[0]; i++) { resultingVector.SetValueNoCheck(ConstantsAndFunctions <T> .Forward(b.GetValueNoCheck(i)), i + a.Shape.shape[0]); } return(resultingVector); } else { var newShape = a.Shape.Copy(); newShape.shape[0] = a.Shape.shape[0] + b.Shape.shape[0]; var res = new GenTensor <T>(newShape); for (int i = 0; i < a.Shape.shape[0]; i++) { res.SetSubtensor(a.GetSubtensor(i), i); } for (int i = 0; i < b.Shape.shape[0]; i++) { res.SetSubtensor(b.GetSubtensor(i), i + a.Shape.shape[0]); } return(res); } }
/// <summary> /// Creates a tensor whose all matrices are identity matrices /// 1 is achieved with TWrapper.SetOne() /// 0 is achieved with TWrapper.SetZero() /// </summary> public static GenTensor <T> CreateIdentityTensor(int[] dimensions, int finalMatrixDiag) { var newDims = new int[dimensions.Length + 2]; for (int i = 0; i < dimensions.Length; i++) { newDims[i] = dimensions[i]; } newDims[newDims.Length - 2] = newDims[newDims.Length - 1] = finalMatrixDiag; var res = new GenTensor <T>(newDims); foreach (var index in res.IterateOverMatrices()) { var iden = CreateIdentityMatrix(finalMatrixDiag); res.SetSubtensor(iden, index); } return(res); }
/// <summary> /// Calls VectorCrossProduct for every vector in the tensor /// </summary> public static GenTensor <T> TensorVectorCrossProduct(GenTensor <T> a, GenTensor <T> b) { #if ALLOW_EXCEPTIONS if (a.Shape != b.Shape) { throw new InvalidShapeException($"Pre-shapes of {nameof(a)} and {nameof(b)} should be equal"); } #endif var res = new GenTensor <T>(a.Shape); foreach (var index in a.IterateOverVectors()) { res.SetSubtensor( VectorCrossProduct(a.GetSubtensor(index), b.GetSubtensor(index)), index ); } return(res); }
public static GenTensor <T> TensorMatrixDivide(GenTensor <T> a, GenTensor <T> b) { #if ALLOW_EXCEPTIONS InvalidShapeException.NeedTensorSquareMatrix(a); InvalidShapeException.NeedTensorSquareMatrix(b); if (a.Shape != b.Shape) { throw new InvalidShapeException("Should be of the same shape"); } #endif var res = new GenTensor <T>(a.Shape); foreach (var ind in res.IterateOverMatrices()) { res.SetSubtensor( MatrixDivide( a.GetSubtensor(ind), b.GetSubtensor(ind) ), ind); } return(res); }