Exemplo n.º 1
0
        /// <summary>
        /// Works on expressions of extra terms to get an expression unified in denominator
        /// </summary>
        /// <param name="sv"></param>
        /// <returns></returns>
        public static SymbolicVariable UnifyDenominators(SymbolicVariable sv)
        {
            var terms = SeparateWithDifferentDenominators(sv);

            SymbolicVariable OrderedVariable = SymbolicVariable.Zero;

            foreach (var exTerm in terms)
            {
                var proTerm = exTerm.Clone();
                if (exTerm._DividedTerm.ExtraTerms.Count > 0)
                {
                    // the denominator needs to be unified also

                    var unif = UnifyDenominators(exTerm._DividedTerm);

                    proTerm._DividedTerm = unif.Numerator;

                    proTerm = SymbolicVariable.Multiply(proTerm, unif.Denominator);
                }

                // multipy the OrderedVariable divided term in the target extra term

                var exNumerator   = SymbolicVariable.Multiply(OrderedVariable.DividedTerm, proTerm.Numerator);
                var exDenominator = SymbolicVariable.Multiply(OrderedVariable.DividedTerm, proTerm.Denominator);

                var OrdNumerator = SymbolicVariable.Multiply(proTerm.Denominator, OrderedVariable.Numerator);


                OrderedVariable = SymbolicVariable.Add(OrdNumerator, exNumerator);

                OrderedVariable._DividedTerm = exDenominator;
            }


            return(OrderedVariable);
        }
        /// <summary>
        /// Works on expressions of extra terms to get an expression unified in denominator
        /// </summary>
        /// <param name="sv"></param>
        /// <returns></returns>
        public static SymbolicVariable UnifyDenominators(SymbolicVariable sv)
        {
            var terms = SeparateWithDifferentDenominators(sv);

            SymbolicVariable OrderedVariable = SymbolicVariable.Zero;

            foreach (var exTerm in terms)
            {
                // multipy the OrderedVariable divided term in the target extra term

                var exNumerator   = SymbolicVariable.Multiply(OrderedVariable.DividedTerm, exTerm.Numerator);
                var exDenominator = SymbolicVariable.Multiply(OrderedVariable.DividedTerm, exTerm.Denominator);

                var OrdNumerator = SymbolicVariable.Multiply(exTerm.Denominator, OrderedVariable.Numerator);


                OrderedVariable = SymbolicVariable.Add(OrdNumerator, exNumerator);

                OrderedVariable._DividedTerm = exDenominator;
            }


            return(OrderedVariable);
        }
        /// <summary>
        /// Simplify Trigonometric Functions
        /// </summary>
        /// <param name="sv"></param>
        public static SymbolicVariable PartialTrigSimplify(SymbolicVariable sv)
        {
            // please refer to TrigSimplification.txt for the algorithm

            Dictionary <string, ParameterSquareTrig> PSTS = new Dictionary <string, ParameterSquareTrig>();

            Func <string, ParameterSquareTrig> PST = (nm) =>
            {
                ParameterSquareTrig p;
                if (!PSTS.TryGetValue(nm, out p))
                {
                    p = new ParameterSquareTrig {
                        Parameter = nm
                    };
                    PSTS.Add(nm, p);
                    return(p);
                }
                else
                {
                    return(p);
                }
            };

            Action <SymbolicVariable> Loop2 = (termPart) =>
            {
                // first test the term then test its fused variables
                var TermsToBeTested = termPart.GetMultipliedTerms();

                foreach (var term in TermsToBeTested)
                {
                    if (term.IsFunction && term._SymbolPower == 2 && term.RawFunctionParameters.Length == 1)
                    {
                        if (term.FunctionName.Equals("Sin", StringComparison.OrdinalIgnoreCase))
                        {
                            PST(term.RawFunctionParameters[0]).Sin_2_Count++;
                        }
                        else if (term.FunctionName.Equals("Cos", StringComparison.OrdinalIgnoreCase))
                        {
                            PST(term.RawFunctionParameters[0]).Cos_2_Count++;
                        }
                        else
                        {
                            // not Trigonometric function
                        }
                    }
                }
            };

            Loop2(sv);
            if (sv._AddedTerms != null)
            {
                foreach (var term in sv._AddedTerms.Values)
                {
                    Loop2(term);
                }
            }


            // coduct the third operation .. final calulcation
            SymbolicVariable SimplifiedResult = sv.Clone();


            foreach (var pst in PSTS.Values)
            {
                while (pst.Cos_2_Count > 0 && pst.Sin_2_Count > 0)
                {
                    var tttt = SymbolicVariable.Add(SimplifiedResult, pst.NegativeSimplifyValue);

                    SimplifiedResult = tttt;

                    pst.Cos_2_Count--;
                    pst.Sin_2_Count--;
                }
            }


            return(SimplifiedResult);
        }
 public static SymbolicVariable operator +(SymbolicVariable a, SymbolicVariable b)
 {
     return(SymbolicVariable.Add(a, b));
 }
        /// <summary>
        /// Multiply Coeffecients of second argument into first argument.
        /// </summary>
        /// <param name="SourceTerm"></param>
        /// <param name="TargetSubTerm"></param>
        private static void MultiplyCoeffecients(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.Add(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)
                            {
                                if (SourceTerm.IsNegativeOne)
                                {
                                    SourceTerm.Coeffecient           = -1 * cst.ConstantValue;
                                    SourceTerm._CoeffecientPowerTerm = cst.ConstantPower;
                                }
                                else
                                {
                                    SourceTerm.FusedConstants.Add(
                                        cst.ConstantValue,
                                        new HybridVariable
                                    {
                                        NumericalVariable = 1,     // power
                                        SymbolicVariable  = cst.ConstantPower.Clone()
                                    });
                                }
                            }
                            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 + "'");
        }
