Il problema di determinare se un programma ha "prestazioni di ottimalità" A o "prestazioni di ottimalità" B per quasi tutte le definizioni di "prestazioni di ottimalità" è indecidibile in generale (prova di seguito). Ciò implica che non esiste un singolo metodo in grado di dirti quanto sia ottimale un algoritmo.
Esistono tuttavia metodi che vengono spesso applicati durante l'analisi degli algoritmi di approssimazione. Spesso, gli algoritmi di approssimazione sono valutati dalle loro garanzie su quanto la sua soluzione sia lontana dalla soluzione ottimale. Fornirò un esempio di problema e approssimazione, che dimostrerò usando il metodo "limite inferiore", che è un metodo molto comunemente usato per dimostrare i rapporti.
Il problema in questione è il problema "Caricamento camion": abbiamo molti camion identici (quanti ne vogliamo), ognuno in grado di trasportare un carico che pesa al massimo T. Abbiamo n oggetti che desideriamo caricare in questi camion per trasporto. Ogni oggetto i ha un peso w_i, dove w_i <= T (quindi non ci sono oggetti che non possono stare su un camion nemmeno da soli). Gli articoli non possono essere divisi in parti. Vorremmo riempire i camion in modo da aver bisogno del minor numero possibile di camion. Questo problema è NP-completo.
Esiste un algoritmo di approssimazione molto semplice per questo problema. Iniziamo semplicemente a caricare un camion con gli articoli, fino a quando il camion non è così pieno che l'articolo successivo non si adatta. Quindi prendiamo un altro camion e cariciamo questo camion con questo articolo che non si adattava al camion precedente. Non cariciamo più articoli su questo camion: invece, prendiamo un nuovo camion, lo riempiamo di nuovo con molti articoli fino a quando non si adatta più, rimettiamo l'ultimo articolo sul suo camion e così via.
Questo algoritmo è una cosiddetta approssimazione 2 per il problema: utilizza al massimo il doppio dei camion di cui la soluzione ottimale avrebbe bisogno. Il "al massimo" è fondamentale: potremmo essere fortunati e trovare la soluzione ottimale, ma almeno non faremo troppo male.
Per dimostrarlo, definiamo innanzitutto un limite inferiore per il numero ottimale di camion di cui abbiamo bisogno. Per questo, immagina che ci sia permesso di tagliare gli elementi in parti: potremmo quindi riempire facilmente tutti i camion tranne l'ultimo. Il numero di camion di cui avremmo bisogno se lo facessimo è un limite inferiore per il numero di camion di cui abbiamo bisogno per la domanda originale: nel caso "migliore" la soluzione ottimale riempie sempre ogni camion completamente, nel qual caso il numero di camion è uguale, ma se le soluzioni ottimali lasciano i camion vuoti, possono solo aver bisogno di più camion.
Ora esaminiamo il nostro algoritmo di approssimazione. Si noti che in ogni fase, riempiamo (parzialmente) due camion. Inoltre, notando come funziona l'algoritmo, gli articoli nel primo camion e l'articolo nel secondo camion non possono stare insieme nel primo camion, quindi la loro somma è almeno T. Ciò significa che ad ogni passaggio, cariciamo almeno un intero camion di oggetti su due camion. Ora confrontalo con il nostro limite inferiore: in tal caso, cariciamo un camion pieno di articoli su un camion. In altre parole, il nostro algoritmo di approssimazione calcola (in tempo lineare) una soluzione che assomiglia molto alla nostra "soluzione" con limite inferiore, ma utilizza due camion anziché uno. Quindi, utilizziamo al massimo il doppio di camion rispetto all'algoritmo ottimale, perché utilizziamo al massimo il doppio di camion rispetto al nostro limite inferiore sull'algoritmo ottimale.
Questo algoritmo fornisce un'approssimazione a fattore costante: è al massimo 2 volte peggiore della soluzione ottimale. Alcuni esempi di altre misure: al massimo C in più rispetto alla soluzione ottimale (errore additivo, abbastanza raro), al massimo c log n volte più male della soluzione ottimale, al massimo cn volte più male della soluzione ottimale, al massimo c 2 ^ (dn) volte meno della soluzione ottimale (pessima; ad esempio, TSP generale ammette solo algoritmi con questo tipo di garanzie).
Ovviamente, se vuoi essere sicuro che il fattore che dimostri sia il miglior fattore che puoi provare, dovresti cercare di trovare casi in cui la soluzione fornita dal tuo algoritmo sia davvero pessima.
Si noti inoltre che a volte utilizziamo algoritmi di approssimazione su problemi che non sono NP-difficili.
Ho imparato questo (tra molti altri) nel corso sugli algoritmi di approssimazione della mia università.
Prova di indecidibilità: sia P un problema e A e B siano algoritmi di approssimazione per P dove A e B non hanno la stessa "ottimalità" per una definizione ragionevole di "ottimalità", e dove il tempo di esecuzione di A e B è sia omega (1) (strettamente più lento del tempo costante, cioè diventano più lenti per casi più grandi) e dove A e B si fermano sempre entrambi.
Sia D un programma che afferma di poter calcolare quanto segue: dato un programma C che calcola un'approssimazione per P, decidi se è buono come A o buono come B per input sufficientemente grandi (puoi quindi usarlo per classificare i programmi secondo la loro ottimalità).
Possiamo quindi usare D per risolvere il problema di arresto. Sia E un programma e F un input per questo programma. Useremo D per decidere se E si fermerà sull'ingresso F.
Progettiamo un programma G che procede come segue: dato un input S per il problema P, esegue E su F e A su S in parallelo: esegue E per un po ', poi A, quindi E ancora e così via. Se E si ferma su F, interrompe l'esecuzione di A e invece esegue B su S e restituisce il risultato di B. Se A si ferma prima che E si arresti, restituisce il risultato di A.
L'uso di D su G ora decide se E si ferma su F: se E si ferma su F, quindi per input sufficientemente grandi S, E si ferma su F prima che A si ferma su S (perché il tempo impiegato da E per arrestarsi non dipende dalla dimensione di l'input, a differenza di A). D riporta quindi che G ha le caratteristiche di ottimalità di B. Se E non si ferma su F, D segnalerà che G ha le caratteristiche di ottimalità di A.