Beispiel #1
0
        /// <inheritdoc/>
        public override ExpNode Execute(VectorProductOperNode node)
        {
            // Verify left and right child are two multiplyable vectors.
            if (node.LeftChild is TensorNode vector1 && vector1.DimensionCount == 1 &&
                node.RightChild is TensorNode vector2 && vector2.DimensionCount == 1 &&
                vector1.SizeIdentity == vector2.SizeIdentity)
            {
                int size = vector1.GetDimensionSize(1);
                switch (node.ProductMethod)
                {
                case VectorProductMethod.DOT:
                    ExpNode[] terms = new ExpNode[size];
                    for (int i = 0; i < size; i++)
                    {
                        terms[i] = QuickOpers.Multiply(vector1.GetChild(i), vector2.GetChild(i));
                    }
                    return(QuickOpers.Sum(terms).Execute(this));

                case VectorProductMethod.CROSS:     // TODO: Convert to matrix notation for determinant
                default:
                    return(node);
                }
            }

            return(HandleError(new CannotMultiplyTensors(this, node)));
        }
Beispiel #2
0
 /// <inheritdoc/>
 public override ExpNode Execute(VarValueNode node)
 {
     if (node.Character != _variable.Character)
     {
         return(ConstantRule(node));
     }
     return(QuickOpers.Multiply(.5, QuickOpers.Pow(node, 2)));
 }
Beispiel #3
0
        /// <inheritdoc/>
        public override ExpNode Execute(MultiplicationOperNode node)
        {
            // TODO: Sinusoidal u substitutions
            // TODO: Constants recognitions for v
            Differentiator differentiator = new(_variable);

            // \int{u'vwx} = uvwx - \int{uv'wx} - \int{uvw'x} - \int{uvwx'}
            int partCount = node.ChildCount - 1;

            // Get u and du
            ExpNode du = node.GetChild(partCount);
            ExpNode u  = du.Clone().Execute(this);

            // Get dvs and vs
            ExpNode[] dvs = new ExpNode[partCount];
            ExpNode[] vs  = new ExpNode[partCount];
            for (int i = 0; i < partCount; i++)
            {
                vs[i]  = node.GetChild(i);
                dvs[i] = vs[i].Clone().Execute(differentiator);
            }

            AdditionOperNode aNode = new();

            // u*vs
            MultiplicationOperNode mNode = new();

            mNode.AddChild(u.Clone());
            for (int i = 0; i < partCount; i++)
            {
                mNode.AddChild(vs[i].Clone());
            }
            aNode.AddChild(mNode);

            // Combinatoric integrals
            for (int i = 0; i < partCount; i++)
            {
                IntegralOperNode intNode = new();
                mNode            = new MultiplicationOperNode();
                intNode.Variable = new VarValueNode(_variable);
                mNode.AddChild(u.Clone());
                for (int j = 0; j < partCount; j++)
                {
                    if (i == j)
                    {
                        mNode.AddChild(dvs[j].Clone());
                    }
                    else
                    {
                        mNode.AddChild(vs[j].Clone());
                    }
                }
                intNode.AddChild(mNode);
                aNode.AddChild(QuickOpers.Negative(intNode));
            }

            return(aNode);
        }
Beispiel #4
0
        /// <inheritdoc/>
        public override ExpNode Execute(MultiplicationOperNode node)
        {
            double valueProg = 1;

            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 MultiplicationOperNode mNode)
                {
                    mNode.TransferChildren(node);
                    node.RemoveChild(i);
                    i--;
                }
                else
                {
                    node.ReplaceChild(simpleChild, i);
                }
            }

            // Anything multiplied by 0, is zero
            if (valueProg == 0)
            {
                return(QuickOpers.MakeNumericalNode(0));
            }

            if (node.ChildCount == 0 || valueProg != 1)
            {
                node.AddChild(QuickOpers.MakeNumericalNode(valueProg));
            }

            MultiplicationHelpers.SimplfiyMTerms(node, this);

            if (node.ChildCount == 0)
            {
                return(QuickOpers.MakeNumericalNode(0));
            }
            else if (node.ChildCount == 1)
            {
                return(node.GetChild(0));
            }

            node = MultiplicationHelpers.MultiplyScalarTensor(node, this);

            if (node == null)
            {
                return(node);
            }

            return(MultiplicationHelpers.Distribute(node, this));
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        /// <inheritdoc/>
        public override ExpNode Execute(RecipricalOperNode node)
        {
            node.Child = node.Child.Execute(this);

            if (node.Child is NumericalValueNode nvNode)
            {
                return(QuickOpers.MakeNumericalNode(1 / nvNode.DoubleValue));
            }

            return(QuickOpers.Pow(node.Child, -1).Execute(this));
        }
