Biorithm  1.1
 All Classes Functions Variables Typedefs Friends
anneal.h
00001 /**************************************************************************
00002  * Copyright (c) 2004-2011 T. M. Murali                                   *
00003  *                                                                        *
00004  * This file is part of Biorithm.                                         *
00005  *                                                                        *
00006  * Biorithm is free software: you can redistribute it and/or modify       *
00007  * it under the terms of the GNU General Public License as published by   *
00008  * the Free Software Foundation, either version 3 of the License, or      *
00009  * (at your option) any later version.                                    *
00010  *                                                                        *
00011  * Biorithm is distributed in the hope that it will be useful,            *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
00014  * GNU General Public License for more details.                           *
00015  *                                                                        *
00016  * You should have received a copy of the GNU General Public License      *
00017  * along with Biorithm.  If not, see <http://www.gnu.org/licenses/>.      *
00018  *                                                                        *
00019  **************************************************************************/
00020 
00027 #ifndef _ANNEAL_H
00028 #define _ANNEAL_H
00029 
00030 #include <stdlib.h>
00031 #include <iostream>
00032 #include <vector>
00033 
00034 using namespace std;
00035 
00037 typedef double MyNT;
00038 
00039 // first two constants taken from pathway perturbation paper.
00040 const MyNT DEFAULT_START_TEMPERATURE = 100;
00041 const MyNT DEFAULT_END_TEMPERATURE = 1E-5;
00042 const unsigned int DEFAULT_NUM_ITERATIONS = 10000;
00043 // #iterations = k => DET = DST / (DDT)^k => DDT = (DST/DET)^{1/k}.
00044 const MyNT DEFAULT_DROP_TEMPERATURE = pow(DEFAULT_START_TEMPERATURE/DEFAULT_END_TEMPERATURE, 1.0/DEFAULT_NUM_ITERATIONS);
00045 
00046 
00069 class MyAbstractAnnealState
00070 {
00071 private:
00072   MyNT _score;
00073 
00074 public:
00076   MyAbstractAnnealState()
00077       : _score(0)
00078     {}
00079   
00080   virtual ~MyAbstractAnnealState()
00081     {}
00082 
00085   MyAbstractAnnealState &operator=(const MyAbstractAnnealState &rhs);
00086   
00091   virtual void computeRandomNeighbour(MyAbstractAnnealState &neighbour) = 0;
00092 
00093 
00095   virtual MyNT computeScore() const = 0;
00096 
00098   virtual void print(ostream &ostr) const = 0;
00099 
00101   virtual void undo() = 0;
00102 
00103 };
00104 
00105 
00106 
00113 template <typename AnnealState >//, typename AnnealMethod>
00114 class MySimulatedAnnealer {
00115 protected:                                              // member data
00116 
00117   // variables related to the annealing policy.
00118   MyNT _startTemperature;
00119   MyNT _endTemperature;
00120   // how much to decrease the temperature each time.
00121   MyNT _dropTemperature;
00122   unsigned int _numMaxIterations;
00123   unsigned int _numMaxIterationsWithoutImprovement;
00124 
00125   MyNT _bestScore;
00126   MyNT  _currentTemperature;
00127   unsigned int _numTotalIterations;
00128   unsigned int _numIterationsWithScoreDecrease;
00129   unsigned int _numIterationsWithoutImprovement;
00130   
00131   AnnealState _startState;
00132   AnnealState _currentState;
00133   // vector< AnnealState > _stateHistory;
00134   // vector< AnnealState > _neighbouringStates;
00135   
00136 //   AnnealMethod &_method;
00137 
00138   
00139   
00140 public:
00141   MySimulatedAnnealer() 
00142       :
00143       _startTemperature(DEFAULT_START_TEMPERATURE),
00144       _endTemperature(DEFAULT_END_TEMPERATURE),
00145       _dropTemperature(DEFAULT_DROP_TEMPERATURE),
00146       _numMaxIterations(DEFAULT_NUM_ITERATIONS),
00147       _numMaxIterationsWithoutImprovement(100),
00148       _bestScore(0), _currentTemperature(_startTemperature),
00149       _numTotalIterations(0), _numIterationsWithScoreDecrease(0),
00150       _numIterationsWithoutImprovement(0),
00151       _startState(), _currentState()// ,
00152         // _stateHistory(), _neighbouringStates()
00153 //         _method(m)
00154     {
00155     }
00156 
00157   MySimulatedAnnealer(const AnnealState &s) 
00158       : _startTemperature(DEFAULT_START_TEMPERATURE),
00159       _endTemperature(DEFAULT_END_TEMPERATURE),
00160       _dropTemperature(DEFAULT_DROP_TEMPERATURE),
00161       _numMaxIterations(DEFAULT_NUM_ITERATIONS),
00162       _numMaxIterationsWithoutImprovement(100),
00163       _bestScore(0), _currentTemperature(_startTemperature),
00164         _numTotalIterations(0), _numIterationsWithScoreDecrease(0),
00165       _numIterationsWithoutImprovement(0),
00166       _startState(s), _currentState()//,
00167         // _stateHistory(), _neighbouringStates()
00168 //         _method(m)
00169     {
00170     }
00171 
00172   virtual ~MySimulatedAnnealer()
00173     { 
00174     }
00175 
00176   bool acceptNeighbour(MyNT score)
00177     {
00178       if (score > _bestScore)
00179         return(true);
00180       // compute probability.
00181       MyNT prob = (score - _bestScore)/_currentTemperature;
00182       prob = exp(prob);
00183       MyNT sample = random()*1.0/RAND_MAX;
00184       if (sample <= prob)
00185         return(true);
00186       return(false);
00187     }
00188   
00189   MyNT computeBestScore(const vector< AnnealState > &neighbours,
00190                         AnnealState &bestNeighbour)
00191     {
00192       typename vector< AnnealState >::const_iterator aitr = neighbours.begin();
00193       MyNT score = aitr->computeScore();
00194       bestNeighbour = *aitr;
00195       MyNT currentScore;
00196       
00197       for (; aitr != neighbours.end(); aitr++)
00198         {
00199           currentScore = aitr->computeScore();
00200           if (currentScore > score)
00201             {
00202               score = currentScore;
00203               bestNeighbour = *aitr;
00204             }
00205         }
00206       return(score);
00207     }
00208   
00209   void decreaseTemperature()
00210     {
00211       _currentTemperature /= _dropTemperature;
00212     }
00213   
00214   void getFinalState(AnnealState &finalState) const
00215     {
00216       finalState = _currentState;// _stateHistory.back();
00217     }
00218   
00219   void initialise() 
00220     {
00221       _bestScore = 0;
00222       _currentTemperature = DEFAULT_START_TEMPERATURE;
00223       _numTotalIterations = 0;
00224       _numIterationsWithoutImprovement = 0;
00225       _currentState = _startState;
00226       // _stateHistory.push_back(_startState);
00227     }
00228 
00230   bool isDone()
00231     {
00232       if (_numMaxIterations == _numTotalIterations)
00233       // if (100 == _numIterationsWithoutImprovement)
00234         return(true);
00235       return(false);
00236     }
00237 
00239   void setNumTotalIterations(unsigned int num)
00240     {
00241       _numMaxIterations = num;
00242       // i should update _dropTemperature as well.
00243       _dropTemperature = pow(_startTemperature/_endTemperature, 1.0/_numMaxIterations);
00244     }
00245   
00247   void run() 
00248   {
00249     MyNT score;
00250     initialise();
00251     AnnealState neighbour;// = NULL;
00252     
00253     // compute its score.
00254     score = _startState.computeScore();
00255     
00256     while (true)
00257       {
00258         // compute the neighbours of the current state.
00259         // _neighbouringStates.clear();
00260         // _stateHistory.back().computeNeighbours(_neighbouringStates);
00261         // if (0 == _neighbouringStates.size())
00262         //   break;
00263         // score = computeBestScore(_neighbouringStates, bestNeighbour);
00264 
00265         // compute a random neighbour of the current state.
00266         _currentState.computeRandomNeighbour(neighbour);
00267         // _stateHistory.back().computeRandomNeighbour(neighbour);
00268         score = neighbour.computeScore();
00269 
00270         if (acceptNeighbour(score))
00271           {
00272             _currentState = neighbour;
00273             // _stateHistory.push_back(neighbour);
00274             if (_bestScore > score)
00275               // this is an iteration where the score decreased.
00276               _numIterationsWithScoreDecrease++;
00277             _bestScore = score;
00278             _numIterationsWithoutImprovement = 0;
00279           }
00280         else
00281           {
00282             // Reverse the changes made by the neighbour.
00291             neighbour.undo();
00292             _numIterationsWithoutImprovement++;
00293           }
00294         // I can delete neighbour in any case. If accepted, I have put
00295         // a copy of it at the back of _stateHistory.
00296         // delete neighbour;
00297         decreaseTemperature();
00298         _numTotalIterations++;
00299 //#ifdef DEBUG
00300         if (0 == (_numTotalIterations%10000))
00301           {
00302             cout << "\t" << _numTotalIterations
00303                  << "\t" << _numIterationsWithScoreDecrease
00304                  << "\t" << _numIterationsWithScoreDecrease*1.0/_numTotalIterations;
00305             _currentState.print(cout);
00306           }
00307 //#endif // DEBUG
00308 
00309         if (isDone())
00310           {
00311 #ifdef DEBUG
00312             _currentState.print(cout);
00313             // _stateHistory.back().print(cout);
00314 #endif // DEBUG
00315             break;
00316           }
00317       }
00318   }
00319 
00321   void setInitialState(AnnealState &s)
00322     {
00323       _startState = s;
00324     }
00325   
00326 };
00327 
00328 
00329 #endif // _ANNEAL_H 
 All Classes Functions Variables Typedefs Friends