Creo que los artículos de Wikipedia
PAGS , N P y PAGS vs. N P son bastante buenos. Todavía aquí está lo que diría: Parte I , Parte II
[Usaré comentarios entre paréntesis para analizar algunos detalles técnicos que puede omitir si lo desea].
Parte 1
Problemas de decisión
Hay varios tipos de problemas computacionales. Sin embargo, en una introducción al curso de teoría de la complejidad computacional, es más fácil enfocarse en el problema de decisión , es decir, problemas en los que la respuesta es SÍ o NO. Existen otros tipos de problemas computacionales, pero la mayoría de las veces las preguntas sobre ellos pueden reducirse a preguntas similares sobre problemas de decisión. Además, los problemas de decisión son muy simples. Por lo tanto, en una introducción al curso de teoría de la complejidad computacional centramos nuestra atención en el estudio de los problemas de decisión.
Podemos identificar un problema de decisión con el subconjunto de entradas que tienen respuesta SÍ. Esto simplifica la notación y nos permite escribir
x ∈ Q en lugar de Q ( x ) = YmiS y
x ∉ Q en lugar de Q ( x ) = NO .
Otra perspectiva es que estamos hablando de consultas de membresía en un conjunto. Aquí hay un ejemplo:
Problema de decisión:
Entrada: Un número natural X ,
Pregunta: ¿Es X un número par?
Problema de membresía:
Entrada: Un número natural X ,
Pregunta: ¿Es X en miv e n = { 0 , 2 , 4 , 6 , ⋯ } ?
Nos referimos a la respuesta SÍ en una entrada como aceptar la entrada y a la respuesta NO en una entrada como rechazar la entrada.
Analizaremos los algoritmos para problemas de decisión y discutiremos qué tan eficientes son esos algoritmos en el uso de recursos computables . Confiaré en su intuición desde la programación en un lenguaje como C en lugar de definir formalmente lo que queremos decir con un algoritmo y recursos computacionales.
[Observaciones: 1. Si quisiéramos hacer todo de manera formal y precisa, necesitaríamos arreglar un modelo de cómputo como el modelo estándar de máquina de Turing para definir con precisión lo que queremos decir con un algoritmo y su uso de recursos computacionales. 2. Si queremos hablar sobre el cálculo sobre objetos que el modelo no puede manejar directamente, necesitaríamos codificarlos como objetos que el modelo de máquina puede manejar, por ejemplo, si estamos usando máquinas de Turing, necesitamos codificar objetos como números naturales y gráficos como cadenas binarias.]
PAGS = Problemas con algoritmos eficientes paraencontrarsoluciones
Suponga que algoritmos eficientes significa algoritmos que utilizan como máximo una cantidad polinómica de recursos computacionales. El principal recurso que nos interesa es el peor tiempo de ejecución de los algoritmos con respecto al tamaño de entrada, es decir, el número de pasos básicos que un algoritmo realiza en una entrada de tamaño norte . El tamaño de una entrada X es norte si se necesitan norte bits de memoria de la computadora para almacenar X , en cuyo caso escribimos El | x | =n . Entonces, por algoritmos eficientes, nos referimos a algoritmos que tienen un tiempo de ejecución polinómico en el peor de los casos .
La suposición de que los algoritmos de tiempo polinómico capturan la noción intuitiva de algoritmos eficientes se conoce como tesis de Cobham . No discutiré en este punto si PAGS es el modelo correcto para problemas que se pueden resolver de manera eficiente y si PAGS captura o no lo que se puede calcular de manera eficiente en la práctica y cuestiones relacionadas. Por ahora hay buenas razones para hacer esta suposición, por lo que para nuestro propósito asumimos que este es el caso. Si no acepta la tesis de Cobham, no hace incorrecto lo que escribo a continuación, lo único que perderemos es la intuición sobre la computación eficiente en la práctica. Creo que es una suposición útil para alguien que está comenzando a aprender sobre la teoría de la complejidad.
PAGS es la clase de problemas de decisión que se pueden resolver de manera eficiente,
es decir, problemas de decisión que tienen algoritmos de tiempo polinómico.
Más formalmente, decimos que un problema de decisión Q está en P iff
hay un algoritmo eficiente A tal que
para todas las entradas x ,
- si Q(x)=YES entonces A(x)=YES ,
- si Q(x)=NO entonces A(x)=NO .
Simplemente puedo escribir A(x)=Q(x) , pero lo escribo de esta manera para que podamos compararla con la definición de NP .
NP = Problemas con algoritmos eficientes paraverificarpruebas / certificados / testigos
A veces no conocemos ninguna forma eficiente de encontrar la respuesta a un problema de decisión, sin embargo, si alguien nos dice la respuesta y nos da una prueba
, podemos verificar de manera eficiente que la respuesta es correcta al verificar la prueba para ver si es una prueba válida. . Esta es la idea detrás de la clase de complejidad NP .
Si la prueba es demasiado larga, no es realmente útil, puede tomar demasiado tiempo leer la prueba y mucho menos verificar si es válida. ¡Queremos que el tiempo requerido para la verificación sea razonable en el tamaño de la entrada original, no en el tamaño de la prueba dada! Esto significa que lo que realmente queremos no son pruebas largas arbitrarias sino pruebas cortas . Tenga en cuenta que si el tiempo de ejecución del verificador es polinómico en el tamaño de la entrada original, solo puede leer una parte polinómica de la prueba. Entonces, por corto, nos referimos al tamaño polinómico .
Formule este punto cuando use la palabra "prueba", quiero decir "prueba corta".
Aquí hay un ejemplo de un problema que no sabemos cómo resolver de manera eficiente, pero podemos verificar las pruebas de manera eficiente:
Partición de
entrada: un conjunto finito de números naturales S ,
Pregunta: ¿ es posible dividir S en dos conjuntos A y B
( A∪B=S y A∩B=∅ ) de
modo que la suma de los números en A sea igual a la suma del número en B ( ∑x∈Ax=∑x∈Bx )?
Si le doy S y le pregunto si podemos dividirlo en dos conjuntos para que sus sumas sean iguales, no conoce ningún algoritmo eficiente para resolverlo. Probablemente intente todas las formas posibles de dividir los números en dos conjuntos hasta que encuentre una partición donde las sumas sean iguales o hasta que haya probado todas las particiones posibles y ninguna haya funcionado. Si alguno de ellos funcionara, diría SÍ, de lo contrario, diría NO.
Pero hay exponencialmente muchas particiones posibles, por lo que tomará mucho tiempo. Sin embargo, si te doy dos conjuntos A y B , se puede comprobar fácilmente si las sumas son iguales y si A y B es una partición de S . Tenga en cuenta que podemos calcular sumas de manera eficiente.
Aquí el par de A y B que le doy es una prueba de una respuesta SÍ. Puede verificar eficientemente mi reclamo mirando mi comprobante y verificando si es un comprobante válido . Si la respuesta es SÍ, entonces hay una prueba válida, y puedo dársela y usted puede verificarla de manera eficiente. Si la respuesta es NO, entonces no hay prueba válida. Entonces, lo que sea que le dé, puede verificarlo y ver que no es una prueba válida. No puedo engañarte con una prueba no válida de que la respuesta es SÍ. Recuerde que si la prueba es demasiado grande, llevará mucho tiempo verificarla, no queremos que esto suceda, por lo que solo nos preocupamos por las pruebas eficientes , es decir, las pruebas que tienen un tamaño polinómico.
A veces las personas usan " certificado " o " testigo " en lugar de "prueba".
Tenga en cuenta que le estoy dando suficiente información sobre la respuesta para una entrada dada x
para que pueda encontrar y verificar la respuesta de manera eficiente. Por ejemplo, en nuestro ejemplo de partición, no le digo la respuesta, solo le doy una partición y puede verificar si es válida o no. Tenga en cuenta que debe verificar la respuesta usted mismo, no puede confiar en mí acerca de lo que digo. Además, solo puede verificar la exactitud de mi prueba. Si mi prueba es válida, significa que la respuesta es SÍ. Pero si mi prueba no es válida, no significa que la respuesta sea NO. Ha visto que una prueba no era válida, no que no haya pruebas válidas. Estamos hablando de pruebas de SÍ. No estamos hablando de pruebas de NO.
Veamos un ejemplo:
A={2,4} y B={1,5} es una prueba de que
S={1,2,4,5} se puede dividir en dos conjuntos con sumas iguales. Sólo tenemos que resumir los números en A y los números en B y ver si los resultados son iguales, y comprobar si A , B es la partición de S .
Si le di A={2,5} y B={1,4} , verificará y verá que mi prueba no es válida. No significa que la respuesta sea NO, solo significa que esta prueba en particular no era válida. Su tarea aquí no es encontrar la respuesta, sino solo verificar si la prueba que se le da es válida.
Es como un estudiante resolviendo una pregunta en un examen y un profesor verificando si la respuesta es correcta. :) (desafortunadamente a menudo los estudiantes no dan suficiente información para verificar la exactitud de su respuesta y los profesores tienen que adivinar el resto de su respuesta parcial y decidir cuánta calificación deberían dar a los estudiantes por sus respuestas parciales, de hecho, es bastante difícil tarea).
Lo sorprendente es que la misma situación se aplica a muchos otros problemas naturales que queremos resolver:
podemos verificar eficientemente si una prueba corta es válida, pero no conocemos ninguna forma eficiente de encontrar la respuesta . Esta es la motivación por la cual la clase de complejidad NP es extremadamente interesante
(aunque esta no fue la motivación original para definirla). Independientemente de lo que haga (no solo en CS, sino también en matemáticas, biología, física, química, economía, administración, sociología, negocios, ...) enfrentará problemas de computación que se incluyen en esta clase. Para tener una idea de cuántos problemas resultan en NP consulte
Un compendio de problemas de optimización de NP . En efecto tendrá dificultades para encontrar problemas naturales que no están en NP . Es simplemente asombroso.
NP es la clase de problemas que tienen verificadores eficientes, es decir,
hay un algoritmo de tiempo polinómico que puede verificar si una solución dada es correcta.
Más formalmente, decimos que un problema de decisión Q está en NP iff
hay un algoritmo eficiente V llamado verificador de modo que
para todas las entradas x ,
- si Q(x)=YES entonces hay una prueba y tal que V(x,y)=YES ,
- si Q(x)=NO entonces para todas las pruebas y , V(x,y)=NO .
Decimos que un verificador es el sonido
si no se hace la prueba cuando la respuesta es NO. En otras palabras, un verificador de sonido no puede ser engañado para aceptar una prueba si la respuesta es realmente NO. No hay falsos positivos.
Del mismo modo, decimos que un verificador está completo
si acepta al menos una prueba cuando la respuesta es SÍ. En otras palabras, un verificador completo puede estar convencido de que la respuesta es SÍ.
La terminología proviene de la lógica y los sistemas de prueba . No podemos usar un sistema de prueba de sonido para probar declaraciones falsas. Podemos usar un sistema de prueba completo para probar todas las declaraciones verdaderas.
El verificador V obtiene dos entradas,
- x : la entrada original paraQ , y
- y : a prueba sugerido paraQ(x)=YES .
Tenga en cuenta que queremos que V sea eficiente en el tamaño de x . Si y es una gran prueba, el verificador podrá leer solo una parte polinómica de y . Es por eso que exigimos que las pruebas sean cortas. Si y es corto, decir que V es eficiente en x
es lo mismo que decir que V es eficiente en x e y
(porque el tamaño de y está limitado por un polinomio fijo en el tamaño de x ).
En resumen, para mostrar que un problema de decisión Q está en NP
, tenemos que dar un algoritmo verificador eficiente que sea sólido y completo .
Nota histórica: históricamente, esta no es la definición original de NP . La definición original utiliza lo que se llama máquinas de Turing no deterministas . Estas máquinas no corresponden a ningún modelo de máquina real y es difícil acostumbrarse a ellas (al menos cuando comienza a aprender sobre la teoría de la complejidad). He leído que muchos expertos piensan que habrían usado la definición del verificador como la definición principal e incluso habrían nombrado la clase VP
(verificable en tiempo polinómico) en lugar de NP
si se remontan a los albores de la teoría de la complejidad computacional. La definición verificador es más natural, más fácil de entender conceptualmente, y más fácil de usar para mostrar problemas son en NP .
P⊆NP
Por lo tanto, tenemos
P = eficiente solucionable y NP = eficientemente verificable . Entonces P=NP si los problemas que pueden verificarse eficientemente son los mismos que los problemas que pueden resolverse eficientemente.
Tenga en cuenta que cualquier problema en P también está en NP , es decir, si puede resolver el problema, también puede verificar si una prueba dada es correcta: ¡el verificador simplemente ignorará la prueba!
Eso es porque no lo necesitamos, el verificador puede calcular la respuesta por sí mismo, puede decidir si la respuesta es SÍ o NO sin ninguna ayuda. Si la respuesta es NO, sabemos que no debería haber pruebas y nuestro verificador simplemente rechazará todas las pruebas sugeridas. Si la respuesta es SÍ, debería haber una prueba y, de hecho, aceptaremos cualquier cosa como prueba.
[Podríamos haber hecho que nuestro verificador acepte solo algunos de ellos, eso también está bien, siempre que nuestro verificador acepte al menos una prueba de que el verificador funciona correctamente para el problema.]
Aquí hay un ejemplo:
n+1a1,⋯,ans
Σni=1ai=s
Ps
NPVP
NPPP⊆NP
NPNP⊆ExpTime
NPNP
En nuestro ejemplo de partición, probamos todas las particiones posibles y verificamos si las sumas son iguales en alguna de ellas.
m2m
NPNP⊆ExpTimeNP⊆PSpace
NPPNPNP
NP=PNP
NPNP
NPNPNPP⊆NP
NPNP
Los límites inferiores parecen difíciles de demostrar
NP
Lamentablemente, la tarea de probar los límites inferiores es muy difícil. ¡ Ni siquiera podemos probar que estos problemas requieran más que tiempo lineal ! Sin mencionar que requiere tiempo exponencial.
Probar límites inferiores de tiempo lineal es bastante fácil: el algoritmo necesita leer la entrada después de todo. Probar límites inferiores superlineales es una historia completamente diferente. Podemos probar límites inferiores superlineales con más restricciones sobre el tipo de algoritmos que estamos considerando, por ejemplo, ordenar algoritmos mediante comparación, pero no conocemos límites inferiores sin esas restricciones.
Para demostrar un límite superior para un problema, solo necesitamos diseñar un algoritmo suficientemente bueno. A menudo se necesita conocimiento, pensamiento creativo e incluso ingenio para crear dicho algoritmo.
Sin embargo, la tarea es considerablemente más simple en comparación con probar un límite inferior. Tenemos que demostrar que no hay buenos algoritmos . No es que no conozcamos ningún algoritmo lo suficientemente bueno en este momento, sino que no existe ningún algoritmo bueno , que a nadie se le ocurra un buen algoritmo . Piénselo por un minuto si no lo ha hecho antes, ¿cómo podemos mostrar un resultado tan imposible ?
1=0
Para demostrar un límite inferior, es decir, para demostrar que un problema requiere una cierta cantidad de tiempo para resolver, significa que tenemos para demostrar que cualquierNPproblemas, por ejemplo, codiciosos y sus extensiones no pueden funcionar, y hay algunos trabajos relacionados con algoritmos de programación dinámica, y hay algunos trabajos sobre formas particulares de usar la programación lineal. Pero estos ni siquiera están cerca de descartar las ideas inteligentes que conocemos (si está interesado, busque límites más bajos en modelos restringidos de cómputo).
Barreras: los límites más bajos son difíciles de probar
Por otro lado, tenemos resultados matemáticos llamados
barreras
que dicen que una prueba de límite inferior no puede ser tal y tal, ¡y tal y tal cubre casi todas las técnicas que hemos utilizado para probar los límites inferiores! De hecho, muchos investigadores dejaron de trabajar para probar los límites inferiores después del resultado de la barrera de pruebas naturales de Alexander Razbarov y Steven Rudich
. Resulta que la existencia de un tipo particular de pruebas de límite inferior implicaría la inseguridad de los generadores de números pseudoaleatorios criptográficos y muchas otras herramientas criptográficas.
Digo casi porque en los últimos años ha habido algunos avances, principalmente por parte de Ryan Williams,
que ha sido capaz de sortear de manera inteligente los resultados de la barrera, aún así los resultados hasta ahora son para modelos de computación muy débiles y bastante lejos de descartar algoritmos generales de tiempo polinómico .
NP
[Por otro lado, el trabajo de Ryan Williams muestra que hay conexiones cercanas entre probar los límites inferiores y probar los límites superiores. Vea su charla en ICM 2014 si está interesado.]
Reducciones: Resolver un problema utilizando otro problema como subrutina / Oracle / Black Box
La idea de una reducción es muy simple: para resolver un problema, use un algoritmo para otro problema.
nSumSum
Problema:
nx1,…,xn
∑ni=1xi
Algoritmo de reducción:
- s=0
- i1n
s=Sum(s,xi)
- s
SumSumSumSum
Esto es esencialmente lo que es una reducción: suponga que tenemos un algoritmo para un problema y úselo como un oráculo para resolver otro problema. Aquí eficiente significa eficiente asumiendo que el oráculo responde en una unidad de tiempo, es decir, contamos cada ejecución del oráculo en un solo paso.
Si el oráculo devuelve una respuesta grande, debemos leerla y eso puede llevar algún tiempo, por lo que debemos contar el tiempo que nos lleva leer la respuesta que nos ha dado el oráculo. Del mismo modo para escribir / hacer la pregunta del oráculo. Pero el oráculo funciona instantáneamente, es decir, tan pronto como hacemos la pregunta del oráculo, el oráculo escribe la respuesta para nosotros en una sola unidad de tiempo. Todo el trabajo que realiza Oracle cuenta un solo paso, pero esto excluye el tiempo que nos lleva escribir la pregunta y leer la respuesta.
Debido a que no nos importa cómo funciona Oracle, sino solo por las respuestas que devuelve, podemos hacer una simplificación y considerar que el Oracle es el problema en lugar de un algoritmo para ello. En otras palabras, no nos importa si el oráculo no es un algoritmo, no nos importa cómo surgen los oráculos con sus respuestas.
Sum
Podemos hacer múltiples preguntas desde un oráculo, y las preguntas no necesitan ser predeterminadas: podemos hacer una pregunta y, en base a la respuesta que devuelve el oráculo, realizamos algunos cálculos por nosotros mismos y luego hacemos otra pregunta basada en la respuesta que obtuvimos. La pregunta anterior.
Otra forma de ver esto es pensarlo como un cálculo interactivo . El cálculo interactivo en sí mismo es un gran tema, por lo que no voy a entrar aquí, pero creo que mencionar esta perspectiva de reducciones puede ser útil.
AOAO
La reducción que discutimos anteriormente es la forma más general de reducción y se conoce como reducción de caja negra
(también conocida como reducción de oráculo , reducción de Turing ).
Más formalmente:
QOQ≤TO
Ax
Q(x)=AO(x)
AOQ
AQ≤PTOT
Sin embargo, es posible que deseemos poner algunas restricciones en la forma en que el algoritmo de reducción interactúa con el oráculo. Hay varias restricciones que se estudian, pero la restricción más útil es la llamada reducciones de muchos
(también conocida como reducciones de mapeo ).
xy
Más formalmente,
QOQ≤mO
Ax
Q(x)=O(A(x))
Q≤PmO
NPANPBANP
PNPNP
La publicación se ha vuelto demasiado larga y supera el límite de una respuesta (30000 caracteres). Continuaré la respuesta en la Parte II .