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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
#include <iostream>
#include <random>
#include <vector>
#include <valarray>
#include <cmath>
#include <ctime>
using namespace std;
mt19937 gen( time( 0 ) );
uniform_real_distribution<double> dist( 0.0, 1.0 );
const double PI = 4.0 * atan( 1.0 );
//====================================================================
double fsphere( const valarray<double> &pos ) // De Jong's Sphere function
{
return ( pos * pos ).sum();
}
//====================================================================
double fholder( const valarray<double> &pos ) // Holder's Table function
{
double x = pos[0], y = pos[1];
x = x - 10 * (int) ( x / 10 ); // evaluate only in [-10,10]
y = y - 10 * (int) ( y / 10 );
return -abs( sin( x ) * cos( y ) * exp( abs( 1.0 - sqrt( x * x + y * y ) / PI ) ) );
}
//====================================================================
double urand( double lower, double upper ) // Returns uniform on (lower,upper)
{
return lower + ( upper - lower ) * dist( gen );
}
//====================================================================
valarray<double> urand( double lower, double upper, int dim ) // Returns array uniform on (lower,upper)
{
valarray<double> result( dim );
for ( auto &x : result ) x = lower + ( upper - lower ) * dist( gen );
return result;
}
//====================================================================
class particle // Individual particle class
{
public:
valarray<double> position, velocity, localg;
double localMin;
particle( int dim, double lower, double upper )
{
position = urand( lower, upper, dim );
velocity = urand( lower, upper, dim );
localg = position;
}
};
//====================================================================
class swarm // Swarm class
{
vector<particle> particles;
valarray<double> globalg;
double globalMin;
int popsize, dim;
double w, deltag, deltap, lrt, lower, upper;
double (*func)( const valarray<double> & );
public:
swarm( int n, int d, double w_, double dg, double dp, double lrt_, double l, double u, double (*f)( const valarray<double> & ) )
: popsize( n ), dim( d ), w( w_ ), deltag( dg ), deltap( dp ), lrt( lrt_ ), lower( l ), upper( u ), func( f )
{
globalg = urand( lower, upper, dim );
globalMin = func( globalg );
particles = vector<particle>( popsize, particle( dim, lower, upper ) );
for ( auto &p : particles )
{
p.localMin = func( p.localg );
if ( p.localMin < globalMin )
{
globalg = p.localg;
globalMin = p.localMin;
}
}
}
//-----------------------------------
void print()
{
cout << "Global best: " << globalMin << " at ";
for ( auto e : globalg ) cout << e << " ";
cout << '\n';
}
//-----------------------------------
void iterate( int itermax )
{
for ( int iter = 1; iter <= itermax; iter++ )
{
// cout << "Iter " << iter << " "; print();
for ( auto &p : particles )
{
// Random vectors
valarray<double> rp = urand( 0.0, 1.0, dim ), rg = urand( 0.0, 1.0, dim );
//Update velocity
p.velocity = w * p.velocity + deltap * rp * ( p.localg - p.position ) + deltag * rg * ( globalg - p.position );
//Update position
p.position = p.position + lrt * p.velocity;
// Update individual particle's minimum and global minimum
double value = func( p.position );
if ( value < p.localMin )
{
p.localg = p.position;
p.localMin = value;
if ( value < globalMin )
{
globalg = p.position;
globalMin = value;
}
}
} // End particle loop
} // End iteration loop
}
};
//====================================================================
int main()
{
cout << "De Jong's sphere:\n";
swarm sphere( 100, 3, 0.7, 0.5, 0.5, 1.0, -10, 10, fsphere );
sphere.iterate( 1000 );
sphere.print();
cout << "\n\nHolder's table function:\n";
swarm holder( 1000, 2, 0.7, 0.5, 0.5, 1.0, -10, 10, fholder );
holder.iterate( 1000 );
holder.print();
}
|