Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My Particle Swarm Optimization code generates different answers in C++ and MATLAB

I have written a global version of Particle Swarm Optimization algorithm in C++. I tried to write it exactly as same as my MATLAB PSO code that have written before, but this code generates different and so worst answers. The MATLAB code is:

clear all;

numofdims = 30;
numofparticles = 50;
c1 = 2;
c2 = 2;
numofiterations = 1000;
V = zeros(50, 30);
initialpop = V;
Vmin = zeros(30, 1);
Vmax = Vmin;
Xmax = ones(30, 1) * 100;
Xmin = -Xmax;
pbestfits = zeros(50, 1);
worsts = zeros(50, 1);
bests = zeros(50, 1);
meanfits = zeros(50, 1);
pbests = zeros(50, 30);

initialpop = Xmin + (Xmax - Xmin) .* rand(numofparticles, numofdims);

X = initialpop;
fitnesses = testfunc1(X);
[minfit, minfitidx] = min(fitnesses);
gbestfit = minfit;
gbest = X(minfitidx, :);

for i = 1:numofdims
    Vmax(i) = 0.2 * (Xmax(i) - Xmin(i));
    Vmin(i) = -Vmax(i);
end

for t = 1:1000
    w = 0.9 - 0.7 * (t / numofiterations);

    for i = 1:numofparticles
        if(fitnesses(i) < pbestfits(i))
            pbestfits(i) = fitnesses(i);
            pbests(i, :) =  X(i, :);
        end
    end
    for i = 1:numofparticles
        for j = 1:numofdims
            V(i, j) = min(max((w * V(i, j) + rand * c1 * (pbests(i, j) - X(i, j))...
                + rand * c2 * (gbest(j) - X(i, j))), Vmin(j)), Vmax(j));
            X(i, j) = min(max((X(i, j) + V(i, j)), Xmin(j)), Xmax(j));
        end
    end

    fitnesses = testfunc1(X);
    [minfit, minfitidx] = min(fitnesses);
    if(minfit < gbestfit)
        gbestfit = minfit;
        gbest = X(minfitidx, :);
    end

    worsts(t) = max(fitnesses);
    bests(t) = gbestfit;
    meanfits(t) = mean(fitnesses);
end

In which, testfunc1 is:

function [out] = testfunc1(R)
    out = sum(R .^ 2, 2);
end

The C++ code is:

#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <ctime>

#define rand_01 ((float)rand() / (float)RAND_MAX)

const int numofdims = 30;
const int numofparticles = 50;

using namespace std;

void fitnessfunc(float X[numofparticles][numofdims], float fitnesses[numofparticles])
{
    memset(fitnesses, 0, sizeof (float) * numofparticles);
    for(int i = 0; i < numofparticles; i++)
    {
        for(int j = 0; j < numofdims; j++)
        {
            fitnesses[i] += (pow(X[i][j], 2));
        }
    }
}

float mean(float inputval[], int vallength)
{
    int addvalue = 0;
    for(int i = 0; i < vallength; i++)
    {
        addvalue += inputval[i];
    }
    return (float)(addvalue / vallength);
}

