Allora, è tutto più o meno chiaro quello che abbiamo fatto scorsa volta. Era giusto un recapo velocissimo. L'importante è che abbiate più o meno i concetti, li rivediamo velocissimamente oggi e poi introduciamo un concetto nuovo. Ok? Allora, come abbiamo detto come abbiamo detto noi studieremo la complessità non degli algoritmi ma dei problemi. Ok? Questa è la differenza sostanziale fra quello che avete visto finora e quello che vedremo in questo corso. Per questa ragione abbiamo necessità di formalizzare i problemi. Abbiamo detto che ci stanno problemi di ricerca, che sono quei problemi per i quali le risposte possono essere varie e i problemi di decisione i quali hanno come risposta solamente un buleano. Ok? S no. Abbiamo detto che praticamente eh i problemi di decisione possono essere vari, possono essere vari contesti, ci possono essere matrici, grafi, ipergrafi, qualsiasi qualsiasi cosa viene in mente immagini, testo, bla, eh tale per cui, insomma ehm andarli ad analizzare da questo punto di vista, cioè se non mettiamo delle ipotesi di semplificazione di viene tutto un po' indicato. Ok? Allora, noi ci siamo andati a scegliere dei problemi che avete già visto nella vostra carriera, che è il problema di decidere linguaggi. Ok? Perché facciamo questo? Perché decidere in un linguaggio è un problema di decisione. Vi ricordate cosa significa decidere un linguaggio? Verificare se una stringa appartiene o meno Verificare se una stringa appartiene o meno un dato linguaggio. Quindi, qual è l'input? una stringa. Il linguaggio fa parte dell'input, no? Ok, questo è importante. Ok, quindi l'input del problema di decidere un linguaggio è dato una stringa e un linguaggio che in qualche modo noi conosciamo, che ci viene dato e definito all'interno del problema. Noi dobbiamo decidere se questa stringa fa parte di questo insieme o meno. Ok? Allora, poiché noi abbiamo detto possiamo codificare, no, con un codice opportuno dentro i linguaggi varie cose, sostanzialmente possiamo ricodificare, ok, all'interno di linguaggio opportuno i problemi e decisioni a cui siamo interessati. Ok? Chiaro per tutti come si fa? Perché noi possiamo definire dei linguaggi appositi su un alfabeto apposita, no? Tale per cui le stringhe che fanno parte del linguaggio sono, ok? Nel caso nel caso dei problemi di decisione noi abbiamo che nel linguaggio fanno parte, ok? Pensiamo a questo problema, il problema dei grafi totalmente connessi. Sapete cos'è il un grafo completamente connesso, totalmente connesso? Ok? È un grafo da cui da ogni nodo si può arrivare a qualsiasi altro nodo. Ok? Supponiamo di avere questo problema. Ok? Dato un grafo, stabilire se totalmente connesso. Questo è un problema di decisione, un problema di ricerca. problema di decisione perché perché la risposta in buuleano, cioè ci danno un grafo, noi dobbiamo dire sì, no. Poi, ok, può richiedere che ci inventiamo varie cose prima di dire sì no, però la risposta alla fine è o sì o no. Quello fa sì che il problema sia di decisione. Ok? Se dobbiamo inventarci un linguaggio che in qualche modo codifichi il problema di decidere se un grafo è totalmente connesso, che linguaggio potremmo inventarci? Ecco, puoi dire un po' più adatto. Cioè, il linguaggio stammina. Esatto. Cioè, noi ci possiamo inventare una codifica su dei simboli opportuni tale per cui le stringhe che fanno parte di questo linguaggio sono solamente le stringhe che secondo la nostra codifica codificano un linguaggio, un grafo totalmente connesso. Ok, è chiaro? Supponiamo di ricevere input una stringa stramba che non codifica un grafo secondo la nostra codifica. Ok? Questa stringa fa parte del linguaggio? No, no. Ok? Perché del linguaggio fanno parte solamente le stringhe sensate, cioè che codificano i grafici e che sono totalmente connessi. Ok? Quindi da un lato noi abbiamo che eh i problemi di decisione possono essere reincoded in linguaggi opportuni, tale per cui sulle stringue per le quali noi dobbiamo rispondere sì, sono le stringhe che appartengono al linguaggio. Le stringhe che codificano roba strana, per definizione nostra, non stanno dentro questo linguaggio. Ok? Ma questa cosa ovviamente si può anche estendere ai problemi di ricerca. Mh, pensiamoci un po' assieme. Supponiamo che dobbiamo codificare dentro un opportuno linguaggio un problema di ricerca. Come possiamo fare? Il problema di decis, cioè risolve il problema di decisione. Problema di ricerca. Noi vogliamo codificare in un linguaggio un problema di ricerca. Eh, la mia risposta sarebbe stata prima risolvo quello di decisione e lo trovo e una volta che l'ho trovato lo leggo e mi dà quella No, vogliamo codificare in un linguaggio opportuno le stringhe che mi codificano un problema di ricerca. Che cos'è un problema di ricerca? Cos'è un problema in generale? Eh, è una una relazione che sono c string di è una relazione binaria, sono coppie, ok? Ricordatevi un problema sono coppie di stringhe, input output, ok? Solo che noi perché parliamo a che cos'è l'input, che cos'è l'output, qual è la relazione? Se in realtà un problema è un insieme di coppie, perché i problemi che ci interessano hanno una lista infinita di coppie, quindi non è che possiamo metterci a scriverle tutte. Allora, ci dobbiamo inventare un modo per descrivere in maniera finita una relazione infinita. Quindi lo descriviamo. Dice questo è l'input, questo è l'output. La relazione fra input e output è questa. Però di fondo un problema di ricerca è una relazione binaria tra stringer che associa input ad output. Ok? Supponiamo noi volessimo codificare dentro un linguaggio un problema di ricerca. Che possiamo fare? secondo, eh, vediamo se c'è qualche voce nuova. Voci nuove. Niente, eh. Ok, prego. Mettere una puoi alzare la forare una stringa in cui è codificato grafo input e il grafo. Il grafica input e il corso ma tu stai suppendo, lei sta supponendo che stiamo un problema di ricerca sul graso. Ok, riformuliamo. Quindi è un linguaggio in cui abbiamo le stringhe che codificano input e l'output. Ok? Cioè noi abbiamo in un linguaggio per ehm codificare un problema di ricerca abbiamo delle codifiche opportune su un alfabeto opportuno della relazione input output, ok? E in quel linguaggio che ci stanno? Ci stanno tutte le stringhe che codificano, secondo la nostra codifica, le coppie input output del problema in questione. Ok? Quindi a quel punto decidere quel tipo di linguaggio richiederà per noi sostanzialmente calcolare la soluzione, anche se non è propriamente così, lo vedremo poi nelle lezioni a venire, ok? E quelle coppie le cui la cui stringa di input è una cosa stran linguaggio o no? No. Quelle stringhe che non codificano coppie ci stanno nel linguaggio, no? No. Ok? Cioè, quindi noi possiamo sempre codificare all'interno di un linguaggio i problemi che a cui noi siamo interessati, però per semplicità noi ci focalizziamo sui problemi di decisioni e di conseguenza siccome un problema di decisione come risposte si no è un linguaggio a di uccidere un linguaggio ha come risposta sino la codifica al linguaggio di un problema decisione è il linguaggio che contiene tutte le istanze sì di quel particolare. problema. Ok? Così è unistanza sì, è un'istanza, cioè una stringa che fa parte di quel linguaggio o un input per quel problema, la tua risposta è sì. È chiaro? Quindi noi possiamo fare sempre questo genere di di giochino. Facciamo questa cosa perché perché ci semplifica la vita. Ok? Dopodiché abbiamo introdotto, siccome noi vogliamo stabilire se un determinato linguaggio sia decidibile o meno e per noi intuitivamente, poi vedremo più nel dettaglio questo che significa, ma intuitivamente una cosa è risolvibile se c'è un algoritmo che la risolve, allora noi ci dovevamo inventare degli algoritmi che decidessero linguaggi. Allora, che facciamo? Li facciamo in Java, li facciamo in Python, li facciamo in Gobble. Ok? Vien detto, per evitare di impelarci, impantanarci nella sintassi dei linguaggi, noi utilizziamo un formalismo che è molto più asciutto, che è il formalismo degli automa. Quindi noi abbiamo che un certo linguaggio è decidibile se esiste un automa che lo decide. Ok? Oggi faremo differenza fra automi che accettano e automi che decidono. Ok? Che cosa abbiamo visto? Abbiamo visto due classi di autommi così velocissimamente e poi che avete fatto i linguaggi li avete sicuramente studiati in maniera più approfondita, però due due classi di automi molto semplici sono gli automi deterministici a stati finiti e gli automi non deterministici a stati finiti, pure quelli. Ok? l'intuizione che avevamo dato e quindi riprendiamo questa perché oggi lavoreremo su questa qua. L'intuizione per un automa stati finiti, che sia deterministico o sia non deterministico, è questo. L'automa ha un input. L'input di quest'automa è un lungo scontrino, è un nastro, ok? sui quali vengono scritti dei simboli. Sono i simboli dell'alfabeto su cui il linguaggio è definito. Chiaro? Sto andando troppo veloce. Ok. L'automa che fa? Ogni volta che legge un simbolo e si trova in un certo stato di funzionamento, transisce verso un nuovo stato e butta via il simbolo, cioè va avanti sul nastro. La caratteristica di questi automi è che una volta che la macchina supera un simbolo, va, porta avanti il lettore, diciamo, quel simbolo è perso, cioè non possiamo andare indietro a guardarlo. Ok? Quindi questa è una macchina che ogni volta che vedo un simbolo deve tra virgolette fare l'operazione giusta perché indietro non torna. Ok, abbiamo introdotto poi delle macchine strane che erano delle macchine non deterministiche. In cosa consisteva il nondeterminismo? Il nonismo di queste macchine consisteva nel fatto che questi automi in presenza di un certo simbolo e un certo stato interno di funzionamento, non avevano una scelta obbligata su cosa fare, ma potevano transire verso più stati successivi. Ok? Quindi le macchine non deterministiche avevano scelte, le macchine deterministiche non hanno scelte. Ok, ci siamo fatti questa metafora. Allora, abbiamo detto che formalmente una macchina accetta, una macchina deterministica accetta se la sua computazione deterministica va a finire in uno stato accettante, consumando tutto l'input. Una macchina non deterministica accetta se ha un modo di accettare il proprio input, ok? Perché avendo varie scelte potrebbe computarle in vari modi. Alcuni che accettano, altri che non accettano. Allora, ci siamo detti, ma se ci sono modi per accettare e modi per non accettare, la macchina dice sì o no? La macchina dice sì ogni volta che c'è almeno un modo per accettare. Ok, chiaro? E ci sono classi strane in cui la maggioranza delle computazioni deve essere Sì, ma quelle forse alla fine se abbiamo tempo le guarderemo. Al momento facciamo il modello standard. La macchina accetta se esiste almeno un modo per accettare. Ok? Risultato interessante che abbiamo menzionato ma non dimostrato è che le macchine non deterministiche, sebbene sembrano sembrano più furbe delle macchine deterministiche, in realtà hanno lo stesso potere di calcolo, cioè sanno fare le stesse cose, non sanno fare più cose e in particolare non lo sanno fare nemmeno più velocemente perché si può dimostrare che automi non deterministici a Stati finiti possono essere trasformati in automi deterministi già Stati finiti equivalenti, cioè che riconoscono lo stesso linguaggio e la performance è la stessa, cioè il tempo che la macchina ci mette a decidere una stenda è sempre lineare perché guarda un simbolo per volta, che sia non deterministico, che sia deterministico, ok? Cioè, quindi le macchine non deterministiche, gli automi non deterministici che abbiamo visto finora, non hanno nulla di più potente di quello che abbiamo. Sono più facilmente programmabili rispetto alle macchine deterministiche. Tutto qua. Perché ce le siamo inventate? Perché progettare automi non deterministici è più facile. Poi lo diamo impasto a un compilatore, ci mette in mano e tira fuori la macchina deterministica. Ok? Noi non ci siamo cervellati per capire come fare una macchina deterministica. Ok? Una cosa che abbiamo notato e ci siamo lasciati con questo esempio la scorsa volta era il linguaggio delle parentesi, a volte si chiama comunque questo qua. Allora, avevamo definito avevamo definito il linguaggio delle stringhe sull'alfabeto AB tale per cui abbiamo prima una sequenza di A, poi una sequenza di B e il numero di B deve essere uguale al al numero di A. Ok? Questo era il constraint. Abbiamo visto intuitivamente perché questa cosa non può funzionare, cioè non ci può essere un automa stati finiti in grado di riconoscere questo linguaggio, né deterministico né non deterministico. E l'intuizione dietro era che la macchina, cioè che l'automa Stati Uniti è troppo semplice, non è in grado di contare. Ok? Eppure noi abbiamo l'esperienza che in Python, in Java eccetera. Noi siamo in grado di riconoscere quel genere di linguaggio. Ok? Allora, la cosa è che un automa stati finiti è troppo semplice, cioè non ha un potere di calcolo sufficientemente forte da essere in grado di contare le cose. Ok? Introduciamo giusto questa notazione perché ci serve poi che sono la notazione dei linguaggi regolari. Allora, sia a sigma un alfabeto, un linguaggio regolare su sigma è un linguaggio che si può ottenere tramite concatenazioni di simboli in sigma e altre parole. Ok? Allora, una un linguaggio regolare è un linguaggio le cui stringhe vengono caratterizzate da quelle che si chiamano espressioni regolari. Le espressioni regolari sono un modo compatto di esprimere linguaggi su sull'alfabeto. Allora, se alfa è un simbolo appartenente a sigma, allora alfa è un'espressione regolare. Ad esempio, se noi abbiamo, che ne so, sigma che è 0, allora solamente 0 o solamente 1 sono delle espressioni regolari, ok? Dopodiché abbiamo che se alfa e beta sono espressioni regolari, allora anche la concatenazione anche la concatenazione alfa beta oplà è una espressione regolare. Ok? Quindi se noi avevamo che 0 e 1 come simboli distinti sono espressioni regolari, allora per questa ragione 00 sarà un'espressione regolare. 0 1 1 1 1 1 e insomma. Ok? Tutti i modi di agganciare i simboli su sigma sono espressioni regolari. Un'altra espressione regolare è la disgiunzione. Alfa e beta sono espressioni regolari. Allora, alfa or beta un'espressione regolare. Alfa or beta è una stringa. E che cavolo su? alfa o beta or beta è una stringa una è quelle stringhe fatte o dal pezzo alfa o dal pezzo beta, quindi che ne so 0 1 0 or 1 per dire. Questa è un'espressione regolare che ci dice che le stringhe che fanno parte di questo linguaggio regolare sono o 0 oppure 1 1. Ok? Se alfa è un'espressione regolare, allora alfa star è un'espressione regolare. Cos'è alfa star? Alfa Star è una concatenazione, ok, di 0 più volte alfa. Quindi se noi abbiamo che ne so 1 0 star, questo qua è il modo compatto di dire che tutte le stringhe che appartengono a questa espressione regolare o linguaggio regolare è 1 10 oppure 1 10 1 10 e così via. Ok? Al posto di star possiamo avere un altro simbolo, l'introduco perché poi quando vedremo macchine toring sta cosa ci serve. Al posto di Star possiamo avere un altro simbolo che è il simbolo più dove ci dice che quel pezzo di espressione, cioè di quel pezzo di parola si deve ripetere almeno una volta. Ok? Risultato interessante è che gli automi a stati finiti, deterministici o non deterministici sanno riconoscere, sanno decidere tutte e solo le espressioni regolari, cioè le espressioni regolari è il potere di computazione degli automi a stati finiti. Loro non sanno fare più di quello. Ok? Cosa interessante è che questo linguaggio qui, che è il linguaggio della parentesizzazione, non è esprimibile tramite un'espressione regolare. Ok? Però, come abbiamo detto, noi abbiamo l'intuizione che questa cosa si può risolvere e allora dobbiamo introdurre un altro modello di calcolo. Sì, prego. Scusi, però perché allora se alfa star è combinazione di alfa è anch'essa regolare e la concatenazione alfa beta abbiamo detto regolare perché eh a^ b^ n nonostamente perché lì si sta imponendo un vincolo sulla lunghezza. Io posso scrivere a star b star o a + b+, ma quindi posso avere 5a e 8b. Ok? Quando diciamo am BM è devono essere proprio lo stesso numero, ok? E il problema della degli automi a stati finiti è che non sanno contare, cioè non hanno, sostanzialmente non hanno la memoria, questo è il problema. Ok? Non sanno contare all'infinito, sapreo contare se abbiamo un dominio finito. Ok? Ah ok. Allora, noi dobbiamo quindi inventarci un modello di calcolo che sia un po' più sofisticato. Per quelli che hanno fatto linguaggi sanno che in realtà non serve una macchina di tingonoscere AMBM. Esiste un altro automa con una memoria molto semplice che è la l'automa appila, però ovviamente non ci buttiamo su questo. Noi sfruttiamo AMBM per introdurre le macchine di touring. Ok? Allora, che cos'è una macchina di touring? Una macchina di touring non è la macchina che si vede nel film, quella è un'altra cosa. La macchina che si vede nel film The Bomb che viene utilizzata per decifrare Enigma. Se andate a Milton Kins, quella macchina è là, la potete visitare al museo lì. Quindi la macchina di Turing non è quella. La macchina di Turing. Che cos'è la macchina di Touring? è una macchina astratta per modellare il calcolo. Ok? è un'idea che gli era venuta a Turing negli anni 20-30 perché in quel a quel tempo i matematici si chiedevano quali funzioni fossero calcolabili in maniera automatica e quale funzioni non fossero calcolabili, quali teoremi potevano essere dimostrati automaticamente e quali teoremi non si potessero di teoricamente. L'idea di computazione a quel tempo c'era già c'era il modello di Charch di Alonso Charch che era il lambda calcolo eccetera, però Turing affrontò quei problemi in un altro modo e si inventò questo modello astratto di calcolo che noi ora chiamiamo macchina di Touring. Lui non aveva chiamato macchina mia, noi la chiamiamo macchina di Touring. Qual è la differenza tra una macchina di ting stati finiti che abbiamo visto finora? Esattamente come gli automi a stati finiti, una macchina di tingo stato interno, quindi ha al proprio interno la codifica di un programma tramite stati, essenzialmente come gli automi stati finiti. Ok? La differenza sta in quello che la macchina di Turing può fare con il nastro. Ok? Noi abbiamo che gli automi a stati finiti possono fare una sola cosa, leggere il simbolo, andare avanti e perso. Ok? Una macchina di touring ha la possibilità sul nastro di fare una serie di cose. La macchina di Touring ha un nastro infinito in entrambe le direzioni e questo qua. Questo nastro è diviso in celle, esattamente come per gli automi a stati finiti. Ok? In queste celle ci stanno i simboli della parola che vogliamo riconoscere, ad esempio A a A B. Ok? Poiché la parola sta su questo nastro infinito, noi dobbiamo delimitare dove questa parola sia. Quindi abbiamo dei simboli speciali sul nastro che ci dicono che in quella cella non ci sta niente, è il simbolo blanc. Ok? Quindi la macchina di touring, esattamente come gli automi a stati finiti, processa tramite stati, ok? Quindi non ha cose pensi eccetera. processa tramite stati, esattamente come gli automi a stati finiti. Le peculiarità di questa macchina sono: il nastro su cui opera è infinito, la testina che la macchina usa per leggere non solo è in grado di leggere un simbolo, ma è anche in grado di scrivere. Ok? Quindi abbiamo una testina che legge simboli, la stessa testina è in grado di sovrascrivere, ok? Quindi schiaffiamo sopra simboli, ok? Dopodiché la cosa importante è che in una macchina di touring questa testina può andare a destra e a sinistra. Ok? Adesso vedremo un esempio. Quindi recap una macchina di Touring è sostanzialmente un automa con un numero finito di stati. Il potere delle macchine di touring sta nel fatto che la macchina su un nastro può leggere e scrivere e può spostare la testina avanti e indietro. Ok? Questa è la peculiarità di una macchina di touring. Quando definiamo un programma per la macchina di Touring, noi abbiamo, ok lo stato di controllo funzione delta che controlla il la testina. Ok. La macchina di Touring ogni volta che Allora l'automa stati finiti cosa aveva? Io sono in un certo stato, leggo un certo simbolo, transisco in un altro stato, salto il simbolo. La macchina di Touring fa un po' più di cose. Sono in un certo stato, leggo un certo simbolo, cosa faccio? transisco in un altro stato e fino a mo sono come le macchine, come gli automi a stati finiti standard, però scrivo anche una cosa sul nastro e decido se spostare la testino a destra o a sinistra. Ok? Quindi per ogni transizione che la macchina fa, indipendenza di quale stato mi trovo e quale simbolo sto leggendo, allora decido in quale altro stato spostarmi, cosa scrivere sul nastro e dove spostare la testina. Ok? Chiaro per tutti? Adesso, prima di introdurle formalmente, noi vogliamo definire una macchina di touring che sia in grado di riconoscere questo linguaggio qui. Ok? Alright. Ok. Supponiamo di avere questo sul nastro. In input c'è A a Aa BB. Noi vogliamo inventarci una macchina che sia in grado di fare questo lavoro. Ok? Ci sono ovviamente tante soluzioni possibili. La soluzione che vi propongo io è questa. Sì, B sbarrato sta per blank, cioè c'è la vuota. Cioè che sul nastro c'è un bianco, visto che il nastro è quindi noi abbiamo scritto a e poi infinito. Sì, infinito. Sì. E questo, per esempio, è già una cosa molto più potente dei computer reali perché i computer reali non hanno una memoria infinita. Ok? Alright. Allora, ci sono mille mila modi per riuscire a riconoscere questo linguaggio. Io ve ne propongo uno e vi suggerisco di pensare così, che immagino che la stragrande maggioranza di voi abbia, visto gli studi che fate, un approccio visivo alla soluzione del problema. Ok? Se non lo processate visivamente non ci riuscirete. Eh, ho potuto sperimentare questo con gli studenti negli anni. Quelli che non costruiscono immagini nella propria testa non riescono a risolvere questo tipo di problema. Allora, che dovete fare nella vostra testa? Io faccio questo. Immagino che gran parte di voi faccia così. Io guardo nel nella mia testa, io mi faccio un filmato di cosa deve succedere alla testina di questa macchina di Touring. Io la vedo andare avanti indietro per fare il suo compito, ok? Dopodiché si tratta di tradurre in un grafo di transizione, in un programma delta, questo andare avanti e indietro è la testina. Però il passaggio veramente importante qua è che voi questa cosa la dovete vedere. Se non la vedete nella testa, disegnatevela, ok? Cioè è l'unico modo per riuscire a risolvere questa cosa. Perché vi dico questo? Perché negli anni, insomma, mi è capitato di interagire con vari studenti. Ci sono quelli che cercano di risolvere questa cosa parlandosi dentro. Ok? si fanno delle domande, ma non vedono niente. Cioè, è difficile così. Quindi io vi dico esplicitamente, voi vi dovete costruire questa immagine. Che cosa vedo io? Io vedo sto bello nastro con la testina di sopra, ma può essere qualsiasi cosa, una nuvoletta, un quadratino come abbiamo fatto là, o una freccetta, una cosa luminosa. Però quello che dovete vedere è questa testina che si sposta avanti e indietro perché guardando questo filmato che riuscirete a tirare fuori la funzione di transizione. Ok? Allora, soluzione per questo problema è una soluzione, eh, non la soluzione. Una soluzione per questo problema è questo qua. L'idea sostanzialmente è la macchina di Touring all'avvio sarà nello stato iniziale bla bla e la testina sarà sul carattere sul simbolo più a sinistra sul primo. Allora, l'idea è io vedo questo, vedo che è una A, la cancello, vado alla ricerca dell'ultima B, la trovo, la cancello, torno indietro. A questo punto questa A non ci sarà più. andrò a prendere questa, la meccio con quest'altra e vado avanti, indietro, avanti, indietro, avanti, indietro, fino a quando ho cancellato tutto. Se il numero di A e di B era lo stesso, arriverò che c'ho un nastro vuoto e non c'ho residui strani. Ok? È chiaro? Questa cosa la dovete vedere nella vostra testa funzionare. Dovete vedere la testina che legge là. Là viene cancellata, la testina viene spostata in fondo. Andiamo sull'ultima B, cancelliamo la B, andiamo sulla prima A, cancelliamo la A, ultima B, prima A, ultima B, prima A, ultima B. A un certo punto il nastro si svuota e diciamo sì, il numero di A e di B era lo stesso e noi accettiamo. Prego. Però dobbiamo assumere che l'utente non possa inserire delle stringhe che contengono il blank. Quello no, quello poi formalizziamo. Ok. No, l'utente non dà blank strani, quindi sono due alfabetti distinto. Sì. Ok. Sì. rischiamo di accettare anche un po' a dipende come progettiamo la macchina. Adesso la progettiamo assieme e vediamo che questo rischio può essere evitato. Ok? Allora, occhio occhio a alla stringa di esempi. Ok? Vi ricordo che abbiamo in testa una strategia visiva. Dobbiamo vedere sta cosa che va avanti e indietro. Ok? Q0 primo stato. Questo è lo stato in cui la macchina parte. Ok, diamo la corrente, la macchina si accende in Q0, testina sul primo simbolo. Ok? Allora, noi siamo qui, stiamo leggendo il primo simbolo. Ok. Ok. Stiamo leggendo il primo simbolo. Allora, guardate questa transizione. La prima ve la scrivo io, le altre le facciamo assieme. Se sono in Q0 leggo A, scrivo blank, quindi lo cancello, e sposto la testina a destra. Ok, quindi eravamo qui, lo stiamo cancellando, spostiamo la testina qui. Ok, chiaro per tutti il significato di questa etichetta che abbiamo dato all'arco? Sull'arco abbiamo qui lo stato iniziale, qui lo stato finale e sull'etichetta dell'arco stiamo dicendo cosa leggiamo, cosa scriviamo, dove spostiamo la testina. Con questo programmiamo le macchine di turn. Sì. E quindi con0 stava indicando il la la posizione della tessina che è sulla prima. Sì, è lo stato in cui parto e quindi dovrei devo definirlo la stessa cosa, no? Abbiamo uno stato nella macchina che si chiama Q0. Potevamo chiamarlo topolino, è la stessa cosa. Ok. che che questo Q0 deve avere per forza una interna. Sì, perché all'inizio noi quasi lo vediamo dopo. All'inizio noi ci aspettiamo un A, andiamo in Q1. Dopodiché cosa fa, ragazzi? Adesso facciamo questo esempio. Guardate il nastro nella vostra mente. Ok? La testina era lì, ha cancellato una A. Dove dobbiamo spostare la testina? Dove dobbiamo spostare la testina? sulla destra. Sulla destra. Ok. Mentre la spostiamo a destra, guardate il nastro. Ok? Dovete vedere il nastro nella vostra testa. C'è un primo pezzo di A. Magari se non vedete le A, coloratele verdi e il resto coloratelo rosso. Ok? Qualsiasi cosa che vi permetta di distinguere le cose, ok? Dobbiamo quindi portare la testina a sin a destra. Questa è la vostra destra. Quindi dobbiamo saltare che cosa prima? Tutte le al Tutte le A. E allora che facciamo? Eh, dov'è lui? Leggo A, scrivo A, significa la lascio lì dov'è e vado a destra. Ok? Quindi, mentre siamo in Q1, la macchina cosa fa? C'è una pam pam, salta. A un certo punto la testina cosa incontra? Guardate l'immagine la vostra testa. B. Ok. Una volta che arriva alle B, la macchina per come è definita ora le supera o no? Per comeè definita ora? No, no, perché non c'è un arco che gli permetta di saltare le B. Quindi che facciamo? Aggiungiamo un'etichetta. Leggo B, scrivo B, vado avanti. Ok? Quindi in uno che stiamo facendo? Stiamo prendendo la testina e la stiamo spostando a destra. Ok, ci siete? Guardate il filmato nella vostra testa. La vedete la testina che va verso destra? Dovete proprio costruire l'immagine. Come facciamo a sapere che la testina è arrivata in fondo? Come fate a saperlo? Perché lo vedi nella testa. Ok. Questa è la cosa, se guardate l'immagine vostra testa, a un certo punto ci sarà un blank. Come faccio a sapere di essere in fondo? Perché la testina è arrivata là. Quindi che faccio? Leggo blank, lascio blank e vado indietro e vado in Q2. Ok. Dove si trova ora la testina? Attenzione, secondo. Quelli dietro state seguendo? Dove si trova la testina dopo tutto sto gran casino? Dove? All'ultima B. Ok, siamo sull'ultima B. Che ci dobbiamo fare con questa B? Dobbiamo chi ha detto toglierla? Dobbiamo cancellarla. Ok. Come si fa? Leggo B, scrivo blank e andiamo avanti o indietro? Indietro. E andiamo in Q3. Ok. A fianco dipl che direzione? Ah, sì, quello è scritta coi piedi, scusami. Ok, da così. Ok, chiaro? Ok, quindi adesso cosa abbiamo? La testina a destra. Ok. Dobbiamo andare dove? prima wait. So che lo sai un attimo. Qualcun altro che dobbiamo fare? Guardate il filmato nella vostra testa. Chi deve fare la testina? Dobbiamo andare a sinistra. Quindi, quali sono i primi caratteri che incontriamo andando a sinistra? C'è B. Scrivo B e vado dietro. Dopodiché che troviamo? Eh, c'è, scrivo a e vado dietro. Ok? A un certo punto arriveremo al bordo sinistro. Ok, questa la tiriamo indietro. La testina arriverà a un certo punto. Ok, come ci accorgiamo di essere in fondo a sinistra? Abbiamo una Come? Abbiamo un a cancellata? Eh, no, perché la A cancellata non ci sta più. Cosa c'è là? C'è un blank. Ok. A quale blank ci dobbiamo fermare? Al primo che incontriamo. Ok? Una volta che incontriamo il primo il primo blank, cioè quello più a sinistra, in quale stato di funzionamento della macchina dobbiamo andare? Ripartiamo tutto da cavo perché dobbiamo mappare una A su una B e quindi semplicemente facciamo questo. Leggo blank, scrivo blank e vado avanti. Ok? Quindi questo pezzo di macchina cosa fa? Cancella A e B uno a un. Ok? Fino a un certo punto. Ok. E quand'è che questa macchina si inceppa? Quando in uscita da Q3 spostando che abbiamo trovato un blank, lo spostiamo avanti e la macchina trova nuovamente blank. Vedetelo con gli occhi, vedetelo con gli occhi. Il nastro si è svuotato. C'è un blank, va avanti, c'è un altro blank perché la parte verde e la parte rossa si sono ridotte e non ci sta più niente. Ok? Quella per noi che cos'è? È il segnale che c'erano tante A quanto B. In quel momento noi accettiamo. Eh. Ah, quindi andiamo in Q4 che è lo stato accettante. Leggo Blank, scrivo blank e vado avanti. Ok. Per rispondere alla domanda del nostro collega, questa macchina può accettare stringhe strane tipo AB a AB? No, perché actually. Yes. Sì, c'è un errore qua. Sì. Perché non le può fare così? M m m Oplà. B interessante. Non ci avevo mai pensato. Blank blank dietro. Ok, questo è uno stato aggiuntivo. Come on, man. Ok, interessante. Non ci avevo mai pensato quella macchina, così come era definita, poteva accettare cose strane AB a AB. Sì, perché siccome mettevamo tutto eh come me lo segno qua tutto qui m doppia label lì, noi potevamo passare una A e una B, quindi devono essere in sequenza. Prima mi leggo le A, poi mi leggo le B. Ok? Se mettiamo due etichette là, è chiaro? Qua qua sto un po' saltando veloce. È chiaro perché prima era sbagliato? Perché se mettiamo quell'atto con due etichette A B, la macchina può vedere una qualsiasi sequenza di A e B e saltarle fino alla ricerca del primo plan. Un attimo. Se io voglio che ci siano prima tutte le A e poi tutte le B, allora mi aspetto prima le A e poi le B. Sì, ma cancellando gli estremi poi avrei avuto una B in testa pro Beh, quello sì, quello sì. Ok, è anche vero. Sì, sì, sì, sì. Ahah. Ma basta che lo fai una volta. Sì, sì, sì. Cioè, se io mi inceppo all'andata, mi incepperò al ritorno, quindi mi fermo dove in uno dei dei due versi. Ok. Ah, c'è altro? C'è altro? No, è chiaro per tutti come funziona questa macchina. Quindi la differenza rispetto agli automi a stati finiti è che questa macchina, a parte transire in un altro stato, questa macchina scrive sul nastro e sposta la testina in due direzioni. Ok? Questa è la differenza sostanziale di una macchina diuring rispetto ad automati finiti. Chiaro? Ok, adesso facciamo una pausa, 10 minuti, poi formalizziamo le macchine di touring e la condizione di accettazione. Allora, cavolo. Alright, guys, si riparte. Ok, ritorno velocemente sulle due macchine diing che abbiamo visto all'inizio. Ok. P la modifica che ho fatto è solo per avere la certezza che funzioni. Potrebbe funzionare anche quella di prima, però cioè mi ci devo mettere un attimo a capire se i casi strambi li accetto, li rifiuto, la variante sono più sicuro che funzioni. Tutto qua. Alrght allora questo è un modo più o meno, no, intuitivo di come funzionano le macchine di Touring. Quindi abbiamo visto che una macchina di Turing ha nel suo programma questa codifica. Dato lo stato corrente è il simbolo che sto leggendo, transisco in un altro stato, scrivo qualcosa sul nastro e eh sposta la testina a destra o a sinistra. Giusto una nota. Questo qui, questo simbolino qua, non è B1, è una virgola. Ok? Quindi è B/ Bola freccetta. Ok? Leggo B, scrivo B e mi muovo a destra. Ok? Quindi quello non è B1 B' e virgola. Ok? la mia virgola un po' strana. Alri, quindi quello che noi dobbiamo fare ora è formalizzare la computazione di una macchina di Touring e dare le condizioni di accettazione. Vi faccio notare che questa macchina, a differenza degli esempi che vedrete per esempio sulle lecture notes disponibili online, questa macchina non ha uno stato di rifiuto. Questa macchina rifiuta per incco. Questa macchina si blocca in uno stato non accettante e dice no. Ok? Ci sono altri modelli in cui abbiamo degli stati esplicitamente per il rifiuto. Alcuni le definiscono così. È totalmente equivalente. Le nostre macchine non hanno stati espliciti di rifiuto. Una macchina rifiuta se si inceppa, se si ferma in uno stato che non eh che non è accettante. Ok? La macchina si ferma in un certo stato quando la funzione di transizione non è definita per quella particolare combinazione stato simbolo. Sono in uno stato, leggo in un simbolo, vado nella mia tabella, la mia tabella non mi dice assolutamente nulla su cosa debba fare per quello stato e quel simbolo. Faccio mi fermo, la macchina si inceppa e siccome si blocca in uno stato non accettante, allora per noi la risposta è no. Ok? Allora, noi dobbiamo adesso formalizzare la computazione di macchina di Touring, che sarà semplicemente un'estensione di cose che abbiamo visto la volta scorsa per gli auteti finite, ok? Dobbiamo semplicemente farle un pelino più sofisticate, però cosa andremo a fare? andremo un po' ad arricchire quello che abbiamo già visto. Ok, partiamo innanzitutto con la definizione di macchina di Touring. Una macchina di Touring, esattamente come gli automi, è definita da alfabeti, ste cose qui. Ok, quindi vediamo un po' che cosa ci sta dentro. Una macchina di Touring è caratterizzata dall'alfabeto sigma che chiamiamo alfabeto di input, cioè sono i simboli che la stringa input può avere. Ci siete? Poi abbiamo un secondo alfabeto che chiamiamo gamma. Gamma è l'alfabeto di nastro. Cioè sono tutti i simboli, compresi i simboli dell'input, perché noi abbiamo che gamma è un sovrazieme di sigma. Sono tutti i simboli che possono stare a un certo punto sul nastro. contengono sia i simboli dell'input che eventualmente altri simboli che la macchina può scrivere. Perché, ad esempio, nel problema AMBM, quello che noi facciamo, prendiamo una A, la cancelliamo, prendiamo una B, la cancelliamo. Un'altra cosa che avremmo potuto fare è prendiamo una A, ci scriviamo una X di sopra, andiamo in fondo, prendiamo una A e B, ci mettiamo una Y di sopra, torniamo indietro. Ok? Quindi A e B fanno parte dell'alfabeto di input perché le stringhe in input possono avere questi simboli, ma sul nastro ci possono stare altri simboli che sono quelli che la macchina è in grado di scrivere, quindi X, Y, Z, casetta, nuvoletta, ok? Qualsiasi cosa. Prego. Blank è in gamba. Abbiamo quindi il simbolo blank che è il simbolo di bianco che è un simbolo che fa parte di gamma. Ok? Alright. Poi, come le gli automi a stati finiti abbiamo Q l'insieme degli stati, ok? Quindi sono tutte le pallette del nostro grafo di transizione sono gli stati di funzionamento della macchina che sono sostanzialmente come quelli degli aut finiti. Q è sempre Dov'è? È lui. Q è un insieme finito. La macchina ha un insieme finito di stati, un insieme finito di simboli input, un insieme finito di simboli di nastro. Ok? sono tutti insiemi finiti. Dopodiché c'è Q0. Q0 è uno degli stati di Q che è designato essere lo stato iniziale, cioè lo stato in cui la computazione della macchina parte. Poi abbiamo F. Fottinsieme di Q. sono l'insieme degli stati accettanti, ok? Possono essere più di uno. Ci sono formalismi che dicono che lo stato accettante è uno solo, che c'è uno stato che rifiuta che è uno solo, è tutta roba equivalente, ce la possiamo gestire come vogliamo perché sono inter traslabili ste cose. Si traslate, si traducono dall'uno all'altro. Ok? Quindi F è l'insieme degli stati accettanti e poi abbiamo delta che è la funzione di transizione, cioè che è il programma della macchina. Ok? Che cos'è delta? Delta è una funzione parziale, cioè che per alcune input potrebbe non essere definita che va da Q gamma verso Q gamma times sinistra destra. Quindi delta è una funzione che dati uno stato corrente e il simbolo che sto leggendo determina qual è lo stato successivo, qual è il simbolo che scrivo sul nastro, ok? E la direzione della testina, cioè se se ne va o a destra o a sinistra. È chiaro? Adesso dobbiamo definire formalmente la semantica delle macchine, cioè cos'è per noi una computazione, cos'è per noi una computazione accettante. Semplicemente estenderemo quello che abbiamo visto già per gli automi a Stati finiti durante la scorsa lezione. Ok. Questo qua per definire una computazione di una macchina di Touring dobbiamo definire cos'è una configurazione per M. Ok? Vi ricordate che per gli atomi a stati finiti avevamo introdotto questo concetto che era la configurazione dell'automa. Generalmente non si fa, l'abbiamo fatto perché ci viene comodo ora perché semplicemente dobbiamo estendere il concetto. Ok? Che cos'è una configurazione per una macchina di Touring? Vi ricordate intuitivamente che cos'era una configurazione per un automa stati finiti? Una stringa che aveva lo stato. A cosa serviva? atale la configurazione per un automa stati definiti era una stringa, ok? Che ci serviva a descrivere lo stato corrente di esecuzione della macchina, ok? Cioè, volevamo capire mentre sta macchina sta processando che sta facendo. Ok? E quindi che cosa avevamo? Avevamo uno una stringa che era formata da uno stato che era lo stato corrente della macchina e poi una serie di simboli che era la parte residua dell'input che la macchina stava processando. Ok? Intuitivamente per le Turing machine una configurazione è sostanzialmente la stessa cosa, cioè è una fotografia dello stato di avanzamento dell'esecuzione di una Turing machine su una certa strisca. Ok? Adesso, se noi ci pensiamo quali sono le informazioni che ci servono per catturare lo stato di avanzamento dei lavori di una tinguring machine, scusi. Posizione, ok? La posizione di cosa? Della testina. Ok. Quindi c'è una cosa particolare, esattamente come gli automi stati finiti, dobbiamo sapere in che stato siamo, ok? Dobbiamo sapere che c'è sul nastro ed è simile agli automi a stati finiti. Quella quella sequenza di simboli dopo lo stato nella configurazione degli DFA che che cos'era? era semplicemente quello che rimaneva sul nastro da processare. Quindi, esattamente come per quelle automi, dobbiamo sapere in che stato siamo, che ci sta scritto sul nastro e dove sta la testina. Allora, quello che noi facciamo è cambiare leggermente la configurazione rispetto a un automa a stati finiti. Negli automi a stati finiti cosa facevamo? stato resto della stringa. Allora, quello che noi facciamo semplicemente che lo stato, adesso facciamo qualche esempio, per le tinguring machine noi non lo mettiamo necessariamente all'inizio, lo mettiamo in mezzo alla stringa per dire dove sta la testina. Ok, tutto qua. Cioè, le l'idea di configurazione che abbiamo usato per gli automi stati finiti la ampliamo leggermente in cui diciamo lo stato invece di scriverlo sempre all'inizio, lo scriviamo in mezzo per dire cos'è che stiamo leggendo. Ok? Ad esempio, se riprendiamo la macchina di prima, eccetera, una configurazione per quella macchina potrebbe essere A Q1 BB. Che cosa significa questo? Questa configurazione qua ci sta dicendo che sul nastro i simboli non blank sono a B, che lo stato della macchina è Q1 e che noi stiamo leggendo questo simbolo, ok? Cioè, quindi semplicemente inserendo lo stato all'interno di questa stringa, noi siamo in grado di dire dov'è collocata la testina. Però l'idea è la stessissima, eh, dobbiamo sapere in che stato siamo, che cosa c'è rimasto sul nastro e dove stiamo guardando. Ok, questa informazione non serviva per il DFA perché perché un automa stati finiti leggeva sempre un solo simbolo che era il primo di tutto, poi li scartava uno dopo l'altro, no? Siccome qui possiamo andare avanti e indietro dobbiamo memorizzare un po' di cose. A parte lo stato e che cosa c'è sul nastro, dobbiamo memorizzare dove che siamo. Ok? Questa cosa qua, per esempio, è dov'è l'altro esempio? Ok. E c A B D Q1 blanc. Questa è un'altra configurazione in cui stiamo dicendo che su un nastro c'è ABB, che lo stato è Q1 e che Q1 sta leggendo il primo blank sulla sinistra. Ok? Quindi i blank nella configurazione li mettiamo solamente se sono indispensabili. Ok? Se scriviamo una cosa di questo tipo, quest'altra configurazione, per esempio, ci dice che la macchina si trova nello stato Q1 che Sul nastro c'è DB, però noi stiamo leggendo il primo blank alla destra di tutta la stringa. Ok? Quindi così noi scriviamo le configurazioni. Nelle configurazioni inseriamo il simbolo blank solo se è indispensabile. Se non ci serve non li inseriamo, ok? Perché si assume che il resto del nastro è vuoto. Ok? Allora, sì. sta facendo riferimento sempre alla che ha fatto prima. Sì e no, è giusto per dire change template. Oplà. Allora, adesso introduciamo un po' di definizioni che è tutta quella lista di cose che abbiamo fatto la volta scorsa. configurazione, configurazione accettante, computazione, computazione parziale, tutte ste cose qua, in maniera tale che blocchetto dopo blocchetto arriviamo a definire che cos'è una computazione per una macchina di Touring. Ok? Date due configurazioni C1 e C2 per una macchina M. Diciamo che C2 è, come si dirà in italiano il legal successor. Legal Successor di C1 rispetto a M e lo scriviamo così. C1, questo simbolo MC2. Se C2 è la configurazione che M raggiunge partendo da C1 facendo un solo passo. secondo la funzione delta. Ok? Quindi noi diciamo che date due configurazioni C1 e C2 per una macchina M. C2 è il successivo di C1 secondo la funzione di transizione di M. Se C2 è la rappresentazione di eh della configurazione successiva C1 secondo la funzione di transizione. Ad esempio, per la macchina che abbiamo visto prima, noi avevamo che ne so Q0 Aa BB. Se questo per noi è C1, noi avremo che C2 Q1B, perché la prima A l'abbiamo cancellata, siamo transiti in 1 e sul nastro è rimasto AB. Ok? Quindi questo è C2 e noi abbiamo che C2 segue C1. Secondo M. Scusate, se C2 è lazione successivao. Ah, se C2 è la configurazione che M raggiunge partendo da C1, da C1 facendo un solo passo secondo la funzione di transizione delta. Ok? Stiamo semplicemente complicando le cose, però quand'è che C2 è il successivo di C1 secondo la macchina M? Quando C2 è una fotografia dello stato di calcolo di M che descrive la computazione di M un passo dopo C1. Ok? Se è una cosa strana C2 non è successivo di F di C1. Ok? Chiaro? Ok. Quindi questo è uno altro la configurazione iniziale. Ok, definiamola prima parola e poi la la scriviamo. Adesso noi dovremmo andare a stabilire, a definire la semantica della computazione. Quindi dovremmo dire che la macchina parte nello stato appropriato, che fa una sequenza di passi appropriati, che arriverà in uno una configurazione finale, quella configurazione sarà accettante, eccetera, ci dobbiamo inventare, perché niente di tutto ciò è scolpito nella pietra, dobbiamo inventare delle definizioni che ci permettono di formalizzare la definizione di computazione accettante. Ok? Allora, fra le varie cose che ci dobbiamo inventare, siccome dobbiamo inventarci un modo per descrivere una macchina che calcola, partendo dall'inizio alla fine, quali configurazioni dobbiamo ci dobbiamo focalizzare iniziale, quella iniziale, cioè ci servirà descrivere la configurazione iniziale. Allora, ci inventiamo una definizione di configurazione iniziale. la configurazione iniziale di m su stringa w che è fatta dai simboli V1 VN. Qual è secondo voi? Q0 Q0 V1 V1 VN. Ok, abbiamo dato un nome a questa configurazione. In teoria sinistro di ci dovrebbe essere siccome non lo stiamo leggendo e non è indispensabile non lo scriviamo, ok? Cioè li scriviamo solo quando li stiamo guardando. Ok? Quindi dobbiamo dovremo descrivere la computazione di M. Sta m a un certo punto si dovrà fermare. Ok? Quindi dobbiamo definire cos'è una configurazione finale, ok? una configurazione finale per Migurazione. Che come la modellereste? Che che caratteristica deve avere una configurazione finale secondo voi? Qn e poi accanto black. Attenzione, attenzione attenzione attenzione. Il fatto che la macchina di prima che abbiamo fatto stesse cancellando roba, non è detto che lo facciano tutte, eh, perché un modo per decidere quel linguaggio è scrivere X Y, poi andiamo a vedere che è la stessa cosa, eccetera. Eh, cioè, quindi la macchina si può fermare che sul nastro c'è roba. Ragazzi, configurazione finale, non configurazione accettante. Cioè una configurazione che arriva al finale della computazione. Qual è l'ultimo passo che fa la macchina? Una configurazione finale è una configurazione che non ammette un successore secondo delta. Tutto qua. È una configurazione che non ammette un legal successor. Come cavolo scritto? Legal. Successor secondo M. Che cos'è? Prego. Quindi non per forza raggiunge uno stampare, no? Perché la macchina che abbiamo visto prima si potrebbe inceppare. Non so se avete visto quel film di Mazzio Capod Caponda, si inceppa la macchina, si ferma e no. Ok? La nostra è la nostra definizione. Su tanti libri troverete che le macchine di Turing hanno lo stato per dire no, cioè che quando devono dire no si spostano in quello stato, si fermano di no. Per noi una la macchina di Touring se si blocca da qualche parte spersa in questa foresta e non sa che fare, quello è no. Per dire sì, si deve arrestare nello stato in uno stato accettante. Ok. Secondo M. Sì. Ok. E delta fa parte di M. Ok. Alr. Where is it? Where is it? Delta. Che sarà una configurazione accettante? Configurazione finale che su accett una configurazione accettante e una configurazione finale. Una confettante. Prima o poi imparerò a scrivere su sto coso. Una con accettante è una confe. Quato è accettante. Ok, stiamo costruendo microblocchi, ok? Di definizioni, poi le mettiamo assieme e tiriamo fuori il senso, cioè la semantica della di una computazione per una macchina di Touring. Ok? Alright. Quindi abbiamo varie cose definite, sappiamo cos'è una configurazione, sappiamo cosa è il legal successor di una di una configurazione secondo una certa macchina, perché se la funzione di la funzione di transizione è differente, il successore di una certa configurazione sarà un altro. Macchine differenti fanno cose differenti. Ok? Poi abbiamo definito cos'è una configurazione iniziale, cos'è una configurazione finale, cos'è una configurazione accettante? È una configurazione finale non accettante o una configurazione rifiutante? Che sarà finale una configurazione finale il cui stato non è fra quelli accettanti. Ok. Definizione di computazione parziale. una computazione parziale di M è semplicemente una sequenza di configurazioni. C1 CM talé C1 è seguito secondo M da C2 che è seguito secondo M da C3 bla bla bla fino a CM. Ok? Quindi una computazione parziale per la macchina di Touring è semplicemente una sequenza di fotografie del suo stato di avanzamento, ok? In cui ogni ogni fotografia è sensata rispetto alla precedente. Ok? Scusi, ma è parziale perché cm Sì, CM non è configurazione finale perché non lo stiamo ripetendo ancora. Ok. Ok. Poi adesso definiamo che cos'è una computazione. Una computazione totale, se volete, o completa. Completa mi piace di più. Come vedete me lo sto inventando, eh, non è che sono cose eh t'ho detto di no. completa di M. A questo punto invece ci interessa la stringa su cui sta processando. Quindi una computazione di M su w computazione parziale D M C1 bla bla bla bla CM. tale che che caratteristiche deve avere questa computazione parziale per poterla chiamare computazione di m su wigali. Sì. Quindi C1 C1 è una configurazione iniziale di MU W e inoltre CM CM è una configurazione finale. cm è una configurazione finale. Ci siete? Alright. Quant andate avanti? Così. Vabboh, niente, vuoi far crescere una computazione. Una computazione di M su w è accettante. Se se è solo se CM è una configurazione accettante. CM è una configurazione accettante. CM è una configurazione. Ok. Noi diciamo, quindi, se noi diamo in input una stringa W a una macchina M, la macchina M accetta w V se la computazione di M su W va a finire in una configurazione accettata. È chiaro? Quindi abbiamo messo tutti i pezzettini per arrivare a dire quand'è che una macchina di touring accetta. Ok. Sì, abbiamo configurazione parziale con sequenza di configurazioni. Configurazioni legali successive. Sì, sì, qua l'ho messo. Eh, dai. Dov'è che sta? In fondo. Vedi? Ho messo il simbolo qua C1 seguito da C2 seguito da C2. È quel simbolino là che ci dice che è legale successivo. Sì. Ok. Quindi abbiamo detto che una macchina di Turing M accetto una stringa W se dando impasto W ad m la computazione di M va a parare in una configurazione accettante. Ok? Sì. Cos'è il linguaggio di una macchina di touring? Il linguaggio di una macchina di Touring M, che lo denotiamo LM, è l'insieme di tutte le stringhe W tali che Mentre processa W e lo scrive in questo modo sputa fuori 1 y s. Ok? Quindi cos'è il linguaggio di una macchina di touring? Il linguaggio di una macchina di Touring è l'insieme di tutte le stringhe sulla quale la macchina di Touring dice di sì. Ok? Vi ricordo che la macchina di Touring per dire sì su quelle stringhe si deve fermare e fermare in uno stato accettante, ok? E se la macchina di Touring su una certa stringa si arresta su uno stato non accettante? La macchina sta dicendo sì o sta dicendo no? Sta dicendo no. E se la macchina di Touring processando una certa stringa non si ferma mai, che cos'è? Sì o no? Non appartiene al linguaggio. Non appartiene al linguaggio perché perché non risponde. Perché la macchina non risponde. Cioè la macchina se non si ferma per noi è no. Ok. Però è un no un po' strano, vedremo poi nelle prossime lezioni, perché non è che si ferma per dirci di no, non si ferma mai, quindi non lo sapremo mai. È un è un po' un problema. Ok? Noi diciamo e queste sono le ultime definizioni, sia L un linguaggio, una macchina di Touring M decide, quindi vai che ve lo scrivo proprio. M decide, guardate la parola, il linguaggio L. Se e solo se per ogni stringa w se W appartiene ad L, allora M processando W si arresta e risponde 1. E v appartiene a L, allora M processando W si arresta e risponde zero. Quindi una macchina decide un linguaggio. Se su tutte le stringhe che appartengono al linguaggio la macchina si ferma e dice di sì. Su tutte le stringhe che non appartengono al linguaggio la macchina si ferma e dice di no. Una macchina accetta un linguaggio L. Se per tutte le stringhe che appartengono al linguaggio la macchina si ferma e dice di sì, sulle altre non abbiamo garanzia. Ok, recup. Una macchina di touring accetta un certo linguaggio L. Se quindi M accetta il linguaggio L, se per ogni stringa dei se per ogni stringa proveniente da sigma star accade che se V appartiene al linguaggio L, allora la macchina si arresta e dice di sì. Se la macchina se la stringa non appartiene ad L, allora la macchina non dice di sì. Cioè la macchina potrebbe dire di no, la macchina potrebbe non fermarsi. Ok? Quindi il fatto che una macchina decida un linguaggio ha una proprietà più forte per noi, perché si accetta ogni volta che deve dire si accetta il linguaggio L, significa che ogni volta che deve dire di sì, la macchina si ferma e dice sì. Se deve dire di no, la macchina potrebbe fermarsi e dire di no, potrebbe non fermarsi mai, eccetera. Se invece diciamo che una macchina decide un certo linguaggio L, allora questa per noi è una garanzia un po' più forte perché ogni volta che deve dire di sì si ferma e dice di sì. Ogni volta che deve dire di no, la macchina si ferma e dice di no. È chiaro? Quindi il fatto che una macchina decida e non semplicemente accetti un linguaggio per noi è fonte di una certa garanzia, perché ogni volta che noi diamo in input una stringa alla macchina, la macchina si fermerà per darci la risposta. Ok? Se invece la macchina semplicemente accetta un linguaggio L, non è che lo decide, ma lo accetta, significa che ogni volta che deve accettare, ecco perché usiamo questa parola, quindi ogni volta che deve dire di sì, la macchina si ferma e dice sì. Quando la macchina deve dire di no, non dà garanzia di risposta. Potrebbe fermarsi e dire di no, potrebbe non fermarsi. Prego. Se per una stringa che risponde di sì che non appartiene a L. Eh, quella è un'altra cosa. Noi definiamo così, dato un linguaggio, se esiste una macchina che ogni volta che su tutte le stringhe che appartengono a L si ferma e dice di sì e tutte le stringhe che non appartengono a L si ferma e dice di no. Allora, la macchina diciamo che sta decidendo il linguaggio. Se invece per un linguaggio Lina per le stringhe che appartengono al linguaggio si ferma e dice di sì, ma per le stringhe che non appartengono al linguaggio la macchina non dà garanzia di risposta. Sicuramente non sbaglia, non si ferma e dice di sì. O non si ferma proprio o si ferma e dice di no. In quel caso diciamo che la macchina sta accettando il linguaggio. Ok? Usiamo questi due termini distinti per far riferimento a queste due casistiche perché ci saranno linguaggi che saranno decidibili, cioè ci saranno ci sono linguaggi per i quali avremo macchine che ogni volta si fermano e ti dicono sì, no. Ci sono linguaggi che mostreremo essere accettabili ma non decidibili, cioè linguaggi per i quali abbiamo un algoritmo che se dobbiamo dire di sì lo sappiamo fare in tempo finito, se dobbiamo dire di no l'algoritmo potrebbe non terminare mai e quelli ovviamente sono problemi più tosti. Ok, prego. Si può affermare che quindi con noi stiamo a intendere che eh la macchina di touring va a valutare la classe di problemi, mentre con accetta va a valutare un singolo problema. No, no, no, no, no. Decidere un linguaggio e accettare un linguaggio fa sempre riferimento all'area semantica del stabilire se una stringa appartiene o meno a quel linguaggio. Quindi decidere L, cioè una macchina decide L significa che ogni volta che gli diamo una stringa input alla macchina e la macchina deve stabilire se la stringa sta dentro L o meno. Se la macchina M decide L su quella stringa W si fermerà sempre per dire o sì o no. Se la macchina ML lo accetta solamente, riceve in input W, la macchina se deve rispondere di sì lo farà in tempo finito. Se la macchina deve rispondere di no, potrebbe non rispondere mai. Quindi noi entrambe, diciamo, eh vengono accettate in input stringhe, soltanto che il decidibile racchiude l'accettazione e quindi essendo indecidibile significa che la macchina si ferma. Se una macchina decide un certo linguaggio L ti dà garanzia di risposta. Ma è più potente come termine, tra virgolette, la decisione o la citazione? Dipende cosa definisci per potente. Tu hai che i linguaggi accettabili sono un sovrazieme dei linguaggi decidibili. Adesso cosa definisci potente? E dipende dalla tua definizione. Quello che ti sto dicendo è che ci sono linguaggi per i quali abbiamo macchine di touring che sanno sanno fare il loro lavoro, cioè per ogni stringa si fermano sempre e ti dicono "Guarda, sì, guarda, no". Ci sono linguaggi che sono talmente difficili da da poter essere risolti, ok? Mi serviva un'altra parola, tale per cui là quello che al più una macchina di Touring è in grado di fare è che per le stringhe sulle quali deve rispondere sì, si ferma e si dice sì, questa stringa fa parte di L, però ci potrebbero essere delle stringhe per le quali la macchina di Turing le riceve in input, dovrebbe dire di no. Adesso la macchina di Turing non sbaglia. Cioè, non è che ti dice sì per no, però non ti risponde sì, nel senso che o si ferma e dice no o non si ferma proprio. Ma qual è il problema di queste macchine? Poi lo vedremo nella prossima lezione. Se noi abbiamo che un certo linguaggio è solamente accettato da una macchina e quello per noi è un po' un problema perché ok, facciamo partire l'algoritmo, sta girando da 2 anni, ancora non abbiamo risposta e che facciamo? aspettiamo. Cioè, quello tra un po' si ferma e dice sì o non si fermerà mai. Boh. Invece quando abbiamo la garanzia che il linguaggio è deciso dalla macchina, la macchina sta computando e sono 2 anni e lì noi sappiamo che prima o poi si arresta. Capite qual è la differenza? Quindi, in conclusione, problemi decidibili sono un sottoinsieme di problemi accettabili, sì che quelli poi li chiameremo semidecidibile, però son cose che vedremo nelle lezioni successive. Ok? Dopo l'introduzione delle macchine di touring, prossima lezione faremo un po' di esercizi su macchine di touring. Ok? Buona serata.