/// <summary>
        /// Converts the symbolic variable into a state of separate simle terms with different denominators
        /// </summary>
        /// <param name="sv"></param>
        /// <returns></returns>
        public static SymbolicVariable[] SeparateWithDifferentDenominators(SymbolicVariable sv)
        {
            List <SymbolicVariable> SeparatedVariabls = new List <SymbolicVariable>();

            for (int i = 0; i < sv.TermsCount; i++)
            {
                SymbolicVariable ordered;
                SymbolicVariable.ReOrderNegativeSymbols(sv[i], out ordered);

                SeparatedVariabls.Add(ordered);
            }

            foreach (var eTerm in sv.ExtraTerms)
            {
                for (int i = 0; i < eTerm.Term.TermsCount; i++)
                {
                    SymbolicVariable ordered;
                    SymbolicVariable.ReOrderNegativeSymbols(eTerm.Term[i], out ordered);

                    if (eTerm.Negative)
                    {
                        ordered = SymbolicVariable.Multiply(SymbolicVariable.NegativeOne, ordered);
                    }

                    SeparatedVariabls.Add(ordered);
                }
            }

            return(SeparatedVariabls.ToArray());
        }
        /// <summary>
        /// Raise to specified power.
        /// </summary>
        /// <param name="power"></param>
        /// <returns></returns>
        public SymbolicVariable Power(int power)
        {
            if (power == 0)
            {
                return(SymbolicVariable._One);
            }

            SymbolicVariable total = this.Clone();
            int pw = Math.Abs(power);

            while (pw > 1)
            {
                if (this.IsFunction && this.FunctionName.Equals("Sqrt", StringComparison.OrdinalIgnoreCase))
                {
                    //
                    var parameterpower = power * 0.5;

                    total = this.FunctionParameters[0].Power(parameterpower);

                    pw = 0; // to end the loop
                }
                else
                {
                    total = SymbolicVariable.Multiply(total, this);
                    pw--;
                }
            }

            if (power < 0)
            {
                total = SymbolicVariable.Divide(SymbolicVariable._One, total);
            }

            return(total);
        }
        /// <summary>
        /// Substitute variable with another variable
        /// </summary>
        /// <param name="variable"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public SymbolicVariable Substitute(string variable, SymbolicVariable value)
        {
            var s  = this.ToString();
            var ss = s.Replace(variable, "(" + value.ToString() + ")");

            return(Parse(ss));
        }
        /// <summary>
        /// Solve for the variable and gets the whole expression for that variable
        /// </summary>
        /// <param name="variable"></param>
        /// <returns></returns>
        public SymbolicVariable Solve(string variable)
        {
            // "5*t1+3/t2"  ==>  5*t1 = -3/t2  ==>  t1  = (-3/t2)*5

            if (_ExtraTerms != null && _ExtraTerms.Count > 0)
            {
                throw new SymbolicException("can't solve expression with extra terms that hold terms with different denominator");
            }

            // Algorithm:
            // search for the term with variable in it
            // don't accept more than one term
            // don't accept terms with power other than 1
            // solve

            SymbolicVariable ExtractedTerm = null;
            SymbolicVariable RestTerm      = this.Clone();

            // extract the needed term
            if (this.Symbol.Equals(variable, StringComparison.OrdinalIgnoreCase))
            {
                ExtractedTerm             = this.Clone();
                ExtractedTerm._AddedTerms = null;

                RestTerm.Coeffecient = 0;
                AdjustZeroCoeffecientTerms(ref RestTerm);  // this will adjust the internal structure of symbolic variabl
            }
            else
            {
                foreach (var t in RestTerm.AddedTerms)
                {
                    if (t.Value.Symbol.Equals(variable, StringComparison.OrdinalIgnoreCase))
                    {
                        ExtractedTerm       = t.Value.Clone();
                        t.Value.Coeffecient = 0;
                        break;
                    }
                }
                AdjustZeroCoeffecientTerms(ref RestTerm);
            }

            if (ExtractedTerm == null)
            {
                throw new SymbolicException("the variable (" + variable + ") of solving not found");
            }

            if (ExtractedTerm.SymbolPower != 1)
            {
                throw new SymbolicException("Variables with higher powers is not solvable for now");
            }

            RestTerm = RestTerm * SymbolicVariable.NegativeOne; // this will transfer the rest value from left to right

            // now we have extracted term as  3*x [Extracted Term] =  5*y [Rest Term]

            SymbolicVariable result = RestTerm / ExtractedTerm.Coeffecient;

            return(result);
        }
