Introducción
El problema del par de puntos más cercanos consiste en dados
Por ejemplo, dados los siguientes puntos, qué par es más cercano?
La respuesta correcta es
Lo cierto es que sí. Existe un algoritmo que usa la técnica divide y vencerás, dividiendo el problema por la mitad recursivamente y que lo acaba resolviendo en un total de
Podemos mejorarlo todavía más? Lo cierto es que sí, pero hasta cierto punto. Existe una cota inferior de
Entonces, hasta aquí esta entrada de blog? Pues lo cierto es que esta cota es para algoritmos deterministas, por lo que no podremos tener un algoritmo que siempre sea más rápido y funcione, pero nada nos impide tener un algoritmo con una cierta probabilidad de fallo, o una cierta (pero arbitariamente pequeña) probabilidad de acabar siendo tan lento como
Un algoritmo aleatorio
-
En primer lugar, tomaremos
pares de puntos al azar (todas las elecciones independientemente y uniformemente). Calcularemos las distancias de esos pares y nos quedaremos con la mínima, que la llamaremos . -
Ahora dividiremos el plano en bloques de tamaño
, y agruparemos todos los puntos en sus respectivos bloques (usando, por eficiencia, tablas hash). -
Calculamos distancias solo entre pares en un mismo bloque o en bloques adyacentes y cogemos la mínima de todas estas y de
. -
Fin del algoritmo.
Implementación
Enlace a la implementación en C++.
Análisis
Según esta entrada en Wikipedia, el tiempo esperado de este algoritmo será
La respuesta siempre será correcta
En el algoritmo habíamos encontrado un par de puntos con distancia
El tiempo depende en ensencia del tamaño de los bloques individualmente
Como hay
Bloques grandes
Supongamos que hemos ejecutado la fase aleatoria y hemos calculado una cierta
Para cualquier
Digamos que incialmente en el algoritmo fijamos una constante
: Se elige un punto del bloque grande : Se elige un par del bloque grande : Se elige algun par del bloque grande en las rondas : No se elige un par del bloque grande (opuesto a ) : No se elige ningun par del bloque grande en las rondas (opuesto a )
Vemos que cuando
Tiempo prácticamente lineal
Para cualquier
Un refinamiento probabilístico de la cota
Si en el desarrollo anterior (donde los bloques grandes) tomamos
Esto nos dice que, en general, podemos coger una
Como con probabilidad
Es el tiempo esperado de este algoritmo lineal?
Viendo que es prácticamente lineal y que podemos hacer arbitrariamente alta la probabilidad de que sea verdaderamente lineal, no puede ser que estas dos cosas impliquen que el tiempo esperado es lineal?
Lo cierto es que según Wikipedia está demostrado que es lineal, pero no he encontrado esa demostración. Como veremos a continuación, que en este caso sea lineal no implica que estas dos propiedades que hemos visto previamente sean suficientes para decir esto.
Las observaciones previas no son suficientes para decir que la esperanza (en el sentido preciso de esperanza matemática) sea lineal. Hablando sobre esto con Felix Moreno, se le ocurrió un ejemplo de algoritmo que cumple lo mismo que el nuesto, pero la esperanza no es lineal:
Imaginemos un algoritmo que tiene un tiempo de ejecución:
Entonces,
Este algoritmo sería
Un algoritmo más sencillo de analizar
Veremos ahora un algoritmo no tan sencillo y que en la práctica es menos eficiente, pero que nos permite un análisis más sencillo. [Kleinberg, Tardos. Algorithm Design, 12.7]
- Permutamos los puntos aleatoriamente.
- Definimos
- Particionamos el plano en cuadrados de lado
. - Para
- Encontramos el cuadrado que corresponde a
- Miramos los 25 cuadrados cercanos al cuadrado de
los que están entre posiciones alrededor como máximo (sin almacenar puntos inicialmente en los cuadrados). - Si hay algun
almacenado en esos cuadrados tal que entonces:- Redefinimos
- Recalculamos la partición del plano con la nueva
- Almacenamos los puntos
en los cuadrados que les corresponden.
- Redefinimos
- En caso contrario:
- Almacenamos
en el cuadrado que le corresponde.
- Almacenamos
- Encontramos el cuadrado que corresponde a
Análisis
Aunque inicialmente parece que este segundo algoritmo debería ser muy lento porque podría estar recalculando los cuadrados con puntos constantemente, vamos a ver que la probabilidad de que eso pase decrece lo suficientemente rápido para que el tiempo esperado sea lineal.
Llamemos
Pero resulta que
Por lo que el tiempo esperado es
Conclusión
Tenemos un algoritmo que es esencialmente lineal, mientras que los métodos deterministas tenían una cota inferior de
Luego hemos visto un algoritmo que aunque parecería más lento (y en la práctica lo es, aunque no asintóticamente), resulta que simplifica mucho su análisis, por lo que a veces podemos encontrar cierta distancia entre la teoría y la implementación.
Por último que, en ocasiones, probar cosas aleatoriamente puede darnos una ventaja imposible de conseguir con métodos deterministas.