00001 #include "AlgParticleSwarmOptimization.h"
00002
00003
00004 ParticleSwarmOptimization::ParticleSwarmOptimization()
00005 {
00006
00007 name_ = "ParticleSwarmOptimization";
00008
00009 areGenotypesAdded_ = false;
00010
00011
00012
00013 selBestOp = static_cast<SelectionOperatorP> (new SelBestOp);
00014 }
00015
00016
00017
00018 void ParticleSwarmOptimization::registerParameters(StateP state)
00019 {
00020 registerParameter(state, "weightType", (voidP) new InertiaWeightType(CONSTANT), ECF::INT,
00021 "weight type update: 0 - constant, 1 - time dependant (based on max generations)");
00022 registerParameter(state, "weight", (voidP) new double(0.8), ECF::DOUBLE,
00023 "initial inertia weight (either constant or time dependant)");
00024 registerParameter(state, "maxVelocity", (voidP) new double(10.0), ECF::DOUBLE,
00025 "max particle velocity");
00026 registerParameter(state, "bounded", (voidP) new uint(0), ECF::UINT,
00027 "should the algorithm respect the bounds defined in the genotype or not (default: 0)");
00028 }
00029
00030
00031 bool ParticleSwarmOptimization::initialize(StateP state)
00032 {
00033
00034 selBestOp->initialize(state);
00035
00036 voidP weightType = getParameterValue(state, "weightType");
00037 m_weightType = *((InertiaWeightType*) weightType.get());
00038
00039 voidP weight = getParameterValue(state, "weight");
00040 m_weight = *((double*) weight.get());
00041
00042 voidP maxV = getParameterValue(state, "maxVelocity");
00043 m_maxV = *((double*) maxV.get());
00044
00045
00046 if(m_weightType == TIME_VARIANT) {
00047 if(state->getRegistry()->isModified("term.maxgen")) {
00048
00049 m_maxIter = *(boost::static_pointer_cast<int>( state->getRegistry()->getEntry("term.maxgen") ));
00050 }
00051 else {
00052 ECF_LOG_ERROR(state, "Error: term.maxgen has to be specified in order to use time variant inertia eight in PSO algorithm");
00053 throw("");
00054 }
00055 }
00056
00057
00058 FloatingPointP flp (new FloatingPoint::FloatingPoint);
00059 if(state->getGenotypes()[0]->getName() != flp->getName()) {
00060 ECF_LOG_ERROR(state, "Error: PSO algorithm accepts only a single FloatingPoint genotype!");
00061 throw ("");
00062 }
00063
00064 voidP sptr = state->getGenotypes()[0]->getParameterValue(state, "dimension");
00065 uint numDimension = *((uint*) sptr.get());
00066
00067 voidP bounded = getParameterValue(state, "bounded");
00068 bounded_ = *((bool*) bounded.get());
00069
00070 sptr = state->getGenotypes()[0]->getParameterValue(state, "lbound");
00071 lbound_ = *((double*) sptr.get());
00072
00073 sptr = state->getGenotypes()[0]->getParameterValue(state, "ubound");
00074 ubound_ = *((double*) sptr.get());
00075
00076
00077 if(areGenotypesAdded_)
00078 return true;
00079
00080 FloatingPointP flpoint[4];
00081 for(uint iGen = 1; iGen < 4; iGen++) {
00082
00083 flpoint[iGen] = (FloatingPointP) new FloatingPoint::FloatingPoint;
00084 state->setGenotype(flpoint[iGen]);
00085
00086 if(iGen == 3)
00087 flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(1));
00088 else
00089 flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(numDimension));
00090
00091
00092 flpoint[iGen]->setParameterValue(state, "lbound", (voidP) new double(0));
00093 flpoint[iGen]->setParameterValue(state, "ubound", (voidP) new double(1));
00094 }
00095 ECF_LOG(state, 1, "PSO algorithm: added 3 FloatingPoint genotypes (particle velocity, best-so-far postition, best-so-far fitness value)");
00096
00097
00098 areGenotypesAdded_ = true;
00099
00100 return true;
00101 }
00102
00103
00104 bool ParticleSwarmOptimization::advanceGeneration(StateP state, DemeP deme)
00105 {
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 for( uint i = 0; i < deme->getSize(); i++ ) {
00121 IndividualP particle = deme->at(i);
00122
00123
00124 FloatingPointP flp = boost::dynamic_pointer_cast<FloatingPoint::FloatingPoint> (particle->getGenotype(3));
00125 double &particlePbestFitness = flp->realValue[0];
00126 double fitness = particle->fitness->getValue();
00127
00128 flp = boost::dynamic_pointer_cast<FloatingPoint::FloatingPoint> (particle->getGenotype(0));
00129 std::vector< double > &positions = flp->realValue;
00130
00131 flp = boost::dynamic_pointer_cast<FloatingPoint::FloatingPoint> (particle->getGenotype(2));
00132 std::vector< double > &pbestx = flp->realValue;
00133
00134
00135 if( fitness < particlePbestFitness ) {
00136 particlePbestFitness = fitness;
00137
00138
00139 for( uint j = 0;j<pbestx.size();j++ ) {
00140 pbestx[j] = positions[j];
00141 }
00142 }
00143
00144 }
00145
00146
00147 for( uint i = 0; i < deme->getSize(); i++ ) {
00148 IndividualP particle = deme->at(i);
00149
00150 IndividualP bestParticle = selBestOp->select( *deme );
00151
00152 FloatingPointP flp = boost::dynamic_pointer_cast<FloatingPoint::FloatingPoint> (particle->getGenotype(0));
00153 std::vector< double > &positions = flp->realValue;
00154
00155 flp = boost::dynamic_pointer_cast<FloatingPoint::FloatingPoint> (particle->getGenotype(1));
00156 std::vector< double > &velocities = flp->realValue;
00157
00158 flp = boost::dynamic_pointer_cast<FloatingPoint::FloatingPoint> (particle->getGenotype(2));
00159 std::vector< double > &pbestx = flp->realValue;
00160
00161
00162 double weight_up;
00163
00164 switch( m_weightType )
00165 {
00166
00167 case TIME_VARIANT:
00168 weight_up = ( m_weight - 0.4 ) * ( m_maxIter - state->getGenerationNo() ) / m_maxIter + 0.4;
00169 break;
00170
00171
00172 case CONSTANT:
00173 default:
00174 weight_up = m_weight;
00175 break;
00176 }
00177
00178 flp = boost::dynamic_pointer_cast<FloatingPoint::FloatingPoint> (bestParticle->getGenotype(2));
00179 std::vector< double > &bestParticlesPbestx = flp->realValue;
00180 for( uint j = 0; j < velocities.size(); j++ ) {
00181 double velocity;
00182
00183 velocity = weight_up * velocities[j] +
00184 2 * (rand()/(float)RAND_MAX) * (pbestx[j] - positions[j]) +
00185 2 * (rand()/(float)RAND_MAX) * (bestParticlesPbestx[j] - positions[j]);
00186 if( velocity > m_maxV ) velocity = m_maxV;
00187 velocities[j] = velocity;
00188
00189 positions[j] += velocities[j];
00190
00191
00192
00193 if(bounded_) {
00194 if(positions[j] < lbound_)
00195 positions[j] = lbound_;
00196 if(positions[j] > ubound_)
00197 positions[j] = ubound_;
00198 }
00199 }
00200
00201
00202 evaluate( particle );
00203 }
00204
00205 return true;
00206 }