Beispiel #7
0
        private void CompleteValue()
        {
            if (_state != ParserState.INT && _state != ParserState.FLOAT)
            {
                return;
            }

            double value = Convert.ToDouble(_cache);

            _tree.AddNode(QuickOpers.MakeNumericalNode(value));
            _cache = string.Empty;
        }
Beispiel #8
0
        /// <inheritdoc/>
        public override ExpNode Execute(VectorProjOperNode node)
        {
            if (node.LeftChild.AreEqualSizeVectors(node.RightChild, out TensorNode a, out TensorNode b))
            {
                VectorProductOperNode adotb = QuickOpers.DotProduct(a, (TensorNode)b.Clone());
                BOperNode             bdotb = QuickOpers.DotProduct((TensorNode)b.Clone(), (TensorNode)b.Clone());

                return(QuickOpers.Multiply(b, adotb, QuickOpers.Reciprical(bdotb)).Execute(this));
            }

            return(HandleError(new CannotVectorProject(this, node)));
        }
Beispiel #9
0
 private static ExpNode SineTable(SineOperNode node)
 {
     return(node.SineFunction switch
     {
         SineFunction.SINE => new SineOperNode(SineFunction.COSINE)
         {
             Child = node.Child
         },
         SineFunction.COSINE => QuickOpers.Negative(new SineOperNode(SineFunction.SINE)
         {
             Child = node.Child
         }),
         _ => node,
     });
Beispiel #10
0
        /// <inheritdoc/>
        public override ExpNode Execute(SineOperNode node)
        {
            if (node.IsConstantBy(_variable))
            {
                return(QuickOpers.MakeNumericalNode(0));
            }

            // Apply chain rule
            var coefficient = node.Child.Clone().Execute(this);
            // Apply table
            var sinFunc = SineTable(node);

            return(QuickOpers.Multiply(coefficient, sinFunc));
        }
Beispiel #11
0
        /// <inheritdoc/>
        public override ExpNode Execute(PowOperNode node)
        {
            // TODO: Handle variable in exponent
            if (node.IsConstantBy(_variable))
            {
                return(QuickOpers.MakeNumericalNode(0));
            }

            var coefficient = node.RightChild;
            var @base       = node.LeftChild;
            var exponent    = QuickOpers.Add(-1, coefficient);

            return(QuickOpers.Multiply(coefficient, QuickOpers.Pow(@base, exponent)));
        }
Beispiel #12
0
        /// <inheritdoc/>
        public override ExpNode Execute(SineOperNode node)
        {
            if (node.IsConstantBy(_variable))
            {
                return(ConstantRule(node));
            }

            Differentiator diff = new(_variable);
            // Apply ChainRule
            var coefficient = node.Child.Execute(diff);
            // Apply table
            var sinFunc = SineTable(node);

            return(QuickOpers.Multiply(QuickOpers.Reciprical(coefficient), sinFunc));
        }
Beispiel #13
0
        /// <inheritdoc/>
        public override ExpNode Execute(PowOperNode node)
        {
            // TODO: Handle variable in exponent
            if (node.IsConstantBy(_variable))
            {
                return(ConstantRule(node));
            }

            // Increment exponent, divide by exponent
            AdditionOperNode   exponent    = QuickOpers.Add(1, node.RightChild);
            RecipricalOperNode coefficient = QuickOpers.Reciprical(exponent.Clone());
            PowOperNode        @base       = QuickOpers.Pow(node.LeftChild, exponent);

            return(QuickOpers.Multiply(coefficient, @base));
        }
Beispiel #14
0
        /// <summary>
        /// Converts the <see cref="NumericalValueNode"/> back to an <see cref="ExpNode"/>.
        /// </summary>
        /// <returns>The <see cref="NumericalValueNode"/> as an <see cref="ExpNode"/>.</returns>
        public ExpNode AsExpNode()
        {
            if (_exponent is NumericalValueNode nvNode)
            {
                if (nvNode.DoubleValue == 0)
                {
                    return(QuickOpers.MakeNumericalNode(1));
                }
                else if (nvNode.DoubleValue == 1)
                {
                    return(_base);
                }
            }

            return(QuickOpers.Pow(_base, _exponent));
        }
Beispiel #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiplicativeTerm"/> class.
        /// </summary>
        /// <param name="node">The node to create as a term.</param>
        public MultiplicativeTerm(ExpNode node)
        {
            DefaultPrinter printer = new();

            if (node is PowOperNode powNode)
            {
                _base     = powNode.LeftChild;
                _exponent = powNode.RightChild;
            }
            else
            {
                _base     = node;
                _exponent = QuickOpers.MakeNumericalNode(1);
            }
            _baseString = _base.Print(printer);
        }
Beispiel #16
0
        /// <inheritdoc/>
        public override ExpNode Execute(RowElimOperNode node)
        {
            // Ensure matrix.
            if (node.Child is TensorNode tensorNode && tensorNode.TensorType == TensorType.Matrix)
            {
                MatrixByRow matrix           = new MatrixByRow(tensorNode);
                int[]       leadingPositions = RefHelpers.GetLeadingColumns(matrix);

                // Put in row-echelon form
                for (int i = 0; i < matrix.Height; i++)
                {
                    int leftMostCol = RefHelpers.GetLeftMostColumn(leadingPositions, i);
                    matrix.SwapRows(i, leftMostCol);
                    Common.Swap(ref leadingPositions[i], ref leadingPositions[leftMostCol]);

                    if (leadingPositions[i] == -1)
                    {
                        continue;
                    }

                    matrix[i].MultiplyRow(QuickOpers.Reciprical(matrix[i][leadingPositions[i]]));
                    for (int j = i + 1; j < matrix.Height; j++)
                    {
                        matrix[j].AddRowToRow(matrix[i], QuickOpers.Negative(matrix[j][leadingPositions[i]]));
                        leadingPositions[j] = RefHelpers.GetLeadingColumn(matrix[j]);
                    }
                }

                if (node.EliminationMethod == RowElimMethod.GaussJordan)
                {
                    // Put in reduced row-echelon form
                    for (int i = matrix.Height - 1; i > 0; i--)
                    {
                        for (int j = i - 1; j >= 0; j--)
                        {
                            matrix[j].AddRowToRow(matrix[i], QuickOpers.Negative(matrix[j][leadingPositions[i]]));
                            leadingPositions[j] = RefHelpers.GetLeadingColumn(matrix[j]);
                        }
                    }
                }

                return(matrix.AsExpNode());
            }

            return(HandleError(new CannotReduceNonMatrix(this, node.Child)));
        }
Beispiel #17
0
        /// <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);
        }
