En análisis numérico , el método de Romberg [1] se utiliza para estimar la integral definida aplicando la extrapolación de Richardson [2] repetidamente sobre la regla del trapecio o la regla del rectángulo (regla del punto medio). Las estimaciones generan una matriz triangular . El método de Romberg es una fórmula de Newton-Cotes : evalúa el integrando en puntos equidistantes. El integrando debe tener derivadas continuas, aunque se pueden obtener resultados bastante buenos si sólo existen unas pocas derivadas. Si es posible evaluar el integrando en puntos espaciados desigualmente, entonces otros métodos, como la cuadratura gaussiana y la cuadratura de Clenshaw-Curtis, son generalmente más precisos.
El método lleva el nombre de Werner Romberg , quien lo publicó en 1955.
Usando , el método se puede definir inductivamente por dónde y . En notación O grande , el error para R ( n , m ) es: [3]
La extrapolación cero, R ( n , 0) , es equivalente a la regla trapezoidal con 2 n + 1 puntos; la primera extrapolación, R ( n , 1) , es equivalente a la regla de Simpson con 2 n + 1 puntos. La segunda extrapolación, R ( n , 2) , equivale a la regla de Boole con 2 n + 1 puntos. Las extrapolaciones adicionales difieren de las fórmulas de Newton-Cotes. En particular, nuevas extrapolaciones de Romberg amplían la regla de Boole de manera muy leve, modificando los pesos en proporciones similares a las de la regla de Boole. Por el contrario, otros métodos de Newton-Cotes producen ponderaciones cada vez más diferentes, lo que eventualmente conduce a ponderaciones positivas y negativas grandes. Esto es indicativo de cómo los métodos de Newton-Cotes con polinomios de interpolación de gran grado no logran converger para muchas integrales, mientras que la integración de Romberg es más estable.
Al etiquetar nuestras aproximaciones como en lugar de , podemos realizar la extrapolación de Richardson con la fórmula de error definida a continuación: Una vez que hayamos obtenido nuestras aproximaciones , podemos etiquetarlas como .
Cuando las evaluaciones de funciones son costosas, puede ser preferible reemplazar la interpolación polinómica de Richardson con la interpolación racional propuesta por Bulirsch y Stoer (1967).
Para estimar el área bajo una curva, se aplica la regla del trapezoide primero a una pieza, luego a dos, luego a cuatro, y así sucesivamente.
Una vez obtenidas las estimaciones de la regla del trapezoide, se aplica la extrapolación de Richardson .
Como ejemplo, la función gaussiana se integra de 0 a 1, es decir, la función de error erf(1) ≈ 0,842700792949715. La matriz triangular se calcula fila por fila y el cálculo finaliza si las dos últimas entradas de la última fila difieren en menos de 10 −8 .
0.771743330,82526296 0,843102830,83836778 0,84273605 0,842711600,84161922 0,84270304 0,84270083 0,842700660,84243051 0,84270093 0,84270079 0,84270079 0,84270079
El resultado en la esquina inferior derecha de la matriz triangular tiene una precisión de los dígitos que se muestran. Es notable que este resultado se derive de las aproximaciones menos precisas obtenidas por la regla del trapecio en la primera columna de la matriz triangular.
A continuación se muestra un ejemplo de una implementación informática del método Romberg (en el lenguaje de programación C ):
#incluir <stdio.h> #incluir <math.h> void print_row ( size_t i , double * R ) { printf ( "R[%2zu] =" , i ); for ( size_t j = 0 ; j <= i ; ++ j ) { printf ( "%f" , R [ j ]); } printf ( " \n " ); } /* ENTRADA: (*f) : puntero a la función a integrar a : límite inferior b : límite superior max_steps: pasos máximos del procedimiento según : precisión deseadaSALIDA: Rp[max_steps-1]: valor aproximado de la integral de la función f para x en [a,b] con precisión 'acc' y pasos 'max_steps'. */ doble romberg ( doble ( * f )( doble ), doble a , doble b , tamaño_t max_steps , doble acc ) { doble R1 [ max_steps ], R2 [ max_steps ]; // buffers dobles * Rp = & R1 [ 0 ], * Rc = & R2 [ 0 ]; // Rp es la fila anterior, Rc es la fila actual double h = b - a ; //tamaño del paso Rp [ 0 ] = ( f ( a ) + f ( b )) * h * 0.5 ; // primer paso trapezoidal print_row ( 0 , Rp ); for ( tamaño_t i = 1 ; i < max_steps ; ++ i ) { h /= 2 .; doble c = 0 ; tamaño_t ep = 1 << ( yo -1 ); //2^(n-1) for ( size_t j = 1 ; j <= ep ; ++ j ) { c += f ( a + ( 2 * j -1 ) * h ); } Rc [ 0 ] = h * c + .5 * Rp [ 0 ]; // R(i,0) for ( size_t j = 1 ; j <= i ; ++ j ) { double n_k = pow ( 4 , j ); Rc [ j ] = ( n_k * Rc [ j -1 ] - Rp [ j -1 ]) / ( n_k -1 ); // calcula R(i,j) } // Imprime la fila i de R, R[i,i] es la mejor estimación hasta el momento print_row ( i , Rc ); if ( i > 1 && fabs ( Rp [ i -1 ] - Rc [ i ]) < acc ) { return Rc [ i ]; } // intercambia Rn y Rc ya que solo necesitamos la última fila double * rt = Rp ; Rp = Rc ; Rc = rt ; } devolver Rp [ max_steps -1 ]; // devolvemos nuestra mejor suposición }
Aquí hay una implementación del método Romberg (en el lenguaje de programación Python ):
def print_row ( i , R ): """Imprime una fila de la tabla Romberg.""" print ( f "R[ { i : 2d } ] = " , end = "" ) para j en el rango ( i + 1 ): imprimir ( f " { R [ j ] : f } " , fin = "" ) imprimir () def romberg ( f , a , b , max_steps , acc ): """ Calcula la integral de una función usando la integración de Romberg. Args: f: La función a integrar. a: Límite inferior de integración. b: Límite superior de integración. max_steps: Número máximo de pasos. acc: Precisión deseada. Devuelve: El valor aproximado de la integral. """ R1 , R2 = [ 0 ] * max_steps , [ 0 ] * max_steps # Búfers para almacenar filas Rp , Rc = R1 , R2 # Punteros a las filas anteriores y actuales h = b - a # Tamaño del paso Rp [ 0 ] = 0,5 * h * ( f ( a ) + f ( b )) # Primer paso trapezoidal imprimir_fila ( 0 , Rp ) para i en el rango ( 1 , max_steps ): h /= 2. c = 0 ep = 1 << ( i - 1 ) # 2^(i-1) para j en el rango ( 1 , ep + 1 ): c + = f ( a + ( 2 * j - 1 ) * h ) Rc [ 0 ] = h * c + 0.5 * Rp [ 0 ] # R(i,0) para j en el rango ( 1 , i + 1 ): n_k = 4 ** j Rc [ j ] = ( n_k * Rc [ j - 1 ] - Rp [ j - 1 ]) / ( n_k - 1 ) # Calcular R( yo,j) # Imprimir la fila i de R, R[i,i] es la mejor estimación hasta el momento print_row ( i , Rc ) si i > 1 y abs ( Rp [ i - 1 ] - Rc [ i ]) < acc : return Rc [ i ] # Intercambiar Rn y Rc para la siguiente iteración Rp , Rc = Rc , Rp return Rp [ max_steps - 1 ] # Devuelve nuestra mejor suposición