Ho riscritto questa risposta per provare a rispondere ad alcuni commenti su una versione precedente.
Presumo che tu abbia letto la definizione di Wikipedia per completezza NP che in realtà non si concentra sui giochi. Analizzerò un po 'l'esatto significato di completezza NP e teoria del gioco e spiegherò l'essenza di un gioco NP-Complete.
Consideriamo una partita a 2 giocatori con mosse alternate, più restrittivamente si tratta essenzialmente di partite combinatorie . Fondamentalmente un gioco in cui hai un certo numero di mosse che possono essere fatte e devi sceglierne una. Ti piacerebbe giocare "perfettamente", il che significa che non faresti mai una mossa "cattiva". Quindi delle mosse consentite che desideri selezionare la migliore. (Ovviamente il tuo avversario ha lo stesso obiettivo ...)
Nota che il gioco perfetto non significa che vincerai sempre. Le regole del gioco possono essere tali che il primo o il secondo giocatore debbano vincere. Anche alcuni giochi come Tic-Tac-Toe dovrebbero concludersi con un pareggio. Quindi ciò che significa "gioco perfetto" in questa discussione è:
(1) Che non sarai mai in una posizione vincente e poi perderai la partita perché hai fatto una mossa "cattiva"
(2) Non perderai mai l'opportunità di ottenere nella posizione vincente se si presenta tale opportunità.
Dato lo stato attuale del gioco, ciò che desideri è poter utilizzare un "algoritmo efficiente" per calcolare la mossa migliore. D'altra parte notiamo che un algoritmo che deve cercare nell'intero albero di gioco è un "algoritmo inefficiente".
Ora possiamo definire "l'efficienza" un po 'più formalmente. Lo semplificherò un po 'ma l'essenza è corretta. Considera il numero di calcoli, , che devono essere fatti per scegliere la mossa successiva, che uno nella media di ogni mossa ha possibilità (il fattore di ramificazione ) e che nel gioco sono rimaste mosse. L'idea è anche che ogni calcolo richiede lo stesso tempo in modo che lo sforzo possa essere tradotto in complessità temporale , , anziché calcoli grezzi.CBnT
- Un "algoritmo efficiente" avrà: dove è un "intero piccolo", e ah sono alcuni numeri reali. Pertanto, l'algoritmo efficiente viene eseguito in tempi polinomiali poiché si tratta di un'espressione polinomiale.
T∝aBa+bBα−1+cBα−2+...+hB0
α
- Un "algoritmo inefficiente" avrà:
e questo algoritmo viene eseguito in tempo esponenziale (ovvero tempo non polinominale). Il punto qui è che man mano che diventa più grande si ottiene un'esplosione combinatoria.
T∝aBn
n
Ora il punto importante è che è impossibile avere un algoritmo efficiente, il tempo polinomiale, che gioca perfettamente per un gioco che NP-completa. Per giocare perfettamente un problema NP-completo deve, per definizione, essere risolto da un algoritmo inefficiente che viene eseguito in un tempo non polinomiale.
Si noti che il tempo di esecuzione riguarda il numero intrinseco di calcoli, non il tempo di risposta percepito da un essere umano. Per un piccolo gioco come Tic-Tac-Toe il computer potrebbe giocare tutte le possibili mosse future e comunque rispondere rapidamente come percepito da un essere umano.
Per Nim è possibile creare un algoritmo temporale polinomiale. In qualsiasi momento del gioco l'algoritmo può calcolare quale giocatore ha una mossa vincente e quale dovrebbe essere quella mossa.
D'altra parte prendiamo il gioco di Qubic . (Stai cercando di creare una linea di 4 in una griglia 3D. Quindi è essenzialmente tic-tac-toe su una griglia 4x4x4.) Qubic è NP-completo quindi non esiste un algoritmo di tempo polinomiale per calcolare la prossima mossa perfetta. L'unico modo per sapere se al momento hai una mossa vincente è provare tutte le mosse possibili di entrambi i giocatori per verificare che una determinata mossa sia vincente o almeno non perdente.
In verità l'intero albero di gioco di Qubic è abbastanza piccolo da poter essere codificato in un programma per computer che può funzionare perfettamente. Ciò che significa codifica è che l'intero albero di gioco è stato esplorato e tutte le mosse sono state elaborate in anticipo. Pertanto, il programma può essenzialmente effettuare una rapida chiamata al database utilizzando lo stato della scheda corrente e recuperare la mossa migliore per quello stato della scheda senza dover effettuare la ricerca dell'albero ogni volta che si deve effettuare una mossa. Questo è davvero un "trucco" per i nostri scopi qui.
Ora parliamo di scacchi per discutere della funzione di valutazione ignorando alcune delle altre caratteristiche dei programmi di gioco degli scacchi. Gli scacchi sono ancora un gioco irrisolto . Non è noto se il primo o il secondo giocatore debbano vincere. Non è possibile ottenere alcuna posizione sul board e prevedere con certezza chi vincerà. In effetti, gli scacchi hanno un albero di gioco così grande che è impossibile cercare l'intero albero di gioco. Avresti bisogno di computer che non siano solo 10 o 100 volte più veloci ma miliardi di miliardi di volte più veloci di qualsiasi altro computer attuale. (C'è la speranza che il calcolo quantistico possa tagliare questo nodo gordiano.)
Pensa alla funzione di valutazione degli scacchi come a dare a ogni possibile mossa successiva una probabilità di essere la mossa migliore. Quello che fa un programma di scacchi è combinare il futuro con la funzione di valutazione. Pertanto, il programma esamina tutte le possibili mosse future fino a quando non arriva a un punto in cui un punteggio "buono" può essere assegnato alla posizione del tabellone. Il computer valuta tutti i percorsi possibili attraverso l'albero in questo modo e quindi sceglie il percorso con il punteggio migliore. Dal momento che la ricerca non è mai arrivata alla fine del gioco per tutti i percorsi valutati, tutti i programmi di scacchi utilizzano in definitiva una funzione di valutazione imperfetta. (Se sei vicino alla fine del gioco, il computer potrebbe essere in grado di guardare tutte le possibili mosse future.) Ciò significa che potrebbe essere possibile battere il programma anche se il programma avesse una posizione vincente ad un certo punto.