Beispiel #18
0
        /// <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));
        }
Beispiel #19
0
        /// <inheritdoc/>
        public override ExpNode Execute(PowOperNode node)
        {
            node.LeftChild  = node.LeftChild.Execute(this);
            node.RightChild = node.RightChild.Execute(this);

            if (node.LeftChild is NumericalValueNode lnvNode && node.RightChild is NumericalValueNode rnvNode)
            {
                return(QuickOpers.MakeNumericalNode(Math.Pow(lnvNode.DoubleValue, rnvNode.DoubleValue)));
            }

            if (node.RightChild is IntValueNode ivNode)
            {
                if (ivNode.DoubleValue == 0)
                {
                    return(QuickOpers.MakeNumericalNode(1));
                }
                if (ivNode.DoubleValue == 1)
                {
                    return(node.LeftChild);
                }

                if (node.LeftChild is ValueNode)
                {
                    // No good expanding
                    return(node);
                }

                int n = ivNode.Value;
                // Expand n times
                MultiplicationOperNode mNode = new();

                mNode.AddChild(node.LeftChild);
                for (int i = 1; i < n; i++)
                {
                    mNode.AddChild(node.LeftChild.Clone());
                }

                return(mNode.Execute(this));
            }

            return(PowerHelpers.Distribute(node));
        }
