B1. Algoritmos y sus costes. Fórmulas y algoritmos: la diferencia entre expresar algo y calcularlo de modo eficiente. Ejemplos de buenos algoritmos: m.c.d., multiplicación anidada, determinantes con Gauss. Lento pero seguro: el ejemplo del método de bisección para localizar ceros. Referencia: DLCN, Cap. 1.1 El haber estudiado diversos métodos para resolver ecuaciones nos hace juzgar muy distintas estas situaciones, en las que se trata de hallar un número: a) tener una expresión que lo define explı́citamente, de modo que “basta evaluarla”; b) tener una expresión que lo define como el resultado de algún proceso de cálculo; c) tener una ecuación que lo define como “su solución”. La a) parece el objetivo a lograr a partir de la c), el punto en el que “el problema queda resuelto”. Las expresiones que siguen permiten reflexionar sobre eso; cada una de ellas define un número: d = m.c.d.(610, 377) i) ii) p(x) = 3 − 2x − 7x2 + 12x3 + 5x4 iii) d = det(A) , con A = . . . iv) c = 2 sen(c) > 0 , con x = √ 37 (una matriz 4x4 dada) . 1. Qué es hallar el número de i) está claro para todos: escribir su desarrollo decimal. ¿Cómo? La definición implica un método torpı́simo; un poco de reflexión lo mejora, y da este algoritmo2 : ! n := n/p , m := m/p Ir dividiendo n, m por cada primo p que dé cocientes enteros: ; parar d := dp cuando el cuadrado del siguiente primo sea mayor que m < n . Pero recordar: de la igualdad algoritmo de Euclides: mientras sea m > 0 , tomar m.c.d.(n, m) = m.c.d.(m, r) , si n − r = m· entero, " n m # := " m n − qm # resulta el , con q el mayor entero tal que qm ≤ n . ! b1.1 √ 2. Qué bobada ii), saquemos la calculadora . . . pero sólo nos dará una aproximación de 37 . Y ¿cómo busca la calculadora esa aproximación? (ver Tema 1). Una vez hallado x , ¿qué hacer? Lo obvio (¿por qué lo es?) no es muy costoso, pero . . . Algoritmo de multiplicación anidada (Horner): p(x) = ((( 5x + 12)x − 7)x − 2)x + 3 $n k o en general, p(x) = k=0 ak x = (. . . (an x + an−1 )x + . . .)x + a0 ! b1.2 3. En el caso iii), es probable que el público tenga como definición el algoritmo recursivo de desarrollar por una linea, pero también sepa cómo hallarlo usando Gauss; la definición formal de det(A) tiene n! sumandos, cada uno de ellos el producto de n números, luego requiere (n − 1)n! productos. ! b1.3 4. En el caso iv), la calculadora no nos da directamente la respuesta, pero permite usar las ideas del Tema 1: se ve sobre las gráficas que F (x) = x − 2 sen(x) se anula en c ∈(1.5 , 2) , y que será F " (c) ∈(1.5 , 2) , luego un iterador muy simple (para usar con la calculadora) es g(x) = x − F (x)/2 = sen(x) + x/2 . Si tengo una calculadora programable, merece la pena usar Newton: g(x) = x − x − 2 sen(x) 1 − 2 cos(x) pero ojo: si se me ocurre usar x0 = 1 , qué desastre . . . 1 Otra lectura recomendada: Knuth. The Art of Computer Programming, 1. Fundamental Algorithms. Secc.1.1. la notación := para la operación de asignar un nuevo valor a una variable en un algoritmo 2 Usaremos 1 5. El método “lento pero seguro” de bisección para localizar un cero de la función continua f : si f (x0 ) f (x1 ) < 0 , tomar m = (x0 + x1 )/2 , hallar f (m) y conservar el xi que dé f (xi ) f (m) < 0 . Pero tampoco hay que pasarse: Regula Falsi: lo mismo pero tomando m= f (x1 )x0 − f (x0 )x1 f (x1 ) − f (x0 ) 6. Ideas adicionales sobre los algoritmos vistos: • el algoritmo de Euclides también puede usarse – para dos racionales (r, s) , y halla su mı́nimo denominador común; – para (r, 1) con r ∈ IR ; el algoritmo da entonces la fracción continua de r , y termina en un número finito de pasos sii r es racional; ! b1.4 • el de Horner, usado con x = a , da el cociente de p(x) por x − a , además del resto p(a) (y es también llamado regla de Ruffini en ese caso) ; • sobre el de Gauss veremos muchas más ideas en el Tema 2. 2 Ejercicios para el Tema B1. ! b1.1. Usar el método “ingenuo” y el algoritmo de Euclides para calcular d = m.c.d.(610, 377) , y comparar el coste en términos del número de divisiones con resto (para saber si p divide a n, m hay que hacer las divisiones n/p, m/p ). Observar que el algoritmo de Euclides ha dado en este caso todos los cocientes =1, y razonar por qué eso ha hecho la operación lo más larga posible; concretamente, probar que si m < n ≤ 610 , el número de pasos para hallar el m.c.d.(n, m) es como máximo el de este ejemplo. ! b1.2. $ Los dos procedimientos para evaluar el polinomio k ak xk suponen calcular unas “sumas parciales”: ! sk−1 + ak xk , empezando con s0 = a0 es el “ingenuo”, sk = x sk+1 + ak , empezando con sn = an es la multiplicación anidada. Escribir ambos como algoritmos, y comparar los costes: 1) de operaciones; 2) de almacenamiento, si en la primera versión vamos guardando los xk . ! b1.3. Para hallar el det de una A sin entradas =0, el número Pn de productos y cocientes con cada uno de los tres métodos es el que figura en la siguiente tabla: analizar los dos algoritmos para deducir las recurrencias dadas, usar el caso n = 1 para llegar a los n = 4, 6, y tratar de deducir las aproximaciones que se dan. número de productos y cocientes n=4 con la definición formal de det(A) : (n − 1)n! 72 desarrollando por una linea: Pn = n(1 + Pn−1 ) ≈ (e − 1)n! 40 usando Gauss: Pn = n(n − 1) + 1 + Pn−1 ≈ n3 /3 23 n=6 3600 1236 75 ! b1.4. Empezando con un ξ0 > 1 , y mientras no se llegue a un ξk entero, definamos ξk+1 por ξk = mk + 1/ξk+1 , con mk = &ξk ' , la parte entera de ξk , y llamemos qk al racional que da en este proceso los mismos mi hasta llegar a ξk = mk , es decir: q0 = m0 , q1 = m0 + 1/m1 , q2 = m0 + 1/(m1 + 1/m2 ) , . . . Esto se llama el desarrollo de ξ0 en fracción continua, y los qk son sus convergentes. √ Hallarlo para ξ0 = 2 , probar (inducción) que mk = 2, ∀k > 0 , y que los qk son los xk hallados para √ √ aproximar 2 en el ejercicio ! 1.1 . Hacer lo mismo para el número ξ0 = (1 + 5)/2 (la razón áurea). Probar que el proceso termina en un número finito de pasos si y sólo si ξ0 es racional, y que equivale al algoritmo de Euclides aplicado a los r0 = ξ0 , r1 = 1 , r2 = r0 − m0 r1 = 1/ξ1 , r3 = 1/(ξ1 ξ2 ) , . . . 3