public static void TestSymbolism() { // Create some constants. ComputerAlgebra.Expression A = 2; ComputerAlgebra.Constant B = ComputerAlgebra.Constant.New(3); // Create some variables. ComputerAlgebra.Expression x = "x"; Variable y = Variable.New("y"); // Create basic expression with operator overloads. ComputerAlgebra.Expression f = A * x + B * y + 4; // This expression uses the implicit conversion from string to // Expression, which parses the string. ComputerAlgebra.Expression g = "5*x + C*y + 8"; // Create a system of equations from the above expressions. var system = new List <Equal>() { Equal.New(f, 0), Equal.New(g, 0), }; // We can now solve the system of equations for x and y. Since the // equations have a variable 'C', the solutions will not be // constants. List <Arrow> solutions = system.Solve(x, y); Debug.WriteLine("The solutions are:"); foreach (Arrow i in solutions) { Debug.WriteLine(i.ToString()); } }
// Expand N(x)/D(x) using partial fractions. private static Expression ExpandPartialFractions(Expression N, Expression D, Expression x) { List <Expression> terms = new List <Expression>(); List <Variable> unknowns = new List <Variable>(); List <Expression> basis = new List <Expression>(); foreach (Expression i in Product.TermsOf(D)) { // Get the multiplicity of this basis term. Expression e = i; int n = Power.IntegralExponentOf(e); if (n != 1) { e = ((Power)i).Left; } // Convert to a polynomial. Polynomial Pi = Polynomial.New(e, x); // Add new terms for each multiplicity n. for (int j = 1; j <= n; ++j) { // Expression for the unknown numerator of this term. Expression unknown = 0; for (int k = 0; k < Pi.Degree; ++k) { Variable Ai = Variable.New("_A" + unknowns.Count.ToString()); unknown += Ai * (x ^ k); unknowns.Add(Ai); } terms.Add(Product.New(unknown, Power.New(e, -j))); } basis.Add(i); } // Equate the original expression with the decomposed expressions. D = Sum.New(terms.Select(j => (Expression)(D * j))).Expand(); Polynomial l = Polynomial.New(N, x); Polynomial r = Polynomial.New(D, x); // Equate terms of equal degree and solve for the unknowns. int degree = Math.Max(l.Degree, r.Degree); List <Equal> eqs = new List <Equal>(degree + 1); for (int i = 0; i <= degree; ++i) { eqs.Add(Equal.New(l[i], r[i])); } List <Arrow> A = eqs.Solve(unknowns); // Substitute the now knowns. return(Sum.New(terms.Select(i => i.Evaluate(A)))); }
/// <summary> /// Solve a linear system of differential equations with initial conditions using the laplace transform. /// </summary> /// <param name="f"></param> /// <param name="y"></param> /// <param name="y0"></param> /// <param name="t"></param> /// <returns></returns> public static List <Arrow> DSolve(this IEnumerable <Equal> f, IEnumerable <Expression> y, IEnumerable <Arrow> y0, Expression t) { // Find F(s) = L[f(t)] and substitute the initial conditions. List <Equal> F = f.Select(i => Equal.New( L(i.Left, t).Evaluate(y0), L(i.Right, t).Evaluate(y0))).ToList(); // Solve F for Y(s) = L[y(t)]. List <Arrow> Y = F.Solve(y.Select(i => L(i, t))); // Take L^-1[Y]. Y = Y.Select(i => Arrow.New(IL(i.Left, t), IL(i.Right, t))).ToList(); if (Y.DependsOn(s)) { throw new Exception("Could not find L^-1[Y(s)]."); } return(Y); }
static void Main(string[] args) { // Create some constants. Expression A = 2; Constant B = Constant.New(3); // Create some variables. Expression x = "x"; Variable y = Variable.New("y"); // Create a basic expressions. Expression f = A * x + B * y + 4; // This expression uses the implicit conversion from string to // Expression, which parses the string. Expression g = "5*x + C*y + 8"; // Create a system of equations from the above expressions. var system = new List <Equal>() { Equal.New(f, 0), Equal.New(g, 0), }; // We can now solve the system of equations for x and y. Since the // equations have a variable 'C', the solutions will not be // constants. List <Arrow> solutions = system.Solve(x, y); Console.WriteLine("The solutions are:"); foreach (Arrow i in solutions) { Console.WriteLine(i.ToString()); } // A fundamental building block of ComputerAlgebra is the 'Arrow' // expression. Arrow expressions define the value of one expression // to be the value given by another expression. For example, 'x->2' // defines the expression 'x' to have the value '2'. // The 'Solve' function used above returns a list of Arrow // expressions defining the solutions of the system. // Arrow expressions are used by the 'Evaluate' function to // substitute values for expressions into other expressions. To // demonstrate the usage of Evaluate, let's validate the solution // by using Evaluate to substitute the solutions into the original // system of equations, and then substitute a value for C. Expression f_xy = f.Evaluate(solutions).Evaluate(Arrow.New("C", 2)); Expression g_xy = g.Evaluate(solutions).Evaluate(Arrow.New("C", 2)); if ((f_xy == 0) && (g_xy == 0)) { Console.WriteLine("Success!"); } else { Console.WriteLine("Failure! f = {0}, g = {1}", f_xy, g_xy); } // Suppose we need to evaluate the solutions efficiently many times. // We can compile the solutions to delegates where 'C' is a // parameter to the delegate, allowing it to be specified later. var x_C = x.Evaluate(solutions).Compile <Func <double, double> >("C"); var y_C = y.Evaluate(solutions).Compile <Func <double, double> >("C"); for (int i = 0; i < 20; ++i) { double C = i / 2.0; Console.WriteLine("C = {0}: (x, y) = ({1}, {2})", C, x_C(C), y_C(C)); } }
static void Main(string[] args) { // Create some constants. Expression A = 2; Constant B = Constant.New(3); // Create some variables. Expression x = "x"; Variable y = Variable.New("y"); // Create a basic expressions. Expression f = A*x + B*y + 4; // This expression uses the implicit conversion from string to // Expression, which parses the string. Expression g = "5*x + C*y + 8"; // Create a system of equations from the above expressions. var system = new List<Equal>() { Equal.New(f, 0), Equal.New(g, 0), }; // We can now solve the system of equations for x and y. Since the // equations have a variable 'C', the solutions will not be // constants. List<Arrow> solutions = system.Solve(x, y); Console.WriteLine("The solutions are:"); foreach (Arrow i in solutions) Console.WriteLine(i.ToString()); // A fundamental building block of ComputerAlgebra is the 'Arrow' // expression. Arrow expressions define the value of one expression // to be the value given by another expression. For example, 'x->2' // defines the expression 'x' to have the value '2'. // The 'Solve' function used above returns a list of Arrow // expressions defining the solutions of the system. // Arrow expressions are used by the 'Evaluate' function to // substitute values for expressions into other expressions. To // demonstrate the usage of Evaluate, let's validate the solution // by using Evaluate to substitute the solutions into the original // system of equations, and then substitute a value for C. Expression f_xy = f.Evaluate(solutions).Evaluate(Arrow.New("C", 2)); Expression g_xy = g.Evaluate(solutions).Evaluate(Arrow.New("C", 2)); if ((f_xy == 0) && (g_xy == 0)) Console.WriteLine("Success!"); else Console.WriteLine("Failure! f = {0}, g = {1}", f_xy, g_xy); // Suppose we need to evaluate the solutions efficiently many times. // We can compile the solutions to delegates where 'C' is a // parameter to the delegate, allowing it to be specified later. var x_C = x.Evaluate(solutions).Compile<Func<double, double>>("C"); var y_C = y.Evaluate(solutions).Compile<Func<double, double>>("C"); for (int i = 0; i < 20; ++i) { double C = i / 2.0; Console.WriteLine("C = {0}: (x, y) = ({1}, {2})", C, x_C(C), y_C(C)); } }
// Expand N(x)/D(x) using partial fractions. private static Expression ExpandPartialFractions(Expression N, Expression D, Expression x) { List<Expression> terms = new List<Expression>(); List<Variable> unknowns = new List<Variable>(); List<Expression> basis = new List<Expression>(); foreach (Expression i in Product.TermsOf(D)) { // Get the multiplicity of this basis term. Expression e = i; int n = Power.IntegralExponentOf(e); if (n != 1) e = ((Power)i).Left; // Convert to a polynomial. Polynomial Pi = Polynomial.New(e, x); // Add new terms for each multiplicity n. for (int j = 1; j <= n; ++j) { // Expression for the unknown numerator of this term. Expression unknown = 0; for (int k = 0; k < Pi.Degree; ++k) { Variable Ai = Variable.New("_A" + unknowns.Count.ToString()); unknown += Ai * (x ^ k); unknowns.Add(Ai); } terms.Add(Product.New(unknown, Power.New(e, -j))); } basis.Add(i); } // Equate the original expression with the decomposed expressions. D = Sum.New(terms.Select(j => (Expression)(D * j))).Expand(); Polynomial l = Polynomial.New(N, x); Polynomial r = Polynomial.New(D, x); // Equate terms of equal degree and solve for the unknowns. int degree = Math.Max(l.Degree, r.Degree); List<Equal> eqs = new List<Equal>(degree + 1); for (int i = 0; i <= degree; ++i) eqs.Add(Equal.New(l[i], r[i])); List<Arrow> A = eqs.Solve(unknowns); // Substitute the now knowns. return Sum.New(terms.Select(i => i.Evaluate(A))); }