Beispiel #20
0
 /// <summary>
 /// Applies the power distributive property.
 /// </summary>
 /// <param name="node">The <see cref="PowOperNode"/> to simplify.</param>
 /// <returns>The resuling <see cref="ExpNode"/>.</returns>
 public static ExpNode Distribute(PowOperNode node)
 {
     if (node.LeftChild is ParenthesisOperNode parNode)
     {
         // Child is parenthesis
         // Check for multiplication
         if (parNode.Child is MultiplicationOperNode mNode)
         {
             // Grand child is multiplication
             // Distribute
             for (int i = 0; i < mNode.ChildCount; i++)
             {
                 PowOperNode pow = QuickOpers.Pow(mNode.GetChild(i), node.RightChild.Clone());
                 mNode.ReplaceChild(pow, i);
             }
             return(mNode);
         }
     }
     return(node);
 }
Beispiel #21
0
        /// <inheritdoc/>
        public override ExpNode Execute(SineOperNode node)
        {
            node.Child = node.Child.Execute(this);

            if (node.Child is NumericalValueNode nvNode)
            {
                double value = 0;
                switch (node.SineFunction)
                {
                case SineFunction.SINE:
                    value = Math.Sin(nvNode.DoubleValue);
                    break;

                case SineFunction.COSINE:
                    value = Math.Cos(nvNode.DoubleValue);
                    break;

                case SineFunction.TANGENT:
                    value = Math.Tan(nvNode.DoubleValue);
                    break;

                case SineFunction.COSECANT:
                    value = 1 / Math.Sin(nvNode.DoubleValue);
                    break;

                case SineFunction.SECANT:
                    value = 1 / Math.Cos(nvNode.DoubleValue);
                    break;

                case SineFunction.COTANGENT:
                    value = 1 / Math.Tan(nvNode.DoubleValue);
                    break;
                }

                return(QuickOpers.MakeNumericalNode(value));
            }

            return(node);
        }
Beispiel #22
0
        /// <inheritdoc/>
        public override ExpNode Execute(SignOperNode node)
        {
            node.Child = node.Child.Execute(this);
            switch (node.Sign)
            {
            case Sign.POSITIVE:
                return(node.Child);

            case Sign.NEGATIVE:
            {
                if (node.Child is NumericalValueNode nvNode)
                {
                    return(QuickOpers.MakeNumericalNode(nvNode.DoubleValue * -1));
                }

                return(QuickOpers.Multiply(-1, node.Child).Execute(this));
            }

            default:
                return(node);
            }
        }
Beispiel #23
0
 /// <summary>
 /// Adds the exponent of another <see cref="MultiplicativeTerm"/>.
 /// </summary>
 /// <param name="other">The other <see cref="MultiplicativeTerm"/>.</param>
 /// <param name="simplifier">The <see cref="Simplifier"/> to simplify with after adding.</param>
 public void AddToExponent(MultiplicativeTerm other, Simplifier simplifier)
 {
     _exponent = QuickOpers.Sum(_exponent, other._exponent).Execute(simplifier);
 }
Beispiel #24
0
 /// <inheritdoc/>
 public override ExpNode Execute(VarValueNode node)
 {
     return(QuickOpers.MakeNumericalNode(node.Character == _variable.Character ? 1 : 0));
 }
Beispiel #25
0
 /// <inheritdoc/>
 public override ExpNode Execute(NumericalValueNode node)
 {
     return(QuickOpers.MakeNumericalNode(0));
 }