Método de Power para calcular o autovelor dominante de uma matriz
Publicado por David Lorente 18/12/2005
[ Hits: 8.871 ]
Homepage: .
Esse é um programa que que fiz para a disciplina de análise numérica. Ele utiliza o algoritmo de power para calcular o autovalor dominante (em módulo) de uma matriz real e seu autovetor associado. O programa usa alocação dinâmica de memória e também um ponteiro para funções (isso não era necessário, mas eu quis enfeitar um pouco :D ). Bom, é isso, espero que ajude a alguém.
/*******************************************************************
* Metodo de power para calcular o autovalor *
* dominante (em modulo) e seu autovetor associado, *
* de uma matriz de numeros reais *
* ---------------------------------------------------------------- *
*Autor: David Oliveira Lorente *
* ---------------------------------------------------------------- *
* Exemplo: *
* Dimensao da matriz: 3 *
* Numero de iteracoes: 3 *
* *
* Matriz de entrada *
* 2.000000 1.000000 1.000000 *
* 1.000000 2.000000 1.000000 *
* 1.000000 1.000000 2.000000 *
* *
* n lambda(n) X(n)' *
* -------------------------------------------------------- *
* 1 2.000000 [ 0.750000 0.250000 1.000000 ]' *
* 2 3.000000 [ 0.916667 0.750000 1.000000 ]' *
* 3 3.666667 [ 0.977273 0.931818 1.000000 ]' *
* *
*******************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define MAX(a,b) c = (absval(a) >= absval(b)) ? a : b // usado no calculo da norma infinita.
FILE *fp; // arquivo texto com o autovetor e seu autovalor associado
double *cria_vetor(int tam) { /* rotina para alocar vetores dinamicamente */
double *vetor;
vetor = (double *) calloc(tam, sizeof(double));
if (!vetor) {
printf("Falta memoria para alocar o vetor de ponteiros");
exit(1);
}
return vetor;
}
double absval(double val) // valor absoluto com precisao dupla
{
if (val >= 0) return val;
else return -val;
}
void dados(int dim, int *N, double *TOL, double **A, double *x) { /* recebe os dados da
matriz de entrada */
for (int i = 0; i < dim; i++)
for (int j = 0; j < dim; j++)
A[i][j] = 0.0;
/* entrada da matriz */
for (int i = 0; i < dim; i++) {
printf("\n Linha #%d: \n", i+1);
for (int j = 0; j < dim; j++) {
printf("\n Coluna #%d: ", j+1);
scanf("%lf", &A[i][j]);
}
}
printf("\n Entre com o vetor X inicial:"); /* vetor inicial X(0) */
for(int i = 0; i < dim; i++) {
printf("\n x#%d: ", i+1);
scanf("%lf", &x[i]);
}
printf("\n Entre com a Tolerancia: ");
scanf("%lf", TOL);
printf("\n Entre com o numero maximo de iteracoes: ");
scanf("%d", N);
system("clear");
fprintf(fp, "Matriz de entrada\n");
for(int i = 0; i < dim; i++) {
for(int j = 0; j < dim; j++)
fprintf(fp, "%lf ", A[i][j]);
fprintf(fp, "\n");
}
fprintf(fp, "\n");
} // fim dados
double norma_inf(double *x, int dim) {
int i;
double c; // norma infinita do vetor
i = 0;
c = x[0];
for(i = 1; i < dim; i++)
c = MAX(c, x[i]);
if(c == 0) {
printf("\n A matriz \"A\" possui um autovalor 0, selecione um novo vetor \"x\" e reinicie!");
fprintf(fp,"\nA matriz \"A\" possui um autovalor 0, selecione um novo vetor \"x\" e reinicie!");
exit(1);
}
return c;
} // fim norma_inf
void exibe(double *x, double lambda, int dim, int k) { // exibe os dados computados
int i;
if(k == 0) {
printf("n\t lambda(n)\t\t\t X(n)' \n");
printf("-----------------------------------------------------------------\n");
fprintf(fp, "n\t lambda(n)\t\t\t X(n)' \n");
fprintf(fp, "-----------------------------------------------------------------\n");
}
printf("%d\t ", k + 1);
fprintf(fp, "%d\t ", k + 1);
printf("%lf\t [ ", lambda);
fprintf(fp, "%lf\t [ ", lambda);
for(i = 0; i < dim; i++) {
printf("%lf ", x[i]);
fprintf(fp, "%lf ", x[i]);
}
printf("]'\n");
fprintf(fp, "]'\n");
} // fim exibe
void power(int dim, int N, double TOL, double **A, double *x) { // calcula o autovalor e o autovetor
double *y, lambda, c1, *aux, erro;
int i, j, k, FLAG;
// alocacao dinamica de memoria
y = cria_vetor(dim);
aux = cria_vetor(dim);
i = 0;
j = 0;
k = 0;
lambda = 0;
FLAG = 0;
c1 = norma_inf(x, dim);
for(i = 0; i < dim; i++)
x[i] = x[i]/c1;
while((k < N)&&(FLAG == 0)){
for(i = 0; i < dim; i++) {
y[i] = 0;
for(j = 0; j < dim; j++)
y[i] += A[i][j]*x[j];
}
c1 = norma_inf(y, dim);
for(int l = 0; l< dim; l++)
aux[l] = x[l] - y[l]/c1;
erro = norma_inf(aux, dim);
for(i = 0; i < dim; i++)
x[i] = y[i]/c1;
FLAG = 0;
if(fabs(erro) < TOL) FLAG = 1;
lambda = c1;
exibe(x, lambda, dim, k);
k++;
}
free(y);
} // fim power
int main() {
double TOL;
double **A, *x;
int dim, N;
fp = fopen("dados.txt","w+");
system("clear");
printf(" ----------------------------------------------\n");
printf(" Calcula o autovalor dominante de uma matriz \n");
printf(" quadrada e o seu autovetor associado pelo \n");
printf(" metodo da potencia. \n");
printf(" ----------------------------------------------\n");
printf("\n Dimensao da matriz ? "); scanf("%d", &dim);
// alocacao dinamica de memoria
A = (double **) calloc(dim, sizeof(double)); // matriz de entrada
for (int i = 0; i < dim; i++) A[i] = (double *) calloc(dim, sizeof(double));
x = cria_vetor(dim); // vetor inicial
dados(dim, &N, &TOL, A, x);
power(dim, N, TOL, A, x);
free(A);
free(x);
fclose(fp);
//system(".\\dados.txt");
getchar();
return 0;
}
// fim power.cpp
Divisores de um inteiro positivo em C++
Agenda eletronica com banco de dados em arquivo texto
Organizar variáveis em ordem crescente
LazyDocker – Interface de Usuário em Tempo Real para o Docker
Instalando COSMIC no Linux Mint
Turbinando o Linux Mint: o poder das Nemo Actions
Inteligência Artificial no desenvolvimento de software: quando começar a usar?
[Resolvido] Algo deu errado ao abrir seu perfil
Usando o VNSTAT para medir o seu consumo de internet
Habilitando clipboard manager no ambiente COSMIC
Quais licenças open source têm valor jurídico? (7)
Não estou conseguindo fazer funcionar meu Postfix na versão 2.4 no Deb... (1)









