Implementación de Métodos Numéricos para Autovalores y Sistemas Lineales
Enviado por Chuletator online y clasificado en Informática y Telecomunicaciones
Escrito el en español con un tamaño de 12,5 KB
Algoritmo de Jacobi para Autovalores y Autovectores
Este segmento de código implementa el algoritmo de Jacobi para el cálculo de autovalores y autovectores de una matriz simétrica. El método es iterativo y busca diagonalizar la matriz mediante una serie de rotaciones.
Inicialización de la Matriz de Autovectores
Se inicializa la matriz de autovectores como una matriz identidad, ya que inicialmente representa la base canónica.
Autovectores = 0.;
for(int i = 0; i < dim; i++) Autovectores[i][i] = 1.;
Bucle Principal del Algoritmo de Jacobi
El algoritmo itera hasta que la matriz se considera diagonalizada (elementos fuera de la diagonal menores que una tolerancia) o se alcanza el número máximo de iteraciones.
for (Niter = 0; Niter < NMaxIter; Niter++){
int p, q;
real max = 0;
Cálculo del Elemento Mayor Fuera de la Diagonal
En cada iteración, se busca el elemento con el mayor valor absoluto fuera de la diagonal principal. Este elemento determinará el plano de rotación.
for (int i = 0; i < dim; i++){
for (int j = i + 1; j < dim; j++){
if (fabs(A[i][j]) > max){
max = fabs(A[i][j]);
p = i;
q = j;
}
}
}
Criterio de Convergencia
Si el elemento más grande fuera de la diagonal es menor que una tolerancia predefinida (TOL
), se considera que el algoritmo ha convergido y se devuelven los autovalores (elementos de la diagonal).
if (max < TOL) {
Array1D a(dim);
for(int l = 0; l < dim; l++) a[l] = A[l][l];
return (a);
}
Cálculo del Ángulo de Rotación
Se calcula el ángulo alpha
necesario para la rotación de Jacobi, que anulará el elemento A[p][q]
.
real alpha = 0.5 * atan((2 * A[p][q]) / (A[q][q] - A[p][p]));
Modificación de la Matriz A
Se aplican las rotaciones de Jacobi a la matriz A
para acercarla a su forma diagonal. Esto implica actualizar los elementos de las filas y columnas p
y q
.
for (int k = 0; k < dim; k++){
if(k != p && k != q){
real D = A[p][k];
A[k][p] = cos(alpha) * D - sin(alpha) * A[q][k];
A[p][k] = A[k][p];
A[k][q] = sin(alpha) * D + cos(alpha) * A[q][k];
A[q][k] = A[k][q];
}
}
real app = A[p][p];
A[p][p] = cos(alpha) * (cos(alpha) * A[p][p] - sin(alpha) * A[q][p]) - sin(alpha) * (cos(alpha) * A[p][q] - sin(alpha) * A[q][q]);
A[q][q] = cos(alpha) * (cos(alpha) * A[q][q] + sin(alpha) * A[p][q]) + sin(alpha) * (cos(alpha) * A[q][p] + sin(alpha) * app);
A[p][q] = 0;
A[q][p] = 0;
Modificación de la Matriz de Autovectores
Simultáneamente, se actualiza la matriz de autovectores aplicando las mismas rotaciones para obtener los autovectores correspondientes.
for(int k = 0; k < dim; k++){
real r_kp = Autovectores[k][p];
Autovectores[k][p] = cos(alpha) * Autovectores[k][p] - sin(alpha) * Autovectores[k][q];
Autovectores[k][q] = sin(alpha) * r_kp + cos(alpha) * Autovectores[k][q];
}
}
Manejo de Error por Exceso de Iteraciones
Si el bucle de iteraciones finaliza sin alcanzar la convergencia, se imprime un mensaje de error.
printf ("Error, número de iteraciones excedido\n");
return(Array1D());
Nota: El fragmento de código finaliza con un cierre de llave }
que sugiere el fin de una función.
Método de Relajación (SOR/Gauss-Seidel)
Este fragmento de código implementa un método iterativo de relajación, comúnmente utilizado para resolver sistemas de ecuaciones lineales. La estructura sugiere una implementación del método de Gauss-Seidel con posible sobre-relajación (SOR) si w
es el factor de relajación.
Bucle Principal de Iteraciones
El algoritmo itera hasta un número máximo de iteraciones (nMax
) o hasta que el error entre iteraciones consecutivas caiga por debajo de una tolerancia.
Array1D v(u.dim());
for(int n = 1; n <= nMax; n++){
real error = 0.; // Variable para almacenar el error en la iteración
Recorrido de Incógnitas y Actualización
Se recorren las incógnitas del sistema de forma ascendente, actualizando cada componente del vector solución u
.
for (int i = 0; i < u.dim(); i++){
real temp = b[i]; // Variable para guardar el nuevo valor de u[i]
for(int j = 0; j < i; j++){
temp -= A[i][j] * u[j];
}
for(int j = i + 1; j < u.dim(); j++){
temp -= A[i][j] * u[j];
}
temp = w * temp / A[i][i] + (1 - w) * u[i];
v[i] = u[i];
u[i] = temp;
}
Criterio de Convergencia
Después de cada iteración completa, se calcula el error entre el vector solución actual (u
) y el anterior (v
). Si este error es menor que la tolerancia (TOL
), el algoritmo ha convergido y se devuelve el número de iteraciones.
error = mn_error_vectores(u, v);
if (error < TOL){
return n;
}
}
Manejo de Error por Exceso de Iteraciones
Si el algoritmo no converge dentro del número máximo de iteraciones, se devuelve -1
.
return -1;
Nota: El fragmento de código finaliza con un cierre de llave }
que sugiere el fin de una función.
Método de la Potencia para el Autovalor Dominante
Este código implementa el método de la potencia, un algoritmo iterativo para encontrar el autovalor de mayor magnitud (autovalor dominante) y su autovector asociado de una matriz.
Inicialización del Autovector y Autovalor Máximo
Se inicializa el autovalor máximo con la norma del autovector inicial y se normaliza este último.
l_max = u_max.norma();
u_max = u_max / l_max;
Bucle Principal de Iteraciones
El algoritmo itera hasta un número máximo de iteraciones (Nmax
) o hasta que el autovector converge.
for(int i = 0; i < Nmax; i++){
Generación de un Nuevo Vector
Se crea un nuevo vector multiplicando la matriz A
por el autovector actual (u_max
).
Array1D u_new = A * u_max;
Cálculo del Nuevo Autovalor y Normalización
Se aplica la norma euclídea al nuevo vector para obtener una estimación del autovalor dominante. Se incluye una lógica para manejar el signo del autovalor.
real l_new = u_new.norma();
Array1D temp = u_max * u_new; // Producto cartesiano (¿producto punto?)
for(int k = 0; k < temp.dim(); k++){
if(temp[k] < 0){
l_max = -l_new;
} else {
l_max = l_new;
}
}
u_new = u_new / l_max; // Normalización del nuevo autovector
Criterio de Convergencia
Si la norma de la diferencia entre el autovector actual y el nuevo es menor que una tolerancia (TOL
), se considera que el algoritmo ha finalizado y se devuelve el número de iteraciones.
if((u_max - u_new).norma() < TOL){
u_max = u_new;
return i;
}
u_max = u_new; // Actualización del autovector para la siguiente iteración
}
Manejo de Error por Exceso de Iteraciones
Si el algoritmo no converge dentro del número máximo de iteraciones, se devuelve -1
.
return -1;
Nota: El fragmento de código finaliza con un cierre de llave }
que sugiere el fin de una función.
Método de Eliminación Gaussiana con Pivoteo
Este segmento de código implementa el método de eliminación Gaussiana con pivoteo parcial para resolver sistemas de ecuaciones lineales de la forma Ax = b
. Es una parte fundamental para el método de la potencia inversa.
Inicialización del Vector de Pivoteo
Se inicializa un vector piv
para llevar un registro de los intercambios de filas durante el pivoteo.
for(int k = 0; k < b.dim(); k++) piv[k] = k;
Aplicación del Método de Gauss (Fase de Eliminación)
Se realiza la fase de eliminación hacia adelante, transformando la matriz en una forma triangular superior. Se incluye pivoteo parcial para mejorar la estabilidad numérica.
for(int k = 0; k < b.dim(); k++){
// Detección del máximo en la diagonal hacia abajo (pivoteo)
real max = fabs(A1[piv[k]][k]);
int kmax = k;
for(int m = k + 1; m < b.dim(); m++){
if(fabs(A1[piv[m]][k]) > max){
max = fabs(A1[piv[m]][k]);
kmax = m;
}
}
if(kmax != k){
int paso = piv[kmax];
piv[kmax] = piv[k];
piv[k] = paso;
}
// Conversión a cero de los elementos bajo la diagonal
for(int j = k + 1; j < b.dim(); j++){
real mul = -A1[piv[j]][k] / A1[piv[k]][k];
A1[piv[j]][k] = 0.;
for(int n = k + 1; n < b.dim(); n++) A1[piv[j]][n] += mul * A1[piv[k]][n];
b1[piv[j]] += mul * b1[piv[k]];
}
}
Fase de Remonte (Sustitución Hacia Atrás)
Una vez que la matriz está en forma triangular superior, se resuelve el sistema mediante sustitución hacia atrás.
if(A1[piv[b.dim() - 1]][b.dim() - 1] == 0.) return Array1D(); // Manejo de matriz singular
u[b.dim() - 1] = b1[piv[b.dim() - 1]] / A1[piv[b.dim() - 1]][b.dim() - 1];
for(int k = b.dim() - 2; k >= 0; k--){
real sum = 0;
for(int l = k + 1; l < b.dim(); l++) sum += A1[piv[k]][l] * u[l];
u[k] = (b1[piv[k]] - sum) / A1[piv[k]][k];
}
return(u);
Método de la Potencia Inversa para el Autovalor Mínimo
Este código implementa el método de la potencia inversa, un algoritmo iterativo para encontrar el autovalor de menor magnitud (autovalor mínimo) y su autovector asociado de una matriz. Este método requiere la resolución de un sistema lineal en cada iteración, a menudo utilizando un método como la eliminación Gaussiana.
Inicialización del Autovector y Autovalor Mínimo
Se inicializa el autovalor mínimo con la norma del autovector inicial y se normaliza este último.
l_min = u_min.norma();
u_min = u_min / l_min;
Bucle Principal de Iteraciones
El algoritmo itera hasta un número máximo de iteraciones (Nmax
) o hasta que el autovector converge.
for(int i = 0; i < Nmax; i++){
Generación de un Nuevo Vector mediante Eliminación Gaussiana
Se crea un nuevo vector resolviendo el sistema lineal A * u_new = u_min
, lo que se logra implícitamente a través de la función mn_gauss
.
Array1D u_new = mn_gauss(A, u_min);
Cálculo del Nuevo Autovalor y Normalización
Se aplica la norma euclídea al nuevo vector para obtener una estimación del autovalor mínimo. Se incluye una lógica para manejar el signo del autovalor.
real l_new = u_new.norma();
Array1D temp = u_min * u_new; // Producto cartesiano (¿producto punto?)
for(int k = 0; k < temp.dim(); k++){
if(temp[k] < 0){
l_min = -l_new;
} else {
l_min = l_new;
}
}
u_new = u_new / l_min; // Normalización del nuevo autovector
Criterio de Convergencia
Si la norma de la diferencia entre el autovector actual y el nuevo es menor que una tolerancia (TOL
), se considera que el algoritmo ha finalizado. El autovalor mínimo se calcula como el inverso del valor obtenido, y se devuelve el número de iteraciones.
if((u_min - u_new).norma() < TOL){
l_min = 1. / l_min; // El autovalor es el inverso del obtenido
u_min = u_new;
return i;
}
u_min = u_new; // Actualización del autovector para la siguiente iteración
}
Manejo de Error por Exceso de Iteraciones
Si el algoritmo no converge dentro del número máximo de iteraciones, se devuelve -1
.
return -1;
Nota: El fragmento de código finaliza con un cierre de llave }
que sugiere el fin de una función.