/// <summary> /// Splits an <see cref="AdditionOperNode"/> into terms and simplifies by common terms. /// </summary> /// <param name="node">The <see cref="AdditionOperNode"/> to simplify.</param> /// <returns>The resulting <see cref="ExpNode"/>.</returns> public static AdditionOperNode SimplfiyATerms(AdditionOperNode node) { SortedSet <AdditiveTerm> aTerms = new(); for (int i = 0; i < node.ChildCount; i++) { AdditiveTerm aTerm = new(node.GetChild(i)); if (aTerms.TryGetValue(aTerm, out AdditiveTerm existingATerm)) { existingATerm.AddToCoefficient(aTerm); } else { aTerms.Add(aTerm); } } node.ClearChildren(); foreach (var term in aTerms) { node.AddChild(term.AsExpNode()); } return(node); }
/// <summary> /// Adds tensors. /// </summary> /// <param name="node">The <see cref="AdditionOperNode"/> containing tensors.</param> /// <param name="simplifier">The <see cref="Simplifier"/> calling.</param> /// <returns>The resuling <see cref="ExpNode"/>.</returns> public static ExpNode SumTensors(AdditionOperNode node, Simplifier simplifier) { if (node.GetChild(0) is TensorNode tensorNode) { for (int i = 1; i < node.ChildCount; i++) { if (node.GetChild(i) is TensorNode otherTensorNode) { if (otherTensorNode.SizeIdentity == tensorNode.SizeIdentity) { for (int j = 0; j < tensorNode.ChildCount; j++) { ExpNode addedNode = QuickOpers .Sum(tensorNode.GetChild(j), otherTensorNode.GetChild(j)) .Execute(simplifier); tensorNode.ReplaceChild(addedNode, j); } } else { return(simplifier.HandleError(new CannotAddTensors(simplifier, node, $"Cannot add tensor of shape {otherTensorNode.SizeIdentity} and tensor of shape {tensorNode.SizeIdentity}."))); } } else { return(simplifier.HandleError(new CannotAddTensors(simplifier, node, "Cannot add scalar and tensor."))); } } return(tensorNode); } else { // There is a scalar. // There cannot be any tensors for (int i = 1; i < node.ChildCount; i++) { if (node.GetChild(i) is TensorNode) { return(simplifier.HandleError(new CannotAddTensors(simplifier, node, "Cannot add tensor and scalar."))); } } } return(node); }
/// <inheritdoc/> public override ExpNode Execute(AdditionOperNode node) { double valueProg = 0; for (int i = 0; i < node.ChildCount; i++) { ExpNode simpleChild = node.GetChild(i).Execute(this); if (simpleChild is NumericalValueNode nvNode) { valueProg += nvNode.DoubleValue; node.RemoveChild(i); i--; } else if (simpleChild is AdditionOperNode aNode) { aNode.TransferChildren(node); node.RemoveChild(i); i--; } else { node.ReplaceChild(simpleChild, i); } } if (node.ChildCount == 0 || valueProg != 0) { node.AddChild(QuickOpers.MakeNumericalNode(valueProg)); } AdditionHelpers.SimplfiyATerms(node); if (node.ChildCount == 0) { return(QuickOpers.MakeNumericalNode(0)); } else if (node.ChildCount == 1) { return(node.GetChild(0)); } return(AdditionHelpers.SumTensors(node, this)); }
/// <inheritdoc/> public override ExpNode Execute(AdditionOperNode node) { // Sum rule for (int i = 0; i < node.ChildCount; i++) { ExpNode diffChild = node.GetChild(i).Execute(this); node.ReplaceChild(diffChild, i); } return(node); }
/// <inheritdoc/> public override string Print(AdditionOperNode node) { string cache = string.Empty; // Add each child seperated by a '+' for (int i = 0; i < node.ChildCount; i++) { var child = node.GetChild(i); bool implicitSign = child is SignOperNode || ((child is NumericalValueNode nvChild) && nvChild.DoubleValue < 0); if (!(i == 0 || implicitSign)) { // Don't add if is a negative sign operator, // a negative numerical value // or if first iteration cache += "+"; } cache += child.Print(this); } return(cache); }