Perceptron learning algorithm not converging to 0 - c

Here is my perceptron implementation in ANSI C:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float randomFloat()
{
srand(time(NULL));
float r = (float)rand() / (float)RAND_MAX;
return r;
}
int calculateOutput(float weights[], float x, float y)
{
float sum = x * weights[0] + y * weights[1];
return (sum >= 0) ? 1 : -1;
}
int main(int argc, char *argv[])
{
// X, Y coordinates of the training set.
float x[208], y[208];
// Training set outputs.
int outputs[208];
int i = 0; // iterator
FILE *fp;
if ((fp = fopen("test1.txt", "r")) == NULL)
{
printf("Cannot open file.\n");
}
else
{
while (fscanf(fp, "%f %f %d", &x[i], &y[i], &outputs[i]) != EOF)
{
if (outputs[i] == 0)
{
outputs[i] = -1;
}
printf("%f %f %d\n", x[i], y[i], outputs[i]);
i++;
}
}
system("PAUSE");
int patternCount = sizeof(x) / sizeof(int);
float weights[2];
weights[0] = randomFloat();
weights[1] = randomFloat();
float learningRate = 0.1;
int iteration = 0;
float globalError;
do {
globalError = 0;
int p = 0; // iterator
for (p = 0; p < patternCount; p++)
{
// Calculate output.
int output = calculateOutput(weights, x[p], y[p]);
// Calculate error.
float localError = outputs[p] - output;
if (localError != 0)
{
// Update weights.
for (i = 0; i < 2; i++)
{
float add = learningRate * localError;
if (i == 0)
{
add *= x[p];
}
else if (i == 1)
{
add *= y[p];
}
weights[i] += add;
}
}
// Convert error to absolute value.
globalError += fabs(localError);
printf("Iteration %d Error %.2f %.2f\n", iteration, globalError, localError);
iteration++;
}
system("PAUSE");
} while (globalError != 0);
system("PAUSE");
return 0;
}
The training set I'm using: Data Set
I have removed all irrelevant code. Basically what it does now it reads test1.txt file and loads values from it to three arrays: x, y, outputs.
Then there is a perceptron learning algorithm which, for some reason, is not converging to 0 (globalError should converge to 0) and therefore I get an infinite do while loop.
When I use a smaller training set (like 5 points), it works pretty well. Any ideas where could be the problem?
I wrote this algorithm very similar to this C# Perceptron algorithm:
EDIT:
Here is an example with a smaller training set:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float randomFloat()
{
float r = (float)rand() / (float)RAND_MAX;
return r;
}
int calculateOutput(float weights[], float x, float y)
{
float sum = x * weights[0] + y * weights[1];
return (sum >= 0) ? 1 : -1;
}
int main(int argc, char *argv[])
{
srand(time(NULL));
// X coordinates of the training set.
float x[] = { -3.2, 1.1, 2.7, -1 };
// Y coordinates of the training set.
float y[] = { 1.5, 3.3, 5.12, 2.1 };
// The training set outputs.
int outputs[] = { 1, -1, -1, 1 };
int i = 0; // iterator
FILE *fp;
system("PAUSE");
int patternCount = sizeof(x) / sizeof(int);
float weights[2];
weights[0] = randomFloat();
weights[1] = randomFloat();
float learningRate = 0.1;
int iteration = 0;
float globalError;
do {
globalError = 0;
int p = 0; // iterator
for (p = 0; p < patternCount; p++)
{
// Calculate output.
int output = calculateOutput(weights, x[p], y[p]);
// Calculate error.
float localError = outputs[p] - output;
if (localError != 0)
{
// Update weights.
for (i = 0; i < 2; i++)
{
float add = learningRate * localError;
if (i == 0)
{
add *= x[p];
}
else if (i == 1)
{
add *= y[p];
}
weights[i] += add;
}
}
// Convert error to absolute value.
globalError += fabs(localError);
printf("Iteration %d Error %.2f\n", iteration, globalError);
}
iteration++;
} while (globalError != 0);
// Display network generalisation.
printf("X Y Output\n");
float j, k;
for (j = -1; j <= 1; j += .5)
{
for (j = -1; j <= 1; j += .5)
{
// Calculate output.
int output = calculateOutput(weights, j, k);
printf("%.2f %.2f %s\n", j, k, (output == 1) ? "Blue" : "Red");
}
}
// Display modified weights.
printf("Modified weights: %.2f %.2f\n", weights[0], weights[1]);
system("PAUSE");
return 0;
}

