/* TD1 Heuristique/Optimisation */
/* Méthode du gradient à pas fixe */
/* gcc -lm td1.c */

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

typedef struct {
	float x[3];
	}VR3;

//Prototypages
void executerGradientPasFixe(float x0[], float pas,float epsilon, int iteration);
float J(float x0[]);
VR3 gradientJ(float x[]);
float norme(float vect[]);

int main(){
	int i,iteration;
	float x0[3],pas,epsilon;
	printf(" Vecteur initial : \n");
	for (i=0; i<3 ; i++){
		printf(" saisissez x%d : \n",i);
		scanf("%f",&(x0[i]));
	}
	printf("saisissez le pas : \n");
	scanf("%f",&pas);
	printf("saisissez la valeur du epsilon : \n");
	scanf("%f",&epsilon);
	printf("saisissez le nombre d'iteration : \n");
	scanf("%d",&iteration);
	executerGradientPasFixe(x0,pas,epsilon,iteration);
	return 0;
}

float J(float x[]){
	return x[0]*x[0] + x[1]*x[1] + x[2]*x[2];
}

VR3 gradientJ(float x[]){
	VR3 v;
	v.x[0] = 2*x[0];
	v.x[1] = 2*x[1];
	v.x[2] = 2*x[2];
	return v;
}

float norme(float vect[]){
	int i;
	float res;
	res = 0.0;
	for (i=0; i<3 ; i++){
		res += vect[i]*vect[i];
	}
	return sqrt(res);
}

void executerGradientPasFixe(float x0[],float pas,float epsilon,int iteration){
	float xOld[3],xNew[3],ecart, xDif[3];
	int i;
	int cpt = 0;
	for (i = 0; i<3 ; i++){
		xOld[i] = x0[i];
	}
	do{
		VR3 v;
		v = gradientJ(xOld);
		for (i = 0; i<3 ; i++){
			xNew[i] = xOld[i] - pas*v.x[i];
		}
		cpt++;
		for (i=0; i<3 ; i++){
			xDif[i] = xNew[i] - xOld[i];
		}
		ecart = norme(xDif);
		for (i = 0; i<3 ; i++){
			xOld[i] = xNew[i];
		}
	}while(cpt <= iteration && ecart > epsilon);
	printf("Point final(");
	for (i = 0; i<3 ; i++){
		printf("%f ",xNew[i]);
		printf(")\n");
	}
	printf(" Valeur du dernier ecart : %f \n",ecart);
	printf(" Valeur de J : %f \n",J(xNew));
}
