Hoy os traigo algo que aunque hace tiempo que se produjo no había aparecido todavía por aquí. Es la respuesta de Rubén, de Automatic Human Behaviour la entrada Sólo con el ordenador no es suficiente que escribí hace un tiempo. He tomado prestado el título original de su post y el texto íntegro del mismo (él me dio permiso vía mail para hacerlo). La url del artículo en su blog es esta.


¿Podemos fiarnos de los textos escritos por matemáticos?

El artículo de hoy pretende ser una respuesta al texto, ¿Podemos fiarnos de los cálculos efectuados con ordenador? escrito por Óscar Ciaurri y Juán Luis Varona y publicado en La Gaceta de la Real Sociedad Matemática Española. Existe una versión en pdf y Diamond, de Gaussianos, publicó una versión resumida en su blog.

Mi hipótesis de partida es que este texto -si bien siempre es útil detectar fallos y errores comunes para que otros no los cometan- esta basado, parcialmente, en falacias con respecto al funcionamiento de los ordenadores y, lo que es peor, de las matemáticas que se emplean dentro de ellos.

Mi objetivo no es rebatir el texto original desde un blog, si no dar al lector las herramientas para comprobar por si mismo algunas de las falacias que he comentado y, de paso, hacer un poco de divulgación científica, que nunca viene mal.

Para empezar, vamos a presentar un modelo teórico que aproxima bastante bien las capacidades y, sobre todo, las limitaciones de cálculo de un ordenador. Es la conocida como, máquina de Turing.
Esta máquina no es mas que un robot que es capaz de procesar una cinta de datos codificados como unos y ceros. En cada instante, el robot puede leer o modificar el dato que tiene en el cabezal. La decisión se basa en un programa que, junto con los datos que lee, van cambiando el estado interno del robot.

De este modelo teórico, vemos dos cosas que se aplican a todos los ordenadores:

1) Los ordenadores solo son capaces de procesar números. Cualquier cosa que queramos que procesen, la tendremos que transformar a 1s y 0s. Un sonido lo tendremos que transformar en una secuencia de números. Una imagen también pasa a ser una secuencia de números. El texto también son números. Un ordenador no sabe leer, solo sabe contar. Todas estas conversiones se basan en convenios que habremos de decidir de antemano.

2) Los ordenadores -al menos los de un solo núcleo- procesan la información de manera secuencial. Esto tiene una implicación muy importante a la hora de determinar la complejidad de un problema. Por ejemplo, si el ordenador tiene que encontrar el camino óptimo entre una serie de rutas, tendrá que recorrerlas todas antes de estar totalmente seguro de que la que decida sera la óptima.

En determinadas situaciones, y partiendo ciertas intuiciones o información previa podemos obtener soluciones más eficientemente. También se puede buscar una solución que no sea la óptima, pero que en la práctica sea lo suficientemente buena. Sin embargo, en un caso general, no se pueden asumir dichas simplificaciones.

En el peor de los casos, podemos encontrarnos con problemas totalmente irresolubles, como el problema de parada, es decir, saber si un programa (con bucles, saltos e interrupciones) se va a parar o por el contrario, quedaría atrapado en un bucle que se ejecuta continuamente (lo que se llama un bucle infinito). La única forma de saberlo, es ejecutando el programa entero, con lo que si el programa tiene un bucle infinito, el programa quedara atrapado y nunca nos dará la solución.

3) También existe limitaciones a nivel práctico. El robot de Turing puede estar trabajando por tiempo indefinido hasta resolver casi cualquier problema (como hemos dicho cualquiera que tenga solución, lo que se llama un problema decible). Sin embargo, en la práctica, existen muchos otros problemas que no se pueden resolver por un ordenador normal, ya que son problemas intratables. La wikipedia pone el ejemplo de los problemas con complejidad exponencial:

Para ver por qué las soluciones de tiempo exponencial no son útiles en la práctica, se puede considerar un problema que requiera 2n operaciones para su resolución (n es el tamaño de la fuente de información). Para una fuente de información relativamente pequeña, n=100, y asumiendo que una computadora puede llevar a cabo 1010 (10 giga) operaciones por segundo, una solución llevaría cerca de 4*1012 años para completarse, mucho más tiempo que la actual edad del universo.