In your current code, the perceptron successfully learns the direction of the decision boundary BUT is unable to translate it.
y y
^ ^
| - + \\ + | - \\ + +
| - +\\ + + | - \\ + + +
| - - \\ + | - - \\ +
| - - + \\ + | - - \\ + +
---------------------> x --------------------> x
stuck like this need to get like this
(as someone pointed out, here is a more accurate version)
The problem lies in the fact that your perceptron has no bias term, i.e. a third weight component connected to an input of value 1.
w0 -----
x ---->| |
| f |----> output (+1/-1)
y ---->| |
w1 -----
^ w2
1(bias) ---|
The following is how I corrected the problem:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define LEARNING_RATE 0.1
#define MAX_ITERATION 100
float randomFloat()
{
return (float)rand() / (float)RAND_MAX;
}
int calculateOutput(float weights[], float x, float y)
{
float sum = x * weights[0] + y * weights[1] + weights[2];
return (sum >= 0) ? 1 : -1;
}
int main(int argc, char *argv[])
{
srand(time(NULL));
float x[208], y[208], weights[3], localError, globalError;
int outputs[208], patternCount, i, p, iteration, output;
FILE *fp;
if ((fp = fopen("test1.txt", "r")) == NULL) {
printf("Cannot open file.\n");
exit(1);
}
i = 0;
while (fscanf(fp, "%f %f %d", &x[i], &y[i], &outputs[i]) != EOF) {
if (outputs[i] == 0) {
outputs[i] = -1;
}
i++;
}
patternCount = i;
weights[0] = randomFloat();
weights[1] = randomFloat();
weights[2] = randomFloat();
iteration = 0;
do {
iteration++;
globalError = 0;
for (p = 0; p < patternCount; p++) {
output = calculateOutput(weights, x[p], y[p]);
localError = outputs[p] - output;
weights[0] += LEARNING_RATE * localError * x[p];
weights[1] += LEARNING_RATE * localError * y[p];
weights[2] += LEARNING_RATE * localError;
globalError += (localError*localError);
}
/* Root Mean Squared Error */
printf("Iteration %d : RMSE = %.4f\n",
iteration, sqrt(globalError/patternCount));
} while (globalError > 0 && iteration <= MAX_ITERATION);
printf("\nDecision boundary (line) equation: %.2f*x + %.2f*y + %.2f = 0\n",
weights[0], weights[1], weights[2]);
return 0;
}
... with the following output:
Iteration 1 : RMSE = 0.7206
Iteration 2 : RMSE = 0.5189
Iteration 3 : RMSE = 0.4804
Iteration 4 : RMSE = 0.4804
Iteration 5 : RMSE = 0.3101
Iteration 6 : RMSE = 0.4160
Iteration 7 : RMSE = 0.4599
Iteration 8 : RMSE = 0.3922
Iteration 9 : RMSE = 0.0000
Decision boundary (line) equation: -2.37*x + -2.51*y + -7.55 = 0
And here's a short animation of the code above using MATLAB, showing the decision boundary at each iteration:

