Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
#SET (CMAKE_CXX_FLAGS "-std=gnu++17 -Wall -O3 -funroll-loops -msse3 -fno-omit-frame-pointer -D_GLIBCXX_DEBUG")

# SET (CMAKE_CXX_FLAGS " -Wall -O3 -funroll-loops -msse3 -fsanitize=address")
SET (CMAKE_CXX_FLAGS " -Wall -O3 -funroll-loops -msse3")
SET (CMAKE_CXX_FLAGS " -Wall -march=native -O3")
#SET (CMAKE_CXX_FLAGS " -Wall -O1 -funroll-loops -msse3 -g -fsanitize=address -fno-omit-frame-pointer -shared-libasan -DGLIBCXX_DEBUG")
#SET (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -g")
#SET (CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS} -Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O4 -funroll-loops -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -DNDEBUG")

#SET (CMAKE_SHARED_LINKER_FLAGS " -Wall -O1 -funroll-loops -msse3 -g -fsanitize=address -fno-omit-frame-pointer -shared-libasan -DGLIBCXX_DEBUG")

Expand Down
8 changes: 6 additions & 2 deletions common/process_arguments.cxx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <memory>
#include <string>
using std::string;

Expand Down Expand Up @@ -120,12 +121,15 @@ IslandSpeciationStrategy* generate_island_speciation_strategy_from_arguments(
get_argument(arguments, "--seed_stirs", false, seed_stirs);
bool start_filled = argument_exists(arguments, "--start_filled");
bool tl_epigenetic_weights = argument_exists(arguments, "--tl_epigenetic_weights");
unique_ptr<AnnealingPolicy> annealing_policy = AnnealingPolicy::from_arguments(arguments);
string output_directory = "";
get_argument(arguments, "--output_directory", false, output_directory);

IslandSpeciationStrategy* island_strategy = new IslandSpeciationStrategy(
number_islands, island_size, mutation_rate, intra_island_co_rate, inter_island_co_rate, seed_genome,
number_islands, island_size, mutation_rate, intra_island_co_rate, inter_island_co_rate, output_directory, seed_genome,
island_ranking_method, repopulation_method, extinction_event_generation_number, num_mutations,
islands_to_exterminate, max_genomes, repeat_extinction, start_filled, transfer_learning,
transfer_learning_version, seed_stirs, tl_epigenetic_weights
transfer_learning_version, tl_epigenetic_weights, annealing_policy
);

return island_strategy;
Expand Down
2 changes: 1 addition & 1 deletion examm/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
add_library(examm_strategy examm.cxx species.cxx island.cxx island_speciation_strategy.cxx species.cxx neat_speciation_strategy.cxx)
add_library(examm_strategy examm.cxx species.cxx island.cxx island_speciation_strategy.cxx species.cxx neat_speciation_strategy.cxx annealing.cxx)
106 changes: 106 additions & 0 deletions examm/annealing.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include "annealing.hxx"

#include <cmath>
#include <memory>

#include "common/arguments.hxx"
#include "common/log.hxx"

unique_ptr<AnnealingPolicy> AnnealingPolicy::from_arguments(const vector<string>& arguments) {
string type;
get_argument(arguments, "--annealing_policy", false, type);
Log::info("Annealing policy = %s\n", type.c_str());
if (type == "linear") {
return unique_ptr<AnnealingPolicy>(new LinearAnnealingPolicy(arguments));
} else if (type == "inv_exp") {
return unique_ptr<AnnealingPolicy>(new InvExpAnnealingPolicy(arguments));
} else if (type == "sin") {
return unique_ptr<AnnealingPolicy>(new SinAnnealingPolicy(arguments));
} else {
Log::info("Using default annealing policy\n");
return make_unique<AnnealingPolicy>();
}
}

double AnnealingPolicy::get_temperature(int32_t genome_number) {
return 0.0;
}

double AnnealingPolicy::operator()(int32_t genome_number, double population_worst_cost, double candidate_cost) {
double temperature = get_temperature(genome_number);

if (fpclassify(temperature) == FP_ZERO || temperature < 0) {
return 0.0;
}

if (population_worst_cost > candidate_cost)
return 1.0;

population_worst_cost = sqrt(population_worst_cost);
candidate_cost = sqrt(candidate_cost);

double denom = population_worst_cost + candidate_cost;
double relative_cost = population_worst_cost / denom - candidate_cost / denom;

// exp((eworst - ecandidate) / T)
double de = exp(-(candidate_cost / (population_worst_cost * temperature)));
}

LinearAnnealingPolicy::LinearAnnealingPolicy(
double start_value, double end_value, int32_t start_genomes, int32_t interp_genomes
)
: start_value(start_value), end_value(end_value), start_genomes(start_genomes), interp_genomes(interp_genomes) {
}

LinearAnnealingPolicy::LinearAnnealingPolicy(const vector<string>& arguments) {
get_argument(arguments, "--linear_start_value", true, start_value);
get_argument(arguments, "--linear_end_value", true, end_value);
get_argument(arguments, "--linear_start_genomes", true, start_genomes);
get_argument(arguments, "--linear_interp_genomes", true, interp_genomes);
}

double LinearAnnealingPolicy::get_temperature(int32_t genome_number) {
if (genome_number <= start_genomes) {
return start_value;
} else if (genome_number <= interp_genomes + start_genomes) {
double weight = (double) (genome_number - (interp_genomes + start_genomes)) / (double) interp_genomes;
return weight * end_value + (1 - weight) * start_value;
} else {
return end_value;
}
}

InvExpAnnealingPolicy::InvExpAnnealingPolicy(double decay_factor) : decay_factor(decay_factor) {
}
InvExpAnnealingPolicy::InvExpAnnealingPolicy(const vector<string>& arguments) {
get_argument(arguments, "--exp_decay_factor", true, decay_factor);
}

double InvExpAnnealingPolicy::get_temperature(int32_t genome_number) {
return std::pow(1. + genome_number, -decay_factor);
}

SinAnnealingPolicy::SinAnnealingPolicy(double period, double min_p, double max_p)
: period(period), min_p(min_p), max_p(max_p) {
if (min_p > max_p) {
std::swap(min_p, max_p);
}

if (min_p > 1.0 || min_p < 0.0) {
throw "Invalid min_p supplied to SinAnnealingPolicyConstructor";
}
if (max_p > 1.0 || max_p < 0.0) {
throw "Invalid max_p supplied to SinAnnealingPolicyConstructor";
}
}
SinAnnealingPolicy::SinAnnealingPolicy(const vector<string>& arguments) {
get_argument(arguments, "--sin_min_p", true, min_p);
get_argument(arguments, "--sin_max_p", true, max_p);
get_argument(arguments, "--sin_period", true, period);
}

double SinAnnealingPolicy::get_temperature(int32_t genome_number) {
double range = max_p - min_p;

return (max_p + min_p) / 2. + range / 2. * std::sin(2. * M_PI * genome_number / period);
}
67 changes: 67 additions & 0 deletions examm/annealing.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <stdint.h>

#include <memory>
using std::unique_ptr;

#include <string>
using std::string;

#include <vector>
using std::vector;

struct AnnealingPolicy {
static unique_ptr<AnnealingPolicy> from_arguments(const vector<string>& arguments);

/**
* Compute the probability to be used during genome insertion.
* This represents the probability of inserting the genome, even if it
* has a fitness value that is worse than the worst member in the population.
*/
virtual double get_temperature(int32_t genome_number);

double operator()(int32_t genome_number, double population_worst_cost, double candidate_cost);
};

/**
* Interpolate between two values for a set number of genomes.
* The `start_value` will be returned for `start_genomes`,
* then a linear interpolation of `start_value` and `end_value` for
* `interp_genomes`. Then, `end_value` is given indefinitely.
*/
class LinearAnnealingPolicy : public AnnealingPolicy {
double start_value, end_value;
int32_t start_genomes, interp_genomes;

public:
LinearAnnealingPolicy(double start_value, double end_value, int32_t start_genomes, int32_t interp_genomes);
LinearAnnealingPolicy(const vector<string>& arguments);

double get_temperature(int32_t genome_number) override;
};

/**
* Calculates p by simply computing `genome_number^(-decay_factor).
**/
class InvExpAnnealingPolicy : public AnnealingPolicy {
double decay_factor;

public:
InvExpAnnealingPolicy(double decay_factor);
InvExpAnnealingPolicy(const vector<string>& arguments);

double get_temperature(int32_t genome_number) override;
};

/**
* Computes `p` as a value falling on a sinusoidal curve with the supplied period.
* a `min_p` and a `max_p` specify the range of the curve.
**/
class SinAnnealingPolicy : public AnnealingPolicy {
double period, min_p, max_p;

public:
SinAnnealingPolicy(double period, double min_p, double max_p);
SinAnnealingPolicy(const vector<string>& arguments);

double get_temperature(int32_t genome_number) override;
};
34 changes: 23 additions & 11 deletions examm/examm.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ void EXAMM::generate_log() {
mkpath(output_directory.c_str(), 0777);
log_file = new ofstream(output_directory + "/" + "fitness_log.csv");
(*log_file
) << "Inserted Genomes,Total BP Epochs,Time,Best Val. MAE,Best Val. MSE,Enabled Nodes,Enabled"
"Edges,Enabled Rec. Edges,Val. MSE,Pre-Insert MSE,Genome Inserted,Trainable Parameters,Island Id";
) << "Inserted Genomes,Total BP Epochs,Time,Best Val. MAE,Best Val. MSE,Trainable Parameters,Enabled "
"Nodes,Enabled"
"Edges,Enabled Rec. Edges,Val. MSE,Pre-Insert MSE,Genome Inserted,Genome Trainable Parameters,Island Id";
(*log_file) << speciation_strategy->get_strategy_information_headers();
(*log_file) << endl;

Expand Down Expand Up @@ -194,11 +195,12 @@ void EXAMM::update_log(RNN_Genome* genome) {
long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(currentClock - startClock).count();
(*log_file) << speciation_strategy->get_evaluated_genomes() << "," << total_bp_epochs << "," << milliseconds
<< "," << best_genome->best_validation_mae << "," << best_genome->best_validation_mse << ","
<< best_genome->get_enabled_node_count() << "," << best_genome->get_enabled_edge_count() << ","
<< best_genome->get_enabled_recurrent_edge_count() << "," << genome->best_validation_mse << ","
<< pre_insert_best_mse << "," << (int32_t) (last_genome_inserted ? 1 : 0) << ","
<< genome->get_number_weights() << "," << genome->get_generation_id()
<< speciation_strategy->get_strategy_information_values(genome) << endl;
<< best_genome->get_number_weights() << "," << best_genome->get_enabled_node_count() << ","
<< best_genome->get_enabled_edge_count() << "," << best_genome->get_enabled_recurrent_edge_count()
<< "," << genome->best_validation_mse << "," << pre_insert_best_mse << ","
<< (int32_t) (last_genome_inserted ? 1 : 0) << "," << genome->get_number_weights() << ","
<< genome->get_generation_id() << speciation_strategy->get_strategy_information_values(genome)
<< endl;
Log::info(
"mse: %f node count: %d edge count: %d rec edges: %d\n", best_genome->best_validation_mse,
best_genome->get_enabled_node_count(), best_genome->get_enabled_edge_count(),
Expand Down Expand Up @@ -263,16 +265,18 @@ bool EXAMM::insert_genome(RNN_Genome* genome) {

// write this genome to disk if it was a new best found genome
if (save_genome_option.compare("all_best_genomes") == 0) {
Log::info("save genome option compared, save genome option size: %d!\n", save_genome_option.size());
for (int i = 0; i < 20 && i < save_genome_option.size(); i++) {
cout << "save_genome_option[" << i << "]: " << save_genome_option[i] << endl;
}
// Log::info("save genome option compared, save genome option size: %d!\n", save_genome_option.size());
// for (int i = 0; i < 20 && i < save_genome_option.size(); i++) {
// cout << "save_genome_option[" << i << "]: " << save_genome_option[i] << endl;
// }

if (insert_position == 0) {
Log::info("saving genome!");
save_genome(genome, "rnn_genome");
Log::info("saved genome!");
}
} else if (save_genome_option.compare("all") == 0) {
save_genome(genome, "rnn_genome");
}
Log::info("save genome complete\n");

Expand All @@ -288,6 +292,14 @@ bool EXAMM::insert_genome(RNN_Genome* genome) {

// write function to save genomes to file
void EXAMM::save_genome(RNN_Genome* genome, string genome_name = "rnn_genome") {
if (genome->get_fitness() != EXAMM_MAX_DOUBLE) {
// need to set the weights for non-initial genomes so we
// can generate a proper graphviz file
vector<double> best_parameters = genome->get_best_parameters();
genome->set_weights(best_parameters);
Log::info("set genome parameters to best\n");
}

genome->write_graphviz(output_directory + "/" + genome_name + "_" + to_string(genome->get_generation_id()) + ".gv");
ofstream equations_filestream(
output_directory + "/" + genome_name + "_" + to_string(genome->get_generation_id()) + ".txt"
Expand Down
5 changes: 2 additions & 3 deletions examm/examm.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,15 @@ class EXAMM {
map<string, int32_t> inserted_counts;
map<string, int32_t> generated_counts;

string output_directory;
const string output_directory;
ofstream* log_file;
ofstream* op_log_file;
double pre_insert_best_mse = 1000000;
bool last_genome_inserted = false;

std::chrono::time_point<std::chrono::system_clock> startClock;

string genome_file_name;
string save_genome_option;
const string save_genome_option;

public:
EXAMM(
Expand Down
Loading