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());
            }
        }
Exemple #2
0
        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));
            }
        }
        /// <summary>
        /// Solve the circuit for transient simulation.
        /// </summary>
        /// <param name="Analysis">Analysis from the circuit to solve.</param>
        /// <param name="TimeStep">Discretization timestep.</param>
        /// <param name="Log">Where to send output.</param>
        /// <returns>TransientSolution describing the solution of the circuit.</returns>
        public static TransientSolution Solve(Analysis Analysis, Expression TimeStep, IEnumerable <Arrow> InitialConditions, ILog Log)
        {
            Expression h = TimeStep;

            Log.WriteLine(MessageType.Info, "Building solution for h={0}", TimeStep.ToString());

            // Analyze the circuit to get the MNA system and unknowns.
            List <Equal>      mna = Analysis.Equations.ToList();
            List <Expression> y   = Analysis.Unknowns.ToList();

            LogExpressions(Log, MessageType.Verbose, "System of " + mna.Count + " equations and " + y.Count + " unknowns = {{ " + String.Join(", ", y) + " }}", mna);

            // Evaluate for simulation functions.
            // Define T = step size.
            Analysis.Add("T", h);
            // Define d[t] = delta function.
            Analysis.Add(ExprFunction.New("d", Call.If((0 <= t) & (t < h), 1, 0), t));
            // Define u[t] = step function.
            Analysis.Add(ExprFunction.New("u", Call.If(t >= 0, 1, 0), t));
            mna = mna.Resolve(Analysis).OfType <Equal>().ToList();

            // Find out what variables have differential relationships.
            List <Expression> dy_dt = y.Where(i => mna.Any(j => j.DependsOn(D(i, t)))).Select(i => D(i, t)).ToList();

            // Find steady state solution for initial conditions.
            List <Arrow> initial = InitialConditions.ToList();

            Log.WriteLine(MessageType.Info, "Performing steady state analysis...");

            SystemOfEquations dc = new SystemOfEquations(mna
                                                         // Derivatives, t, and T are zero in the steady state.
                                                         .Evaluate(dy_dt.Select(i => Arrow.New(i, 0)).Append(Arrow.New(t, 0), Arrow.New(T, 0)))
                                                         // Use the initial conditions from analysis.
                                                         .Evaluate(Analysis.InitialConditions)
                                                         // Evaluate variables at t=0.
                                                         .OfType <Equal>(), y.Select(j => j.Evaluate(t, 0)));

            // Solve partitions independently.
            foreach (SystemOfEquations i in dc.Partition())
            {
                try
                {
                    List <Arrow> part = i.Equations.Select(j => Equal.New(j, 0)).NSolve(i.Unknowns.Select(j => Arrow.New(j, 0)));
                    initial.AddRange(part);
                    LogExpressions(Log, MessageType.Verbose, "Initial conditions:", part);
                }
                catch (Exception)
                {
                    Log.WriteLine(MessageType.Warning, "Failed to find partition initial conditions, simulation may be unstable.");
                }
            }

            // Transient analysis of the system.
            Log.WriteLine(MessageType.Info, "Performing transient analysis...");

            SystemOfEquations system = new SystemOfEquations(mna, dy_dt.Concat(y));

            // Solve the diff eq for dy/dt and integrate the results.
            system.RowReduce(dy_dt);
            system.BackSubstitute(dy_dt);
            IEnumerable <Equal> integrated = system.Solve(dy_dt)
                                             .NDIntegrate(t, h, IntegrationMethod.Trapezoid)
                                             // NDIntegrate finds y[t + h] in terms of y[t], we need y[t] in terms of y[t - h].
                                             .Evaluate(t, t - h).Cast <Arrow>()
                                             .Select(i => Equal.New(i.Left, i.Right)).Buffer();

            system.AddRange(integrated);
            LogExpressions(Log, MessageType.Verbose, "Integrated solutions:", integrated);

            LogExpressions(Log, MessageType.Verbose, "Discretized system:", system.Select(i => Equal.New(i, 0)));

            // Solving the system...
            List <SolutionSet> solutions = new List <SolutionSet>();

            // Partition the system into independent systems of equations.
            foreach (SystemOfEquations F in system.Partition())
            {
                // Find linear solutions for y. Linear systems should be completely solved here.
                F.RowReduce();
                IEnumerable <Arrow> linear = F.Solve();
                if (linear.Any())
                {
                    linear = Factor(linear);
                    solutions.Add(new LinearSolutions(linear));
                    LogExpressions(Log, MessageType.Verbose, "Linear solutions:", linear);
                }

                // If there are any variables left, there are some non-linear equations requiring numerical techniques to solve.
                if (F.Unknowns.Any())
                {
                    // The variables of this system are the newton iteration updates.
                    List <Expression> dy = F.Unknowns.Select(i => NewtonIteration.Delta(i)).ToList();

                    // Compute JxF*dy + F(y0) == 0.
                    SystemOfEquations nonlinear = new SystemOfEquations(
                        F.Select(i => i.Gradient(F.Unknowns).Select(j => new KeyValuePair <Expression, Expression>(NewtonIteration.Delta(j.Key), j.Value))
                                 .Append(new KeyValuePair <Expression, Expression>(1, i))),
                        dy);

                    // ly is the subset of y that can be found linearly.
                    List <Expression> ly = dy.Where(j => !nonlinear.Any(i => i[j].DependsOn(NewtonIteration.DeltaOf(j)))).ToList();

                    // Find linear solutions for dy.
                    nonlinear.RowReduce(ly);
                    IEnumerable <Arrow> solved = nonlinear.Solve(ly);
                    solved = Factor(solved);

                    // Initial guess for y[t] = y[t - h].
                    IEnumerable <Arrow> guess = F.Unknowns.Select(i => Arrow.New(i, i.Evaluate(t, t - h))).ToList();
                    guess = Factor(guess);

                    // Newton system equations.
                    IEnumerable <LinearCombination> equations = nonlinear.Equations;
                    equations = Factor(equations);

                    solutions.Add(new NewtonIteration(solved, equations, nonlinear.Unknowns, guess));
                    LogExpressions(Log, MessageType.Verbose, String.Format("Non-linear Newton's method updates ({0}):", String.Join(", ", nonlinear.Unknowns)), equations.Select(i => Equal.New(i, 0)));
                    LogExpressions(Log, MessageType.Verbose, "Linear Newton's method updates:", solved);
                }
            }

            Log.WriteLine(MessageType.Info, "System solved, {0} solution sets for {1} unknowns.",
                          solutions.Count,
                          solutions.Sum(i => i.Unknowns.Count()));

            return(new TransientSolution(
                       h,
                       solutions,
                       initial));
        }
Exemple #4
0
 public void AddEquation(Expression a, Expression b)
 {
     AddEquations(Equal.New(a, b));
 }