/// <summary> /// Creates a new <see cref="VectorProjOperNode"/> projecting <paramref name="a"/> onto <paramref name="b"/>. /// </summary> /// <param name="a">The <see cref="TensorNode"/> to project from.</param> /// <param name="b">The <see cref="TensorNode"/> to project onto.</param> /// <returns>A new <see cref="VectorProjOperNode"/> as <paramref name="a"/> projected onto <paramref name="b"/>.</returns> public static VectorProductOperNode DotProduct(TensorNode a, TensorNode b) { VectorProductOperNode node = new VectorProductOperNode(VectorProductMethod.DOT); node.AddChild(a); node.AddChild(b); return(node); }
/// <summary> /// Multiplies a tensor by scalars. /// </summary> /// <param name="node">The <see cref="MultiplicationOperNode"/> to simplify.</param> /// <param name="simplifier">The <see cref="Simplifier"/> calling.</param> /// <returns>The resuling <see cref="MultiplicationOperNode"/>.</returns> public static MultiplicationOperNode MultiplyScalarTensor(MultiplicationOperNode node, Simplifier simplifier) { TensorNode tensor1 = null; int ti = -1; for (int i = 0; i < node.ChildCount; i++) { if (i == ti) { continue; } if (node.GetChild(i) is TensorNode tensor2) { if (tensor1 != null) { if (i < ti) { TensorNode swap = tensor1; tensor1 = tensor2; tensor2 = swap; } if (!tensor1.CanMatrixMultiply(tensor2)) { return((MultiplicationOperNode)simplifier.HandleError(new CannotMultiplyTensors(simplifier, node, $"Tensor nodes of size {tensor1.SizeIdentity} and {tensor2.SizeIdentity} could not be multiplied."))); } } else { tensor1 = tensor2; ti = i; i = -1; } } else { if (tensor1 != null) { for (int j = 0; j < tensor1.ChildCount; j++) { ExpNode simpleChild = QuickOpers.Multiply(tensor1.GetChild(j), node.GetChild(i)).Execute(simplifier); tensor1.ReplaceChild(simpleChild, j); } node.RemoveChild(i); if (i < ti) { ti--; } i--; } } } return(node); }
/// <inheritdoc/> public override ExpNode Execute(TensorNode node) { for (int i = 0; i < node.ChildCount; i++) { ExpNode simpleChild = node.GetChild(i).Execute(this); node.ReplaceChild(simpleChild, i); } return(node); }
/// <summary> /// Initializes a new instance of the <see cref="MatrixRow"/> class. /// </summary> /// <param name="matrix">The matrix it's a row off.</param> /// <param name="row">The row of the matrix represented.</param> public MatrixRow(TensorNode matrix, int row) { int width = matrix.GetDimensionSize(1); _values = new ExpNode[width]; for (int i = 0; i < width; i++) { _values[i] = matrix.GetChildD(row, i); } }
/// <summary> /// Initializes a new instance of the <see cref="MatrixByRow"/> class. /// </summary> /// <param name="matrix">The matrix to represent.</param> public MatrixByRow(TensorNode matrix) { Height = matrix.GetDimensionSize(2); Width = matrix.GetDimensionSize(1); _rows = new MatrixRow[Height]; for (int i = 0; i < Height; i++) { _rows[i] = new MatrixRow(matrix, i); } }
/// <summary> /// Checks if two <see cref="TensorNode"/>s are vectors and equal size. /// </summary> /// <param name="node">The first <see cref="ExpNode"/>.</param> /// <param name="other">The second <see cref="ExpNode"/>.</param> /// <param name="vector1">The first <see cref="ExpNode"/> as a <see cref="TensorNode"/>.</param> /// <param name="vector2">The second <see cref="ExpNode"/> as a <see cref="TensorNode"/>.</param> /// <returns>True if two <see cref="TensorNode"/>s are equal size and vectors.</returns> public static bool AreEqualSizeVectors(this ExpNode node, ExpNode other, out TensorNode vector1, out TensorNode vector2) { if (node is TensorNode tensor1 && other is TensorNode tensor2) { vector1 = tensor1; vector2 = tensor2; return(AreEqualSizeVectors(tensor1, tensor2)); } vector1 = vector2 = null; return(false); }
/// <summary> /// Checks if two <see cref="TensorNode"/>s can matrix multiply. /// </summary> /// <param name="node">The first <see cref="TensorNode"/>.</param> /// <param name="other">The second <see cref="TensorNode"/>.</param> /// <returns>True if the Tensors can multiply as matricies.</returns> public static bool CanMatrixMultiply(this TensorNode node, TensorNode other) { // Ensure both TensorNodes are matricies if (node.TensorType != TensorType.Matrix) { return(false); } if (other.TensorType != TensorType.Matrix) { return(false); } // Ensure node's last dimension is the size of other's first dimension return(node.GetDimensionSize(2) == other.GetDimensionSize(1)); }
/// <inheritdoc/> public override string Print(TensorNode node) { string cache = string.Empty; switch (node.TensorType) { case TensorType.Vector: { // Print each child seperated by ',' wrapped in "<>"; cache += "<"; for (int i = 0; i < node.ChildCount; i++) { cache += node.GetChild(i).Print(this); if (i < node.ChildCount - 1) { cache += ","; } } cache += ">"; return(cache); } case TensorType.Matrix: { cache = $"\\matrix{node.SizeIdentity}{{"; for (int i = 0; i < node.ChildCount; i++) { cache += node.GetChild(i).Print(this); if (i < node.ChildCount - 1) { cache += ","; } } cache += "}"; return(cache); } default: // TODO: Print matricies and tensors return(string.Empty); } }
/// <inheritdoc/> public override ParseError ParseNextChar(char c) { if ((c == ',' || c == '>') && _depth == 0) { ParserStatus error = _childParser.Finalize(); if (error.Failed) { return(new ParseError(error)); } ExpTree tree = _childParser.Tree; _childParser = new DefaultParser(); if (tree == null) { return(new ParseError(ErrorType.UNKNOWN)); } _children.Add(tree.Root); if (c == '>') { Output = new TensorNode(new int[] { _children.Count }, _children); } return(new ParseError()); } else { if (c == '<') { _depth++; } else if (c == '>') { _depth--; } ParserStatus result = _childParser.ParseNextChar(c); return(new ParseError(result)); } }
/// <inheritdoc/> public override ParseError ParseNextChar(char c) { switch (_state) { case State.ARGUMENT_X: return(ParseUintArg(c)); case State.OPEN_Y: case State.ARGUMENT_Y: return(ParseUintArg(c)); case State.OPEN_EXPRESSION: if (c == '{') { _state = State.EXPRESSION; _matrix = new TensorNode(_sizes); return(new ParseError()); } else { return(new ParseError(ErrorType.CANNOT_PROCEED)); } case State.EXPRESSION: { if ((c == '}' || c == ',') && _depth == 0) { ParserStatus status = _childParser.Finalize(); if (status.Failed) { return(new ParseError(status)); } ExpTree tree = _childParser.Tree; _childParser = new DefaultParser(); if (tree == null) { return(new ParseError(ErrorType.UNKNOWN)); } _matrix.AddChild(tree.Root); if (c == '}') { _state = State.DONE; Output = _matrix; } return(new ParseError()); } else { if (c == '{') { _depth++; } else if (c == '}') { _depth--; } ParserStatus result = _childParser.ParseNextChar(c); return(new ParseError(result)); } } default: return(new ParseError(ErrorType.UNKNOWN)); } }
/// <summary> /// Checks if two <see cref="TensorNode"/>s are vectors and equal size. /// </summary> /// <param name="node">The first <see cref="TensorNode"/>.</param> /// <param name="other">The second <see cref="TensorNode"/>.</param> /// <returns>True if two <see cref="TensorNode"/>s are equal size and vectors.</returns> public static bool AreEqualSizeVectors(this TensorNode node, TensorNode other) { return(node.DimensionCount == 1 && node.AreEqualSize(other)); }
/// <summary> /// Checks if two <see cref="TensorNode"/>s are the same size. /// </summary> /// <param name="node">The first <see cref="TensorNode"/>.</param> /// <param name="other">The second <see cref="TensorNode"/>.</param> /// <returns>True if the two tensors are equal size.</returns> public static bool AreEqualSize(this TensorNode node, TensorNode other) { return(node.SizeIdentity == other.SizeIdentity); }
/// <summary> /// Executes operation on a <see cref="TensorNode"/>. /// </summary> /// <param name="node">The <see cref="TensorNode"/> to execute operation on.</param> /// <returns>The result of the operation on a <see cref="TensorNode"/>.</returns> public virtual ExpNode Execute(TensorNode node) => Execute((EnumerableCollectionNode)node);
/// <summary> /// Prints a <see cref="TensorNode"/>. /// </summary> /// <param name="node">The <see cref="TensorNode"/> to print.</param> /// <returns>The <see cref="TensorNode"/> printed to a string.</returns> public virtual string Print(TensorNode node) => Print((EnumerableCollectionNode)node);