/// OPTIMİZASYON
//  2 derece polinom interpolasyon kullanarak optimizasyon 
import java.util.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
import javax.swing.*;

//prototip fonksiyon sınıfı
abstract class f_xr
{
  abstract double func(double x,int equation_ref);
}
//sizin eğri uydurmada kullanacağınız fonksiyonu tanımlayan sınıf
//örnek fonksiyon :
// y=a[0]+a[1]*x + a[2]*x*x + a[3]/x+ a[4]/x*x 
class fxr extends f_xr
{
	double func(double x,int i)
	{	
     double xx=1.0;
      if(i==0) xx=1.0;
      else if(i==1) xx=x;
      else if(i==2) xx=x*x;
      else if(i==3) xx=1.0/x; 
      else if(i==4) xx=1.0/(x*x);  
   return xx;
	}
} 

class f_GenelEKK extends f_x
{
  double E[];
  public f_GenelEKK(String s1,int m)
  {	  
  double x[];
  double y[];
  double a[][]=Text.readDoubleT(s1);
  x=a[0];
  y=a[1];
  E=EKKgenel(x,y,m);
  }

public double func(double x)
{
// this function calculates the value of
// least square curve fitting function
fxr fi=new fxr();
int n=E.length;
double ff=0;
if(n!=0.0)
  { 
  for(int i=n-1;i>=0;i--)
   {ff+=E[i]*fi.func(x,i);}
  } 
return ff;
}

//Genel en küçük kareler metodu en kucuk kareler metodu	
	  
  public static double[] pivotlugauss(double a[][],double b[])
  { //kısmi pivotlu gauss eleme yöntemi
  int n=b.length;	  
  double x[]=new double[n];
  double carpan=0;
  double toplam=0;
  double buyuk;
  double dummy=0;
  //gauss eleme
  int i,j,k,p,ii,jj;
  for(k=0;k<(n-1);k++)
  { //pivotlama
	p=k;
	buyuk=Math.abs(a[k][k]);
	for(ii=k+1;ii<n;ii++)
	{  dummy=Math.abs(a[ii][k]);
	   if(dummy > buyuk) {buyuk=dummy;p=ii;}
	}
	if(p!=k)
	{ for(jj=k;jj<n;jj++)
	  { dummy=a[p][jj];
	    a[p][jj]=a[k][jj];
	    a[k][jj]=dummy;
	  }
	  dummy=b[p];
	  b[p]=b[k];
	  b[k]=dummy;
	}
	//gauss elemeyi çözme  
    for(i=k+1;i<n;i++)
    {  carpan=a[i][k]/a[k][k];
       a[i][k]=0;
       for(j=k+1;j<n;j++)
       {   a[i][j]-=carpan*a[k][j]; }
           b[i]   =b[i]   -carpan*b[k];
	}
  }
  //geriye doğru yerine koyma
  x[n-1]=b[n-1]/a[n-1][n-1];
  for(i=n-2;i>=0;i--)
  {
    toplam=0;
    for(j=i+1;j<n;j++)
    {  toplam+=a[i][j]*x[j];}
    x[i]=(b[i]-toplam)/a[i][i];
  }
  return x;
}
  
public static double[] EKKgenel(double xi[],double yi[],int n)
{
fxr f=new fxr();
int l=xi.length;
int i,j,k;
int np1=n+1;
double A[][];
A=new double[np1][np1];
double B[];
B=new double[np1];
double X[];
X=new double[np1];
for(i=0;i<n+1;i++)
  {  B[i]=0;
	 for(j=0;j<np1;j++)
     {
	 A[i][j]=0.0;    
     for(k=0;k<l;k++) A[i][j]+=f.func(xi[k],i)*f.func(xi[k],j);
     }
     for(k=0;k<l;k++) B[i]+= f.func(xi[k],i)*yi[k];
  }
System.out.println("A = \n"+Matrix.toString(A));
System.out.println("B = \n"+Matrix.toStringT(B));  
X=pivotlugauss(A,B);
//X=B/A;
double max=0;
for(i=0;i<n+1;i++)
 if(Math.abs(X[i]) > max) max = Math.abs(X[i]);
for(i=0;i<n+1;i++)
 if((Math.abs(X[i]/max) > 0) && (Math.abs(X[i]/max) < 1.0e-100)) X[i]=0;
Text.printT(X,"Genel Fonksiyon katsayılar vektörü"); 
return X;
}

}

public class FOPO1GenelEKK
{
public static double golden(f_x f,double a,double b,double epsilon)
{return golden(f,a,b,epsilon,1.0e-10,0);}
public static double golden(f_x f,double a,double b)
{return golden(f,a,b,1.0e-10,1.0e-10,0);}
public static double golden(f_x f,double a,double b,double epsilon,double delta,int print)
{
//  f fonksiyonunun minimumunu bulur
// not  maximum f(x) = minimum (-f(x))
    double r1 = (Math.sqrt(5.0)-1.0)/2.0; // golden ratio
    double r2 = r1*r1;
    double h = b - a;
    double ya = f.func(a);
    double yb = f.func(b);
    double c = a + r2*h;
    double d = a + r1*h;
    double yc = f.func(c);
    double yd = f.func(d);
    int k = 1;
    double dp,dy,p,yp;
    while ((Math.abs(yb-ya)>epsilon) || (h>delta))
    {
      k++;
      if (yc<yd)
        {
        b = d;
        yb = yd;
        d = c;
        yd = yc;
        h = b - a;
        c = a + r2 * h;
        yc = f.func(c);
        }
      else
       {
         a = c;
         ya = yc;
         c = d;
         yc = yd;
         h = b - a;
         d = a + r1 * h;
         yd = f.func(d);
       }//end of if
    }//end of while
    dp = Math.abs(b-a);
    dy = Math.abs(yb-ya);
    p = a;
    yp = ya;
    if (yb<ya)
    {
      p = b;
      yp = yb;
    }
    if(print==1)
    {System.out.println("x min = "+p+"ymin = "+yp+"error of x ="+dp+"error of y"+dy); }
    return p;
}

     public static void main (String args[]) throws java.io.IOException 
     { 
	 f_GenelEKK  f=new f_GenelEKK ("in.txt",4);    
     double a,b;
     a=Double.parseDouble(JOptionPane.showInputDialog(" Fonksiyonun alt sınırını giriniz a : "));
     b=Double.parseDouble(JOptionPane.showInputDialog(" Fonksiyonun üst sınırını giriniz b : "));
     double r;
     r= golden(f,a,b,1.0e-10,1.0e-5,0);
     JOptionPane.showMessageDialog(null," optimizasyon değeri  : "+r+"\nFonksiyon değeri : "+f.func(r),
     "Genel En Küçük kareler eğri uydurmalı Fibonacchi sayısal veri optimizasyonu : ",JOptionPane.PLAIN_MESSAGE);
     Plot pp=new Plot(f,-4.0,6.0,200);
     pp.addData("in.txt");
     pp.setPlotType(1,38);   // veriyi beşköşe yıldız olarak çiz
     pp.setColor(1,Color.blue); // veriyi mavi çiz
     pp.plot();
     } 
}
