Oppure

Loading
25/05/12 15:30
Puffetta
Ciao a tuttti!
ho scritto questo programma che deve risolvere un sistema lineare del tipo Ax=b con il metodo di gauss o di cholesky(metodo scelto dall'utente) ho però un grosso problema: il metodo di gauss funziona perfettamente(a quanto pare), mentre se uso il metodo di cholesky il programma va in loop. mi potreste aiutare a trovare l'errore? io non riesco a vederlo:-(

grazie a tutti!!!!

/*Risoluzione di sistemi lineari usando metodi diretti quali metodo di eliminazione di gauss, cholesky e thomas*/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

typedef double matrice[300][300];
typedef double vettore[300];


int sceglimatrice();
void creamatrice(int mat, matrice A, vettore b, int n);
double U();
void prodotto(matrice A, matrice B, int n);
int sceglimetodo(int mat);
void gauss(matrice A, vettore b, vettore x, int n);
void riduci(matrice, vettore, int);
int cercapivot(vettore, int, int);
void scambiarighe(matrice, int, int, int);
void cholesky(matrice A, vettore b, vettore x, int n);
void risolvi_sup(matrice A, vettore b,vettore x, int n);
void risolvi_inf(matrice A, vettore b,vettore x, int n);


int main()
{
      int n, metodo, mat;
      matrice A;
      vettore x, b;
      
      printf("Risolviamo il sistema lineare Ax=b.\nInseriamo tutti i dati riguardanti la matrice A\n");
      
      mat=sceglimatrice();

      printf("\nQuante righe e colonne ha la matrice A? n=");
      scanf("%d", &n);
      
      creamatrice(mat, A, b, n);
      
      metodo=sceglimetodo(mat);
      /*
      for(int i=1; i<=n; i++)
         {
            for(int j=1; j<=n; j++)
            printf("  %lf  ", A[i][j]);

	        printf("\n");
          }

      
      for(int i=1; i<=n; i++) printf("\t%lf", b[i]);
      
      printf("\nmetodo=%d\n", metodo);
      */
      
      switch(metodo)
          {
            case 1:  gauss(A, b, x, n);
                     break;
             
            case 2:  cholesky(A, b, x, n);
                     break;
          }
     
     printf("\n\n Le soluzioni del sistema sono:");
     
     for(int i=1; i<=n; i++) printf("\t%lf", x[i]);

     system("PAUSE");
     return 0;
}


double U()
{ 
       return (double)rand()/RAND_MAX;
} 


int sceglimatrice()
{
     int mat=0;

     printf("Scegliere il tipo da matrice da utilizzare:\n");

     printf("\nMATRICE RANDOM\n\n");
     printf(" 1) Matrice randomica generica\n\n");
     printf(" 2) Matrice randomica simmetrica e definita positiva\n\n");
     printf(" 3) Matrice randomica tridiagonale\n\n");
     printf(" 4) Matrice randomica diagonale dominante\n");
     printf("\nMATRICE INSERITA DA TASTIERA\n\n");
     printf(" 5) Matrice generica\n\n");
     printf(" 6) Matrice simmetrica e definita positiva\n\n");
     printf(" 7) Matrice tridiagonale\n\n");
     printf(" 8) Matrice diagonale dominante\n\n");
     
     printf("Quale tipo di matrice devo usare? ");
     scanf("%d", &mat);     

     while((mat<=0)||(mat>8))
       {
          printf("\nIl valore inserito non e' corretto. Inserire nuovamente il valore  ");
          scanf("%d", &mat);
       }
     
     return mat;
}

//Questa funzione crea la matrice in base alle esigenze dell'utente
void creamatrice(int mat, matrice A, vettore b, int n)
{
   srand(time(0));
   
   switch(mat)     
     {
        //Matrice randomica generica e vettore randomico 
        case 1:
             {                     
	   	       for(int i=1; i<=n; i++)
    		  	   {
                      for(int j=1; j<=n; j++)
                 		               A[i][j]=U();//matrice
	            			   
 			          b[i]=U();//vettore
                   }
             }
             break;
        
        //Matrice randomica simmetrica e definita positiva e vettore randomico  
        case 2:
             { 
                matrice B;
                
                for(int i=1; i<=n; i++)
           		  	{
                      for(int j=i; j<=n; j++)
						{
                          B[i][j]=U();
                          B[j][i]=B[i][j];
						}
                      
                             
                      b[i]=U();
                     } 
                
                //Uso la matrice B per creare la matrice A richiesta facendo A=(Bt)*B con B simmetrica
                prodotto(A, B, n);   
             }
             break;
        
        //Matrice randomica tridiagonale e vettore randomico            
        case 3:
             {       
               for(int i=1; i<=n; i++)
       		      {
					  A[i][i]=U();
                       
                      if(i!=n)
                           A[i+1][i]=U();
                          
                      if(i!=1)
                           A[i-1][i]=U();
                          
                      b[i]=U();
                  }
			}
			break;
            
        case 4:
             {
                  //diagonale dominante!!!!!!
             }
             break;
     }
   
   //Matrici inserite da tastiera. uso dunque lo scanf per acquisire le componenti
   if((mat==5)||(mat==6)||(mat==7)||(mat==8))
      {
         printf("\nInserire i coefficienti della matrice A:");
         for(int i=1; i<=n; i++)
        	for(int j=1; j<=n; j++)
               	       	scanf("%lf", &(A[i][j]));
         
         printf("\nInserire il vettore dei termini noti");
         for(int i=1; i<=n; i++)
             {
                printf("Inserire il termine noto b[%d]=", i);
                scanf("%lf", &b[i]);
             }                                                        
      }
}


int sceglimetodo(int mat)
{
  int metodo=0;
    
  printf("\nQuale metodo devo usare per risolvere il sistema lineare quadrato Ax=b?\n1.Gauss   2.Cholesky   3.Thomas\n");
  scanf("%d", &metodo);
  
  while((metodo<=0)||(metodo>4))
	{
       printf("\n Il valore inserito non e' corretto!!! Scegliere di nuovo il metodo ");
       scanf("%d", &metodo);
	}
  
  if((metodo==2)&&((mat==2)||(mat==6)))
                                   return metodo;
          
  if((metodo==3)&&((mat==3)||(mat==7)))
                                   return metodo;
  
  while((metodo!=1)&&(mat!=1)&&(mat!=5))
       {
          printf("\nIl metodo scelto non puo' essere usato sulla matrice A.\nscegliere un altro metodo  ");
          scanf("%d", &metodo);
          
          if((metodo==2)&&((mat==2)||(mat==6)))
                                         break;
          
          if((metodo==3)&&((mat==3)||(mat==7)))
                                          break;                                                                 
      }
      
  return metodo;
}


void gauss(matrice A, vettore b, vettore x, int n)
{
  riduci(A, b, n);
      
  risolvi_sup(A, b, x, n);
}


void riduci(matrice A, vettore b, int n)
{
     double mik; vettore kcolonna; int kmax;
     
     for(int k=1; k<=n-1; k++)
             {
                  for(int h=k; h<=n; h++)
                          {
                               kcolonna[h]=A[h][k];
                               
                               kmax=cercapivot(kcolonna, k, n);
                               
                               if(kmax!=k)    scambiarighe( A, k, kmax, n);                               
                          }
             
                  for(int i=k+1; i<=n; i++)
                     {
                            mik=A[i][k]/A[k][k];
                            
                            for(int j=k+1; j<=n; j++)       A[i][j]=A[i][j]-mik*A[k][j];
                            
                            b[i]=b[i]-mik*b[k];
                     }
             }
     return;     
}

int cercapivot(vettore kcolonna, int k, int n)
{
    double maxmodulo=fabs(kcolonna[k]);
    
    int imax=k;
    
    for(int i=k+1; i<=n; i++)
                   if(!maxmodulo)        exit (1);
            
    return imax;
}


void scambiarighe(matrice A, int k, int kmax, int n)
{
     double aux;
     
     for(int j=k; j<=n; j++)
             {
                  aux=A[j][k];
     
                  A[j][k]=A[j][kmax];
     
                  A[j][kmax]=aux;
             }
     return;
}


void cholesky(matrice A, vettore b, vettore x, int n)
{
     printf(" ********** ");
     matrice H, HT;
     vettore y;
     
     printf(" ++++++++++  ");
     
     //creo la matrice H
     for(int i=1; i<=n; i++)
       for(int j=1; j<=n; j++)
           {
              if(i==j==1)
                 H[i][j]=sqrt(A[i][i]);
                 
              if(j<i)
                  H[i][j]=0;
                  
              if(j>i)
                {
                  double somma=0;
                  
                  for(int k=1; k<=j-1; k++)
                                somma+=H[i][k]*H[j][k];
                                
                  H[i][j]=(A[i][j]-somma)/H[j][j];     
                }   
              
              if(j==i)
                {
                  double somma=0;
                  
                  for(int k=1; k<=i-1; k++)
                                somma+=pow(H[i][k], 2);
                                
                  H[i][j]=A[i][i]-somma;     
                }    
           }    
     
     for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
                           HT[i][j]=H[j][i];
                           
     risolvi_inf(HT, b, y, n);
     
     risolvi_sup(H, y, x, n);
}

//Questa funzione mi risolve un sistema la cui matrice e' triangolare inferiore
void risolvi_inf(matrice A, vettore b,vettore x, int n)
{    
     x[1]=b[1]/A[1][1];
     
     for(int i=2; i<=n; i++)
             {
		for(int j=1; j<=i; j++)        b[i]=b[i]-A[i][j]*x[j];
                    
                x[i]=b[i]/A[i][i];
             }
     return;   
}


//Questa funzione mi risolve un sistema la cui matrice e' triangolare superiore
void risolvi_sup(matrice A, vettore b,vettore x, int n)
{    
     x[n]=b[n]/A[n][n];
     
     for(int i=n-1; i>=1; i--)
             {      
                    for(int j=i+1; j<=n; j++)        b[i]=b[i]-A[i][j]*x[j];
                    
                    x[i]=b[i]/A[i][i];
             }
     return;   
}


//Questa matrice mi fa il prodotto (Bt)*B e pone il risultato della nuova matrice A
void prodotto(matrice A, matrice B, int n)
{
   for(int i=1; i<=n; i++)
       for(int j=1; j<=n; j++)
             {
               A[i][j]=0;
               
               for(int k=1; k<=n; k++)
                       A[i][j]=A[i][j]+B[i][k]*B[j][k];
             }
   return;
}     
aaa