Exemplo n.º 1
0
 /// <summary>
 /// Solve a linear equation or system of linear equations.
 /// </summary>
 /// <param name="Equations">Equation or set of equations to solve.</param>
 /// <param name="For">Variable of set of variables to solve for.</param>
 /// <returns>The solved values of x, including non-independent solutions.</returns>
 public static List<Arrow> Solve(this IEnumerable<Equal> Equations, IEnumerable<Expression> For)
 {
     SystemOfEquations S = new SystemOfEquations(Equations, For);
     S.RowReduce();
     S.BackSubstitute();
     return S.Solve();
 }
Exemplo n.º 2
0
        public void ShouldSolveSystemWith1EquationAnd1Variable()
        {
            // x = 2
            var variableX = new Variable("x");
            var left = new Expression(1, variableX);
            var right = new Expression(2, Variable.NULL);
            var equation = new Equation(left, right);
            var equationList = new List<Equation>();
            equationList.Add(equation);

            var target = new SystemOfEquations(equationList);
            target.Solve();
            var result = variableX.Value;

            Assert.AreEqual(1, result.Count);
            Assert.AreEqual(2, result.First().Coefficient);
            Assert.AreEqual(Variable.NULL, result.First().Variable);
        }
Exemplo n.º 3
0
        public void ShouldSolveUnSortedSystemWith3ComplexEquations()
        {
            //x=1; y=2; z=3;
            //x+2y-z = 2
            //     z = 3
            //x-y    = -1
            var variableX = new Variable("x");
            var variableY = new Variable("y");
            var variableZ = new Variable("z");

            var left1FirstEq = new Expression(1, variableX);
            var left2FirstEq = new Expression(2, variableY);
            var left3FirstEq = new Expression(-1, variableZ);
            var rightFirstEq = new Expression(2, Variable.NULL);

            var left1SecondEq = new Expression(1, variableZ);
            var rightSecondEq = new Expression(3, Variable.NULL);

            var left1ThirdEq = new Expression(1, variableX);
            var left2ThirdEq = new Expression(-1, variableY);
            var rightThirdEq = new Expression(-1, Variable.NULL);

            var firstEquation = new Equation(new List<Expression>() { left1FirstEq, left2FirstEq,left3FirstEq }, rightFirstEq);
            var secondEquation = new Equation(new List<Expression>() { left1SecondEq }, rightSecondEq);
            var thirdEquation = new Equation(new List<Expression>() {left1ThirdEq, left2ThirdEq}, rightThirdEq);

            var target = new SystemOfEquations(new List<Equation>() {firstEquation, secondEquation, thirdEquation});
            target.Solve();
            var resultX = variableX.Value;
            var resultY = variableY.Value;
            var resultZ = variableZ.Value;

            Assert.AreEqual(1, resultX.Count);
            Assert.AreEqual(1, resultY.Count);
            Assert.AreEqual(1, resultZ.Count);
            Assert.AreEqual(Variable.NULL, resultX.First().Variable);
            Assert.AreEqual(1, resultX.First().Coefficient);
            Assert.AreEqual(Variable.NULL, resultY.First().Variable);
            Assert.AreEqual(2, resultY.First().Coefficient);
            Assert.AreEqual(Variable.NULL, resultZ.First().Variable);
            Assert.AreEqual(3, resultZ.First().Coefficient);
        }
Exemplo n.º 4
0
        /// <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));
        }
Exemplo n.º 5
0
 public void TestInitialize()
 {
     library = new SystemOfEquations();
 }
Exemplo n.º 6
0
        /// <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);
        }
Exemplo n.º 7
-1
        public void ShouldSolveSystemWith1EquationAnd2Variables()
        {
            //x+y=10    x=6; y=4
            //x-y=2
            var variableX = new Variable("x");
            var variableY = new Variable("y");

            var left1FirstEq = new Expression(1, variableX);
            var left2FirstEq = new Expression(1, variableY);
            var rightFirstEq = new Expression(10, Variable.NULL);

            var left1SecondEq = new Expression(1, variableX);
            var left2SecondEq = new Expression(-1, variableY);
            var rightSecondEq = new Expression(2, Variable.NULL);

            var firstEquation = new Equation(new List<Expression>() { left1FirstEq, left2FirstEq }, rightFirstEq);
            var secondEquation = new Equation(new List<Expression>() {left1SecondEq, left2SecondEq}, rightSecondEq);

            var target = new SystemOfEquations(new List<Equation>() {firstEquation, secondEquation});
            target.Solve();
            var resultX = variableX.Value;
            var resultY = variableY.Value;

            Assert.AreEqual(1, resultX.Count);
            Assert.AreEqual(1, resultY.Count);
            Assert.AreEqual(Variable.NULL, resultX.First().Variable);
            Assert.AreEqual(6, resultX.First().Coefficient);
            Assert.AreEqual(Variable.NULL, resultY.First().Variable);
            Assert.AreEqual(4, resultY.First().Coefficient);
        }