Algoritmo de Chan

Una demostración en 2D del algoritmo de Chan. Cabe destacar que el algoritmo divide los puntos de forma arbitraria, no según la coordenada x

En geometría computacional, el algoritmo de Chan, que recibe su nombre de Timothy M. Chan, es un algoritmo sensible a la salida óptimo para calcular la envolvente convexa de un conjunto de puntos, en un espacio bidimensional o tridimensional. El algoritmo requiere un tiempo , donde es el número de vértices de la salida (la envolvente convexa). En el caso plano, el algoritmo combina un algoritmo (el método de Graham, por ejemplo) con la marcha de Jarvis () para obtener un tiempo óptimo. El algoritmo de Chan destaca por ser mucho más sencillo que el Algoritmo de Kirkpatrick-Seidel y por extenderse naturalmente al espacio tridimensional. Este paradigma fue desarrollado independientemente por Frank Nielsen en su tesis doctoral.

Algoritmo

Descripción general

Una sola pasada del algoritmo requiere un parámetro que se encuentra entre 0 y (número de puntos del conjunto ). Idealmente, , pero , el número de vértices en la envolvente convexa de salida, se desconoce al inicio. Se realizan múltiples pasadas con valores crecientes de , que finalizan cuando alcanza un valor determinado. Véase más abajo la elección del parámetro .

El algoritmo comienza dividiendo arbitrariamente el conjunto de puntos en subconjuntos con un máximo de puntos cada uno; nótese que .

Para cada subconjunto , calcula la envolvente convexa, , utilizando un algoritmo (por ejemplo, el método de Graham), donde es el número de puntos en el subconjunto. Dado que hay subconjuntos de puntos cada uno, esta fase requiere un tiempo .

Durante la segunda fase, se ejecuta la marcha de Jarvis, utilizando las (mini) envolventes convexas precalculadas, . En cada paso de este algoritmo de marcha de Jarvis, se tiene un punto en la envolvente convexa (al principio, puede ser el punto en con la coordenada y más baja, que está garantizado que está en la envolvente convexa de ), y se necesita encontrar un punto tal que todos los demás puntos de estén a la derecha de la línea , donde la notación simplemente significa que el siguiente punto, es decir, , se determina como una función de y . Se conoce la envolvente convexa del conjunto , , y contiene como máximo puntos (ordenados en sentido horario o antihorario), lo que permite calcular en tiempo mediante búsqueda binaria. Por lo tanto, el cálculo de para todos los subconjuntos se puede realizar en tiempo . Luego, se puede determinar utilizando la misma técnica que se usa normalmente en la marcha de Jarvis, pero considerando solo los puntos (es decir, los puntos en las mini envolventes convexas) en lugar de todo el conjunto . Para esos puntos, una iteración de la marcha de Jarvis es , lo cual es insignificante comparado con el cálculo para todos los subconjuntos. La marcha de Jarvis finaliza cuando el proceso se ha repetido veces (porque, según su funcionamiento, tras como máximo iteraciones de su bucle más externo, donde es el número de puntos en la envolvente convexa de , se debe haber encontrado dicha envolvente). Por lo tanto, la segunda fase requiere un tiempo de , equivalente a un tiempo de si está cerca de (véase más abajo la descripción de una estrategia para elegir de forma que esto ocurra).

Al ejecutar las dos fases descritas anteriormente, la envolvente convexa de puntos se calcula en tiempo .

Elección del parámetro m

Si se elige un valor arbitrario para , puede ocurrir que . En ese caso, después de pasos en la segunda fase, se interrumpe la marcha de Jarvis, ya que ejecutarla hasta el final llevaría demasiado tiempo.

En ese momento, se habrá consumido un tiempo y la envolvente convexa no se habrá calculado.

La idea es realizar múltiples pasadas del algoritmo con valores crecientes de ; cada pasada finaliza (con éxito o sin éxito) en tiempo . Si aumenta demasiado lentamente entre pasadas, el número de iteraciones puede ser grande. Por otro lado, si aumenta demasiado rápido, el primer para el cual el algoritmo finaliza con éxito puede ser mucho mayor que , y producir una complejidad .

