How to deal with large sums of floating points (C++) - c++

I'm trying to understand why computing determinant of a 3x3 matrix in this way gives broken results:
#include <iostream>
#include <array>
#include <vector>
int main(int argc, char const *argv[])
{
const int dim = 3;
std::vector<std::vector<float>> data;
data.resize(dim, std::vector<float>(dim, 0));
std::array<float, dim*dim> myArray = {
-1000.0, -1000.0, -1000.0,
-1000.0, -1000.0, -1000.0,
-1000.0, -1000.0, -999.0
};
for(int i = 0; i < dim; i++){
for(int j = 0; j < dim; j++){
data[i][j] = myArray[dim*i + j];
}
}
float det =
data[0][0] * data[1][1] * data[2][2] +
data[0][1] * data[1][2] * data[2][0] +
data[0][2] * data[2][1] * data[1][0] -
data[2][0] * data[1][1] * data[0][2] -
data[0][0] * data[1][2] * data[2][1] -
data[1][0] * data[0][1] * data[2][2];
float anotherDet = 0;
for(int i = 0; i < 2; i++){
anotherDet = anotherDet + 1000 * 1000 * 1000;
}
for(int i = 0; i < 2; i++){
anotherDet = anotherDet - 1000 * 1000 * 1000;
}
anotherDet = anotherDet - 1000 * 1000 * 999;
anotherDet = anotherDet + 1000 * 1000 * 999;
std::cout << det << " " << anotherDet << std::endl;
return 0;
}
The output of this code is -64 0, whereas the real determinant of such matrix should be zero. My suspicion is that the error is related to the floating points precision, but I still don't get the logic for why such discrepancies happen.
I tried debugging, and indeed I found that there is a rounding error that gets carried on. -2999000060 is the value of det in the middle of that large sum.
But if I try the following:
float det2 =
1000 * 1000 * 1000 +
1000 * 1000 * 1000 +
1000 * 1000 * 999 -
1000 * 1000 * 1000 -
1000 * 1000 * 1000 -
1000 * 1000 * 999;
It gives the correct value of 0, but only because its an arithmetic operation, and thus there are not rounding errors.
Edit: I understand now how operations with floats that big could carry some rounding error.

Related

Partial Derivative of Real Data Using Fourier Transform(FFTW) in 2D Gives Not Giving Correct Results

I am trying to calculate the partial derivative of the function Sin(x)Sin(y) along the x-direction using Fourier Transform (FFTW library in C++). I take my function from real to Fourier space (fftw_plan_dft_r2c_2d), multiply the result by -i * kappa array (wavenumber/spatial frequency), and then transform the result back into real space (fftw_plan_dft_c2r_2d). Finally, I divide the result by the size of my 2D array Nx*Ny (I need to do this based on the documentation). However, the resulting function is scaled up by some value and the amplitude is not 1.
'''
#define Nx 360
#define Ny 360
#define REAL 0
#define IMAG 1
#define Pi 3.14
#include <stdio.h>
#include <math.h>
#include <fftw3.h>
#include <iostream>
#include <iostream>
#include <fstream>
#include <iomanip>
int main() {
int i, j;
int Nyh = Ny / 2 + 1;
double k1;
double k2;
double *signal;
double *result2;
double *kappa1;
double *kappa2;
double df;
fftw_complex *result1;
fftw_complex *dfhat;
signal = (double*)fftw_malloc(sizeof(double) * Nx * Ny );
result2 = (double*)fftw_malloc(sizeof(double) * Nx * Ny );
kappa1 = (double*)fftw_malloc(sizeof(double) * Nx * Nyh );
result1 = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * Nx * Nyh);
dfhat = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * Nx * Nyh);
for (int i = 0; i < Nx; i++){
if ( i < Nx/2 + 1)
k1 = 2 * Pi * (-Nx + i) / Nx;
else
k1 = 2 * Pi * i / Nx;
for (int j = 0; j < Nyh; j++){
kappa1[j + Nyh * i] = k1;
}
}
fftw_plan plan1 = fftw_plan_dft_r2c_2d(Nx,Ny,signal,result1,FFTW_ESTIMATE);
fftw_plan plan2 = fftw_plan_dft_c2r_2d(Nx,Ny,dfhat,result2,FFTW_ESTIMATE);
for (int i=0; i < Nx; i++){
for (int j=0; j < Ny; j++){
double x = (double)i / 180 * (double) Pi;
double y = (double)j / 180 * (double) Pi;
signal[j + Ny * i] = sin(x) * sin(y);
}
}
fftw_execute(plan1);
for (int i = 0; i < Nx; i++) {
for (int j = 0; j < Nyh; j++) {
dfhat[j + Nyh * i][REAL] = 0;
dfhat[j + Nyh * i][IMAG] = 0;
dfhat[j + Nyh * i][IMAG] = -result1[j + Nyh * i][REAL] * kappa1[j + Nyh * i];
dfhat[j + Nyh * i][REAL] = result1[j + Nyh * i][IMAG] * kappa1[j + Nyh * i];
}
}
fftw_execute(plan2);
for (int i = 0; i < Nx; i++) {
for (int j = 0; j < Ny; j++) {
result2[j + Ny * i] /= (Nx*Ny);
}
}
for (int j = 0; j < Ny; j++) {
for (int i = 0; i < Nx; i++) {
std::cout <<std::setw(15)<< result2[j + Ny * i];
}
std::cout << std::endl;
}
fftw_destroy_plan(plan1);
fftw_destroy_plan(plan2);
fftw_free(result1);
fftw_free(dfhat);
return 0;
}
'''
This is how the result looks
I have defined my kappa array to have Nx * Ny/2+1 elements and have split the array at the center (as all references suggest). But it does not work. I would appreciate any help!

