public static IEnumerable <string> Variables(IExpr expr) { if (expr.IsSymbol()) { yield return(expr.SymbolValue()); } if (expr.IsFunc()) { var func = expr as Function; if (!func.IsBinary) { foreach (var variable in Variables(func.FirstArgument)) { yield return(variable); } } else { foreach (var variable in Variables(func.FirstArgument).Concat(Variables(func.SecondArgument))) { yield return(variable); } } } }
public static IExpr Subtitute(IExpr expr, string variable, IExpr subt) { if (expr.IsSymbol()) { if (expr.SymbolValue() == variable) { return(subt); } else { return(expr); } } else if (expr.IsConstant()) { return(expr); } else { var func = expr as Function; if (!func.IsBinary) { return(new Function(func.Name, Subtitute(func.FirstArgument, variable, subt))); } else { return(new Function(func.Name, Subtitute(func.FirstArgument, variable, subt), Subtitute(func.SecondArgument, variable, subt))); } } }
public static IExpr Differentiate(IExpr expr, string variable) { if (expr.IsConstant()) { return(Constant(0.0)); } else if (expr.IsSymbol()) { if (expr.SymbolValue() == variable) { return(Constant(1.0)); } else { return(Constant(0.0)); } } else { var func = expr as Function; if (func.IsBinary) { switch (func.Name) { case "plus": { var left = Differentiate(func.FirstArgument, variable); var right = Differentiate(func.SecondArgument, variable); return(Plus(left, right)); } case "minus": { var left = Differentiate(func.FirstArgument, variable); var right = Differentiate(func.SecondArgument, variable); return(Plus(left, Times(Constant(-1.0), right))); } case "times": { var f = func.FirstArgument; var fPrime = Differentiate(f, variable); var g = func.SecondArgument; var gPrime = Differentiate(g, variable); return(Plus(Times(f, gPrime), Times(g, fPrime))); } case "pow": { var g = func.FirstArgument; var h = func.SecondArgument; if (h.IsConstant()) { var pow = h.ConstantValue(); return(Times(Times(Constant(pow), Pow(g, Constant(pow - 1.0))), Differentiate(g, variable))); } else if (g.IsConstant() && h.IsSymbol()) { var constant = g.ConstantValue(); return(Times(func, Log(g))); } else { return(func); } } case "div": { var rewritten = Div(func.FirstArgument, func.SecondArgument); return(Differentiate(rewritten, variable)); } default: return(func); } } else { switch (func.Name) { case "sin": return(Times(Cos(func.FirstArgument), Differentiate(func.FirstArgument, variable))); case "cos": return(Times(Times(Constant(-1.0), Sin(func.FirstArgument)), Differentiate(func.FirstArgument, variable))); case "tan": return(Pow(Sec(func.FirstArgument), Constant(2.0))); case "log": return(Div(Differentiate(func.FirstArgument, variable), func.FirstArgument)); default: return(func); } } } }
public static IEnumerable<string> Variables(IExpr expr) { if (expr.IsSymbol()) yield return expr.SymbolValue(); if (expr.IsFunc()) { var func = expr as Function; if (!func.IsBinary) { foreach(var variable in Variables(func.FirstArgument)) yield return variable; } else { foreach (var variable in Variables(func.FirstArgument).Concat(Variables(func.SecondArgument))) yield return variable; } } }
public static IExpr Subtitute(IExpr expr, string variable, IExpr subt) { if (expr.IsSymbol()) { if (expr.SymbolValue() == variable) return subt; else return expr; } else if (expr.IsConstant()) { return expr; } else { var func = expr as Function; if (!func.IsBinary) { return new Function(func.Name, Subtitute(func.FirstArgument, variable, subt)); } else { return new Function(func.Name, Subtitute(func.FirstArgument, variable, subt), Subtitute(func.SecondArgument, variable, subt)); } } }
public static IExpr Differentiate(IExpr expr, string variable) { if (expr.IsConstant()) { return Constant(0.0); } else if (expr.IsSymbol()) { if (expr.SymbolValue() == variable) return Constant(1.0); else return Constant(0.0); } else { var func = expr as Function; if (func.IsBinary) { switch (func.Name) { case "plus": { var left = Differentiate(func.FirstArgument, variable); var right = Differentiate(func.SecondArgument, variable); return Plus(left, right); } case "minus": { var left = Differentiate(func.FirstArgument, variable); var right = Differentiate(func.SecondArgument, variable); return Plus(left, Times(Constant(-1.0), right)); } case "times": { var f = func.FirstArgument; var fPrime = Differentiate(f, variable); var g = func.SecondArgument; var gPrime = Differentiate(g, variable); return Plus(Times(f, gPrime), Times(g, fPrime)); } case "pow": { var g = func.FirstArgument; var h = func.SecondArgument; if (h.IsConstant()) { var pow = h.ConstantValue(); return Times(Times(Constant(pow), Pow(g, Constant(pow - 1.0))), Differentiate(g, variable)); } else if (g.IsConstant() && h.IsSymbol()) { var constant = g.ConstantValue(); return Times(func, Log(g)); } else { return func; } } case "div": { var rewritten = Div(func.FirstArgument, func.SecondArgument); return Differentiate(rewritten, variable); } default: return func; } } else { switch(func.Name) { case "sin": return Times(Cos(func.FirstArgument), Differentiate(func.FirstArgument, variable)); case "cos": return Times(Times(Constant(-1.0), Sin(func.FirstArgument)), Differentiate(func.FirstArgument, variable)); case "tan": return Pow(Sec(func.FirstArgument), Constant(2.0)); case "log": return Div(Differentiate(func.FirstArgument, variable), func.FirstArgument); default: return func; } } } }