It might help if you put the seeding of the random generator at the start of your main instead of reseeding on every call to randomFloat, i.e.
float randomFloat()
{
float r = (float)rand() / (float)RAND_MAX;
return r;
}
// ...
int main(int argc, char *argv[])
{
srand(time(NULL));
// X, Y coordinates of the training set.
float x[208], y[208];

Some small errors I spotted in your source code:
int patternCount = sizeof(x) / sizeof(int);
Better change this to
int patternCount = i;
so you doesn't have to rely on your x array to have the right size.
You increase iterations inside the p loop, whereas the original C# code does this outside the p loop. Better move the printf and the iteration++ outside the p loop before the PAUSE statement - also I'd remove the PAUSE statement or change it to
if ((iteration % 25) == 0) system("PAUSE");
Even doing all those changes, your program still doesn't terminate using your data set, but the output is more consistent, giving an error oscillating somewhere between 56 and 60.
The last thing you could try is to test the original C# program on this dataset, if it also doesn't terminate, there's something wrong with the algorithm (because your dataset looks correct, see my visualization comment).

globalError will not become zero, it will converge to zero as you said, i.e. it will become very small.
Change your loop like such:
int maxIterations = 1000000; //stop after one million iterations regardless
float maxError = 0.001; //one in thousand points in wrong class
do {
//loop stuff here
//convert to fractional error
globalError = globalError/((float)patternCount);
} while ((globalError > maxError) && (i<maxIterations));
Give maxIterations and maxError values applicable to your problem.

Related

This solution would not accept any floats

Currently on one of the cs50x problem sets 'Cash', which is a simple 'ask for how much change is owed, then calculate how many coins are required' task, so not here asking for a solution but, I don't understand why this won't work.
While it does ask for an input, when I type in a float such as 5.96, it simply hangs. No returns, no errors whatsoever. I have to force it shut. The other thing is the while loop doing the same when set to 0, which is the intended way of doing things in order to get the exact number of coins.
I know how inefficient this code is and there are simpler ways of doing things. I just wish to understand the whys in order to avoid making the same mistakes moving on. Thanks.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
// changes and other containers
int p = 1;
int n = 5;
int d = 10;
int q = 25;
int x = 0;
float c;
// get how much change is owed in float
do
{
c = get_float("Change owed: ");
}
while (c < 0);
// int conversion to avoid imprecision
int a = round(c * 100);
// 1 because 0 spits out an unknown error
while (a >= 1)
{
// if the converted amount is bigger than a quarter
if (a >= q)
{
// x = number of coins, a = amount left
x = a / q;
a = a % q;
}
else if (a >= d)
{
x = x + a / d;
a = a - a % d;
}
else if (a >= n)
{
x = x + a / n;
a = a - a % n;
}
else
{
x = x + a / p;
a = a - a % p;
}
}
printf("%i\n", x);
printf("%i\n", a);
}
Thanks to WhozCraig, I figured out that my logic was at fault.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
// changes and other containers
int p = 1;
int n = 5;
int d = 10;
int q = 25;
int x = 0;
float c;
// get how much change is owed in float
do
{
c = get_float("Change owed: ");
}
while (c < 0);
// int conversion to avoid imprecision
int a = round(c * 100);
// 1 because 0 spits out an unknown error
while (a >= 1)
{
// if the converted amount is bigger than a quarter
if (a >= q)
{
// x = number of coins, a = amount left
x = a / q;
a = a % q;
}
else if (a >= d)
{
x = x + a / d;
a = a % d;
}
else if (a >= n)
{
x = x + a / n;
a = a % n;
}
else
{
x = x + a / p;
a = a % p;
}
}
printf("%i\n", x);
printf("%i\n", a);
}

Optimization with a float in c