Why my window function isn't removing harmonics?

I have been working on creating a mixed wave signal. My code is in c++ :
Server signal:
void server_sineWave(BitDepth buffer[], double sin_freq, double beep_freq) {
BitDepth amplitude = std::numeric_limits<BitDepth>::max() * 0.5;
QWORD c = 0;
double d = (samplerate / sin_freq);
int initial = NUM_SAMPLES / 25;
for (QWORD i = 0; i < NUM_SAMPLES; i += channels) {
buffer[i] = amplitude * sin((2 * pi * sin_freq * i) / samplerate); // sin wave generated at "freq"
if (i == initial) {
for (QWORD j = 0; j < 480; j++) {
double stream = amplitude * sin((2 * pi * sin_freq * i / samplerate));
double beep = amplitude * sin((2 * pi * beep_freq * j / samplerate));
double multiplier = .4 * (1 - cos(2 * pi * j / 480));
buffer[i] = stream + (beep * multiplier);
i++;
}
initial = i + 19200.0;
}
}
}
Client signal:
void client_sineWave(BitDepth buffer[], double sin_freq, double beep_freq) {
BitDepth amplitude = std::numeric_limits<BitDepth>::max() * 0.5;
QWORD c = 0;
double d = (samplerate / sin_freq);
int initial = NUM_SAMPLES / 25;
for (QWORD i = 0; i < NUM_SAMPLES; i += channels) {
buffer[i] = amplitude * sin(2 * pi * sin_freq * i / samplerate); // sin wave generated at "freq"
if (i == initial) {
for (QWORD j = 0; j < 480; j++) {
double stream = amplitude * sin((2 * pi * sin_freq * i / samplerate));
double beep = amplitude * sin((2 * pi * beep_freq * j / samplerate));
double multiplier = .4 * (1 - cos(2 * pi * j / 480));
buffer[i] = stream + (beep * multiplier);
// buffer[i] += (beep * multiplier);
i++;
}
initial = i + 19200.0;
//(1000 + rand() % 10000)
//double deg = 360.0 / d;
//buffer[i] = buffer[i + (1 * (channels - 1))] = sin((c++ * deg) * pi / 180) * amplitude;
}
}
}
Mixing of server and client signals:
void mix(BitDepth buffer[], BitDepth server[], BitDepth client[], double duration_milliseconds) {
QWORD num_samples = duration_milliseconds * (NUM_SAMPLES / 10000.0);
double tmp = 0;
QWORD size = NUM_SAMPLES + num_samples;
BitDepth *server_delay = new BitDepth[size];
BitDepth *client_delay = new BitDepth[size];
for (QWORD i = 0; i < size; i++) {
if (i < num_samples) {
server_delay[i] = 0;
client_delay[i + NUM_SAMPLES] = 0;
}
if (i > num_samples) {
server_delay[i] = server[i - num_samples];
client_delay[i - num_samples] = client[i - num_samples];
}
}
for (QWORD i = 0; i < NUM_SAMPLES; i += channels) {
// double multiplier = .5 * (1 - cos(2 * pi * i / NUM_SAMPLES-1));
// double multiplier = (0.54 - 0.46 * cos(2.0 * M_PI * (double) i / (double) (NUM_SAMPLES - 1)));
// server_delay[i] = multiplier * (server_delay[i]);
// client_delay[i] = multiplier * (client_delay[i]);
tmp = server_delay[i] + client_delay[i];
if (tmp > 32767) {
tmp = 32767;
} else if (tmp < -32768) {
tmp = -32768;
}
buffer[i] = tmp;
}
}
My Result in spectrogram from the above code:
Now, when I change the amplitude by increasing value from 0.5 to 0.8, in the following line:
BitDepth amplitude = std::numeric_limits<BitDepth>::max() * 0.5;
to
BitDepth amplitude = std::numeric_limits<BitDepth>::max() * 0.8;
I get following result:
I am new in DSP c++ programming and I really don't know what is this issue and how to resolve this issue?
Please help me in solving this issue.
thanks.
As Suggested by #PaulR, clipping was causing a lot of harmonics.
Your waveform is clipping (because 0.8 + 0.8 > 1.0), which will generate a lot of harmonics - look at the data in your debugger and you’ll see lots of flat peaks at +/- 32k.
So, after taking care of this limit. My issue is resolved.
Thanks alot.

