Sé que Knapsack
es NP-completo, mientras que DP puede resolverlo. Dicen que la solución de DP es pseudo-polynomial
, ya que es exponencial en la "longitud de entrada" (es decir, la cantidad de bits necesarios para codificar la entrada). Desafortunadamente no lo entendí. ¿Alguien puede explicarme eso pseudo-polynomial
lentamente?
87
Respuestas:
El tiempo de ejecución es O (NW) para un problema de la mochila ilimitada con N elementos y mochila de tamaño W. W no es polinomio en la longitud de la entrada, sin embargo, que es lo que hace que sea pseudo- -polynomial.
Considere W = 1,000,000,000,000. Solo se necesitan 40 bits para representar este número, por lo que el tamaño de entrada = 40, pero el tiempo de ejecución computacional usa el factor 1,000,000,000,000 que es O (2 40 ).
Por lo tanto, se dice que el tiempo de ejecución es O (N.2 bits en W ), que es exponencial.
Ver también:
fuente
En la mayoría de nuestros problemas, estamos tratando con grandes listas de números que encajan cómodamente dentro de los tipos de datos estándar int / float. Debido a la forma en que la mayoría de los procesadores están construidos para manejar números de 4 a 8 bytes a la vez sin costo adicional (en relación con los números que caben, digamos, 1 byte), rara vez encontramos un cambio en el tiempo de ejecución debido a la ampliación de nuestros números o dentro de los rangos que encontramos en problemas reales, por lo que el factor dominante sigue siendo solo la gran cantidad de puntos de datos, los nom factores a los que estamos acostumbrados.
(Puede imaginar que la notación Big-O esconde un factor constante que divide 32 o 64 bits por dato, dejando solo el número de puntos de datos siempre que cada uno de nuestros números quepa en esa cantidad de bits o menos )
Pero intente volver a trabajar con otros algoritmos para actuar sobre conjuntos de datos que involucren grandes entradas (números que requieren más de 8 bytes para representar) y vea qué le hace eso al tiempo de ejecución. La magnitud de los números involucrados siempre marca la diferencia, incluso en los otros algoritmos como el ordenamiento binario, una vez que se expande más allá del búfer de seguridad que los procesadores convencionales nos brindan "gratis" al manejar lotes de 4 a 8 bytes.
El truco con el algoritmo Knapsack que discutimos es que es inusualmente sensible (en relación con otros algoritmos) a la magnitud de un parámetro en particular, W. Agregue un bit a W y duplica el tiempo de ejecución del algoritmo. No hemos visto ese tipo de respuesta dramática a los cambios de valor en otros algoritmos antes de este, por lo que podría parecer que estamos tratando a Knapsack de manera diferente, pero ese es un análisis genuino de cómo responde de una manera no polinomial. a cambios en el tamaño de entrada.
fuente
El tiempo de ejecución del algoritmo de la mochila está limitado no solo al tamaño de la entrada (n - el número de artículos) sino también a la magnitud de la entrada (W - la capacidad de la mochila) O (nW) que es exponencial en su forma representado en computadora en binario (2 ^ n). La complejidad computacional (es decir, cómo se realiza el procesamiento dentro de una computadora a través de bits) solo se refiere al tamaño de las entradas, no a sus magnitudes / valores .
Ignore la lista de valor / peso por un momento. Digamos que tenemos una instancia con capacidad de mochila 2. W tomaría dos bits en los datos de entrada. Ahora aumentaremos la capacidad de la mochila a 4, manteniendo el resto de la entrada. Nuestra entrada solo ha crecido un poco, pero la complejidad computacional se ha duplicado. Si aumentamos la capacidad a 1024, tendríamos solo 10 bits de la entrada para W en lugar de 2, pero la complejidad se ha incrementado en un factor de 512. La complejidad del tiempo crece exponencialmente en el tamaño de W en representación binaria (o decimal) .
Otro ejemplo simple que me ayudó a comprender el concepto de pseudopolinomio es el algoritmo de prueba de primalidad ingenuo. Para un número dado n, estamos verificando si está dividido uniformemente por cada número entero en el rango 2..√n, por lo que el algoritmo toma √ (n − 1) pasos. Pero aquí, n es la magnitud de la entrada, no su tamaño.
Por el contrario, la búsqueda de una matriz para un elemento dado se ejecuta en tiempo polinómico: O (n). Toma como máximo n pasos y aquí n es el tamaño de la entrada (la longitud de la matriz).
[ mira aquí ]
Calcular los bits necesarios para almacenar el número decimal
fuente
La forma en que entiendo esto es que la capacidad habría sido O (W) si la entrada de capacidad fuera una matriz de [1,2, ..., W] , que tiene un tamaño de W. Pero la entrada de capacidad no es una matriz de números, en cambio es un solo entero. La complejidad del tiempo se trata de la relación con el tamaño de la entrada. El tamaño de un entero NO es el valor del entero, sino el número de bits que lo representan. Más tarde convertimos este entero W en una matriz [1,2, ..., W] en el algoritmo, lo que lleva a la gente a pensar erróneamente que W es el tamaño, pero esta matriz no es la entrada, sino el entero en sí.
Piense en la entrada como "una matriz de cosas" y el tamaño como "cuántas cosas en la matriz". La entrada del elemento es en realidad una matriz de n elementos en la matriz, por lo que size = n. La entrada de capacidad NO es una matriz de números W , sino un único entero , representado por una matriz de log (W) bits. Aumente el tamaño en 1 (agregando 1 bit significativo), W se duplica, por lo que el tiempo de ejecución se duplica, de ahí la complejidad del tiempo exponencial.
fuente