¿Cuáles son algunos problemas prácticos en los que no se puede evitar el uso de algoritmos con big-O muy grande?

Antes de dar un ejemplo, debo aclarar algo de terminología. Su pregunta indica que tal vez esté un poco confundido acerca de lo que se entiende por “algoritmo heurístico”, porque los algoritmos heurísticos a menudo tienen tiempos de ejecución de gran O muy grandes; Por eso necesitamos una heurística. El tiempo de ejecución Big-O es (tradicionalmente / por defecto) el peor tiempo de ejecución; Utilizamos una heurística para hacer que un algoritmo se ejecute rápidamente en los casos más comunes. En otras palabras, la heurística captura algo sobre el dominio del problema para que los problemas que realmente encuentre no sean el peor de los casos.

Veamos ejemplos. El Boolean Satisfiability Problem (SAT) es un problema clásico de NP completo, por lo que cada algoritmo conocido tiene un tiempo de ejecución exponencial en el peor de los casos. El problema consiste en decidir si las variables en una expresión booleana dada (variables ANDed, ORed y NOTed juntas) pueden asignarse valores de verdad de modo que toda la expresión sea verdadera. Por ejemplo, “a AND b” es trivialmente satisfactoria; “A AND NOT a” es trivialmente insatisfactorio.

¿Dónde podríamos necesitar resolver este problema? Bueno, a menudo queremos simplificar alguna expresión booleana. Esto sucede en el diseño de circuitos integrados, por ejemplo, que en gran medida se realiza por software en estos días. Tenga en cuenta que simplificar completamente una expresión booleana es al menos tan difícil como decidir si es satisfactoria, porque si no lo es, se simplifica a FALSO.

Para obtener la respuesta a su pregunta, resolvemos este problema utilizando algoritmos con una complejidad de tiempo exponencial, como picosat (entre muchos otros) y, sin embargo, a menudo lo resolvemos para expresiones muy grandes. Los algoritmos utilizados son a menudo fundamentalmente bastante simples (adivinar y dar marcha atrás cuando se encuentra un conflicto; véase, por ejemplo, el aprendizaje de cláusulas controladas por conflictos), pero se hacen rápidamente en casos comunes (por ejemplo, muchas cláusulas OR juntas, con pocos AND y NOTs) por heurística sobre qué variables elegir y cómo retroceder.

El punto clave es que el tiempo de ejecución Big-O no lo es todo. Si lo fuera, los algoritmos de tiempo exponencial simplemente serían inviables con entradas suficientemente grandes. Tal como están las cosas, las entradas generalmente están restringidas a pequeños subconjuntos del dominio que pueden resolverse en un tiempo razonable.

Hay muchos otros problemas para los cuales se toman enfoques similares. En particular:

  • Para el famoso problema de la mochila, tenemos un algoritmo que es de tiempo lineal tanto en el número de pesos de entrada como en el peso total. Este es un tiempo técnicamente exponencial, porque el tamaño de entrada es logarítmico en el peso total utilizando una representación binaria.
  • El isomorfismo gráfico, nuevamente utilizado en EDA, para el cual existen algoritmos eficientes para prácticamente todos los gráficos comunes pero que no tiene un algoritmo de tiempo polinomial conocido.

Tan pronto como su software comience a manejar una cantidad significativa de datos, no puede evitar grandes O.

Además, puede que no sean datos, pero tan pronto como comience a hacer una cantidad significativa de cálculos, no puede evitar grandes O.

En mis primeros días de desarrollo, en su mayoría proyectos de hobby, realmente no me importaba esto e incluso en mis trabajos anteriores vi código mal diseñado en términos de su complejidad de tiempo, es decir, gran O, pero en ambos casos ni gran cantidad de datos ni datos significativos los cálculos estuvieron involucrados. Entonces el código era aceptable.

Un buen ejemplo práctico sería simplemente calcular la mejor ruta desde su hogar a su trabajo, que es lo que hace el software de navegación. Hay muchos cálculos involucrados en la búsqueda de la mejor ruta y, a medida que conduce, debe actualizarse muy rápidamente en función del cambio del conjunto de datos.

Del mismo modo, al buscar en Google, verá que tan pronto como comienza a escribir, comienza a darle sugerencias como opciones de autocompletar. Con algoritmos O grandes y pobres, primero no sería tan rápido, segundo no sería tan relevante para lo que está escribiendo.

Cada pieza de código que es rápida y precisa, y que maneja muchos datos y cálculos, la O grande se vuelve relevante.

En mi experiencia personal, cuando comencé a tocar grandes conjuntos de datos, de repente la complejidad comenzó a importar.

Más tarde, al tratar con cálculos complejos, me di cuenta de la importancia de la complejidad del tiempo, es decir, la gran O.

Y póngalos juntos, que es más o menos la esencia de la programación actual, es decir, muchos datos, muchos cálculos, cálculos complejos relacionados con la IA, el aprendizaje automático o la simple toma de decisiones: debe hacerlo de manera rápida y eficiente. No puede utilizar un código no creativo (o mal codificado en otras palabras) que tomará 10 segundos para dar su salida, y tiene cientos de miles de solicitudes para las cuales necesita devolver la respuesta.

Lo aprendí con experiencia y de proyectos de la vida real, de lo contrario al principio tampoco podría entender la importancia de la gran O. Y todavía lo estoy aprendiendo. Siempre hay espacio para mejorar sus algoritmos.

More Interesting

¿Cuáles son los algoritmos de correspondencia de gráficos de última generación?

¿Cuáles son algunas de las preguntas famosas al calcular los caminos más cortos (gráficos) usando Dijkstra's, DAG y Bellman-Ford?

La mayoría de las definiciones / teoremas / ejemplos de privacidad diferencial que he encontrado son para consultas que devuelven un solo número por columna, como un promedio. ¿Existen mecanismos diferencialmente privados para otros tipos de consultas, como los que subconjustan filas en función de algún criterio?

¿Por qué son tan importantes los algoritmos?

¿Se puede usar la GPU para optimizar los algoritmos gráficos?

¿Hay algún libro que tenga todos los códigos para todas las estructuras de datos? ¿Al menos para todas las estructuras de datos de árbol?

Dadas dos cadenas de longitud N, ¿cómo encuentro la ventana máxima de patrones coincidentes si pueden mutarse?

¿Qué es la matriz? Por favor explique los detalles.

¿Por qué el tipo Bubble se llama Bobble?

¿Están sobrevalorados los algoritmos, en comparación con la escritura de software limpio, escalable y de fácil mantenimiento? Sé mi parte de algoritmos y acerté mis entrevistas. Pero en la industria, se trata de cumplir con los requisitos de software y administrar la base del código.

¿Por qué las personas usan mid = low + (high-low) / 2 en lugar de (low + high) / 2?

Cómo implementar la ordenación de inserción recursiva usando una lista vinculada

¿Se podría explicar y crear inteligencia artificial utilizando algoritmos?

¿Somos solo un algoritmo?

¿Cómo funciona el algoritmo de clasificación de páginas de Google?