Ejemplo n.º 5
0
 public static SymbolicVariable Abs(this SymbolicVariable sv)
 {
     if (sv.IsNegative)
     {
         return(sv * SymbolicVariable.NegativeOne);
     }
     else
     {
         return(sv.Clone());
     }
 }
 /// <summary>
 /// Multiply hybrid variable by symbolic variable, and returns the value into symbolic variable.
 /// because hybrid variable is either number of symbolic.
 /// </summary>
 /// <param name="a"></param>
 /// <param name="b"></param>
 /// <returns><see cref="SymbolicVariable"/></returns>
 internal static SymbolicVariable Multiply(HybridVariable a, SymbolicVariable b)
 {
     if (a.SymbolicVariable != null)
     {
         return(Multiply(a.SymbolicVariable, b));
     }
     else
     {
         return(Multiply(new SymbolicVariable(a.NumericalVariable.ToString(CultureInfo.InvariantCulture)), b));
     }
 }
        /// <summary>
        /// Trys to simplify the expression with trigonemtric rules.
        /// </summary>
        /// <param name="sv"></param>
        /// <returns></returns>
        public static SymbolicVariable TrigSimplify(SymbolicVariable sv)
        {
            if (sv.ExtraTerms.Count > 0)
            {
                return(sv.Clone());                         //prevent simplification in case of extra terms
            }
            var factorized = FactorWithCommonFactor(sv);

            SymbolicVariable total = SymbolicVariable.Zero.Clone();

            // facorized expressions contain their terms in the multiplied symbols
            for (int i = 0; i < factorized.TermsCount; i++)
            {
                // go through each term
                var term = factorized[i];

                for (int fui = 0; fui < term.FusedSymbols.Count; fui++)
                {
                    var ss = term.GetFusedTerm(fui);
                    var sp = ss;
                    if (!ss.IsOneTerm)
                    {
                        if (ss.CanBeFactored())
                        {
                            sp = TrigSimplify(ss);
                        }
                        else
                        {
                            sp = PartialTrigSimplify(ss);
                        }
                        if (sp.IsOne)  // if equals 1  then remove it
                        {
                            // remove this fused symbol from the structure
                            term._FusedSymbols.Remove(term.GetFusedKey(fui));
                        }
                        else
                        {
                            // replace with the new value in the fused symbols.
                            term._FusedSymbols.Add(sp.ToString(), term._FusedSymbols[term.GetFusedKey(fui)]);

                            term._FusedSymbols.Remove(term.GetFusedKey(fui));
                        }
                    }
                }

                total = total + term;
            }

            // so begin in the factorized
            var tsimp = PartialTrigSimplify(total);

            return(tsimp);
        }
        /// <summary>
        /// Reorders the negative symbols and gets them into DividedTerm object.
        /// for example 4*x^-2*y^6*u^-4  will get u^4*x^2  and 5/a  will get a
        /// works only in single term doesn't include extra terms
        /// </summary>
        /// <param name="sVariable">source symbolic variable (processed in one term only)</param>
        /// <param name="reOrderedVariable"></param>
        /// <returns></returns>
        public static SymbolicVariable ReOrderNegativeSymbols(SymbolicVariable sVariable, out SymbolicVariable reOrderedVariable)
        {
            SymbolicVariable denominator = SymbolicVariable.One.Clone();

            reOrderedVariable = sVariable.Clone();

            if (sVariable.SymbolPower < 0)
            {
                // transfer symbols into the divided term
                denominator.SymbolPower = Math.Abs(sVariable.SymbolPower);
                denominator.Symbol      = sVariable.Symbol;

                if (sVariable._SymbolPowerTerm != null) //include the symbol power term also but invert its sign
                {
                    denominator._SymbolPowerTerm = SymbolicVariable.Multiply(SymbolicVariable.NegativeOne, sVariable._SymbolPowerTerm);
                }


                // fix the reordered variable by removing this symbol information because it will appear later
                //   in the divided term.

                reOrderedVariable.SymbolPower      = 0;
                reOrderedVariable._SymbolPowerTerm = null;
                reOrderedVariable.Symbol           = string.Empty;
            }

            foreach (var fs in sVariable.FusedSymbols)
            {
                if (fs.Value.IsNegative)
                {
                    var siv = new SymbolicVariable(fs.Key);
                    if (fs.Value.SymbolicVariable != null)
                    {
                        siv._SymbolPowerTerm =
                            SymbolicVariable.Multiply(SymbolicVariable.NegativeOne, fs.Value.SymbolicVariable);
                    }
                    else
                    {
                        siv.SymbolPower = Math.Abs(fs.Value.NumericalVariable);
                    }

                    denominator = SymbolicVariable.Multiply(denominator, siv);  // accumulate negative power symbols here

                    // remove this fused symbol from reOrdered variable
                    reOrderedVariable.FusedSymbols.Remove(fs.Key);
                }
            }


            reOrderedVariable.DividedTerm = SymbolicVariable.Multiply(reOrderedVariable.DividedTerm, denominator);

            return(denominator);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Converts the symbolic variable into a state of separate simple terms with different denominators
        /// </summary>
        /// <param name="sv"></param>
        /// <returns></returns>
        public static SymbolicVariable[] SeparateWithDifferentDenominators(SymbolicVariable sv)
        {
            List <SymbolicVariable> SeparatedVariabls = new List <SymbolicVariable>();


            var svclone = sv.Clone(true);
            var divisor = svclone._DividedTerm;

            svclone._DividedTerm = SymbolicVariable.One;
            for (int i = 0; i < svclone.TermsCount; i++)
            {
                SymbolicVariable ordered;
                SymbolicVariable.ReOrderNegativeSymbols(svclone[i], out ordered);
                ordered._DividedTerm = SymbolicVariable.Multiply(divisor, ordered._DividedTerm);
                SeparatedVariabls.Add(ordered);
            }

            var extraTerms = sv.ExtraTerms;

            foreach (var eTerm in extraTerms)
            {
                /*
                 * for (int i = 0; i < eTerm.Term.TermsCount; i++)
                 * {
                 *  SymbolicVariable ordered;
                 *  SymbolicVariable.ReOrderNegativeSymbols(eTerm.Term[i], out ordered);
                 *
                 *  if (eTerm.Negative)
                 *  {
                 *      ordered = SymbolicVariable.Multiply(SymbolicVariable.NegativeOne, ordered);
                 *  }
                 *
                 *  SeparatedVariabls.Add(ordered);
                 * }
                 */

                SeparatedVariabls.AddRange(SeparateWithDifferentDenominators(eTerm.Term));
            }

            return(SeparatedVariabls.ToArray());
        }
        public SymbolicVariable Power(double power)
        {
            if (Math.Floor(power) == power)
            {
                return(Power((int)power));
            }

            SymbolicVariable p = this.Clone();

            if (p.IsOneTerm)
            {
                // raise the coeffecient and symbol
                if (!string.IsNullOrEmpty(p.Symbol))
                {
                    p.SymbolPower = power;
                }
                p.Coeffecient = Math.Pow(p.Coeffecient, power);
            }
            else
            {
                if (power == 0.5)
                {
                    // return sqrt function of the multi term

                    return(new SymbolicVariable("Sqrt(" + p.ToString() + ")"));
                }
                else if (power > 0 && power < 1)
                {
                    // I don't have solution for this now
                    throw new SymbolicException("I don't have solution for this type of power " + p.ToString() + "^ (" + power.ToString() + ")");
                }
                else
                {
                    // multi term that we can't raise it to the double
                    return(p.RaiseToSymbolicPower(new SymbolicVariable(power.ToString())));
                }
            }

            return(p);
        }
Ejemplo n.º 11
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);
        }
 public static SymbolicVariable Simplify(SymbolicVariable sv)
 {
     return(UnifyDenominators(sv));
 }
        /// <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);
        }
        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 + "'");
        }
 public static SymbolicVariable operator -(SymbolicVariable a, SymbolicVariable b)
 {
     return(SymbolicVariable.Subtract(a, b));
 }
        /// <summary>
        /// Factor the expression.
        /// </summary>
        /// <param name="sv"></param>
        /// <returns></returns>
        public static SymbolicVariable FactorWithCommonFactor(SymbolicVariable sv)
        {
            var map = sv.GetCommonFactorsMap();


            // get all keys  sorted by number of elements

            var keys = (from mk in map
                        orderby mk.Value.Count descending
                        where mk.Key.Equals(One) == false && mk.Value.Count > 1 && mk.Key.IsCoeffecientOnly == false
                        select mk.Key).ToArray();



            if (keys.Length == 0)
            {
                return(sv.Clone());
            }
            // ignore the 1 key

            // imagine a*x+a*y  result is a*(x+y)

            SymbolicVariable result = SymbolicVariable.One.Clone();

            var term_key = keys[0];  // the biggest values count   as shown above in the query statement

            var term_indices = map[term_key];

            List <SymbolicVariable> Common_Factors_Keys = new List <SymbolicVariable>();

            Common_Factors_Keys.Add(term_key);

            // find the other keys that has the same indices like this key
            for (int i = 1; i < keys.Length; i++)
            {
                var target_indices = map[keys[i]];
                if (target_indices.Count == term_indices.Count)
                {
                    // compare indices toghether
                    foreach (var idc in term_indices)
                    {
                        if (!target_indices.Contains(idc))
                        {
                            continue;
                        }
                    }

                    // reaching this line indicates that the two arrays contains the same indices

                    // so we save this key as another common factor for the expression
                    Common_Factors_Keys.Add(keys[i]);
                }

                if (target_indices.Count < term_indices.Count)
                {
                    break;                                            // the array is ordered from higher count to low count so there is no point in comparing more results .. break the loop
                }
            }

            //Common_Factors_Keys  now contains the factors that I will work on it.

            SymbolicVariable common_multipliers = SymbolicVariable.Zero.Clone();
            SymbolicVariable rest_multipliers   = SymbolicVariable.Zero.Clone();

            for (int i = 0; i < sv.TermsCount; i++)
            {
                if (term_indices.Contains(i))
                {
                    // remove the common factor and add the result into the common_multipliers
                    var term = sv[i].Clone();
                    foreach (SymbolicVariable ke in Common_Factors_Keys)
                    {
                        term = SymbolicVariable.Divide(term, ke);   // divide by factor to remove it from the term.

                        /*
                         * if (term.Symbol == ke.Symbol)
                         * {
                         *  term.SymbolPower = 0;
                         *  AdjustZeroPowerTerms(term);
                         * }
                         * else
                         * {
                         *  // remove from the fused symbols
                         *  term._FusedSymbols.Remove(ke.ToString());
                         * }
                         */
                    }

                    common_multipliers += term;
                }
                else
                {
                    // doesn't contain the variable we want to remove so we store the term into the rest of the expressions to be added at the end of this procedure
                    rest_multipliers += sv[i].Clone();
                }
            }

            // at last alter the symbolic variable instant so that it contains the new shape
            foreach (var ke in Common_Factors_Keys)
            {
                result = result * ke;
            }

            result.FusedSymbols.Add(common_multipliers.ToString(), new HybridVariable {
                NumericalVariable = 1.0
            });

            result = result + rest_multipliers;

            return(result);
        }
        /// <summary>
        /// Subtracts symbolic variable b from symbolic variable a
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static SymbolicVariable Subtract(SymbolicVariable a, SymbolicVariable b)
        {
            if (a == null || b == null)
            {
                return(null);
            }

            if (!a.DividedTerm.Equals(b.DividedTerm))
            {
                SymbolicVariable a_b       = a.Clone();
                bool             econsumed = false;
                if (a_b.ExtraTerms.Count > 0)
                {
                    // find if in extra terms there is an equality  of b into it
                    for (int iet = 0; iet < a_b.ExtraTerms.Count; iet++)
                    {
                        if (a_b.ExtraTerms[iet].Term.DividedTerm.Equals(b.DividedTerm))
                        {
                            a_b.ExtraTerms[iet].Term = Subtract(a_b.ExtraTerms[iet].Term, b);
                            econsumed = true;
                            break;
                        }
                    }
                }

                if (!econsumed)
                {
                    // add in the extra terms
                    var negative_b = b.Clone();

                    a_b.ExtraTerms.Add(new ExtraTerm {
                        Term = negative_b, Negative = true
                    });
                }
                AdjustZeroCoeffecientTerms(ref a_b);
                return(a_b);
            }


            SymbolicVariable subB = b.Clone();
            int sub = -1;

            SymbolicVariable sv = a.Clone();

NewPart:


            bool consumed = false;

            if (a.BaseEquals(subB))
            {
                if (a.CoeffecientPowerTerm == null && subB.CoeffecientPowerTerm == null)
                {
                    sv.Coeffecient = a.Coeffecient - subB.Coeffecient;
                    consumed       = true;
                }
                else if (a.CoeffecientPowerTerm != null && subB.CoeffecientPowerTerm != null)
                {
                    if (a.CoeffecientPowerTerm.Equals(subB.CoeffecientPowerTerm))
                    {
                        var cr = a.Coeffecient - subB.Coeffecient;
                        if (cr == 0)
                        {
                            sv.Coeffecient = cr;
                            consumed       = true;
                        }
                    }
                }
                else
                {
                    // nothing
                }
            }

            //so the equality doesn't exits or this instance have other terms also

            // there are two cases now
            //  1- the symbolic can be added to one of the existing terms (which will be perfect)
            //  2- there are no compatible term so we have to add it to the addedvariables of this instance.


            foreach (var av in a.AddedTerms)
            {
                if (av.Value.BaseEquals(subB))
                {
                    var iv = a.AddedTerms[av.Key].Clone();

                    if (iv.CoeffecientPowerTerm == null && subB.CoeffecientPowerTerm == null)
                    {
                        iv.Coeffecient        = iv.Coeffecient - subB.Coeffecient;
                        sv.AddedTerms[av.Key] = iv;
                        consumed = true;
                    }
                    else if (iv.CoeffecientPowerTerm != null && subB.CoeffecientPowerTerm != null)
                    {
                        if (iv.CoeffecientPowerTerm.Equals(subB.CoeffecientPowerTerm))
                        {
                            var cr = iv.Coeffecient - subB.Coeffecient;
                            if (cr == 0)
                            {
                                iv.Coeffecient        = cr;
                                sv.AddedTerms[av.Key] = iv;
                                consumed = true;
                            }
                        }
                    }
                    else
                    {
                    }
                }
            }


            if (!consumed)
            {
                // add it to the positive variables.

                SymbolicVariable pv;

                sv.AddedTerms.TryGetValue(subB.WholeValueBaseKey, out pv);

                if (pv == null)
                {
                    pv              = subB.Clone();
                    pv.Coeffecient *= -1;

                    var SubTerms = pv._AddedTerms; // store them for later use.
                    pv._AddedTerms = null;

                    pv.DividedTerm = One;

                    sv.AddedTerms.Add(pv.WholeValueBaseKey, pv);

                    if (SubTerms != null)
                    {
                        //then add the value added terms if exist
                        foreach (var at in pv.AddedTerms)
                        {
                            at.Value.Coeffecient *= -1;
                            sv.AddedTerms.Add(at.Value.WholeValueBaseKey, at.Value);
                        }
                    }
                }
                else
                {
                    //exist before add it to this variable.

                    sv.AddedTerms[subB.WholeValueBaseKey] = Subtract(sv.AddedTerms[subB.WholeValueBaseKey], subB);
                }
            }

            if (b.AddedTerms.Count > 0)
            {
                sub = sub + 1;  //increase
                if (sub < b.AddedTerms.Count)
                {
                    // there are still terms to be consumed
                    //   this new term is a sub term in b and will be added to all terms of a.
                    subB = b.AddedTerms.ElementAt(sub).Value;
                    goto NewPart;
                }
            }

            // reaching here indicates that we didn't sum up the value to any of the target extra terms
            // so we need to include extra terms here
            if (b._ExtraTerms != null && b._ExtraTerms.Count > 0)
            {
                // add extra terms of b into sv
                foreach (var eb in b._ExtraTerms)
                {
                    var eeb = eb.Clone();

                    if (eeb.Negative)
                    {
                        eeb.Negative = false;                // -- == +
                    }
                    sv.ExtraTerms.Add(eeb);
                }
            }


            AdjustSpecialFunctions(ref sv);
            AdjustZeroPowerTerms(sv);
            AdjustZeroCoeffecientTerms(ref sv);


            return(sv);
        }
        /// <summary>
        /// Parse expression of variables and make SymbolicVariable
        /// </summary>
        /// <param name="expr"></param>
        /// <returns></returns>
        public static SymbolicVariable Parse(string expression)
        {
            var r = from zr in expression.Split(new string[] { ":=" }, StringSplitOptions.RemoveEmptyEntries)
                    where string.IsNullOrWhiteSpace(zr) == false
                    select zr.Trim();

            string[] rr = r.ToArray();

            string expr = string.Empty;

            if (rr.Length == 0)
            {
                return(null);
            }
            if (rr.Length > 1)
            {
                //function
                expr = rr[1];
            }
            else
            {
                expr = rr[0];
            }

            char[] separators = { '^', '*', '/', '+', '-', '(', '|' };
            char[] seps       = { '^', '*', '/', '+', '-', '|' };


            expr = expr.Replace(" ", "");

            //if (expression.StartsWith("-") ||expression.StartsWith("+")) expression = expression.Insert(1,"1*");

            // simple parsing
            // obeys the rules of priorities

            // Priorities
            //    ^  Power
            //    *  multiplication
            //    /  division
            //    +  Addition
            //    -  Subtraction


            bool NextGroupIsNegativeSign = false;

            // Tokenization is done by separating with operators
            SymbolicExpressionOperator Root = new SymbolicExpressionOperator();
            SymbolicExpressionOperator ep   = Root;

            StringBuilder TokenBuilder    = new StringBuilder();
            Stack <int>   PLevels         = new Stack <int>();
            bool          Inner           = false;
            bool          FunctionContext = false;

            for (int ix = 0; ix < expr.Length; ix++)
            {
                if (PLevels.Count == 0)
                {
                    // include the normal parsing when we are not in parenthesis group
                    if (separators.Contains(expr[ix]))
                    {
                        if ((expr[ix] == '-' || expr[ix] == '+') && ix == 0)
                        {
                            if (expr[ix] == '-')
                            {
                                // in case of -x  for example ..this will converted into operations
                                //  of -1 * x
                                ep.SymbolicExpression = SymbolicVariable.NegativeOne;
                                ep.Operation          = "*";

                                ep.Next = new SymbolicExpressionOperator();
                                ep      = ep.Next;      // advance the reference to the next node to make the linked list.

                                TokenBuilder = new StringBuilder();
                            }
                            else
                            {
                                // append the normal token
                                TokenBuilder.Append(expr[ix]);
                            }
                        }
                        else if (ix > 1 &&
                                 char.ToUpper(expr[ix - 1]) == 'E' && char.IsDigit(expr[ix - 2]) &&
                                 (expr[ix] == '-' || expr[ix] == '+'))
                        {
                            // case of 3e+2 4e-2  all cases with e in it.
                            TokenBuilder.Append(expr[ix]);
                        }
                        else if (expr[ix] == '(')
                        {
                            PLevels.Push(1);
                            var bb = ix > 0 ? separators.Contains(expr[ix - 1]) : true;
                            if (!bb)
                            {
                                //the previous charachter is normal word which indicates we reached a function
                                FunctionContext = true;
                                TokenBuilder.Append(expr[ix]);
                            }
                        }
                        else if (
                            seps.Contains(expr[ix - 1]) &&
                            (expr[ix] == '-' || expr[ix] == '+')
                            )
                        {
                            if (expr[ix + 1] == '(')
                            {
                                // so this sign is glued to the next parentheisis group

                                TokenBuilder.Append(expr[ix]);

                                // now TokenBuilder contains all signs before this

                                // and we need to preserve the information about next group
                                //   that it has a sign.

                                string signs = TokenBuilder.ToString();

                                int nve = signs.ToCharArray().Count(sign => sign == '-');

                                if ((nve % 2.0) != 0)
                                {
                                    // negative sign
                                    NextGroupIsNegativeSign = true;
                                }
                                TokenBuilder.Clear();
                            }
                            else
                            {
                                TokenBuilder.Append(expr[ix]);
                            }
                        }
                        else
                        {
                            // tokenize   when we reach any operator  or open '(' parenthesis
                            if (Inner)
                            {
                                ep.SymbolicExpression = Parse(TokenBuilder.ToString());

                                if (NextGroupIsNegativeSign)
                                {
                                    ep.SymbolicExpression = SymbolicVariable.Multiply(SymbolicVariable.NegativeOne, ep.SymbolicExpression);

                                    NextGroupIsNegativeSign = false;
                                }
                                Inner = false;
                            }
                            else
                            {
                                ep.SymbolicExpression = new SymbolicVariable(TokenBuilder.ToString());
                            }

                            TokenBuilder = new StringBuilder();

                            ep.Operation = expr[ix].ToString();
                            ep.Next      = new SymbolicExpressionOperator();
                            ep           = ep.Next; // advance the reference to the next node to make the linked list.
                        }
                    }
                    else
                    {
                        TokenBuilder.Append(expr[ix]);
                    }
                }
                else
                {
                    // we are in group
                    if (expr[ix] == '(')
                    {
                        PLevels.Push(1);
                    }
                    if (expr[ix] == ')')
                    {
                        PLevels.Pop();

                        if (PLevels.Count == 0)
                        {
                            Inner = true;
                            if (FunctionContext)
                            {
                                TokenBuilder.Append(expr[ix]);
                                FunctionContext = false;
                                Inner           = false; // because i am taking the function body as a whole in this parse pass.
                                // then inner parameters of the function will be parsed again
                            }
                        }
                        else
                        {
                            TokenBuilder.Append(expr[ix]);
                        }
                    }
                    else
                    {
                        TokenBuilder.Append(expr[ix]);
                    }
                }
            }

            // Last pass that escaped from the loop.
            if (Inner)
            {
                ep.SymbolicExpression = Parse(TokenBuilder.ToString());
                if (NextGroupIsNegativeSign)
                {
                    ep.SymbolicExpression = SymbolicVariable.Multiply(SymbolicVariable.NegativeOne, ep.SymbolicExpression);

                    NextGroupIsNegativeSign = false;
                }

                Inner = false;
            }
            else
            {
                ep.SymbolicExpression = new SymbolicVariable(TokenBuilder.ToString());
            }
            TokenBuilder = null;


            string[] Group = { "^"    /* Power for normal product '*' */
            };

            string[] SymGroup = { "|" /* Derivation operator */ };

            string[] Group1 = { "*" /* normal multiplication */,
                                "/" /* normal division */,
                                "%" /* modulus */ };


            string[] Group2 = { "+", "-" };

            /// Operator Groups Ordered by Priorities.
            string[][] OperatorGroups = { Group, SymGroup, Group1, Group2 };

            foreach (var opg in OperatorGroups)
            {
                SymbolicExpressionOperator eop = Root;

                //Pass for '[op]' and merge it  but from top to child :)  {forward)
                while (eop.Next != null)
                {
                    //if the operator in node found in the opg (current operator group) then execute the logic

                    if (opg.Count(c => c.Equals(eop.Operation, StringComparison.OrdinalIgnoreCase)) > 0)
                    {
                        short skip;
                        eop.SymbolicExpression = ArithExpression(eop, out skip);

                        //drop eop.Next
                        if (eop.Next.Next != null)
                        {
                            while (skip > 0)
                            {
                                eop.Operation = eop.Next.Operation;

                                eop.Next = eop.Next.Next;

                                skip--;
                            }
                        }
                        else
                        {
                            //no more nodes exit the loop

                            eop.Next      = null; //last item were processed.
                            eop.Operation = string.Empty;
                        }
                    }
                    else
                    {
                        eop = eop.Next;
                    }
                }
            }

            if (rr.Length > 1)
            {
                // there was a function defintion
                var fname = rr[0];

                Functions[fname] = Root.SymbolicExpression;
            }

            return(Root.SymbolicExpression);
        }
