Newer
Older
int CLOUD_POINTS = 3;
double RANDOMNESS = 0.01;
double LR = 0.0001;
double ER = 0.0000000001;
Point* line(double a, double b){
Point * points = (Point*)malloc(sizeof(Point)*LINE_POINTS);
double x = 0.0;
Point d;
d.x = x;
d.y = (a*x)+b;
points[i]=d;
//printf("%lf, %lf", d.x, d.y);
x+=X_VALUE;
}
return points;
}
// La fonction pow() de math.h avait un problème aavec mon Makefile donc je l'ai refaite
// et puis après avoir résolu le problème (emplacement du -lm) afin de pouvoir utiliser
// sqrt() j'ai décidé de la laisser car le nom est mignon
double popow(double v, double w){
double u=v;
for(int i=1;i<w;i++){
v*=u;
}
return v;
}
double double_random(double min, double max)
{
double my_random;
my_random = (double)rand()/RAND_MAX*(max-min)+min;
//printf ( "%f\n", my_random);
return my_random;
}
// Version 1 du nuage, se doit d'appeler line indirectement
Point * my_cloud = malloc(sizeof(Point)*CLOUD_POINTS);
Point chosen_point = a_line[rand()%LINE_POINTS-1];
double new_y = double_random(chosen_point.y-RANDOMNESS, chosen_point.y+RANDOMNESS);
my_cloud[i].x=chosen_point.x;
my_cloud[i].y=new_y;
printf("\nx = %f | y = %f\n", my_cloud[i].x,my_cloud[i].y);
}
return my_cloud;
}
// Version 2 du nuage, peut être généré grâce aux a et b d'une droite
// Génère aléatoirement des points sur l'axe des x (qui ne sont donc pas espacés uniformément)
// le while ne sert pas à grand chose. cloud2_5() est censé rectifier ça.
Point* cloud2(double *a, double *b){
Point * my_cloud = (Point*)malloc(sizeof(Point)*CLOUD_POINTS);
for(int i=0;i<CLOUD_POINTS;i++){
Point chosen_point;
chosen_point.x = double_random(0,1);
for(int j=0;j<CLOUD_POINTS-1;j++){
while(chosen_point.x==my_cloud[j].x){
chosen_point.x = double_random(0,1);
}
}
double rj = double_random(-RANDOMNESS, RANDOMNESS);
chosen_point.y = (*a*chosen_point.x)+*b+rj;
my_cloud[i].x=chosen_point.x;
my_cloud[i].y=chosen_point.y;
//printf("\nx = %f | y = %f\n", my_cloud[i].x,my_cloud[i].y);
double random_point_in_cloud2_5(Point* my_cloud){
double v = double_random(0,1);
for(int i=0;i<CLOUD_POINTS;i++){
if(v==my_cloud[i].x){
v =random_point_in_cloud2_5(my_cloud);
}
}
return v;
}
Point* cloud2_5(double *a, double *b){
Point * my_cloud = (Point*)malloc(sizeof(Point)*CLOUD_POINTS);
for(int i=0;i<CLOUD_POINTS;i++){
Point chosen_point;
chosen_point.x=random_point_in_cloud2_5(my_cloud);
double rj = double_random(-RANDOMNESS, RANDOMNESS);
chosen_point.y = (*a*chosen_point.x)+*b+rj;
my_cloud[i].x=chosen_point.x;
my_cloud[i].y=chosen_point.y;
//printf("\nx = %f | y = %f\n", my_cloud[i].x,my_cloud[i].y);
}
return my_cloud;
}
// version 3 du nuage, plus simple, x espacés uniformément
Point* cloud3(double *a, double *b){
Point * my_cloud = (Point*)malloc(sizeof(Point)*CLOUD_POINTS);
my_cloud[i].x=((double)i/(double)CLOUD_POINTS);
double rj = double_random(-RANDOMNESS, RANDOMNESS);
my_cloud[i].y = ((*a)*my_cloud[i].x)+(*b)+rj;
Point* cloud_test(){
Point * my_cloud = (Point*)malloc(sizeof(Point)*3);
my_cloud[0].x = 0.51;
my_cloud[0].y = 0.24;
my_cloud[1].x = 0.98;
my_cloud[1].y = 0.867;
my_cloud[2].x = 0.1;
my_cloud[2].y = 0.0042;
return my_cloud;
}
//double* avg = (double*)malloc(sizeof(double)*4);
double* avg = malloc(sizeof(double)*4);
double x_avg, y_avg, x2_avg, xy_avg;
for(int i=0; i<cloud_size-1;i++){
x_avg+=my_cloud[i].x;
y_avg+=my_cloud[i].y;
x2_avg+=popow(my_cloud[i].x,2);
xy_avg+=(my_cloud[i].x*my_cloud[i].y);
x_avg/=cloud_size;y_avg/=cloud_size;x2_avg/=cloud_size;xy_avg/=cloud_size;
avg[0]=x_avg;avg[1]=y_avg;avg[2]=x2_avg;avg[3]=xy_avg;
printf("x=%f - y=%f - x2=%f - xy=%f", avg[0],avg[1],avg[2],avg[3]);
return avg;
}
double* a_n_b = (double*)malloc(sizeof(double)*2);
double x_avg = my_averages[0];
double y_avg = my_averages[1];
double x2_avg = my_averages[2];
double xy_avg = my_averages[3];
double a = (xy_avg-(x_avg*y_avg))/(x2_avg-popow(x_avg,2));
double b = y_avg-(a*x_avg);
a_n_b[0]=a;
a_n_b[1]=b;
return a_n_b;
}
// Sommes (similaire à averages() mais ne divise pas par le nb de points)
double* sums(Point* my_cloud, int cloud_size){
//double* avg = (double*)malloc(sizeof(double)*4);
double* my_sums = (double*)malloc(sizeof(double)*4);
double x, y, x2, xy;
for(int i=0; i<cloud_size-1;i++){
x+=my_cloud[i].x;
y+=my_cloud[i].y;
x2+=popow(my_cloud[i].x,2);
xy+=(my_cloud[i].x*my_cloud[i].y);
}
my_sums[0]=x;my_sums[1]=y;my_sums[2]=x2;my_sums[3]=xy;
printf("x=%f - y=%f - x2=%f - xy=%f", my_sums[0],my_sums[1],my_sums[2],my_sums[3]);
return my_sums;
}
// La nouvelle fonction gradient 2 en 1, uniquement chez Lidl
double gradient(double *a, double *b, Point* my_cloud, int cloud_size, bool is_a){
double my_gradient;
for(int i = 0;i<cloud_size;i++){
//Somme des Xi(aXi+b-Yi)
if(is_a){
my_gradient+=(my_cloud[i].x)*((*a*(my_cloud[i].x)+*b-(my_cloud[i].y)));
//Somme des aXi+b-Yi
my_gradient+=(*a*(my_cloud[i].x))+*b-(my_cloud[i].y);
}
}
return my_gradient;
}
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*void gradient_one(double* a, double* b, Point* my_cloud, double* current_cost){
double gr_A,gr_B;
double* my_new_a,my_new_b;
gr_A = gradient(a, b, my_cloud, CLOUD_POINTS, true);
gr_B = gradient(a, b, my_cloud, CLOUD_POINTS, false);
// Les 2 lignes ci-dessous pourraient être condensées, mais c'est pour rendre le code
// plus explicite que je sépare volontairement les étapes.
my_new_a = (*a) - (LR * gr_A);
//printf("\nNew A : %f\n", my_new_a);
my_new_b = (*b) - (LR * gr_B);
//printf("New B : %f\n", my_new_b);
*current_cost = cost2(a,b,my_new_a,my_new_b);
//printf("\nCost : %f\n", current_cost);
*a = my_new_a; *b = my_new_b;
}
void gradient_descent_v3(double* a, double* b, Point* my_cloud){
//double current_cost = 10.0;
printf("\navant\n");
gradient_one(a, b,my_cloud, ¤t_cost);
printf("\naprès\n");
int nb_it = 1;
//double* a_n_b = (double*)malloc(sizeof(double)*2);
while(current_cost>=ER){
gradient_one(a, b,my_cloud, ¤t_cost);
nb_it++;
}
printf("\nCost : %f || Nombre d'itérations : %d\n ", current_cost, nb_it);
//a_n_b[0]=a; a_n_b[1]=b;
//return a_n_b;
}*/
void gradient_descent_v4(double *a, double *b, Point* my_cloud){
double gr_A,gr_B,my_new_a,my_new_b,current_cost;
double *zero;
double z = 0.0;
zero = &z;
current_cost = cost2(zero,zero,a,b);
int nb_it = 0;
//double* a_n_b = (double*)malloc(sizeof(double)*2);
while(current_cost>=ER){
gr_A = gradient(a, b, my_cloud, CLOUD_POINTS, true);
gr_B = gradient(a, b, my_cloud, CLOUD_POINTS, false);
// Les 2 lignes ci-dessous pourraient être condensées, mais c'est pour rendre le code
// plus explicite que je sépare volontairement les étapes.
my_new_a = (*a) - (LR * gr_A);
//printf("\nNew A : %f\n", my_new_a);
my_new_b = (*b) - (LR * gr_B);
//printf("New B : %f\n", my_new_b);
current_cost = cost2(a,b,&my_new_a,&my_new_b);
//printf("\nCost : %f\n", current_cost);
*a = my_new_a; *b = my_new_b;
//current_cost = cost(a, b, my_cloud, CLOUD_POINTS);
nb_it++;
printf("\nCost : %f || Nombre d'itérations : %d\n ", current_cost, nb_it);
//a_n_b[0]=a; a_n_b[1]=b;
//return a_n_b;
// La nouvelle fonction gradient_descent 2 en 1, uniquement chez Lidl
// Formule fausse et pas fait la norme donc bug. A refaire demain.
void gradient_descent_v2(double *a, double *b, Point* my_cloud, double current_cost){
double gr_A,gr_B,my_new_a,my_new_b;
int nb_it = 0;
//double* a_n_b = (double*)malloc(sizeof(double)*2);
while(current_cost>=ER){
gr_A = gradient(a, b, my_cloud, CLOUD_POINTS, true);
gr_B = gradient(a, b, my_cloud, CLOUD_POINTS, false);
// Les 2 lignes ci-dessous pourraient être condensées, mais c'est pour rendre le code
// plus explicite que je sépare volontairement les étapes.
my_new_a = (*a) - (LR * gr_A);
//printf("\nNew A : %f\n", my_new_a);
my_new_b = (*b) - (LR * gr_B);
//printf("New B : %f\n", my_new_b);
current_cost = cost2(a,b,&my_new_a,&my_new_b);
//printf("\nCost : %f\n", current_cost);
*a = my_new_a; *b = my_new_b;
//current_cost = cost(a, b, my_cloud, CLOUD_POINTS);
nb_it++;
printf("\nCost : %f || Nombre d'itérations : %d\n ", current_cost, nb_it);
//a_n_b[0]=a; a_n_b[1]=b;
//return a_n_b;
double cost2(double *a, double *b, double *new_a, double *new_b){
return sqrt(popow((*new_a - *a),2)+popow((*new_b - *b), 2));
/*// Create a vector X = [0,1,2...99]
double_vector_t *X = iota(100);
// Create a vector Y = my_function(x)
double_vector_t *Y = apply_function(X, my_function);
// Export our vectors into files
export_vector("./X.vec", X);
export_vector("./Y.vec", Y);
// Free our vectors
destroy_vector(&Y);
destroy_vector(&X);
*/
double a_init = 0.98902527076;
double b_init = -0.1537833935;
//Point* fluffy = cloud2_5(&a_init, &b_init);
Point* fluffy = cloud_test();
printf("\na initial = %f || b initial = %f\n", a_init, b_init);
double a = double_random(-100,100);
double b = double_random(-100,100);
//double initial_cost = cost2(&a, &b,0,0);
//gradient_descent_v2(&a, &b, fluffy, initial_cost);
double initial_costs = 0;
gradient_descent_v4(&a, &b, fluffy);
printf("\na trouvé = %f || b trouvé = %f\n", a, b);