Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
e69fc71
Removing c++20 features unsupported by GCC versions < 12.2
jkarns275 Jan 30, 2023
903dcfb
Fix minimum c++ requirement in CMakeLists.txt to be compatible with G…
Jan 30, 2023
09c5cbc
properly specify minimum CMake version
Jan 30, 2023
8e150e9
Merge conflicts
Jan 30, 2023
8ec09ca
Fixed bug introduced during merge
Jan 30, 2023
2aec52c
Merge conflicts
Jan 30, 2023
1c9bcff
Tweaking for clusteR
Jan 31, 2023
9c6be46
Added updated cluster instructions to the README.md
Jan 31, 2023
d7023b6
Updated format script
jkarns275 Jan 31, 2023
89b3410
Formatting
jkarns275 Jan 31, 2023
cbf7574
Added OpenMPI package to cluster instructions
Jan 31, 2023
c6a3697
Merge branch 'dnas' of github.com:travisdesell/exact into dnas
Feb 2, 2023
06f12b5
Adding argument parsing for DNAS
jkarns275 Feb 7, 2023
ad5a7a3
Formatting
jkarns275 Feb 9, 2023
eda79a0
Committing experiment scripts
jkarns275 Apr 12, 2023
cd597a4
Commit for AISTATS results
jkarns275 Sep 20, 2023
fa03e78
Preparing for gecco 2024 experiments
jkarns275 Dec 13, 2023
c0264d9
Tweak experimental parameters
jkarns275 Dec 13, 2023
1607c26
Tweaking experiments
Dec 26, 2023
778d24a
Modified scripts
jkarns275 Jan 8, 2024
ffa684a
Prepping for cluster
jkarns275 Jan 30, 2024
60acb2c
gecco 2024 related experiment files + hacky changes
Jan 31, 2024
5730472
BP schedule
Feb 2, 2024
70e79d4
moving scripts
Feb 19, 2024
4c3ebfc
removed old fileS
Feb 19, 2024
c0b9e41
removed old fileS
jkarns275 Feb 19, 2024
438d996
Merge branch 'dnas' of github.com:travisdesell/exact into dnas
jkarns275 Feb 19, 2024
79df69a
Fixed bug caused by accidental paste
jkarns275 Feb 19, 2024
6875246
Synchronous EXAMM flag added --sychronous
jkarns275 Feb 19, 2024
a600606
Adding additional log information
jkarns275 Feb 24, 2024
72ce5d4
Additional log data
jkarns275 Feb 29, 2024
5949736
Cluster script updates
Mar 6, 2024
ff78fa2
merge from remote
jkarns275 Mar 6, 2024
ff155b8
Merge and introduce node_t for typed node enumeration
jkarns275 Mar 12, 2024
89d19a7
Merge with main
jkarns275 Mar 13, 2024
9527715
Remove scripts in root directory
jkarns275 Mar 13, 2024
fbb32b2
Remove junk file
jkarns275 Mar 13, 2024
217e5be
First stage of removing old-style architectural hashes
jkarns275 Mar 18, 2024
ed5ad17
Add annealing policy
jkarns275 Mar 18, 2024
7f9686b
Clang format
jkarns275 Mar 18, 2024
9c0ec5b
Initial implementation
jkarns275 Mar 18, 2024
050e278
Clang format
jkarns275 Mar 18, 2024
e59c649
Finishing touches
jkarns275 Mar 20, 2024
19f43fe
Format
jkarns275 Mar 20, 2024
3bfc9fa
add ability to specify delimiter for CSV inputs
aidanlabella Apr 3, 2024
d665e84
add script for new delimiter option
aidanlabella Apr 4, 2024
a5fdba9
Write island best to disk
jkarns275 Apr 5, 2024
28fe832
Update build for native optimization
jkarns275 Apr 9, 2024
4e477a2
Merge branch 'josh/simulated-annealing' of github.com:travisdesell/ex…
aidanlabella Apr 18, 2024
99fda86
add scripts for training/evolution with NASA merra
aidanlabella May 3, 2024
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
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 2 This line for cluster
#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")
# SET (CMAKE_CXX_FLAGS " -Wall -O3 -funroll-loops -msse3 -fsanitize=address")
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
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ Update the code format before start a pull request with:
~/exact $ sh scripts/util/format.sh
```


You may also want to have graphviz installed so you can generate images of the evolved neural networks. EXACT/EXALT/EXAMM will write out evolved genomes in a .gv (graphviz) format for this. For example, can generate a pdf from a gv file (assuming graphviz is installed with):

```
Expand Down
2 changes: 2 additions & 0 deletions common/files.hxx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef EXACT_BOINC_COMMON_HXX
#define EXACT_BOINC_COMMON_HXX

#include <stdint.h>

#include <stdexcept>
using std::runtime_error;