calculate the precise, non integer frequencies from time series in (FFTW)

I want to calculate the frequency of time series precisely with at least 3 decimal value.
This is a simple example that calculates the frequency of integer values.
#include <fftw3.h>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <fstream>
#define REAL 0
#define IMAG 1
#define NUM_POINTS 1024
void acquire_signal(double *signal, double *theta) {
/* Generate two sine waves of different frequencies and
* amplitudes.
*/
int i;
for (i = 0; i < NUM_POINTS; ++i) {
theta[i] = (double)i / (double)NUM_POINTS;
signal[i] = 1.0*sin(50.0 * 2.0 * M_PI * theta[i]) +
0.5*sin(80.0 * 2.0 * M_PI * theta[i]);
}
}
int main() {
unsigned flags{0};
double *theta = new double[NUM_POINTS];
double *signal = new double[NUM_POINTS];
fftw_complex result[NUM_POINTS/2+1];
fftw_plan plan = fftw_plan_dft_r2c_1d(NUM_POINTS,
signal,
result,
flags);
acquire_signal(signal,theta);
fftw_execute(plan);
//save signal and result
std::ofstream f1,f2;
f1.open ("signal.txt");
for (int i=0; i<NUM_POINTS; i++){
f1 <<theta[i]<<" "<<signal[i]<<"\n";
}
f1.close();
f2.open("result.txt");
for (int i=0; i<NUM_POINTS/2; i++){
double yf = 2.0/(double)(NUM_POINTS)* sqrt(result[i][REAL]*result[i][REAL]+ result[i][IMAG]* result[i][IMAG]);
f2<< (double)i << " "<<yf <<"\n";
}
f2.close();
fftw_destroy_plan(plan);
delete[] signal,theta;
return 0;
}
But how should I change the code if I have
signal = 1.0*sin(50.350 * 2.0 * M_PI * theta[i]) +
0.5*sin(80.455 * 2.0 * M_PI * theta[i]);
Is it appropriate to change the units of time and frequency?
for example time in 1000*s and frequency in kHz?
Just changing the numbers in sin will shift your lines from 50 and 80 to 50.350 and 80.455 Hz, and assuming you have 1024 lines by 1024 Hz. But you still have 1Hz resolution. You need more lines (x1000) by the same sampling frequency to get bigger resolution.
For example if you want 1/4 Hz resolution you need 4x more samples so by 1024 Hz sample rate you need fs * 4 samples:
...
#define NUM_POINTS (1024 * 4)
double fs = 1024; // Sample rate in Hz
void acquire_signal(double *signal, double *theta) {
/* Generate two sine waves of different frequencies and
* amplitudes.
*/
int i;
for (i = 0; i < NUM_POINTS; ++i) {
theta[i] = (double)i / (double)fs;
signal[i] = 1.0*sin(50.0 * 2.0 * M_PI * theta[i]) +
0.5*sin(80.0 * 2.0 * M_PI * theta[i]);
}
}
....
for (int i=0; i< (NUM_POINTS/2 + 1) ; i++){
double yf = 2.0/(double)(NUM_POINTS)* sqrt(result[i][REAL]*result[i][REAL]+ result[i][IMAG]* result[i][IMAG]);
f2 << (double)i * fs / ( NUM_POINTS ) << " "<<yf <<"\n";
}
0 2.90715e-16
0.25 1.19539e-16
0.5 2.15565e-16
0.75 2.88629e-16
1 3.05084e-16
1.25 3.864e-16
...
49.75 9.47968e-16
50 1
50.25 1.12861e-15
50.5 4.95946e-16
50.75 6.9016e-16
...

