1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
#include "StdAfx.h"
#include <cmath>
#include ".\simanneal.h"
int ApplySimAnneal(double *chart, int chart_length, int dir, int start, int scatter, int minx)
{
double Tinit = 1;
double minT = 1e-8;
int max_consec_rejections = 1000;
int max_try = 300;
int max_success = 20;
double k = 1;
double Tgrad = 0.8;
int itry = 0;
int parent = start;
int success = 0;
bool finished = false;
int consec = 0;
double T = Tinit;
double initenergy = chart [parent];
double newenergy, oldenergy;
int total = 0;
int current, newparam=0;
oldenergy = chart [0];
while (!finished) {
itry++;
current=parent;
if ((itry >= max_try) || (success >= max_success) || (T < minT) || (consec >= max_consec_rejections)) {
finished = true;
total = total + itry;
break;
}
else {
T = Tgrad*T;
total = total + itry;
itry=1;
success = 1;
}
newparam = current + scatter*rand ();
if (newparam < minx)
newparam = minx;
if (newparam >= chart_length)
newparam = chart_length;
newenergy = chart [newparam];
if ((oldenergy - newenergy)*dir > 1e-6*dir) {
parent = newparam;
oldenergy = newenergy;
success++;
consec = 0;
}
else {
if (rand ()*dir < dir*exp ((oldenergy - newenergy) / (k*T))){
parent = newparam;
oldenergy = newenergy;
success++;
}
else
consec++;
}
}
return parent;
}
int HighestCoincidence(int *values, int count)
{
int coinccount [10];
int coincvalues [10];
int coinctotal = 0;
int i;
for (i = 0; i < count; i++){
bool coincfound = false;
for (int j = 0; j < coinctotal; j++)
if (values [i] == coincvalues [j]){
coinccount [j]++;
coincfound = true;
}
if (!coincfound) {
coincvalues [coinctotal] = values [i];
coinctotal ++;
}
}
int maxcoinc = 0;
for (i = 1; i < coinctotal; i++)
if (coinccount [i] > coinccount [maxcoinc])
i = maxcoinc;
return coincvalues [maxcoinc];
}
int RepeatSA(double * chart, int chart_length, int dir, int start, int scatter, int minx)
{
int sa_results [9];
for (int i = 0; i < 9; i++)
sa_results [i] = ApplySimAnneal (chart, chart_length, dir, start, scatter, minx);
return HighestCoincidence (sa_results, 9);
}
int SeparateChart(double * chart, int * result, int chart_length, int nvs, int scatter)
{
int dir, current = 0;
int total = 0;
if (RepeatSA (chart, chart_length, 1, nvs, scatter, 0) > RepeatSA (chart, chart_length, -1, nvs, scatter, 0))
dir = -1;
else
dir = 1;
while (current + nvs < chart_length){
current = RepeatSA(chart, chart_length, dir, current + nvs, scatter, current);
dir = -dir;
result [total] = current;
total++;
}
return total;
}
|