Ok so last time we saw the noneterministic model and today we are going to do some exercises on theministic model just to get some lunch Ok. So what today che insegno un altro corso in inglese e quindi bla. Eh, gradirei insegnarlo in inglese questo perché così mi verrebbe più facile, però no, mi hanno detto che non si può fare. Allora, abbiamo introdotto quindi nell'ultima lezione il modello non deterministico di macchine di Touring. Eh, ok, vi è chiara la definizione? Ok, la definizione formale, definizione formale di condizioni di accettazione, bla. La cosa interessante che abbiamo visto la scorsa volta è che quello che fa una macchina non deterministica può essere fatto anche, spieghiamolo meglio, i linguaggi accettati da una macchina non deterministica sono anche accettabati dalla macchine deterministiche tramite opportuna simulazione che perde una catastrofe di tempo, abbiamo visto, e quello è tuttora un problema aperto. se si possa far di meglio o o no. Ah, specifico giusto due cose, domande che mi hanno fatto al termine della lezione dell'altra volta, così poi ci mettiamo in linea per quello che ci serve domani. Poi penso di fare altre esercitazioni su macchine di Touring, a un certo punto ancora devo stabilire a che livello, eh. Ok, prima domanda. Ma ci stanno? Vi ricordate? Allora, avevamo che avevamo oplà, questo è l'insieme dei linguaggi ricorsivamente numerabili. Questo è l'insieme dei linguaggi ricorsivi. Vi ricordate la differenza? Linguaggi ricorsivi sono quei linguaggi per i quali esistono macchine di touring deterministiche o non, questo non ci importa, ormai sappiamo che hanno lo stesso potere, che sono in grado di decidere quel linguaggio, il che significa che ogni volta si fermano, cioè su ogni stringa in input, la macchina si ferma, da una risposta e dà la risposta corretta. Ok? I linguaggi nel re sono i linguaggi per i quali abbiamo macchine di touring deterministiche o non deterministiche che li accettano. Che cosa significa? Significa che sono quei linguaggi per le quali esistono macchine di touring che dato l'input, quindi una cosa su cui dobbiamo essere completamente espliciti, la macchina di touring non può dare risposte sbagliate, eh. Ok? Quindi riceve in input la stringa. Se la stringa è un'istanza sì del linguaggio, cioè quindi se la stringa appartiene al linguaggio, la macchina non può esimersi dall'arrestarsi e dire di sì. Ok? Cioè, non è che per non fare errori la macchina non risponde, ok? Cioè, se la stringa è una stringa, sì. Per quel linguaggio la macchina si deve fermare e deve rispondere di sì. Ok? Se la string input invece è una stringa, no, è un'istanza no del linguaggio, allora in quel caso la macchina può o non fermarsi proprio o fermarsi e dire di no. Cioè non è che può fermarsi e dare la risposta sbagliata. Quindi ogni volta che la macchina si arresta, la macchina si arresta e dà la risposta corretta. E quando deve rispondere sì, la macchina non può non dirlo. Cioè, non è che per costruire una macchina che accetti un certo linguaggio, ah, quindi non vogliamo fargli fare degli errori, andiamo on the safe side e non gli facciamo rispondere quando siamo un po' incerti, no? Cioè, la macchina sulle stanze sì non può esimersi dal dire sì. Ok, questa è una cosa fondamentale. La domanda che mi è stata fatta è: "Ma ci stanno linguaggi qua fuori R?" Eh, sì, ci stanno, li vedremo nelle prossime lezioni. Ehm, quindi R. Ok, abbiamo detto tutto. Alright, quello che facciamo oggi sono esercizi su macchine su di riconoscimento di linguaggi tramite macchine non deterministiche. E partiamo da questo qua che è uno che abbiamo appena visto. Eh, no, appena visto, abbiamo già visto. Ok. Ah, alright. Allora, noi vogliamo vedere, vogliamo apprezzare la differenza rispetto alla macchina deterministica. Ecco, quindi questo è il nostro scopo, vedere come ci semplifica la vita una macchina non deterministica rispetto a una macchina deterministica. Vi ricordate come l'avevamo risolto questo? Avevamo risolto che questa stringa per essere una stringa sì del linguaggio deve avere un numero pari di simboli. Quindi li contiamo, dividiamo per due, quella è la è la lunghezza di metà input, ci andiamo a selezionare W e poi andiamo a vedere che sia la stessa cosa. Ok? Questa era la soluzione deterministica. La soluzione non deterministica è molto più lineare, la vedremo stamattina e la sfruttiamo per ragionare un po' su come si progettano le macchine non deterministiche perché quello che vedremo oggi che il pattern il design pattern principale del design delle macchine non deterministiche si chiama gess and check, cioè la macchina gessa, cioè cerca di indovinare qualcosa e poi fa un check, cioè controlla che quello che ha indovinato, l'ha indovinato bene. Allora, la questione è: "Ma scusa, ma indovina o non indovina? Perché devo controllare quello che ho indovinato?" E vedremo da dove arriva questa cosa, perché, come sappiamo bene, non esiste un aggeggino che una macchina di touring non deterministica, no? Quello è solo un modello astratto di calcolo con una definizione molto particolare di condizione di accettazione. Ti dice una macchina i Touring accetta se esiste un modo per la macchina per accettare e quella cosa là. Quindi le dobbiamo dare una metafora che ci permetta di utilizzarlo in qualche modo. Questa è la cosa, ok? E la metafora che in genere si usa ed è quella che vi consiglio io, è la metafora dell'indovinare qualcosa e del controllare che quello che ho indovinato è corretto. Ok? Questa cosa ci permette di semplificare di molto il design delle macchine. Eh, lo vedremo stamattina e poi anche perché in alcune dimostrazioni poi ci servirà che le macchine facciano proprio questo tipo di lavoro. Indovinano roba, controllano roba. Ok? Questo è il modo in cui usiamo le macchine non deterministiche, è il modo più semplice per farlo. Ok. Ok. Partiamo da qui. Partiamo quindi da da questo linguaggio. Ovviamente ci stanno tanti modi per riconoscerlo. Vi ve ne propongo uno. Ok? Questo qua lo facciamo assieme, poi lascio proporre a voi più cose dei prossimi esercizi. Allora, l'idea è sostanzialmente questa. Una macchina di Touring non deterministica non ha necessità di conoscere per certo qual è il mezzo dell'input, cioè noi avremo questa roba in input, quindi che ne so 0 1 qua c'è la metà. La macchina non deterministica ha, tra virgolette il potere di sentire, no, era un feeling di quando arriva in mezzo. Ok? Cioè la macchina lo sa, diciamo questo, quando arriviamo a metà la macchina lo sa che quella è la metà. Adesso poi vediamo come tutto ciò si ricollega alla definizione formale, perché ovviamente non è che la macchina può sapere questa cosa, però nel momento in cui la pensiamo possiamo pensarla come se, questo è il gioco, no? come se la macchina lo sapesse. In realtà la macchina non sa assolutamente niente, però il design della funzione di transizione che facciamo è tale per cui che tale per cui la la macchina possiamo considerarla che come se sapesse quando arriva il momento della metà della stringa. Ok? E facciamo così. Allora, abbiamo che la stringa W deve essere almeno un carattere. Allora, quello che vi propongo è sì prendere questo primo pezzo, ricopiarlo su un secondo nastro, dopodiché usare lui per controllare che sia nella seconda parte. Ok? Cioè questa è l'idea. Il trucco di questa macchina è che la macchina saprà quando è arrivato il momento che è la metà e lì si ferma. Dice "Ok, ne ho abbastanza. Ok, ho mangiato abbastanza spaghetti per oggi". Vado oltre. Ok. Alri. Q0 stato iniziale. Allora, abbiamo detto che come primo pezzo la macchina inizia a ricopiare, cioè come prima fase di computazione la macchina ricopia dal nastro di input la porzione di W di interesse. Ok? E come si fa? Quindi deve leggere almeno un carattere. Quindi è sul primo nastro ci sta alfa, lascio alfa e vado avanti. Sul secondo nastro c'è blank, scuo alfa e vado avanti. Ok? E andiamo in Q1. Alfa è un carattere tra 0 e 1. Ok? Quindi la macchina prende un carattere da primo nastro, lo appiccica sul secondo nastro. Ok? Dopodiché lo fa per tanti altri caratteri. Ok? Quindi sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è beta, scrivo alfa e vado avanti. Ok? Quindi che sta facendo la macchina al momento? Scopia e colla. Prende quello che ci sta sul primo nastro, lo ricopia sul secondo nastro, ok? E lo fa per un certo numero di caratteri. Ok? A noi ci interesserebbe che la macchina facesse questa cosa per V per W. Esattamente. Non di più, non di meno. Come facciamo a a garantirci questo? Ce lo garantiamo così, che la macchina a un certo punto sa che è arrivato il momento di fermarsi. Ok? Lo indovina? Dice "Ok, qua ci sono". Qua si ferma e si sposta in un'altra fase di computazione. Come facciamo? Come fa a saperlo la macchina? Sul secondo nastro c'è blank, lascia blank e torna indietro e va in Q2. Ok? Allora, vi faccio notare che qui c'è il primo pezzo di non determinismo, eh perché siccome su questa etichetta non abbiamo scritto niente, su questa qua non abbiamo scritto niente relativamente al primo nastro, lì sostanzialmente stiamo intendendo sul primo nastro c'è qualsiasi cosa, lasciamo lì com'è e teniamo la testina ferma. Ma quella roba là è in contrasto su questo, che sul primo nastro ci può essere qualsiasi cosa. Quindi da questo lato avremmo su primo nastro c'è qualsiasi cosa e sul secondo c'è blank. Di qua abbiamo sul primo nastro c'è qualsiasi cosa e su secondo nastro c'è blank. Ok? Quindi qui ci sta un determinismo. Lì la macchina può decidere se continuare a copiare o è arrivato il momento della metà della stream. Ok? Questo è completamente a discrezione della macchina. Ok? Nel momento in cui, quindi, il trick, la rule ofble che vi do è nel momento in cui progettate una macchina di touring, pensate come se la macchina sapesse quando fermarsi, cioè la macchina lo indovina. Ok? Quindi è la fase di guess. La macchina lì sta indovinando. È come se qualcuno gli dicesse "È arrivato il momento di fermarsi". Ok? Non lo deve vedere dal nastro. La macchina lo capisce. Ok? Come fa? Eh, lo fa. Ok. La macchina lo fa. Ok. Una volta che la macchina ha deciso di transire verso Q2, quindi ha deciso dov'era il mezzo della stringa, dobbiamo far sì che la macchina controlli, qui sembra un po' la parte controintuitiva, che la macchina controlli di aver indovinato bene. Dice, "Ma scusa, ma se indovina o non indovina? Perché devo controllare di aver indovinato bene se la macchina indovina? Allora, questo è un piccolo prezzo che dobbiamo pagare per poter ragionare sulle macchine come se sapessero indovinare. In realtà le macchine non sanno indovinare. Possiamo pensare, possiamo usare questa metafora che la macchina indovina nel momento in cui noi controlliamo ogni volta che ciò che abbiamo indovinato è corretto. Ok? Quindi, se qualsiasi cosa che indoviniamo, che chiamiamo ci appiccichiamo una fase di controllo di check che quello che abbiamo indovinato è corretto, allora possiamo approcciare le macchine non deterministiche come se sapessero indovinare, anche se fattivamente non lo fanno. Ok? Quindi questa è la cosa. Possiamo utilizzare la metafora dell'indovino, cioè la metafora del la macchina sa quando transire. Se a ogni cosa che la macchina indovina noi ci appicciniamo una fase di controllo. Ok? Se facciamo l'uno e l'altro overall questa cosa possiamo percepirla, pensarla come se la macchina stesse indovinando. Ok? però va sempre divisa in due. Se noi facciamo solo gess e non controlliamo, la macchina può fare un casino. Ok? Se facciamo guessamo indovinando, allora possiamo pensare che la macchina stia indovinando correttamente, ok? Questo è importante, solo gess non basta, serve il guess più il check. Ok? e vedremo che le macchine non deterministiche così funzionano, gessano, cercano, gessano, cercano, fanno dei guess sofisticati, fanno dei controlli più sofisticati. Ok, ma è così. Alrght come qual è il Adesso lo facciamo assieme. Quindi la macchina qua ha fatto il guess della posizione, dopodiché deve controllare che ha beccato il punto giusto. E come fa? riavvolge il secondo nastro, quindi c'è alfa, lascio alfa e vado dietro fino a quando sul secondo nastro c'è blank, lascio blank e vado avanti, ok? E vado in Q3. Quando siamo in Q3 avremo la testina su primo nastro lasciata qui e la testina su secondo nastro lasciata qui. Dobbiamo adesso semplicemente controllare che quello che ci sta sul primo nastro e quello che ci sta sul secondo nastro sono la stessa cosa. Tutto qua. Ok. Ah alright. Mettiamo qua che c'è spazio. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è alfa, lascio alfa e vado avanti. Ok? Chiaro per tutti? Dopodiché, come facciamo a essere sicuri che quelli là sono esattamente gli stessi? Sul primo nastro c'è blank, lascio blank e sto fermo. Sul secondo nastro c'è blank, lascio blank e sto fermo. Andiamo in Q4 e accettiamo. Ok, chiaro? Semplicissima questa macchina. È chiaro come funziona? Intuizione del funzionamento di questa macchina. Questa macchina parte sulla string in input, inizia a copiarsi la prima parte di W. Magicamente decide che la W è finita. riavvolge il secondo nastro, dopodiché controlla secondo nastro, il primo nastro. Bene che siamo la stessa cosa. Ok, chiaro? Questa qui, questa qui è la fase di gess. Lì la macchina indovina dov'è la metà della stringa. Qui tutta questa seconda parte controlla che quello che si è ricopiato sul secondo nastro è effettivamente il punto intermedio. Ok? Quindi, siccome facciamo l'uno e l'altro, allora possiamo pensarla come se la macchina avesse indovinato. Ma la questione a questo punto è chiaro per tutti come funziona questa macchina? Prego. Ma è possibile che la macchina indovini male o vediamo per assunto che no? Mo mo faccio vedere com'è. Se se si fa gess e check la macchina non può indovinare male. Se se si fa solo gess la macchina può indovinare male. Se si fa gess in cerk la macchina non può indovinare male per una ragione precisa sulla definizione di accettazione che adesso vediamo assieme. Ok? Però quello che il primo messaggio che voglio che vi arrivi è nel momento in cui dovete design, dovete progettare macchine non deterministiche, ogni volta che ha una fase di gess associate a una fase di check, potete sostanzialmente considerare la macchina capace di indovinare cose. Ok? Ma lo potete fare solamente se queste cose le fate a coppia. Per ogni guest ci deve essere un jack, senò la macchina può combinare cose strane. Ok? Alrght. Una domanda. In questo caso la soluzione da questa a macchina deterministica efficienti che abbiamo già fatto e quella questa è leggermente più veloce perché se prendiamo questa transiamo in macchina terministica il risultato è equivalente che abbiamo già fatto o è più lento? La simul dipende dalla simulazione. La simulazione di quel che abbiamo visto la scorsa volta in aula. Se noi prendiamo questa macchina e la simuliamo, ok? Nel modo che abbiamo visto in aula, il risultato è più lento dei della macchina deterministica che abbiamo disegnato from scratch. Perché la macchina deterministica, la simulazione di questa macchina tramite una macchina deterministica mi farebbe fare tutte le possibilità, il primo simbolo, al secondo simbolo, al terzo simbolo e tante di quelle sono sbagliate. Ok? La macchina deterministica che invece noi abbiamo progettato direttamente, quella là si calcola la metà, cioè era furba, non è che la trovava a caso, si contava la lunghezza della stringa, la divideva per due e a quel punto stava dove stava la metà, però se la doveva calcolare. La simulazione standard deterministica di questa macchina non deterministica è lenta perché proverebbe tutto. Tanto non è che sia proprio necessario. Eh, cosa differente è quando invece si deve beccare una sottostringa e in quel caso dobbiamo provare tutti i punti di partenza, però ho preferito questo esercizio perché ci fa ragionare un po' di cose su un po' di cose, ok? Perché? Quindi ora noi ci vogliamo spostare su questa questione. Ma questa macchina così come è progettata può indovinare male o non può indovinare male? Allora, la ragione è questa. Allora, un attimo che ve lo segno qua. Qui c'è il yess. Ok. Questo è il check. Alrght. Allora, come abbiamo detto le macchine non deterministiche in realtà non esistono. Non esiste niente lontanamente avvicinabile a una macchina non deterministica. eh sono solamente dei modelli di calcolo per farci ragionare su alcune cose, tale per cui noi abbiamo una definizione formale formale di condizione di accettazione di una macchina di touring non deterministica. una macchina di Turing non deterministica, accetta il proprio input se nella nel proprio computation 3 c'è un computation branch accettante e questa è la definizione. Ok? Allora, quello che dobbiamo andare a fare è guardare il computation 3 di questa macchina. Ok? Alright. Quindi noi abbiamo l'ID Z0. Facciamo intuitivo, eh, troppo precisi non possiamo essere. Ok. Configurazione iniziale della macchina, noi sappiamo che è praticamente eh quella configurazione che è all'avvio della macchina. La macchina sta in Q0, c'è tutta la stringa sul nastro di input, ancora non è stato letto niente. Ok, come potete vedere qua, quindi noi partiamo da qui. Primo passo è indistintamente copiarci un carattere, ok? Quindi da un ID 0 andremo verso un altro ID nel quale la copia di questo primo carattere è avvenuta. Ok? Chiaro? Su lì la macchina non ha scelta. Da quel momento in poi la macchina può scegliere se copiare il carattere corrente o passare alla fase di computazione successiva, capito? Quando siamo in Q1, la macchina lì o copia o passa, ok? E lì a scelta. Quindi l'albero di computazione è qualcosa di questo tipo, vedete? Sì. o copia o check. Ok, quindi o mi sposto verso il check o faccio la seconda copia, cioè copia il secondo carattere. Una volta che in questi D, siccome è ancora in Q1, la o se ne copia un altro o inizia una fase di check. Chiaro? In questo qua pure o copio o cecco chiaro come sta funzionando questa cosa? Cioè la macchina parte in Q0. In Q0 ha una sola scelta. La macchina copia il primo carattere. Dal secondo carattere in poi la macchina può fare due cose: o copia un carattere in più o inizia la fase di check. Ok? La fase di check, vi faccio notare è completamente deterministica, cioè cose strane non ne possono accadere per come l'abbiamo progettata noi. Qui ci sono macchine più sofisticate nel quale anche il check deve usare un guess, però quel guest deve sempre essere eh accoppiato a un'altra fase di check, senò non se ne esce. Ok? Ogni guess ha necessità di un jack, quindi ok, la vedete? Alright. Quindi la macchina all'inizio copia il primo carattere e non può fare altro. Dopodiché quando sta in Q1 o fa una copia del secondo carattere o inizia una fase di check. Queste fasi di check ovviamente sono delle catene di instantaneous description, non è solo una ID, ce ne sono tante, ok? Perché devo riavvolgere il secondo nastro, devo iniziare a verificare che primo e secondo nastro sono la stessa cosa, eccetera e mi sposto verso lo stato accettante solamente se il contenuto del secondo nastro è equivale alla seconda parte della della stringa. Ok? Quindi in realtà questo qua sono catene di ID, non è uno solo. È chiaro? Allora, focalizziamoci su questi rami, su questi rami di controllo. Nei rami di controllo dove la macchina ha indovinato male. Cosa possiamo dire dell'ultimo dell'ultima ID di questa catena? Supponiamo che qui è la macchina abbia indovinato male. Che cosa possiamo dire di questo ID? È uno stato finale non accettante. Ok. E ce lo segniamo, eh? Ok. Supponiamo che questo qua sia un altro ramo dove aveva sbagliato. Ok. Cosa possiamo dire dell'ultima ID di questa catena? La stessa cosa è uno stato finale non accettante. Ok? Supponiamo invece che questo sia un ramo del guess giusto. Ok? Cosa possiamo dire di questa ultima ID della catena? Che è uno stato finale accettante? Ok? Alri, allora perché noi vogliamo accoppiare fasi di gess a fasi di gent? Perché quello che noi vogliamo ottenere è sostanzialmente un albero di computazione con questa forma, cioè un albero nel quale i rami al di sotto di un gess, cioè i rami a balle di un gess, vadano a finire in uno stato accettante solamente se il punto dove la macchina sta facendo la diramazione è un punto corretto. Ecco perché mettiamo il check, in maniera tale che rami come questo qui, questo qui sono tutti computation branches dentro l'albero di computazione che vanno a terminare in configurazioni non accettanti. Di conseguenza la macchina non può dire di sì se calcola facendo questa cosa qua. Quindi noi mettiamo il check per far sì che la macchina possa dire di sì solamente se esiste un modo per accettare. Ok? Quindi, nel momento in cui noi noi che cosa facciamo intuitivamente? A che serve il check? Il check serve a filtrare via passi di gess sbagliati. Ok? A quello serve il check. Il check serve a dare questa forma particolare al all'albero, no? In cui avvalle di una cosa che sto indovinando devo verificare che la cosa che ho indovinato sia corretta perché perché voglio filtrarmi via gli errori. Se io faccio quindi, quindi la macchina non è qui che sta indovinando il punto. La definizione della macchina è che il suo albero di computazione ha questa forma. Però se io l'albero di computazione faccio in modo che su tutti i computation branches sbagliati andiamo a sbattere contro un muro e lasciamo liberi solamente le computazioni corrette tramite il check di quello che abbiamo fatto, allora è come se la macchina stesse indovinando il punto esatto. Ok? Sì. Potremmo pensare che la macchina stia facendo tutti i tentativi contemporaneamente vedere se ci sono la puoi pensare così, ma è sempre una metafora. Puoi usare la metafora che ti aggada di più. Ok? Quello sì, puoi farlo. Io, per esempio, la il mio modo di pensare alle particiche è più di tipo seriale, nel senso per me, ma è sempre una metafora, eh, dipende da come vi trovate voi meglio a ragionare. Per me, a me viene più semplice pensare in maniera seriale che indovino il punto e poi controllo. Un altro modo per pensarci è quello che dice lei. La macchina li tenta tutti e vede se c'è un modo da accettare. l'uno o l'altro vanno bene perché sono metafore, ok? Perché la definizione di accettazione dei Turing è diversa. È esiste un la macchina accetta se esiste un modo per accettare. Adesso se le torna comodo progettare una macchina di touring pensando al fatto che la macchina si parallelizzi a un certo punto è una questione di comodità. se viene comodo lo può fare. A me personalmente mi è più comodo pensarlo in maniera seriale, cioè la macchina indovini e poi controllo quello che faccio. Ok? Perché i nei problemi di complessità che vedremo nella seconda parte di questo corso è molto più semplice pensarla così: indovino sta cosa, controllo. Indovino sta cosa, controllo. Ok? Ci saranno tanti problemi, che ne so. Hamilton, lo conoscete? Ecco, è un classico problema NP NP completo. Come lo fa una macchina non deterministica a risolvere? Gessa il ciclo e controlla di averlo gessato correttamente. Questa è la soluzione di Miltorian Cy. Questo dimostra che Milton Cycle sta in MP, capito? Cioè, senò dovremmo pensare la macchina prova tutti i patti che si può fare, eh, cioè dipende come vi trovate bene. Io mi trovo bene a pensar la seriale. La macchina indovina il ciclo, controllo di aver indovinato correttamente. Ok, tutto qua. Che poi alla fine è lo stesso paradigma di qui, che ne so, eh, qualche altro problema classico su grafo. Cos'è un indipendenetto di un grafo, lo sapete? Un vertex cover, una una cricca. Una cricca, questa la sapete che è è un è un sottografo completamente connesso. Ok? Come faccio a stabilire se esiste un sottografo completamente? Questo è un altro problema NP completo, li vedremo tutti nella seconda parte di questo corso. Come faccio a sapere che ci sta una cricca o click di taglia K dentro un grafo? mi me la ghesso, controllo che la il sottografo che mi sono gessato è completamente connesso. Finito. Ok, questo prova che il problema sta in NP, però ok, queste sono tutte cose che vedremo nelle prossime settimane. Quindi il mio consiglio è concentratevi su eh su una metafora, ok? Cioè, perché l'importante è avere metodo nelle cose che fate. Se una metafora vi viene meglio di un'altra, stick to that one. Ok? E la usate, vi esercitate. L'importante è che la metafora sia utile, nel senso che non vi porti fuori strada. Eh, se la metafora che usate non vi è utile, magari ne provate un'altra. Cioè, io mi sono sempre esercitato su questa, mi trovo bene su questa, continuo a usarla. Ma perché la macchina indovina? No, perché la macchina definita in questo modo è come se indovinasse. Ok, tutto qua. Alright, altro esercizio. Come siamo messi a tempi? Male. Alrght. Questo è un esercizio simile a uno che vi avevo lasciato per casa. Ok. A B. Vi chiedo di tenere duro un po'. Ritardiamo un po' il break oggi, eh. Se vuole saltarli prima. Saltare a quest'ora. prima finire prima. Sì, sì, mi manca l'aria poi. No, no, no, lo capisco. È una è una proposta, è un'opzione. Certo, certo, certo. Stavo giusto scherzando. Quindi AB a A B A e B appartiene 01 plus e poi A è una sottostringa di B oppure A reverse è una sottostringa di B. Ok? È chiaro? Allora, abbiamo queste stringhe con questa forma. C'è A, un cancelletto, c'è B. Noi dobbiamo verificare che A sia dentro B da qualche parte o il contrario di A sia dentro B da qualche parte. Ok? È chiaro il task? Allora, ovviamente questo ha varie soluzioni, come tutti gli esercizi che vediamo hanno infinit infinite, ma tante soluzioni di sicuro. Io ve ne propongo una. Qualsiasi che funziona va bene. Ok. Alri. Allora, quello che vi propongo è sostanzialmente questo. Eh, volevo mostrarvi questo modo di funzionamento della macchina. Qui abbiamo a che è 01 1, poi c'è 10 1 1 e qua abbiamo 00 1 1 1 1 1 0 bla bla bla bla. Ok? Questo è A e questo è B. Allora, la mia idea è questa. Prendo A, lo ricopio sul secondo nastro. Ok. Dopodiché, non deterministicamente decido fin da subito se in B sarà o A o A reverse. Chiaro? Cioè questo è il trucco. La macchina può indovinare quello che vogliamo se glielo facciamo controllare. Quindi la macchina fa questo, si ricopia sul secondo nastro. Passato il cancelletto, magicamente la macchina decide se quello che dovrà andare a vedere è A o A reverse dentro B. Dopodiché, non deterministicamente troverà l'inizio di A o di A reverse dentro la stringa, fa un controllo e chiude. Ok? Quindi la trovavo interessante perché la macchina qui per esempio può decidere fin da subito se quello che andrà a verificare è a o a reverse. Ok? e poi vi faccio vedere una seconda modalità. Ok? Alright. Quindi Q0 stato iniziale. Oplà. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro che ci sta? Blank. Scriviamo alfa e andiamo avanti. Ok. Questo lo dobbiamo fare per tutti i caratteri. Eh un zero a ci serve che sia almeno un simbolo 01 plus. Ok? Quindi facciamo la stessa cosa. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo c'è alfa, lascio alfa e vado avanti. Ok. Primo momento di gess. Come? Non, però non ho capito, scusi. Non esce la cop di tutto tutto a lo facciamo. Nel momento in cui arriviamo al cancelletto, a parte finire la copia di A, nel momento in cui superiamo il cancelletto, la macchina decide se in B sarà A o A reverse. Un ramo, avete visto che ci ho fatto questa bella biforcazione? Un ramo va verso la parte di computazione dove la macchina fa un check da un altro ramo fa eh la parte di computazione dove c'è a reverse. Ok. Ah sì sì sì sì. Y eh vediamo se ce la facciamo. No. Ok. Grazie. Sul primo c'è cancelletto, lascio cancelletto e vado avanti. Sul secondo c'è blank, lascio blank e vado dietro. Facciamo il rano di sopra per il controllo di A. Quindi andiamo in Q2, riavvolgiamo A sul secondo nastro, quindi c'è alfa alfa e vado dietro fino a quando finisce. Sul secondo nastro c'è blank, lascio blank e vado avanti e andiamo in Q3. Ok, chiaro? Quindi, qual è la situazione corrente su questa parte di rame? Eh, vedete che questo quello di sotto l'ho lasciato l'ho lasciato pendente. Ok? Quindi la parte della computazione di sopra è dove la macchina decide che quello che deve cercare è A. Quindi che cosa fa? Siccome sul secondo nastro aveva scritto A, lo riavvolge, posiziona la testina sul primo simbolo di A, poi abbiamo la testina sul primo simbolo di B. Dopodiché la macchina deve cercare dentro B l'inizio di A. Chiaro? Poiché questa macchina è non deterministica, l'inizio di A dentro B lo indoviniamo. Quindi facciamo una cascata di due gess. C'è un primo gess in Q1 nel quale decidiamo se controlleremo A o A reverse. Dopodiché dobbiamo controllare, ad esempio, la presenza di A. Per controllare la presenza di A ci serve stabilire dove inizia A dentro B. Come facciamo a farlo? Indoviniamo anche quello. Ok? Guardate, cioè noi possiamo indovinare tutto quello che vogliamo fintanto che controlliamo quello che stiamo indovinando. Ok? Questo è la cosa importante. Quindi Q3 inizio ad avanzare sul primo nastro. Sul primo nastro c'è alfa. Lascio alfa e vado avanti e mi salto tutti i caratteri che non mi servono. Ok? È chiaro che faccio in Q3? La dovete vedere, eh, sennò non funziona. Qua c'abbiamo il nostro bel cancelletto. Qua c'è la testina su B. inizia a saltarmi roba fino a quando magicamente stabilisco che da lì in poi ci sta. Chiaro? Quindi questa cosa si fa in Q3 nel quale su questo anello c'è alfa alfa e vado avanti fino a quando sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è alfa, lascio alfa e vado avanti e vado in Q4. Chiaro? A quel punto quello è un altro punto di gess, eh, quindi abbiamo fatto due gessi in cascata. Qua abbiamo ghessato se era a o a reverse quello che dovevamo cercare e poi abbiamo ghessato dov'è che inizia a dentro B. Una volta che l'abbiamo indovinato e questa questa parte di guest sta nel passaggio fra Q3 e Q4. Dentro Q4 dobbiamo iniziare la fase di check, cioè dobbiamo verificare che nel punto dove abbiamo scelto ci sia effettivamente A. Come si fa? Si fa come abbiamo visto prima, sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è alfa, lascio alfa e vado avanti. Ok? Come faccio a sapere che ci sta proprio a che c'è tutto a sul primo nastro? Qual è la condizione di uscita sul quarto nastro? Esattamente, bravissimo. Quindi sul secondo nastro c'è blank. Lascio blank e sto fermo e andiamo in Q5. Ok, abbiamo guardiamo un po' il filmato, abbiamo controllato che c'era qua. Abbiamo finito, siamo rimasti in mezzo a B. Ci rimane l'ultima cosa da verificare su B che è non ci siano cancelletti strani in fondo. Quindi portiamo la testina in fondo e accettiamo quando arriviamo su blank. Ok? Quindi in Q5, sì, in Q5. Sul primo nastro c'è Alfa, lascio Alfa e vado avanti. Sul primo nastro trovo blank, lascio blank e sto fermo e accetto in Q6. Vedete? Sì, vedete? Ok, quindi questo è il pezzo di ramo di computazione nel quale la macchina, dopo aver deciso di controllare A dentro B, decide pure dove sta A dentro B e fa la verifica che ci sia proprio A dentro la B. Ok, è chiaro? Ci manca l'altro. dice è iniziato su Q4. Eh, è iniziato nel ramo che transisce fra Q3 e Q4. In in Q3 la macchina può stabili ha due scelte. Può continuare a saltare caratteri sul primo nastro o iniziare a controllare i caratteri sul primo nastro. Quindi in quel ramo là che esce da Q3 va verso Q4, è lì dove la macchina fa il guess e il check sta iniziando nel momento in più la su. Ok, però è ovviamente il check inizia già in quel ramo. Nel momento in cui c'è iness della posizione la macchina sta anche iniziando il controllo. Ok, poi c'è tutto il resto. Sì, avremmo potuto farlo anche con due etichette. direttamente nell'anello di Q3 oppure serve fare un altro aguntivo che ci porta al nuovo statico? Ah, dice dice fra Q3 e Q4 la fase di check. Sì, saressimo grap e il controllo d'avanzamento su Eh, no. Mh, non entro nel dettaglio. Ora glielo spiego alla fine di questo perché voglio metterlo insieme. Buona domanda. insieme a un altro esempio che voglio farvi per commentarvi eh perché voglio spiegarvi una cosa importante di questo esercizio. Sì, non capisco una cosa, ma se noi abbiamo una transizione tra Q3 a Q4, cioè noi abbiamo la stringa e dopo il cancelletto trova il primo carattere che corrisponde, quindi andiamo avanti, però dopo il secondo carattere non corrisponde, cioè non ci blocchiamo lì, però la macchina se non è il punto corretto è quello che abbiamo spiegato prima. Qui la macchina no potrebbe avere che si copia solo il primo carattere di W, decide di andare avanti e quei due per caso vanno bene, anzi la questione è che la macchina No, se si fa in sequenza un gess e un check, la macchina gessa la posizione corretta, così la può pensare Se è il primo carattere è lo stesso, ma è farlocco, cioè non è il punto preciso, il punto esatto dell'inizio della ripetizione di la macchina quello lo salta, ma non perché lo sa, perché c'è una fase di check successiva, quindi la macchina per definizione che accetta solamente se c'è un modo per accettare, troverà il modo di accettarlo nel momento in cui filtriamo gli errori. Questa è la cosa. Quindi, ma la macchina che fa indietro? No, la macchina non è che torna indietro. Questa macchina ha possibilità di scelta, sceglierà quella giusta se ce n'è una giusta. Quindi in caso di eh presenza di un'attenzione la macchina terministica c'era sempre la il percorso ctimale dal principio. Anche allora se l'ero pone così non posso fare l'evoluzione questa frase? Posso analizzarla esattamente? Ok. mi dice, "Ma allora io posso ipotizzare, ragazzi, questa è una cosa importante, eh, perché c'è un presupposto linguistico in questa in questa frase che mi fa capire una serie di cose." Ma allora la macchina non deterministica, nel momento in cui la possibilità ha la possibilità di scelta fa la scelta giusta fin da principio. L'utilizzo della della parola fin da principio mi fa pensare che nella sua testa lei pensi che ci sia una consequenzialità di cose, nel senso che la macchina potrebbe sbagliare e tornare indietro per provare un'altra cosa. La macchina non deterministica non fa né questo né néaltro perché la macchina non ci sta. Noi abbiamo questa definizione formale di condizione di accettazione di una macchina non deterministica, che è che la macchina accetta il proprio input se fra tutti i computation branches del computation 3 ce n'è uno accettante. Ok? Adesso se fra tutte le possibilità una di quelle l'accetta la macchina dice di sì, però la macchina fisicamente interprende quel percorso? No, perché la macchina non c'è. Però quello che possiamo fare è pensarla metaforicamente. Possiamo pensarla metaforicamente come se la macchina prendesse la decisione giusta. È come se, ma non è che la macchina ha veramente questa sequenzialità temporale perché non c'è, cioè non c'è un prima o un dopo. Per dire è come se io facessi, no, questaaltra domanda. Ho una macchinouring non deterministica, gli do un input sul quale deve rispondere no. In quale dei computation branch io mi aspetto di vedere la macchina bloccata? È chiara la domanda? Abbiamo una macchina non deterministica, gli diamo in input un'istanza no del linguaggio. La macchina si deve bloccare. In quale de computation branch la macchina si blocca? Cioè, in quale vedremo che la macchina è andata a fermarsi? Su quale scelta si è andata a infognare? Su nessuno. Perché la macchina non c'è? Cioè è quella la questione fondamentale. La macchina fisicamente non esiste. Esiste solo nella nostra testa una definizione formale di condizione di accettazione. Possiamo lavorare tramite metafore. Dice "Ah, la macchina è come sei se faccio un cer". Sì. Da quel punto di vista sì, allora se io la penso come metafora, allora la sua domanda ma la macchina sceglie la cosa giusta fin da subito? In questo caso, se io prendo la metafora della macchina che indovina, sì, la macchina becca sempre alla prima scelta la la scelta giusta, però è fuoriante come descrizione. Questa è solo una metafora. È una metafora di funzionamento di una macchina che non esiste, cioè capisce dov'è l'inghitto. Sì. unica cosa che volevo dire è che cioè io con ottimale nonevo scelta giusta ma scelta più efficiente. No, la macchina la macchina se nel proprio computation 3 ha 3 8 1000 rami accettanti alla macchina non fa nessuna differenza. La macchina dice sì perché esiste un modo di accettare, ma non è che sceglie il modo più efficiente perché la macchina non è che ha, come dire, una necessità di sbrigarsi perché non c'è macchina e è un'astrazione. È un'astrazione, cioè questo deve passare, è un'astrazione comoda per noi per pensare perché perché le macchine non deterministiche si possono simulare. quella quella è la questione e siccome è più facile risolvere i problemi tramite una metafora non deterministica, allora usiamo quella lì. Ma la macchina di per sé non c'è. Quella quello è il punto rodale della questione perché senò se la macchina fosse veramente in grado di riconoscere il punto esatto dell'inizio di A dentro B, ma perché mai dovremmo controllare che A inizia dentro B? Se la macchina sa farlo, il problema è che la macchina non lo sa fare. Noi la pensiamo come se fosse in grado di farlo perché facciamo uno. Tutto qua. Ok. Discorso però non vale per quelle deterministiche. Quelle deterministiche sono macchine che si possono costruire, quelle di alfa storia, quelle deterministiche quando sbaglia dentro. Questa è la ragione per cui la simulazione deterministica di una macchina non deterministica deve smazzarsi l'albero di computazione perché le deve trovare, cioè non ha il mondo migliore. Chiaro? Sì. Prego. Par anche la metafora di e Simne che provano tutte le possibilità possibili e c'è nella Sne si riesce a se questa metaforile la può usare e se l'importante è che lei che voi siate consapevoli che queste qua sono una metafora, perché se venite all'esame io vi chiedo quandete una macchina non deterministica certa e mi dite perché indovina la soluzione e quello è va bene la prossima volta. Cioè, no, non è quella la definizione di accettazione della macchina non deterministica. La macchina i tuning non deterministica accetta se in questa cosa astratta che abbiamo chiamato l'albero di computazione c'è un ramo accettante. Questa è la definizione. Ma lachiva purtroppo per noi non siamo in grado di costruirla. Risolveremmo una marea di cose se avessimo macchine non deterministiche fisiche non si possono costruire. è quello il problema. Avremmo problemi, avrem avremmo grande performance su certe cose, avremmo grattacapi infinite su altri perché tutta la crittografia moderna crollerebbe in quell'istante, cioè nel momento in cui avessimo macchie non deterministiche fisicamente costruibili, cioè ci possiamo ascoltare la crittografia che conosciamo al momento. Ok? Alrght. Sì. Ah, in questa prima parte dell'automa sono state fatte due guess. Sì, la fase su check è l'unica per entrambe. Sì, sì. Ottima osservazione. Ok. L'importante è che noi mappiamo un guest su un check. Adesso se tutti i jack li mettiamo assieme va benissimo. Ok. Tardino, eh. Alri. Quindi dobbiamo fare il secondo pezzo. Il secondo pezzo? No, riposiamoci un pochino. Ok, dai, 10 minuti. Ok. Oh, che ci manca? Ci manca il pezzo di computation in cui la macchina decide a reverse. Ok. Ovviamente ce lo possiamo inventare in 1000 modi differenti. Quello che vi suggerisco io è questo nella così che vedete voi. Vedete? Sì. Quindi Q0 Q1 con ansonia. Allora, Q0 Q1 ci stiamo copiando A. Ok? Quando transiamo da Q1 perché becchiamo un cancelletto. Dov'è che sta la testina sulla copia di A che abbiamo infilato sul secondo nastro? Sta alla fine. E siccome noi dobbiamo cercare la presenza di areverse dentro B in questa parte di computazione, eh in questa qua, allora non la riavggiamo, la lasciamo lì dov'è. Ok? Quindi sul primo nastro c'è cancelletto, lascio cancelletto e vado avanti. Sul secondo nastro c'è blank, lascio blank e vado dietro e andiamo in Q7. Ok. Alright. Quindi il giochino ora è lo stesso. Dobbiamo trovare dentro B dove inizia la stringa a reverse. Quindi ci saltiamo le cose che non ci interessano. So sul primo c'è alfa. Lascio alfa e vado avanti. Fino a quando decidiamo che è arrivato il momento. Su primo c'è alfa, lascio alfa, vado avanti. Sul secondo cosa c'è? Alfa, lasciamo alfa e andiamo indietro. Ok. Q8. Facciamo la verifica. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è alfa, lascio alfa e torno indietro. Fino a quando stessa condizione di accentione, sul secondo c'è blank. Lascio blank, sto fermo e poi da Q5 in poi verifichiamo che in fondo AB non c'è nulla di strambo. Per strambo intendo, mi hanno chiesto perché controlliamo là. Lo ripeto velocemente. L'alfabeto di input di questa macchina è quali sono i simboli dell'alfabeto di input di questa macchina? 0 1 e cancelletto. 0 1 e cancelletto. Quindi vuol dire che nell'input io posso avere dei cancelletti un po' a caso. Quello che devo f devo verificare è che in fondo a non ne compaia uno. Questa è la ragione per cui in Q5 avanziamo sul primo nastro alla ricerca di robe strane. Ok? Alright. C'è abbastanza spazio. In questo caso sul Nord fare anche seo clicca a fare anche la copertura della camo trovamo come al contrario. Sì, sì. L'importante è scindere solo come solo il controllo qua. Ah, sì, sì, sì, quella è un'altra un'altra possibilità. Certo. Ah, allora c'era questo esempio. Ok, vi propongo quest'altra soluzione, eh. Facciamo su un'altra pagina, mi serve spazio. Allora, stiamo riconoscendo lo stesso linguaggio, eh, però vi propongo un'altra soluzione e ne discutiamo assieme. Q0 entriamo. L'idea è praticamente che suo e su terzo nastro mi faccio due copie di A. Uno lo lascio, lo tengo all'inizio, un altro lo tengo alla fine, ok? E mentre verifico, mentre viaggio su B, a un certo punto decido se è l'uno o l'altro. Ok? Questa è l'idea, però ve la voglio commentare. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo c'è blank, scrivo alfa e vado avanti. Sul terzo c'è blank, scrivo alfa e vado avanti. Andiamo in Q1. Continuiamo a fare le copie. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è blank, scrivo alfa e vado avanti. Sul terzo nastro c'è blank, scrivo alfa e vado avanti. Fino a quando arriviamo al cancelletto. Sul primo nastro c'è cancelletto e andiamo avanti. Sul secondo nastro c'è Blank, lascio blank e torno indietro. Sul terzo nastro c'è Blank, lascio blank e torno dietro. Q2. Riavvolgiamo il secondo nastro. Alfa alfa dietro fino a quando andiamo qua. Sul secondo c'è blank. Lascio blank e vado avanti e andiamo in Q3. Ok? Quindi è una cosa molto semplice. Abbiamo fatto doppia copia di A sul secondo e terzo nastro. Arrivati al cancelletto, il secondo nastro l'abbiamo riavvolto in maniera tale da avere la testina all'inizio di A. Sul terzo nastro siamo rimasti in ultima posizione in maniera tale da avere a alla fine. Ok. E dopo faccio questo. Sul primo nastro c'è alfa. lafa e vado avanti. Dopodiché a un certo punto decido che inizia o a o a reverse. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è alfa, lascio alfa e vado avanti. Oppure sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul terzo nastro c'è alfa, lascio alfa e vado dietro. Sul quarto Q4. Faccio la stessa cosa. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è alfa, lascio alfa e vado avanti. Oppure sul primo nastro, voi vedete sì, c'è alfa, lascio alfa e vado avanti. Sul terzo nastro c'è alfa, lascio alfa, vado dietro. Accetto quando o sul secondo finisco o sul terzo finisco. Chiaro? Ok, questa cosa funziona? Magari da Q3 a Q4 e passa che un e 3 sono uguali, però poi Q4 può passare che uno e du sono uguali, quindi può essere un po' più splicito, cioè magari credo di aver in sì da Q3 a Q4 controlla che alfa Q1 e alfa di3 sono uguali, poi Q4 quando rientra invece di entrare di nuovo in tre in due e va avanti. Bene. Ok. Questa cosa è sbagliata, eh, questa cosa che ho appena scritto, ve lo segnate? È sbagliato. È un errore comunissimo, lo vedete in un sacco di esercizi. Questa cosa non funziona, ce lo scriviamo bello chiaro, così quando ve li rileggete siete sicuri. Questo è un errore. Ok. Perché è un errore? Perché il check è ambiguo, eh, perché il CCK è ambiguo. Perché il check è ambiguo, perché, come diceva il nostro collega prima, la questione qui è che per adesso, ovviamente nel momento in cui parte il check, abbiamo solo una scelta, la macchina matcherà il contenuto del primo nastro o con quello che c'è sul secondo o con quello che c'è su terzo. Però una volta che arriva qui e inizia a fare il check di A dentro B, potrebbe prendere un po' di simboli da secondo nastro, un po' di simboli da terzo nastro e li mette assieme per matchare una cosa che su B non è né A e né A reverse, ok? C'è si fa una composizione di roba perché la macchina non deterministica pur di dire sì il modo lo trova e alla fine si trova ad arrivare in uno in una configurazione, in uno stato accettante nel quale per arrivarci si è letta un po' di cose da due e un po' di cose da tre. Chiaro per tutti? Quindi questo è sbagliato. Giusto come sì a Q3 avessimo una biforcazione sarebbe corretto. Ok? è l'uso della doppia label che è un errore perché quando mettiamo doppia label stiamo dicendo alla macchina tu puoi percorrere questo arco o in questa condizione o in quest'altra condizione. Quindi le prende e le inizia a mettere assieme un po' alla mini frigo, cioè come gli gira lo fa. Perché che qual è la condizione di accettazione di una macchina di touring non deterministica? Se esiste un modo per accettare, adesso se il modo per accettare è che un po' di simboli riprendo da due e un po' di simboli lo prende da tre, la macchina lo fa. Ok? Quindi il check qua, per esempio, la questione ma che è qua la macchina perde il potere di indovinare? No, la macchina il potere di indovinare non l'ha mai avuto. È qui che il check fa blocco. Ok? E quindi qui, siccome stiamo controllando una cosa un po' cambata per aria, la macchina il potere di indovinare non ce l'ha. La macchina è come un fiume in piena, cerca di accettare. Mo come fa? Non gli importa. Se noi filtriamo male gli errori, la macchina dirà sì quando ok? È chiaro per tutti? Quindi sono state le sensazioni che non essere. Esattamente. Ci sono branci di accentrazione che non ci dovrebbero essere, però se non glieli filtriamo bene c'è una macchina che ne sa ok, questo è il mio programma, il programmatore questo fatto, cioè non è che la macchina è in grado di correggere i nostri bug, la macchina fa quello che ti diciamo, quindi piglia e parte. Se trova il modo di accettare la macchina accetta. Ok? E in questo modo noi non stiamo facendo un check senza altro esercizio. Questo che è? Ok, facciamo prima questo. L è l'insieme delle stringhe. A cancelletto B cancelletto C. No, W tale che la lunghezza di W è due volte la lunghezza di A-o la lunghezza di B. La lunghezza di B è inferiore a due volte la lunghezza di A. V A e B provengono da 01 star e poi A reverse sta dentro W and B sta dentro do W. Ok, quindi quello è un end. Eh, per le condizioni devono essere devono essere per entrambe, ok? maggiore come scusi maggiore di strettamente maggiore di 2a - b. Ok? Ma questo è un esercizio giusto per fare un po' di conti con le stringhe per impratichirsi su questo. Ok? Poi in realtà è una ricerca di sottostringa standard, l'abbiamo già visto più volte. Alright. Allora, ovviamente ci sono tanti modi per risolverlo. Quello che vi propongo io è questo. Sul primo nastro abbiamo l'input, come sempre. Sul secondo nastro calcoleremo la quantità 2a - b faremo altri controlli. Quindi sul secondo nastro andremo a mettere tante x quanto è la quantità 2 lunghezza di A - lunghezza di B. Poi su terzo nastro mi ci metto una copia di A. Su quarto nastro mi ci metto una copia di B. Come potete notare, possiamo usare i nastri che vogliamo. Eh, l'unico vincolo che abbiamo è che i nastri non crescono durante l'esecuzione, cioè il loro numero è fissato al momento di progettazione. Eh, sì. Ok. Allora, cos'è che vedete? Ok. No, quindi più o meno qua, vedete? Ok. Partiamo da Q0. Allora, in questo primo pezzo di macchina, quello che mi faccio è copiare a su terzo nastro e iniziare a scrivere il doppio della lunghezza di X. No, scrivo A sul terzo nastro, sì. e scrivo il doppio della lunghezza di a su secondo nastro, in maniera tale che noi possiamo fare la sottrazione. Ok? Quindi sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è blank, scrivo X e vado avanti. Sul terzo nastro c'è blank, scrivo alfa e vado avanti e vado in Q1. Una volta che sono in culo su secondo nastro c'è blank, scrivo X e vado avanti. Ok? Quindi con questi due stati oscillanti, una volta copiamo un simbolo di A e lo mettiamo sul terzo nastro, ci mettiamo una X sul secondo e una volta ci aggiungiamo una X secondo nastro. Alla fine di tutta sta storia avremo A su terzo nastro e il doppio della lunghezza di A su eh su secondo nastro. Sì, po stringhe però inutono essere vuote perché era 01. Però uno del vincolo che ci dice, poi li andiamo a verificare, uno dei vincoli che abbiamo che il doppio della lunghezza di A deve essere strettamente maggiore della lunghezza di B. Adesso B è vero che può essere 0, però se A fosse 0 avremmo 0 2* 0, no? Quindi a una cosa almeno mi serve. Ok? Ok. Quindi noi facciamo questo giochino fino a quando arriviamo al cancelletto che separa A da B. A quel punto andiamo avanti e facciamo sul primo nastro c'è cancelletto, lascio cancelletto e vado avanti. Sul secondo nastro c'è blank, lascio blank e torno indietro. Sul terzo nastro c'è andiamo un po' più sotto blank. Lascio un blank e torno dietro. E andiamo in V2. Ok, a questo punto sono posizionato in primo nastro. La la testina del primo nastro è posizionata su B. Ricopio B su quarto nastro e nel frattempo inizio a fare la sottrazione. Quindi sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è X, scrivo blank e torno dietro. Su quarto nastro c'è blank scrivo alfa e vado avanti. Ok, forse serve un pelino più lungo. Yes. Alri. Quindi sul primo nastro c'è cancelletto. Lascio cancelletto e vado avanti. Dopodiché sul secondo nastro, siccome noi dovevamo verificare che la lunghezza di B fosse inferiore alla due volte la lunghezza di A, allora noi verifichiamo che sul nastro sia rimasta almeno una X. Quello ci dice che il doppio della lunghezza di A è più grande della lunghezza di B. Quindi sul secondo c'è X e lascio X e sto fermo. Sul quarto c'è blank, lascio blank e torno dietro e andiamo in Q3. Adesso noi dobbiamo verificare l'ultima condizione che la lunghezza di W, vedete? la lunghezza di w sia 2a - b. Ok? Allora, facciamo così. 2a - b 2a - b sta sul secondo nastro, quindi avanziamo i simboli di dopp. Sul primo nastro c sta alfa, andiamo av lasciamo alfa e andiamo avanti. Sul secondo nastro c'era X, lo cancelliamo e andiamo indietro. A un certo punto le X secondo nastro devono finire, mentre sto ancora leggendo una roba sul primo nastro. Quindi, sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul secondo nastro c'è blank, lascio blank e sto fermo. E andiamo in Q4. In Q4 avanziamo sul primo nastro e lo portiamo in fondo per verificare che in fondo non ci sia nulla. Primo nastro, c'è blank. Lascio blank e torno dietro. Ok, Q5. Sì, la connizione ehm incontrare un un blank dentro la seconda della seconda strega si può mettere anche alla fine della terza all'inizio quando si cancella da Q3 a Ah ah dove dove vuole mettere la mettere anche nel ciclo di Q3 con la con condizione. Eh, poi mh sì, dipende da poi che condizione usa per uscire, l'importante è che sia consistente. Ok? Io in questo modo mi garantisco che esco mentre le X secondo nastro so finite e c'è ancora roba sul primo nastro. Adesso se quel modo riesce a, cioè questa condizione semantica lei la riesce a garantire in un altro modo, va bene. Ok, quindi poi sul primo nastro andiamo avanti fino al fondo finché troviamo il blank. Ok? A quel punto siamo in Q5, abbiamo la testina in fondo a W. Noi dobbiamo adesso verificare che in W ci sta e ci stava A reverse e B devono stare dentro do W. Ok? Queste cose si possono controllare in vario modo. Ok? Adesso ad esempio, noi abbiamo che B sta sul quarto nastro. e abbiamo lasciato la testina di B in fondo. Quindi quello che possiamo fare è che mentre indietreggiamo sul primo nostro a un certo punto decidiamo che B inizia, li indietreggiamo assieme e allora quella cosa significa che B sta dentro. A quando finiamo riavvolgiamo fino al primo cancelletto, riandiamo nell'altra direzione e ci cerchiamo a reverse da qualche parte. Ok, chiaro? Alright. Quindi ci cerchiamo sul primo nastro c'è alfa, lascio alfa e vado avanti e mi cerco. Qua va fatto un doppio controllo, però ora lo vediamo. Mi cerco il punto in cui B finisce. Ok, quindi sul primo nastro c'è alfa, lascio alfa e torno indietro. No, avanti, quello è dietro. Oplà. Ed ecco qua. Quindi sul primo nastro c'è alfa, lascio alfa e torno dietro. Sul quarto nastro c'è alfa, lascio alfa e torno dietro. Poi è la stessa cosa, eh. Q6 abbiamo sul primo nastro c'è alfa, lascio alfa e vado dietro. Sul quarto nastro c'è alfa, lascio alfa e torno indietro. Accetto quando sul quarto nastro arriva il blank. Andiamo in Q7. Ok. È chiaro che fa questo pezzo Q5, Q6, Q7? Siamo sul primo nastro, stiamo tornando indietro, ci dobbiamo indovinare dove iniz dove finisce B. Una volta che troviamo il punto dove finisce B, riavvolgiamo assieme primo nastro e quarto nastro e ci sinceriamo che B stia proprio là dentro. Ok? Siccome la stringa B potrebbe essere vuota, allora aggiungiamo quest'arco da Q5 a Q7. Sul quarto nastro c'è blank. Lascio blank e sto fermo. Voi vedete? Sì, vedete. Ok, quindi stavamo indietreggiando, abbiamo beccato il punto dove ci stava B. Verifichiamo la presenza di B. B finisce. Torniamo dietro al cancelletto. Dobbiamo cercarci adesso il punto dentro dopp dove inizia a reverse. Ok, il trucco è sempre lo stesso. Dobbiamo gessare l'inizio della stringa, cercare che la stringa sia effettivamente là. Sì. Ah, a dov'è? Ok. Sul primo nastro c'è alfa. Vado alfa e vado dietro perché dobbiamo riavvolgere completamente W fino al cancelletto disponibile. Quindi sul primo nastro c'è cancelletto. Lascio cancelletto e vado avanti. Ok, in Q8 siamo pronti a fare il giochino. Q8. Sul primo nastro c'è alfa. Lascio alfa e vado avanti fino a quando decido che inizia a reverse. Sul primo nastro c'è alfa, lascio alfa e vado avanti. Sul terzo nastro c'è alfa, lascio alfa e vado dietro. Q9, stessa cosa. Sul primo c'è alfa, lascio alfa e vado avanti. Sul terzo c'è alfa, lascio alfa e vado dietro. Accetto quando il contenuto del terzo nastro termina. Chiaro? Chiaro per tutti? Ok, quindi questo non era un esercizio particolarmente intricato. Vediamo come vi faccio ora. Questo è troppo facile. Facciamo questo. Una domanda se cont come se suultimo controllo un Ah, sì, è molto complicato. Eh, sarebbe come l'esercizio di prima. Lei deve decidere se ci sta un o l'altro. Sì, ma devo anche un cion però. Ha un axor intende se uno o se sono solo eh in quel caso è più complicato. Sì, perché si deve sincerare perché è interessante come come questione perché la macchina dei touring non deterministica fa di tutto per dire sì, quindi per fargli dire di no la macchina non deterministica la devo fermare su tutti i tentativi che fa, quindi si deve fare una cosa sofisticata. Sì, fatti uno scapo fine in cui manca uno scavo macchina. Sì, si può fare. Sì, sì, sì, sì, sì. Là, però lei quello che deve fare è che quel pezzo di macchina deve essere sostanzialmente deterministico. Sì, cioè praticamente lei si deve sincerare che la macchina lì non ha modo di accettare. Ok. Alright. Allora, un esercizio un pelino più intricato perché sennò vediamo cose troppo facili. Se ce la facciamo a finirlo, bene 10 minuti mi sa di no, però ci proviamo in caso lo finiamo assieme la prossima volta. L. Allora, le stringhe fatte così. C'è una sequenza di n simboli X. Poi c'è un cancelletto. Poi ci sta V1 cancelletto bla bla bla cancelletto wn. E quindi questo già vi inizia a dire che il numero delle stringhe w con i sono tante quante le x primo cancelletto. Ok? Abbiamo che n è strettamente maggiore di 0. W con i vabbò questo non è che cambi molto, però appartiene a B o C o D plus. E poi arriva la parte interessante. Per ogni i con i compreso fra n e 1 esiste una stringa s con i tale che s con i è sottostringa di w con i, s con i è lunga i e s con i è uguale a s con i reverse. Cioè è una stringa palindroma. Ok, questo è già un esercizio più interessante. Diciamo che è un po' più così che avranno la forma gli esercizi sul testo d'esame, eh, sono un po' più sofisticati. Come sta nel foglio? Come come si sta nel foglio? Come? Eh, ma se fa eh c'è entrato per questo. E la fa allarga i fogli e lo fa doppio. Doppio. Oppure ci facciamo dare i fogli a tre camo i poste. I poster. Ok. Alright. Allora, dobbiamo capire bene, dobbiamo capire bene sta macchina che fa. Ok. Ovviamente ci sono tanti modi per risolverla. Ogni modo che funziona va bene, ok? Quindi qualsiasi cosa ci inventiamo che funzioni va benissimo. Sì, è una domanda. Se io pagina contro magari voglio mettere più nas, però se ci sono n io potrei mettere un numero numero che stato di nas poi gestirli forma di perché quant'è quantoè n eh non lo so. 5 10 lei deve saperlo dal principio quant quell N. Quindi con le stringhe fino a quell' n funziona, con le stringhe con n più grosso non funziona. Il numero di nastri non lo deve determinare all'inizio e deve essere una quantità limitata. Può essere pure 1 milione, però deve essere fissato. E se poi arriva la screening a congere 2 milioni come fa? Capito? Quindi dobbiamo fare qualcosa di più flessibile. Ok? Allora, è chiaro per tutti questo? Che cosa sto cavolo di linguaggio che tiene? C'ha una sequenza di simboli X che ci serve a contare. Ci dice quante saranno le doppia boniere successive. Dopodiché quello è un modo complicato per dire che in per ogni doppia v con i doppia v con i contiene una stringa palindroma di lunghezza I. Questo è quello che ci sta dicendo l'esercizio. Ok? Pensate un attimo su come si possa fare perché il dettaglio sicuramente non lo riusciamo a vedere. Allora, ragioniamo assieme. Poi la soluzione la prossimo giro, però pensiamo un attimo come si fa e poi ne discutiamo. Come cassetti fa n m perché sono di N, quindi sì, noi dobbiamo verificare che le doppie V sono tante quanto N, quindi se sono di più o sono di meno dobbiamo rifiutare. Quindi quello è un primo check che va fatto, cioè che le doc V che compaiono sul nastro sono tante quanto le X all'inizio. Però mi doppia un cancelletto. Come? Però mi doppia voce un cancelletto prima, quindi bastaare i cancelletti prima. Basta vedere, basta meccare i cancelletti. Eh, quello è semplice. Sì. Io userei quattro nastri, il primo di input, sì. Il secondo per tenere traccia della della i, insomma, quale? Quanto è i? Sì. e gli altri due per la copia di bui in modo tale che così riesco a fare il check su andata e ritorno se c'è il reverso, quindi su su bui. Esatto, su bui e ogni volta vado a sovrascrivere, cioè quando ho finito il check su w e devo passare a W1, ah vado a sovrascrivere il Ok. Lei come fa a sapere che dalla perché se ho capito bene, lei vuole ricopiare W su un secondo nastro in maniera tale che può fare un controllo di parromo. Come fa a sapere che sta selezionando la stessa porzione di lunghezza i e come fa a controllare? Perché noi possiamo testare quello che vogliamo e vi proporrò una soluzione particolare, però va controllata. Un attimo. Lei allora eh sempre la cosa di tener traccia della I attuale con un nastro specifico su che da tutte le sue X. Eh non deterministicamente decido che sto cominciando ad analizzare SI in un qualche momento in cui analizzo la stringa doppia i eh per i punti copio quello che lei eh in un nastro suo specifico. Sì. Poi torno indietro e se corrisponde salto il prossimo. Ok. Sì. Ok, hai ascoltato Hai ascoltato come funziona la soluzione proposta dal vostro collega? Allora, la ricapitolo per chi non era riuscito a sentire. L'idea è poi ci fermiamo ci fermiamo alle idee, prossima volta lo vediamo. Quindi serve un'altra esercitazione su Turing Machines. Alr, vediamo domani, lunedì. Allora, l'idea è che siccome noi dobbiamo cercare stringhe palindrome di lunghezza I per ste B con I che avanzano, no, ci sarà V con1, V con 2, V con 3, eccetera e la lunghezza di questa stringa S con I cresce, no? Allora l'idea del vostro collega è che io mi tengo su un nastro quanto vale i correntemente, no? E però vado a aggiornare ogni volta, ogni volta ci aggiungo una x, quindi sta i cresce. Ok? Allora, e questo è un pezzo. L'altro pezzo è che mentre processo, che ne so, w con5, non deterministicamente, dentro w con5, io decido dove inizia la stringa panindroma di W con5 che sarebbe S5. Che faccio? Decido il punto, mi copio cinque caratteri su un altro nastro, ok? Dopodiché mi faccio il controllo di calindromo, cioè sul primo nastro e sull'altro nastro vado in un messo e nell'altro. È chiaro per tutti? Questa cosa funziona? Sì. Me ne propongo una io che la trovo interessante, esattamente come i vostri colleghi hanno proposto. Sul nastro mi tengo la ricorrente perché è una quantità che ci serve, no? Dobbiamo sapere questa cosa qua. Dopodiché, quindi, io mi gestisco su un nastro aggiuntivo questa lì che cresce, eh magari aggiungo delle X e bla. Io invece invece di andarmela a prendere della doppia mula e seguì, io faccio quest'altra cosa. Sfrutto il potere del nondeterminismo. Su due nastri aggiuntivi io mi scrivo la s con i, la indovino. Cioè, che ne so, sul terzo blanco, sul terzo nastro c'è blank e scrivo un carattere. Sul quarto nastro c'è blank, scrivo lo stesso carattere e me ne scrivo io in un verso uno nell'altro, cioè tutti così e poi faccio il controllo. Quindi la differenza che faccio io è che io non la vado a prendere docch è più giusto, no? è la stessa cosa, eh, funziona. Io non la vado a prendere da occhio a buon lì, io la scuto non deterministicamente sui nastri aggiuntivi e dopodiché verifico che questa cosa che mi sono inventato perché altri ha buttati a caso su sui nastri aggiuntivi quella roba stia sul primastro. Funziona anche questo? Uno prende un voto più alto dell'altro, no, perché sono entrambi corretti. Però ci tenevo a farvi vedere che una macchina non deterministica sa fare questo, può sputare in anticipo sul nastro quello che dovrà vedere da lì a un poco. Ok? Magari pensate come si può risolvere questa cosa, ve le scrivete così prossima volta lo vediamo assieme. Ok? Buon pranzo se non avete già pranzato. Alri.