Tempo pseudopolinomiale

In teoria della complessità computazionale, un algoritmo è detto pseudopolinomiale se la sua complessità temporale è polinomiale nel valore numerico del suo input e non necessariamente nella sua dimensione (ovvero il numero di bits necessari per la sua codifica).

Se si vuole rappresentare un intero W {\displaystyle W} in una base b 2 {\displaystyle b\geq 2} sono necessari almeno log b W {\displaystyle \lceil \log _{b}{W}\rceil } bits. Perciò in genere il valore W {\displaystyle W} è esponenziale nella sua grandezza.

Un problema NP-completo per il quale si conosce un algoritmo pseudopolinomiale che lo risolve è anche detto weakly NP-completo. È invece detto strongly NP-completo un problema NP-completo per il quale è dimostrato la non esistenza di un algoritmo pseudopolinomiale che lo risolve, a meno che P=NP.

Esempi

Test di primalità

Consideriamo il problema del verificare se un numero n {\displaystyle n} è primo. Un approccio banale è quello di verificare se i numeri nell'insieme { 2 , 3 , , n } {\displaystyle \{2,3,\dots ,{\sqrt {n}}\}} dividono n {\displaystyle n} (con resto 0). Questo approccio richiede n 1 {\displaystyle {\sqrt {n}}-1} operazioni di divisione, ovvero un numero sublineare nel valore di n {\displaystyle n} ma non nella sua dimensione. Infatti, rappresentando n {\displaystyle n} con log n {\displaystyle \log {n}} bits avremo che il tempo di esecuzione dell'algoritmo (in funzione della grandezza dell'istanza in input) sarà O ( 2 n ) {\displaystyle O(2^{\sqrt {n}})} .

Per esempio, se si volesse verificare con questo approccio la primalità di un numero n {\displaystyle n} leggermente più piccolo di 10 10 {\displaystyle 10^{10}} servirebbero fino a 10 5 {\displaystyle 10^{5}} operazioni (nel caso peggiore), nonostante per rappresentare n {\displaystyle n} servano solamente 32 {\displaystyle 32} bits (all'incirca).

Inoltre è facile creare un'istanza per la quale questo approccio non è affatto ragionevole: per esempio fissando un numero a 1024-bit.

Per fortuna, nel 2002 è stato scoperto un algoritmo che verifica la primalità di un numero in tempo O ( log 6 n ) {\displaystyle O(\log ^{6}{n})} [1].

Knapsack problem

Il Knapsack problem (noto in italiano come problema dello zaino o problema della bisaccia) è un problema di ottimizzazione combinatoria definito come segue:

è dato uno zaino che può sopportare un peso massimo pari a una valore numerico W {\displaystyle W} . Abbiamo a disposizione n {\displaystyle n} items, ognuno dei quali avente un peso w i {\displaystyle w_{i}} e un valore v i {\displaystyle v_{i}} . L'obiettivo è quello di scegliere un sottoinsieme di oggetti da portare nello zaino in modo che il loro peso sia sostenibile, e tale che massimizzi il valore trasportato.

Una soluzione ammissibile può essere rappresentata da un vettore n {\displaystyle n} -dimensionale x _ = ( x 1 , . . . , x n ) {\displaystyle {\underline {x}}=(x_{1},...,x_{n})} composto dai soli valori 0 e 1, tale che x i = 1 {\displaystyle x_{i}=1} se l'oggetto i {\displaystyle i} -esimo verrà portato nello zaino, 0 {\displaystyle 0} altrimenti.

Più formalmente, i vincoli del problema sono:

  • maximize i = 1 n v i x i {\displaystyle \sum _{i=1}^{n}v_{i}x_{i}}
  • subject to i = 1 n w i x i W {\displaystyle \sum _{i=1}^{n}w_{i}x_{i}\leq W}

È noto che risolvere questo problema è NP-hard, perciò è impossibile trovare un algoritmo polinomiale a meno che P=NP. Esiste però un algoritmo di programmazione dinamica che risolve il problema in tempo O ( n W ) {\displaystyle O(nW)} . Dato che W {\displaystyle W} è un valore dato come parametro in input, esso verrà rappresentato con non meno di log W {\displaystyle \log {W}} bits. Perciò tale algoritmo computa effettivamente in tempo esponenziale rispetto alla dimensione dell'input.

Note

  1. ^ (EN) L'articolo originale (PDF), su cse.iitk.ac.in.
  Portale Matematica: accedi alle voci di Wikipedia che trattano di Matematica