I am currently doing exercices on Kattis and I meet a problem with I think the float.
I must compare the size of matchstick with the size of box
Sibice problem on Kattis.com
Here is a picture of the exercise
I can make examples but when I submit I past only the first two...
Here is a picture of my submission
I don't have a trace or explication for know my errors... I tried to change the type of my variables but there is no change... I think the problems is float but I need it.
Here is my code
#include <stdio.h>
void sibice(float n, float w, float h)
{
float v = 0;
for(float i = 0; i != n; i += 1) {
scanf("%f", &v);
if(v < w + h / 2)
printf("DA\n");
if(v == w + h / 2)
printf("DA\n");
if(v > w + h / 2) {
printf("NE\n");
}
}
}
int main(void)
{
float n = 0;
float w = 0;
float h = 0;
scanf("%f %f %f", &n, &w, &h);
sibice(n, w, h);
return (0);
}
Do you think that I can optimize my code ?
Incorrect test
If a match can fit is a more like v*v <= h*h + w*w than v < w + h / 2. Can it diagonally fit?
See Pythagorean theorem
#include <math.h>
...
float hyp = hypotf(h,w); // sqrt(h*h + w*w)
for(float i = 0; i != n; i += 1) {
scanf("%f", &v);
// if(v < w + h / 2)
if(v < hyp)
No need for 3 tests
One test is sufficient.
if(v <= hyp) {
printf("DA\n");
} else {
printf("NE\n");
}
Integer math
As all calculations are whole numbers, code could use int only math.
void sibice(int n, int w, int h) {
int hyp2 = h*h + w*w;
for (int i = 0; i != n; i += 1) {
int v;
scanf("%d", &v);
if (v*v <= hyp2)
...
Other issues may exist
Why do you need to use float? With these changes the code passes the tests:
#include <stdio.h>
#include <stdlib.h>
void sibice(int n, int w, int h)
{
int v;
int result;
for (int i = 0; i != n; i += 1) {
result = scanf("%d", &v);
if (1 != result)
exit(1);
if (v * v <= w * w + h * h)
printf("DA\n");
else
printf("NE\n");
}
}
int main(void)
{
int n = 0;
int w = 0;
int h = 0;
int result = 0;
result = scanf("%d %d %d", &n, &w, &h);
if (3 != result)
return 1;
sibice(n, w, h);
return (0);
}

End condition for precision integration loop

I'm trying to integrate the function 1/((1+x^2)x^0.5) using the trapezium rule. I need the precision to be as great as possible so I am therefore increasing the number of strips, N, until the computer cannot recognise a change between the total for consecutive N. However, the end condition is not currently working, leading to continuous integration. Does anyone have any better suggestions than my current code?
Many thanks,
Beth
#include<stdio.h>
#include<math.h>
#include<float.h>
double inter(double x, double h, double y, double N, double total)
{
total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));
x=x+h;
while (x<y)
{
total=total+(1/((1+pow(x,2))*sqrt(x)));
x=x+h;
//printf("x - %.16lf \n", x);
}
total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));
total=total*h;
//printf("t - %lf \n", total);
return total;
}
main()
{
double x,y,total,h,value,newvalue,f, N;
int finish;
x=0.1;
y=1000;
total=0;
N=1000;
finish=0;
value=0;
while(finish==0)
{
h=(y-x)/(N-1);
newvalue=inter(x,h,y,N,total);
printf("h-%.16lf\n", h);
printf("N-%.16lf\n", N);
printf("New value %.16lf\n", newvalue);
printf("c-%.16lf\n", value);
if(value==newvalue)
{
finish=1;
printf("finish-%d\n", finish);
}
else
{
value=newvalue;
newvalue=newvalue-3;
N=N+1000;
printf("newvalue-%lf\n", newvalue);
printf("value-%lf\n", value);
}
}
printf("%lf\n", value);
}
If you wish to create an automatic refinement of your numerical integration, one technique is to look at the relative convergence of your integration.
double previous = 0;
double current = inter( x, (y-x)/(N-1), y, N, total ); // Solve some baseline
do
{
N = N + 1000;
h = (y-x)/(N-1);
previous = current;
current = inter( x, h, y, N, total );
} while( abs( current - previous ) / current > 0.001 );
That code will stop after you observe less than 0.1% relative refinement in your estimation. Decreasing 0.001 will effectively increase your accuracy. Usually the best way to compare doubles is through a tolerance check like:
abs( a - b ) < k
where k is some factor of the order of accuracy you wish to achieve.
This integral is difficult because the f(x) -> ∞ as x -> 0. In this example, I changed the range to 1 to 1000. I also used a summation function to minimize rounding error when summing up a large number of values. The integral from wolframalpha ~= .487474, this program results in ~=.487475 . The exact integral can be found using this link:
integral 1/((1+x^2)sqrt(x))
#include<stdio.h>
#include<math.h>
#include<float.h>
/* clear array */
void clearsum(double asum[2048])
{
size_t i;
for(i = 0; i < 2048; i++)
asum[i] = 0.;
}
/* add a number into array */
void addtosum(double d, double asum[2048])
{
size_t i;
while(1){
/* i = exponent of d */
i = ((size_t)((*(unsigned long long *)&d)>>52))&0x7ff;
if(i == 0x7ff){ /* max exponent, could be overflow */
asum[i] += d;
return;
}
if(asum[i] == 0.){ /* if empty slot store d */
asum[i] = d;
return;
}
d += asum[i]; /* else add slot to d, clear slot */
asum[i] = 0.; /* and continue until empty slot */
}
}
/* return sum from array */
double returnsum(double asum[2048])
{
double sum = 0.;
size_t i;
for(i = 0; i < 2048; i++)
sum += asum[i];
return sum;
}
double fx(double x)
{
return 1./((1.+x*x)*sqrt(x));
}
double inter(double x, double y, double n)
{
double asum[2048]; /* for summation functions */
double h;
double d;
if(n < 1.){
n = 1.;
h = 0.;
} else {
h = (y-x)/(n-1.0);
}
y -= h/2.;
clearsum(asum);
d = .5*h*fx(x);
addtosum(d, asum);
for( ; x < y; x += h){
d = h*fx(x);
addtosum(d, asum);
}
d = .5*h*fx(x);
addtosum(d, asum);
d = returnsum(asum);
return d;
}
int main()
{
double x,y,n,value,newvalue;
x=1.0;
y=1000.;
value=0.;
for(n = 100000000.; 1; n += 100000000.)
{
newvalue=inter(x,y,n);
printf("new value %.16lf %.0lf\n", newvalue, n);
if(fabs(newvalue-value) < (newvalue*1E-7))
break;
value = newvalue;
}
return 0;
}
Using Simpson's rule, the results are more accurate and converge at much smaller values for n:
#include<stdio.h>
#include<math.h>
#include<float.h>
/* clear array */
void clearsum(double asum[2048])
{
size_t i;
for(i = 0; i < 2048; i++)
asum[i] = 0.;
}
/* add a number into array */
void addtosum(double d, double asum[2048])
{
size_t i;
while(1){
/* i = exponent of d */
i = ((size_t)((*(unsigned long long *)&d)>>52))&0x7ff;
if(i == 0x7ff){ /* max exponent, could be overflow */
asum[i] += d;
return;
}
if(asum[i] == 0.){ /* if empty slot store d */
asum[i] = d;
return;
}
d += asum[i]; /* else add slot to d, clear slot */
asum[i] = 0.; /* and continue until empty slot */
}
}
/* return sum from array */
double returnsum(double asum[2048])
{
double sum = 0.;
size_t i;
for(i = 0; i < 2048; i++)
sum += asum[i];
return sum;
}
double fx(double x)
{
return 1./((1.+x*x)*sqrt(x));
}
double simpson(double x, double y, double n)
{
double asum[2048]; /* for summation functions */
double h;
double a;
if(n < 1.){
n = 1.;
h = 0.;
} else {
h = (y-x)/(n-1.0);
}
y += h/2.;
clearsum(asum);
for( ; x < y; x += h){
a = h/6.*(fx(x) + 4.*fx(x + h/2.) + fx(x + h));
addtosum(a, asum);
}
a = returnsum(asum);
return a;
}
int main()
{
double x,y,n,value,newvalue;
x=1.0;
y=1000.;
value=0.;
for(n = 1000.; 1; n += 1000.)
{
newvalue=simpson(x,y,n);
printf("new value %.16lf %.0lf\n", newvalue, n);
if(fabs(newvalue-value) < (newvalue*1E-10))
break;
value = newvalue;
}
return 0;
}

