Un algoritmo aleatorio es un algoritmo que emplea un grado de aleatoriedad como parte de su lógica o procedimiento. El algoritmo normalmente utiliza bits uniformemente aleatorios como entrada auxiliar para guiar su comportamiento, con la esperanza de lograr un buen rendimiento en el "caso promedio" sobre todas las posibles elecciones aleatorias determinadas por los bits aleatorios; por lo tanto, el tiempo de ejecución o la salida (o ambos) son variables aleatorias.
Existe una distinción entre algoritmos que utilizan la entrada aleatoria para que siempre terminen con la respuesta correcta, pero donde el tiempo de ejecución esperado es finito ( algoritmos de Las Vegas , por ejemplo Quicksort [1] ), y algoritmos que tienen posibilidades de producir un resultado incorrecto ( algoritmos de Monte Carlo , por ejemplo el algoritmo de Monte Carlo para el problema MFAS [2] ) o no producir un resultado ya sea al señalar una falla o al no terminar. En algunos casos, los algoritmos probabilísticos son el único medio práctico para resolver un problema. [3]
En la práctica común, los algoritmos aleatorios se aproximan utilizando un generador de números pseudoaleatorios en lugar de una fuente verdadera de bits aleatorios; dicha implementación puede desviarse del comportamiento teórico esperado y de las garantías matemáticas que pueden depender de la existencia de un generador de números aleatorios verdadero ideal.
Como ejemplo motivador, considere el problema de encontrar una ' a ' en una matriz de n elementos.
Entrada : una matriz de n ≥2 elementos, en los que la mitad son ' a ' y la otra mitad son ' b '.
Salida : busque una ' a ' en la matriz.
Damos dos versiones del algoritmo, un algoritmo de Las Vegas y un algoritmo de Monte Carlo .
Algoritmo de Las Vegas:
encontrandoA_LV ( matriz A , n ) comenzar repetir Seleccione aleatoriamente un elemento entre n elementos . hasta que se encuentre ' a'
Este algoritmo tiene éxito con probabilidad 1. El número de iteraciones varía y puede ser arbitrariamente grande, pero el número esperado de iteraciones es
Como es constante, el tiempo de ejecución esperado para muchas llamadas es . (Ver notación Big Theta )
Algoritmo de Montecarlo:
encontrandoA_MC ( matriz A , n , k ) comenzar i : = 0 repetir Seleccione aleatoriamente un elemento entre n elementos . i := i + 1 hasta que se encuentre i = k o ' a '
Si se encuentra una ' a ', el algoritmo tiene éxito; de lo contrario, falla. Después de k iteraciones, la probabilidad de encontrar una ' a ' es:
Este algoritmo no garantiza el éxito, pero el tiempo de ejecución está limitado. El número de iteraciones es siempre menor o igual que k. Tomando k como constante, el tiempo de ejecución (esperado y absoluto) es .
Los algoritmos aleatorios son particularmente útiles cuando se enfrenta a un "adversario" malicioso o un atacante que intenta deliberadamente introducir una mala entrada en el algoritmo (consulte el análisis competitivo y de complejidad del peor de los casos (algoritmo en línea) ), como en el dilema del prisionero . Es por esta razón que la aleatoriedad es omnipresente en la criptografía . En aplicaciones criptográficas, no se pueden utilizar números pseudoaleatorios, ya que el adversario puede predecirlos, lo que hace que el algoritmo sea efectivamente determinista. Por lo tanto, se requiere una fuente de números verdaderamente aleatorios o un generador de números pseudoaleatorios criptográficamente seguro . Otra área en la que la aleatoriedad es inherente es la computación cuántica .
En el ejemplo anterior, el algoritmo de Las Vegas siempre genera la respuesta correcta, pero su tiempo de ejecución es una variable aleatoria. Se garantiza que el algoritmo Monte Carlo (relacionado con el método Monte Carlo para simulación) se completará en un período de tiempo que puede estar limitado por una función del tamaño de entrada y su parámetro k , pero permite una pequeña probabilidad de error . Observe que cualquier algoritmo de Las Vegas se puede convertir en un algoritmo de Monte Carlo (a través de la desigualdad de Markov ), haciendo que genere una respuesta arbitraria, posiblemente incorrecta, si no se completa dentro de un tiempo específico. Por el contrario, si existe un procedimiento de verificación eficiente para comprobar si una respuesta es correcta, entonces un algoritmo de Monte Carlo se puede convertir en un algoritmo de Las Vegas ejecutando el algoritmo de Monte Carlo repetidamente hasta que se obtenga una respuesta correcta.
La teoría de la complejidad computacional modela algoritmos aleatorios como máquinas probabilísticas de Turing . Se consideran los algoritmos de Las Vegas y Monte Carlo y se estudian varias clases de complejidad . La clase de complejidad aleatoria más básica es RP , que es la clase de problemas de decisión para los cuales existe un algoritmo aleatorio eficiente (tiempo polinómico) (o máquina probabilística de Turing) que reconoce instancias NO con absoluta certeza y reconoce instancias SÍ con una probabilidad. de al menos 1/2. La clase complementaria de RP es co-RP. Se dice que las clases de problemas que tienen algoritmos (posiblemente no terminantes) con tiempo polinómico promedio de ejecución de casos cuya salida es siempre correcta están en ZPP .
La clase de problemas para los cuales se permite identificar instancias SÍ y NO con algún error se llama BPP . Esta clase actúa como el equivalente aleatorio de P , es decir, BPP representa la clase de algoritmos aleatorios eficientes.
Quicksort fue descubierto por Tony Hoare en 1959 y publicado posteriormente en 1961. [4] En el mismo año, Hoare publicó el algoritmo de selección rápida , [5] que encuentra el elemento mediano de una lista en el tiempo esperado lineal. Permaneció abierto hasta 1973 si existía un algoritmo determinista de tiempo lineal. [6]
En 1917, Henry Cabourn Pocklington introdujo un algoritmo aleatorio conocido como algoritmo de Pocklington para encontrar eficientemente números primos en módulo de raíces cuadradas . [7] En 1970, Elwyn Berlekamp introdujo un algoritmo aleatorio para calcular eficientemente las raíces de un polinomio en un campo finito. [8] En 1977, Robert M. Solovay y Volker Strassen descubrieron una prueba de primalidad aleatoria en tiempo polinomial (es decir, determinar la primalidad de un número). Poco después, Michael O. Rabin demostró que la prueba de primalidad de Miller de 1976 también podía convertirse en un algoritmo aleatorio de tiempo polinomial. En ese momento, no se conocía ningún algoritmo determinista de tiempo polinomial demostrable para las pruebas de primalidad.
Una de las primeras estructuras de datos aleatorios es la tabla hash , que fue introducida en 1953 por Hans Peter Luhn en IBM . [9] La tabla hash de Luhn utilizaba encadenamiento para resolver colisiones y también fue una de las primeras aplicaciones de listas enlazadas . [9] Posteriormente, en 1954, Gene Amdahl , Elaine M. McGraw , Nathaniel Rochester y Arthur Samuel de IBM Research introdujeron el sondeo lineal , [9] aunque Andrey Ershov independientemente tuvo la misma idea en 1957. [9] En 1962, Donald Knuth realizó el primer análisis correcto del sondeo lineal, [9] aunque el memorando que contenía su análisis no se publicó hasta mucho más tarde. [10] El primer análisis publicado se debió a Konheim y Weiss en 1966. [11]
Los primeros trabajos sobre tablas hash asumieron el acceso a una función hash completamente aleatoria o asumieron que las claves en sí eran aleatorias. [9] En 1979, Carter y Wegman introdujeron funciones hash universales , [12] que demostraron que podían usarse para implementar tablas hash encadenadas con un tiempo esperado constante por operación.
Los primeros trabajos sobre estructuras de datos aleatorias también se extendieron más allá de las tablas hash. En 1970, Burton Howard Bloom introdujo una estructura de datos de membresía aproximada conocida como filtro Bloom . [13] En 1989, Raimund Seidel y Cecilia R. Aragon introdujeron un árbol de búsqueda equilibrado aleatorio conocido como treap . [14] Ese mismo año, William Pugh introdujo otro árbol de búsqueda aleatoria conocido como lista de omisión . [15]
Antes de la popularización de los algoritmos aleatorios en informática, Paul Erdős popularizó el uso de construcciones aleatorias como técnica matemática para establecer la existencia de objetos matemáticos. Esta técnica se conoce como método probabilístico . [16] Erdős dio su primera aplicación del método probabilístico en 1947, cuando utilizó una construcción aleatoria simple para establecer la existencia de gráficos de Ramsey. [17] En 1959 utilizó un algoritmo aleatorio mucho más sofisticado para establecer la existencia de gráficos con gran circunferencia y número cromático. [18] [16]
Quicksort es un algoritmo familiar y de uso común en el que la aleatoriedad puede resultar útil. Muchas versiones deterministas de este algoritmo requieren O ( n 2 ) tiempo para ordenar n números para alguna clase bien definida de entradas degeneradas (como una matriz ya ordenada), con la clase específica de entradas que generan este comportamiento definida por el protocolo para selección de pivote. Sin embargo, si el algoritmo selecciona elementos pivote de manera uniforme y aleatoria, tiene una probabilidad demostrablemente alta de terminar en O ( n log n ) tiempo, independientemente de las características de la entrada.
En geometría computacional , una técnica estándar para construir una estructura como un casco convexo o triangulación de Delaunay es permutar aleatoriamente los puntos de entrada y luego insertarlos uno por uno en la estructura existente. La aleatorización garantiza que el número esperado de cambios en la estructura causados por una inserción sea pequeño y, por lo tanto, el tiempo de ejecución esperado del algoritmo puede limitarse desde arriba. Esta técnica se conoce como construcción incremental aleatoria. [19]
Entrada : Un gráfico G ( V , E )
Salida : Un corte que divide los vértices en L y R , con el número mínimo de aristas entre L y R.
Recuerde que la contracción de dos nodos, u y v , en un (multi)gráfico produce un nuevo nodo u ' con aristas que son la unión de las aristas incidentes en u o v , excepto desde cualquier arista que conecte u. y v . La Figura 1 da un ejemplo de contracción de los vértices A y B. Después de la contracción, el gráfico resultante puede tener bordes paralelos, pero no contiene bucles propios.
Algoritmo básico de Karger [20] :
comenzar yo = 1 repetir repetir Tome una arista aleatoria (u,v) ∈ E en G reemplaza u y v con la contracción u' hasta que solo queden 2 nodos obtener el resultado de corte correspondiente C i yo = yo + 1 hasta que i = m genera el corte mínimo entre C 1 , C 2 , ..., C m . fin
En cada ejecución del bucle exterior, el algoritmo repite el bucle interior hasta que solo queden 2 nodos, se obtiene el corte correspondiente. El tiempo de ejecución de una ejecución es y n denota el número de vértices. Después de m ejecuciones del bucle externo, generamos el corte mínimo entre todos los resultados. La figura 2 ofrece un ejemplo de una ejecución del algoritmo. Después de la ejecución, obtenemos un corte de tamaño 3.
Lema 1 : Sea k el tamaño de corte mínimo y sea C = { e 1 , e 2 , ..., e k } el corte mínimo. Si, durante la iteración i , no se selecciona ninguna arista e ∈ C para la contracción, entonces C i = C.
Si G no está conectado, entonces G se puede dividir en L y R sin ningún borde entre ellos. Entonces el corte mínimo en un gráfico desconectado es 0. Ahora, supongamos que G es conexo. Sea V = L ∪ R la partición de V inducida por C : C = { { u , v } ∈ E : u ∈ L , v ∈ R } (bien definido ya que G es conexo). Considere una arista { u , v } de C. Inicialmente, u , v son vértices distintos. Mientras elijamos una arista , u y v no se fusionan. Así, al final del algoritmo, tenemos dos nodos compuestos que cubren todo el gráfico, uno formado por los vértices de L y el otro por los vértices de R. Como en la figura 2, el tamaño del corte mínimo es 1 y C = {( A , B )}. Si no seleccionamos ( A , B ) para la contracción, podemos obtener el corte mínimo.
Lema 2 : si G es un multigrafo con p vértices y cuyo corte mínimo tiene tamaño k , entonces G tiene al menos pk /2 aristas.
Debido a que el corte mínimo es k , cada vértice v debe satisfacer el grado ( v ) ≥ k . Por tanto, la suma de los grados es al menos pk . Pero es bien sabido que la suma de los grados de los vértices es 2| mi |. El lema sigue.
La probabilidad de que el algoritmo tenga éxito es 1: la probabilidad de que todos los intentos fallen. Por independencia, la probabilidad de que todos los intentos fallen es
Según el lema 1, la probabilidad de que C i = C es la probabilidad de que no se seleccione ningún borde de C durante la iteración i . Considere el bucle interno y sea G j el gráfico después de j contracciones de borde, donde j ∈ {0, 1,…, n − 3} . G j tiene n − j vértices. Usamos la regla de la cadena de posibilidades condicionales . La probabilidad de que la arista elegida en la iteración j no esté en C , dado que no se ha elegido ninguna arista de C antes, es . Tenga en cuenta que G j todavía tiene un corte mínimo de tamaño k , por lo que según el Lema 2, todavía tiene al menos aristas.
De este modo, .
Entonces, según la regla de la cadena, la probabilidad de encontrar el corte mínimo C es
La cancelación da . Por tanto, la probabilidad de que el algoritmo tenga éxito es al menos . Para , esto es equivalente a . El algoritmo encuentra el corte mínimo con probabilidad , en el tiempo .
La aleatoriedad puede verse como un recurso, como el espacio y el tiempo. La desrandomización es entonces el proceso de eliminar la aleatoriedad (o utilizar la menor cantidad posible de ella). Actualmente no se conoce [ a partir de? ] si todos los algoritmos se pueden desaleatorizar sin aumentar significativamente su tiempo de ejecución. Por ejemplo, en complejidad computacional , se desconoce si P = BPP , es decir, no sabemos si podemos tomar un algoritmo aleatorio arbitrario que se ejecuta en tiempo polinomial con una pequeña probabilidad de error y desaleatorizarlo para que se ejecute en tiempo polinomial sin usar aleatoriedad. .
Existen métodos específicos que se pueden emplear para desaleatorizar algoritmos aleatorios particulares:
Cuando el modelo de computación se restringe a las máquinas de Turing , actualmente queda abierta la cuestión de si la capacidad de realizar elecciones aleatorias permite resolver algunos problemas en tiempo polinomial que no se pueden resolver en tiempo polinomial sin esta capacidad; ésta es la cuestión de si P = BPP. Sin embargo, en otros contextos, existen ejemplos específicos de problemas en los que la aleatorización produce mejoras estrictas.
{{cite book}}
: Mantenimiento CS1: falta el editor de la ubicación ( enlace )