Ejemplo n.º 20
0
        public static SymbolicVariable operator /(int a, SymbolicVariable b)
        {
            var sv = new SymbolicVariable(a.ToString(CultureInfo.InvariantCulture)) / b;

            return(sv);
        }
 public static SymbolicVariable operator +(SymbolicVariable a, SymbolicVariable b)
 {
     return(SymbolicVariable.Add(a, b));
 }
Ejemplo n.º 22
0
        public static SymbolicVariable Divide(SymbolicVariable a, SymbolicVariable b)
        {
            if (a == null || b == null)
            {
                return(null);
            }

            SymbolicVariable SourceTerm = a.Clone();

            // if the divided term is more than on term
            // x^2/(y-x)  ==>
            if (b.AddedTerms.Count > 0 || (b._ExtraTerms != null && b._ExtraTerms.Count > 0))
            {
                if (a.Equals(b))
                {
                    return(new SymbolicVariable("1"));
                }

                //multiply divided term by this value
                if (!a.IsZero)
                {
                    SourceTerm.DividedTerm = Multiply(SourceTerm.DividedTerm, b);

                    return(SourceTerm);
                }
                else
                {
                    return(new SymbolicVariable("0"));
                }
            }


            SymbolicVariable TargetSubTerm = b.Clone();


            TargetSubTerm._AddedTerms = null;   // remove added variables to prevent its repeated calculations in second passes
            TargetSubTerm._ExtraTerms = null;
            // or to make sure nothing bad happens {my idiot design :S)

            if (a.BaseEquals(TargetSubTerm))
            {
                #region symbols are equal (I mean 2*x^3 = 2*X^3)

                DivideCoeffecients(ref SourceTerm, TargetSubTerm);

                if (a.SymbolPowerTerm != null || TargetSubTerm.SymbolPowerTerm != null)
                {
                    SourceTerm._SymbolPowerTerm = a.SymbolPowerTerm - TargetSubTerm.SymbolPowerTerm;
                }
                else
                {
                    SourceTerm.SymbolPower = SourceTerm.SymbolPower - TargetSubTerm.SymbolPower;
                }



                //fuse the fused symbols in b into sv
                foreach (var bfv in TargetSubTerm.FusedSymbols)
                {
                    if (SourceTerm.FusedSymbols.ContainsKey(bfv.Key))
                    {
                        SourceTerm.FusedSymbols[bfv.Key] -= bfv.Value;
                    }
                    else
                    {
                        SourceTerm.FusedSymbols.Add(bfv.Key, bfv.Value * -1);
                    }
                }
                #endregion
            }
            else
            {
                #region Symbols are different
                if (string.IsNullOrEmpty(SourceTerm.Symbol))
                {
                    #region First Case: Source primary symbol doesn't exist
                    // the instance have an empty primary variable so we should add it

                    if (TargetSubTerm._BaseVariable != null)
                    {
                        SourceTerm._BaseVariable = TargetSubTerm._BaseVariable;
                    }
                    else
                    {
                        SourceTerm.Symbol = TargetSubTerm.Symbol;
                    }

                    SourceTerm.SymbolPower = -1 * TargetSubTerm.SymbolPower;
                    if (TargetSubTerm.SymbolPowerTerm != null)
                    {
                        SourceTerm._SymbolPowerTerm = -1 * TargetSubTerm.SymbolPowerTerm.Clone();
                    }

                    //fuse the fusedvariables in b into sv
                    foreach (var bfv in TargetSubTerm.FusedSymbols)
                    {
                        if (SourceTerm.FusedSymbols.ContainsKey(bfv.Key))
                        {
                            SourceTerm.FusedSymbols[bfv.Key] -= bfv.Value;
                        }
                        else
                        {
                            SourceTerm.FusedSymbols.Add(bfv.Key, bfv.Value * -1);
                        }
                    }
                    #endregion
                }
                else
                {
                    if (SourceTerm.Symbol.Equals(TargetSubTerm.Symbol, StringComparison.OrdinalIgnoreCase))
                    {
                        #region Second Case: Primary symbol in both source and target exist and equal
                        if (SourceTerm._SymbolPowerTerm != null || TargetSubTerm._SymbolPowerTerm != null)
                        {
                            // make sure the object of symbol power term have values if they don't
                            if (SourceTerm._SymbolPowerTerm == null)
                            {
                                // transfer the numerical power into symbolic variable mode
                                SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm.SymbolPower.ToString(CultureInfo.InvariantCulture));

                                // also revert the original symbol power into 1  for validation after this
                                SourceTerm.SymbolPower = 1;
                            }

                            if (TargetSubTerm._SymbolPowerTerm == null)
                            {
                                TargetSubTerm._SymbolPowerTerm = new SymbolicVariable(TargetSubTerm.SymbolPower.ToString(CultureInfo.InvariantCulture));

                                TargetSubTerm.SymbolPower = -1; // the target will always be dominator
                            }

                            SourceTerm._SymbolPowerTerm -= TargetSubTerm._SymbolPowerTerm;

                            if (SourceTerm._SymbolPowerTerm.IsCoeffecientOnly)
                            {
                                SourceTerm._SymbolPower     = SourceTerm._SymbolPowerTerm.Coeffecient;
                                SourceTerm._SymbolPowerTerm = null;  // remove it because we don't need symbolic when we reach co
                            }
                            else
                            {
                                // correct the source symbol power (because after division the power may still be positive
                                if (SourceTerm._SymbolPowerTerm.IsNegative)
                                {
                                    SourceTerm._SymbolPower = -1;

                                    SourceTerm._SymbolPowerTerm *= NegativeOne;
                                }
                            }
                        }
                        else
                        {
                            SourceTerm.SymbolPower -= TargetSubTerm.SymbolPower;
                        }

                        // also subtract the fused variables
                        foreach (var fv in TargetSubTerm.FusedSymbols)
                        {
                            if (SourceTerm.FusedSymbols.ContainsKey(fv.Key))
                            {
                                SourceTerm.FusedSymbols[fv.Key] -= fv.Value;
                            }
                            else
                            {
                                SourceTerm.FusedSymbols.Add(fv.Key, fv.Value * -1);
                            }
                        }
                        #endregion
                    }
                    else if (SourceTerm.FusedSymbols.ContainsKey(TargetSubTerm.Symbol))
                    {
                        #region Third Case: Target primary symbol exist in source fused variables

                        if (TargetSubTerm.SymbolPowerTerm != null)
                        {
                            SourceTerm.FusedSymbols[TargetSubTerm.Symbol] -= TargetSubTerm.SymbolPowerTerm;
                        }
                        else
                        {
                            SourceTerm.FusedSymbols[TargetSubTerm.Symbol] -= TargetSubTerm.SymbolPower;
                        }

                        // however primary symbol in source still the same so we need to add it to the value in target (if applicable)

                        // also

                        // there are still some fused variables in source that weren't altered by the target fused symbols
                        // go through every symbol in fused symbols and add it to the source fused symbols
                        foreach (var tfs in TargetSubTerm.FusedSymbols)
                        {
                            if (SourceTerm.FusedSymbols.ContainsKey(tfs.Key))
                            {
                                // symbol exist so accumulate it
                                SourceTerm._FusedSymbols[tfs.Key] -= tfs.Value;
                            }
                            else
                            {
                                // two cases here
                                // 1 the fused key equal the primary symbol in source
                                if (SourceTerm.Symbol.Equals(tfs.Key, StringComparison.OrdinalIgnoreCase))
                                {
                                    if (tfs.Value.SymbolicVariable != null)
                                    {
                                        if (SourceTerm._SymbolPowerTerm != null)
                                        {
                                            SourceTerm._SymbolPowerTerm -= tfs.Value.SymbolicVariable;
                                        }
                                        else
                                        {
                                            // sum the value in the numerical part to the value in symbolic part
                                            SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm._SymbolPower.ToString(CultureInfo.InvariantCulture)) - tfs.Value.SymbolicVariable;
                                            // reset the value in numerical part
                                            SourceTerm._SymbolPower = -1;
                                        }

                                        if (SourceTerm._SymbolPowerTerm.IsCoeffecientOnly)
                                        {
                                            SourceTerm._SymbolPower     = SourceTerm._SymbolPowerTerm.Coeffecient;
                                            SourceTerm._SymbolPowerTerm = null;
                                        }
                                    }
                                    else
                                    {
                                        SourceTerm._SymbolPower -= tfs.Value.NumericalVariable;
                                    }
                                }
                                else
                                {
                                    // 2 no matching at all which needs to add the symbol in target into the fused symbols in source.
                                    SourceTerm.FusedSymbols.Add(tfs.Key, tfs.Value * -1);
                                }
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        #region Fourth Case: Target primary symbol doesn't exist in Source Primary Symbol nor Source Fused symbols

                        // Add Target primary symbol to the fused symbols in source
                        SourceTerm.FusedSymbols.Add(
                            TargetSubTerm.Symbol,
                            new HybridVariable
                        {
                            NumericalVariable = -1 * TargetSubTerm.SymbolPower,
                            SymbolicVariable  = TargetSubTerm.SymbolPowerTerm == null ? null : -1 * (SymbolicVariable)TargetSubTerm.SymbolPowerTerm
                        });

                        // But the primary symbol of source may exist in the target fused variables.

                        foreach (var fsv in TargetSubTerm.FusedSymbols)
                        {
                            if (SourceTerm.FusedSymbols.ContainsKey(fsv.Key))
                            {
                                SourceTerm.FusedSymbols[fsv.Key] -= fsv.Value;
                            }
                            else
                            {
                                // 1- if symbol is the same as priamry source
                                if (SourceTerm.Symbol.Equals(fsv.Key, StringComparison.OrdinalIgnoreCase))
                                {
                                    if (fsv.Value.SymbolicVariable != null)
                                    {
                                        if (SourceTerm._SymbolPowerTerm != null)
                                        {
                                            SourceTerm._SymbolPowerTerm -= fsv.Value.SymbolicVariable;
                                        }
                                        else
                                        {
                                            // sum the value in the numerical part to the value in symbolic part
                                            SourceTerm._SymbolPowerTerm =
                                                new SymbolicVariable(SourceTerm._SymbolPower.ToString(CultureInfo.InvariantCulture)) - fsv.Value.SymbolicVariable;
                                            // reset the value in numerical part
                                            SourceTerm._SymbolPower = -1;
                                        }
                                    }
                                    else
                                    {
                                        if (SourceTerm.SymbolPowerTerm != null)
                                        {
                                            SourceTerm._SymbolPowerTerm -= new SymbolicVariable(fsv.Value.ToString());
                                        }
                                        else
                                        {
                                            SourceTerm._SymbolPower -= fsv.Value.NumericalVariable;
                                        }
                                    }
                                }
                                else
                                {
                                    SourceTerm.FusedSymbols.Add(fsv.Key, fsv.Value * -1);
                                }
                            }
                        }
                        #endregion
                    }
                }

                DivideCoeffecients(ref SourceTerm, TargetSubTerm);
                #endregion
            }

            if (SourceTerm.AddedTerms.Count > 0)
            {
                Dictionary <string, SymbolicVariable> newAddedVariables = new Dictionary <string, SymbolicVariable>(StringComparer.OrdinalIgnoreCase);
                foreach (var vv in SourceTerm.AddedTerms)
                {
                    // get rid of divided term here because I already include it for the source term above
                    var TSubTerm = TargetSubTerm.Numerator;

                    var newv = Divide(vv.Value, TSubTerm);
                    newAddedVariables.Add(newv.WholeValueBaseKey, newv);
                }
                SourceTerm._AddedTerms = newAddedVariables;
            }

            // Extra Terms of a
            if (SourceTerm.ExtraTerms.Count > 0)
            {
                List <ExtraTerm> newExtraTerms = new List <ExtraTerm>();
                foreach (var et in SourceTerm.ExtraTerms)
                {
                    var eterm = et.Term;
                    if (et.Negative)
                    {
                        eterm = Multiply(NegativeOne, eterm);
                    }

                    var newe = Divide(eterm, TargetSubTerm);
                    newExtraTerms.Add(new ExtraTerm {
                        Term = newe
                    });
                }
                SourceTerm._ExtraTerms = newExtraTerms;
            }


            int subIndex           = 0;
            SymbolicVariable total = SourceTerm;

            while (subIndex < b.AddedTerms.Count)
            {
                // we should multiply other parts also
                // then add it to the current instance

                // there are still terms to be consumed
                //   this new term is a sub term in b and will be added to all terms of a.
                TargetSubTerm = b.AddedTerms.ElementAt(subIndex).Value.Clone();

                TargetSubTerm.DividedTerm = b.DividedTerm;   // this line is important because I extracted this added term from a bigger term with the same divided term
                                                             // and when I did this the extracted term lost its divided term

                total    = total + Divide(a, TargetSubTerm);
                subIndex = subIndex + 1;  //increase
            }

            // for extra terms  {terms that has different divided term}
            int extraIndex = 0;
            while (extraIndex < b.ExtraTerms.Count)
            {
                var eTerm = b.ExtraTerms[extraIndex];
                TargetSubTerm = eTerm.Term;
                if (eTerm.Negative)
                {
                    TargetSubTerm = Multiply(NegativeOne, TargetSubTerm);
                }

                var TargetTermSubTotal = Divide(a, TargetSubTerm);
                total = Add(total, TargetTermSubTotal);
                extraIndex++;
            }


            AdjustSpecialFunctions(ref total);

            AdjustZeroPowerTerms(total);
            AdjustZeroCoeffecientTerms(ref total);


            return(total);
        }
 public static SymbolicVariable operator /(SymbolicVariable a, SymbolicVariable b)
 {
     return(SymbolicVariable.Divide(a, b));
 }
 public static SymbolicVariable operator *(SymbolicVariable a, SymbolicVariable b)
 {
     return(SymbolicVariable.Multiply(a, b));
 }
