public static SymbolicVariable operator -(SymbolicVariable a, SymbolicVariable b)
 {
     return(SymbolicVariable.Subtract(a, b));
 }
Exemplo n.º 2
0
        /// <summary>
        /// Multiply Coeffecients of second argument into first argument.
        /// </summary>
        /// <param name="SourceTerm"></param>
        /// <param name="TargetSubTerm"></param>
        private static void DivideCoeffecients(ref SymbolicVariable SourceTerm, SymbolicVariable TargetSubTerm)
        {
            // Note: I will try to avoid the primary coeffecient so it doesn't hold power
            //      and only hold coeffecient itself.
            foreach (var cst in TargetSubTerm.Constants)
            {
                if (SourceTerm._CoeffecientPowerTerm == null && cst.ConstantPower == null)
                {
                    SourceTerm.Coeffecient /= cst.ConstantValue;
                }
                // there is a coeffecient power term needs to be injected into the source
                else
                {
                    // no the coeffecient part is not empty so we will test if bases are equal
                    // then make use of the fusedsymbols to add our constant


                    double sbase = Math.Log(SourceTerm.Coeffecient, cst.ConstantValue);

                    if (SourceTerm.Coeffecient == cst.ConstantValue)
                    {
                        // sample: 2^x/2^y = 2^(x-y)
                        var cpower = cst.ConstantPower;
                        if (cpower == null)
                        {
                            cpower = One;
                        }

                        if (SourceTerm._CoeffecientPowerTerm == null)
                        {
                            SourceTerm._CoeffecientPowerTerm = One;
                        }
                        SourceTerm._CoeffecientPowerTerm -= cpower;
                    }
                    else if ((sbase - Math.Floor(sbase)) == 0.0 && sbase > 0)   // make sure there are no
                    {
                        // then we can use the target base
                        // 27/3^x = 3^3/3^x = 3^(3-x)
                        var cpower = cst.ConstantPower;
                        if (cpower == null)
                        {
                            cpower = new SymbolicVariable("1");
                        }
                        SourceTerm._CoeffecientPowerTerm = SymbolicVariable.Subtract(new SymbolicVariable(sbase.ToString(CultureInfo.InvariantCulture)), cpower);
                        SourceTerm.Coeffecient           = cst.ConstantValue;
                    }
                    else
                    {
                        // sample: 2^(x+y)*log(2)*3^y * 3^z   can't be summed.
                        HybridVariable SameCoeffecient;
                        if (SourceTerm.FusedConstants.TryGetValue(cst.ConstantValue, out SameCoeffecient))
                        {
                            SameCoeffecient.SymbolicVariable            -= cst.ConstantPower;
                            SourceTerm.FusedConstants[cst.ConstantValue] = SameCoeffecient;
                        }
                        else
                        {
                            // Add Target coefficient symbol to the fused symbols in source, with key as the coefficient number itself.
                            if (cst.ConstantPower != null)
                            {
                                SourceTerm.FusedConstants.Add(
                                    cst.ConstantValue,
                                    new HybridVariable
                                {
                                    NumericalVariable = -1,     // power
                                    SymbolicVariable  = Subtract(Zero, cst.ConstantPower)
                                });
                            }
                            else
                            {
                                // coeffecient we working with is number only
                                // First Attempt: to try to get the power of this number with base of available coeffecients
                                // if no base produced an integer power value then we add it into fused constants as it is.

                                if (cst.ConstantValue == 1.0)
                                {
                                    continue;                            // ONE doesn't change anything so we bypass it
                                }
                                double?SucceededConstant = null;
                                double ower = 0;
                                foreach (var p in SourceTerm.Constants)
                                {
                                    ower = Math.Log(cst.ConstantValue, p.ConstantValue);
                                    if (ower == Math.Floor(ower))
                                    {
                                        SucceededConstant = p.ConstantValue;
                                        break;
                                    }
                                }

                                if (SucceededConstant.HasValue)
                                {
                                    if (SourceTerm.Coeffecient == SucceededConstant.Value)
                                    {
                                        SourceTerm._CoeffecientPowerTerm -= new SymbolicVariable(ower.ToString(CultureInfo.InvariantCulture));
                                    }
                                    else
                                    {
                                        var rr = SourceTerm.FusedConstants[SucceededConstant.Value];

                                        rr.SymbolicVariable -= new SymbolicVariable(ower.ToString(CultureInfo.InvariantCulture));
                                        SourceTerm.FusedConstants[SucceededConstant.Value] = rr;
                                    }
                                }
                                else
                                {
                                    SourceTerm.FusedConstants.Add(
                                        cst.ConstantValue,
                                        new HybridVariable
                                    {
                                        NumericalVariable = -1,     // power
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }
        private static SymbolicVariable ArithExpression(SymbolicExpressionOperator eop, out short skip)
        {
            SymbolicVariable left  = eop.SymbolicExpression;
            string           op    = eop.Operation;
            SymbolicVariable right = eop.Next.SymbolicExpression;

            skip = 1;

            if (op == "|")
            {
                int    p  = (int)right.SymbolPower;
                string rp = right.Symbol;

                SymbolicVariable v = left;
                while (p > 0)
                {
                    v = v.Differentiate(rp);
                    p--;
                }
                return(v);
            }

            if (op == "^")
            {
                // This will be right associative operator
                // which means if more than one power appeared like this 3^2^4  then it will be processed like this 3^(2^4)

                if (eop.Next.Next != null)
                {
                    if (eop.Next.Operation == "^")
                    {
                        short iskip;
                        var   powerResult = SymbolicVariable.SymbolicPower(
                            left
                            , ArithExpression(eop.Next, out iskip)
                            );

                        skip += iskip;
                        return(powerResult);
                    }
                    else
                    {
                        return(SymbolicVariable.SymbolicPower(left, right));
                    }
                }
                else
                {
                    return(SymbolicVariable.SymbolicPower(left, right));
                }
            }

            if (op == "*")
            {
                return(SymbolicVariable.Multiply(left, right));
            }
            if (op == "/")
            {
                return(SymbolicVariable.Divide(left, right));
            }
            if (op == "+")
            {
                return(SymbolicVariable.Add(left, right));
            }
            if (op == "-")
            {
                return(SymbolicVariable.Subtract(left, right));
            }


            throw new NotSupportedException("Not Supported Operator '" + op + "'");
        }