Estrategia de elevación al cuadrado

Una estrategia posible consiste en elevar al cuadrado el valor de en cada iteración, hasta un valor máximo de (que corresponde a una partición en conjuntos unitarios). Partiendo de un valor de 2, en la iteración se elige . En ese caso, se realizan iteraciones, dado que el algoritmo finaliza una vez que se alcanza:

con logaritmo tomado en base , y el tiempo total de ejecución del algoritmo es:

En tres dimensiones

Para generalizar esta construcción al caso tridimensional, se debe utilizar el algoritmo de Preparata y Hong para calcular la envolvente convexa tridimensional en lugar del método de Graham, y una versión tridimensional de la marcha de Jarvis. La complejidad temporal permanece como .

Pseudocódigo

En el siguiente pseudocódigo, el texto entre paréntesis y en cursiva son comentarios. Para comprender completamente el siguiente pseudocódigo, se recomienda que el lector esté familiarizado con los algoritmos del método de Graham y de la marcha de Jarvis para calcular la envolvente convexa, , de un conjunto de puntos .

Entrada: Establecer con puntos.
Salida: Establece con puntos, la envolvente convexa de .
(Seleccionar un punto de que esté garantizado que pertenece a : por ejemplo, el punto con la coordenada y más baja.)
(Esta operación toma tiempo: por ejemplo, se puede simplemente iterar a través de .)
( se utiliza en la marcha de Jarvis de este algoritmo de Chan,
para calcular el segundo punto, , en la envolvente convexa de .)
(Nota: no es un punto de .)
(Para más información, consulte los comentarios junto a la parte correspondiente del algoritmo de Chan.)
(Nota: , el número de puntos en la envolvente convexa final de , es desconocido.
(Estas son las iteraciones necesarias para descubrir el valor de , que es una estimación de .)
( es necesario para que este algoritmo de Chan encuentre la envolvente convexa de .)
(Más específicamente, queremos , para no realizar demasiadas iteraciones innecesarias y para que la complejidad temporal de este algoritmo de Chan sea .)
(Como se explicó anteriormente en este artículo, se utiliza una estrategia en la que se requieren como máximo iteraciones para encontrar .)
(Nota: el final puede no ser igual a , pero nunca es menor que ni mayor que .)
(Sin embargo, este algoritmo de Chan se detiene una vez que se realizan iteraciones del bucle más externo,
es decir, incluso si , no realiza iteraciones del bucle más externo.)
(Para más información, consulte la parte de la marcha de Jarvis de este algoritmo a continuación, donde se devuelve si .)
para hacer
(Establecer el parámetro para la iteración actual. Se utiliza un "esquema de elevación al cuadrado" como se describe anteriormente en este artículo.
Existen otros esquemas: por ejemplo, el "esquema de duplicación", donde , para .
Si se utiliza el "esquema de duplicación", la complejidad temporal resultante de este algoritmo de Chan es .
(Inicializa una lista (o arreglo) vacía para almacenar los puntos de la envolvente convexa de , a medida que se encuentran.)
(Divide arbitrariamente el conjunto de puntos en subconjuntos de aproximadamente elementos cada uno.)
(Calcula la envolvente convexa de todos los subconjuntos de puntos, .)
(Tarda Tiempo .
Si , entonces la complejidad temporal es .'
para hacer
(Calcular la envolvente convexa del subconjunto , , usando el escaneo de Graham, que toma tiempo.'
( es la envolvente convexa del subconjunto de puntos .'
(En este punto, se han calculado las envolventes convexas de los subconjuntos de puntos respectivamente.)
(Ahora, use una versión modificada del algoritmo marcha de Jarvis para calcular la envolvente convexa de .)
(La marcha de Jarvis se ejecuta en tiempo, donde es el número de puntos de entrada y es el número de puntos en la envolvente convexa.)
(Dado que la marcha de Jarvis es un algoritmo sensible a la salida, su tiempo de ejecución depende del tamaño de la envolvente convexa, .)
(En la práctica, esto significa que la marcha de Jarvis realiza iteraciones de su bucle más externo.)
En cada una de las En estas iteraciones, realiza como máximo iteraciones de su bucle más interno.
(Queremos , por lo que no queremos realizar más de iteraciones en el siguiente bucle externo.)
(Si el actual es menor que , es decir, , no se puede encontrar la envolvente convexa de .)
(En esta versión modificada de la marcha de Jarvis, realizamos una operación dentro del bucle más interno que tarda tiempo.
Por lo tanto, la complejidad temporal total de esta versión modificada es
Si , entonces la complejidad temporal es .'
para hacer
(Nota: aquí, ya se conoce un punto en la envolvente convexa de , que es .)
(En este bucle para interno, se calculan posibles puntos siguientes que se encuentran en la envolvente convexa de , .)
(Cada uno de estos posibles puntos siguientes proviene de un diferente):
es decir, es un posible punto siguiente en la envolvente convexa de , que forma parte de la envolvente convexa de .)
(Nota: depende de : es decir, para cada En cada iteración , existen posibles puntos siguientes que pueden estar en la envolvente convexa de .
(Nota: en cada iteración , solo uno de los puntos se añade a la envolvente convexa de ).
para hacer
( encuentra el punto tal que el ángulo se maximiza
donde es el ángulo entre los vectores y . Este ángulo se almacena en .
(Los ángulos no necesitan calcularse directamente: se puede usar una prueba de orientación).
( se puede realizar en tiempo .)
(Nota: en la iteración , y se conoce y es un punto en la envolvente convexa de :
en este caso, es el punto de con la coordenada y más baja.'
(Elegir el punto que maximiza el ángulo para que sea el siguiente punto en la envolvente convexa de ).
(La marcha de Jarvis finaliza cuando el siguiente punto seleccionado en la envolvente convexa, , es el punto inicial, ).
si
(Devuelve la envolvente convexa de , que contiene puntos).
(Nota: por supuesto, no es necesario devolver , que es igual a ).
devuelve
si no
(Si después de iteraciones no se ha encontrado un punto tal que , entonces ).
(Se necesita comenzar de nuevo con un valor mayor para ).

Implementación

El artículo de Chan contiene varias sugerencias que pueden mejorar el rendimiento práctico del algoritmo, por ejemplo:

Extensiones

El artículo de Chan contiene otros problemas cuyos algoritmos conocidos pueden optimizarse para ser sensibles a la salida utilizando su técnica, por ejemplo:

Véase también

Referencias

  1. 1 2 Chan, Timothy M. (1996). «Optimal output-sensitive convex hull algorithms in two and three dimensions». Discrete & Computational Geometry 16 (4): 361-368. doi:10.1007/BF02712873.
  2. ↑ Nielsen, Frank (2000). «Grouping and Querying: A Paradigm to Get Output-Sensitive Algorithms». Discrete and Computational Geometry. Lecture Notes in Computer Science 1763. pp. 250-257. ISBN 978-3-540-67181-7. doi:10.1007/978-3-540-46515-7_21.
  3. ↑ Frank Nielsen. "Adaptive Computational Geometry". Ph.D. thesis, Institut National de Recherche en Informatique et en Automatique, 1996.
  4. ↑ Chazelle, Bernard; Matoušek, Jiří (1995). «Derandomizing an output-sensitive convex hull algorithm in three dimensions». Computational Geometry 5: 27-32. doi:10.1016/0925-7721(94)00018-Q.
  5. ↑ {{cite journal|last1=Hershberger|first1=John|title=Finding the upper envelope of n line segments in O(n log n) time|journal= Information Processing Letters|volume=33|issue=4|pages=169–174|fecha=1989|doi=10.1016/0020-0190(89)90136-1}