Expand Down
8 changes: 4 additions & 4 deletions common/log.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ int8_t Log::parse_level_from_string(string level) {
void Log::initialize(const vector<string>& arguments) {
// TODO: should read these from the CommandLine (to be created)

string std_message_level_str, file_message_level_str;
string std_message_level_str = "INFO", file_message_level_str = "NONE";

get_argument(arguments, "--std_message_level", true, std_message_level_str);
get_argument(arguments, "--file_message_level", true, file_message_level_str);
get_argument(arguments, "--output_directory", true, output_directory);
get_argument(arguments, "--std_message_level", false, std_message_level_str);
get_argument(arguments, "--file_message_level", false, file_message_level_str);
get_argument(arguments, "--output_directory", false, output_directory);

std_message_level = parse_level_from_string(std_message_level_str);
file_message_level = parse_level_from_string(file_message_level_str);
Expand Down
16 changes: 10 additions & 6 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 Expand Up @@ -189,10 +193,10 @@ void get_train_validation_data(
time_series_sets->export_training_series(time_offset, train_inputs, train_outputs);
time_series_sets->export_test_series(time_offset, validation_inputs, validation_outputs);

int32_t sequence_length = 0;
if (get_argument(arguments, "--train_sequence_length", false, sequence_length)) {
Log::info("Slicing input training data with time sequence length: %d\n", sequence_length);
slice_input_data(train_inputs, train_outputs, sequence_length);
int32_t train_sequence_length = 0;
if (get_argument(arguments, "--train_sequence_length", false, train_sequence_length)) {
Log::info("Slicing input training data with time sequence length: %d\n", train_sequence_length);
slice_input_data(train_inputs, train_outputs, train_sequence_length);
}

int32_t validation_sequence_length = 0;
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)
86 changes: 86 additions & 0 deletions examm/annealing.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#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::operator()(int32_t genome_number) {
return 0.0;
}

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::operator()(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::operator()(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::operator()(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);
}
65 changes: 65 additions & 0 deletions examm/annealing.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#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 operator()(int32_t genome_number);
};

/**
* 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);

virtual double operator()(int32_t genome_number);
};

/**
* 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);

virtual double operator()(int32_t genome_number);
};

/**
* 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);

virtual double operator()(int32_t genome_number);
};
55 changes: 40 additions & 15 deletions examm/examm.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,10 @@ void EXAMM::generate_log() {
Log::info("Generating fitness log\n");
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";
(*log_file
) << "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 @@ -152,7 +154,7 @@ void EXAMM::update_op_log_statistics(RNN_Genome* genome, int32_t insert_position
}
}

void EXAMM::update_log() {
void EXAMM::update_log(RNN_Genome* genome) {
if (log_file != NULL) {
// make sure the log file is still good
if (!log_file->good()) {
Expand Down Expand Up @@ -183,17 +185,27 @@ void EXAMM::update_log() {
}
(*op_log_file) << endl;
}

RNN_Genome* best_genome = get_best_genome();
if (best_genome == NULL) {
best_genome = speciation_strategy->get_global_best_genome();
}

std::chrono::time_point<std::chrono::system_clock> currentClock = std::chrono::system_clock::now();
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()
<< speciation_strategy->get_strategy_information_values() << 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(),
best_genome->get_enabled_recurrent_edge_count()
);
}
}

Expand Down Expand Up @@ -246,15 +258,17 @@ bool EXAMM::insert_genome(RNN_Genome* genome) {

// updates EXAMM's mapping of which genomes have been generated by what
genome->update_generation_map(generated_from_map);
pre_insert_best_mse = this->get_best_fitness();

int32_t insert_position = speciation_strategy->insert_genome(genome);
Log::info("insert to speciation strategy complete, at position: %d\n", insert_position);

// 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!");
Expand All @@ -264,16 +278,26 @@ bool EXAMM::insert_genome(RNN_Genome* genome) {
}
Log::info("save genome complete\n");

last_genome_inserted = insert_position >= 0;

speciation_strategy->print();
Log::info("printed speciation strategy!\n\n");

update_op_log_statistics(genome, insert_position);
update_log();
return insert_position >= 0;
update_log(genome);

return last_genome_inserted;
}

// 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 Expand Up @@ -314,7 +338,7 @@ RNN_Genome* EXAMM::generate_genome() {
return genome;
}

int32_t EXAMM::get_random_node_type() {
node_t EXAMM::get_random_node_type() {
return possible_node_types[rng_0_1(generator) * possible_node_types.size()];
}

Expand Down Expand Up @@ -354,7 +378,8 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) {

g->assign_reachability();
double rng = rng_0_1(generator) * total;
int32_t new_node_type = get_random_node_type();
node_t new_node_type = get_random_node_type();
Log::info("%d %d\n", new_node_type, NODE_TYPES.size());
string node_type_str = NODE_TYPES[new_node_type];
Log::debug("rng: %lf, total: %lf, new node type: %d (%s)\n", rng, total, new_node_type, node_type_str.c_str());

Expand Down
Loading