martes, mayo 12, 2009

La repetición que atonta

Permítanme comenzar este texto con un pequeño ejercicio, bajo la promesa de que después se revelará la importancia del mismo. Si el ejercicio los aburre, les invito a saltárselo e ir directo a la carne del final.

El ejercicio consiste en realizar operaciones aritméticas simples. Olvidemos todo lo que sabemos de aritmética por un momento, y comencemos por lo más básico. Primero tenemos que aprender a contar: aprendemos los números naturales 0,1,2,... con su órden específico (que es lo que nos permite contar).
¿Listo? Pefecto, pasemos entonces a algo un poco más interesante y difícil: la suma. Para realizar una suma es suficiente con saber contar. Por ejemplo, si queremos sumar 5+4 lo que tenemos que hacer es empezar en 5 y contar hasta 4 moviéndonos cada vez una posición sobre los números reales.
Pero una vez que sabemos sumar, podemos entonces multiplicar, simplemente contando. Usando de nuevo un ejemplo, si queremos multiplicar 6*3, entonces comenzamos en 0 y contamos hasta 3, haciendo en cada ocasión una suma de 6. Es decir, comenzamos en 0, contamos "1" y sumamos, 0+6=6; contamos "2" y sumamos 6+6=12; contamos "3" y sumamos 12+6=18, y terminamos.
Obviamente, contando podemos también calcular potencias y, tal vez más interesante, hacer restas, divisiones, etc.

La pregunta que surge entonces es, ¿por qué se nos enseña entonces a multiplicar en formas tan complejas, cuando todo lo que necesitamos saber es contar? La respuesta creo que es obvia: aunque el algoritmo aquí descrito es muy sencillo en cuanto a su descripción, en realidad sería muy difícil para nosotros como humanos aplicarlo, simplemente porque muy fácilmente podemos equivocarnos mientras contamos. Si quisieramos hacer 2^10, por ejemplo, tendríamos que repetir 10 veces un producto por 2; cada uno de esos productos significa sumar 2 veces el número hasta entonces calculado y cada una de esas sumas consiste en contar hasta el mismo número. Es decir, tenemos tres contadores anidados, y el proceso nos llevaría desde el número 1 hasta el 1024; un tanto tedioso, ¿no lo creen?

En realidad resulta más sencillo y mucho más eficiente realizar las operaciones como nos enseñan en la escuela. Y es esta razón, la eficiencia, lo que hace que en las computadoras se implementen algoritmos más inteligentes para realizar operaciones aritméticas que el simple uso de contadores. De hecho, las máquinas son muy buenas haciendo repeticiones y los contadores son mucho muy fáciles de implementar, pero los diseñadores de hardware y software dedican mucho tiempo (o tal vez en la actualidad ya no tanto, pero en un principio lo hacían) a implementar las operaciones aritméticas más veloces.

Y ahora viene la pregunta que ronda mi cabeza desde hace unas semanas. Si esto es así, ¿cómo es posible que ahora la gente promueva el uso de algoritmos que únicamente se dedican a repetir métodos más simples, sin pensar en que puede haber métodos más eficientes de hacer lo mismo si nos dedicamos a construir un algoritmo especializado? No hace mucho leí un comentario que decía que no valía la pena dedicar tiempo a desarrollar algoritmos especializados si los métodos repetitivos eran suficientemente rápidos (en ese caso, rápido significaba que acababa en menos de una hora con datos medianamente grandes).

La única posible respuesta a ese comentario que me viene a la mente es: la repetición que nos dan las máquinas, ese poder que nos permite simplemente iterar sin pensar, y hacerlo velozmente y sin aburrirnos nosotros, nos está haciendo no sólo tontos, sino flojos para pensar en un mejor método.

¿Algún comentario?

2 comentarios:

Hek@nibru dijo...

En principio estoy de acuerdo; sin embargo, si el algoritmo especializado no mejora el desempeño significativamente (cada quien define qué significa esto), entonces no creo que valga la pena el esfuerzo. Mejor dedica tu tiempo a resolver otro problema!

Juan dijo...

Agregando un poco más a la discusión. Es cierto que ‘echarle coco’ nos puede llevar casi siempre a encontrar soluciones más eficientes para nuestros problemas. Sin embargo en algunos casos el tiempo que pasamos buscando una ‘solución inteligente’ puede llegar a sobre pasar, y a veces por mucho, al tiempo que nos tomaría el implementar la solución ‘tonta’ y dejar que la computadora haga la repetición aburrida.

Mas aún, incluso cuando sabemos de un algoritmo muy eficiente para resolver cierta tarea, a veces implementar el algoritmo tonto es una mejor opción. Muy en broma, pero también un poco en serio, cuando programaba para los concursos de la ACM hablábamos de la complejidad ‘C’ de un algoritmo, que es el tiempo que nos llevaría el codificarlo. Muchas veces un algoritmo sofisticado tendrá una complejidad ‘C’ mayor que uno más ingenuo.

El problema está, por supuesto, en ser capaz de estimar todos estos diferentes tiempos (de tener la idea, de implementarla, y luego de la máquina en ejecutarla) y tratar de determinar la combinación más adecuada. Problema nada fácil por supuesto, y cuya solución dependerá de lo que se pretenda resolver (y cuantas veces!).