Perché il problema dello zaino è pseudo-polinomiale?


89

So che Knapsackè NP-completo mentre può essere risolto da DP. Dicono che la soluzione DP è pseudo-polynomial, poiché è esponenziale nella "lunghezza di ingresso" (cioè il numero di bit necessari per codificare l'ingresso). Purtroppo non ho capito. Qualcuno può spiegarmi quella pseudo-polynomialcosa lentamente?


Risposte:


92

Il tempo di esecuzione è O (NW) per un problema di zaino illimitato con N elementi e zaino di taglia W. W non è polinomiale nella lunghezza dell'input, il che è ciò che lo rende pseudo polinomiale.

Considera W = 1.000.000.000.000. Sono necessari solo 40 bit per rappresentare questo numero, quindi la dimensione dell'input = 40, ma il runtime computazionale utilizza il fattore 1.000.000.000.000 che è O (2 40 ).

Quindi il tempo di esecuzione è più precisamente detto O (N.2 bit in W ), che è esponenziale.

Vedi anche:


1
Il collegamento # 3 che fa riferimento a "Complessità della programmazione dinamica per il problema dello zaino 0-1" è morto.
dev_nut

1
Scusa, non ho capito. Diciamo che se abbiamo un algoritmo con complessità temporale O (N), allora abbiamo O (2 ^ (bit in N)), che è esponenziale? Grazie ~
Lusha Li

3
@LushaLi Questo mi ha aiutato: youtube.com/watch?v=9oI7fg-MIpE . Se N è un array in cui ogni elemento ha un input di dimensione massima fissa (diciamo che ogni elemento dell'array non è più di 32 bit), e esegui un ciclo for su questo array una volta, allora è un algoritmo temporale polinomiale nell'input dimensione N dell'array. Tuttavia, se N è un numero intero e si esegue un ciclo su N, N è illimitato e cresce in modo esponenziale nel numero di bit necessari per rappresentarlo. Quindi un semplice ciclo for su N è, in realtà, esponenziale. Notare che nel caso dell'array, la dimensione di ogni elemento dell'array era delimitata in alto.
max_max_mir

Non ero convinto. Esistono molti algoritmi con le stesse proprietà che non sono "pseudo-polinomiali". Dimmi, qual è la complessità del Setaccio di Eratostene (o di qualsiasi altro cercatore di numeri primi)?
Ofir A.

31

Nella maggior parte dei nostri problemi, abbiamo a che fare con grandi elenchi di numeri che si adattano comodamente ai tipi di dati int / float standard. A causa del modo in cui la maggior parte dei processori è costruita per gestire numeri di 4-8 byte alla volta senza costi aggiuntivi (rispetto ai numeri che rientrano, diciamo, 1 byte), raramente riscontriamo un cambiamento nel tempo di esecuzione dal ridimensionamento dei nostri numeri o all'interno di intervalli che incontriamo nei problemi reali, quindi il fattore dominante rimane solo l'enorme quantità di punti dati, i fattori n o m a cui siamo abituati.

(Puoi immaginare che la notazione Big-O nasconda un fattore costante che divide 32 o 64 bit per dato, lasciando solo il numero di punti dati ogni volta che ciascuno dei nostri numeri rientra in quel numero di bit o meno )

Ma prova a rielaborare con altri algoritmi per agire su set di dati che coinvolgono big int - numeri che richiedono più di 8 byte per essere rappresentati - e guarda cosa fa per il runtime. La grandezza dei numeri coinvolti fa sempre la differenza, anche in altri algoritmi come l'ordinamento binario, una volta che ci si espande oltre il buffer di sicurezza che i processori convenzionali ci danno "gratuitamente" gestendo batch da 4-8 byte.

Il trucco con l'algoritmo Knapsack di cui abbiamo discusso è che è insolitamente sensibile (rispetto ad altri algoritmi) all'ampiezza di un particolare parametro, W. Aggiungi un bit a W e raddoppi il tempo di esecuzione dell'algoritmo. Non abbiamo visto quel tipo di risposta drammatica ai cambiamenti di valore in altri algoritmi prima di questo, motivo per cui potrebbe sembrare che stiamo trattando Knapsack in modo diverso, ma questa è un'analisi genuina di come risponde in modo non polinomiale ai cambiamenti nella dimensione di input.


8

Il tempo di esecuzione dell'algoritmo dello zaino è legato non solo alla dimensione dell'input (n - il numero di elementi) ma anche alla grandezza dell'input (W - la capacità dello zaino) O (nW) che è esponenziale per come è rappresentato in computer in binario (2 ^ n). La complessità computazionale (cioè come l'elaborazione viene eseguita all'interno di un computer attraverso i bit) riguarda solo la dimensione degli ingressi, non le loro grandezze / valori .

Ignorare l'elenco dei valori / pesi per un momento. Supponiamo di avere un'istanza con capacità a zaino 2. W prenderebbe due bit nei dati di input. Ora aumenteremo la capacità dello zaino a 4, mantenendo il resto dell'input. Il nostro input è cresciuto solo di un bit, ma la complessità computazionale è aumentata di due volte. Se aumentiamo la capacità a 1024, avremmo solo 10 bit di input per W invece di 2, ma la complessità è aumentata di un fattore di 512. La complessità temporale cresce esponenzialmente nella dimensione di W nella rappresentazione binaria (o decimale) .

Un altro semplice esempio che mi ha aiutato a capire il concetto di pseudo-polinomio è l'ingenuo algoritmo di verifica della primalità. Per un dato numero n stiamo controllando se è diviso equamente per ogni numero intero nell'intervallo 2..√n, quindi l'algoritmo esegue √ (n − 1) passi. Ma qui, n è l'ampiezza dell'input, non la sua dimensione.

                     Now The regular O(n) case

Al contrario, la ricerca in un array per un dato elemento viene eseguita in tempo polinomiale: O (n). Ci vogliono al massimo n passi e qui n è la dimensione dell'input (la lunghezza dell'array).

[ Vedere qui ]

Calcolo dei bit necessari per memorizzare il numero decimale


3
Quindi, per il tuo ultimo esempio di ricerca, perché non considerare anche n come binario? se n = 1024, richiede anche solo 10 bit, quindi non dovrebbe essere pseudo-polinomiale?
user1024

7

Il modo in cui capisco questo è che la capacità sarebbe stata O (W) se l'input di capacità fosse un array di [1,2, ..., W] , che ha una dimensione di W. Ma l'input di capacità non lo è un array di numeri, è invece un singolo intero. La complessità temporale riguarda la relazione con la dimensione dell'input. La dimensione di un numero intero NON è il valore dell'intero, ma il numero di bit che lo rappresentano. Successivamente convertiamo questo intero W in un array [1,2, ..., W] nell'algoritmo, portando le persone a pensare erroneamente che W sia la dimensione, ma questo array non è l'input, lo è l'intero stesso.

Pensa all'input come "un array di cose" e alla dimensione come "quante cose nell'array". L'input dell'elemento è in realtà un array di n elementi nell'array, quindi size = n. L'input di capacità NON è un array di numeri W al suo interno, ma un singolo intero , rappresentato da un array di bit log (W). Aumentarne la dimensione di 1 (aggiungendo 1 bit significativo), W raddoppia così il tempo di esecuzione raddoppia, da qui la complessità temporale esponenziale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.