How to implement overlap add method?

I implemented my filter, where overlap add method to prevent circular convultion is used.
input - file with noise, output should be filtered file.
My result: out is slightly modified, frequencies aren`t cut
My guess is that I wrongly multiply in the frequency domain input signal on the filter kernel
(My intention is to cut off frequencies that aren't in range [300,3700]). How multiplication should be done?
I construct kernel using blackmanwindow - is my understanding correct? ( I compute amount of frequency per one sample of filter, then go through samples and see if it is in range I want to cut off I calculate frequency using formula for Blackman window.)
I just started learning DSP.
Here is my implementation (what is wrong with it???):
void DeleteFrequencies(char* fileWithNoise, char* resultFile, const int bufferSize, int lowestFrequency, int highestFrequency, int sampleRate )
{
// |1|. files
std::fstream in;
std::fstream out;
in.open (fileWithNoise, std::ios::in | std::ios::binary);
out.open(resultFile, std::ios::out | std::ios::binary);
// |2|. Filter kernel design. I shall use blackman window
// fundamental params
const int filterKernelLength = 200; // 512
const int filterMaxFrequency = sampleRate / 2; // 8000 / 2
const int frequencyPerSamle = filterMaxFrequency / filterKernelLength;
double *RealFilterResp = new double [bufferSize / 2];
double *ImmFilterResp = new double [bufferSize / 2];
// coefficients for Blackman window
const double a0 = 0.42659;
const double a1 = 0.49656;
const double a2 = 0.076849;
// construct filter kernel
for (int i = 0 ; i < bufferSize / 2; ++i)
{
if ( i >= filterKernelLength ) // padd filter kernel with zeroes
{
RealFilterResp[i] = 0;
ImmFilterResp[i] = 0;
}
else if (i * frequencyPerSamle < lowestFrequency || i * frequencyPerSamle > highestFrequency)
{
// apply blackman window (to eleminate frequencies < 300 hz and > 3700 hz)
RealFilterResp[i] = a0 - a1 * cos (2 * M_PI * i / (bufferSize / 2 - 1)) + a2 * cos (4 * M_PI / (bufferSize / 2 - 1));
ImmFilterResp[i] = a0 - a1 * cos (2 * M_PI * i / (bufferSize / 2 - 1)) + a2 * cos (4 * M_PI / (bufferSize / 2 - 1));
}
else
{
RealFilterResp[i] = 1;
ImmFilterResp[i] = 1;
}
}
// |3|. overlap add method
// calculate parameters for overlap add method (we use it to prevent circular convultion)
const int FFT_length = pow (2.0 ,(int)(log(bufferSize + filterKernelLength - 1.0)/log(2.0)) + 1.0);
double *OLAP = new double[bufferSize / 2 ]; // holds the overlapping samples from segment to segment
memset(OLAP,0, bufferSize / 2 * sizeof (double));
double *RealX = new double[bufferSize];
memset(RealX, 0, bufferSize * sizeof(double));
double *ImmX = new double[bufferSize];
memset(ImmX, 0, bufferSize * sizeof(double));
short* audioDataBuffer = new short[bufferSize];
memset(audioDataBuffer, 0 , sizeof(short) * bufferSize);
// start reading from file by chunks of bufferSize
while (in.good())
{
// get proper chunk of data
FillBufferFromFile(audioDataBuffer, bufferSize, in); // read chunk from file
ShortArrayToDoubleArray(audioDataBuffer, RealX, bufferSize); // fill RealPart
ForwardRealFFT(RealX, ImmX, bufferSize); // go to frequency domain
// perform convultion as multiplication in frequency domain
for (int j = 0; j < bufferSize / 2; ++j)
{
double tmp = RealX[j] * RealFilterResp[j] - ImmX[j] * ImmFilterResp[j];
ImmX[j] = RealX[j] * ImmFilterResp[j] + ImmX[j] * RealFilterResp[j];
RealX[j] = tmp;
}
// Inverse FFT
ReverseRealFFT(RealX, ImmX, bufferSize); // go to time domain
// add last segment overlap to this segment
for (int j = 0; j < filterKernelLength - 2; ++j )
{
RealX[j] += OLAP[j];
}
// save samples that will overlap the next segment
for (int j = bufferSize/2 + 1; j < bufferSize; ++j )
{
OLAP[j - bufferSize/2 - 1] = audioDataBuffer[j];
}
// write results
DoubleArrayToShortArray(RealX, audioDataBuffer, bufferSize);
FillFileFromBuffer(audioDataBuffer, bufferSize, out);
}
/*ReverseRealFFT(RealX, ImmX, bufferSize
);
DoubleArrayToShortArray(RealX, audioDataBuffer, bufferSize);*/
delete [] audioDataBuffer;
delete [] RealFilterResp;
delete [] ImmFilterResp;
delete [] OLAP;
delete [] RealX;
delete [] ImmX;
in.close();
out.close();
}
If your intention is to use the window method to implement the filter, the window should multiply the time-domain sequence corresponding to the infinite impulse response of the ideal bandpass filter.
Specifically, for a bandpass filter of bandwidth w0=2*pi*(3700-300)/8000 centered at wc=2*pi*(300+3700)/8000, the ideal impulse response would be (for -infinity < n < infinity):
w0*sinc(0.5*w0*n/pi) * cos(wc*n) / pi
Which you would shift to the interval [0,N-1], and then apply the window that you computed:
double sinc(double x) {
if (fabs(x)<1e-6) return 1.0;
return sin(M_PI * x)/(M_PI * x);
}
void bandpassDesign(int N, double* filterImpulseResponse) {
double w0 = 2*(3700-300)*M_PI/8000;
double wc = 2*(300+3700)*M_PI/8000;
double shift = 0.5*N;
for (int i = 0; i < bufferSize; ++i) {
double truncatedIdealResponse = w0*sinc(0.5*w0*(i-shift)/M_PI) * cos(wc*i) / M_PI;
double window = a0 - a1 * cos (2 * M_PI * i / (N- 1)) + a2 * cos (4 * M_PI * i / (N- 1));
filterImpulseResponse[i] = truncatedIdealResponse * window;
}
}
You can then take the FFT to obtain the frequency-domain coefficients. Remember that if you intend on filtering data using this filter, the time sequence has to be zero padded.
For example, if you wish to use a 1024-point FFT with the overlap-add method, and assuming a 128-point filter kernel meets your filter design specifications, you would call bandpassDesign with N=128, pad with 1024-128=896 zeros, then take the FFT.
Your window coefficients are wrong - the window function is purely real, and you are going to multiply your (complex) frequency domain data with these real coeffs. So your filter coef initialisation:
double *RealFilterResp = new double [bufferSize / 2];
double *ImmFilterResp = new double [bufferSize / 2];
if ( i >= filterKernelLength ) // padd filter kernel with zeroes
{
RealFilterResp[i] = 0;
ImmFilterResp[i] = 0;
}
else if (i * frequencyPerSamle < lowestFrequency || i * frequencyPerSamle > highestFrequency)
{
// apply blackman window (to eleminate frequencies < 300 hz and > 3700 hz)
RealFilterResp[i] = a0 - a1 * cos (2 * M_PI * i / (bufferSize / 2 - 1)) + a2 * cos (4 * M_PI / (bufferSize / 2 - 1));
ImmFilterResp[i] = a0 - a1 * cos (2 * M_PI * i / (bufferSize / 2 - 1)) + a2 * cos (4 * M_PI / (bufferSize / 2 - 1));
}
else
{
RealFilterResp[i] = 1;
ImmFilterResp[i] = 1;
}
should just be:
double *FilterResp = new double [bufferSize / 2];
if ( i >= filterKernelLength ) // padd filter kernel with zeroes
{
FilterResp[i] = 0;
}
else if (i * frequencyPerSamle < lowestFrequency || i * frequencyPerSamle > highestFrequency)
{
FilterResp[i] = a0 - a1 * cos (2 * M_PI * i / (bufferSize / 2 - 1)) + a2 * cos (4 * M_PI / (bufferSize / 2 - 1));
}
else
{
FilterResp[i] = 1;
}
and the frequency domain multiplication:
for (int j = 0; j < bufferSize / 2; ++j)
{
double tmp = RealX[j] * RealFilterResp[j] - ImmX[j] * ImmFilterResp[j];
ImmX[j] = RealX[j] * ImmFilterResp[j] + ImmX[j] * RealFilterResp[j];
RealX[j] = tmp;
}
should just be:
for (int j = 0; j < bufferSize / 2; ++j)
{
RealX[j] *= FilterResp[j];
ImmX[j] *= FilterResp[j];
}

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.
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.
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.