¿Encuentra programáticamente la notación de Landau (notación Big O o Theta) de un algoritmo?

11

Estoy acostumbrado a buscar la notación de Landau (Big O, Theta ...) de mis algoritmos a mano para asegurarme de que estén tan optimizados como sea posible, pero cuando las funciones se vuelven realmente grandes y complejas, está tomando forma demasiado tiempo para hacerlo a mano. También es propenso a errores humanos.

Pasé un tiempo en Codility (ejercicios de codificación / algo), y noté que le darán la notación de Landau para su solución presentada (tanto en el uso del tiempo como de la memoria).

Me preguntaba cómo lo hacen ... ¿Cómo lo harías?

¿Hay otra forma además del análisis léxico o el análisis del código?

Esta pregunta se refiere principalmente a PHP y / o JavaScript, pero estoy abierto a cualquier lenguaje y teoría.

Julien L
fuente
44
Verifique esta respuesta de SO. Suena como lo que estás buscando.
Deco
2
Si puedes crear un programa que resuelva este problema para todos y cada uno de los algoritmos, serás famoso como "el hombre que refutó a Turing".
user281377
1
Para ver las pruebas de que, en general, es imposible decidir los tiempos de ejecución, consulte aquí y aquí ; las respuestas allí prueban incluso más de lo que pide, en realidad.
Alex ten Brink

Respuestas:

13

Me preguntaba cómo lo hacen ... ¿Cómo lo harías?

Me imagino que en realidad están estimando las medidas Big O ... ejecutando el programa para diferentes tamaños de problemas, midiendo el tiempo y el uso del espacio, y ajustando curvas a los resultados.

El problema con este enfoque es que puede equivocarse si las funciones de costo cambian de forma a medida que N aumenta; por ej 1000 N + N^1.5.

¿Hay otra forma además del análisis léxico o el análisis del código?

El análisis léxico y el análisis no son suficientes. También debe razonar sobre el comportamiento del algoritmo. Y hacer eso automáticamente para un algoritmo previamente desconocido es difícil.

Stephen C
fuente
66
"hacer eso automáticamente para un algoritmo previamente desconocido es difícil" - Más precisamente: es equivalente a resolver el problema de detención.
Jörg W Mittag
Ermm ... no exactamente. Resolver el problema de detención sería equivalente a poder hacerlo para todos los algoritmos previamente desconocidos.
Stephen C
2
Si, lo siento. Hacerlo para un algoritmo es equivalente a (o más bien implica) probar la terminación.
Jörg W Mittag
1
Los aspectos prácticos de esto son que 1) es imposible probar o refutar la terminación de algunos algoritmos, pero 2) la mayoría de los algoritmos no tienen este impedimento teórico, pero 3) el estado del arte en la prueba de teoremas no está lo suficientemente avanzado para ser capaz de hacer esto de todos modos ... excepto en casos relativamente simples. De ahí mi afirmación de que imagino que lo están haciendo de una manera diferente. Pero obviamente, no podemos estar seguros de cómo lo están haciendo realmente sin mirar su código.
Stephen C
3

No pueden sin analizar el código.

Los ejemplos a continuación con "inflación / deflación" artificial de complejidad prueban que simplemente medir el tiempo de ejecución del programa no es suficiente para estimar confiablemente Big-O

void lets_trick_runtime(int n) {
   if (n == 10 || n == 25 || n == 118) {
      // unfair speed-up
      do_precalculated_solution_in_constant_time(n);
      return;
   }
   if (n == 11 || n == 26 || n == 119) {
      // unfair slow-down
      do_some_fake_processing_in_n_cube_time(n);
      return;
   }
   // fair solution
   do_general_solution_in_quadratic_time(n);
}

La estimación del tiempo de ejecución para lo anterior sería susceptible de dar estimaciones falsas: tiempo constante para valores de ndonde hay una solución precalculada y tiempo cúbico para valores donde unfair slow-downentra en acción, en lugar del tiempo cuadrático "justo".

mosquito
fuente
Sin embargo, si comprueban los casos "injustos", aún pueden suponer que el peor de los casos estima la complejidad de Big-O.
Yam Marcovic
1

Creo que esto no es posible.

Si ejecuta algunas pruebas con un número fijo de diferentes tamaños de entrada, puede calcular fácilmente un polinomio, que se aproximará a los tiempos de ejecución que ha medido muy bien. Entonces terminas con un polinomio para cada programa posible, lo que significaría P = NP(¡sí!;)).

Si intentas hacerlo con manipulación simbólica, terminas en el halting problem. Como no puede decidir si su programa se detendrá, no puede decidir qué complejidad de tiempo de ejecución tendrá.

Sin embargo, puede haber casos muy especiales, donde el método posterior es posible. Pero estos casos pueden ser tan pequeños, que es cuestionable si alguna vez se paga el esfuerzo.

SpaceTrucker
fuente
1
+1, aunque creo que el problema de detención podría considerarse una rareza.
Yam Marcovic
0

¿Cómo lo haría? La forma en que resuelvo casi cualquier problema no quiero sentarme y resolver . Simulo

Para muchos problemas, puede ser suficiente ejecutar su algoritmo muchas veces usando una variedad de tamaños y luego ajustar una curva de regresión a esos resultados. Eso identificaría rápidamente algunos costos generales "fijos" particulares de su algoritmo (la intersección de la curva) y cómo se escala a medida que aumenta el tamaño de su problema.

Se necesitarán algunos ajustes para capturar soluciones particularmente complicadas, pero especialmente si solo está buscando una estimación aproximada, debería poder obtenerla de esa manera, y ver cómo su estimación difiere de sus resultados reales y decidir si es Una aproximación aceptable.

La mayor debilidad en mi mente con este método es que si su algoritmo se escala muy mal, ese paso inicial de "ejecutarlo un montón de veces" se volverá feo. Pero, francamente, ese es el caso, eso solo debería ser un indicador de que tal vez desee retroceder y reconsiderar las cosas.

Fomite
fuente
0

Mi intuición es que una solución general a este problema es imposible; afirmando, como lo hace, hechos a priori sobre el tiempo de ejecución de los algoritmos sin ejecutarlos (alude al análisis léxico). Dicho esto, es posible que algún algoritmo heurístico para una clase (probablemente grande) de algoritmos (ya que lo hacemos todo el tiempo), pero un algoritmo general para hacer esto sería equivalente a resolver el problema Entscheidungs que es bien sabido que no es posible (cf. Church, Turing, et al.). Estoy ~ 99.9% seguro de esto ahora que lo pienso ...

muy tonto
fuente