import java.io.*;
import javax.swing.*;

class SCO10
{
  public static double[] gauss(double a[][],double b[])
  {
  int n=b.length;	  
  double x[]=new double[n];
  double carpan=0;
  double toplam=0;
  //gauss eleme
  int i,j,k;
  System.out.println("Orijinal Matris :\n"+Matrix.toString(a));
  for(k=0;k<(n-1);k++)
  {
    for(i=k+1;i<n;i++)
    {  carpan=a[i][k]/a[k][k];
       a[i][k]=0;//bu deyim sadece elimine matrisin doğru değerlerini
                 //hesaplamak için konulmuştur 
       for(j=k+1;j<n;j++)
       {   a[i][j]-=carpan*a[k][j]; }
           b[i]   =b[i]   -carpan*b[k];
	}
  }
  System.out.println("Elimine Matris :\n"+Matrix.toString(a));
  //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[] 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;
  System.out.println("Orijinal Matris :\n"+Matrix.toString(a));
  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;
	}
	  System.out.println("pivotlu Matris : k="+k+"\n"+Matrix.toString(a));
	//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];
	}
  }
  System.out.println("elimine prosesibitmiş matris : \n"+Matrix.toString(a));
  //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 void pivot(double a[][],int o[],double s[],int k)
  {// GaussLU için pivot metodu
    int n=a.length;
    int dummy1=0;
    double buyuk;
    double dummy=0;
    //pivotlama
	int p=k;
	buyuk=Math.abs(a[o[k]][k]);
	for(int ii=k+1;ii<n;ii++)
	{  dummy=Math.abs(a[o[ii]][k]/s[o[ii]]);
	   if(dummy > buyuk) {buyuk=dummy;p=ii;}
	}
	dummy1=o[p];
	o[p]=o[k];
	o[k]=dummy1;	   
  }
  
  public static int[] sirali_indeks(int n)
  {   // sıralı rakamları taşıyan bir vektör oluşturur 
	  int o[]=new int[n];
	  for(int i=0;i<n;i++) {o[i]=i;}
	  return o;
  }	  
  
  public static double[][] gaussLU(double ai[][],int o[])
  { //kısmi pivotlu gauss eleme yöntemi
  int n=ai.length;	    
  double a[][]=new double[n][n];
  double s[]=new double[n];
  double carpan=0;
  double toplam=0;
  double absaij;

  //gauss eleme
  int i,j,k,p,ii,jj;
  //System.out.println("Orijinal Matris :\n"+Matrix.toString(ai));
  for(i=0;i<n;i++)
  {for(j=0;j<n;j++){a[i][j]=ai[i][j];}}
  for(i=0;i<n;i++)
  { o[i]=i;s[i]=Math.abs(a[i][0]);
    for(j=1;j<n;j++)
      { absaij=Math.abs(a[i][j]);
        if(absaij>s[i]) {s[i]=absaij;}
      }
  }
  for(k=0;k<(n-1);k++)
  { pivot(a,o,s,k);
	//pivot referansını değiştir		
	//System.out.println("pivotlu Matris : k="+k+"\n"+Matrix.toString(a));
	//gauss elemeyi çözme  
    for(i=k+1;i<n;i++)
    {  carpan=a[o[i]][k]/a[o[k]][k];
       a[o[i]][k]=carpan;
       for(j=k+1;j<n;j++)
       {   a[o[i]][j]-=carpan*a[o[k]][j]; }
	}
  }
  return a;
  }
  
  public static double[] yerine_koyma(double ai[][],double bi[])
  {   int n=ai.length;
	  return yerine_koyma(ai,bi,sirali_indeks(n));
  }
  
  public static double[][] yerine_koyma(double ai[][],double bi[][])
  {   int n=ai.length;
	  return yerine_koyma(ai,bi,sirali_indeks(n));
  }  
  
  public static double[] yerine_koyma(double ai[][],double bi[],int o[])
  { //gauss LU çözümüyle LU indirgenmesi yapılmış Matris kullanarak lineer 
    //denklem sistemi kökleri
    int n=ai.length;
    double toplam;
    double x[]=new double[n];
     double a[][]=new double[n][n];
    double b[]=new double[n];
    int i,j;
  for(i=0;i<n;i++)
      {for(j=0;j<n;j++){a[i][j]=ai[i][j];};b[i]=bi[i];}   
  //System.out.println("a=\n "+Matrix.toString(a));
  //System.out.println("b=\n "+Matrix.toStringT(b));             
  for(i=1;i<n;i++)
      {toplam=b[o[i]];for(j=0;j<i;j++){toplam-=a[o[i]][j]*b[o[j]];};b[o[i]]=toplam;}
   //System.out.println("d=\n "+Matrix.toStringT(b));      
  x[n-1]=b[o[n-1]]/a[o[n-1]][n-1];
  for(i=(n-2);i>=0;i--)
      {toplam=0;      
       for(j=i+1;j<n;j++)      
        {toplam+=a[o[i]][j]*x[j];};
        x[i]=(b[o[i]]-toplam)/a[o[i]][i];
      }
  //System.out.println("d=\n "+Matrix.toStringT(x));        
  return x;              
  }  
  
  public static double[][] yerine_koyma(double ai[][],double bi[][],int o[])
  {
    int n=ai.length;
    int m=bi[0].length;
    double toplam;
    double x[][]=new double[n][m];
    double a[][]=new double[n][n];
    double b[][]=new double[n][m];
    int i,j,k;
  for(i=0;i<n;i++)
      {for(j=0;j<n;j++){a[i][j]=ai[i][j];};for(k=0;k<m;k++) {b[i][k]=bi[i][k];}}   
  //System.out.println("a=\n "+Matrix.toString(a));
  //System.out.println("b=\n "+Matrix.toStringT(b));             
  for(k=0;k<m;k++)
  {
  for(i=1;i<n;i++)
      {toplam=b[o[i]][k];for(j=0;j<i;j++){toplam-=a[o[i]][j]*b[o[j]][k];};b[o[i]][k]=toplam;}
   //System.out.println("d=\n "+Matrix.toStringT(b));      
  x[n-1][k]=b[o[n-1]][k]/a[o[n-1]][n-1];
  for(i=(n-2);i>=0;i--)
      {toplam=0;      
       for(j=i+1;j<n;j++)      
        {toplam+=a[o[i]][j]*x[j][k];};
        x[i][k]=(b[o[i]][k]-toplam)/a[o[i]][i];
      }
  }//kin sonu   
  //System.out.println("d=\n "+Matrix.toStringT(x));        
  return x;          
  }
      
  public static double[] gaussjordan(double a[][],double b[])
  { //pivotsuz
  int n=b.length;	  
  double x[]=new double[n];
  double carpan=0;
  double toplam=0;
  double buyuk;
  double dummy=0;
  int i,j,k,p,ii,jj;
  for(k=0;k<n;k++)
  { //gauss jordan elemeyi çözme
	for(j=k+1;j<n;j++)
	{ a[k][j]/=a[k][k]; }
	  b[k]/=a[k][k];
	a[k][k]=1.0;
	  
    for(i=0;i<n;i++)
    {  if(i!=k)
       {
	      carpan=a[i][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];
       }    
	}
  }
  for(i=0;i<n;i++)
  {
    x[i]=b[i];
  }
  return x;
  } 	
  