4) Otra limitación técnica viene del hecho de que la memoria (el tamaño de la cinta), no es infinita. De hecho, para almacenar cualquier posible número, necesitaríamos una cadena arbitrariamente larga de 1s y 0s. Eso no solo aumenta el coste de memoria, si no también el coste computacional de procesar un único número. De este modo, se suele limitar el tamaño de los números a 8, 16, 32 o 64 bits. Puede parecer que 64 bits dan mucho juego (son 264 números), y de hecho, lo dan, pero recordemos que los números naturales son infinitos números. Y tan lejos del infinito esta un googol como el 1. Pero es que además, como vimos en otros articulos, los números reales son un infinito de segundo orden, es decir, en el intervalo que hay entre cada uno de los infinitos números enteros, hay infinitos números reales, cada uno con potencialmente infinitos decimales. ¿No parecen demasiados para representarlos con 264 números? Pues se hace, pero con el consiguiente error asociado que hay que tener en cuenta.

En resumen, hay muchos problemas que para nosotros son triviales, pero que para un ordenador como los que utilizamos habitualmente, son imposibles ya que: requieren un tiempo de cálculo enorme, requiere una cantidad de recursos impracticable o simplemente, no existe ninguna forma de que el ordenador obtenga un resultado.

Para terminar con los preliminares, quisiera añadir un pequeño trasfondo de lo que es la Ingeniería de Software.

El software ha de pensarse que es como un producto más. Por ejemplo, podemos compararlo con un coche.

A principios del siglo XX, los vehículos a motor estaban todavía en fase de desarrollo. Los pocos vehículos que circulaban por las carreteras tenían continuos fallos y taras. Era raro poder circular más de 10 kilómetros sin que se gripase el motor, se fundiese alguna lampara o se pinchase una rueda. El mundo tampoco estaba preparado para ellos, y parte de los problemas provenían de carencia de pavimento en las carretas, falta de señalización, etc.

Sin embargo, a pesar de los avances que se han dado a lo largo del siglo XX (de todos es sabido que la industria de la automoción es una de las que más dinero mueve a nivel mundial), solo recientemente se han creado e implantado extensivos controles de calidad y diseños exhaustivos que otorgan una gran calidad al producto final y una garantía de seguridad.

Se tardó un siglo en desarrollar e implantar toda esa tecnología.

Por otro lado, a pesar de los avances que ha sufrido el campo de la automoción, no le pedimos a un coche que vuele, por mucho que lo utilicemos para viajar, y volar sea una forma eficaz de hacerlo. Incluso si alguien utiliza un motor de coche para volar, no es la mejor forma de hacerlo. Es una falacia razonar que si un elemento se utiliza para un fin, ha sido diseñado para ese propósito.

Por ejemplo, por mucho que utilicemos los ordenadores para cálculo simbólico, el modelo de ordenador de von Neumann, que aun hoy utilizamos, se diseñó para calculo numérico. Y punto. Cualquier algoritmo que resuelva problemas s
imbólicos será porque primero los convierte a problemas numéricos.

La Informática como ciencia y como tecnología, es mucho mas joven que la automoción. Sin embargo, ya se están empezando a implantar controles de calidad dignos de las grandes compañías de vehículos. Casi desde el principio de la programación, han existido los betatester (gente que se dedica a probar y sacar los fallos de un programa al final de su desarrollo), se han desarrollado técnicas de métodos formales y análisis de software para reducir al mínimo los errores.

Sin embargo, siempre aparecen errores. Al igual que en los vehículos siguen apareciendo fallos de diseño (como el famoso Mercedes que hace pocos años tuvo que ser retirado del mercado porque en caso de accidente, el motor se incrustaba en el habitáculo de pasajeros). Por desgracia, el software es algo que se maneja jerárquicamente. Aunque no nos demos cuenta, en todo momento estamos ejecutando varias piezas de software (programas de trabajo, sistemas operativos, drivers, controladores…) que a su vez están basados en otras piezas de software (compiladores, interpretes…). Simplemente con que falle solo uno de esos elementos, el sistema falla. Y lo más probable es que, a fecha de hoy, alguna de esas piezas de software estén todavía hechas con métodos antiguos de programación y sin los controles de calidad que hoy se utilizan. ¿Alguien se atrevería a conducir en una autopista donde, al fallar cualquiera de los vehículos que van en ella, automáticamente fallaran todos? ¡Estaríamos arreglando pinchazos cada 100 metros!