void PSO(int numofiterations, float c1, float c2,
              float Xmin[numofdims], float Xmax[numofdims], float initialpop[numofparticles][numofdims],
              float worsts[], float meanfits[], float bests[], float *gbestfit, float gbest[numofdims])
{
    float V[numofparticles][numofdims] = {0};
    float X[numofparticles][numofdims];
    float Vmax[numofdims];
    float Vmin[numofdims];
    float pbests[numofparticles][numofdims];
    float pbestfits[numofparticles];
    float fitnesses[numofparticles];
    float w;
    float minfit;
    int   minfitidx;

    memcpy(X, initialpop, sizeof(float) * numofparticles * numofdims);
    fitnessfunc(X, fitnesses);
    minfit = *min_element(fitnesses, fitnesses + numofparticles);
    minfitidx = min_element(fitnesses, fitnesses + numofparticles) - fitnesses;
    *gbestfit = minfit;
    memcpy(gbest, X[minfitidx], sizeof(float) * numofdims);

    for(int i = 0; i < numofdims; i++)
    {
        Vmax[i] = 0.2 * (Xmax[i] - Xmin[i]);
        Vmin[i] = -Vmax[i];
    }

    for(int t = 0; t < 1000; t++)
    {
        w = 0.9 - 0.7 * (float) (t / numofiterations);

        for(int i = 0; i < numofparticles; i++)
        {
            if(fitnesses[i] < pbestfits[i])
            {
                pbestfits[i] = fitnesses[i];
                memcpy(pbests[i], X[i], sizeof(float) * numofdims);
            }
        }
        for(int i = 0; i < numofparticles; i++)
        {
            for(int j = 0; j < numofdims; j++)
            {
                V[i][j] = min(max((w * V[i][j] + rand_01 * c1 * (pbests[i][j] - X[i][j])
                                   + rand_01 * c2 * (gbest[j] - X[i][j])), Vmin[j]), Vmax[j]);
                X[i][j] = min(max((X[i][j] + V[i][j]), Xmin[j]), Xmax[j]);
            }
        }

        fitnessfunc(X, fitnesses);
        minfit = *min_element(fitnesses, fitnesses + numofparticles);
        minfitidx = min_element(fitnesses, fitnesses + numofparticles) - fitnesses;
        if(minfit < *gbestfit)
        {
            *gbestfit = minfit;
            memcpy(gbest, X[minfitidx], sizeof(float) * numofdims);
        }

        worsts[t] = *max_element(fitnesses, fitnesses + numofparticles);
        bests[t] = *gbestfit;
        meanfits[t] = mean(fitnesses, numofparticles);
    }


}

int main()
{
    time_t t;
    srand((unsigned) time(&t));

    float xmin[30], xmax[30];
    float initpop[50][30];
    float worsts[1000], bests[1000];
    float meanfits[1000];
    float gbestfit;
    float gbest[30];
    for(int i = 0; i < 30; i++)
    {
        xmax[i] = 100;
        xmin[i] = -100;
    }
    for(int i = 0; i < 50; i++)
        for(int j = 0; j < 30; j++)
        {
            initpop[i][j] = rand() % (100 + 100 + 1) - 100;
        }

    PSO(1000, 2, 2, xmin, xmax, initpop, worsts, meanfits, bests, &gbestfit, gbest);

    cout<<"fitness: "<<gbestfit<<endl;
    return 0;
}

I have debugged two codes many times but can not find the difference which makes answers different. It is making me crazy! May you help me please?

Update:

Please consider that, the function mean is just used for reporting some information and is not used in the optimization procedure.

like image 892
Hamed Avatar asked Aug 07 '12 19:08

Hamed


People also ask

What are the 2 main equations involved in particle swarm Optimisation?

After finding the two best values, the position and velocity of the particles are updated by the following two equations: v i k = w v i k + c 1 r 1 ( pbest i k − x i k ) + c 2 r 2 ( gbest k − x i k ) x i k + 1 = x i k + v i k + 1 where v i k is the velocity of the th particle at the th iteration, and x i k is the ...

Where is the best overall value used in the particle swarm optimization method?

The first value is the best personal solution the particle has found so far. The second one is the best global solution that the swarm of particles has found so far. So each particle has in memory its best personal solution and the best global solution.


2 Answers

You've got integer division in the following line w = 0.9 - 0.7 * (float) (t / numofiterations); w will be 0.2 for every iteration, change it to w = 0.9 - 0.7 * t / numofiterations;

The first multiplication will automatically promote t to a double the division should then promote numof iterations to a double.

The parenthesis means it will be done first and therefore not be promoted as wo integers is involved in the division.

like image 94
badger the bold Avatar answered Sep 19 '22 00:09

badger the bold


This could be a mistake in function mean:

return (float)(addvalue / vallength);

This is integer division, so the result is truncated down, then cast to float. It is unlikely this is what you want.

like image 23
juanchopanza Avatar answered Sep 20 '22 00:09

juanchopanza