FIR filter in C?

I have a homework to implement an FIR filter in C and I wonder whether you think I understood the assignment correctly. The program I wrote that I think solves the problem is:
#include <stdio.h>
float FIRfloats[5];
void floatFIR(float newsample)
{
int i;
float sum=0;
FIRfloats[0]=newsample*0.0299;
FIRfloats[1]=FIRfloats[2]*0.4701;
FIRfloats[2]=FIRfloats[3]*0.4701;
FIRfloats[3]=FIRfloats[4]*0.0299;
/* sum */
for(i=0;i<5;i++)
{
sum=sum+FIRfloats[i];
}
printf("Sum: %f\n", sum);
}
int main ()
{
float n=0.0f;
while (scanf("%f", &n) > 0)
{
floatFIR(n);
}
return 0;
}
And the specification is
Before a new sample xk arrives the old samples are shifted to the
right and then each sample is scaled with a coefficient before the
result yk, the total sum of all scaled samples, is calculated
Coefficients should be c0=0.0299, c1=0.4701, c2=0.4701, c3=0.0299.
Do you think that I solved the assignment correctly? I think it seemed too easy and therefore I wonder.
I'm afraid the implementation provided in the question will not provide the correct results.
In FIR (Finite Impulse Response) filter with 4 coefficients the output series (y) for input series (x) is:
y[t] = c0*x[t] + c1*x[t-1] + c2*x[t-2] + c3*x[t-3]
Therefore the implementation should be similar to:
/* add includes (stdio.h and whatever else you'll need...) */
float floatFIR(float inVal, float* x, float* coef, int len)
{
float y = 0.0;
for (int i = (len-1) ; i > 0 ; i--)
{
x[i] = x[i-1];
y = y + (coef[i] * x[i]);
}
x[0] = inVal;
y = y + (coef[0] * x[0]);
return y;
}
main(int argc, char** argv)
{
float coef[4] = {0.0299, 0.4701, 0.4701, 0.0299};
float x[4] = {0, 0, 0, 0}; /* or any other initial condition*/
float y;
float inVal;
while (scanf("%f", &inVal) > 0)
{
y = floatFIR(inVal, x, coef, 4);
}
return 0;
}
This does the shift and multiplication at the same loop (which does not affect results - only is more efficient.)
If you want to follow the spec exactly, you can change floatFir like this:
float floatFIR(float inVal, float* x, float* coef, int len)
{
float y = 0.0;
for (int i = (len-1) ; i > 0 ; i--)
{
x[i] = x[i-1];
}
x[0] = inVal;
for (int i = 0 ; i < len ; i++)
{
y = y + (coef[i] * x[i]);
}
return y;
}