Pero en todo este panorama, los programadores tenemos una ventaja que la automoción no tendrá nunca, los demostradores de teoremas. Un demostrador de teoremas es un programa que nos garantiza, matemáticamente, que nuestro trozo de código hace exactamente lo que queremos que haga. Es decir, nos garantiza que matemáticamente es correcto, perfecto. Por desgracia, los demostradores de teoremas todavía se encuentra en fase de investigación y sus capacidades, a día de hoy, son muy limitadas. Realmente, la dificultad de un demostrador de teoremas, deriva de que es un cálculo simbólico, no numérico.

Ahora, vayamos por partes a resolver algunos de los puntos que comentan los autores. Como he dicho antes, no es mi idea rebatir el texto completo, así que me centrare en algunos de los puntos que se resumen en el blog de Gaussianos.

1) Cálculo de limites:

Los autores denuncian que una función cuyo limite en determinado punto varia si el limite se toma «por arriba» o «por abajo» no es resuelto como tal por Mathematica, ya que si le damos a calcular el limite, sin definir por donde se mira, nos devuelve el valor por arriba y no nos avisa de que esta indefinido.

Solo hace falta ir a la documentación de Mathematica y leer:

The value of Sign[x] at x=0 is 0. [..] Its limit, however, is 1. The limit is by default taken from above.

Es decir, Mathematica sí que nos avisa de que va a coger el límite «por arriba». En muchos otros ejemplos del articulo, la crítica es la misma: el programa no nos informa de lo que hace. Eso es totalmente falso, porque como lo hemos visto, si que informa, aunque en la documentación. Lógicamente, un software de esa magnitud no puede estar informando de cada acción que haga. ¿Se imaginan los lectores un navegador de internet que cada vez que pulsara en un link le saliese un mensaje:

«Acaba de pulsar un link. Esto le enviara a otra pagina y dejará atras la página que esta leyendo. ¿Desea continuar?»

Acabaríamos todos de los nervios. Lo primero de todo, antes de usar un software, antes de usar cualquier herramienta, es leerse el manual. Eso lo sabe cualquier técnico y debería saberlo cualquier usuario de software. De hecho, existe un programa que se diseñó para intentar informar al usuario bastante a menudo, a sabiendas de que no se leería la documentación por su cuenta. El programa era el asistente de la ayuda de Microsoft Office, más conocido como Clippo. El odio que suscitó es tal, que existen hasta videojuegos cuyo único objetivo es aniquilar el personaje animado de la forma mas cruel posible.

2) Gráficos ficticios:

Decir que en este caso, gran parte del error que se comete no es de los autores originales, si no del resumen de Gaussianos.

En este caso, los autores protestan porque el programa no representa bien según que gráficas, haciendo clara referencia, aunque no explícita, al teorema de Niquist-Shanon.

Para empezar, decir que un ordenador, jamas podrá dibujar una gráfica continua, ya que por definición, tiene infinitos puntos. Y como hemos visto, para un ordenador, infinito es 264. Un ordenador siempre es discreto. De todos modos, aunque la pudiese representar, nunca la podría sacar por pantalla, ya que siempre tendríamos la limitación de los píxeles, o en último término, del ojo humano.

Pero aun así, en este caso, los autores originales claramente comentan que el software Mathematica puede resolver este problema hasta cierto punto. Por la descripción que hacen de la método que usa Mathematica, se están refiriendo al potente algoritmo de bootstrapping. Este algoritmo, aunque fundamentado en una solida base matemática, se puede explicar de manera bastante sencilla: En caso de que las muestras que estemos tomando no sean suficientemente representativas, podemos usar las que tenemos para obtener información sobre la función y así tomar más muestras en determinadas zonas «de manera inteligente». De este modo se consigue mejorar la calidad del resultado con menos coste añadido.

Por desgracia, el algoritmo de bootstrapping es un algoritmo con coste exponencial. Es decir, cuando aumentamos el número de dimensiones, el coste aumenta enormemente hasta hacerlo intratable, como veíamos antes. Lógicamente, cuando un usuario le da al botón para dibujar una función, no quiere que pasen años o siglos antes de poder verla. Es por ello, que Mathematica ha limitado el uso del bootstrapping a gráficas de una sola dimensión, donde el tiempo de cálculo, entra dentro de lo razonable. Este nimio detalle es contemplado en el articulo original, pero en el resumen de Gaussianos, inexplicablemente, se perdió.

3) Simplificar

