void printbeta(char *input, int length) { int i; for(i=0; i < length; i++) { //printf("%c", findbeta(input[i]) ); printf("%c", findbeta(toupper(input[i])) ); } //printf("\ni=%d\n", i); }
void printbeta(char *input, char *output, int length) { int i; for(i=0; i < length; i++) { output[i]=findbeta(toupper(input[i])); printf("%c", output[i]); } output[i]='\0'; //printf("\ni=%d\n", i); }
/// Solve the trust-region subproblem using /// the method of More and Sorensen /// /// Using the implementation as in Algorithm 7.3.6 /// of Trust Region Methods /// /// main output d, the soln to the TR subproblem /// @param J :: The Jacobian. /// @param f :: The residuals. /// @param hf :: The Hessian (sort of). /// @param Delta :: The raduis of the trust region. /// @param d :: The output vector of corrections to the parameters giving the /// solution to the TR subproblem. /// @param nd :: The 2-norm of d. /// @param options :: The options. /// @param inform :: The inform struct. /// @param w :: The work struct. void more_sorensen(const DoubleFortranMatrix &J, const DoubleFortranVector &f, const DoubleFortranMatrix &hf, double Delta, DoubleFortranVector &d, double &nd, const nlls_options &options, nlls_inform &inform, more_sorensen_work &w) { // The code finds // d = arg min_p v^T p + 0.5 * p^T A p // s.t. ||p|| \leq Delta // // set A and v for the model being considered here... // Set A = J^T J matmult_inner(J, w.A); // add any second order information... // so A = J^T J + HF w.A += hf; // now form v = J^T f mult_Jt(J, f, w.v); // if scaling needed, do it if (options.scale != 0) { apply_scaling(J, w.A, w.v, w.apply_scaling_ws, options, inform); } auto n = J.len2(); auto scale_back = [n, &d, &options, &w]() { if (options.scale != 0) { for (int i = 1; i <= n; ++i) { d(i) = d(i) / w.apply_scaling_ws.diag(i); } } }; auto local_ms_shift = options.more_sorensen_shift; // d = -A\v DoubleFortranVector negv = w.v; negv *= -1.0; solve_spd(w.A, negv, w.LtL, d, inform); double sigma = 0.0; if (inform.status == NLLS_ERROR::OK) { // A is symmetric positive definite.... sigma = zero; } else { // reset the error calls -- handled in the code.... inform.status = NLLS_ERROR::OK; inform.external_return = 0; inform.external_name = ""; min_eig_symm(w.A, sigma, w.y1); if (inform.status != NLLS_ERROR::OK) { scale_back(); return; } sigma = -(sigma - local_ms_shift); // find a shift that makes (A + sigma I) positive definite get_pd_shift(sigma, d, options, inform, w); if (inform.status != NLLS_ERROR::OK) { scale_back(); return; } } nd = norm2(d); if (boost::math::isnan(nd) || boost::math::isinf(nd)) { inform.status = NLLS_ERROR::NAN_OR_INF; throw std::runtime_error("Step is NaN or infinite."); } // now, we're not in the trust region initally, so iterate.... auto sigma_shift = zero; int no_restarts = 0; // set 'small' in the context of the algorithm double epsilon = std::max(options.more_sorensen_tol * Delta, options.more_sorensen_tiny); int it = 1; for (; it <= options.more_sorensen_maxits; ++it) { if (nd <= Delta + epsilon) { // we're within the tr radius if (fabs(sigma) < options.more_sorensen_tiny || fabs(nd - Delta) < epsilon) { // we're good....exit break; } if (w.y1.len() == n) { double alpha = 0.0; findbeta(d, w.y1, Delta, alpha, inform); if (inform.status == NLLS_ERROR::OK) { DoubleFortranVector tmp = w.y1; tmp *= alpha; d += tmp; } } // also good....exit break; } // w.q = R'\d // DTRSM( "Left", "Lower", "No Transpose", "Non-unit", n, 1, one, w.LtL, n, // w.q, n ); for (int j = 1; j <= w.LtL.len1(); ++j) { for (int k = j + 1; k <= w.LtL.len1(); ++k) { w.LtL(j, k) = 0.0; } } w.LtL.solve(d, w.q); auto nq = norm2(w.q); sigma_shift = (pow((nd / nq), 2)) * ((nd - Delta) / Delta); if (fabs(sigma_shift) < options.more_sorensen_tiny * fabs(sigma)) { if (no_restarts < 1) { // find a shift that makes (A + sigma I) positive definite get_pd_shift(sigma, d, options, inform, w); if (inform.status != NLLS_ERROR::OK) { break; } no_restarts = no_restarts + 1; } else { // we're not going to make progress...jump out inform.status = NLLS_ERROR::MS_NO_PROGRESS; break; } } else { sigma = sigma + sigma_shift; } shift_matrix(w.A, sigma, w.AplusSigma); DoubleFortranVector negv = w.v; negv *= -1.0; solve_spd(w.AplusSigma, negv, w.LtL, d, inform); if (inform.status != NLLS_ERROR::OK) { break; } nd = norm2(d); } if (it == options.more_sorensen_maxits) { // maxits reached, not converged inform.status = NLLS_ERROR::MS_MAXITS; } scale_back(); }