00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "simAnn.h"
00027
00028 #include <time.h>
00029
00030 #include "searchState.h"
00031 #include "searchEnergy.h"
00032
00033
00034 #include "debug.h"
00035
00036 #define TINY 1.0e-7
00037
00038 SimAnn::SimAnn()
00039 {
00040 setParameters(ANNEAL_DEFAULT);
00041 mWriteResults = false;
00042 mFile = NULL;
00043
00044 if (mWriteResults) {
00045 } else {
00046 mFile = NULL;
00047 }
00048 mTotalSteps = 0;
00049 }
00050
00051 SimAnn::~SimAnn()
00052 {
00053 if (mWriteResults) fclose(mFile);
00054 }
00055
00056 void
00057 SimAnn::writeResults(bool w)
00058 {
00059 if (w) {
00060 if (mWriteResults) {
00061 DBGA("Sim ann already writing");
00062 return;
00063 }
00064 mFile = fopen("simAnn.txt","a");
00065 mWriteResults = true;
00066 } else {
00067 if (mWriteResults) {
00068 fclose(mFile);
00069 mFile = NULL;
00070 } else {
00071 DBGA("Sim Ann was not writing");
00072 }
00073 mWriteResults = false;
00074 }
00075 }
00076
00077 void SimAnn::setParameters(AnnealingType type)
00078 {
00079 switch (type) {
00080 case ANNEAL_DEFAULT:
00081
00082
00083
00084 YC = 7.0;
00085 HC = 7.0;
00086 YDIMS = 8;
00087 HDIMS = 8;
00088 NBR_ADJ = 1.0;
00089 ERR_ADJ = 1.0e-6;
00090 DEF_T0 = 1.0e6;
00091 DEF_K0 = 30000;
00092 break;
00093 case ANNEAL_LOOP:
00094
00095 YC = 7.0;
00096 HC = 7.0;
00097 YDIMS = 8;
00098 HDIMS = 8;
00099 NBR_ADJ = 1.0;
00100 ERR_ADJ = 1.0e-6;
00101 DEF_T0 = 1.0e6;
00102 DEF_K0 = 35000;
00103 break;
00104 case ANNEAL_MODIFIED:
00105
00106 YC = 2.38;
00107 YDIMS = 8;
00108 HC = 2.38;
00109 HDIMS = 8;
00110 NBR_ADJ = 1.0e-3;
00111 ERR_ADJ = 1.0e-1;
00112 DEF_T0 = 1.0e3;
00113 DEF_K0 = 0;
00114 break;
00115 case ANNEAL_STRICT:
00116 DBGP("Strict Sim Ann parameters!");
00117
00118 YC = 0.72;
00119 HC = 0.22;
00120 YDIMS = 2;
00121 HDIMS = 2;
00122 NBR_ADJ = 1.0;
00123 ERR_ADJ = 1.0;
00124 DEF_T0 = 10.0;
00125 DEF_K0 = 0;
00126 break;
00127 case ANNEAL_ONLINE:
00128
00129
00130 YC = 0.24;
00131 HC = 0.54;
00132
00133 YDIMS = 2;
00134 HDIMS = 3;
00135 NBR_ADJ = 1.0;
00136 ERR_ADJ = 1.0e-2;
00137 DEF_T0 = 1.0e1;
00138 DEF_K0 = 100;
00139 break;
00140 default:
00141 fprintf(stderr,"Unknown Annealing params requested, using default!\n");
00142 setParameters(ANNEAL_DEFAULT);
00143 break;
00144 }
00145 }
00146
00147 void SimAnn::reset()
00148 {
00149 srand( (unsigned)time(NULL) );
00150 mCurrentStep = DEF_K0;
00151 mT0 = DEF_T0;
00152 }
00153
00160 SimAnn::Result
00161 SimAnn::iterate(GraspPlanningState *currentState, SearchEnergy *energyCalculator, GraspPlanningState *targetState)
00162 {
00163
00164 double T = cooling(mT0, YC, mCurrentStep, YDIMS);
00165
00166
00167 GraspPlanningState* newState;
00168 double energy; bool legal = false;
00169 int attempts = 0; int maxAttempts = 10;
00170 DBGP("Ngbr gen loop");
00171 while (!legal && attempts <= maxAttempts) {
00172 newState = stateNeighbor(currentState, T * NBR_ADJ, targetState);
00173 DBGP("Analyze state...");
00174 energyCalculator->analyzeState( legal, energy, newState );
00175 DBGP("Analysis done.");
00176 if (!legal) delete newState;
00177 attempts++;
00178 }
00179
00180 if (!legal) {
00181 DBGP("Failed to compute a legal neighbor");
00182
00183
00184
00185
00186 return FAIL;
00187 }
00188
00189
00190 DBGP("Legal neighbor computed; energy: " << energy )
00191 newState->setEnergy(energy);
00192 newState->setLegal(true);
00193 newState->setItNumber(mCurrentStep);
00194
00195
00196 T = cooling(mT0, HC, mCurrentStep, HDIMS);
00197
00198 double P = prob(ERR_ADJ*currentState->getEnergy(), ERR_ADJ*newState->getEnergy(), T);
00199 double U = ((double)rand()) / RAND_MAX;
00200 Result r = KEEP;
00201 if ( P > U ) {
00202 DBGP("Jump performed");
00203 currentState->copyFrom(newState);
00204 r = JUMP;
00205 } else{
00206 DBGP("Jump rejected");
00207 }
00208
00209 mCurrentStep+=1; mTotalSteps+=1;
00210 DBGP("Main iteration done.")
00211 delete newState;
00212
00213 if (mWriteResults && mCurrentStep % 2 == 0 ) {
00214 assert(mFile);
00215 fprintf(mFile,"%d %d %f %f %f %f\n",mCurrentStep,mTotalSteps,T,currentState->getEnergy(),
00216 currentState->readPosition()->readVariable("Tx"),
00217 targetState->readPosition()->readVariable("Tx"));
00218
00219 }
00220
00221 return r;
00222 }
00223
00224
00225
00226 GraspPlanningState* SimAnn::stateNeighbor(GraspPlanningState *s, double T, GraspPlanningState *t)
00227 {
00228 GraspPlanningState *sn = new GraspPlanningState(s);
00229 if (t) {
00230 variableNeighbor( sn->getPosition(), T, t->getPosition() );
00231 variableNeighbor( sn->getPosture(), T, t->getPosture() );
00232 } else {
00233 variableNeighbor( sn->getPosition(), T, NULL );
00234 variableNeighbor( sn->getPosture(), T, NULL );
00235 }
00236 return sn;
00237 }
00238
00239 void
00240 SimAnn::variableNeighbor(VariableSet *set, double T, VariableSet *target)
00241 {
00242 SearchVariable *var;
00243 double v,tv,conf;
00244 for (int i=0; i<set->getNumVariables(); i++) {
00245 var = set->getVariable(i);
00246 if ( var->isFixed() ) continue;
00247 v = var->mMaxVal + 1.0;
00248 int loop = 0;
00249 while ( v>var->mMaxVal || v < var->mMinVal ) {
00250 loop++;
00251 if (!target || !target->getVariable(i)->isFixed()) {
00252
00253 v = var->getValue() + neighborDistribution(T) * var->mMaxJump;
00254 } else {
00255
00256 tv = target->getVariable(i)->getValue();
00257 DBGP(target->getVariable(i)->getName() << " input: " << tv);
00258 conf = target->getVariable(i)->getConfidence();
00259 assert( conf >= 0 && conf <= 1);
00260
00261 double change = tv - var->getValue();
00262 if (change > var->mMaxJump) change = var->mMaxJump;
00263 else if (change < -1 * var->mMaxJump) change = -1 * var->mMaxJump;
00264 change = change / var->mMaxJump;
00265
00266 DBGP(var->getName() << " value: " << var->getValue() << " Target: " << tv << " Change: " << change);
00267 v = var->getValue() + biasedNeighborDistribution(T,change,conf) * var->mMaxJump;
00268 }
00269 if (var->isCircular()) {
00270 DBGP("Circular variable! " << var->getName());
00271 if ( v > var->mMaxVal) v -= var->getRange();
00272 else if ( v < var->mMinVal) v += var->getRange();
00273 }
00274 if ( v > var->mMaxVal && v - var->mMaxVal < TINY) v = var->mMaxVal;
00275 if ( v < var->mMinVal && v - var->mMinVal > -TINY) v = var->mMinVal;
00276
00277 if (loop == 100) {
00278 DBGA("value: " << var->getValue() << " Mj: " << var->mMaxJump);
00279 DBGA("min val: " << var->mMinVal << " max val: " << var->mMaxVal);
00280 if (target->getVariable(i)->isFixed()) {
00281 DBGA("Target: " << tv << "; Nbr: " << biasedNeighborDistribution(T,tv - var->getValue(),conf));
00282 }
00283 break;
00284 }
00285 }
00286 if (loop > 10) DBGA("Neighbor gen loops: " << loop);
00287 var->setValue(v);
00288 }
00289 }
00290
00291
00292 double
00293 SimAnn::cooling(double t0, double c, int k, int d)
00294 {
00295 double t;
00296
00297
00298
00299
00300 t = t0 * exp ( -c * (double)pow((double)k, 1.0/d) );
00301 return t;
00302 }
00303
00304 double
00305 SimAnn::prob(double e_old, double e_new, double T)
00306 {
00307 if (e_new < e_old) return 1.0;
00308 return pow( M_E , (e_old - e_new) / T);
00309 }
00310
00311 double
00312 SimAnn::neighborDistribution(double T)
00313 {
00314 double y;
00315
00316
00317 double u = ((double)rand()) / RAND_MAX;
00318 double v = fabs( 2.0 * u - 1.0);
00319
00320
00321 y = T * ( pow( 1.0+1.0/T , v ) - 1 );
00322 if ( u<0.5) y = -1.0 * y;
00323
00324 return y;
00325 }
00326
00327 double
00328 SimAnn::neighborInverse(double T, double y)
00329 {
00330 double u = log(1+fabs(y)/T)/log(1+1.0/T);
00331 if ( y<0) u = -1.0 * u;
00332 return u;
00333 }
00334
00335 double
00336 SimAnn::biasedNeighborDistribution(double T, double in, double conf)
00337 {
00338 double u1,u2,u;
00339 double sigma_sq,mean;
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 sigma_sq = 1.0 - conf;
00353
00354 DBGP("In: " << in << " conf: " << conf << " simga_sq: " << sigma_sq);
00355
00356
00357
00358 mean = neighborInverse(T,in);
00359
00360
00361
00362
00363
00364
00365
00366 u = 2;
00367 double loops = 0;
00368 while ( u>1 || u<-1) {
00369
00370 u1 = ((double)rand()) / RAND_MAX;
00371 u2 = ((double)rand()) / RAND_MAX;
00372
00373
00374 u = sqrt( -2 * log(u1) ) * cos(2*M_PI*u2);
00375
00376
00377 u = mean + sqrt(sigma_sq) * u;
00378 loops++;
00379 }
00380
00381 if (loops > 20) DBGA("Biased distribution loops: " << loops);
00382
00383
00384 double y = T * ( pow( 1.0+1.0/T , fabs(u) ) - 1 );
00385 if ( u < 0) y = -1.0 * y;
00386 DBGP("u: " << u << " y: " << y << " loops: " << loops);
00387
00388 return y;
00389 }