C function returns wrong value

float a, b;
float sa() { return a;};
int main() {
a = 10;
b = sa();
printf("%f", b);
return 0;
}
This is a simplified version of my code.
I believe the program should print 10 but it gives me really small numbers like -65550, not always the same but very alike.
I have used the debugger to check the value of variabe a right before it is returned and it is 10, so the function returns 10, but b is set to something like -65550. I don't understand why this happens.
I'd appreciate some intell.
Thanks in advance.
Here is the full code:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
int dimensiuni, nrBitiSolutie, bitiPeDimensiune, gasitInbunatatire, nrRulari;
float limInf, limSup, precizie, valoareFunctie, minim, minimNou, T;
char solutie[100000];
float solutieReala[100];
void generateRandomSolution();
void bitesToFloat();
void rastrigin();
void rosenbrock();
float nextFirstFit();
float nextBestFit();
void main() {
int k;
T = 10;
gasitInbunatatire = 1;
srand ( time(NULL) );
printf("Introduceti numarul de dimensiuni: ");
scanf("%d", &dimensiuni);
printf("Introduceti limita inferioara si cea superioara: ");
scanf("%f%f", &limInf, &limSup);
printf("Introduceti precizia: ");
scanf("%f", &precizie);
//calculam numarul de biti necesari ca sa reprezentam solutia
nrBitiSolutie = dimensiuni * ceil(log(limSup-limInf * pow(10, precizie)))/log(2.0);
bitiPeDimensiune = nrBitiSolutie/dimensiuni;
//generam o solutie random
generateRandomSolution();
bitesToFloat();
rastrigin();
minim = valoareFunctie;
printf("Pornim de la %f\n", minim);
while( (nrRulari < 10000) && (T > 0.001)) {
minimNou = sa(); //error occurs here. sa() returns about 200 but minimNou is set to -65550
if (minimNou < minim) {
printf("Minim nou: %f\n", minimNou);
minim = minimNou;
T *= 0.995;
}
nrRulari++;
}
printf("Minimul aproximat: %f\n", minim);
system("pause");
}
void generateRandomSolution() {
int l;
for (l = 0; l < nrBitiSolutie; l++) solutie[l] = rand()%2;
}
void bitesToFloat() {
int i, parcurse = 1, gasite = 0;
int variabila = 0;
float nr;
for (i = 0; i < nrBitiSolutie; i++) {
variabila = variabila<<1 | (int)solutie[i];
if(parcurse == bitiPeDimensiune) {
nr = (float)variabila / (float)pow(2, bitiPeDimensiune);
nr *= limSup-limInf;
nr += limInf;
nr *= pow(10, precizie);
nr = (int)nr;
nr /= pow(10, precizie);
parcurse = 0;
solutieReala[gasite++] = nr;
variabila = 0;
}
parcurse++;
}
}
void rastrigin() {
int i;
valoareFunctie = 10 * dimensiuni;
for (i = 0; i < dimensiuni; i++) {
valoareFunctie += pow((float)solutieReala[i], 2) - 10 * (float)cos(2 * 3.14 * (float)solutieReala[i]);
}
}
void rosenbrock() {
int i;
valoareFunctie = 0;
for (i = 0; i < dimensiuni - 1; i++) {
valoareFunctie += 100 * pow((solutieReala[i+1] - pow(solutieReala[i], 2)), 2) + pow((1-solutieReala[i]), 2);
}
}
float sa() {
int j;
for (j = 0; j < nrBitiSolutie; j++) {
solutie[j] = solutie[j] == 0 ? 1 : 0;
bitesToFloat();
rastrigin();
if (valoareFunctie < minim) return valoareFunctie;
else if ( (rand()/INT_MAX) < exp((minim - valoareFunctie)/T) )
return valoareFunctie;
else solutie[j] = solutie[j] == 0 ? 1 : 0;
}
return minim;
}
I have marked where the error occurs with error occurs here comment
You simplified the code incorrectly. In your simplification, you defined sa() before calling it. But in your full program, you call sa() before defining it. In the absence of a declaration, functions are assumed to return int. Since your function actually returns a float, the result is undefined. (In this case, you will read a garbage value from the top of the floating point stack and then the floating point stack will underflow, and things go downhill from there.)

Resources