コード例 #1
0
        /// <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);
        }
コード例 #2
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);
        }
コード例 #3
0
        /// <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);
        }