void DifferentialEvolution::initialize_population(RunManagerAbstract &run_manager, int d) { ostream &fout_restart = file_manager.get_ofstream("rst"); int iter = 0; RestartController::write_start_iteration(fout_restart, solver_type_name, iter, iter); Parameters ctl_pars; for (int i = 0; i < d; ++i) { ctl_pars.clear(); initialize_vector(ctl_pars); par_transform.ctl2model_ip(ctl_pars); run_manager.add_run(ctl_pars); } RestartController::write_upgrade_runs_built(fout_restart); // make innitial population vector model runs cout << endl; cout << " performing initial population model runs... "; cout.flush(); run_manager.run(); gen_1.copy(run_manager.get_runstorage_ref()); // get the best_run to track phi int r_status; int n_par = par_list.size(); best_phi = std::numeric_limits<double>::max(); Parameters tmp_pars; Observations tmp_obs; ModelRun tmp_run(obj_func_ptr); for (int i_run = 0; i_run < d; ++i_run) { bool r_status = gen_1.get_run(i_run, tmp_pars, tmp_obs); if (r_status > 0) { par_transform.model2ctl_ip(tmp_pars); tmp_run.update_ctl(tmp_pars, tmp_obs); double tmp_phi = tmp_run.get_phi(DynamicRegularization::get_unit_reg_instance()); if (tmp_phi < best_phi) { best_phi = tmp_phi; best_run_idx = i_run; } } } }
void DifferentialEvolution::solve(RunManagerAbstract &run_manager, RestartController &restart_controller, int max_gen, double f, double cr, bool dither_f, ModelRun &cur_run) { ostream &os = file_manager.rec_ofstream(); ostream &fout_restart = file_manager.get_ofstream("rst"); for (int iter = 0; iter < max_gen && best_phi > std::numeric_limits<double>::min(); ++iter) { RestartController::write_start_iteration(fout_restart, solver_type_name, iter+1, iter+1); Parameters tmp_pars; Observations tmp_obs; // write header for iteration cout << endl; output_file_writer.iteration_report(cout, iter+1, run_manager.get_total_runs(), "differntial evolution"); os << endl; output_file_writer.iteration_report(os, iter + 1, run_manager.get_total_runs(), "differntial evolution"); // write initial phi report for this iteration bool run_target_ok = gen_1.get_run(best_run_idx, tmp_pars, tmp_obs); par_transform.model2ctl_ip(tmp_pars); map<string, double> phi_comps = obj_func_ptr->phi_report(tmp_obs, tmp_pars, DynamicRegularization::get_unit_reg_instance()); output_file_writer.phi_report(cout, iter, run_manager.get_nruns(), phi_comps, DynamicRegularization::get_unit_reg_instance().get_weight(), false); output_file_writer.phi_report(os, iter, run_manager.get_nruns(), phi_comps, DynamicRegularization::get_unit_reg_instance().get_weight(), false); run_manager.reinitialize(); mutation(run_manager, f, dither_f, cr); RestartController::write_upgrade_runs_built(fout_restart); // make trial vector model runs cout << endl; cout << " performing trial vector model runs... "; cout.flush(); run_manager.run(); os << endl; best_run_idx = recombination(run_manager); os << endl; run_target_ok = gen_1.get_run(best_run_idx, tmp_pars, tmp_obs); par_transform.model2ctl_ip(tmp_pars); // write parameter file for this iteration output_file_writer.write_par(file_manager.open_ofile_ext("par"), tmp_pars, *(par_transform.get_offset_ptr()), *(par_transform.get_scale_ptr())); file_manager.close_file("par"); // write final phi report for this iteration phi_comps = obj_func_ptr->phi_report(tmp_obs, tmp_pars, DynamicRegularization::get_unit_reg_instance()); output_file_writer.phi_report(cout, iter, run_manager.get_nruns(), phi_comps, DynamicRegularization::get_unit_reg_instance().get_weight(), true); cout << endl; output_file_writer.phi_report(os, iter, run_manager.get_nruns(), phi_comps, DynamicRegularization::get_unit_reg_instance().get_weight(), true); os << endl; } }
bool Jacobian_1to1::calculate(ModelRun &init_model_run, vector<string> numeric_par_names, vector<string> obs_names, ParamTransformSeq &par_transform, const ParameterGroupInfo &group_info, const ParameterInfo &ctl_par_info, RunManagerAbstract &run_manager, const PriorInformation &prior_info, set<string> &out_of_bound_par, bool phiredswh_flag, bool calc_init_obs) { int i_run; string *par_name; double par_value; Parameters model_parameters(par_transform.ctl2model_cp(init_model_run.get_ctl_pars())); Observations observations(init_model_run.get_obs_template()); base_numeric_parameters = par_transform.ctl2numeric_cp( init_model_run.get_ctl_pars()); run_manager.reinitialize(file_manager.build_filename("rnj")); const vector<string> &model_par_name_vec = run_manager.get_par_name_vec(); const vector<string> &obs_name_vec = run_manager.get_obs_name_vec(); size_t n_par = model_par_name_vec.size(); failed_parameter_names.clear(); // compute runs for to jacobain calculation as it is influenced by derivative type( forward or central) vector<JacobianRun> del_numeric_par_vec; if (calc_init_obs) { del_numeric_par_vec.push_back(JacobianRun("", 0)); run_manager.add_run(model_parameters); } Parameters new_derivative_pars; bool success; Parameters base_derivative_parameters = par_transform.numeric2derivative_cp(base_numeric_parameters); //Loop through derivative parameters and build the parameter sets necessary for computing the jacobian for (auto &i_name : numeric_par_names) { assert(base_derivative_parameters.find(i_name) != base_derivative_parameters.end()); vector<JacobianRun> tmp_del_numeric_par_vec; double derivative_par_value = base_derivative_parameters.get_rec(i_name); success = get_derivative_parameters(i_name, derivative_par_value, par_transform, group_info, ctl_par_info, tmp_del_numeric_par_vec, phiredswh_flag); if (success && !tmp_del_numeric_par_vec.empty()) { del_numeric_par_vec.insert(del_numeric_par_vec.end(), tmp_del_numeric_par_vec.begin(), tmp_del_numeric_par_vec.end()); // update changed model parameters in model_parameters for (const auto &par : tmp_del_numeric_par_vec) { Parameters org_pars; Parameters new_pars; org_pars.insert(make_pair(par.par_name, model_parameters.get_rec(par.par_name))); new_pars.insert(make_pair(par.par_name, par.numeric_value)); par_transform.derivative2model_ip(new_pars); for (auto &ipar : new_pars) { model_parameters[ipar.first] = ipar.second; } run_manager.add_run(model_parameters); for (const auto &ipar : org_pars) { model_parameters[ipar.first] = ipar.second; } } } else { failed_parameter_names.insert(i_name); } } ofstream &fout_restart = file_manager.get_ofstream("rst"); fout_restart << "jacobian_model_runs_begin_group_id " << run_manager.get_cur_groupid() << endl; // make model runs run_manager.run(); fout_restart << "jacobian_model_runs_end_group_id " << run_manager.get_cur_groupid() << endl; // calculate jacobian base_sim_obs_names = obs_names; if(matrix.rows() != base_sim_obs_names.size() || matrix.cols() !=numeric_par_names.size()) { matrix.resize(base_sim_obs_names.size(), numeric_par_names.size()); } // initialize prior information prior_info_sen.clear(); unordered_map<string, int> par2col_map = get_par2col_map(); unordered_map<string, int>::iterator found; unordered_map<string, int>::iterator not_found = par2col_map.end(); i_run = 0; // if initial run was performed, get the newly calculated values if (calc_init_obs) { Parameters tmp_pars; Observations tmp_obs; bool success = run_manager.get_run(i_run, tmp_pars, tmp_obs); if (!success) { throw(PestError("Error: Base parameter run failed. Can not compute the Jacobian")); } par_transform.model2ctl_ip(tmp_pars); init_model_run.update_ctl(tmp_pars, tmp_obs); ++i_run; } base_numeric_parameters = par_transform.ctl2numeric_cp(init_model_run.get_ctl_pars()); // process the parameter pertubation runs int nruns = del_numeric_par_vec.size(); list<pair<ModelRun, double> > run_list; base_numeric_par_names.clear(); ModelRun tmp_model_run = init_model_run; int icol = 0; vector<string>par_name_vec; for(; i_run<nruns; ++i_run) { par_name = &del_numeric_par_vec[i_run].par_name; Parameters tmp_pars; Observations tmp_obs; bool success = run_manager.get_run(i_run, tmp_pars, tmp_obs); if (success) { par_name_vec.clear(); par_name_vec.push_back(*par_name); par_transform.model2ctl_ip(tmp_pars); tmp_model_run.update_ctl(tmp_pars, tmp_obs); Parameters numeric_pars(tmp_pars, par_name_vec); par_transform.ctl2numeric_ip(numeric_pars); par_value = numeric_pars.get_rec(*par_name); run_list.push_back(make_pair(tmp_model_run, par_value)); } if(i_run+1>=nruns || *par_name != del_numeric_par_vec[i_run+1].par_name) { if (!run_list.empty()) { base_numeric_par_names.push_back(*par_name); double base_numeric_par_value = base_numeric_parameters.get_rec(*par_name); run_list.push_front(make_pair(init_model_run, base_numeric_par_value)); calc_derivative(*par_name, icol, run_list, par_transform, group_info, ctl_par_info, prior_info); icol++; } else { failed_parameter_names.insert(*par_name); } run_list.clear(); } } matrix.conservativeResize(base_sim_obs_names.size(), base_numeric_par_names.size()); // clean up fout_restart << "jacobian_saved" << endl; run_manager.free_memory(); return true; }
int DifferentialEvolution::recombination(RunManagerAbstract &run_manager) { ostream &os = file_manager.rec_ofstream(); int best_run_idx = 0; ModelRun run_target(obj_func_ptr); ModelRun run_canidate(obj_func_ptr); Parameters tmp_pars_targ; Observations tmp_obs_targ; Parameters tmp_pars_can; Observations tmp_obs_can; best_phi = std::numeric_limits<double>::max(); int d = gen_1.get_nruns(); int n_good_runs_targ = gen_1.get_num_good_runs(); int n_good_runs_can = run_manager.get_num_good_runs(); double phi_sum_targ = 0.0; double phi_sum_can = 0.0; double phi_sum_new = 0.0; double phi_max_targ = 0.0; double phi_max_can = 0.0; double phi_max_new = 0.0; double phi_min_targ = std::numeric_limits<double>::max(); double phi_min_can = std::numeric_limits<double>::max(); double phi_min_new = std::numeric_limits<double>::max(); os << " population phi values:" << endl; os << " parent canidate" << endl; os << " id phi phi" << endl; os << " ---- --------- ---------" << endl; for (int i_run = 0; i_run < d; ++i_run) { double new_phi = std::numeric_limits<double>::max(); bool run_target_ok = gen_1.get_run(i_run, tmp_pars_targ, tmp_obs_targ); bool run_canidate_ok = run_manager.get_run(i_run, tmp_pars_can, tmp_obs_can); if (!run_canidate_ok && !run_target_ok) { //keep current target new_phi = std::numeric_limits<double>::max(); ++failed_runs_old; ++failed_runs_new; os << " " << left << setw(10) << i_run << setw(15) << "N/A" << setw(15) << "N/A"; os << endl; } else if (!run_canidate_ok) { //keep current target ++failed_runs_new; par_transform.model2ctl_ip(tmp_pars_targ); // compute phi run_target.update_ctl(tmp_pars_targ, tmp_obs_targ); double phi_target = run_target.get_phi(DynamicRegularization::get_unit_reg_instance()); phi_sum_targ += phi_target; phi_sum_new += phi_target; phi_min_targ = min(phi_min_targ, phi_target); phi_max_targ = max(phi_max_targ, phi_target); os << " " << left << setw(10) << i_run << setw(15) << phi_target << setw(15) << "N/A"; os << endl; } else if (!run_target_ok) { gen_1.update_run(i_run, tmp_pars_can, tmp_obs_can); // compute phi par_transform.model2ctl_ip(tmp_pars_can); run_canidate.update_ctl(tmp_pars_can, tmp_obs_can); new_phi = run_canidate.get_phi(DynamicRegularization::get_unit_reg_instance()); ++failed_runs_old; phi_sum_can += new_phi; phi_sum_new += new_phi; phi_min_can = min(phi_min_targ, new_phi); phi_max_can = max(phi_max_targ, new_phi); os << " " << left << setw(10) << i_run << setw(15) << "N/A" << setw(15) << new_phi; os << endl; } else { // process target parameters and observations par_transform.model2ctl_ip(tmp_pars_targ); run_target.update_ctl(tmp_pars_targ, tmp_obs_targ); double phi_target = run_target.get_phi(DynamicRegularization::get_unit_reg_instance()); //process canidate parameters and observations par_transform.model2ctl_ip(tmp_pars_can); run_canidate.update_ctl(tmp_pars_can, tmp_obs_can); double phi_canidate = run_canidate.get_phi(DynamicRegularization::get_unit_reg_instance()); new_phi = min(phi_target, phi_canidate); os << " " << left << setw(10) << i_run; os << setw(15) << phi_target; os << setw(15) << phi_canidate; os << endl; if (phi_canidate < phi_target) { gen_1.update_run(i_run, tmp_pars_can, tmp_obs_can); } phi_sum_targ += phi_target; phi_sum_can += phi_canidate; phi_sum_new += new_phi; phi_min_can = min(phi_min_can, phi_canidate); phi_max_can = max(phi_max_can, phi_canidate); phi_min_targ = min(phi_min_targ, phi_target); phi_max_targ = max(phi_max_targ, phi_target); } phi_min_new = min(phi_min_new, new_phi); phi_max_new = max(phi_max_new, new_phi); if (new_phi < best_phi) { best_phi = new_phi; best_run_idx = i_run; } } double phi_avg_targ = std::numeric_limits<double>::max(); double phi_avg_can = std::numeric_limits<double>::max(); double phi_avg_new = std::numeric_limits<double>::max(); int n_good_runs_new = gen_1.get_num_good_runs(); if (n_good_runs_targ > 0) { phi_avg_targ = phi_sum_targ / n_good_runs_targ; } if (n_good_runs_can > 0) { phi_avg_can = phi_sum_can / n_good_runs_can; } if (n_good_runs_new > 0) { phi_avg_new = phi_sum_new / n_good_runs_new; } write_run_summary(cout, n_good_runs_targ, phi_avg_targ, phi_min_targ, phi_max_targ, n_good_runs_can, phi_avg_can, phi_min_can, phi_max_can, n_good_runs_new, phi_avg_new, phi_min_new, phi_max_new); cout << endl; os << endl; write_run_summary(os, n_good_runs_targ, phi_avg_targ, phi_min_targ, phi_max_targ, n_good_runs_can, phi_avg_can, phi_min_can, phi_max_can, n_good_runs_new, phi_avg_new, phi_min_new, phi_max_new); os << endl; return best_run_idx; }
void DifferentialEvolution::mutation(RunManagerAbstract &run_manager, double f, bool dither_f, double cr) { int d = gen_1.get_nruns(); int r_status; int n_par = par_list.size(); std::uniform_int_distribution<int> uni_par(0, n_par-1); std::uniform_real_distribution<double> cr_prob(0.0, 1.0); std::uniform_real_distribution<double> dither_f_prob(.5, 1.0); vector<int> successful_run_ids; // generate a vector of successful runs for (int i_run = 0; i_run < d; ++i_run) { r_status = gen_1.get_run_status(i_run); if (r_status > 0) { successful_run_ids.push_back(i_run); } } int d_ok = successful_run_ids.size(); std::uniform_int_distribution<int> uni_run_ok(0, d_ok-1); Parameters xa; Parameters xb; Parameters xc; Parameters x_trial; for (int i_run = 0; i_run < d; ++i_run) { int xa_id = successful_run_ids[uni_run_ok(rand_engine)]; int xb_id = successful_run_ids[uni_run_ok(rand_engine)]; while (xa_id == xb_id) { xb_id = successful_run_ids[uni_run_ok(rand_engine)]; } int xc_id = successful_run_ids[uni_run_ok(rand_engine)]; //initialize trail vector with the traget vector gen_1.get_parameters(i_run, x_trial); gen_1.get_parameters(xa_id, xa); gen_1.get_parameters(xb_id, xb); gen_1.get_parameters(xc_id, xb); par_transform.model2ctl_ip(xa); par_transform.model2ctl_ip(xb); par_transform.model2ctl_ip(xc); int par_id_chg = uni_par(rand_engine); for (int idx=0; idx<n_par; ++idx) { const string &ipar = par_list[idx]; double a = xa[ipar]; double b = xb[ipar]; double c = xc[ipar]; double delta = a - b; double tmp_f = f; if (dither_f) { tmp_f = dither_f_prob(rand_engine); } double c_p = c + tmp_f * (delta); double p_min = parameter_info[ipar].lower_bnd; double p_max = parameter_info[ipar].upper_bnd; // reflect purturbation if parameter is outside it's bounds while (c_p < p_min || c_p > p_max) { if (c_p < p_min) { c_p += p_min - c_p; } if (c_p > p_max) { c_p -= c_p - p_max; } } // do cross over //the trial vector was initialized with the target vector // so the parameters from the parent don't need to be set double rand_cr = cr_prob(rand_engine); if (rand_cr > cr || idx == par_id_chg) { x_trial[ipar] = c_p; } } par_transform.ctl2model_ip(x_trial); run_manager.add_run(x_trial); } }