Este punto y otros por el estilo donde se habla del cálculo simbólico directamente no tienen sentido. Todos los razonamientos se basan en la premisa de: «Dado que esas operaciones son triviales para cualquiera, también lo deberían ser para la máquina.»

Bien, y yo me pregunto: ¿Por qué? Hemos visto que hay muchos problemas que son triviales para nosotros y no para un ordenador. Otros son triviales para el ordenador y tremendamente complejos para nosotros. Simplemente funcionamos distinto. De hecho, cuando se crearon originalmente, se crearon con la idea de complementarnos, luego se especializaron en lo que se nos da mal a los humanos. Lógico, ¿no creen?

Además,
los autores de Mathematica, dado que el calculo simbólico es muy costoso y ha de probar muchos caminos y opciones, han optado por dar una solución práctica. Han cogido las operaciones más rápidas y que aparecen más frecuentemente a la hora de simplificar y las han incluido en una función. Esta función tiene la ventaja de ser muy rápida, pero no te garantiza un resultado satisfactorio. Luego existe otra función que tiene una biblioteca de operaciones mucho más extensa y por lo tanto da mejores resultados, pero más lento.

Es como cuando nos vamos a comprar un libro, que primero leemos el resumen, y aunque no nos garantiza que el libro sea bueno o malo, si que en algunos casos nos puede servir de ayuda.

Esto no es una solución matemática, ni tiene ninguna base teórica. Simplemente se ha hecho así por comodidad del usuario. Prueba primero la rápida, y si no funciona, siempre podrás probar la lenta, pero si te funciona, eso que te has quitado de encima. Tiene sentido, ¿no?

Pero no sabemos como han escogido los programadores que operaciones poner en la rápida y cuales no. Y no existe ninguna justificación matemática. Hacer suposiciones con la premisa: «esta operación es muy sencilla, debería ser resuelto por la función resumida» simplemente no tiene ni pies ni cabeza.

4) Fallos de código:

Esta parte es la única que no esta basada en falacias. Es normal que haya fallos en un código, al igual que es normal que haya fallos en cualquier producto. No es deseable, pero somos humanos. Me parece una labor encomiable que se busquen esos errores y se hagan públicos a una comunidad que usa ese software masivamente. Incluso la idea de anunciar los fallos de versiones antiguas, ya que mucha gente no actualizara su software a menudo, al ser software de pago.

Desconozco si Mathematica ofrece actualizaciones gratuitas de las correcciones de software, aunque muchos de los programas comerciales sí lo hagan. Normalmente, aunque no nos demos cuenta, cuando se compra un software, muchas veces se compra también el soporte adicional.

Por otro lado, lo que veo un error es escribir el texto a modo de denuncia en vez de simplemente informativo. De hecho, muchos de esos fallos que se comentan se han corregido en las últimas versiones, lo cual es loable y no denunciable. Además en vez de denunciarlo en una revista española que no leerán los programadores, se puede contactar con ellos. Es muy probable que corrijan los fallos en la próxima versión e incluso nos regalen alguna suscripción gratuita por haberlos encontrado.

En este punto, es admirable la labor de las comunidades de software libre, donde puedes informar del error, que normalmente es subsanado a las pocas horas y, al día siguiente, puedes descargarte el nuevo código perfectamente arreglado.

Mi conclusión es que sí podemos fiarnos de los cálculos de un ordenador, pero no podemos fiarnos de los usos y decisiones que tomemos a posteriori.

Nota: Como punto final, me gustaría comentar que no tengo ninguna implicación con Mathematica ni con la compañía que lo ha desarrollado. Simplemente ha sido la herramienta en la que estaba basada el texto original. Personalmente, y dado que mis aplicaciones van más orientadas al cálculo numérico, prefiero Matlab. Como alternativa de software libre y gratuita, existe Octave, que si bien tiene alguna capacidad reducida, es un serio competidor. También existen lenguajes de programación orientados al cálculo científico con excelentes bibliotecas de apoyo, como por ejemplo R (para cálculo estadístico) y Python con SciPy (más general).


Como habéis visto Rubén me dio la réplica con este artículo y, aunque con muchísimo retraso, quería ponerla aquí. Espero vuestros comentarios sobre el asunto, pero, por favor, con la mayor educación posible tanto para hacia Rubén como hacia mí. Aviso ésto porque sé que estos temas a veces se salen de madre y pueden llegar a límites que no estoy dispuesto a aceptar. De todas formas estoy seguro de que todos sabremos mantener la compostura.

Print Friendly, PDF & Email