Skip to content

Commit

Permalink
Adding first version of genetic search algorithm based on random
Browse files Browse the repository at this point in the history
  • Loading branch information
khuck committed Apr 12, 2024
1 parent 652ec16 commit bf5a820
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/apex/genetic_search.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include "genetic_search.hpp"
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>

namespace apex {

namespace random {

double inline myrand() {
return ((double) rand() / (RAND_MAX));
}

size_t GeneticSearch::get_max_iterations() {
size_t max_iter{1};
for (auto& v : vars) {
switch (v.second.vtype) {
case VariableType::doubletype: {
max_iter = max_iter * v.second.dvalues.size();
break;
}
case VariableType::longtype: {
max_iter = max_iter * v.second.lvalues.size();
break;
}
case VariableType::stringtype: {
max_iter = max_iter * v.second.svalues.size();
break;
}
default: {
break;
}
}
}
// want to see multiple values of each one
//return max_iter;
return std::min(max_iterations, (std::max(min_iterations, max_iter)));
}

class log_wrapper {
private:
std::ofstream myfile;
public:
log_wrapper(const std::map<std::string, Variable>& vars) {
myfile.open("tuning.csv");
myfile << "iter,";
for (auto& v : vars) { myfile << v.first << ","; }
myfile << "time" << std::endl;
}
~log_wrapper() {
myfile.close();
}
std::ofstream& getstream() {
return myfile;
}
};

void GeneticSearch::evaluate(double new_cost) {
static log_wrapper log(vars);
static size_t count{0};
if (++count % 10000 == 0) { std::cout << count << std::endl; }
log.getstream() << count << ",";
for (auto& v : vars) { log.getstream() << v.second.toString() << ","; }
log.getstream() << new_cost << std::endl;
if (new_cost < cost) {
if (new_cost < best_cost) {
best_cost = new_cost;
std::cout << "New best! " << new_cost << " k: " << k;
for (auto& v : vars) { v.second.save_best(); }
for (auto& v : vars) { std::cout << ", value: " << v.second.toString(); }
std::cout << std::endl;
}
cost = new_cost;
}
//for (auto& v : vars) { v.second.choose_neighbor(); }
k++;
return;
}

} // random

} // apex


132 changes: 132 additions & 0 deletions src/apex/genetic_search.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#pragma once
#include <vector>
#include <string>
#include <iostream>
#include <cstdint>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <random>
#include <limits>
#include <map>
#include "apex_types.h"
#include "apex_assert.h"

namespace apex {

namespace random {

enum class VariableType { doubletype, longtype, stringtype } ;

class Variable {
public:
std::vector<double> dvalues;
std::vector<long> lvalues;
std::vector<std::string> svalues;
VariableType vtype;
size_t current_index;
size_t best_index;
void * value; // for the client to get the values
size_t maxlen;
Variable () = delete;
Variable (VariableType vtype, void * ptr) : vtype(vtype), current_index(0),
best_index(0), value(ptr), maxlen(0) { }
void set_current_value() {
if (vtype == VariableType::doubletype) {
*((double*)(value)) = dvalues[current_index];
}
else if (vtype == VariableType::longtype) {
*((long*)(value)) = lvalues[current_index];
}
else {
*((const char**)(value)) = svalues[current_index].c_str();
}
}
size_t get_next_neighbor() {
current_index = (rand() % maxlen);
APEX_ASSERT(current_index < maxlen);
set_current_value();
return current_index;
}
void save_best() { best_index = current_index; }
void set_init() {
maxlen = (std::max(std::max(dvalues.size(),
lvalues.size()), svalues.size())) - 1;
current_index = 0;
set_current_value();
}
std::string getBest() {
if (vtype == VariableType::doubletype) {
*((double*)(value)) = dvalues[best_index];
return std::to_string(dvalues[best_index]);
}
else if (vtype == VariableType::longtype) {
*((long*)(value)) = lvalues[best_index];
return std::to_string(lvalues[best_index]);
}
//else if (vtype == VariableType::stringtype) {
*((const char**)(value)) = svalues[best_index].c_str();
return svalues[best_index];
}
std::string toString() {
if (vtype == VariableType::doubletype) {
return std::to_string(dvalues[current_index]);
}
else if (vtype == VariableType::longtype) {
return std::to_string(lvalues[current_index]);
}
//else if (vtype == VariableType::stringtype) {
return svalues[current_index];
//}
}
};

class GeneticSearch {
private:
double cost;
double best_cost;
size_t kmax;
size_t k;
std::map<std::string, Variable> vars;
const size_t max_iterations{1000};
const size_t min_iterations{100};
public:
void evaluate(double new_cost);
GeneticSearch() :
kmax(0), k(1) {
cost = std::numeric_limits<double>::max();
best_cost = cost;
//std::cout << "New Session!" << std::endl;
//srand (1);
srand (time(NULL));
}
double getEnergy() { return best_cost; }
bool converged() { return (k > kmax); }
void getNewSettings() {
/* Increment neighbour */
for (auto& v : vars) { v.second.get_next_neighbor(); }
}
void saveBestSettings() {
for (auto& v : vars) { v.second.getBest(); }
}
void printBestSettings() {
std::string d("[");
for (auto v : vars) {
std::cout << d << v.second.getBest();
d = ",";
}
std::cout << "]" << std::endl;
}
size_t get_max_iterations();
std::map<std::string, Variable>& get_vars() { return vars; }
void add_var(std::string name, Variable var) {
vars.insert(std::make_pair(name, var));
kmax = get_max_iterations();
/* get max iterations */
//std::cout << "Max iterations : " << kmax << std::endl;
}
};

} // random

} // apex

0 comments on commit bf5a820

Please sign in to comment.