En álgebra lineal numérica , el algoritmo de matriz tridiagonal , también conocido como algoritmo de Thomas (llamado así en honor a Llewellyn Thomas ), es una forma simplificada de eliminación gaussiana que se puede utilizar para resolver sistemas de ecuaciones tridiagonales . Un sistema tridiagonal para n incógnitas se puede escribir como
dóndey.
Para tales sistemas, la solución se puede obtener enoperaciones en lugar derequerido por eliminación gaussiana . Un primer barrido elimina ely luego una sustitución hacia atrás (abreviada) produce la solución. Ejemplos de tales matrices surgen comúnmente de la discretización de la ecuación de Poisson 1D y la interpolación de splines cúbicos naturales .
El algoritmo de Thomas no es estable en general, pero sí lo es en varios casos especiales, como cuando la matriz es diagonalmente dominante (ya sea por filas o columnas) o simétrica definida positiva ; [ 1 ] [ 2 ] para una caracterización más precisa de la estabilidad del algoritmo de Thomas, véase el Teorema de Higham 9.12. [ 3 ] Si se requiere estabilidad en el caso general, se recomienda en su lugar la eliminación gaussiana con pivoteo parcial (GEPP). [ 2 ]
Método
El barrido hacia adelante consiste en el cálculo de nuevos coeficientes de la siguiente manera, denotando los nuevos coeficientes con primas:
y
La solución se obtiene entonces mediante sustitución hacia atrás:
El método anterior no modifica los vectores de coeficientes originales, pero también debe llevar un registro de los nuevos coeficientes. Si los vectores de coeficientes pueden modificarse, entonces un algoritmo con menos gestión de datos es:
Parahacer
seguido de la sustitución hacia atrás
La implementación como una función C , que utiliza espacio temporal para evitar modificar sus entradas para ac, permitiendo que se reutilicen:
void thomas ( const int X , double x [ restrict X ], const double a [ restrict X ], const double b [ restrict X ], const double c [ restrict X ], double scratch [ restrict X ]) { /* resuelve Ax = d, donde A es una matriz tridiagonal que consta de vectores a, b, c X = número de ecuaciones x[] = inicialmente contiene la entrada, d, y devuelve x. indexado desde [0, ..., X - 1] a[] = subdiagonal, indexado desde [1, ..., X - 1] b[] = diagonal principal, indexado desde [0, ..., X - 1] c[] = superdiagonal, indexado desde [0, ..., X - 2] scratch[] = espacio de trabajo de longitud X, proporcionado por quien llama, que permite que a, b, c sean const no realizado en este ejemplo: eliminación manual costosa de subexpresiones comunes */ scratch [ 0 ] = c [ 0 ] / b [ 0 ]; x [ 0 ] = x [ 0 ] / b [ 0 ];/* bucle desde 1 hasta X - 1 inclusive */ for ( int ix = 1 ; ix < X ; ix ++ ) { if ( ix < X -1 ){ scratch [ ix ] = c [ ix ] / ( b [ ix ] - a [ ix ] * scratch [ ix - 1 ]); } x [ ix ] = ( x [ ix ] - a [ ix ] * x [ ix - 1 ]) / ( b [ ix ] - a [ ix ] * scratch [ ix - 1 ]); }/* bucle desde X - 2 hasta 0 inclusive */ for ( int ix = X - 2 ; ix >= 0 ; ix -- ) x [ ix ] -= scratch [ ix ] * x [ ix + 1 ]; }Derivación
La derivación del algoritmo de matriz tridiagonal es un caso especial de eliminación gaussiana .
Supongamos que las incógnitas sony que las ecuaciones a resolver son:
Considere modificar el segundo () ecuación con la primera ecuación como sigue:
lo que daría como resultado:
Tenga en cuenta queSe ha eliminado de la segunda ecuación. Utilizando una táctica similar con la segunda ecuación modificada en la tercera ecuación se obtiene:
Esta vezfue eliminado. Si este procedimiento se repite hasta quefila; la (modificada)La ecuación involucrará solo una incógnita,. Esto se puede resolver y luego utilizar para resolver elecuación, y así sucesivamente hasta que se resuelvan todas las incógnitas.
Evidentemente, los coeficientes de las ecuaciones modificadas se vuelven cada vez más complicados si se expresan explícitamente. Al examinar el procedimiento, los coeficientes modificados (indicados con tildes) pueden definirse recursivamente:
Para acelerar aún más el proceso de solución,Se puede dividir (si no hay riesgo de división por cero ), los nuevos coeficientes modificados, cada uno denotado con una prima, serán:
Esto da como resultado el siguiente sistema con las mismas incógnitas y coeficientes definidos en términos de los originales anteriores:
La última ecuación contiene una sola incógnita. Resolverla reduce la penúltima ecuación a una sola incógnita, de modo que esta sustitución hacia atrás puede utilizarse para hallar todas las incógnitas:
- ;\ i=n-1,n-2,\ldots ,1.}
Variantes
En algunas situaciones, particularmente aquellas que involucran condiciones de contorno periódicas , puede ser necesario resolver una forma ligeramente perturbada del sistema tridiagonal:
En este caso, podemos utilizar la fórmula de Sherman-Morrison para evitar las operaciones adicionales de eliminación gaussiana y seguir empleando el algoritmo de Thomas. El método requiere resolver una versión no cíclica modificada del sistema tanto para la entrada como para un vector correctivo disperso, y luego combinar las soluciones. Esto se puede realizar de manera eficiente si ambas soluciones se calculan simultáneamente, ya que la parte directa del algoritmo de matriz tridiagonal pura se puede compartir.
Si lo indicamos por:
Entonces, el sistema a resolver es:
En este caso los coeficientesyson, en general hablando, distintos de cero, por lo que su presencia no permite aplicar directamente el algoritmo de Thomas. Por lo tanto, podemos considerarycomo sigue: Dóndees un parámetro a elegir. La matriz A se puede reconstruir como. La solución se obtiene entonces de la siguiente manera: [ 4 ] primero resolvemos dos sistemas de ecuaciones tridiagonales aplicando el algoritmo de Thomas:
Luego reconstruimos la solución x utilizando la fórmula de Shermann-Morrison :
La implementación como una función C , que utiliza espacio temporal para evitar modificar sus entradas para ac, permitiendo que se reutilicen:
void cyclic_thomas ( const int X , double x [ restrict X ], const double a [ restrict X ], const double b [ restrict X ], const double c [ restrict X ], double cmod [ restrict X ], double u [ restrict X ]) {/* resuelve Ax = v, donde A es una matriz tridiagonal cíclica que consta de los vectores a, b, c. X = número de ecuaciones x[] = inicialmente contiene la entrada v y devuelve x. Indexado desde [0, ..., X - 1] a[] = subdiagonal, indexada regularmente desde [1, ..., X - 1], a[0] es la esquina inferior izquierda b[] = diagonal principal, indexada desde [0, ..., X - 1] c[] = superdiagonal, indexada regularmente desde [0, ..., X - 2], c[X - 1] es la esquina superior derecha cmod[], u[] = vectores de prueba, cada uno de longitud X *//* esquinas inferior izquierda y superior derecha del sistema tridiagonal cíclico respectivamente */const double alpha = a [ 0 ];const double beta = c [ X - 1 ];/* arbitrario, pero elegido de tal manera que se evite la división por cero */const double gamma = - b [ 0 ];cmod [ 0 ] = c [ 0 ] / ( b [ 0 ] - gamma );u [ 0 ] = gamma / ( b [ 0 ] - gamma );x [ 0 ] /= ( b [ 0 ] - gamma );/* bucle desde 1 hasta X - 2 inclusive */para ( int ix = 1 ; ix + 1 < X ; ix ++ ) {const double m = 1.0 / ( b [ ix ] - a [ ix ] * cmod [ ix - 1 ]);cmod [ ix ] = c [ ix ] * m ;u [ ix ] = ( 0.0f - a [ ix ] * u [ ix - 1 ]) * m ;x [ ix ] = ( x [ ix ] - a [ ix ] * x [ ix - 1 ]) * m ;}/* maneja X - 1 */const double m = 1.0 / ( b [ X - 1 ] - alpha * beta / gamma - a [ X - 1 ] * cmod [ X - 2 ]);u [ X - 1 ] = ( alfa - a [ X - 1 ] * u [ X - 2 ]) * m ;x [ X - 1 ] = ( x [ X - 1 ] - a [ X - 1 ] * x [ X - 2 ]) * m ;/* bucle desde X - 2 hasta 0 inclusive */para ( int ix = X - 2 ; ix >= 0 ; ix -- ) {u [ ix ] -= cmod [ ix ] * u [ ix + 1 ];x [ ix ] -= cmod [ ix ] * x [ ix + 1 ];}const double fact = ( x [ 0 ] + x [ X - 1 ] * alpha / gamma ) / ( 1.0 + u [ 0 ] + u [ X - 1 ] * alpha / gamma );/* bucle desde 0 hasta X - 1 inclusive */para ( int ix = 0 ; ix < X ; ix ++ )x [ ix ] -= hecho * u [ ix ];}También existe otra forma de resolver la forma ligeramente perturbada del sistema tridiagonal considerado anteriormente. [ 5 ] Consideremos dos sistemas lineales auxiliares de dimensión:
Para mayor comodidad, definimos adicionalmenteyAhora podemos encontrar las soluciones.yAplicando el algoritmo de Thomas al sistema tridiagonal auxiliar de dos vías.
La soluciónentonces se puede representar de la forma:
En efecto, multiplicando cada ecuación del segundo sistema auxiliar por, sumando con la ecuación correspondiente del primer sistema auxiliar y utilizando la representación, inmediatamente vemos que las ecuaciones númeroSe satisfacen las ecuaciones 2 a n del sistema original; solo queda satisfacer la ecuación número1. Para ello, considere la fórmula parayy sustituiryen la primera ecuación del sistema original. Esto produce una ecuación escalar para:
Por lo tanto, encontramos:
La implementación como una función C , que utiliza espacio temporal para evitar modificar sus entradas para ac, permitiendo que se reutilicen:
void cyclic_thomas ( const int X , double x [ restrict X ], const double a [ restrict X ], const double b [ restrict X ], const double c [ restrict X ], double cmod [ restrict X ], double v [ restrict X ]) {/* Primero, resuelve un sistema de longitud X - 1 para dos segundos miembros, ignorando ix == 0 */cmod [ 1 ] = c [ 1 ] / b [ 1 ];v [ 1 ] = - a [ 1 ] / b [ 1 ];x [ 1 ] = x [ 1 ] / b [ 1 ];/* bucle desde 2 hasta X - 1 inclusive */para ( int ix = 2 ; ix < X - 1 ; ix ++ ) {const double m = 1.0 / ( b [ ix ] - a [ ix ] * cmod [ ix - 1 ]);cmod [ ix ] = c [ ix ] * m ;v [ ix ] = ( 0.0f - a [ ix ] * v [ ix - 1 ]) * m ;x [ ix ] = ( x [ ix ] - a [ ix ] * x [ ix - 1 ]) * m ;}/* maneja X - 1 */const double m = 1.0 / ( b [ X - 1 ] - a [ X - 1 ] * cmod [ X - 2 ]);cmod [ X - 1 ] = c [ X - 1 ] * m ;v [ X - 1 ] = ( - c [ 0 ] - a [ X - 1 ] * v [ X - 2 ]) * m ;x [ X - 1 ] = ( x [ X - 1 ] - a [ X - 1 ] * x [ X - 2 ]) * m ;/* bucle desde X - 2 hasta 1 inclusive */para ( int ix = X - 2 ; ix >= 1 ; ix -- ) {v [ ix ] -= cmod [ ix ] * v [ ix + 1 ];x [ ix ] -= cmod [ ix ] * x [ ix + 1 ];}x [ 0 ] = ( x [ 0 ] - a [ 0 ] * x [ X - 1 ] - c [ 0 ] * x [ 1 ]) / ( b [ 0 ] + a [ 0 ] * v [ X - 1 ] + c [ 0 ] * v [ 1 ]);/* bucle desde 1 hasta X - 1 inclusive */para ( int ix = 1 ; ix < X ; ix ++ )x [ ix ] += x [ 0 ] * v [ ix ];}En ambos casos, los sistemas auxiliares que se deben resolver son genuinamente tridiagonales, por lo que la complejidad computacional general de resolver el sistemapermanece lineal con respecto a la dimensión del sistema n , es deciroperaciones aritméticas.
En otras situaciones, el sistema de ecuaciones puede ser tridiagonal por bloques (véase matriz por bloques ), con submatrices más pequeñas dispuestas como elementos individuales en el sistema matricial anterior (por ejemplo, el problema de Poisson 2D ). Se han desarrollado formas simplificadas de eliminación gaussiana para estas situaciones. [ 6 ]
El libro de texto Matemáticas Numéricas de Alfio Quarteroni , Sacco y Saleri, incluye una versión modificada del algoritmo que evita algunas de las divisiones (utilizando multiplicaciones en su lugar), lo cual resulta beneficioso en algunas arquitecturas informáticas.
Se han publicado solucionadores tridiagonales paralelos para muchas arquitecturas vectoriales y paralelas, incluidas las GPU [ 7 ] [ 8 ].
Para un tratamiento extenso de solucionadores tridiagonales paralelos y tridiagonales por bloques, consulte [ 9 ].
Referencias
- ↑ Pradip Niyogi (2006). Introducción a la dinámica de fluidos computacional . Pearson Education India. pág. 76. ISBN 978-81-7758-764-7.
- 1 2 Biswa Nath Datta (2010). Álgebra lineal numérica y aplicaciones, segunda edición . SIAM. pág. 162. ISBN 978-0-89871-765-5.
- ↑ Nicholas J. Higham (2002). Precisión y estabilidad de los algoritmos numéricos: Segunda edición . SIAM. pág. 175. ISBN 978-0-89871-802-7.
- ↑ Batista, Milan; Ibrahim Karawia, Abdel Rahman A. (2009). "El uso de la fórmula de Sherman-Morrison-Woodbury para resolver sistemas de ecuaciones lineales tridiagonales y pentadiagonales cíclicos por bloques" . Matemáticas Aplicadas y Computación . 210 (2): 558– 563. doi : 10.1016/j.amc.2009.01.003 . ISSN 0096-3003 .
- ↑ Ryaben'kii, Victor S.; Tsynkov, Semyon V. (2 de noviembre de 2006), "Introducción" , A Theoretical Introduction to Numerical Analysis , Chapman and Hall/CRC, pp. 1–19 , doi : 10.1201/9781420011166-1 , ISBN 978-0-429-14339-7, consultado el 25 de mayo de 2022
- ↑ Quarteroni, Alfio ; Sacco, Ricardo; Saleri, Fausto (2007). "Sección 3.8". Matemáticas Numéricas . Springer, Nueva York. ISBN 978-3-540-34658-6.
- ↑ Chang, L.-W.; Hwu, W.-M. (2014). "Una guía para implementar solucionadores tridiagonales en GPU". En V. Kidratenko (ed.). Computación numérica con GPU . Springer. ISBN 978-3-319-06548-9.
{{cite conference}}: CS1 maint: varios nombres: lista de autores ( enlace ) - ^ Venetis, es decir; Kouris, A.; Sobczyk, A.; Gallopoulos, E.; Sameh, A. (2015). "Un solucionador tridiagonal directo basado en rotaciones de Givens para arquitecturas de GPU". Computación Paralela . 49 : 101– 116. doi : 10.1016/j.parco.2015.03.008 .
- ↑ Gallopoulos, E.; Philippe, B.; Sameh, AH (2016). «Capítulo 5». Paralelismo en cálculos matriciales . Springer. ISBN 978-94-017-7188-7.
- Conte, SD; de Boor, C. (1972). Análisis numérico elemental . McGraw-Hill, Nueva York. ISBN 0070124469.
- Este artículo incorpora texto del artículo Tridiagonal_matrix_algorithm_-_TDMA_(Thomas_algorithm) en CFD-Wiki , que está bajo la licencia GFDL .
- Press, WH; Teukolsky, SA; Vetterling, WT; Flannery, BP (2007). «Sección 2.4» . Numerical Recipes: The Art of Scientific Computing (3.ª ed.). Nueva York: Cambridge University Press. ISBN 978-0-521-88068-8.
- Álgebra lineal numérica