Ejemplo n.º 25
0
        public static SymbolicVariable DiffBFunction(SymbolicVariable fv, string parameter)
        {
            var pa = fv.GetFunctionParameters()[0];

            var ps = SymbolicVariable.Multiply(pa, pa);

            var func = fv.FunctionName;

            var dpa = pa.Differentiate(parameter);


            if (string.Equals(func, "asin", StringComparison.OrdinalIgnoreCase))
            {
                //asin(x) → 1 / sqrt(1-x^2)

                return(SymbolicVariable.Parse(dpa.ToString() + "/sqrt(1-(" + ps.ToString() + "))"));
            }

            if (string.Equals(func, "acos", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse("-" + dpa.ToString() + "/sqrt(1-(" + ps.ToString() + "))"));
            }

            if (string.Equals(func, "atan", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse(dpa.ToString() + "/(" + ps.ToString() + "+1)"));
            }

            if (string.Equals(func, "acot", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse("-" + dpa.ToString() + "/(" + ps.ToString() + "+1)"));
            }

            if (string.Equals(func, "asec", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse(dpa.ToString() + "/(sqrt(1-1/(" + ps.ToString() + "))*" + ps.ToString() + ")"));
            }

            if (string.Equals(func, "acsc", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse("-" + dpa.ToString() + "/(sqrt(1-1/(" + ps.ToString() + "))*" + ps.ToString() + ")"));
            }



            #region hyperbolic functions
            if (string.Equals(func, "asinh", StringComparison.OrdinalIgnoreCase))
            {
                //asin(x) → 1 / sqrt(x^2+1)

                return(SymbolicVariable.Parse(dpa.ToString() + "/sqrt(" + ps.ToString() + "+1)"));
            }

            if (string.Equals(func, "acosh", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse("-" + dpa.ToString() + "/sqrt(" + ps.ToString() + "-1)"));
            }

            if (string.Equals(func, "atanh", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse(dpa.ToString() + "/(1-(" + ps.ToString() + "))"));
            }

            if (string.Equals(func, "acoth", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse("-" + dpa.ToString() + "/(" + ps.ToString() + "-1)"));
            }

            if (string.Equals(func, "asech", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse("-" + dpa.ToString() + "/(sqrt(1/" + ps.ToString() + "-1)*" + ps.ToString() + ")"));
            }

            if (string.Equals(func, "acsch", StringComparison.OrdinalIgnoreCase))
            {
                return(SymbolicVariable.Parse("-" + dpa.ToString() + "/(sqrt(1/" + ps.ToString() + "+1)*" + ps.ToString() + ")"));
            }

            #endregion
            throw new SymbolicException(fv.FunctionName + " differentiation not implemented yet");
        }
        /*
         *
         * Expression like   a*sin(x)+a*cos(x)  can be written as follow a*(sin(x)+cos(x))
         * i want to know the common factor that can be multiplied in these terms
         *
         * so the common factor in my case is a variable key in fused terms or whatever
         *
         * the result should be factor and its existence in indices in the symblic variable added terms
         *
         * in case of previous example          [a..>0,1]
         *
         * and the result should be the common factor as symbolic variable
         * multiplied term
         * terms that cannot be factorized .. to be added later
         *
         */

        /// <summary>
        /// Returns a map of occurence of variable name in the terms of the symbolic variable expression
        /// </summary>
        /// <returns></returns>
        public Dictionary <SymbolicVariable, List <int> > GetCommonFactorsMap()
        {
            // a*sin(x)+a*cos(x) + c
            // loop through all terms
            //   begin with primary term
            //     see if it exists in added terms in primary or fusedsymbols
            // build a dictionary with the existence of this variable
            // repeat this for each fused variable
            // the dictionary will increase in its data
            //  once we are done       check the dictionary lenghs for each variable .. the one with more existence of 2 or more is what we need
            // begin an analysis for the existence indices
            //   a =>  2,5,9
            //   b =>  2,3,4
            // then a*b => 2   and etc.

            List <SymbolicVariable[]> bo2bo2 = new List <SymbolicVariable[]>();

            bo2bo2.Add(this.GetMultipliedTerms());

            if (_AddedTerms != null)
            {
                foreach (var aterm in _AddedTerms)
                {
                    bo2bo2.Add(aterm.Value.GetMultipliedTerms());
                }
            }

            // now i have the matrix of multiplied terms.

            /*
             * a*sin(x)+a*cos(x) + c
             *
             * 0           1          2
             * -------------------------
             * a           a          c
             * sin(x)     cos(x)
             *
             *
             * a in columns 0, 1
             *
             */

            // take each column components and compare to next columns components
            Dictionary <SymbolicVariable, List <int> > CommonFactorsMap = new Dictionary <SymbolicVariable, List <int> >();

            for (int column = 0; column < bo2bo2.Count; column++)
            {
                var components = bo2bo2[column];


                for (int ix = 0; ix < components.Length; ix++)
                {
                    // get the component.
                    SymbolicVariable src_component = components[ix];

                    // once we this component we should write its existence in the list
                    List <int> indices;
                    if (!CommonFactorsMap.TryGetValue(src_component, out indices))
                    {
                        // new creation of the list
                        indices = new List <int>();
                        indices.Add(column);
                        CommonFactorsMap.Add(src_component, indices);
                    }


                    for (int nxc = column + 1; nxc < bo2bo2.Count; nxc++)
                    {
                        var targetColumn = bo2bo2[nxc];

                        // compare it to the next column components

                        for (int nx_i = 0; nx_i < targetColumn.Length; nx_i++)
                        {
                            var trg_nx_compnent = targetColumn[nx_i];
                            if (src_component.Equals(trg_nx_compnent))
                            {
                                // bingo we found a match   .. write this information
                                if (!indices.Contains(nxc))
                                {
                                    indices.Add(nxc);
                                }
                            }
                        }
                    }
                }
            }


            return(CommonFactorsMap);
        }
