Purpose
Find an such that the return value of is maximized in the domain . This is Simulated Annealing.
Time Complexity
Usage
Declaration
struct State{ // Structure representing the state double x;
// f(x) = -x^4 + x^3 + x^2 + x // max f(x): 2.33.... (x = 1.28...) double eval(){ // Evaluation function return -pow(x,4)+pow(x,3)+pow(x,2)+x; } void modify(){ // State transition x += ((double)rand() / (RAND_MAX))-0.5; }};
ESAnnealing<State> sa;// Initialize the state inside sasa.state.x=0;Please rewrite the contents of State according to your purpose.
Hyperparameter Setup & Annealing
// (trials per epoch, initial temperature, target temperature, cooling coefficient)sa.annealing(100,100000,0.1,0.99);Result Reference
// The result can be referenced by 'state' in the classstd::cout << "Solution: " << "f(x) = " << sa.state.eval() << ", x = " << sa.state.x << std::endl;Implementation
template <class T>class ESAnnealing{public: T state;
void annealing(double epoch, double temperature, double temperature_target, double coolingcoef, unsigned int seed = 42, bool verbose = true) { assert(0 <= coolingcoef and coolingcoef < 1); assert(temperature >= temperature_target); srand(seed); double initscore = state.eval(); double beststate_score = initscore; T beststate = state; int estimeted_epoch = std::ceil((std::log(temperature_target) - std::log(temperature)) / std::log(coolingcoef)); if (verbose) std::cout << std::fixed << std::setprecision(6) << "ESAnnealing started with:" << "\n" << "| epoch " << epoch << "\n" << "| temperature " << temperature << "\n" << "| target temp " << temperature_target << "\n" << "| coolingcoef " << coolingcoef << "\n" << "| seed " << seed << "\n" << "| est epoch " << estimeted_epoch << "\n" << std::flush; int cnt = 0; while (temperature > temperature_target) { for (int i = 0; i < epoch; i++) { T newstate = state; newstate.modify(); double statescore = state.eval(); double newstatescore = newstate.eval(); double delta = newstatescore - statescore;
if (0 < delta) { state = newstate; } else if (frand() > std::exp(delta / temperature)) { state = newstate; }
if (beststate_score < newstatescore) { beststate_score = newstatescore; beststate = newstate; } } temperature *= coolingcoef;
if (verbose) std::cout << cnt << "/" << estimeted_epoch - 1 << " temp: " << temperature << " eval: " << beststate_score << std::endl;
cnt++; } state = beststate; if (verbose) std::cout << "annealed: " << initscore << "->" << beststate_score << std::endl; }
private: double frand() { return ((double)rand() / (RAND_MAX)); }};from github.com/romophic/ESAnnealing
Verify
//TODO