Está bien, lo intentaré. Tenga en cuenta que esta será una respuesta un tanto lentosa, ya que esto se basa en muchas cosas con las que las personas que no son informáticas podrían no estar familiarizadas.
Paso 0: problemas y algoritmos
Un problema es básicamente lo que significa en términos simples, pero en términos más concretos. Específicamente, si se me ocurre una solución, es posible decidir inequívocamente si tenía razón o no.
Un ejemplo: Multiplicación polinómica
La mayoría de las personas están familiarizadas con los polinomios, se ven algo así como:
[matemáticas] 5x ^ 2 + 2x – 7 [/ matemáticas]
Entonces, es posible que también haya tenido que multiplicar dos polinomios, así:
[matemáticas] (5x ^ 2 + 2x – 7) [/ matemáticas] * [matemáticas] (8x ^ 4 – 7x ^ 3 + 1) [/ matemáticas]
Entonces nuestro problema es ahora: dados dos polinomios, multiplíquelos.
La solución de este problema es fácil de clasificar como correcta o incorrecta: no hay “depende” o “maybes”. Eso está bien. En general, este es el tipo de problemas que enfrentamos: problemas claros con respuestas definitivas.
Un ingenuo algoritmo
Bueno, el método más obvio es el que usamos normalmente: simplemente tome cada término del primer polinomio, multiplíquelo con cada término individual del segundo, y luego agregue todo lo que obtenga.
Esto es lo que se llama un algoritmo, una especie de receta para resolver el problema. Lo primero que nos preocupa es si un algoritmo es correcto, es decir, ¿siempre da la respuesta correcta? Pero una vez que lo hemos hecho, el problema relevante es: ¿qué tan rápido es? Y eso nos lleva a …
Paso 1: Complejidad del tiempo y notación Big O
Esto básicamente significa cuánto tiempo tarda el algoritmo en calcular la respuesta correcta dado un problema de tamaño n.
Por ejemplo, n en nuestro problema de multiplicación polinómica es el tamaño de los polinomios, es decir, el número de términos. Digamos que cada uno de ellos tiene n términos.
Veamos cómo funciona la complejidad del tiempo en este caso.
Como elegimos el primer término del primer polinomio, y lo multiplicamos con todos los n términos del segundo, y hacemos esto para cada uno de los n términos del primero, tomamos
[matemática] n * n = n ^ 2 [/ matemática] pasos.
Lo que esto significa es que si duplicamos el tamaño de nuestra entrada (n), ahora nos llevaría [matemática] 4n ^ 2 [/ matemática] pasos, cuatro veces más.
Por lo tanto, nuestro algoritmo de multiplicación simple es O (n ^ 2).
Estoy escondiendo muchas minucias, pero esto es esencialmente de lo que se trata la notación O grande: cuánto más tarda un algoritmo a medida que aumentamos el tamaño de la entrada.
Puede haber varios otros órdenes: O (log (n)), que es excelente, O (n) – lineal, esto sigue siendo bastante bueno, O (1) – es decir, el esfuerzo involucrado no aumenta en absoluto, y pronto.
Pero algunas de estas órdenes no nos gustan en absoluto.
Paso 2: ¡El orden exponencial es MALO!
Ahora que tenemos una idea sobre el tiempo de ejecución y el orden, hagamos algunos cálculos. Supongamos que tenemos un algoritmo que es de orden exponencial, es decir,
[matemáticas] O (2 ^ n) [/ matemáticas]
Digamos que un problema de tamaño 1, es decir, [matemática] n = 1 [/ matemática], nos toma 2 milisegundos para resolver. Bastante bien eh?
Hmm, veamos.
Ahora suponga que el tamaño del problema es 10. Eso en realidad nos lleva aproximadamente 2 ^ 10 milisegundos, o aproximadamente un segundo. Sigue yendo fuerte. ¿Qué sucede cuando el tamaño del problema llega a 20?
Ahora estamos hasta 1024 * 1024 ms, o aproximadamente 16 minutos. Quizás quieras tomar una taza de café.
En el momento en que estamos en [matemáticas] n = 30 [/ matemáticas], sin embargo, estamos viendo 12 días. Whoa! Y si desafortunadamente obtenemos n = 40, ¡eso nos llevará 34 años! No está bien.
Entonces, cuando el tamaño del problema pasó de 1 a 40, el tiempo para resolverlo pasó de 1 milisegundo a 34 años.
Y es por eso que odiamos absolutamente el orden exponencial: para algo más que pequeños problemas, simplemente no es lo suficientemente rápido para fines prácticos. Es tan malo que hace que algo como n ^ 2, n ^ 4 o incluso n ^ 10 se vea mejor en comparación.
Paso 3: P y NP
Y ahora estamos llegando al meollo de la cuestión. Hay todo un mundo de problemas, algunos fáciles, otros difíciles y otros intermedios. Básicamente los dividimos en dos partes (no necesariamente exclusivas):
- P: Estos son los problemas que puede resolver razonablemente rápido. En la práctica, razonablemente rápido resulta ser un tiempo polinómico (n ^ 2, n ^ 3 y similares). La P significa Tiempo olinomial.
- NP: Estos son problemas donde puedes compruebe si una solución dada es correcta o no razonablemente rápida. ¡El NP representa algo complicado que no vamos a abordar ahora mismo!
Paso 4: ¿P = NP?
Y así llegamos a la verdadera pregunta aquí:
Dado un problema cuyas soluciones puedo verificar rápidamente (NP), ¿también puedo encontrar un algoritmo que pueda resolver este problema rápidamente (P)?
De manera equivalente, ¿están todos los problemas en la clase NP también en la clase P?
Un ejemplo:
Suponga que se nos dan algunos enteros, como {−7, −3, −2, 5, 8}, y deseamos saber si algunos de estos enteros suman cero. En este ejemplo, la respuesta es “sí”, ya que el subconjunto de enteros {−3, −2, 5} corresponde a la suma (−3) + (−2) + 5 = 0. La tarea de decidir si El subconjunto con suma cero existe se denomina problema de suma de subconjuntos .
Ahora, dar una solución candidata es bastante sencillo aquí: ¡solo agréguelas! Pero, en realidad, encontrar la solución correcta implica mucho esfuerzo: tenemos que buscar muchas posibilidades (exponencial, en realidad).
¿La respuesta? No lo sabemos Este es un gran problema en la informática y en muchas otras áreas de la ciencia. Si supiéramos que P = NP, sabemos que es posible resolver un montón de problemas difíciles rápidamente, y eso, créanme, es un gran problema. Afectaría todo tipo de áreas dispares. Por ejemplo, la seguridad en las transacciones en línea se centra esencialmente en el hecho de que factorizar grandes cantidades es difícil. Pero si P = NP, ese ya no sería el caso.
Si resulta que P no es igual a NP, bueno, eso no cambiará las cosas tan radicalmente, pero seguirá siendo un gran problema. Por un lado, sabremos que simplemente no podemos resolver estos problemas rápidamente, por lo que podemos pasar a buscar otras vías: algoritmos aproximados, algoritmos probabilísticos, etc.
Paso 5: NP-completitud y NP-dureza
Ok, hora de diagramas elegantes:
Lo que está viendo es una representación de problemas P, NP, NP completos y NP difíciles. Puede ver que P está realmente contenido en NP, tiene sentido, ya que si puede resolverlo rápidamente, también puede verificar la solución rápidamente. Más allá de NP, tenemos NP-hard.
¿Qué significa ser NP-hard? Significa que si puede resolver un problema NP-difícil en tiempo polinómico, entonces puede resolver todos los problemas NP en tiempo polinómico.
Lo que esto significa es que los problemas NP pueden reducirse a problemas NP difíciles. Reducir el problema A a B significa que con un poco de modificación, también puedo adaptar un algoritmo para B a A. Entonces, por ejemplo, si pudiera resolver ecuaciones cúbicas [matemáticas] ax ^ 3 + bx ^ 2 + cx + d = 0 [/ matemáticas], entonces claramente también puedo resolver ecuaciones cuadráticas, ya que una ecuación cuadrática [matemáticas] ax ^ 2 + bx + c = 0 [/ math] es solo una ecuación cúbica con el término x ^ 3 cero. Entonces, he reducido la resolución de ecuaciones cuadráticas a la resolución de ecuaciones cúbicas.
Y, por último, los problemas de NP completo son, como puede ver en la imagen, problemas NP y NP. Es decir, puede reducir todos los problemas de NP a un problema de NP completo y, como beneficio adicional, también es fácil verificar la solución a un problema de NP completo.
Paso 6: tl; dr
Resumir :
- P: problemas que pueden resolverse rápidamente.
- NP: problemas cuyas soluciones se pueden verificar rápidamente.
- P = NP: ¿podemos tener algoritmos rápidos para todos los problemas cuyas respuestas podemos verificar fácilmente?
- NP-hard: resuelve uno de estos rápidamente, y puedes resolver todos los problemas de NP rápidamente.
- NP-complete: NP-hard y las soluciones se pueden verificar fácilmente.
PD: No soy un experto en todo esto, y muchos detalles técnicos se han perdido en mi explicación. Entonces, si estás leyendo esto y eres alguien como Jessica Su, perdona cualquier imprecisión. Editar sugerencias bienvenido!
Editar: abordar las preguntas de Christopher VanLang en los comentarios de las preguntas:
¿Qué significa que un problema sea no determinista?
En el polinomio no determinista, no determinista es la computadora, no el problema. Los problemas son deterministas.
¿Cuál es la definición de un problema?
Un problema en este contexto se refiere a una definición precisa de lo que se nos da y lo que se supone que debemos hacer, sin duda ni subjetividad. Por ejemplo, el problema de la clasificación es:
Dada una lista de números, envíe los números en un orden no decreciente (es decir, ordénelos por tamaño). Lo importante es que las respuestas a los problemas son en blanco y negro: o tienen razón o no. No hay medidas a medias.
¿Cómo se relaciona todo esto con una máquina de Turing?
Máquinas de Turing por las que no necesita preocuparse. Una máquina de turing es básicamente un modelo teórico para una computadora.
Si P es un subconjunto de NP, ¿por qué molestarse en tener una clasificación P en primer lugar?
Bueno, esto es lo que hacemos: tomar una clase general y poner algunas de las cosas en ella bajo una etiqueta separada por conveniencia.
Las películas de acción son un subconjunto de películas. Las mujeres son un subconjunto de humanos. Los planetas son un subconjunto de cuerpos astronómicos. Las sillas son un subconjunto de muebles.
El hecho de que P sea un subconjunto de NP no significa que la noción de P no sea útil. Lo usamos para identificar problemas que se pueden resolver en tiempo polinómico. Otros problemas en NP pueden o no ser solucionables en tiempo polinómico.
¿Cuál es la definición de difícil?
La definición varía, pero cualquier cosa que requiera un tiempo exponencial o más largo para resolver se considera difícil, porque como dije en mi respuesta, a medida que aumenta el tamaño del problema, ¡el tiempo necesario para resolverlo aumenta como loco!
¿Cuál es la definición de fácil? Si P = NP, ¿por qué importa algo de esto?
Fácil es problemas que se pueden resolver en tiempo polinómico o mejor. Si P = NP esto es importante porque sabremos que podemos resolver estos problemas de NP en tiempo polinómico. Dado que NP contiene muchos problemas que tienen importancia en la vida real, es un gran problema.