public static Ls_ret lsm(double[] x, double[] F, double fval, double alfa, int M, double[] lastfv, double eta, double fcnt, double bl, Type assembly) { int n = x.Length; Ls_ret ls_ret = new Ls_ret(); double maxbl = 100; double gamma = 1e-04; double sigma1 = 0.1; double sigma2 = 0.5; double lam1 = 1; double lam2 = 1; double cbl = 0; double fmax = double.NegativeInfinity; for (int i = 0; i < lastfv.Length; i++) { fmax = Math.Max(fmax, lastfv[i]); } double[] xnew = new double[n]; double[] Fnew = new double[n]; while (cbl < maxbl) { double[] d = new double[n]; for (int i = 0; i < n; i++) { d[i] = -alfa * F[i]; } xnew = new double[n]; for (int i = 0; i < n; i++) { xnew[i] = x[i] + lam1 * d[i]; } Fnew = function(xnew, assembly); fcnt++; if (problem(Fnew)) { ls_ret.xnew = null; ls_ret.Fnew = null; ls_ret.fcnt = fcnt; ls_ret.bl = bl; ls_ret.lsflag = 1; ls_ret.fune = double.NaN; return(ls_ret); } double fune1 = quad(Fnew); if (fune1 <= (fmax + eta - (lam1 * lam1 * gamma * fval))) { if (cbl >= 1) { bl = bl + 1; } ls_ret.xnew = xnew; ls_ret.Fnew = Fnew; ls_ret.fcnt = fcnt; ls_ret.bl = bl; ls_ret.lsflag = 0; ls_ret.fune = fune1; return(ls_ret); // return(list(xnew = xnew, Fnew = Fnew, fcnt = fcnt, //bl = bl, lsflag = 0, fune = fune1)) } for (int i = 0; i < n; i++) { xnew[i] = x[i] - lam2 * d[i]; } Fnew = function(xnew, assembly); fcnt++; if (problem(Fnew)) { ls_ret.xnew = null; ls_ret.Fnew = null; ls_ret.fcnt = fcnt; ls_ret.bl = bl; ls_ret.lsflag = 1; ls_ret.fune = double.NaN; return(ls_ret); } double fune2 = quad(Fnew); if (fune2 <= (fmax + eta - (lam2 * lam2 * gamma * fval))) { if (cbl >= 1) { bl = bl + 1; } ls_ret.xnew = xnew; ls_ret.Fnew = Fnew; ls_ret.fcnt = fcnt; ls_ret.bl = bl; ls_ret.lsflag = 0; ls_ret.fune = fune2; return(ls_ret); // return(list(xnew = xnew, Fnew = Fnew, fcnt = fcnt, //bl = bl, lsflag = 0, fune = fune2)) } double lamc = (2d * fval * lam1 * lam1) / (2d * (fune1 + (2d * lam1 - 1d) * fval)); double c1 = sigma1 * lam1; double c2 = sigma2 * lam1; if (lamc < c1) { lam1 = c1; } else if (lamc > c2) { lam1 = c2; } else { lam1 = lamc; } lamc = (2d * fval * lam2 * lam2) / (2d * (fune2 + (2d * lam2 - 1d) * fval)); c1 = sigma1 * lam2; c2 = sigma2 * lam2; if (lamc < c1) { lam2 = c1; } else if (lamc > c2) { lam2 = c2; } else { lam2 = lamc; } cbl = cbl + 1; } ls_ret.xnew = xnew; ls_ret.Fnew = Fnew; ls_ret.fcnt = fcnt; ls_ret.bl = bl; ls_ret.lsflag = 2; ls_ret.fune = double.NaN; //TTH: set to NaN return(ls_ret); //return(list(xnew = xnew, Fnew = Fnew, fcnt = fcnt, bl = bl, //lsflag = 2, fune = fune)) }
public static void Solve(double[] par, Type assembly) { //double[] x0 = new double[] { 0.3235007, 0.7100014, 0.4234151, 0.4153759, 0.1978808, 0.8531196, 0.4555675, 0.5234385, 0.2557746, 0.5328845 }; //Iteration: 0 ||F(x0)||: 0.08864655 //iteration: 10 ||F(xn)|| = 0.1041679 //iteration: 20 ||F(xn)|| = 0.02157386 //iteration: 30 ||F(xn)|| = 0.003530724 //iteration: 40 ||F(xn)|| = 8.22081e-05 //iteration: 50 ||F(xn)|| = 8.77939e-07 // ctrl <- list(maxit = 1500, M = 10, tol = 1e-07, trace = TRUE, //triter = 10, noimp = 100, NM=FALSE, BFGS=FALSE) string conv = ""; int method = 2; int M = 10; //should be between 5-20, very hard stuff kan use > 20. double maxit = 15000; double tol = 1e-07; bool trace = true; double triter = 10; //when to print iterations double noimp = 100; //when to stop (no improvement) double n = par.Length; double fcnt = 0; int iter = 0; double bl = 0; double alfa = 1; double eta = 1; double eps = 1e-10; double[] lastfv = new double[M]; double[] F = function(par, assembly); fcnt++; double F0 = Math.Sqrt(quad(F)); double normF = F0; G.Writeln("Iteration 0, ||F(x0)||: " + F0 / Math.Sqrt(n)); double[] pbest = par; double normF_best = normF; lastfv[0] = normF * normF; double flag = 0; double knoimp = 0; double alfa1 = 0; double alfa2 = 0; while (normF / Math.Sqrt(n) > tol && iter <= maxit) { if ((Math.Abs(alfa) <= eps) || (Math.Abs(alfa) >= 1 / eps)) { if (normF > 1) { alfa = 1; } else if (normF >= 1e-05 && normF <= 1) { alfa = 1 / normF; } else if (normF < 1e-05) { alfa = 1e+05; } } if (iter == 0) { alfa = Math.Min(1d / normF, 1d); alfa1 = alfa; alfa2 = alfa; } double temp = alfa2; alfa2 = alfa; if (normF <= 0.01) { alfa = alfa1; // retard scheme } alfa1 = temp; Ls_ret ls_ret = lsm(par, F, normF * normF, alfa, M, lastfv, eta, fcnt, bl, assembly); fcnt = ls_ret.fcnt; bl = ls_ret.bl; flag = ls_ret.lsflag; if (flag > 0) { break; } double[] Fnew = ls_ret.Fnew; double[] pnew = ls_ret.xnew; double fune = ls_ret.fune; double pF = 0; double pp = 0; double FF = 0; for (int i = 0; i < n; i++) { pF += ((pnew[i] - par[i]) * (Fnew[i] - F[i])); pp += ((pnew[i] - par[i]) * (pnew[i] - par[i])); FF += ((Fnew[i] - F[i]) * (Fnew[i] - F[i])); } if (method == 1) { alfa = pp / pF; } else if (method == 2) { alfa = pF / FF; } else if (method == 3) { alfa = Math.Sign(pF) * Math.Sqrt(pp / FF); } if (double.IsNaN(alfa)) { alfa = eps; } par = pnew; F = Fnew; double fun = fune; normF = Math.Sqrt(fun); if (normF < normF_best) { pbest = par; normF_best = normF; knoimp = 0; } else { knoimp = knoimp + 1; } iter++; lastfv[(1 + iter % M) - 1] = fun; eta = F0 / ((iter + 1) * (iter + 1)); G.Writeln("Iteration " + iter + " ||F(xn)||: " + normF); if (knoimp == noimp) { flag = 3; break; } if (flag == 0) { if (normF_best / Math.Sqrt(n) <= tol) { conv = "Successful convergence"; } else if (iter > maxit) { conv = "Maximum limit for iterations exceeded"; } else { conv = "Method stagnated"; } } else if (flag == 1) { conv = "Failure: Error in function evaluation"; } else if (flag == 2) { conv = "Failure: Maximum limit on steplength reductions exceeded"; } else if (flag == 3) { conv = "Lack of improvement in objective function"; } } G.Writeln(conv); }