9#include "genetic_algorithm.h"
56const Tensor<bool, 1>& GeneticAlgorithm::get_selection()
const
70Index GeneticAlgorithm::get_genes_number()
const
96 const Index genes_number = get_genes_number();
97 Index individuals_number;
103 individuals_number = 10;
107 population.resize(individuals_number, genes_number);
110 for(Index i = 0; i < individuals_number; i++)
parameters(i).resize(genes_number);
112 training_errors.resize(individuals_number);
113 selection_errors.resize(individuals_number);
115 fitness.resize(individuals_number);
116 fitness.setConstant(type(-1.0));
118 selection.resize(individuals_number);
134 const Index new_individuals_number = new_population.dimension(2);
138 ostringstream buffer;
142 buffer <<
"OpenNN Exception: InputsSelection class.\n"
143 <<
"void check() const method.\n"
144 <<
"Pointer to training strategy is nullptr.\n";
146 throw logic_error(buffer.str());
153 if(!loss_index_pointer)
155 buffer <<
"OpenNN Exception: InputsSelection class.\n"
156 <<
"void check() const method.\n"
157 <<
"Pointer to loss index is nullptr.\n";
159 throw logic_error(buffer.str());
166 if(!neural_network_pointer)
168 buffer <<
"OpenNN Exception: InputsSelection class.\n"
169 <<
"void check() const method.\n"
170 <<
"Pointer to neural network is nullptr.\n";
172 throw logic_error(buffer.str());
175 if(new_individuals_number != individuals_number)
177 ostringstream buffer;
179 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
180 <<
"void set_population(const Tensor<type, 2>&) method.\n"
181 <<
"Population rows("<<new_individuals_number
182 <<
") must be equal to population size("<<individuals_number<<
").\n";
184 throw logic_error(buffer.str());
193void GeneticAlgorithm::set_training_errors(
const Tensor<type, 1>& new_training_errors)
195 training_errors = new_training_errors;
199void GeneticAlgorithm::set_selection_errors(
const Tensor<type, 1>& new_selection_errors)
201 selection_errors = new_selection_errors;
214 if(new_fitness.size() != individuals_number)
216 ostringstream buffer;
218 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
219 <<
"void set_fitness(const Tensor<type, 1>&) method.\n"
220 <<
"Fitness size ("<<new_fitness.size()
221 <<
") must be equal to population size ("<< individuals_number <<
").\n";
223 throw logic_error(buffer.str());
226 for(Index i = 0; i < individuals_number; i++)
228 if(new_fitness[i] < 0)
230 ostringstream buffer;
232 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
233 <<
"void set_fitness(const Tensor<type, 2>&) method.\n"
234 <<
"Fitness must be greater than 0.\n";
236 throw logic_error(buffer.str());
253 if(new_individuals_number < 4)
255 ostringstream buffer;
257 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
258 <<
"void set_individuals_number(const Index&) method.\n"
259 <<
"Population size must be greater than 4.\n";
261 throw logic_error(buffer.str());
268 population.resize(new_individuals_number, new_genes_number);
272 training_errors.resize(new_individuals_number);
273 selection_errors.resize(new_individuals_number);
275 fitness.resize(new_individuals_number);
276 fitness.setConstant(type(-1.0));
278 selection.resize(new_individuals_number);
292 if(new_mutation_rate < 0 || new_mutation_rate > 1)
294 ostringstream buffer;
296 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
297 <<
"void set_mutation_rate(const type&) method.\n"
298 <<
"Mutation rate must be between 0 and 1.\n";
300 throw logic_error(buffer.str());
318 if(new_elitism_size > individuals_number)
320 ostringstream buffer;
322 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
323 <<
"void set_elitism_size(const Index&) method.\n"
324 <<
"Elitism size("<< new_elitism_size
325 <<
") must be lower than the population size("<<individuals_number<<
").\n";
327 throw logic_error(buffer.str());
344 if(individuals_number == 0)
346 ostringstream buffer;
348 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
349 <<
"void initialize_population() method.\n"
350 <<
"Population size must be greater than 0.\n";
352 throw logic_error(buffer.str());
357 const Index genes_number = get_genes_number();
359 Tensor<bool, 1> individual(genes_number);
361 for(Index i = 0; i < individuals_number; i++)
363 for(Index j = 0; j < genes_number; j++)
365 rand()%2 == 0 ? individual[j] = false : individual[j] =
true;
370 if(is_false(individual))
372 individual(
static_cast<Index
>(rand())%genes_number) =
true;
375 for(Index j = 0; j < genes_number; j++)
394 ostringstream buffer;
396 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
397 <<
"void evaluate_population() method.\n"
398 <<
"Population size must be greater than 0.\n";
400 throw logic_error(buffer.str());
417 Tensor<string, 1> inputs_names;
425 Tensor<bool, 1> individual;
430 const Index genes_number = get_genes_number();
432 for(Index i = 0; i < individuals_number; i++)
436 if(
display) cout <<
"Individual " << i+1 << endl;
438 const Tensor<Index, 0> input_columns_number = individual.cast<Index>().sum();
440 Tensor<Index, 1> input_columns_indices(input_columns_number(0));
444 for(Index j = 0; j < genes_number; j++)
448 input_columns_indices(index) = original_input_columns_indices(j);
453 data_set_pointer->set_input_target_columns(input_columns_indices, original_target_columns_indices);
469 training_errors(i) = training_results.get_training_error();
470 selection_errors(i) = training_results.get_selection_error();
474 cout <<
"Inputs: " << endl;
476 const Tensor<string, 1> inputs_names = neural_network_pointer->
get_inputs_names();
478 for(Index i = 0; i < inputs_names.size(); i++) cout <<
" " << inputs_names(i) << endl;
480 cout <<
"Training error: " << training_results.get_training_error() << endl;
481 cout <<
"Selection error: " << training_results.get_selection_error() << endl;
493 const Tensor<Index, 1> rank = calculate_rank_greater(selection_errors);
495 for(Index i = 0; i < individuals_number; i++)
510 ostringstream buffer;
512 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
513 <<
"void perform_selection() method.\n"
514 <<
"Population size must be greater than 0.\n";
516 throw logic_error(buffer.str());
521 ostringstream buffer;
523 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
524 <<
"void perform_selection() method.\n"
525 <<
"No fitness found.\n";
527 throw logic_error(buffer.str());
532 selection.setConstant(
false);
536 const Index selected_individuals_number =
static_cast<Index
>((individuals_number-
elitism_size)/2);
538 const Tensor<type, 1> cumulative_fitness =
fitness.cumsum(0);
540 Tensor<Index, 1> fitness_rank = calculate_rank_greater(
fitness);
542 Index selection_count = 0;
548 const type pointer =
static_cast<type
>(rand()/(RAND_MAX+1.0))*cumulative_fitness(individuals_number-1);
550 if(pointer < cumulative_fitness(0) && !selection(0))
557 for(Index i = 1; i < individuals_number; i++)
559 if(cumulative_fitness(i-1) < pointer
560 && pointer < cumulative_fitness(i)
569 }
while(selection_count < selected_individuals_number);
573 Index selection_assert = 0;
574 for(Index i = 0; i < individuals_number; i++)
if(selection(i)) selection_assert++;
576 if(selection_assert != individuals_number/2)
578 ostringstream buffer;
580 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
581 <<
"void perform_selection() method.\n"
582 <<
"Number of selected individuals (" << selection_assert <<
") must be " << individuals_number/2 <<
" .\n";
584 throw logic_error(buffer.str());
597 const Index genes_number = get_genes_number();
601 const Index selected_individuals_number = individuals_number/2;
603 Index count_selected_individuals = 0;
604 for(Index i = 0; i < individuals_number; i++)
if(selection(i)) count_selected_individuals++;
606 if(selected_individuals_number != count_selected_individuals)
608 ostringstream buffer;
610 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
611 <<
"void perform_crossover() method.\n"
612 <<
"Selected individuals number is wrong.\n";
614 throw logic_error(buffer.str());
619 Index parent_1_index = 0;
620 Index parent_2_index = 0;
622 Tensor<bool, 1> parent_1(genes_number);
623 Tensor<bool, 1> parent_2(genes_number);
625 Tensor<bool, 1> offspring_1(genes_number);
626 Tensor<bool, 1> offspring_2(genes_number);
628 Index offspring_count = 0;
630 Tensor<bool, 2> new_population(individuals_number, genes_number);
632 Index new_individual_index = 0;
634 Tensor<Index, 1> fitness_rank = calculate_rank_greater(
fitness);
638 new_individual_index = fitness_rank(i);
640 for(Index j = 0; j < genes_number; j++)
642 new_population(offspring_count, j) =
population(new_individual_index, j);
648 for(Index i = 0; i < individuals_number; i++)
650 if(offspring_count > individuals_number-1)
break;
652 if(!selection(i))
continue;
657 parent_2_index =
static_cast<Index
>(rand())%individuals_number;
658 }
while(selection(parent_2_index) && parent_1_index != parent_2_index);
660 parent_1 =
population.chip(parent_1_index, 0);
661 parent_2 =
population.chip(parent_2_index, 0);
663 for(Index j = 0; j < genes_number; j++)
667 offspring_1(j) = parent_1[j];
668 offspring_2(j) = parent_2[j];
672 offspring_1(j) = parent_2[j];
673 offspring_2(j) = parent_1[j];
679 if(is_false(offspring_1))
680 offspring_1(
static_cast<Index
>(rand())%genes_number) =
true;
682 if(is_false(offspring_2))
683 offspring_2(
static_cast<Index
>(rand())%genes_number) =
true;
685 for(Index j = 0; j < genes_number; j++)
687 new_population(offspring_count, j) = offspring_1(j);
691 if(offspring_count + 1 <= individuals_number-1) new_population(offspring_count+1, j) = offspring_2(j);
694 offspring_count += 2;
699 if(offspring_count == individuals_number-1)
701 for(Index i = 0; i < individuals_number; i++)
703 if(!selection(i))
continue;
708 parent_2_index =
static_cast<Index
>(rand())%individuals_number;
709 }
while(selection(parent_2_index) && parent_1_index != parent_2_index);
711 parent_1 =
population.chip(parent_1_index, 0);
712 parent_2 =
population.chip(parent_2_index, 0);
714 for(Index j = 0; j < genes_number; j++)
718 offspring_1(j) = parent_1[j];
722 offspring_1(j) = parent_2[j];
726 if(is_false(offspring_1))
727 offspring_1(
static_cast<Index
>(rand())%genes_number) =
true;
729 for(Index j = 0; j < genes_number; j++)
731 new_population(offspring_count, j) = offspring_1(j);
746 const Index genes_number = get_genes_number();
748 Tensor<bool, 1> individual(genes_number);
750 for(Index i = 0; i < individuals_number; i++)
752 for(Index j = 0; j < genes_number; j++)
754 if(
static_cast<type
>(rand()/(RAND_MAX+1.0)) <=
mutation_rate)
762 if(is_false(individual))
764 individual(
static_cast<Index
>(rand())%genes_number) =
true;
766 for(Index j = 0; j < genes_number; j++)
785 if(
display) cout <<
"Performing genetic inputs selection..." << endl << endl;
810 Index optimal_individual_index;
814 time_t beginning_time, current_time;
815 type elapsed_time = type(0);
817 time(&beginning_time);
823 if(
display) cout <<
"Generation: " << epoch + 1 << endl;
827 optimal_individual_index = minimal_index(selection_errors);
836 inputs_selection_results.optimal_inputs =
population.chip(optimal_individual_index, 0);
838 data_set_pointer->set_input_columns(original_input_columns_indices, inputs_selection_results.optimal_inputs);
853 elapsed_time =
static_cast<type
>(difftime(current_time, beginning_time));
859 cout <<
"Generation mean training error: " << training_errors.mean() << endl;
860 cout <<
"Generation mean selection error: " << selection_errors.mean() << endl;
862 cout <<
"Generation minimum training error: " << training_errors(optimal_individual_index) << endl;
863 cout <<
"Generation minimum selection error: " << selection_errors(optimal_individual_index) << endl;
868 cout <<
"Elapsed time: " <<
write_time(elapsed_time) << endl;
877 if(
display) cout <<
"Epoch " << epoch << endl <<
"Maximum time reached: " <<
write_time(elapsed_time) << endl;
879 inputs_selection_results.
stopping_condition = InputsSelection::StoppingCondition::MaximumTime;
886 if(
display) cout <<
"Epoch " << epoch << endl <<
"Selection error reached: " << selection_errors(optimal_individual_index) << endl;
888 inputs_selection_results.
stopping_condition = InputsSelection::StoppingCondition::SelectionErrorGoal;
895 if(
display) cout <<
"Epoch " << epoch << endl <<
"Maximum number of epochs reached: " << epoch << endl;
897 inputs_selection_results.
stopping_condition = InputsSelection::StoppingCondition::MaximumEpochs;
904 inputs_selection_results.resize_history(epoch+1);
920 data_set_pointer->set_input_columns(original_input_columns_indices, inputs_selection_results.optimal_inputs);
922 const Tensor<Scaler, 1> input_variables_scalers = data_set_pointer->get_input_variables_scalers();
937 if(
display) inputs_selection_results.print();
939 return inputs_selection_results;
948 Tensor<string, 2> string_matrix(8, 2);
952 ostringstream buffer;
954 Tensor<string, 1> labels(6);
955 Tensor<string, 1> values(6);
959 labels(0) =
"Population size";
960 values(0) = to_string(individuals_number);
964 labels(1) =
"Elitism size";
969 labels(2) =
"Mutation rate";
974 labels(3) =
"Selection loss goal";
979 labels(4) =
"Maximum Generations number";
984 labels(5) =
"Maximum time";
987 string_matrix.chip(0, 1) = labels;
988 string_matrix.chip(1, 1) = values;
990 return string_matrix;
1002 ostringstream buffer;
1004 file_stream.OpenElement(
"GeneticAlgorithm");
1008 file_stream.OpenElement(
"PopulationSize");
1011 buffer << individuals_number;
1013 file_stream.
PushText(buffer.str().c_str());
1019 file_stream.OpenElement(
"ElitismSize");
1024 file_stream.
PushText(buffer.str().c_str());
1030 file_stream.OpenElement(
"MutationRate");
1035 file_stream.
PushText(buffer.str().c_str());
1041 file_stream.OpenElement(
"SelectionErrorGoal");
1046 file_stream.
PushText(buffer.str().c_str());
1052 file_stream.OpenElement(
"MaximumGenerationsNumber");
1057 file_stream.
PushText(buffer.str().c_str());
1063 file_stream.OpenElement(
"MaximumTime");
1068 file_stream.
PushText(buffer.str().c_str());
1085 ostringstream buffer;
1087 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
1088 <<
"void from_XML(const tinyxml2::XMLDocument&) method.\n"
1089 <<
"GeneticAlgorithm element is nullptr.\n";
1091 throw logic_error(buffer.str());
1100 const Index new_population_size =
static_cast<Index
>(atoi(element->GetText()));
1106 catch(
const logic_error& e)
1108 cerr << e.what() << endl;
1119 const type new_mutation_rate =
static_cast<type
>(atof(element->GetText()));
1125 catch(
const logic_error& e)
1127 cerr << e.what() << endl;
1138 const Index new_elitism_size =
static_cast<Index
>(atoi(element->GetText()));
1144 catch(
const logic_error& e)
1146 cerr << e.what() << endl;
1157 const string new_display = element->GetText();
1163 catch(
const logic_error& e)
1165 cerr << e.what() << endl;
1176 const type new_selection_error_goal =
static_cast<type
>(atof(element->GetText()));
1182 catch(
const logic_error& e)
1184 cerr << e.what() << endl;
1191 const tinyxml2::XMLElement* element = root_element->FirstChildElement(
"MaximumGenerationsNumber");
1195 const Index new_maximum_epochs_number =
static_cast<Index
>(atoi(element->GetText()));
1201 catch(
const logic_error& e)
1203 cerr << e.what() << endl;
1214 const type new_maximum_correlation =
static_cast<type
>(atof(element->GetText()));
1220 catch(
const logic_error& e)
1222 cerr << e.what() << endl;
1233 const type new_minimum_correlation =
static_cast<type
>(atof(element->GetText()));
1239 catch(
const logic_error& e)
1241 cerr << e.what() << endl;
1252 const type new_maximum_time = type(atoi(element->GetText()));
1258 catch(
const logic_error& e)
1260 cerr << e.what() << endl;
1267void GeneticAlgorithm::print()
const
1269 cout <<
"Genetic algorithm" << endl;
1271 cout <<
"Genes number: " << get_genes_number() << endl;
1280 FILE * file = fopen(file_name.c_str(),
"w");
1299 if(document.LoadFile(file_name.c_str()))
1301 ostringstream buffer;
1303 buffer <<
"OpenNN Exception: GeneticAlgorithm class.\n"
1304 <<
"void load(const string&) method.\n"
1305 <<
"Cannot load XML file " << file_name <<
".\n";
1307 throw logic_error(buffer.str());
This class represents the concept of a data set for data modelling problems, such as approximation,...
Tensor< Descriptives, 1 > calculate_input_variables_descriptives() const
Tensor< Index, 1 > get_target_columns_indices() const
Returns a indices vector with the positions of the targets.
Tensor< Index, 1 > get_input_columns_indices() const
Returns a indices vector with the positions of the inputs.
Index get_input_variables_number() const
Tensor< string, 1 > get_input_columns_names() const
Returns a string vector that contains the names of the columns whose uses are Input.
Tensor< string, 1 > get_input_variables_names() const
Index get_input_columns_number() const
Returns the number of columns whose uses are Input.
Tensor< bool, 2 > population
Population matrix.
void set_individuals_number(const Index &)
void set_fitness(const Tensor< type, 1 > &)
void from_XML(const tinyxml2::XMLDocument &)
void set_default()
Sets the members of the genetic algorithm object to their default values.
void set_elitism_size(const Index &)
Tensor< Tensor< type, 1 >, 1 > parameters
Performance of population.
void load(const string &)
virtual ~GeneticAlgorithm()
Destructor.
Tensor< string, 2 > to_string_matrix() const
InputsSelectionResults perform_inputs_selection()
Select the inputs with best generalization properties using the genetic algorithm.
void evaluate_population()
GeneticAlgorithm()
Default constructor.
const Index & get_elitism_size() const
Returns the size of the elite in the selection.
void perform_fitness_assignment()
Calculate the fitness with the errors depending on the fitness assignment method.
void perform_selection()
Selects for crossover some individuals from the population.
void perform_mutation()
Perform the mutation of the individuals generated in the crossover.
void save(const string &) const
Index get_individuals_number() const
Returns the size of the population.
void set_mutation_rate(const type &)
void write_XML(tinyxml2::XMLPrinter &) const
const type & get_mutation_rate() const
Returns the rate used in the mutation.
const Tensor< type, 1 > & get_fitness() const
Returns the fitness of the population.
const Tensor< bool, 2 > & get_population() const
Returns the population matrix.
Tensor< type, 1 > fitness
Fitness of population.
void set_population(const Tensor< bool, 2 > &)
void initialize_population()
Initialize the population depending on the intialization method.
void perform_crossover()
Perform the crossover depending on the crossover method.
This abstract class represents the concept of loss index composed of an error term and a regularizati...
NeuralNetwork * get_neural_network_pointer() const
Returns a pointer to the neural network object associated to the error term.
DataSet * get_data_set_pointer() const
Returns a pointer to the data set object associated to the error term.
This class represents the concept of neural network in the OpenNN library.
ScalingLayer * get_scaling_layer_pointer() const
Returns a pointer to the scaling layers object composing this neural network object.
bool has_scaling_layer() const
const Tensor< string, 1 > & get_inputs_names() const
Returns a string vector with the names of the variables used as inputs.
void set_inputs_number(const Index &)
void set_parameters(Tensor< type, 1 > &)
void set_parameters_random()
void set_inputs_names(const Tensor< string, 1 > &)
Tensor< type, 1 > get_parameters() const
void set()
Sets the scaling layer to be empty.
This class represents the concept of training strategy for a neural network in OpenNN.
TrainingResults perform_training()
LossIndex * get_loss_index_pointer()
Returns a pointer to the LossIndex class.
void set_display(const bool &)
DataSet * get_data_set_pointer()
Returns a pointer to the DataSet class.
void PushText(const char *text, bool cdata=false)
Add a text node.
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.
This structure contains the optimization algorithm results.