[Musica] [Musica] [Musica] Ok. Eh, oggi continuiamo con Space Complexity che abbiamo iniziato ieri. Vediamo un altro po' di classi, poi chiudiamo su questo. Settimana prossima faremo macchine con oracoli, functional problems e chiudiamo. Poi facciamo il mock exam l'ultimo giorno. Ok. Ah, alright. Ok. Quindi, che abbiamo fatto ieri? Ieri abbiamo introdotto questo concetto di space complexity, spaceed complexity classes e abbiamo definito dispace, nespace e così via. Dopodiché ci siamo focalizzati su long space, non deterministic long space. Abbiamo visto un paio di eh abbiamo visto un paio di problemi. Questo prende [Musica] Abbiamo visto un paio di problemi. Ehm l'ultimo che abbiamo visto è Richability. abbiamo visto essere non deterministic log space completo e siccome c'è quel risultato che abbiamo solamente accennato, non abbiamo dimostrato, ma la dimostrazione non è molto differente da quella similare su P versus NP, abbiamo che se o è un qualsiasi problema non deterministic log space completo fosse il log space deterministico, allora L sarebbe uguale ML. Ok? Quindi per questa ragione noi non riteniamo che ritability sia in L, cioè non riteniamo che sia possibile decidere ritability in spazio logaritmico deterministico. Ok? Però quello che vedremo ora è un risultato interessante riguardo la complessità di Richanisce fornirà il un passo intermedio per il teorema di Sadic che vediamo vediamo più tardi. Ok? Allora, sebbene noi non siamo in grado di dimostrare che richility appartenga a L, che vi ricordo L è D space di log n. Quello che siamo però in grado di dimostrare è che rich ability appartiene a dispace log square n. Ok? Log square intendo che è questa cosa qua, eh? log n quad. Quello è polilogaritmico, quindi noi siamo in grado di dimostrare che utility sta là dentro. L'algoritmo che dobbiamo tirar fuori è un algoritmo un po' trucchiettoso, e ci permette di, appunto, dimostrare questa cosa qua. Adesso noi vediamo com'è possibile collocare abbild square log squared. Ehm, e questo qua poi sarà in realtà un pezzo di una costruzione che ci serve per dimostrare poi un risultato abbastanza generale sulle classi di complessità spaziali. Ok, allora focalizziamoci su un esempio. [Musica] Ok. 1 2 3 4 e 5. Supponiamo che vogliamo andare da S a T. Ok? Quindi abbiamo un'istanza di ricability in cui c'è quel grafo orientato. Il nodo sorgente è il nodo due, il nodo destinazione è il nodo numero 5. Ok? Questa qui è un'istanza sì o un'istanza no? Del problema? È un'istanza sì. Ok? perché ci sta un ci sta un un pass e in particolare avremo che S poi andiamo sul nodo 1, poi andiamo sul nodo 4, sul nodo 3 e poi andiamo su T. Ok? Questo è il path all'interno di questo di questo grafo. Allora, il trucco per riuscire a risolverlo in spazio log square log square n praticamente fare una ricerca binaria, fare una specie di ricerca binaria. Questo è il trucco per riuscire a ottenere questo risultato. E allora è sostanzialmente questo. L'osservazione che facciamo è se esiste un pat per andare da S a t, allora deve esistere un nodo intermedio, tipo il 4 in questo esempio e ci deve stare un path che va da s a 4 e da 4 a t. Ok? Quindi la questione è che noi sostanzialmente possiamo andare a da un lato potremmo gessarlo questo modo intermedio, però visto che siamo in un dominio di spazio invitato, potremmo provare a usare lo spazio e riusarlo, no? Ci proviamo tutti questi U, tanto noi li scriviamo là in mezzo, li riscriviamo sempre e quindi non stiamo abbessando, li proviamo e manteniamo l'utilizzo dello spazio. Ok? Quindi l'idea sostanzialmente è questa. Se io voglio sapere se ci sta un puff dal nodo S al nodo T, allora io basto che basta che io verifichi l'esistenza di un nodo a metà strada che possiamo chiamare U e poi verificare che ci sia un percorso da S verso U e poi da U verso S. Ok? Quindi questo approccio è di tipo ricorsivo, quindi noi ci inventiamo un algoritmo ricorsivo che sfrutta esattamente questo principio. Se io voglio andare da S a tono tre casi, sostanzialmente, due casi base, abbastanza facile e un caso dove applichiamo la ricorsione. casi base sono s = t e allora rispondiamo di sì. L'altro caso è tcessivo di S e allora rispondiamo sì. Se invece questo non accade, allora proviamo sostanzialmente tutti le U per vedere se ci sta un puff da s a U che da U verso t. Ok? Questo è intuitivamente la l'approccio che utilizzeremo per risolvere questo problema. Spazio C. Sì. Allora, definiamo questo algoritmo che chiamiamo exists pat che prende quattro argomenti G, S, T e K. E questo algoritmo risponde vero? Se in G es un percorso da S a t di lunghezza al + K. Ok? Quindi questo è quello che noi facciamo in questo vogliamo risolvere con questo algoritmo. Ok? Son quattro parametri GSTK. È vero, no? che esiste un puff da S a T dentro G di lunghezza K. Poi ovviamente se noi chiamiamo exists puff Gst T e o A qu sono gli archi, allora ovviamente questo algoritmo risolverebbe il problema della rechability, ok? Se noi gli diamo come vincolo di numero di nodi tutti i nodi disponibili sul grafico, ok? Allora, dobbiamo semplicemente trascrivere quello che ci siamo detti prima. Quindi caso uno, primo caso base, se K è allora se S è T accettiamo, altrimenti rifiutiamo. Ok. [Musica] Altro caso, se K è esattamente 1, allora se ST appartiene all'insieme degli archi, qui abbiamo che G è la coppia VA, dove V sono i vertici e A sono gli archi. Se ST è un arco in G, allora accettiamo, altrimenti rifiutiamo. Ok, finora ci siamo occupati dei casi base della ricorsione. Manca l'ultimo pezzo, il verificare l'esistenza di questo U intermedio. Allora, facciamo così. for each you from the if e qui facciamo le chiamate ricorsive if exists puff dove in g da s a u con al più k mezzi nodi and exists path from G eh no, from U to T con al più KZ nodi. Allora, accettiamo. Se nessuna di questa cosa funziona, rifiutiamo. Vedete tutto l'algoritmo? Yes. Qua c'entra tutto. Ok. Allora, di nuovo questo algoritmo che fa? Se noi abbiamo K0 verifichiamo che sorgente e destinazione siano lo stesso. Se sì accettiamo, senò rifiutiamo. Se possiamo fare al più un salto verifichiamo che T sia un successivo di Ss. Se questo è il caso accettiamo, senò lo rifiutiamo. Se non siamo in nessuno di questi due casi, quindi k è più grosso, noi verifichiamo l'esistenza di un nodo intermedio e lo facciamo con un for. Eh, quindi non lo stiamo li stiamo provando tutti. Facciamo delle chiamate ricorsive e ci chiediamo, ma è vero che esiste un percorso da S a U di lunghezza al + k/2 e un percorso da U verso t di lunghezza al + k/2? Se sì accettiamo. Se per nessuna di queste U riusciamo ad accettare allora rifiutiamo. Percorso, non ce ne sta. Ok? Quindi questo algoritmo ci risolve il nostro il nostro problema, ok? Dobbiamo considerare, voi l'avete trascritto perché mi serve spazio qua, dobbiamo considerare qual è la complessità spaziale di questo algoritmo. Ok? Quindi vediamo quanta memoria questo algoritmo necessiti. Per il momento ignoriamo le chiamate ricorsive, andiamo a guardare il resto. Ok? Allora, per guardare il resto sostanzialmente che ci serve a noi? Ci serve dello spazio in memoria per riuscire a sapere chi sono S e T, perché noi facciamo questi test, ok? Quindi sono o dei puntatori verso il nastro di input dove appaiono S e T nella descrizione del grafo, oppure, come dicevamo ieri, può essere un ID, un ID di taglia logaritmica. Ok? Quindi a noi serve due, potremmo dire registri di taglia logaritmica, due due spazietti di taglia logaritmica su worktape, uno per registrare S, l'altro per registrare t, che ci servono sia per questo test che per questo test. Dopodiché ci serve un altro spazio di taglia logaritmica per tenere tracce di chi è l' corrente. Ok? Questo qua. Quindi, se noi al momento ignoriamo la parte delle chiamate logaritmiche a noi servono tre pezzettini, le chiamate ricorsive, scusate. A noi servono tre pezzettini di taglia logaritmica. Ok? Quindi, a parte quello, noi abbiamo che per memorizzare S t e u serve spazio o di log n. Ok? Notate che u noi lo riscriviamo, cioè non è che noi iniziamo a scriverlo sul nastro, è il primo U, è il secondo U è il terzo U e così via. Noi u lo scriviamo sul nastro e poi lo ci riscriviamo sopra, quindi risparmiamo spazio. Ok? Quindi se noi ignoriamo le chiamate ricorsive per una sola call a noi serve spazio logaritmico. Ok? Quello che noi ci dobbiamo chiedere adesso è siccome questo algoritmo è ricorsivo e quindi su stack andiamo a mettere tutte le chiamate eccetera, lo spazio occupato durante l'esecuzione è dato da quante chiamate facciamo per lo spazio di ognuna di queste chiamate, ok? Quindi sull'altezza massima dello ste noi lì potremo capire quanto spazio staremo occupando in memoria. Ok? Chiaro? Quindi ci dobbiamo occupare di questa cosa. Andiamo a vedere l'albero della computazione ricorsiva per questo per questo algoritmo. Supponiamo di avere exists path. Qui abbiamo GST. La chiamata iniziale è proprio sul numero degli archi. Ok? In questo modo abbiamo è la primissima chiamata GST, numero degli archi. Allora, nella prima chiamata noi genereremo due chiamate ricorsive, ok? Per ogni U genereremo delle chiamate ricorsive. Adesso andiamo a guardare questa cosa nello specifico. Nel momento in cui andiamo a testare le U diverse, tutte queste chiamate ricorsive stanno in memoria allo stesso momento sulla primissima la primissima chiamata di exist, no? Cioè c'è un for. Noi questi U li consideriamo uno per volta. Quindi, preso un u, facciamo due chiamate ricorsive. Allegria. Exist path. Andiamo da GSU a mezzi e l'altra è existat Gut. A mezzi, ok? Spazio là non ce n'è. A mezzi c'è scritto là. Ok. Sì, potremmoare una chiamata come per esempio quella di sinistra prima. Esattamente. Questa è l'osservazione che facciamo, cioè le due chiamate parall le due chiamate per uno mica vengono eseguite in parallelo, facciamo prima uno e poi l'altro. Di conseguenza, noi esploreremmo prima questa parte qua, poi lui genererebbe altre due chiamate ricorsive e questo qua ne genera altre due e così via. Ma noi di questi chiamate ricorsive, quando si forca ne abbiamo sempre uno in memoria. Non ne facciamo due contemporaneamente. Quando ritorniamo dalla chiamata ricorsiva e quello ci ha detto sì, va bene, a quel punto facciamo partire l'altra. Ok? Quindi ci sarà a un certo punto qui arriviamo all'ultimo passaggio in cui questo è caso base e quest'altro è un caso base e quindi noi avremo per esempio questo path di chiamate ricorsive in memoria oppure questo qua. Ma non li avremo tutti assieme, ne avremo uno per volta, come un attraversamento in profondità. è come un attraversamento in profondità, però delle chiamate ricorsive. Ok? È chiaro questo? Questo è è la parte importante di questa di questo ragionamento, cioè che noi questo albero di computazione di questo algoritmo di ricorsivo non sarà mai tutto completo in memoria. In memoria abbiamo un solo branch. Ok? Questa è la parte fondamentale dell'osservazione. Ok. Adesso la nostra domanda. Noi sappiamo dall'analisi di prima che ognuno di questi luoghi di esecuzione, record di attivazione, cioè lo spazio di lavoro di qualsiasi di queste chiamate ricorsive, tipo questa qua, questa qua, questa qui, questa qui e così via, ognuno di loro prende spazio logaritmico. Ok? Adesso noi ci chiediamo, ma quanto è profondo questo albero? Perché quello ce lo dice, perché a questo punto è chiamata ricorsiva, chiamata ricorsiva, chiamata ricorsiva, spazio logaritmico. Altra richiamata chiamata ricorsiva, spazio logaritmico. Quindi avremo spazio logaritmico per il numero di chiamate su step. Quante sono? sono logaritmiche perché volta perché ogni volta dimezziamo K. Ok? Quello è il trucco. Siccome sto K noi lo andiamo a dimezzare ogni volta, ecco perché c'è il principio della ricerca binaria, noi dimezziamo ogni volta a quel K. Di conseguenza la profondità di questa cosa è log a. Ok? Quindi su step nella peggiore delle ipotesi avremo big o di log a chiamate ricorsive, ognuna delle quali richiede spazio logaritmico. Da ciò, qual è la complessità spaziale di questo algoritmo? è O log a O log N. E siccome A fa parte dell'input e quindi è lineare nell'input, avremo che questa cosa qui è O di log squ N. Quindi questo algoritmo ha uno spazio di esecuzione polilogaritmico, cioè al quadrato di un logaritmo. Ok? Chiaro per tutti come funziona questa cosa? Quindi noi abbiamo dimostrato che esiste una procedura che ci permette di eh decidere rich ability in spazio quadratico logaritmico. Ok? Dice "Ah, bello sto risultato, non ce ne facciamo niente". Sì, in effetti. Però in realtà questo costituisce la base di un teorema molto più importante che è un teorema che caratterizzi le classi di complessità di le classi di complessità spaziali, ok? Che è il teorema di Savic. Facciamo l'altra pagina. Allora, il teorema di Savic è un teorema abbastanza interessante perché ci permette di dare dei risultati che noi sulle classi temporali non siamo in grado di fare. sulle classi spaziali, probabilmente perché il riuso dello spazio ci permette di avere molta potenza, noi siamo in grado di dimostrare una cosa abbastanza interessante. Quello è definito dopo. Vabbò. Allora, il teorema di Savic ci dice questo: sia SN una space function, quindi sia Snale che SDN big Omega di log n, cioè, quindi s n deve essere almeno logaritmica. Questa cosa, questo risultato non vale per space function che crescono meno di logaritmo. Ok? Allora, abbiamo che n space di SN è contenuto in d space di Sn². Ok? Allora, questo è un risultato interessante perché sostanzialmente ci dice che tutto quello che è possibile fare in spazio non deterministico per una certa funzione lo si può fare in spazio deterministico con quella funzione al quadrato. Ok? Quindi significa che riusciamo a differenza del gap per le classi temporali in cui per passare da non deterministico a deterministico abbiamo un salto di tipo esponenziale. Quando lavoriamo su classi spaziali il salto è solamente quadratico, ok? che è molto poco. Allora, diamo giusto uno sketch, una una bozza di dimostrazione non troppo precisa, giusto per dare un'intuizione di come di come si dimostri questo teorema. Allora, per dimostrare questo teorema noi dobbiamo sfruttare due elementi. La riduzione verso ritability che abbiamo visto ieri, almeno il concetto, cioè l'idea che avevamo utilizzato e l'algoritmo che abbiamo visto stamattina per la risoluzione in spazio log squarespace di ritability. Ok? Allora, dimostrazione sia L un linguaggio appartenente a Nspace SDN, quindi esiste una macchina M non deterministica, tale che il linguaggio di M è propriamente è proprio L e il suo running space è s. Ok? Allora, di questa macchina M non deterministica che riconosce il linguaggio L, noi possiamo andare ad analizzare il suo computation graph. Che cos'è il computation graph? È la cosa che abbiamo visto ieri quando ragionavamo su reachability. è sostanzialmente un grafo i cui nodi sono relativi ai vari stadi computazione della macchina e ci sta un arco che collega due nodi se un nodo è il successivo del precedente rispetto alla funzione di transizione di m. Ok? Computation graph è il concetto che abbiamo visto ieri quando ci siamo inventati la riduzione vernicability è quella cosa lì. Ok? Allora, l'idea di base per far vedere che L possa essere, sebbene sia riconoscibile in spazio non deterministico Sn per riconoscerlo in spazio deterministico Sn², quello che noi facciamo è questo, l'intuizione proprio semplice. costruiamo il suo computation graph e per computation graph intendiamo quello di er. Dopodiché lanciamo l'algoritmo di ritability che abbiamo visto stamattina su quel grafo e a quel punto verifichiamo se esista un percorso dal dalla configurazione iniziale a quel nodo che chiamavamo ieri in vista. Ok? Tutto qua di nuovo. Quindi prendiamo questi due pezzi che abbiamo. La nozione di computation graph introdotta ieri è l'algoritmo che abbiamo visto stamattina che dimza i percorsi. Ok? costruiamo quello, ci lanciamo l'algoritmo sopra da S, che è la configurazione iniziale a Vistar, che era quel modo particolare in cui tutte le configurazioni accettanti concluiscono e ci chiediamo se esista questo percorso o meno. Ok? Per fare questo però ci dobbiamo chiedere quanto grosso sia questo grafo, ok? Perché adesso questo grafo lo dobbiamo proprio rappresentare prima di lanciarci sopra l'algoritmo che lo risolve che risolve il problema della richility. Ok? Allora, come dicevamo ieri, noi abbiamo che i nodi del computation graph possono essere distinti, non è necessario scrivere tutta la la configurazione come facevamo in passato. Quei nodi possono essere distinti guardando a quattro elementi. il contenuto del nastro di lavoro, perché sono le uniche cose che realmente cambiano. Il contenuto del nastro di lavoro, la posizione della testina sul nastro di input, la posizione della testina sul nastro di lavoro e lo stato corrente di computazione. Quindi noi avremo che una label avrà il work tape, una label per questi nodi del computation graph. Avrà un pezzo di label che è il contenuto del work tape. Poi abbiamo la posizione della testina sul nostro di input, la posizione della testina sul nastro di lavoro e un identificativo dello stato corrente. Ok? È la cosa che abbiamo visto ieri. Alri, adesso facciamo lo stesso ragionamento di ieri. Quanto è grande questa parte di questa label? Se la macchina M esegue in spazio SDN. Attenzione, eh no, no. Lo spazio usato da M di running space di M è SDN. Sn SDN, quindi questo è big o dn. Ok? Perché lo spazio che noi diamo disponibile alla macchina M per eseguire è proprio SDN. Quindi su workape noi scriviamo bigo di SDN simboli. Ok? Quanto è grande il puntatore alla cella corrente sul nastro di input? Logaritmo di il nastro di input. Il n quanto è lungo l'input? N. Quindi i puntatori alle celle del nastro di input hanno taglia log logaritmo di n, quindi qua log n. Ok, prego. Ma eh non potremmo scrivere H1 come una codifica dell'alfabeto di In che senso? Nel senso sarà capitol da N ai elementi n singoli. H1 sarà l'elemento uno di quei n sing simboli, quindi dovre essere scritto come, cioè lei vorrebbe che, se ho capito bene che l'alfabeto di nastro abbia tanti simboli quanto la lunghezza della stringa input. Ho capito bene? No, forse non ho capito bene io come fatto questo? Allora, semplicemente questo. Noi abbiamo il nastro di input che ha, che ne so, 16 celle. Sì, cioè la la stringa in input ha 16 simboli, ok? Indicizzati 0 1 2 3 bla bla 15. Se io devo memorizzare dove si trovi la testina, allora a me serve indicarlo con un numero in posizione 10. Questo numero io lo posso scrivere in rappresentazione binaria e a quel punto a me servono logaritmo di n bit per dire la testina sta lì. Ok? Ma allora non potrei direttamente considerare la sti hola indirettamente il simbolo letto dalla testina? No, perché se lei ha un simbolo ripetuto in input, come fa a sapere a quale di quello ci stiamo riferendo? string copi cioè ci saranno tutti string lavoro perché il work tap sarà cambiato se la destin ma se io ho contenuto di un work tape che è una certa cosa e dopo dico h simbolo stellina e input della stellina ce ne stavano cinque o se io come faccio a sapere dove si trova la testina? Cioè quello è il problema, perché io devo spostarmi, devo fare la foto di dove cosa sta facendo la macchina. Io posso pure dire "Ok, leggo la stellina". Però quando poi la funzione di transizione mi dice va a destra, magari una stellina c'ha la casetta, dopo un'altra stellina c'ha l'alberello e io come faccio a sapere la testina cosa leggerà dopo se non so dove sta la testina? Quindi io devo memorizzare la posizione, non solo il contenuto. Non è sufficiente quello per ricostruire il funzionamento della macchina. È più chiaro così? Nulla. Ok. Quindi in H1 memorizziamo la posizione che è un numero, eh, non è che chissà che stiamo facendo. La testina sa in posizione 27. Ok? Dobbiamo fare la stessa cosa per H2. Quanto è grosso H2? log di s è log s n e q è una costante, ok? Perché il numero dei degli stati non dipende da Ok? Non dipende da eh dalla lunghezza dell'input. Ok? Allora, poiché guardate qui c'è questo elemento qua che è l'unico che tra virgolette non dipende da SN. Ok? Siccome, e qui c'è l'osservazione, siccome S nendo essere almeno log n, tutta la label Sì, label richiede Big o D SDN. simboli. Sì, sì, sì, c'ha simboli. Ok, quindi noi abbiamo espresso un vincolo su Sn. Siccome Sn non è più piccolo di log n, allora non sarà mai questo il leading term. Da per questa ragione noi abbiamo che tutto lo spazio che ci serve per rappresentare questa label che poi utilizzeremo nei nodi del computation graph è big o ddn. Ok? Alright. A questo punto possiamo fare delle considerazioni sulla sul grafo, no? sul grafo, su questo computation graph che stiamo andando a costruire, perché come vi dicevo, il nostro obiettivo è scriviamo il computation graph in memoria, lanciamo l'algoritmo di ricability, diamo la risposta. Quello che noi ci stiamo chiedendo è quanto occupa in memoria tutta questa procedura. Quindi il primo pezzo che ci serve è stabilire, ma questo grafo quanto è grosso? Ok? Quindi noi abbiamo che questi sono gli identificativi dei nodi. Ok? Ci chiediamo quindi quanti sono i nodi di questo grafico. Allora, noi abbiamo che su work tape ci possono stare i vari simboli di nastro. Poi qua abbiamo la codifica binaria, binaria binaria. Però il tutto è bounded da cosa? dalla quantità di nodi che si possono generare se noi usassimo tutti i simboli di nastro in tutte le posizioni, ok? Quello è proprio al più e quello il numero, ok? Siano L I sia L. Scriviamo meglio. Facciamo proprio così. Sia l la cardinalità dell'alfabeto di nastro. Ok? Allora, il numero di nodi è big o di cosa? S l elevato SN. Ragazzi, qua stiamo proprio togliendo costanti eccetera, facciamo proprio un'analisi raff, eh, quindi è big o d^ s n è il numero dei nodi di questo grafo G, di questo computation graph. Ok, so tantini, eh. Quando rappresentiamo il grafo, facciamo solo la lista dei nodi. Ci servono gli archi. Gli archi in linea di principio sono tutte le possibili coppie dei nodi. Posso essere proprio tante. Ok. Quanti sono gli archi? Big O di cosa? Attenzione, attenzione. Se abbiamo eh se abbiamo V nodi, no, un numero di S, eh abbiamo M nodi. Ok? Se abbiamo m nodi, quanti sono al massimo gli archi? Qu m quato. Quindi se il numero dei nodi è big o di l^ s n, quanti potranno mai essere gli archi? quadrato il quadrato di quello, quindi è L^ S n al quadrato che per la proprietà delle potenze è big o di L^ 2 * S n e questo è il numero di vertici è numero di di di archi. Sì, sì, sì. numero di archi. Ok? Fra i due, chi è quello più grande? Il secondo. Quindi quello è leading term. Abbiamo che la taglia di questo computation graph è questa qui, è big o di l^ 2 * SN. Ok? Quindi, nel momento in cui facciamo avanzare questa procedura, noi abbiamo che generiamo il computation graph e occupiamo quello spazio. Dopodiché dobbiamo eseguire la procedura di Richability vista stamattina su quel grafo. Ricordo che la complessità complessità spaziale di Exist path existia del grafo. Ok, allora combiniamo le cose. Che cosa abbiamo? Abbiamo big o. Guardo gli appunti, non voglio scrivere una stupidaggine. Big O di log 2 * SN quadrato. Questa cosa è big o di cosa? di 2 * s n * log al quadrato. Questa qui che cos'è? Una costante. È una costante, quindi la possiamo buttare. Costante e anche questa è una costante e si può togliere. Quindi il tutto è big o di cosa? Di S n al quadrato. Chiaro? Vi ricordo che le costanti possono essere tolte dalle classi asintotiche, ok? Quindi 2 è una costante e la togliamo. Log in base 2 di L è una costante perché? Perché L è il numero di simboli dell'alfabeto di nastro, ma l'alfabeto di nastro è fissato, non è che cambia in base a quanto è grande la stringa, diciamo, "Ah, mi serve un simbolo in più, la stringa è troppo gross". Ok, quello è fissato. Quindi questi due li possiamo ignorare e il tutto è bigo d Sn al quadato. Ok? Qual è la conseguenza di questa cosa qua? Facciamo prima questo e poi facciamo pausa. Noto che finiamo prestissimo oggi, quindi avremmo il tempo di fare il questionario. Cercavo cercavo un giorno in cui ilceste perdere, ma non un questionario di esame, il questionario mio. Allora, possiamo quindi definire possiamo quindi definire P spazio e NP spazio, ok? Che sono l'equivalente di PD NP, invece di essere sul tempo possono essere sullo spazio. Ok? Secondo voi cosa sarà My Space? Ah, dove li ho? Qua. Come potremo definire la classe polynomial space? Me lo ricordate com'è definito P time? è l'unione per i c maggiore uguali di 1. Sì. E di di time e sì di space di n^ c. Bravissimo. Ok. Questo è pi spazio. Che cos'è pi spazio? È l'insieme di tutti i linguaggi che possono essere decisi in spazio polinomiale da una macchina di Touring deterministica. spazio è una classe tostissima, eh, cioè mo adesso vedremo poi la relazione con le altre con le altre classi che abbiamo visto, ma un problema che sia uno dei problemi tosti di più spazio è un problema che richiede una quantità di tempo mostruosa per essere per essere risolto. Ok? ed n spazio. Esattamente l'unione su C che è maggiore di 1 di n space di n^ c. È chiaro? Ok. Guardate queste due definizioni. Guardate cosa possiamo dire della relazione di contenimento di questi due di queste due classe. Chi contiene chi? quella la più immediata, la più semplice. Sì, abbiamo che sicuramente pi spazio è contenuto in n spazio. Ok? Benissimo. Guardate il teorema di Savic che cosa ci dice? Che sono uguali. Che sono uguali. Il teorema di Savic sostanzialmente ci dice che tutte le classi spaziali da pi spazio a salire perché la cosa non funziona sul log space perché quello sarebbe log space al quadrato. Ok? Quindi il teorema di Savic ci dice che tutte le classi di complessità spaziali da polinomial a salire la classe deterministica eguaglia la classe non deterministica. P spazio è uguale a NPA per il teorema di Savic. L'intuizione qual è? L'intuizione è che siccome abbiamo vincoli sullo spazio, ma non sul tempo, cioè il tempo una volta che lo usiamo il tempo è andato, non è che lo recuperiamo, lo spazio invece può essere riutilizzato. Ecco perché pi spazio è uguale a n spazio, perché noi praticamente una macchina a P spazio può simulare una macchina non deterministica, polynomial space, semplicemente riprovando, facendo le fa un tentativo, non è andata bene, riprovo, ma lo spazio chiuso è sempre lo stesso, è quella la ragione sostanzialmente. Ok? Questo fa sì che tutte le classi di complessità spaziale sopra si considera sempre la versione deterministica perché la versione non deterministica non ci dà nulla di più. Ok? Bene, con questo facciamo un po' di pausa, una decina di minuti. [Musica]