public static void Analyze(Analysis Mna, Node Anode, Node Cathode, Expression V, Arrow InitialConditions) { Analyze(Mna, Mna.AnonymousName(), Anode, Cathode, V, InitialConditions); }
/// <summary> /// Create a new assignment from an arrow expression. The left side of the arrow must be a variable. /// </summary> /// <param name="Assign"></param> /// <returns></returns> public static Assignment New(Arrow Assign) { return New(Assign.Left, Assign.Right); }
public static void Analyze(Analysis Mna, string Name, Node Anode, Node Cathode, Expression V, Arrow InitialConditions) { Analyze(Mna, Name, Anode, Cathode, V); Mna.AddInitialConditions(InitialConditions); }
// Use homotopy method with newton's method to find a solution for F(x) = 0. private static List <Arrow> NSolve(List <Expression> F, List <Arrow> x0, double Epsilon, int MaxIterations) { int M = F.Count; int N = x0.Count; // Compute JxF, the Jacobian of F. List <Dictionary <Expression, Expression> > JxF = Jacobian(F, x0.Select(i => i.Left)).ToList(); // Define a function to evaluate JxH(x), where H = F(x) - s*F(x0). CodeGen code = new CodeGen(); ParamExpr _JxH = code.Decl <double[, ]>(Scope.Parameter, "JxH"); ParamExpr _x0 = code.Decl <double[]>(Scope.Parameter, "x0"); ParamExpr _s = code.Decl <double>(Scope.Parameter, "s"); // Load x_j from the input array and add them to the map. for (int j = 0; j < N; ++j) { code.DeclInit(x0[j].Left, LinqExpr.ArrayAccess(_x0, LinqExpr.Constant(j))); } LinqExpr error = code.Decl <double>("error"); // Compile the expressions to assign JxH for (int i = 0; i < M; ++i) { LinqExpr _i = LinqExpr.Constant(i); for (int j = 0; j < N; ++j) { code.Add(LinqExpr.Assign( LinqExpr.ArrayAccess(_JxH, _i, LinqExpr.Constant(j)), code.Compile(JxF[i][x0[j].Left]))); } // e = F(x) - s*F(x0) LinqExpr e = code.DeclInit <double>("e", LinqExpr.Subtract(code.Compile(F[i]), LinqExpr.Multiply(LinqExpr.Constant((double)F[i].Evaluate(x0)), _s))); code.Add(LinqExpr.Assign(LinqExpr.ArrayAccess(_JxH, _i, LinqExpr.Constant(N)), e)); // error += e * e code.Add(LinqExpr.AddAssign(error, LinqExpr.Multiply(e, e))); } // return error code.Return(error); Func <double[, ], double[], double, double> JxH = code.Build <Func <double[, ], double[], double, double> >().Compile(); double[] x = new double[N]; // Remember where we last succeeded/failed. double s0 = 0.0; double s1 = 1.0; do { try { // H(F, s) = F - s*F0 NewtonsMethod(M, N, JxH, s0, x, Epsilon, MaxIterations); // Success at this s! s1 = s0; for (int i = 0; i < N; ++i) { x0[i] = Arrow.New(x0[i].Left, x[i]); } // Go near the goal. s0 = Lerp(s0, 0.0, 0.9); } catch (FailedToConvergeException) { // Go near the last success. s0 = Lerp(s0, s1, 0.9); for (int i = 0; i < N; ++i) { x[i] = (double)x0[i].Right; } } } while (s0 > 0.0 && s1 >= s0 + 1e-6); // Make sure the last solution is at F itself. if (s0 != 0.0) { NewtonsMethod(M, N, JxH, 0.0, x, Epsilon, MaxIterations); for (int i = 0; i < N; ++i) { x0[i] = Arrow.New(x0[i].Left, x[i]); } } return(x0); }
public static void Analyze(Analysis Mna, Node Anode, Node Cathode, Expression Current, Arrow InitialConditions) { Analyze(Mna, Anode, Cathode, Current); Mna.AddInitialConditions(InitialConditions); }
public void AddDefinition(Arrow x) { AddDefinition(x.Left, x.Right); }
/// <summary> /// Create a new assignment from an arrow expression. The left side of the arrow must be a variable. /// </summary> /// <param name="Assign"></param> /// <returns></returns> public static Assignment New(Arrow Assign) { return(New(Assign.Left, Assign.Right)); }