00001 #include "qscr.h"
00002 #include "siman.h"
00003 #include "linrdist.h"
00004 #include "util.h"
00005 #include <iostream>
00006 #include <cmath>
00007 #include <stdlib.h>
00008 #include <cassert>
00009
00010
00011
00012 SimAnneal::SimAnneal(Function *ff, matrix simplex,
00013 double temptr, unsigned it, double tol, long s,
00014 unsigned steps) {
00015 unsigned n = (*ff).getdim();
00016 assert(simplex.row()==int(n+1) && simplex.column()==int(n));
00017 p = simplex;
00018 funk = ff;
00019 ndim = n;
00020 tt = -temptr;
00021 seed = s;
00022 ftol = tol;
00023 iter = it;
00024 static_iter = it;
00025 nosteps = steps;
00026
00027 psum.newsize(ndim);
00028 calc_psum();
00029
00030 pb.newsize(ndim);
00031 pb = p.getrow(0).trans();
00032 yb = (*funk)(pb);
00033
00034 y.newsize(ndim);
00035 y = pval(p);
00036 }
00037
00038
00039 matrix SimAnneal::pval(matrix const& pp) {
00040 assert(pp.row()==int(ndim+1) && pp.column()==int(ndim));
00041 matrix res(ndim+1);
00042 for (unsigned i=0; i<ndim+1; i++) {
00043 res.set((*funk)(pp.getrow(i).trans()),i);
00044 }
00045 return res;
00046 }
00047
00048
00049 void SimAnneal::calc_psum()
00050 {
00051
00052
00053
00054 for (unsigned j=0;j<ndim;j++) {
00055 double sum = 0.0;
00056 for (unsigned i=0;i<ndim+1;i++)
00057 sum += p.get(i,j);
00058 psum.set(sum,j);
00059 }
00060 }
00061
00062
00063 double SimAnneal::amotsa(int ihi, double &yhi,
00064 double const fac) {
00065
00066
00067
00068 unsigned j;
00069 double fac1, fac2, yflu, ytry;
00070 matrix ptry(ndim);
00071
00072 fac1 = (1.0-fac)/ndim;
00073 fac2 = fac1-fac;
00074 for (j=0; j<ndim; j++) {
00075 double val = psum.get(j)*fac1 - p.get(ihi,j)*fac2;
00076 ptry.set(val,j);
00077 }
00078
00079 ytry = (*funk)(ptry);
00080
00081 if (ytry<=yb) {
00082 for (j=0; j<ndim; j++) {
00083 pb.set(ptry.get(j),j);
00084 }
00085 yb = ytry;
00086 }
00087
00088
00089
00090 yflu = ytry-tt*log(ran1(&seed));
00091 if (yflu<yhi) {
00092 y.set(ytry,ihi);
00093 yhi=yflu;
00094 for (j=0; j<ndim; j++) {
00095 double val = ptry.get(j)-p.get(ihi,j);
00096 psum.set(psum.get(j) + val,j);
00097 p.set(ptry.get(j),ihi,j);
00098 }
00099 }
00100 return yflu;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 void SimAnneal::amebsa() {
00123
00124 unsigned ihi,ilo,mpts=ndim+1;
00125 double rtol, swap, ylo, ynhi, ysave, yt, ytry, yhi;
00126 matrix psum(ndim);
00127 unsigned cnt = 1;
00128 std::string st;
00129
00130
00131 calc_psum();
00132 for (;;) {
00133
00134 st = "Min-value so far=" + numStr(yb) +
00135 " found at ( ";
00136 for (unsigned i=0; i<ndim; i++) {
00137 st += numStr(pb.get(i)) + " ";
00138 }
00139 st += ")";
00140 qmvaddstr(22,5, st.c_str()); qclrtoeol();
00141
00142 switch(cnt) {
00143 case 1:
00144 qmvaddstr(24,5, "---");
00145 break;
00146 case 2:
00147 qmvaddstr(24,5, "
00148 break;
00149 case 3:
00150 qmvaddstr(24,5, "|||");
00151 break;
00152 case 4:
00153 qmvaddstr(24,5, "\\\\\\");
00154 break;
00155 case 5:
00156 qmvaddstr(24,5, "---");
00157 break;
00158 case 6:
00159 qmvaddstr(24,5, "\\\\\\");
00160 break;
00161 case 7:
00162 qmvaddstr(24,5, "|||");
00163 break;
00164 case 8:
00165 qmvaddstr(24,5, "
00166 cnt = 0;
00167 break;
00168 }
00169
00170 cnt++;
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 qmvaddstr(6,55, "Current simplex:");
00181 for (int i=0; i<p.row(); i++) {
00182 qmvaddstr(7+i,56, p.row2string(i)); qclrtoeol();
00183 }
00184 st = "Temperature: " + numStr(-tt);
00185 qmvaddstr(12,55, st.c_str()); qclrtoeol();
00186 st = "Iteration: " + numStr(iter);
00187 qmvaddstr(13,55, st.c_str()); qclrtoeol();
00188
00189
00190
00191
00192 qmove(24,8);
00193
00194 ilo=0;
00195 ihi=1;
00196
00197 ynhi=ylo=y.get(0)+tt*log(ran1(&seed));
00198 yhi=y.get(1)+tt*log(ran1(&seed));
00199 if (ylo>yhi) {
00200 ihi=0;
00201 ilo=1;
00202 swap = ynhi;
00203 ynhi=yhi;
00204 yhi=ylo;
00205 ylo=ynhi;
00206
00207 }
00208 for (unsigned i=2; i<mpts; i++) {
00209 yt=y.get(i)+tt*log(ran1(&seed));
00210 if (yt<=ylo) {
00211 ilo=i;
00212 ylo=yt;
00213 }
00214 if (yt>yhi) {
00215 ynhi=yhi;
00216 ihi=i;
00217 yhi=yt;
00218 } else if (yt>ynhi) {
00219 ynhi = yt;
00220 }
00221 }
00222
00223
00224 rtol = 2.0*fabs(yhi-ylo)/(fabs(yhi)+fabs(ylo));
00225 if (rtol<ftol || iter<0) {
00226
00227 swap=y.get(0);
00228 y.set(y.get(ilo),0);
00229 y.set(swap,ilo);
00230 for (unsigned n=0;n<ndim;n++) {
00231 swap = p.get(0,n);
00232 p.set(p.get(ilo,n),0,n);
00233 p.set(swap,ilo,n);
00234 }
00235 break;
00236 }
00237
00238 iter -= 2;
00239
00240
00241 ytry = amotsa(ihi,yhi,-1.0);
00242 if (ytry<=ylo) {
00243
00244
00245 ytry = amotsa(ihi,yhi,2.0);
00246
00247 } else if (ytry>=ynhi) {
00248
00249
00250 ysave=yhi;
00251 ytry = amotsa(ihi,yhi,0.5);
00252
00253 if (ytry>=ysave) {
00254
00255 for (unsigned i=0;i<mpts;i++) {
00256 if (i != ilo) {
00257 for (unsigned j=0;j<ndim;j++) {
00258 double val = 0.5*(p.get(i,j)+p.get(ilo,j));
00259 psum.set(val,j);
00260 p.set(val,i,j);
00261 }
00262 y.set((*funk)(psum),i);
00263 }
00264 }
00265 iter -= ndim;
00266 calc_psum();
00267 }
00268 } else ++(iter);
00269 }
00270
00271 }
00272
00273 void SimAnneal::optimize() {
00274 amebsa();
00275 iter = static_iter;
00276 }
00277
00278
00279
00280 void SimAnneal::anneal() {
00281 double step = tt/10;
00282 double origtt = tt;
00283 double curtt = tt;
00284 for (unsigned i=0; i<nosteps; i++) {
00285 tt = curtt;
00286 p = newsimplex(pb);
00287 optimize();
00288 curtt -= step;
00289 }
00290 tt = origtt;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299 matrix newsimplex(matrix const& x, double epsilon) {
00300
00301
00302 unsigned nn = x.row();
00303
00304 matrix p(nn+1,nn);
00305 for (unsigned i=0; i<nn; i++) {
00306 p.set(x.get(i),0,i);
00307 }
00308
00309 for (unsigned j=1; j<=nn; j++) {
00310 for (unsigned i=0; i<nn; i++) {
00311 p.set(x.get(i),j,i);
00312 }
00313 p.set(p.get(j,j-1)+epsilon,j,j-1);
00314 }
00315
00316 return p;
00317 }
00318
00319
00320
00321 #ifdef TEST
00322
00323
00324
00325
00326 double f2(matrix const& x) {
00327 double xx = (x.get(0)-1);
00328 double xy = (x.get(1)-1);
00329 return xx*xx+xy*xy;
00330 }
00331
00332
00333 double f1(matrix const& x) {
00334 double xx = x.get(0);
00335 return exp(-pow((xx-1.0),2.0))*sin(8*xx);
00336 }
00337
00338
00339 int main(int argc, char *argv[]) {
00340 try {
00341
00342 qinit();
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 Function FF(f1,1);
00353 matrix simplex(2);
00354 simplex.set(6,0); simplex.set(7,1);
00355
00356
00357
00358
00359
00360 std::cerr << std::endl;
00361
00362 matrix minP_anneal, minP_simplex;
00363 double minV_anneal, minV_simplex;
00364
00365 {
00366 SimAnneal sa(&FF, simplex, 0.01, 500);
00367 sa.anneal();
00368 minP_anneal = sa.get_pb();
00369 minV_anneal = sa.get_yb();
00370 }
00371
00372 std::cerr << "balblablalblaba" << std::endl;
00373 {
00374 SimAnneal sa(&FF, simplex, 0.0, 2000);
00375 sa.optimize();
00376 minP_simplex = sa.get_pb();
00377 minV_simplex = sa.get_yb();
00378 }
00379
00380
00381 std::string line = "";
00382 for (unsigned i=0; i<50; i++)
00383 line += "-";
00384 line += "\n";
00385
00386 qend();
00387
00388
00389 std::cerr << line;
00390 std::cerr << "Minimum found with SA-method " <<
00391 (minP_anneal.trans()).row2string(0) << std::endl;
00392 std::cerr << "With function value " << minV_anneal << std::endl << std::endl;
00393
00394 std::cerr << line;
00395 std::cerr << "Minimum found with Simplex-method " <<
00396 (minP_simplex.trans()).row2string(0) << std::endl;
00397 std::cerr << "With function value " << minV_simplex << std::endl << std::endl;
00398
00399 std::cerr << line;
00400
00401 } catch(std::string const& err) {
00402 std::cerr << err << std::endl;
00403 return 1;
00404 }
00405 return 0;
00406 }
00407
00408
00409
00410 #endif//TEST