#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <stdlib.h>
#define Rasm 3
//               Описание переменных доступных во всей программе.
int N=0,k=0;
int numF,flag;
float S[Rasm][Rasm],lambda[Rasm],eps;
float xn[Rasm],xn1[Rasm],x0[Rasm];
float x[Rasm],Sm[Rasm],Sk[Rasm];
//              Описние функций
void init(void);
extern void isoline(void);
int prov_X(float *,float *);
extern float func(float *);
float poisk_l(int iter,float *);
//            Основная программа
void main(void)
{
 //                  Описание      переменных  .
  int i,j;
  int num=0;
  float delta=0.0000000001,f1,f2,p,p1,p2,x0_1[Rasm];
  float y,z=0,z1=0;
  int y1;
  FILE *fp;
  init();
  fp = fopen("raboch.dat", "wt");
  fprintf(fp,"%d\n",N);
  for(i=0;i<N;i++) x0[i]=x[i];
do  {
   if ( k==0 ){
	       for( i=0;i<N;i++)
		for( j=0;j<N;j++)
		  { if ( i == j ) S[i][j]=1.0;
		    else S[i][j]=0.0;
		  }
	     }
  for(i=0;i<N;i++) x0_1[i]=x0[i];

// Определяется LAMBDA путем минимизации f(x[i-1]+l*S[i])

  for (i=0;i<N;i++){
    if ( i == 0 ) {
		   lambda[i]=poisk_l(i,x0);
		   for(j=0;j<N;j++) xn[j]=x0[j];
		  }
   else lambda[i]=poisk_l(i,xn);
	  f1=func(xn);
	  for(j=0;j<N;j++) xn[j]=xn[j]+lambda[i]*S[j][i];
	  f2=func(xn);
	  if ( delta <= ( p=(f1-f2)) )
	  { delta=p;
	    num=i;
	  }
  }

 for(i=0;i<N;i++)
  { xn1[i]=2*xn[i]-x0[i];
    Sm[i]=xn[i]-x0[i];
  }
 p1=(func(x0)-func(xn)-delta);
 p=( func(x0)-2*func(xn)+func(xn1))*(p1*p1);
 p2=0.5*delta*(func(x0)-func(xn1))*(func(x0)-func(xn1));
 z=func(xn1);
 z1=func(x0);
  if ( ( z >= z1 ) && ( p >= p2)) {
	if ( func(xn)>func(xn1) )
	     for(i=0;i<N;i++) x0[i]=xn1[i];
	else for(i=0;i<N;i++) x0[i]=xn[i];
  goto Again;  // Перейти на проверку неравенств
 }
 else {
	for(i=num;i<N-1;i++)
	 for(j=0;j<N;j++) S[j][i]=S[j][i+1];
	for(i=0;i<N;i++)  S[i][N-1]=Sm[i];
	 p=poisk_l(N-1,xn);
	 for(i=0;i<N;i++) Sk[i]=(xn[i]-x0[i]);
	 for(i=0;i<N;i++) x0[i]=xn[i]+p*Sk[i];
      }
Again:
       y=fabs(func(x0));
       y1=prov_X(x0_1,x0);
       if( ( y< eps) || y1) {
       break;
       }
       else k=k+1;

gotoxy(35,12);
printf("итерация %d\n",k);
  for(i=0;i<N;i++)
    fprintf(fp,"%f  ",xn[i]);
    fprintf(fp,"%f\n",func(xn));
}
while  (1);
 fclose(fp);
 numF=k;
 if ( N<=2 ) isoline();
 printf("\nМинимум функции найден в точке :");
 for(i=0;i<N;i++)  printf("%f  ",xn[i]);
    printf("\n равен : %f\n",func(xn));
return;
}
float poisk_l(int iter,float *x0){
 float c[Rasm],xk[Rasm],xk1[Rasm],dx=0.1,l=1.0,l1,z=0.0,z1=0.0,z_=0.0;
  int i,iter1;
	iter1=iter;
	for(i=0;i<N;i++) {
	  xk[i]=x0[i];
	  c[i]=x0[i]+l*S[i][iter1];
	}
	z=func(xk);
	z1=func(c);
	if ( z <= z1 ) dx=-dx;
	do {
	  l1=l+dx;
	  for(i=0;i<N;i++) {
	xk[i]=x0[i]+l*S[i][iter1];
	xk1[i]=x0[i]+l1*S[i][iter1];
	c[i]=x0[i]+(l1+dx)*S[i][iter1];
	}
	z=func(xk);z1=func(xk1);z_=func(c);
	  if( ( z >= z1 ) && ( z1>= z_) ) l=l1;
	  else dx=dx/2;
	} while ( fabs( z1-z ) > eps );
  return(l1);
}

void init(void){
 int i,j;
  clrscr();
  printf("\nВыберите номер тестируемой функции:\n ");
  printf("\n0:   Функция Розенброка\n ");
  printf("\n     100(x2-x1^2)^2+(1-x1)^2\n ");
  printf("\n1:   4*(x1-5)^2+(x2-6)^2\n ");
  printf("\n2:   (x1+x2-11)^2+(x1-x2+7)^2\n ");
  printf("\n3:   (X1-5)^2+(X2-3)^2+(X3+10)^2\n");
  scanf("%d",&flag);
  printf("\nЧисло переменных в задаче ");
  scanf("%d",&N);
  printf("\nВведите начальную точку поиска X0:");
  for(i=0;i<N;i++){
   printf("\nКоордината x%d ",i);
   scanf("%f",&x[i]);
  }
  printf("\nТочость вычисления лямбда ");
  scanf("%f",&eps);
  for(i=0;i<Rasm;i++){
   xn[i]=x0[i]=xn1[i]=lambda[i]=0.0;
   for(j=0;j<Rasm;j++) S[i][j]=0.0;
  }
  clrscr();
return;
}
int prov_X(float *x1,float *x2){
 int i,p=0;
 for (i=0;i<N;i++){
  if ( fabs( x2[i]-x1[i] ) < 1e-10 ) p=(1);
  else p=0;
  }
return(p);
}