public static double[][] choleskyLU(double c[][])
{
// cholesky LU 
// sadece simetrik matrisler içindir
// 	
double factor=0;
double buyuk;
int i,j,k,p,ii,jj;
int n=c.length;
double d[][]=new double[n][n];
double dummy;
double toplam;
for(i=0;i<n;i++)
{for(j=0;j<n;j++) d[i][j]=c[i][j];}
for(k=1;k<=n;k++)
{
 for(i=1;i<(k-1);i++)
    {toplam=0;;
     for(j=1;j<=(i-1);j++)
     { toplam+=d[i-1][j-1]*d[k-1][j-1]; }
    d[k-1][i-1]=(d[k-1][i-1]-toplam)/d[i-1][i-1];
    }
 toplam=0.0;
 for(j=1;j<=(k-1);j++)
 { toplam+=d[k-1][j-1]*d[k-1][j-1]; }
 d[k-1][k-1]=Math.sqrt((d[k-1][k-1]-toplam));      
}
return d;
}

public static double[][] crautLU(double c[][])
{
//craut LU ayrıştırma, pivotsuz

int n=c.length;
double sum;
int i,j,k; 
double d[][]=new double[n][n];
for(i=0;i<n;i++)
{for(j=0;j<n;j++) d[i][j]=c[i][j];}

for(j=1;j<=n;j++)
{ 
  for(i=1;i<j;i++)
    {
    sum=d[i-1][j-1];
    for(k=1;k<i;k++)
	{ sum-=d[i-1][k-1]*d[k-1][j-1];}
    d[i-1][j-1]=sum;
    }
  for(i=j;i<=n;i++)
    {
    sum=d[i-1][j-1];
    for(k=1;k<j;k++)
      {sum-=d[i-1][k-1]*d[k-1][j-1];}
    d[i-1][j-1]=sum;
    }
  if(j != n)
  { for(i=j+1;i<=n;i++)
       d[i-1][j-1]/=d[j-1][j-1];
  }    
}    
return d;
}

  public static double[][] I(int n)
  {
  //birim matris
  double b[][];
  b=new double[n][n];
  for(int i=0;i<n;i++)
    b[i][i]=1.0;
  return b;
  }
  
  public static double[][] inverse(double a[][])
  {
  int n=a.length;	  
  int q[]=new int[n];
  double c[][]=gaussLU(a,q);
  double s[][]=yerine_koyma(c,I(n),q);
  return s;
  }
  
  public static double [][] AXB(double a[][],double b[][])
  {//denklem sistemi çözümü b matrisi için	  
  int n=a.length;	  
  int q[]=new int[n];
  double c[][]=gaussLU(a,q);
  double s[][]=yerine_koyma(c,b,q);
  return s;
  }
  
  public static double [] AXB(double a[][],double b[])
  {
  //denklem sistemi çözümü b vektörü için	  
  int n=a.length;	  
  int q[]=new int[n];
  double c[][]=gaussLU(a,q);
  double s[]=yerine_koyma(c,b,q);
  return s;
  }
  
  public static double [] gauss_seidel(double a[][],double b[])
  {
  double lambda=1.2;
  int n=a.length;
  //ilk x tahmin değerleri 0 olarak alındı
  double x[]=new double[n];
  return gauss_seidel(a,b,x,lambda);
  }
  
  public static double [] gauss_seidel(double a[][],double b[],double x[],double lambda)
  {
  //denklem sistemi çözümü b iteratif gauss_seidel metodu metodu
  //yakınsama faktörü lambda ile birlikte verilmiş formül	  
  int n=a.length;
  int imax=300;
  double es=1.0e-20;
  double dummy=0;
  double ea=1e-1;
  double sum=0;
  double old=0;
  int iter=0;
  int sentinel=0;
  for(int i=0;i<n;i++)
  {  dummy=a[i][i];
     for(int j=0;j<n;j++)
       {a[i][j]/=dummy;}
     b[i]/=dummy;
  }
  for(int i=0;i<n;i++)
  {  sum=b[i];
     for(int j=0;j<n;j++)
       {if(i!=j)sum-=a[i][j]*x[j];}
     x[i]=sum;
  }
  iter=0;
  do
  {
  sentinel=1;
  for(int i=0;i<n;i++)
     {
	 old=x[i];
	 sum=b[i];
	 for(int j=0;j<n;j++)
	    {if(i!=j) sum-=a[i][j]*x[j];}
	    x[i]=lambda*sum+(1.0-lambda)*old;
	    if(sentinel==1 && x[i]!=0.0 ) {ea=Math.abs((x[i]-old)/x[i])*100.0;}
	    if(ea<es) sentinel=0; 
     }
  iter++;
  }while(sentinel==1 && iter<imax);  
  if(iter>=imax) System.out.println("Maksimum iterasyon sayısı aşıldı sonuç geçerli olmayabilir iter = "+iter);
  return x;
  }
  
  //bantmatris çözümü
  public static double [] thomas(double a[][],double r[])
  {
  int n=a.length;
  double f[]=new double[n];
  double e[]=new double[n];
  double g[]=new double[n];
  double x[]=new double[n];
  for(int i=0;i<n;i++)     {f[i]=a[i][i];}
  for(int i=0;i<(n-1);i++) {g[i]=a[i][i+1];}
  for(int i=0;i<(n-1);i++)     {e[i+1]=a[i+1][i];}
  for(int k=1;k<n;k++)
     {e[k]=e[k]/f[k-1];
      f[k]=f[k]-e[k]*g[k-1];
     }
  for(int k=1;k<n;k++)
     {r[k]=r[k]-e[k]*r[k-1];
     }
  x[n-1]=r[n-1]/f[n-1];   
  for(int k=(n-2);k>=0;k--)
     {x[k]=(r[k]-g[k]*x[k+1])/f[k];}
  return x;      
  }
  
  public static double [] thomas(double f[],double e[],double g[],double r[])
  {
  int n=f.length;
  double x[]=new double[n];
  for(int k=1;k<n;k++)
     {e[k]=e[k]/f[k-1];
      f[k]=f[k]-e[k]*g[k-1];
     }
  for(int k=1;k<n;k++)
     {r[k]=r[k]-e[k]*r[k-1];
     }
  x[n-1]=r[n-1]/f[n-1];   
  for(int k=(n-2);k>=0;k++)
     {x[k]=(r[k]-g[k]*x[k+1])/f[k];}
  return x;      
  }  
  public static void main(String args[]) throws IOException
  {
  double a[][]={{4,-1,-1},{6,8,0},{-5,0,12}};
  double b[]={-2,45,80};
  String s="ters matris : \n"+Matrix.toString(inverse(a));
  //double a[][]={{1,7,-4},{4,-4,9},{12,-1,3}};
  //double b[]={-51,62,8};
  int n=a.length;
  double x[]=new double[n];
  int o[]=new int[n];
  double c[][]=gaussLU(a,o);
  s+="Gauss LU: \n"+Matrix.toString(c);  
  x=yerine_koyma(c,b,o);
  s+="yerine koyma çözümü : \n"+Matrix.toStringT(x);
  s+="gauss seidel \n"+Matrix.toStringT(gauss_seidel(a,b));
  JOptionPane.showMessageDialog(null,s,"SCO10 gaussLU ve Gauss-seidel metodu",JOptionPane.PLAIN_MESSAGE);
  }
}