Exemplo n.º 7
0
        private static SymbolicVariable DiffBigTerm(SymbolicVariable sv, string parameter)
        {
            // now result contains only one term
            // -----------------------------------

            // we need to differentiate multiplied terms   in this  ONE TERM
            // every term is differentiated and multiplied by other terms  if  x*y*z  then == dx*y*z+x*dy+z+x*y*dz

            int MultipliedTermsCount = sv.FusedSymbols.Count + sv.FusedConstants.Count + 1; // last one is the basic symbol and coeffecient in the instant

            SymbolicVariable SvDividedTerm = sv.DividedTerm;                                // here we isolate the divided term for later calculations

            sv.DividedTerm = One;

            // separate all terms into array by flatting them
            List <MultipliedTerm> MultipliedTerms = new List <MultipliedTerm>(MultipliedTermsCount);

            Action <SymbolicVariable> SpliBaseTerm = (rr) =>
            {
                var basicterm = rr.Clone();
                basicterm._FusedConstants = null;
                basicterm._FusedSymbols   = null;

                // split coeffecient and its associated symbol

                if (basicterm.CoeffecientPowerTerm != null)
                {
                    // coefficient
                    SymbolicVariable CoeffecientOnly = new SymbolicVariable("");
                    CoeffecientOnly._CoeffecientPowerTerm = basicterm.CoeffecientPowerTerm;
                    CoeffecientOnly.Coeffecient           = basicterm.Coeffecient;
                    MultipliedTerms.Add(new MultipliedTerm(CoeffecientOnly));

                    // multiplied symbol
                    if (!string.IsNullOrEmpty(basicterm.SymbolBaseKey))
                    {
                        MultipliedTerms.Add(new MultipliedTerm(SymbolicVariable.Parse(basicterm.WholeValueBaseKey)));
                    }
                }
                else
                {
                    MultipliedTerms.Add(new MultipliedTerm(basicterm));
                }
            };

            Action <SymbolicVariable> SpliFusedConstants = (rr) =>
            {
                var basicterm = rr.Clone();

                var FCConstants = basicterm._FusedConstants;

                // Key  is the coefficient
                //  value contains the power  which always will be symbolic power or null
                foreach (var FC in FCConstants)
                {
                    SymbolicVariable CoeffecientOnly = new SymbolicVariable("");
                    CoeffecientOnly._CoeffecientPowerTerm = FC.Value.SymbolicVariable.Clone();
                    CoeffecientOnly.Coeffecient           = FC.Key;

                    MultipliedTerms.Add(new MultipliedTerm(CoeffecientOnly));
                }
            };

            Action <SymbolicVariable> SplitFusedSymbols = (rr) =>
            {
                var basicterm = rr.Clone();

                var FSymbols = basicterm._FusedSymbols;

                // Key  is the coefficient
                //  value contains the power  which always will be symbolic power or null
                foreach (var FS in FSymbols)
                {
                    var ss = new SymbolicVariable(FS.Key);
                    ss.SymbolPower = FS.Value.NumericalVariable;
                    if (FS.Value.SymbolicVariable != null)
                    {
                        ss._SymbolPowerTerm = FS.Value.SymbolicVariable.Clone();
                    }

                    MultipliedTerms.Add(new MultipliedTerm(ss));
                }
            };

            SpliBaseTerm(sv);
            if (sv.FusedConstants.Count > 0)
            {
                SpliFusedConstants(sv);
            }
            if (sv.FusedSymbols.Count > 0)
            {
                SplitFusedSymbols(sv);
            }

            List <SymbolicVariable> CalculatedDiffs = new List <SymbolicVariable>(MultipliedTermsCount);

            // get all differentials of all terms                       // x*y*z ==>  dx  dy  dz
            for (int ix = 0; ix < MultipliedTerms.Count; ix++)
            {
                CalculatedDiffs.Add(DiffTerm(MultipliedTerms[ix].Term, parameter));
            }

            // what about divided term ??
            if (!SvDividedTerm.IsOne)
            {
                /*
                 * diff(f(x)*g(x)/h(x),x);
                 *      -(f(x)*g(x)*('diff(h(x),x,1)))/h(x)^2       <== notice the negative sign here and the squared denominator
                 *      +(f(x)*('diff(g(x),x,1)))/h(x)
                 *      +(g(x)*('diff(f(x),x,1)))/h(x)
                 */
                var dvr = Subtract(Zero, SvDividedTerm.Differentiate(parameter));  //differential of divided takes minus sign because it wil
                CalculatedDiffs.Add(dvr);

                // add the divided term but in negative  value because it is divided and in differentiation it will have -ve power
                MultipliedTerms.Add(new MultipliedTerm(SvDividedTerm, true));
            }

            // every result of calculated differentials should be multiplied by the other terms.
            for (int ix = 0; ix < CalculatedDiffs.Count; ix++)
            {
                var term = CalculatedDiffs[ix];

                if (term.IsZero)
                {
                    continue;
                }
                var mt   = One;
                int mltc = MultipliedTerms.Count;

                //if (!SvDividedTerm.IsOne) mltc++;

                for (int iy = 0; iy < mltc; iy++)
                {
                    if (iy == ix)
                    {
                        continue;
                    }

                    if (MultipliedTerms[iy].Divided)
                    {
                        mt = SymbolicVariable.Divide(mt, MultipliedTerms[iy].Term);
                    }
                    else
                    {
                        mt = SymbolicVariable.Multiply(mt, MultipliedTerms[iy].Term);
                    }
                }

                // term *mt
                CalculatedDiffs[ix] = SymbolicVariable.Multiply(mt, term);
            }

            //       dx*y*z     dy*x*z       dz*x*y
            var total = Zero;

            foreach (var cc in CalculatedDiffs)
            {
                if (cc.IsZero)
                {
                    continue;
                }

                total = SymbolicVariable.Add(total, cc);
            }

            if (!SvDividedTerm.IsOne)
            {
                total.DividedTerm = Multiply(SvDividedTerm, SvDividedTerm);
            }

            return(total);
        }