Ejemplo n.º 27
0
        /// <summary>
        /// get the function derivation  like sin => cos
        /// </summary>
        /// <param name="function"></param>
        /// <param name="negative">indicates if the function returned should have negative value or not</param>
        /// <returns>string of the differentiated function</returns>
        public static string[] DiffFFunction(SymbolicVariable function, out bool negative)
        {
            string func = function.FunctionName;

            if (string.Equals(func, "exp", StringComparison.OrdinalIgnoreCase))
            {
                negative = false;
                return(new string[] { "exp" });
            }


            if (string.Equals(func, "sin", StringComparison.OrdinalIgnoreCase))
            {
                negative = false;
                return(new string[] { "cos" });
            }

            if (string.Equals(func, "sinh", StringComparison.OrdinalIgnoreCase))
            {
                negative = false;
                return(new string[] { "cosh" });
            }

            if (string.Equals(func, "cos", StringComparison.OrdinalIgnoreCase))
            {
                negative = true;
                return(new string[] { "sin" });
            }

            if (string.Equals(func, "cosh", StringComparison.OrdinalIgnoreCase))
            {
                negative = false;
                return(new string[] { "sinh" });
            }

            if (string.Equals(func, "tan", StringComparison.OrdinalIgnoreCase))
            {
                negative = false;
                return(new string[] { "sec", "sec" });
            }

            if (string.Equals(func, "tanh", StringComparison.OrdinalIgnoreCase))
            {
                negative = false;
                return(new string[] { "sech", "sech" });
            }

            if (string.Equals(func, "sec", StringComparison.OrdinalIgnoreCase))
            {
                negative = false;
                return(new string[] { "sec", "tan" });
            }

            if (string.Equals(func, "sech", StringComparison.OrdinalIgnoreCase))
            {
                negative = true;
                return(new string[] { "sech", "tanh" });
            }

            if (string.Equals(func, "csc", StringComparison.OrdinalIgnoreCase))
            {
                negative = true;
                return(new string[] { "csc", "cot" });
            }

            if (string.Equals(func, "csch", StringComparison.OrdinalIgnoreCase))
            {
                negative = true;
                return(new string[] { "csch", "coth" });
            }

            if (string.Equals(func, "cot", StringComparison.OrdinalIgnoreCase))
            {
                negative = true;
                return(new string[] { "csc", "csc" });
            }

            if (string.Equals(func, "coth", StringComparison.OrdinalIgnoreCase))
            {
                negative = true;
                return(new string[] { "csch", "csch" });
            }

            negative = false;
            return(null);
        }
        /// <summary>
        /// Multiply two symbolic variables
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static SymbolicVariable Multiply(SymbolicVariable a, SymbolicVariable b)
        {
            if (a == null || b == null)
            {
                return(null);
            }

            if (a.IsZero)
            {
                return(new SymbolicVariable("0"));
            }
            if (b.IsZero)
            {
                return(new SymbolicVariable("0"));
            }

            if (a.IsOne)
            {
                return(b.Clone());
            }
            if (b.IsOne)
            {
                return(a.Clone());
            }

            SymbolicVariable TargetSubTerm = b.Clone();

            TargetSubTerm._AddedTerms = null;   // remove added variables to prevent its repeated calculations in second passes
            TargetSubTerm._ExtraTerms = null;   // remove the extra terms also
            // or to make sure nothing bad happens {my idiot design :S)

            SymbolicVariable SourceTerm = a.Clone();

            if (a.BaseEquals(TargetSubTerm))
            {
                #region Symbols are Equal (I mean 2*x^3 = 2*X^3)


                MultiplyCoeffecients(ref SourceTerm, TargetSubTerm);


                if (a.SymbolPowerTerm != null || TargetSubTerm.SymbolPowerTerm != null)
                {
                    SourceTerm._SymbolPowerTerm = a.SymbolPowerTerm + TargetSubTerm.SymbolPowerTerm;
                }
                else
                {
                    SourceTerm.SymbolPower = SourceTerm.SymbolPower + TargetSubTerm.SymbolPower;
                }

                //fuse the fused variables in b into sv
                foreach (var bfv in TargetSubTerm.FusedSymbols)
                {
                    if (SourceTerm.FusedSymbols.ContainsKey(bfv.Key))
                    {
                        SourceTerm.FusedSymbols[bfv.Key] += bfv.Value;
                    }
                    else
                    {
                        SourceTerm.FusedSymbols.Add(bfv.Key, bfv.Value);
                    }
                }

                #endregion
            }
            else
            {
                #region Symbols are Different

                if (string.IsNullOrEmpty(SourceTerm.Symbol))
                {
                    #region First Case: Source primary symbol doesn't exist

                    //  so take the primary symbol from the target into source
                    //  and copy the symbol power to it  and symbolic power
                    //

                    // the instance have an empty primary variable so we should add it
                    if (TargetSubTerm._BaseVariable != null)
                    {
                        SourceTerm._BaseVariable = TargetSubTerm._BaseVariable;
                    }
                    else
                    {
                        SourceTerm.Symbol = TargetSubTerm.Symbol;
                    }

                    SourceTerm.SymbolPower = TargetSubTerm.SymbolPower;
                    if (TargetSubTerm.SymbolPowerTerm != null)
                    {
                        SourceTerm._SymbolPowerTerm = TargetSubTerm.SymbolPowerTerm.Clone();
                    }
                    else
                    {
                        SourceTerm._SymbolPowerTerm = null;
                    }



                    //fuse the fused variables in target into source
                    foreach (var fv in TargetSubTerm.FusedSymbols)
                    {
                        if (SourceTerm.FusedSymbols.ContainsKey(fv.Key))
                        {
                            SourceTerm.FusedSymbols[fv.Key] += fv.Value;
                        }
                        else
                        {
                            SourceTerm.FusedSymbols.Add(fv.Key, fv.Value);
                        }
                    }
                    #endregion
                }
                else
                {
                    #region Testing against symbol of targetsubterm
                    if (SourceTerm.Symbol.Equals(TargetSubTerm.Symbol, StringComparison.OrdinalIgnoreCase))
                    {
                        #region Second Case: Primary symbol in both source and target exist and equal

                        // which means the difference is only in fused variables.

                        // test for complex power (power that contains other symbolic variable)
                        if (SourceTerm._SymbolPowerTerm != null || TargetSubTerm._SymbolPowerTerm != null)
                        {
                            // make sure the object of symbol power term have values if they don't
                            if (SourceTerm._SymbolPowerTerm == null)
                            {
                                // transfer the numerical power into symbolic variable mode
                                SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm.SymbolPower.ToString(CultureInfo.InvariantCulture));
                                // also revert the original symbol power into 1  for validation after this
                                SourceTerm.SymbolPower = 1;
                            }
                            if (TargetSubTerm._SymbolPowerTerm == null)
                            {
                                TargetSubTerm._SymbolPowerTerm = new SymbolicVariable(TargetSubTerm.SymbolPower.ToString(CultureInfo.InvariantCulture));
                                TargetSubTerm.SymbolPower      = 1;
                            }

                            // we used symbol power term
                            SourceTerm._SymbolPowerTerm += TargetSubTerm._SymbolPowerTerm;
                        }
                        else
                        {
                            SourceTerm.SymbolPower += TargetSubTerm.SymbolPower;
                        }

                        // then add the fused variables
                        foreach (var fv in TargetSubTerm.FusedSymbols)
                        {
                            if (SourceTerm.FusedSymbols.ContainsKey(fv.Key))
                            {
                                SourceTerm.FusedSymbols[fv.Key] += fv.Value;
                            }
                            else
                            {
                                SourceTerm.FusedSymbols.Add(fv.Key, fv.Value);
                            }
                        }
                        #endregion
                    }
                    else if (SourceTerm.FusedSymbols.ContainsKey(TargetSubTerm.Symbol))
                    {
                        #region Third Case: Target primary symbol exist in source fused variables

                        // fill the source symbol in fused variables from the primary symbol in Target term.
                        if (TargetSubTerm.SymbolPowerTerm != null)
                        {
                            SourceTerm.FusedSymbols[TargetSubTerm.Symbol] +=
                                new HybridVariable
                            {
                                NumericalVariable = TargetSubTerm.SymbolPower,
                                SymbolicVariable  = TargetSubTerm.SymbolPowerTerm
                            }
                        }
                        ;
                        else
                        {
                            SourceTerm.FusedSymbols[TargetSubTerm.Symbol] += TargetSubTerm.SymbolPower;
                        }

                        // however primary symbol in source still the same so we need to add it to the value in target
                        //    (if exist in fused variables in target)

                        // also

                        // there are still some fused variables in source that weren't altered by the target fused symbols
                        // go through every symbol in fused symbols and add it to the source fused symbols
                        foreach (var tfs in TargetSubTerm.FusedSymbols)
                        {
                            if (SourceTerm.FusedSymbols.ContainsKey(tfs.Key))
                            {
                                // symbol exist so accumulate it
                                SourceTerm._FusedSymbols[tfs.Key] += tfs.Value;
                            }
                            else
                            {
                                // two cases here
                                // 1 the fused key equal the primary symbol in source
                                if (SourceTerm.Symbol.Equals(tfs.Key, StringComparison.OrdinalIgnoreCase))
                                {
                                    if (tfs.Value.SymbolicVariable != null)
                                    {
                                        if (SourceTerm._SymbolPowerTerm != null)
                                        {
                                            SourceTerm._SymbolPowerTerm += tfs.Value.SymbolicVariable;
                                        }
                                        else
                                        {
                                            // sum the value in the numerical part to the value in symbolic part
                                            SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm._SymbolPower.ToString(CultureInfo.InvariantCulture)) + tfs.Value.SymbolicVariable;
                                            // reset the value in numerical part
                                            SourceTerm._SymbolPower = 1;
                                        }
                                    }
                                    else
                                    {
                                        SourceTerm._SymbolPower += tfs.Value.NumericalVariable;
                                    }
                                }
                                else
                                {
                                    // 2 no matching at all which needs to add the symbol from target into the fused symbols in source.
                                    SourceTerm.FusedSymbols.Add(tfs.Key, tfs.Value);
                                }
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        #region Fourth Case: Target primary symbol doesn't exist in Source Primary Symbol nor Source Fused symbols
                        // Add Target primary symbol to the fused symbols in source
                        SourceTerm.FusedSymbols.Add(
                            TargetSubTerm.Symbol,
                            new HybridVariable
                        {
                            NumericalVariable = TargetSubTerm.SymbolPower,
                            SymbolicVariable  = TargetSubTerm.SymbolPowerTerm == null ? null : TargetSubTerm.SymbolPowerTerm.Clone()
                        });


                        // But the primary symbol of source may exist in the target fused variables.

                        foreach (var fsv in TargetSubTerm.FusedSymbols)
                        {
                            if (SourceTerm.FusedSymbols.ContainsKey(fsv.Key))
                            {
                                SourceTerm.FusedSymbols[fsv.Key] += fsv.Value;
                            }
                            else
                            {
                                // 1- if symbol is the same as priamry source
                                if (SourceTerm.Symbol.Equals(fsv.Key, StringComparison.OrdinalIgnoreCase))
                                {
                                    if (fsv.Value.SymbolicVariable != null)
                                    {
                                        if (SourceTerm._SymbolPowerTerm != null)
                                        {
                                            SourceTerm._SymbolPowerTerm += fsv.Value.SymbolicVariable;
                                        }
                                        else
                                        {
                                            // sum the value in the numerical part to the value in symbolic part
                                            SourceTerm._SymbolPowerTerm = new SymbolicVariable(SourceTerm._SymbolPower.ToString(CultureInfo.InvariantCulture)) + fsv.Value.SymbolicVariable;
                                            // reset the value in numerical part
                                            SourceTerm._SymbolPower = 1;
                                        }
                                    }
                                    else
                                    {
                                        if (SourceTerm.SymbolPowerTerm != null)
                                        {
                                            SourceTerm._SymbolPowerTerm += new SymbolicVariable(fsv.Value.ToString());
                                        }
                                        else
                                        {
                                            SourceTerm._SymbolPower += fsv.Value.NumericalVariable;
                                        }
                                    }
                                }
                                else
                                {
                                    SourceTerm.FusedSymbols.Add(fsv.Key, fsv.Value);
                                }
                            }
                        }
                        #endregion
                    }

                    #endregion
                }

                MultiplyCoeffecients(ref SourceTerm, TargetSubTerm);

                #endregion
            }

            if (SourceTerm.DividedTerm.IsOne)
            {
                SourceTerm.DividedTerm = TargetSubTerm.DividedTerm;
            }
            else
            {
                SourceTerm.DividedTerm = Multiply(SourceTerm.DividedTerm, TargetSubTerm.DividedTerm);
            }

            //here is a code to continue with other parts of a when multiplying them
            if (SourceTerm.AddedTerms.Count > 0)
            {
                Dictionary <string, SymbolicVariable> newAddedVariables = new Dictionary <string, SymbolicVariable>(StringComparer.OrdinalIgnoreCase);
                foreach (var vv in SourceTerm.AddedTerms)
                {
                    // get rid of divided term here because I already include it for the source term above
                    var TSubTerm = TargetSubTerm.Numerator;

                    var newv = Multiply(vv.Value, TSubTerm);

                    newAddedVariables.Add(newv.WholeValueBaseKey, newv);
                }
                SourceTerm._AddedTerms = newAddedVariables;
            }

            // Extra Terms of a
            if (SourceTerm.ExtraTerms.Count > 0)
            {
                List <ExtraTerm> newExtraTerms = new List <ExtraTerm>();
                foreach (var et in SourceTerm.ExtraTerms)
                {
                    var eterm = et.Term;
                    if (et.Negative)
                    {
                        eterm = Multiply(NegativeOne, eterm);
                    }

                    var newe = Multiply(eterm, TargetSubTerm);
                    newExtraTerms.Add(new ExtraTerm {
                        Term = newe
                    });
                }
                SourceTerm._ExtraTerms = newExtraTerms;
            }

            // now source term which is the first parameter cloned, have the new calculated value.
            int subIndex           = 0;
            SymbolicVariable total = SourceTerm;

            while (subIndex < b.AddedTerms.Count)
            {
                // we should multiply other parts also
                // then add it to the current instance

                // there are still terms to be consumed
                //   this new term is a sub term in b and will be added to all terms of a.
                TargetSubTerm = b.AddedTerms.ElementAt(subIndex).Value.Clone();


                TargetSubTerm.DividedTerm = b.DividedTerm;   // this line is important because I extracted this added term from a bigger term with the same divided term
                                                             // and when I did this the extracted term lost its divided term


                var TargetTermSubTotal = Multiply(a, TargetSubTerm);
                total = Add(total, TargetTermSubTotal);

                subIndex = subIndex + 1;  //increase
            }

            // for extra terms  {terms that has different divided term}
            int extraIndex = 0;
            while (extraIndex < b.ExtraTerms.Count)
            {
                var eTerm = b.ExtraTerms[extraIndex];
                TargetSubTerm = eTerm.Term;
                if (eTerm.Negative)
                {
                    TargetSubTerm = Multiply(NegativeOne, TargetSubTerm);
                }
                var TargetTermSubTotal = Multiply(a, TargetSubTerm);
                total = Add(total, TargetTermSubTotal);
                extraIndex++;
            }


            AdjustSpecialFunctions(ref total);
            AdjustZeroPowerTerms(total);

            AdjustZeroCoeffecientTerms(ref total);


            return(total);
        }
Ejemplo n.º 29
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
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }
 public static SymbolicVariable Pow(SymbolicVariable a, double power)
 {
     return(a.RaiseToSymbolicPower(new SymbolicVariable(power.ToString())));
 }