Algoritmo per i metodi di Jacobi e Gauss-Seidel in C

di il
5 risposte

Algoritmo per i metodi di Jacobi e Gauss-Seidel in C

Buongiorno a tutti e buon inizio di 2022! Vi sottopongo quello che per me sta diventando un vero fardello. Ho scritto il codice sotto riportato, ma non riesco ad individuare quale sia l'errore che non mi permette di avere un output corretto, per l'esattezza ottengo che le soluzioni sono tutte uguali a 0.0000 e il numero di iterazioni ottenuto risulta essere sempre 1. Grazie per la vostra attenzione e il vostro eventuale aiuto.
/*Metodi di Jacobi e Gauss-Seidel*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX 100
#define MAX_NORMA 100
#define MAX_ITER 10000
#define MAX_DIM 100

void leggiMatrice (int *n, int *m, float A[MAX_DIM][MAX_DIM]) { //n=numero di righe, m=numero di colonne
int i,j; //i=indice di riga, j=indice di colonna
printf ("Numero di righe (n): \n");
scanf ("%d",n);
printf ("Numero di colonne (m): \n");
scanf ("%d",m);
for (i=0;i<*n;i++) {
printf ("Inserisci gli elementi della riga %d: \n",i);
for (j=0;j<*m;j++) {
scanf ("%f",&A[j]);
}
}
}

void stampaVettore (int n, float v[MAX_DIM]) {
int i;
for (i=0;i<n;i++) {
printf ("%f",v);
printf ("\n");
}
printf ("\n");
}

void copiaVettore (int n, float x[], float v[]) {
int i;
for (i=0;i<n;i++) {
v=x;
}
}

float jacobi_gs (int n, float x[], float A[MAX][MAX], int indice) { //indice=1 per Jacobi oppure indice=2 per Gauss-Seidel
int k=0,i,j;
float v[MAX], sum, norma=MAX_NORMA, eps=1e-6;
while (norma>eps) { //Condizioni di arresto
copiaVettore (n,x,v); //Si usa il vettore di appoggio non solo per il metodo di Jacobi, ma anche per la norma
for (j=0;j<n;j++) { //j scorre le soluzioni x(j)
sum=0;
for (i=0;i<n;i++) {
if (i!=j) {
if (indice==1)
sum=sum+A[j]*v; //Metodo di Jacobi
else
sum=sum+A[j]*x; //Metodo di Gauss-Seidel (variabili già aggiornate)
}
}
x[j]=(1/A[j][j])*(A[j][n]-sum);
}
norma=0;
for (j=0;j<n;j++) {
norma=norma+pow(x[j]-v[j],2); //Si aggiorna la norma ||x(j)-x(j-1)|| per le condizioni di arresto
}
norma=sqrt(norma);
k++; //k=numero di iterazioni (per contarle)
if (k>=MAX_ITER) //Numero massimo di iterazioni
break;
}
return (k);
}

void dominanzaDiagonale (int n, float A[MAX][MAX]) {
int i,j; //i=indice di riga, j=indice di colonna
for (i=0;i<n;i++) { //Si scorrono le righe della matrice
float R=0; //R=somma iterata degli elementi che NON si trovano sulla diagonale della riga i
for (j=0;j<n;j++) { //Si scorrono le colonne della matrice
if (j!=i)
R=R+fabs(A[j]);
}
if (fabs(A[i])<=R) {
printf ("\nLa matrice non e' strettamente dominante diagonale, pertanto il sistema potrebbe non convergere.");
break; //Si interrompe la verifica se già si scopre la non dominanza diagonale alla riga i
}
}
}

int main () {
int i,n,m,k,indice;
float x[MAX], A[MAX][MAX];
printf ("\n");
printf ("La convergenza e' assicurata con una matrice dominante diagonale.\n");
leggiMatrice (&n,&m,A);
dominanzaDiagonale (n,A);
do {
printf ("\nDigita 1 per Jacobi, 2 per Gauss-Seidel, 0 per uscire.\n");
scanf ("%d",&indice);
while (indice!=1 && indice!=2 && indice!=0) { //Controllo dell'indice
printf ("Inserisci 1,2 oppure 0: \n");
scanf ("%d",&indice);
}
if (indice!=0) {
for (i=0;i<n;i++) {
x[i]=0;
}
k=jacobi_gs(n,x,A,indice); //I due metodi sono stati implementati nella stessa funzione jacobi_gs; quindi passo indice alla funzione jacobi_gs
printf ("\nLa soluzione e': \n");
stampaVettore (n,x);
printf ("Il numero di iterazioni eseguite e': %d. \n",k);
}
}
while (indice!=0); //Condizione per uscire
printf ("\nCiao!\n");
return (0);
}

5 Risposte

  • Re: Algoritmo per i metodi di Jacobi e Gauss-Seidel in C

    Usa i tag CODE se no non si capisce...
  • Re: Algoritmo per i metodi di Jacobi e Gauss-Seidel in C

    Mi scuso tantissimo. ecco il codice ben visibile.
    /*Metodi di Jacobi e Gauss-Seidel*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define MAX 100
    #define MAX_NORMA 100
    #define MAX_ITER 10000
    #define MAX_DIM 100
    
    void leggiMatrice (int *n, int *m, float A[MAX_DIM][MAX_DIM]) { //n=numero di righe, m=numero di colonne
    int i,j; //i=indice di riga, j=indice di colonna
    printf ("Numero di righe (n): \n");
    scanf ("%d",n);
    printf ("Numero di colonne (m): \n");
    scanf ("%d",m);
    for (i=0;i<*n;i++) {
    printf ("Inserisci gli elementi della riga %d: \n",i);
    for (j=0;j<*m;j++) {
    scanf ("%f",&A[j]);
    }
    }
    }
    
    void stampaVettore (int n, float v[MAX_DIM]) {
    int i;
    for (i=0;i<n;i++) {
    printf ("%f",v);
    printf ("\n");
    }
    printf ("\n");
    }
    
    void copiaVettore (int n, float x[], float v[]) {
    int i;
    for (i=0;i<n;i++) {
    v=x;
    }
    }
    
    float jacobi_gs (int n, float x[], float A[MAX][MAX], int indice) { //indice=1 per Jacobi oppure indice=2 per Gauss-Seidel
    int k=0,i,j;
    float v[MAX], sum, norma=MAX_NORMA, eps=1e-6;
    while (norma>eps) { //Condizioni di arresto
    copiaVettore (n,x,v); //Si usa il vettore di appoggio non solo per il metodo di Jacobi, ma anche per la norma
    for (j=0;j<n;j++) { //j scorre le soluzioni x(j)
    sum=0;
    for (i=0;i<n;i++) {
    if (i!=j) {
    if (indice==1)
    sum=sum+A[j]*v; //Metodo di Jacobi
    else
    sum=sum+A[j]*x; //Metodo di Gauss-Seidel (variabili già aggiornate)
    }
    }
    x[j]=(1/A[j][j])*(A[j][n]-sum);
    }
    norma=0;
    for (j=0;j<n;j++) {
    norma=norma+pow(x[j]-v[j],2); //Si aggiorna la norma ||x(j)-x(j-1)|| per le condizioni di arresto
    }
    norma=sqrt(norma);
    k++; //k=numero di iterazioni (per contarle)
    if (k>=MAX_ITER) //Numero massimo di iterazioni
    break;
    }
    return (k);
    }
    
    void dominanzaDiagonale (int n, float A[MAX][MAX]) {
    int i,j; //i=indice di riga, j=indice di colonna
    for (i=0;i<n;i++) { //Si scorrono le righe della matrice
    float R=0; //R=somma iterata degli elementi che NON si trovano sulla diagonale della riga i
    for (j=0;j<n;j++) { //Si scorrono le colonne della matrice
    if (j!=i)
    R=R+fabs(A[j]);
    }
    if (fabs(A[i])<=R) {
    printf ("\nLa matrice non e' strettamente dominante diagonale, pertanto il sistema potrebbe non convergere.");
    break; //Si interrompe la verifica se già si scopre la non dominanza diagonale alla riga i
    }
    }
    }
    
    int main () {
    int i,n,m,k,indice;
    float x[MAX], A[MAX][MAX];
    printf ("\n");
    printf ("La convergenza e' assicurata con una matrice dominante diagonale.\n");
    leggiMatrice (&n,&m,A);
    dominanzaDiagonale (n,A);
    do {
    printf ("\nDigita 1 per Jacobi, 2 per Gauss-Seidel, 0 per uscire.\n");
    scanf ("%d",&indice);
    while (indice!=1 && indice!=2 && indice!=0) { //Controllo dell'indice
    printf ("Inserisci 1,2 oppure 0: \n");
    scanf ("%d",&indice);
    }
    if (indice!=0) {
    for (i=0;i<n;i++) {
    x[i]=0;
    }
    k=jacobi_gs(n,x,A,indice); //I due metodi sono stati implementati nella stessa funzione jacobi_gs; quindi passo indice alla funzione jacobi_gs
    printf ("\nLa soluzione e': \n");
    stampaVettore (n,x);
    printf ("Il numero di iterazioni eseguite e': %d. \n",k);
    }
    }
    while (indice!=0); //Condizione per uscire
    printf ("\nCiao!\n");
    return (0);
    }
  • Re: Algoritmo per i metodi di Jacobi e Gauss-Seidel in C

    Ho copiato il codice in un IDE e mi ha mostrato parecchi problemi: ad esempio con GCC su Linux non compila; scorrendo il codice si vedono cose che non potrebbero funzionare in C (che però non vengono segnalate come problematiche, è una feature del C), ma che non fanno quello che pensi debbano fare, ad esempio:
    void stampaVettore (int n, float v[MAX_DIM]) {
    int i;
    for (i=0;i<n;i++) {
    printf ("%f",v);
    printf ("\n");
    }
    printf ("\n");
    }
    v è un puntatore a float, per cui la relativa printf non ti stampa il contenuto dell'elemento i-esimo del vettore, ma l'indirizzo in memoria di v[0].
  • Re: Algoritmo per i metodi di Jacobi e Gauss-Seidel in C

    Andrea Quaglia ha scritto:


    Ho copiato il codice in un IDE e mi ha mostrato parecchi problemi: ad esempio con GCC su Linux non compila; scorrendo il codice si vedono cose che non potrebbero funzionare in C (che però non vengono segnalate come problematiche, è una feature del C), ma che non fanno quello che pensi debbano fare, ad esempio:
    void stampaVettore (int n, float v[MAX_DIM]) {
    int i;
    for (i=0;i<n;i++) {
    printf ("%f",v);
    printf ("\n");
    }
    printf ("\n");
    }
    v è un puntatore a float, per cui la relativa printf non ti stampa il contenuto dell'elemento i-esimo del vettore, ma l'indirizzo in memoria di v[0].
    Ciao, grazie della tua risposta. Purtroppo non ho ben capito come potrei risolvere il problema. Provo un pò a rivedermi per l'ennesima volta da capo il programma che per assurdo ( a questo punto) mi viene compilato bene .
  • Re: Algoritmo per i metodi di Jacobi e Gauss-Seidel in C

    Andrea Quaglia ha scritto:


    v è un puntatore a float, per cui la relativa printf non ti stampa il contenuto dell'elemento i-esimo del vettore, ma l'indirizzo in memoria di v[0].
    Presumo dipenda dal fatto che abbia messo tra tag code non il codice originale, ma quello precedentemente postato dove i [ii] sono andati persi.
Devi accedere o registrarti per scrivere nel forum
5 risposte