¿Cómo se modela la complejidad del algoritmo para lenguajes funcionales?

38

La complejidad del algoritmo está diseñada para ser independiente de los detalles de nivel inferior, pero se basa en un modelo imperativo, por ejemplo, el acceso a la matriz y la modificación de un nodo en un árbol toman O (1) tiempo. Este no es el caso en lenguajes funcionales puros. La lista de Haskell toma tiempo lineal para acceder. La modificación de un nodo en un árbol implica hacer una nueva copia del árbol.

¿Debería haber un modelado alternativo de la complejidad del algoritmo para los lenguajes funcionales?

wsaleem
fuente
3
Esto podría ser lo que estás buscando.
Aristu
1
Su pregunta puede ser respondida aquí: cs.stackexchange.com/q/18262/755 . En particular, la complejidad del tiempo en un lenguaje puramente funcional difiere de la complejidad del tiempo en un lenguaje imperativo en una proporción de como máximo , para algunos supuestos adecuados sobre las capacidades de ambos idiomas. O(Iniciar sesiónnorte)
DW
3
GHC Haskell admite matrices y árboles mutables y demás, lo que le permite acceder a la matriz y modificar nodos de árbol en el tiempo O (1), utilizando "hilos de estado" (las STmónadas).
Tanner Swett
1
@BobJarvis depende. ¿Es una lista un tipo de datos abstracto para usted o está considerando específicamente listas enlazadas?
Raphael
1
¿Qué propósito busca para modelar la complejidad algorítmica? ¿Estás buscando algo matemáticamente puro o algo práctico? Para un valor práctico, debe prestar atención a cosas como si tiene o no memorización disponible para usted, pero desde un punto de vista matemático purista, las capacidades de la implementación no deberían importar.
Cort Ammon

Respuestas:

34

Si supone que el cálculo es un buen modelo de lenguajes de programación funcionales, entonces uno puede pensar: el cálculo λ tiene una noción aparentemente simple de complejidad temporal: solo cuente el número de pasos de reducción β ( λ x . M ) N M [ N / x ] .λλβ(λX.METRO)norteMETRO[norte/ /X]

¿Pero es esta una buena medida de complejidad?

Para responder a esta pregunta, debemos aclarar qué entendemos por medida de complejidad en primer lugar. La tesis de Slot y van Emde Boas da una buena respuesta : cualquier buena medida de complejidad debe tener una relación polinómica con la noción canónica de complejidad temporal definida con las máquinas de Turing. En otras palabras, debe haber un 'razonable' que codifica A partir de lambda términos -calculus a las máquinas de Turing, como para algunas polinomio p , es el caso de que para cada término M de tamaño | M | : M se reduce a un valor en p ( | M |tr(.)λpagsMETROEl |METROEl |METRO pasos de reducción β exactamente cuando t r ( M ) se reduce a un valor en p ( | t r ( M ) | ) pasos de una máquina Turing.pags(El |METROEl |) βtr(METRO)pags(El |tr(METRO)El |)

Durante mucho tiempo, no estaba claro si esto se puede lograr en el cálculo λ. Los principales problemas son los siguientes.

  • Hay términos que producen formas normales (en un número polinómico de pasos) que son de tamaño exponencial. Incluso escribir las formas normales lleva tiempo exponencial.
  • La estrategia de reducción elegida juega un papel importante. Por ejemplo, existe una familia de términos que se reduce en un número polinómico de β-pasos paralelos (en el sentido de una reducción λ óptima ), pero cuya complejidad es no elemental (es decir, peor que exponencial).

β

No estoy seguro de cuál es la situación para otras estrategias de evaluación. No soy consciente de que se haya llevado a cabo un programa similar para la complejidad del espacio.

Martin Berger
fuente
23

La complejidad del algoritmo está diseñada para ser independiente de los detalles de nivel inferior.

No en realidad no. Siempre contamos las operaciones elementales en algunos modelos de máquina:

  • Pasos para máquinas de Turing.
  • Operaciones básicas en RAM.

ΩΘOΘ

Por lo tanto, su pregunta tiene una respuesta simple: arreglar un modelo de máquina y qué "operaciones" contar. Esto te dará una medida. Si desea que los resultados sean comparables a los algoritmos no funcionales, lo mejor sería compilar sus programas en RAM (para el análisis de algoritmos) o TM (para la teoría de la complejidad), y analizar el resultado. Los teoremas de transferencia pueden existir para facilitar este proceso.

Rafael
fuente
Convenido. Nota al margen: Las personas hacen con frecuencia hacen un montón de errores sobre qué operaciones son "constantes". Por ejemplo, suponiendo que a + b es O(1)cuando realmente esO(log ab)
Paul Draper
3
@PaulDraper Esa es una suposición diferente, no necesariamente un error. Podemos modelar lo que queremos: la pregunta es si responde preguntas interesantes. Ver también aquí .
Raphael
eso suena mucho como "deshacerse del modelo de máquina"
Paul Draper
@PaulDraper Depende del tipo de sentimientos que adjunte a la palabra "máquina". Ver también esta discusión . FWIW, el modelo RAM de costo unitario, ¡posiblemente el modelo estándar en análisis de algoritmos! - es útil, de lo contrario no se habría utilizado durante décadas. Todos los límites familiares para la clasificación, búsqueda, etc. se basan en ese modelo. Tiene sentido porque modela bien las computadoras reales siempre que los números quepan en los registros.
Raphael
1

En lugar de formular su medida de complejidad en términos de alguna máquina abstracta subyacente, puede incluir el costo en las definiciones del lenguaje en sí, esto se llama Dinámica de Costos . Uno atribuye un costo a cada regla de evaluación en el lenguaje, de manera compositiva, es decir, el costo de una operación es una función del costo de sus sub-expresiones. Este enfoque es más natural para los lenguajes funcionales, pero puede usarse para cualquier lenguaje de programación bien definido (por supuesto, la mayoría de los lenguajes de programación no están bien definidos).

cabeza de jardín
fuente
<Discusión sobre qué es un modelo de máquina eliminado.> Continuemos esta discusión en el chat .
Raphael