/* Normalize a given vector in 3D. */ void normalize(GLdouble *v){ GLdouble norm = calculate_norm(v[0], v[1], v[2]); v[0] = v[0] / norm; v[1] = v[1] / norm; v[2] = v[2] / norm; }
std::set<int>& DiscontinuityDetector::get_discontinuous_element_ids(double threshold) { Element* e; for_all_active_elements(e, mesh) { for(int edge_i = 0; edge_i < e->get_num_surf(); edge_i++) if(calculate_relative_flow_direction(e, edge_i) < -1e-3 && !e->en[edge_i]->bnd) { double jump = calculate_jumps(e, edge_i); double diameter_indicator = std::pow(e->get_diameter(), (H2D_GET_H_ORDER(spaces[0]->get_element_order(e->id)) + 1) / 2); double edge_length = std::sqrt(std::pow(e->vn[(edge_i + 1) % 4]->x - e->vn[edge_i]->x, 2) + std::pow(e->vn[(edge_i + 1) % 4]->y - e->vn[edge_i]->y, 2)); double norm = calculate_norm(e, edge_i); double discontinuity_detector = jump / (diameter_indicator * edge_length * norm); if(discontinuity_detector > threshold) discontinuous_element_ids.insert(e->id); } } return discontinuous_element_ids; };
void TwostepTimeSolver::solve() { libmesh_assert(core_time_solver.get()); // The core_time_solver will handle any first_solve actions first_solve = false; // We may have to repeat timesteps entirely if our error is bad // enough bool max_tolerance_met = false; // Calculating error values each time Real single_norm(0.), double_norm(0.), error_norm(0.), relative_error(0.); while (!max_tolerance_met) { // If we've been asked to reduce deltat if necessary, make sure // the core timesolver does so core_time_solver->reduce_deltat_on_diffsolver_failure = this->reduce_deltat_on_diffsolver_failure; if (!quiet) { libMesh::out << "\n === Computing adaptive timestep === " << std::endl; } // Use the double-length timestep first (so the // old_nonlinear_solution won't have to change) core_time_solver->solve(); // Save a copy of the double-length nonlinear solution // and the old nonlinear solution std::unique_ptr<NumericVector<Number>> double_solution = _system.solution->clone(); std::unique_ptr<NumericVector<Number>> old_solution = _system.get_vector("_old_nonlinear_solution").clone(); double_norm = calculate_norm(_system, *double_solution); if (!quiet) { libMesh::out << "Double norm = " << double_norm << std::endl; } // Then reset the initial guess for our single-length calcs *(_system.solution) = _system.get_vector("_old_nonlinear_solution"); // Call two single-length timesteps // Be sure that the core_time_solver does not change the // timestep here. (This is unlikely because it just succeeded // with a timestep twice as large!) // FIXME: even if diffsolver failure is unlikely, we ought to // do *something* if it happens core_time_solver->reduce_deltat_on_diffsolver_failure = 0; Real old_time = _system.time; Real old_deltat = _system.deltat; _system.deltat *= 0.5; core_time_solver->solve(); core_time_solver->advance_timestep(); core_time_solver->solve(); single_norm = calculate_norm(_system, *_system.solution); if (!quiet) { libMesh::out << "Single norm = " << single_norm << std::endl; } // Reset the core_time_solver's reduce_deltat... value. core_time_solver->reduce_deltat_on_diffsolver_failure = this->reduce_deltat_on_diffsolver_failure; // But then back off just in case our advance_timestep() isn't // called. // FIXME: this probably doesn't work with multistep methods _system.get_vector("_old_nonlinear_solution") = *old_solution; _system.time = old_time; _system.deltat = old_deltat; // Find the relative error *double_solution -= *(_system.solution); error_norm = calculate_norm(_system, *double_solution); relative_error = error_norm / _system.deltat / std::max(double_norm, single_norm); // If the relative error makes no sense, we're done if (!double_norm && !single_norm) return; if (!quiet) { libMesh::out << "Error norm = " << error_norm << std::endl; libMesh::out << "Local relative error = " << (error_norm / std::max(double_norm, single_norm)) << std::endl; libMesh::out << "Global relative error = " << (error_norm / _system.deltat / std::max(double_norm, single_norm)) << std::endl; libMesh::out << "old delta t = " << _system.deltat << std::endl; } // If our upper tolerance is negative, that means we want to set // it based on the first successful time step if (this->upper_tolerance < 0) this->upper_tolerance = -this->upper_tolerance * relative_error; // If we haven't met our upper error tolerance, we'll have to // repeat this timestep entirely if (this->upper_tolerance && relative_error > this->upper_tolerance) { // Reset the initial guess for our next try *(_system.solution) = _system.get_vector("_old_nonlinear_solution"); // Chop delta t in half _system.deltat /= 2.; if (!quiet) { libMesh::out << "Failed to meet upper error tolerance" << std::endl; libMesh::out << "Retrying with delta t = " << _system.deltat << std::endl; } } else max_tolerance_met = true; } // Otherwise, compare the relative error to the tolerance // and adjust deltat last_deltat = _system.deltat; // If our target tolerance is negative, that means we want to set // it based on the first successful time step if (this->target_tolerance < 0) this->target_tolerance = -this->target_tolerance * relative_error; const Real global_shrink_or_growth_factor = std::pow(this->target_tolerance / relative_error, static_cast<Real>(1. / core_time_solver->error_order())); const Real local_shrink_or_growth_factor = std::pow(this->target_tolerance / (error_norm/std::max(double_norm, single_norm)), static_cast<Real>(1. / (core_time_solver->error_order()+1.))); if (!quiet) { libMesh::out << "The global growth/shrink factor is: " << global_shrink_or_growth_factor << std::endl; libMesh::out << "The local growth/shrink factor is: " << local_shrink_or_growth_factor << std::endl; } // The local s.o.g. factor is based on the expected **local** // truncation error for the timestepping method, the global // s.o.g. factor is based on the method's **global** truncation // error. You can shrink/grow the timestep to attempt to satisfy // either a global or local time-discretization error tolerance. Real shrink_or_growth_factor = this->global_tolerance ? global_shrink_or_growth_factor : local_shrink_or_growth_factor; if (this->max_growth && this->max_growth < shrink_or_growth_factor) { if (!quiet && this->global_tolerance) { libMesh::out << "delta t is constrained by max_growth" << std::endl; } shrink_or_growth_factor = this->max_growth; } _system.deltat *= shrink_or_growth_factor; // Restrict deltat to max-allowable value if necessary if ((this->max_deltat != 0.0) && (_system.deltat > this->max_deltat)) { if (!quiet) { libMesh::out << "delta t is constrained by maximum-allowable delta t." << std::endl; } _system.deltat = this->max_deltat; } // Restrict deltat to min-allowable value if necessary if ((this->min_deltat != 0.0) && (_system.deltat < this->min_deltat)) { if (!quiet) { libMesh::out << "delta t is constrained by minimum-allowable delta t." << std::endl; } _system.deltat = this->min_deltat; } if (!quiet) { libMesh::out << "new delta t = " << _system.deltat << std::endl; } }
int main(int argc, char *argv[]) { struct RNAfold_args_info args_info; char *string, *input_string, *structure=NULL, *cstruc=NULL; char fname[80], ffname[80], gfname[80], *ParamFile=NULL; char *ns_bases=NULL, *c; int i, j, ii, jj, mu, length, l, sym, r, pf=0, noconv=0; unsigned int input_type; double energy, min_en, kT, sfact=1.07; int doMEA=0, circular = 0, N; char *pf_struc; double dist; plist *pl; FILE * filehandle; FILE * statsfile; char* line; double tau = 0.01; /* Variance of energy parameters */ double sigma = 0.01; /* Variance of experimental constraints */ double *gradient; /* Gradient for steepest descent search epsilon[i+1]= epsilon[i] - gradient * step_size */ double initial_step_size = 0.5; /* Initial step size for steepest descent search */ double step_size; double D; /* Discrepancy (i.e. value of objective function) for the current prediction */ int iteration, max_iteration = 2000; /* Current and maximum number of iterations after which algorithm stops */ double precision = 0.1; /* cutoff used for stop conditions */ double tolerance = 0.1; /* Parameter used by various GSL minimizers */ int method_id = 1; /* Method to use for minimization, 0 and 1 are custom steepest descent, the rest are GSL implementations (see below)*/ int initial_guess_method = 0; int sample_N = 1000; double *prev_epsilon; double *prev_gradient; double DD, prev_D, sum, norm; int status; double* gradient_numeric; double* gradient_numeric_gsl; /* Minimizer vars */ const gsl_multimin_fdfminimizer_type *T; gsl_multimin_fdfminimizer *minimizer; gsl_vector *minimizer_x; gsl_vector *minimizer_g; gsl_multimin_function_fdf minimizer_func; minimizer_pars_struct minimizer_pars; char *constraints; char outfile[256]; char constraints_file[256]; char epsilon_file[256]; FILE* fh; double last_non_nan_lnQ; pf_overflow = 0; pf_underflow = 0; dangles=2; do_backtrack = 1; string = NULL; noPS = 0; outfile[0]='\0'; epsilon_file[0]='\0'; strcpy(psDir, "dotplots"); if(RNAfold_cmdline_parser (argc, argv, &args_info) != 0) exit(1); /* RNAbpfold specific options */ if (args_info.tau_given) tau = args_info.tau_arg; if (args_info.sigma_given) sigma = args_info.sigma_arg; if (args_info.precision_given) precision = args_info.precision_arg; if (args_info.step_given) initial_step_size = args_info.step_arg; if (args_info.maxN_given) max_iteration = args_info.maxN_arg; if (args_info.minimization_given) method_id = args_info.minimization_arg; if (args_info.init_given) initial_guess_method = args_info.init_arg; if (args_info.tolerance_given) tolerance = args_info.tolerance_arg; if (args_info.outfile_given) strcpy(outfile, args_info.outfile_arg); if (args_info.constraints_given) strcpy(constraints_file, args_info.constraints_arg); if (args_info.epsilon_given) strcpy(epsilon_file, args_info.epsilon_arg); if (args_info.sampleGradient_given) sample_conditionals=1; if (args_info.hybridGradient_given) { sample_conditionals=1; hybrid_conditionals=1; } if (args_info.numericalGradient_given) numerical=1; if (args_info.sampleStructure_given) sample_structure=1; if (args_info.psDir_given) strcpy(psDir, args_info.psDir_arg); if (args_info.sparsePS_given) sparsePS=args_info.sparsePS_arg; if (args_info.gridSearch_given) grid_search = 1; /* Generic RNAfold options */ if (args_info.temp_given) temperature = args_info.temp_arg; if (args_info.reference_given) fold_constrained=1; if (args_info.noTetra_given) tetra_loop=0; if (args_info.dangles_given) dangles = args_info.dangles_arg; if (args_info.noLP_given) noLonelyPairs = 1; if (args_info.noGU_given) noGU = 1; if (args_info.noClosingGU_given) no_closingGU = 1; if (args_info.noconv_given) noconv = 1; if (args_info.energyModel_given) energy_set = args_info.energyModel_arg; if (args_info.paramFile_given) ParamFile = strdup(args_info.paramFile_arg); if (args_info.nsp_given) ns_bases = strdup(args_info.nsp_arg); if (args_info.pfScale_given) sfact = args_info.pfScale_arg; if (args_info.noPS_given) noPS=1; /* Create postscript directory */ if (!noPS) { struct stat stat_p; if (stat (psDir, &stat_p) != 0) { if (mkdir(psDir, S_IRWXU|S_IROTH|S_IRGRP ) !=0) { fprintf(stderr, "WARNING: Could not create directory: %s", psDir); } } } if (ParamFile != NULL) { read_parameter_file(ParamFile); } if (ns_bases != NULL) { nonstandards = space(33); c=ns_bases; i=sym=0; if (*c=='-') { sym=1; c++; } while (*c!='\0') { if (*c!=',') { nonstandards[i++]=*c++; nonstandards[i++]=*c; if ((sym)&&(*c!=*(c-1))) { nonstandards[i++]=*c; nonstandards[i++]=*(c-1); } } c++; } } /*Read sequence*/ fname[0] = '\0'; while((input_type = get_input_line(&input_string, 0)) & VRNA_INPUT_FASTA_HEADER) { (void) sscanf(input_string, "%42s", fname); free(input_string); } length = (int) strlen(input_string); string = strdup(input_string); free(input_string); structure = (char *) space((unsigned) length+1); /* For testing purpose pass dot bracket structure of reference structure via -C */ if (fold_constrained) { input_type = get_input_line(&input_string, VRNA_INPUT_NOSKIP_COMMENTS); if(input_type & VRNA_INPUT_QUIT) { exit(1); } else if((input_type & VRNA_INPUT_MISC) && (strlen(input_string) > 0)) { cstruc = strdup(input_string); free(input_string); } else warn_user("-C was given but reference structure is missing"); } if(noconv) { str_RNA2RNA(string); } else { str_DNA2RNA(string); } /* Allocating space */ epsilon = (double *) space(sizeof(double)*(length+1)); exp_pert = (double **)space(sizeof(double *)*(length+1)); perturbations = (double **)space(sizeof(double *)*(length+1)); prev_epsilon = (double *) space(sizeof(double)*(length+1)); gradient = (double *) space(sizeof(double)*(length+1)); gradient_numeric = (double *) space(sizeof(double)*(length+1)); gradient_numeric_gsl = (double *) space(sizeof(double)*(length+1)); prev_gradient = (double *) space(sizeof(double)*(length+1)); q_unpaired = (double *) space(sizeof(double)*(length+1)); p_unpaired_cond = (double **)space(sizeof(double *)*(length+1)); p_unpaired_cond_sampled = (double **)space(sizeof(double *)*(length+1)); p_pp = (double **)space(sizeof(double *)*(length+1)); p_unpaired = (double *) space(sizeof(double)*(length+1)); p_unpaired_tmp = (double *) space(sizeof(double)*(length+1)); for (i=0; i <= length; i++) { epsilon[i] = gradient[i] = q_unpaired[i] = 0.0; p_unpaired_cond[i] = (double *) space(sizeof(double)*(length+1)); p_unpaired_cond_sampled[i] = (double *) space(sizeof(double)*(length+1)); p_pp[i] = (double *) space(sizeof(double)*(length+1)); exp_pert[i] = (double *) space(sizeof(double)*(length+1)); perturbations[i] = (double *) space(sizeof(double)*(length+1)); for (j=0; j <= length; j++) { p_pp[i][j]=p_unpaired_cond[i][j] = 0.0; p_unpaired_cond_sampled[i][j] = 0.0; } } /*** If file with perturbation vector epsilon is given we fold using this epsilon and are done ***/ if (args_info.epsilon_given) { plist *pl, *pl1,*pl2; filehandle = fopen (epsilon_file,"r"); if (filehandle == NULL) { nrerror("Could not open file with perturbation vector."); } i=1; while (1) { double t; line = get_line(filehandle); if (line == NULL) break; if (i>length) nrerror("Too many values in perturbation vector file."); if (sscanf(line, "%lf", &epsilon[i]) !=1) { nrerror("Error while reading perturbation vector file."); } i++; } if (i-1 != length) { nrerror("Too few values in perturbation vector file."); } init_pf_fold(length); pf_fold_pb(string, NULL); sprintf(fname,"%s/dot.ps", psDir); pl1 = make_plist(length, 1e-5); (void) PS_dot_plot_list_epsilon(string, fname, NULL, pl1, epsilon, ""); exit(0); } /*** Get constraints from reference structure or from external file ***/ /* Structure was given by -C */ if (fold_constrained) { for (i=0; i<length; i++) { if (cstruc[i] == '(' || cstruc[i] == ')') { q_unpaired[i+1] = 0.0; } else { q_unpaired[i+1] = 1.0; } } /*Read constraints from file*/ } else { filehandle = fopen (constraints_file,"r"); if (filehandle == NULL) { nrerror("No constraints given as dot bracket or wrong file name"); } i=1; while (1) { double t; line = get_line(filehandle); if (line == NULL) break; if (i>length) nrerror("Too many values in constraints.dat"); if (sscanf(line, "%lf", &q_unpaired[i]) !=1) { nrerror("Error while reading constraints.dat"); } i++; } if (i-1 != length) { nrerror("Too few values in constraints.dat"); } } /* Create file handle */ if (outfile[0] !='\0') { statsfile = fopen (outfile,"w"); } else { statsfile = fopen ("stats.dat","w"); } setvbuf(statsfile, NULL, _IONBF, 0); if (!grid_search) { fprintf(statsfile, "Iteration\tDiscrepancy\tNorm\tdfCount\tMEA\tSampled_structure\tSampled_energy\tSampled_distance\tEpsilon\ttimestamp\n"); } else { /* If we do a grid search we have a different output. */ fprintf(statsfile, "Dummy\tm\tb\tdummy\tMEA\tepsilon\n"); } if (statsfile == NULL) { nrerror("Could not open stats.dat for writing."); } fprintf(stderr, "tau^2 = %.4f; sigma^2 = %.4f; precision = %.4f; tolerance = %.4f; step-size: %.4f\n\n", tau, sigma, precision, tolerance, initial_step_size); st_back=1; min_en = fold(string, structure); (void) fflush(stdout); if (length>2000) free_arrays(); pf_struc = (char *) space((unsigned) length+1); kT = (temperature+273.15)*1.98717/1000.; /* in Kcal */ pf_scale = exp(-(sfact*min_en)/kT/length); /* Set up minimizer */ minimizer_x = gsl_vector_alloc (length+1); minimizer_g = gsl_vector_alloc (length+1); for (i=0; i <= length; i++) { epsilon[i] = 0.0; gsl_vector_set (minimizer_g, i, 0.0); gsl_vector_set (minimizer_x, i, epsilon[i]); } minimizer_pars.length=length; minimizer_pars.seq = string; minimizer_pars.tau=tau; minimizer_pars.sigma=sigma; minimizer_pars.kT=kT; minimizer_func.n = length+1; minimizer_func.f = calculate_f; minimizer_func.df = numerical ? calculate_df_numerically: calculate_df; minimizer_func.fdf = calculate_fdf; minimizer_func.params = &minimizer_pars; //min_en = fold_pb(string, structure); //fprintf(stderr, "%f", min_en); //exit(0); /* Calling test functions for debugging */ for (i=1; i <= length; i++) { if (i%2==0) { epsilon[i] = +0.2*i; } else { epsilon[i] = -0.2*i; } } //test_folding(string, length); /* //test_stochastic_backtracking(string, length); */ /* //test_gradient(minimizer_func, minimizer_pars); */ /* //test_gradient_sampling(minimizer_func, minimizer_pars); */ //exit(1); count_df_evaluations=0; /* Initial guess for epsilon */ if (initial_guess_method !=0 && initial_guess_method !=3) { /* Vars for inital guess methods */ double m,b; double* curr_epsilon; double* best_epsilon; double best_m, best_b, best_scale; double curr_D; double min_D = 999999999.0; double inc = +0.25; double cut; if (initial_guess_method == 1) fprintf(stderr, "Mathew's constant perturbations\n"); if (initial_guess_method == 2) fprintf(stderr, "Perturbations proportional to q-p\n"); curr_epsilon = (double *) space(sizeof(double)*(length+1)); best_epsilon = (double *) space(sizeof(double)*(length+1)); last_non_nan_lnQ = min_en; // Calculate p_unpaired for unperturbed state which we need later // for the proportinal method if (initial_guess_method == 2) { init_pf_fold(length); for (i=0; i <= length; i++) { epsilon[i] = 0.0; } pf_fold_pb(string, NULL); for (i = 1; i < length; i++) { for (j = i+1; j<= length; j++) { p_pp[i][j]=p_pp[j][i]=pr[iindx[i]-j]; } } get_pair_prob_vector(p_pp, p_unpaired_tmp, length, 1); free_pf_arrays(); } /* We do the same grid search as in the Mathews paper Fig. 4*/ for (m=0.25; m <=7.0; m+=0.25) { // Weird way of writing this inner loop for the grid search. We // traverse the grid without big jumps in the parameters to make // sure that the updated scaling factor is accurate all the time. inc*=-1; for (b = inc < 0.0 ? 0.0 : -3.0; inc < 0.0 ? b >= -3.0 : b<= 0.0 ; b+=inc) { // calculate cut point with x-axis and skip parameter pairs // which give a cut point outside the range of // q_unpaired (0 to 1). They gave frequently overflows and the // idea is that we both want positive and negative perturbations cut = exp( (-1) * b / m ) - 1; fprintf(stderr, "\nm = %.2f, b = %.2f, cut=%.2f\n", m, b, cut); if (cut > 1.0 || cut < 0.01) { fprintf(stderr, "\nSkipping m = %.2f, b = %.2f\n", m, b); continue; } /* Mathew's constant perturbations */ if (initial_guess_method == 1) { for (i=0; i <= length; i++) { /* We add epsilon to unpaired regions (as opposed to paired regions as in the Mathews paper) so we multiply by -1; if missing data we set it to 0.0 */ if (q_unpaired[i] < -0.5) { curr_epsilon[i] = 0.0; } else { curr_epsilon[i] = (m *(log(q_unpaired[i]+1))+b) *(-1); } gsl_vector_set (minimizer_x, i, curr_epsilon[i]); } /* Perturbations proportional to q-p */ } else { for (i=0; i <= length; i++) { curr_epsilon[i] = (m *(log(q_unpaired[i]+1)-log(p_unpaired_tmp[i]+1))+ b ) * (-1); gsl_vector_set (minimizer_x, i, curr_epsilon[i]); } } // Repeat and adjust scaling factor until we get result without over-/underflows do { // First we use default scaling factor if (pf_underflow == 0 && pf_overflow == 0) { sfact = 1.070; } if (pf_underflow) { sfact *= 0.8; fprintf(stderr,"Underflow, adjusting sfact to %.4f\n", sfact ); } if (pf_overflow) { sfact *= 1.2; fprintf(stderr,"Overflow, adjusting sfact to %.4f\n", sfact ); } pf_scale = exp(-(sfact*last_non_nan_lnQ)/kT/length); //fprintf(stderr,"Scaling factor is now: %.4e\n", pf_scale); curr_D = calculate_f(minimizer_x, (void*)&minimizer_pars); if (!isnan(last_lnQ)) last_non_nan_lnQ = last_lnQ; // Give up when even extreme scaling does not give results // (for some reason I could not get rid of overflows even with high scaling factors) if (sfact < 0.1 || sfact > 2.0) break; } while (pf_underflow == 1 || pf_overflow == 1); // We have not given up so everything is ok now if (!(sfact < 0.1 || sfact > 2.0)) { if (curr_D < min_D) { min_D = curr_D; for (i=0; i <= length; i++) { best_epsilon[i] = curr_epsilon[i]; } best_m = m; best_b = b; best_scale = pf_scale; } /*If we are interested in the grid search we misuse the print_stats function and report m and b together with MEA*/ if (grid_search) { for (i=0; i <= length; i++) { epsilon[i] = curr_epsilon[i]; } print_stats(statsfile, string, cstruc, length, 0, 0, m, 0.0, b, 0); } fprintf(stderr, "curr D: %.2f, minimum D: %.2f\n", curr_D, min_D); // Adjust pf_scale with default scaling factor but lnQ from // previous step sfact = 1.070; pf_scale = exp(-(sfact*last_lnQ)/kT/length); } else { sfact = 1.070; fprintf(stderr, "Skipping m = %.2f, b = %.2f; did not get stable result.\n", m, b); } } // for b } // for m fprintf(stderr, "Minimum found: m=%.2f, b=%.2f: %.2f\n", best_m, best_b, min_D); for (i=0; i <= length; i++) { epsilon[i] = best_epsilon[i]; gsl_vector_set (minimizer_x, i, best_epsilon[i]); } pf_scale = best_scale; } if (initial_guess_method == 3) { srand((unsigned)time(0)); for (i=0; i <= length; i++) { double r = (double)rand()/(double)RAND_MAX * 4 - 2; epsilon[i] = r; gsl_vector_set (minimizer_x, i, epsilon[i]); } } /* If we just wanted a grid search we are done now. */ if (grid_search) { exit(0); } prev_D = calculate_f(minimizer_x, (void*)&minimizer_pars); print_stats(statsfile, string, cstruc, length, 0 , count_df_evaluations , prev_D, -1.0, 0.0,1); /* GSL minimization */ if (method_id !=0) { if (method_id > 2) { char name[100]; // Available algorithms // 3 gsl_multimin_fdfminimizer_conjugate_fr // 4 gsl_multimin_fdfminimizer_conjugate_pr // 5 gsl_multimin_fdfminimizer_vector_bfgs // 6 gsl_multimin_fdfminimizer_vector_bfgs2 // 7 gsl_multimin_fdfminimizer_steepest_descent // http://www.gnu.org/software/gsl/manual/html_node/Multimin-Algorithms-with-Derivatives.html switch (method_id) { case 2: minimizer = gsl_multimin_fdfminimizer_alloc (gsl_multimin_fdfminimizer_conjugate_fr, length+1); strcpy(name, "Fletcher-Reeves conjugate gradient"); break; case 3: minimizer = gsl_multimin_fdfminimizer_alloc (gsl_multimin_fdfminimizer_conjugate_pr, length+1); strcpy(name, "Polak-Ribiere conjugate gradient"); break; case 4: minimizer = gsl_multimin_fdfminimizer_alloc ( gsl_multimin_fdfminimizer_vector_bfgs, length+1); strcpy(name, "Broyden-Fletcher-Goldfarb-Shanno"); break; case 5: minimizer = gsl_multimin_fdfminimizer_alloc ( gsl_multimin_fdfminimizer_vector_bfgs2, length+1); strcpy(name, "Broyden-Fletcher-Goldfarb-Shanno (improved version)"); break; case 6: minimizer = gsl_multimin_fdfminimizer_alloc (gsl_multimin_fdfminimizer_steepest_descent, length+1); strcpy(name, "Gradient descent (GSL implmementation)"); break; } fprintf(stderr, "Starting minimization via GSL implementation of %s...\n\n", name); // The last two parmeters are step size and tolerance (with // different meaning for different algorithms gsl_multimin_fdfminimizer_set (minimizer, &minimizer_func, minimizer_x, initial_step_size, tolerance); iteration = 1; do { status = gsl_multimin_fdfminimizer_iterate (minimizer); D = minimizer->f; norm = gsl_blas_dnrm2(minimizer->gradient); print_stats(statsfile, string, cstruc, length,iteration, count_df_evaluations, D, prev_D, norm, iteration%sparsePS == 0); prev_D = D; if (status) { fprintf(stderr, "An unexpected error has occured in the iteration (status:%i)\n", status); break; } status = gsl_multimin_test_gradient (minimizer->gradient, precision); if (status == GSL_SUCCESS) fprintf(stderr, "Minimum found stopping.\n"); iteration++; } while (status == GSL_CONTINUE && iteration < max_iteration); gsl_multimin_fdfminimizer_free (minimizer); gsl_vector_free (minimizer_x); /* Custom implementation of steepest descent */ } else { if (method_id == 1) { fprintf(stderr, "Starting custom implemented steepest descent search...\n\n"); } else { fprintf(stderr, "Starting custom implemented steepest descent search with Barzilai Borwein step size...\n\n"); } iteration = 0; D = 0.0; while (iteration++ < max_iteration) { for (i=1; i <= length; i++) { gsl_vector_set (minimizer_x, i, epsilon[i]); } D = calculate_f(minimizer_x, (void*)&minimizer_pars); if (numerical) { calculate_df_numerically(minimizer_x, (void*)&minimizer_pars, minimizer_g); } else { calculate_df(minimizer_x, (void*)&minimizer_pars, minimizer_g); } for (i=1; i <= length; i++) { gradient[i] = gsl_vector_get (minimizer_g, i); } // Do line search fprintf(stderr, "\nLine search:\n"); // After the first iteration, use Barzilai-Borwain (1988) step size (currently turned off) if (iteration>1 && method_id==2) { double denominator=0.0; double numerator=0.0; for (i=1; i <= length; i++) { numerator += (epsilon[i]-prev_epsilon[i]) * (gradient[i]-prev_gradient[i]); denominator+=(gradient[i]-prev_gradient[i]) * (gradient[i]-prev_gradient[i]); } step_size = numerator / denominator; norm =1.0; } else { // Use step sized given by the user (normalize it first) step_size = initial_step_size / calculate_norm(gradient, length); } for (i=1; i <= length; i++) { prev_epsilon[i] = epsilon[i]; prev_gradient[i] = gradient[i]; } do { for (mu=1; mu <= length; mu++) { epsilon[mu] = prev_epsilon[mu] - step_size * gradient[mu]; } for (i=1; i <= length; i++) { gsl_vector_set (minimizer_x, i, epsilon[i]); } DD = calculate_f(minimizer_x, (void*)&minimizer_pars); if (step_size > 0.0001) { fprintf(stderr, "Old D: %.4f; New D: %.4f; Step size: %.4f\n", D, DD, step_size); } else { fprintf(stderr, "Old D: %.4f; New D: %.4f; Step size: %.4e\n", D, DD, step_size); } step_size /= 2; } while (step_size > 1e-12 && DD > D); norm = calculate_norm(gradient,length); if (DD > D) { fprintf(stderr, "Line search did not improve D in iteration %i. Stop.\n", iteration); if (hybrid_conditionals) { sample_conditionals=0; } else { break; } } print_stats(statsfile, string, cstruc, length,iteration, count_df_evaluations, DD, prev_D, norm, iteration%sparsePS == 0); if (norm<precision && iteration>1) { fprintf(stderr, "Minimum found stopping.\n"); break; } prev_D = DD; } } /* Force last dotplot to be printed */ print_stats(statsfile, string, cstruc, length,iteration, count_df_evaluations, DD, prev_D, norm, 1); } free(pf_struc); if (cstruc!=NULL) free(cstruc); (void) fflush(stdout); free(string); free(structure); RNAfold_cmdline_parser_free (&args_info); return 0; }