void Generation::mutate_chromosome(Chromosome& chromosome, 
	                               double const& prob_mutation,
								   std::vector<bound> const& param_bounds, 
								   std::mt19937& urng) const
{
	std::uniform_real_distribution<> uniform_distr(0.0, 1.0);
	for (size_t i = 0; i < chromosome.size; ++i) {
		if (uniform_distr(urng) <= prob_mutation) {
			chromosome.genes[i] = chromosome.create_random_gene(param_bounds[i].lower, param_bounds[i].upper, urng);
		}
	}
}
void GeneticAlgorithm::record_error_plot(PeldorCalculator const& peldor_calc,
	                                     Chromosome const& chromosome,
									     std::vector<exp_signal> const& signals_exp,
									     Spin const& spinA, Spin const& spinB,
									     std::vector<int> const& param_numbers,
									     std::vector<int> const& param_modes,
										 std::vector<bound> const& param_bounds,
										 genetic_parameters const& genetic_param,
									     output_parameters const& output_param) const
{
	const size_t n_plots = output_param.error_plot_variables.size();
	const size_t plot_size = output_param.error_plot_size;
	size_t n_vars(0);
	// Initialize random generator
	std::random_device rd;
	std::array<unsigned int, std::mt19937::state_size> seed_data;
	std::generate_n(seed_data.begin(), seed_data.size(), std::ref(rd));
	std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
	std::mt19937 engine(seq);
	for (size_t i = 0; i < n_plots; ++i) { // iterate over the error plots
		n_vars = output_param.error_plot_variables[i].size();
		// Check if the selected variables of the error plot were optimized
		int indexVariable(0);
		bool inappropriateVariables(0);
		for (size_t j = 0; j < n_vars; ++j) {
			indexVariable = output_param.error_plot_variables[i][j] - 1;
			if (param_numbers[indexVariable] == -1) {
				std::cout << "  Inappropriate variable (it was not optimized): " << output_param.error_plot_variables[i][j] << std::endl;
				inappropriateVariables = 1;
				break;
			}
		}
		if (inappropriateVariables) continue;
		// Create a generation with different values of the parameters to be varied
		genetic_parameters genetic_param_ep(genetic_param);
		genetic_param_ep.size_generation = output_param.error_plot_size;
		Generation* generation_ep = new Generation(genetic_param_ep);
		for (size_t k = 0; k < plot_size; ++k) generation_ep->chromosomes.push_back(chromosome); // initialize all chromosomes with the optimized chromosome
		int indexGene(0);
		for (size_t j = 0; j < n_vars; ++j) { // vary the genes corresponding to the defined variables
			indexGene = param_numbers[output_param.error_plot_variables[i][j] - 1];
			for (size_t k = 0; k < plot_size; ++k) {
				generation_ep->chromosomes[k].genes[indexGene] = chromosome.create_random_gene(param_bounds[indexGene].lower, param_bounds[indexGene].upper, engine);
			}
		}
		// Score the generation
		generation_ep->score_chromosomes(peldor_calc, signals_exp, spinA, spinB, param_numbers, param_modes, genetic_param);
		generation_ep->sort_chromosomes();
		//// Modified! Save fits
		//output_parameters output_param_ep(output_param);
		//for (size_t j = 0; j < n_vars; ++j) {
		//	std::stringstream nPlot;
		//	nPlot << j;
		//	output_param_ep.directory = output_param.directory + nPlot.str();
		//	record_fit(peldor_calc, generation_ep->chromosomes[j], signals_exp, spinA, spinB, param_numbers, param_modes, output_param_ep);
		//}
		// Create & open a file
		std::ostringstream filename;
		filename << output_param.directory << "error_plot";
		for (size_t j = 0; j < n_vars; ++j) filename << "_" << output_param.error_plot_variables[i][j];
		filename << ".dat";
		std::fstream file;
		file.open(filename.str().c_str(), std::ios::out);
		// Write the names of columns
		size_t const col_width = 15;
		std::ostringstream col_name;
		for (size_t j = 0; j < n_vars; ++j) {
			col_name << "Parameter" << (j + 1);
			file << std::left << std::setw(col_width) << col_name.str();
			col_name.str(std::string()); col_name.clear();
		}
		if (genetic_param.merit_function == 1)      file << std::left << std::setw(col_width) << "RMSD" << std::endl;
		else if (genetic_param.merit_function == 2) file << std::left << std::setw(col_width) << "RMSD/PCC" << std::endl;
		else if (genetic_param.merit_function == 3) file << std::left << std::setw(col_width) << "PCC" << std::endl;
		// Write the error plot
		for (size_t k = 0; k < plot_size; ++k) {
			for (size_t j = 0; j < n_vars; ++j) { 
				indexGene = param_numbers[output_param.error_plot_variables[i][j] - 1];
				if (std::count(angular_indices, angular_indices + 20, indexGene)) {
					file << std::left << std::setw(col_width) << std::fixed << std::setprecision(0) << generation_ep->chromosomes[k].genes[indexGene] * rad2deg;
				}
				else {
					file << std::left << std::setw(col_width) << std::fixed << std::setprecision(2) << generation_ep->chromosomes[k].genes[indexGene];
				}
			}
			file << std::left << std::setw(col_width) << std::fixed << std::setprecision(5) << generation_ep->chromosomes[k].fitness;
			file << std::endl;
		}
		file.close();
		// Clean up
		delete generation_ep;
	}
}