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

11,845

Solution 1

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.

Solution 2

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.

Share:
11,845
Hamed
Author by

Hamed

An Electronics engineer who is interested in programming and an Ubuntu user for more than 7 years.

Updated on June 05, 2022

Comments

  • Hamed
    Hamed almost 2 years

    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.