/// <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> /// 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); }
/// <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()); }
/// <summary> /// Works on expressions of extra terms to get an expression unified in denominator /// </summary> /// <param name="sv"></param> /// <returns></returns> public static SymbolicVariable UnifyDenominators(SymbolicVariable sv) { var terms = SeparateWithDifferentDenominators(sv); SymbolicVariable OrderedVariable = SymbolicVariable.Zero; foreach (var exTerm in terms) { // multipy the OrderedVariable divided term in the target extra term var exNumerator = SymbolicVariable.Multiply(OrderedVariable.DividedTerm, exTerm.Numerator); var exDenominator = SymbolicVariable.Multiply(OrderedVariable.DividedTerm, exTerm.Denominator); var OrdNumerator = SymbolicVariable.Multiply(exTerm.Denominator, OrderedVariable.Numerator); OrderedVariable = SymbolicVariable.Add(OrdNumerator, exNumerator); OrderedVariable._DividedTerm = exDenominator; } return(OrderedVariable); }
/// <summary> /// 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); }
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"); }
public static SymbolicVariable operator *(SymbolicVariable a, SymbolicVariable b) { return(SymbolicVariable.Multiply(a, b)); }
/// <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); }
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 + "'"); }
private static SymbolicVariable DiffBigTerm(SymbolicVariable sv, string parameter) { // now result contains only one term // ----------------------------------- // we need to differentiate multiplied terms in this ONE TERM // every term is differentiated and multiplied by other terms if x*y*z then == dx*y*z+x*dy+z+x*y*dz int MultipliedTermsCount = sv.FusedSymbols.Count + sv.FusedConstants.Count + 1; // last one is the basic symbol and coeffecient in the instant SymbolicVariable SvDividedTerm = sv.DividedTerm; // here we isolate the divided term for later calculations sv.DividedTerm = One; // separate all terms into array by flatting them List <MultipliedTerm> MultipliedTerms = new List <MultipliedTerm>(MultipliedTermsCount); Action <SymbolicVariable> SpliBaseTerm = (rr) => { var basicterm = rr.Clone(); basicterm._FusedConstants = null; basicterm._FusedSymbols = null; // split coeffecient and its associated symbol if (basicterm.CoeffecientPowerTerm != null) { // coefficient SymbolicVariable CoeffecientOnly = new SymbolicVariable(""); CoeffecientOnly._CoeffecientPowerTerm = basicterm.CoeffecientPowerTerm; CoeffecientOnly.Coeffecient = basicterm.Coeffecient; MultipliedTerms.Add(new MultipliedTerm(CoeffecientOnly)); // multiplied symbol if (!string.IsNullOrEmpty(basicterm.SymbolBaseKey)) { MultipliedTerms.Add(new MultipliedTerm(SymbolicVariable.Parse(basicterm.WholeValueBaseKey))); } } else { MultipliedTerms.Add(new MultipliedTerm(basicterm)); } }; Action <SymbolicVariable> SpliFusedConstants = (rr) => { var basicterm = rr.Clone(); var FCConstants = basicterm._FusedConstants; // Key is the coefficient // value contains the power which always will be symbolic power or null foreach (var FC in FCConstants) { SymbolicVariable CoeffecientOnly = new SymbolicVariable(""); CoeffecientOnly._CoeffecientPowerTerm = FC.Value.SymbolicVariable.Clone(); CoeffecientOnly.Coeffecient = FC.Key; MultipliedTerms.Add(new MultipliedTerm(CoeffecientOnly)); } }; Action <SymbolicVariable> SplitFusedSymbols = (rr) => { var basicterm = rr.Clone(); var FSymbols = basicterm._FusedSymbols; // Key is the coefficient // value contains the power which always will be symbolic power or null foreach (var FS in FSymbols) { var ss = new SymbolicVariable(FS.Key); ss.SymbolPower = FS.Value.NumericalVariable; if (FS.Value.SymbolicVariable != null) { ss._SymbolPowerTerm = FS.Value.SymbolicVariable.Clone(); } MultipliedTerms.Add(new MultipliedTerm(ss)); } }; SpliBaseTerm(sv); if (sv.FusedConstants.Count > 0) { SpliFusedConstants(sv); } if (sv.FusedSymbols.Count > 0) { SplitFusedSymbols(sv); } List <SymbolicVariable> CalculatedDiffs = new List <SymbolicVariable>(MultipliedTermsCount); // get all differentials of all terms // x*y*z ==> dx dy dz for (int ix = 0; ix < MultipliedTerms.Count; ix++) { CalculatedDiffs.Add(DiffTerm(MultipliedTerms[ix].Term, parameter)); } // what about divided term ?? if (!SvDividedTerm.IsOne) { /* * diff(f(x)*g(x)/h(x),x); * -(f(x)*g(x)*('diff(h(x),x,1)))/h(x)^2 <== notice the negative sign here and the squared denominator * +(f(x)*('diff(g(x),x,1)))/h(x) * +(g(x)*('diff(f(x),x,1)))/h(x) */ var dvr = Subtract(Zero, SvDividedTerm.Differentiate(parameter)); //differential of divided takes minus sign because it wil CalculatedDiffs.Add(dvr); // add the divided term but in negative value because it is divided and in differentiation it will have -ve power MultipliedTerms.Add(new MultipliedTerm(SvDividedTerm, true)); } // every result of calculated differentials should be multiplied by the other terms. for (int ix = 0; ix < CalculatedDiffs.Count; ix++) { var term = CalculatedDiffs[ix]; if (term.IsZero) { continue; } var mt = One; int mltc = MultipliedTerms.Count; //if (!SvDividedTerm.IsOne) mltc++; for (int iy = 0; iy < mltc; iy++) { if (iy == ix) { continue; } if (MultipliedTerms[iy].Divided) { mt = SymbolicVariable.Divide(mt, MultipliedTerms[iy].Term); } else { mt = SymbolicVariable.Multiply(mt, MultipliedTerms[iy].Term); } } // term *mt CalculatedDiffs[ix] = SymbolicVariable.Multiply(mt, term); } // dx*y*z dy*x*z dz*x*y var total = Zero; foreach (var cc in CalculatedDiffs) { if (cc.IsZero) { continue; } total = SymbolicVariable.Add(total, cc); } if (!SvDividedTerm.IsOne) { total.DividedTerm = Multiply(SvDividedTerm, SvDividedTerm); } return(total); }
/// <summary> /// Derive one pure term. /// </summary> /// <param name="sv"></param> /// <param name="parameter"></param> private static SymbolicVariable DiffTerm(SymbolicVariable term, string parameter) { var sv = term.Clone(); bool symbolpowercontainParameter = false; if (sv._SymbolPowerTerm != null) { if (sv._SymbolPowerTerm.InvolvedSymbols.Contains(parameter, StringComparer.OrdinalIgnoreCase)) { symbolpowercontainParameter = true; } else { int prcount = sv._SymbolPowerTerm.FusedSymbols.Count(p => p.Key.Equals(parameter, StringComparison.OrdinalIgnoreCase)); symbolpowercontainParameter = prcount > 0; } } bool cc = false; if (sv.BaseVariable != null) { cc = sv.BaseVariable.InvolvedSymbols.Contains(parameter, StringComparer.OrdinalIgnoreCase); // case of base variable } else if (sv.IsFunction && symbolpowercontainParameter == true) { // search if a parameter contains the same parameter foreach (var pf in sv.FunctionParameters) { if (pf.Symbol.Equals(parameter, StringComparison.OrdinalIgnoreCase)) { cc = true; break; } } } else { cc = sv.Symbol.Equals(parameter, StringComparison.OrdinalIgnoreCase); } // x^3*y^2*z^5 , diff to x; if (cc) { if (sv._SymbolPowerTerm == null) { sv.Coeffecient *= sv._SymbolPower; sv._SymbolPower -= 1; if (sv._SymbolPower == 0) { sv._Symbol = ""; } } else { if (symbolpowercontainParameter) { // here is the case when base and power are the same with the parameter we are differentiating with // i.e. x^x|x // Logarithmic Differentiation var lnterm = new SymbolicVariable("log(" + sv.ToString() + ")"); var dlnterm = lnterm.Differentiate(parameter); sv = Multiply(sv, dlnterm); } else { // symbol power term exist SymbolicVariable oldPower = sv._SymbolPowerTerm; sv._SymbolPowerTerm = Subtract(sv._SymbolPowerTerm, One); sv = Multiply(sv, oldPower); } } } else if (symbolpowercontainParameter) { // this case is when the power term is the same var log = new SymbolicVariable(lnText + "(" + sv.Symbol + ")"); var dp = sv._SymbolPowerTerm.Differentiate(parameter); sv = SymbolicVariable.Multiply(log, SymbolicVariable.Multiply(dp, sv)); } else { // try in the fused variables HybridVariable hv; if (sv.FusedSymbols.TryGetValue(parameter, out hv)) { if (hv.SymbolicVariable == null) { sv.Coeffecient *= hv.NumericalVariable; hv.NumericalVariable -= 1; if (hv.NumericalVariable == 0) { sv._FusedSymbols.Remove(parameter); } else { sv._FusedSymbols[parameter] = hv; } } else { // symbol power term exist SymbolicVariable oldPower = hv.SymbolicVariable; hv.SymbolicVariable = Subtract(hv.SymbolicVariable, One); sv._FusedSymbols[parameter] = hv; sv = Multiply(sv, oldPower); } } else { if (sv.IsFunction) { var fv = sv.Clone(); // remove the power term in this copied function term fv._SymbolPowerTerm = null; fv.SymbolPower = 1.0; fv.Coeffecient = 1.0; if (fv.FunctionName.Equals(lnText, StringComparison.OrdinalIgnoreCase)) { if (fv.FunctionParameters.Length != 1) { throw new SymbolicException("Log function must have one parameter for differentiation to be done."); } // d/dx ( ln( g(x) ) ) = g'(x)/g(x) var pa = fv.FunctionParameters[0]; var dpa = pa.Differentiate(parameter); fv = SymbolicVariable.Divide(dpa, pa); } else if (fv.FunctionName.Equals("sqrt", StringComparison.OrdinalIgnoreCase)) { // d/dx ( sqrt( g(x) ) ) = g'(x) / 2* sqrt(g(x)) if (fv.FunctionParameters.Length != 1) { throw new SymbolicException("Sqrt function must have one parameter for differentiation to be done."); } var pa = fv.FunctionParameters[0]; var dpa = pa.Differentiate(parameter); var den = Multiply(Two, fv); fv = Divide(dpa, den); } else if (FunctionDiff.BFunctions.Contains(fv.FunctionName, StringComparer.OrdinalIgnoreCase)) { fv = FunctionDiff.DiffBFunction(fv, parameter); } else { // triogonometric functions bool IsNegativeResult; string[] newfuntions = FunctionDiff.DiffFFunction(fv, out IsNegativeResult); if (newfuntions != null) { //if(IsNegative) // get the parameters in the function and differentiate them if (fv.FunctionParameters.Length == 0) { throw new SymbolicException("Special function without any parameters is not suitable for differentiation"); } else if (fv.FunctionParameters.Length == 1) { var pa = fv.FunctionParameters[0]; var presult = pa.Differentiate(parameter); fv.SetFunctionName(newfuntions); if (IsNegativeResult) { fv = SymbolicVariable.Multiply(presult, SymbolicAlgebra.SymbolicVariable.NegativeOne * fv); } else { fv = SymbolicVariable.Multiply(presult, fv); } } else { throw new SymbolicException("more than one parameter is not normal for this special function"); } } else { // the function is not a special function like sin, cos, and log. // search for the function in the running context. var extendedFunction = Functions.Keys.FirstOrDefault(c => c.StartsWith(fv.FunctionName, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrEmpty(extendedFunction)) { string[] fps = extendedFunction.Substring(extendedFunction.IndexOf("(")).TrimStart('(').TrimEnd(')').Split(','); if (fps.Length != fv.RawFunctionParameters.Length) { throw new SymbolicException("Insufficient function parameters"); } // replace parameters var dsf = Functions[extendedFunction].ToString(); for (int ipxf = 0; ipxf < fps.Length; ipxf++) { dsf = dsf.Replace(fps[ipxf], fv.RawFunctionParameters[ipxf]); } fv = SymbolicVariable.Parse(dsf).Differentiate(parameter); } else { throw new SymbolicException("This function is not a special function, and I haven't implemented storing user functions in the running context"); } } } // second treat the function normally as if it is one big symbol if (sv._SymbolPowerTerm == null) { sv.Coeffecient *= sv._SymbolPower; sv._SymbolPower -= 1; if (sv._SymbolPower == 0) { sv._Symbol = ""; } } else { // symbol power term exist SymbolicVariable oldPower = sv._SymbolPowerTerm; sv._SymbolPowerTerm = Subtract(sv._SymbolPowerTerm, One); sv = Multiply(sv, oldPower); } sv = SymbolicVariable.Multiply(fv, sv); } else if (sv.IsCoeffecientOnly && sv._CoeffecientPowerTerm != null) { // hint: the coeffecient only term has power of 1 or symbolic power should exist in case of raise to symbolic power // get log(coeffeniect) var log = new SymbolicVariable(lnText + "(" + sv.Coeffecient.ToString(CultureInfo.InvariantCulture) + ")"); var dp = sv._CoeffecientPowerTerm.Differentiate(parameter); sv = SymbolicVariable.Multiply(log, SymbolicVariable.Multiply(dp, sv)); } else { // the whole term will be converted to zero. // empty everything :) sv._SymbolPowerTerm = null; sv._CoeffecientPowerTerm = null; sv._SymbolPower = 1; sv.Coeffecient = 0; //sv._DividedTerm = null; sv._BaseVariable = null; sv._Symbol = string.Empty; if (sv._SymbolPowerTerm != null) { sv._FusedSymbols.Clear(); sv._FusedSymbols = null; } } } } return(sv); }