mi ha detto, cioè sempre No, no, [Musica] ok, iniziamo. Ok, veloce quello che abbiamo fatto ieri. [Musica] Ok. Ok, [Musica] recap quello che abbiamo fatto ieri e poi iniziamo gli argomenti per oggi che continua a essere un recap. Ehm, allora, velocissimo. Problemi di ricerca. Noi siamo interessati ai problemi di ricerca che sono quelli più generici, ok? Problemi di ricerca sono quei problemi in quali la risposta può essere valida. Qual è il prodotto tra questi due numeri? Qual è l'idea la derivata di questa funzione? Qual è il percorso minimo fra B? Ok, problemi di affiancate a questi problemi ci stanno i problemi di decisione che sono quei problemi nei quali la possibile risposta sono solo due, sì o no? Ok? I problemi di decisione sono anche dei problemi di ricerca, ma non mi cioè i problemi di decisione sono risolti insieme. Abbiamo visto che c'è una certa relazione fra problemi di decisione e problemi di ricerca perché dato un problema di ricerca ci possiamo diventare un problema di decisione che è molto simile tale per cui essere capaci di risolvere uno ci dà sostanzialmente la difficoltà eh ci dà informazioni sulla difficoltà di risolvere il problema di che cosa facciamo? Quindi ci focalizziamo sui problemi di decisione perché è più semplice per noi da un punto di vista di analisi. Ok? Quindi problemi di decisione. Dopodiché abbiamo fatto un un salto extra, abbiamo detto: "Ok, c'è un problema abbastanza studiato in in formatica teorica che è un problema di decisione che sono i problemi di decidere i linguaggi." Ok? Che cos'è un linguaggio? Abbiamo detto che un linguaggio è semplicemente un insieme di stringhe. Cosa significa decidere un linguaggio? Significa data una stringa, stabilire se quella stringa appartiene all'insieme del linguaggio o meno. Le risposte sui sui linguaggi, sul problema di decidere un linguaggio sono due, sì, no? Quindi è un problema di decisione. Noi leghiamo i problemi di decisione a opportuni linguaggi in maniera tale che risolvere un problema di decisione è equivalente a decidere uno specifico linguaggio. Chiaro per tutti? Perché ci spostiamo sui linguaggi? Perché i meccanismi, cioè il formalismo che possiamo usare per stabilire se linguaggio de cilber o meno, invece che avere algoritmi asti, scritti in Java, Python whatever, noi utilizziamo il concetto di automa che è più semplice e più formalmente definibile e di questo e per questa ragione ci focalizziamo su questo. Ok? Domanda per voi. Supponiamo di avere un linguaggio L, ok? Un linguaggio L e noi ci vogliamo focalizzare sul problema di decidere L. Ok? Qual è l'input, qual è l'output? L'input è una stringa e l'output è un alta. E l'input è una stringa e l'input è volata. L'input è una stringa. Ok. Decidere il linguaggio L. Il linguaggio L non è input. È chiaro per tutti questo passaggio? Cioè, stiamo attenti a non confonderci qua. Decidere un linguaggio L. L'input di questo problema è una stringa, non gliaggio L. E dove compare il linguaggio L in questo problema? Nella relazione. Nella relazione, nella definizione. Ok? Dobbiamo stare molto attenti perché a un certo punto vedremo problemi in cui avremo linguaggi input. Ok? Quindi qua dobbiamo stare attenti. Dato fissato un linguaggio L, il problema di decidere il linguaggio L è, data una stringa, stabilire se questa stringa appartiene a L o meno. Ed L è una cosa data, cioè fa parte della definizione del problema, non sta nell'input di questo problema, ok? non abbiamo una rappresentazione del linguaggio in ingresso, almeno per il momento. Poi nelle lezioni future vedremo problemi che prendono input, linguaggi e fanno cosa sui linguaggi. Ok? Però argomento ci focalizziamo su questa cosa basica, cioè dato fissato un linguaggio, prendiamo una stringa, ci viene data una stringa, noi dobbiamo essere in grado di stabilire se quella stringa appartene al linguaggio o meno. Ok? E poi ci siamo focalizzati su questa cosa ieri in cui praticamente volevamo riconoscere l'insieme delle stringhe binarie che quizano numeri dispari. C'eravamo detti praticamente che un semplicissimo Sì, ma la stringa in input è la descrizione del linguag input, ok? Dipende dal problema. Se il tuo problema è fisso L, devo decidere L, la stringa input è una stringa sull'alfabeto su cui LSO stesso è definito. Ok? E di questa stringa io devo dire se questa qua sta dentro questo insieme o no. Ah, ok. Sì, sì, ok. Sì, sì, sì. Nelle prossime lezioni vedremo, però è inutile andarci ora, dei problemi un po' più sofisticati nel quale in input avremo stringhe che descrivono linguaggi e ci chiederemo ah, ma questo linguaggio ha questa proprietà o cose di questo tipo? Ok? Però è quello è proprio un altro livello semantico. Qua siamo fissato un linguaggio, dato una stringa, devo decidere se questa stringa sta qua dentro o sta qua fuori. Ok? Allora, ieri abbiamo visto questo esempio della del linguaggio delle stringhe binarie che codificano numeri dispari e ci siamo detti che praticamente quello che dobbiamo andare a fare è andare a guardare l'ultimo bit. Ok? Ieri abbiamo usato questa metafora dei segnali in ingresso all'automa. Una cosa, un passaggio extra che possiamo fare è questo qua. Pensare che così ci iniziamo a poco a poco a spostare verso le Turing machines che un automa è un computer molto semplice che ha input un nastro. Ok? Vedete presenti gli scontrini? Ok, abbiamo in input uno di questi scontrini. Bello lungo. Ok. E su questo scontrino ci stanno i simboli 0 1 0 1. Quindi questa cosa qui, questa stringa in input abbiamo che è codificata su uno scontrino, su questo lungo nastro di carta. l'automa o gli premiamo i bottoni, come abbiamo detto ieri, oppure un'altra metafora, perché di metafore stiamo parlando, è che questo automa abbia la capacità di leggere un simbolo per volta da questo scontrino. Guarda sullo scontrino, dice ah c'è un uno, ah, c'è zero, eccetera. e la sua computazione praticamente abbiamo visto ieri che è oscillare fra questi due stati. Lo stato Q1 che ha il significato di l'ultimo simbolo che ho visto è un 1 e lo stato Q0 che significa l'ultimo simbolo che ho visto non è uno. Ok? Allora, come serve a niente questo coso? Come funziona questa macchina? Quando su nastro leggo uno, mi sposto nello stato che significa l'ultima cosa che ho visto è un uno quando io leggo su nastro zero, mi sposto nello stato in cui significa io l'ultima cosa che ho visto è zero. Adesso se l'ultima cosa che ho visto è zero e rileggo nuovamente zero, rimango dove sono. Se l'ultima cosa che ho visto è uno e eh leggo nuovamente uno, rimango in quello stato di esecuzione. Ok? Questa è una macchina semplicissima, però è in grado di svolgere questo compito. Date una stringa binaria, è in grado di stabilire se questa stringa rappresenta un numero binario dispari. Ok? La cosa interessante di questa macchina è che è la caratteristica di questi atomi, come sapete, è che la lettura dei simboli sul nastro avviene un simbolo dopo l'altro, cioè questo scontrino lo iniziamo a tirare e una volta letto lo buttiamo, ok? Non andiamo mai dietro. C'è questa testina sullo scontrino che legge un simbolo e va avanti, un altro simbolo e va avanti e va avanti e va avanti. Quello che è letto è perso, non si torna indietro. Ok? Quindi questa macchina deve in qualche modo fare la mossa giusta nel momento in cui vede il simbolo. Non ci può ripensare. Ok? Questa è la caratteristica di questi automi. Ok? Si legge, si butta. si legge, si butta. Vedremo automi più sofisticati in cui questa cosa non avviene. Ok. Allora, ovviamente noi abbiamo fatto una descrizione di eh di queste macchine in maniera un po' così chiacchiereccia. Quello che adesso noi vogliamo fare è guardare una definizione formale di queste macchine, del loro della loro computazione, del loro nozione di accettazione di stringa, in maniera tale che su questo iniziamo ad agganciarci i pezzi e vedremo che la definizione di touring machine non sarà molto simile da quello che vediamo da queste macchine, cioè le touring machines, come vedremo, saranno automi come quelli che stiamo vedendo ora, solo che riescono a fare qualcosina in più. Quindi iniziamo a vedere le definizioni formali di queste macchine in maniera tale che a poco a poco ci aggiungiamo pezzi fino a quando arriveremo a costruire la definizione formale di cos'è una machine. Ok? Alrght. Come si farà? Ok. Ok. Allora, ragioniamo insieme come si possa fare questa cosa. Allora, noi abbiamo detto che un autonoma stati definiti sostanzialmente ha varie modalità di funzionamento e graficamente noi le rappresentavamo con quei nodi nel grafo. Ok? Quindi per modellare un automa ci servirà qualcosa per descrivere il la modalità di funzionamento. Ok? Queste modalità di funzionamento le chiamiamo stati, quindi avremo necessità da qualche parte di infilare degli stati. Cioè una un autroma stati finiti è caratterizzato da un certo numero di stati. Ok? Stiamo modellando assieme questa cosa. Se voi andate sui libri trovate 1000 definizioni differenti. Io ve ne propongo una e una che ragionevole che ci stiamo inventando assieme. Ok? Non è oro colato, si possono definire in mille modi. Facciamo questa cosa assieme per mostrarvi che il processo di definire queste cose è una cosa che possiamo fare anche noi. Pensiamo al problema che stiamo modellando e ci inventiamo così. Ok? è tutto inventato, eh, niente scolpito nella pietra, poi ci stanno cose inventate che funzionano meglio di altre e quindi le selezioniamo. Ok? Quindi noi abbiamo queste macchine, hanno degli stati che processano, quindi da qualche parte nella formalizzazione di queste modelle ci deve essere sto stato, devono esserci stati. Ok? Poi abbiamo detto che la macchina che fa? Legge che cosa? simbol legge il nastro legge simboli sul nastro, quindi questa macchina dovrà avere associato un insieme di simboli che è in grado di di distinguere. Ok? Dopodiché che di che cosa è caratterizzata la la macchina? Da che cosa passa con adess? Ok? Quindi c'è un pezzo proprio un pezzo della definizione è cosa fa questa macchina, cioè quindi il programma e il programma qua dentro che cos'è? Un grafo. È un grafo. Ma che cosa ci dice questo grafo? Che genere di informazioni ci dà? Sulle stringhe accettate? Come? Scusami? Cioè sulle stringhe accettate dice eh ok. Però qua dentro questo grafo che stiamo codificando intuitivamente il linguaggio è quello che noi decidiamo. Però questo grafo che informazione ci dà? Passaggio tra gli stati. Come? Il passaggio tra gli stati. Che il passaggio tra gli stati? Il passaggio tra gli stati, cioè il funzionamento. Cioè questo grafo ci sta dicendo se siamo in questo stato e se leggiamo questo simbolo ce ne andiamo di là. Se siamo in quest'altro stato e leggiamo quest'altro simbolo, facciamo quest'altra cosa. Cioè, quindi il programma è sostanzialmente codificato negli negli edges che collegano le cose. Quindi dentro la definizione di automa ci andrà infilata pure questa cosa. Quale altra caratteristica vediamo qua dentro che potrebbe essere utile nella definizione di un automa? Stati iniziali, stati finali? stado iniziale e stato finale. Dobbiamo sapere quando accendiamo sta macchinina dove si trova. Ok, quindi andrà definito quello e ma la macchinina quando si arresta come facciamo a stabilire se dice sì o no? Ok. E quindi ci serve quest'altra cosa. Quindi queste sono tutte informazioni che abbiamo dato qui intuitivamente. Adesso le dobbiamo infilare in una definizione formale. Ok. Alright. avremo che no un automa stati finiti D è caratterizzato da Abbiamo detto che questo automa legge simboli da un nastro. Di conseguenza ci serve l'alfabeto sul quale questa macchina lavora, quindi è caratterizzato da sigma. Sigma che cos'è? Sigma è un alfabeto. Di cos'altro era fatto questo automa? Se ripensiamo al grafo, riguardatelo nella vostra vente. Che ci sta in questo grafo. Gli stati, le pallette. Ok. Quindi abbiamo un insieme Q di stati. Riguardate nella vostra mente o nei vostri appunti quel grafo. C'erano stati diversi dagli altri. Che cosa abbiamo? lo stato iniziale. Quindi Q0 Q0 appartenente a Q è lo stato iniziale. Poi abbiamo l'insieme F, che è un sottoinsieme di tutti gli stati Q che sono gli stati finali. Riguardiamo nella nostra mente il grafo che ci sta in questo grafo. Ci stanno gli archi che è la codifica del programma, ok? Che ci dicono come sta macchina balla fra uno stato e l'altro, ok? La chiamiamo delta. Delta è la funzione di transizione, ok? Cioè, si chiama così perché ci dice come la macchina transisce da uno stato all'altro. Ok? Comeè definita questa funzione? Qual è l'inputs di questa funzione? Stato è un simbolo. È un simbol. Questa funzione ci dice se siamo in questo stato e stiamo leggendo questa cosa, quindi input della funzione è una funzione che va dagli stati per i simboli, quindi il prodotto cartesiano degli stati e dei simboli. Quindi questa cosa significa la funzione di transizione. Se siamo in uno stato e leggiamo un certo simbolo, allora che informazione ci dà questa funzione? Lo stato successivo, cioè dove ci spostiamo. Q. Quindi delta è una funzione che va mappa coppie stato simbolo verso il prossimo stato. Ok? Così si leggono le funzioni. Ok? Questa è una funzione, il che significa che per ogni coppia stato corrente simbolo letto, il prossimo stato è uno solo. Ok? Quindi per questo è una funzione perché mappa ogni singola coppia, ok? Verso un un solo stato successivo. Ok? Quindi questa è la definizione formale di automa stati finiti. Ok? Questo è un automa stati finiti perché l'insieme Q degli stati è un insieme a cardinalità finita. Ok? Cioè quando noi progettiamo un automa, ok? questo automa Q questo automa in cui decidiamo quali sono gli stati, gli stati non possono cambiare mentre la macchina esegue. Cioè, non è che la macchina gira, vede un simbolo e m qua mi aspettavo altro e e tira fuori uno stato aggiuntivo, cioè mi cresce una palletta extra nel grafo, ok? Cioè il grafo è il programma della macchina. La macchina segue per vedisse nuovamente quello che c'è scritto nel grafo. Il grafo non cambia mentre la macchina esegue. Ok? Questo è importantissimo, eh, perché vi dovrebbe già fare iniziare a pensare che i computer sono un aggeggio un po' strano perché eseguono programmi differenti. Ok, poi vedremo come questa cosa è possibile, però ok, ma un automa ha un programma fissato, ma io sul mio computer ci riesco a mettere giochi diversi, com'è che fa cose diverse? Ok, vedremo formalmente questa cosa come si ottiene. Ok. Alri. Questa è la definizione di automa. Però ancora non abbiamo definito formalmente come questo automa computare. Ok? Perché qua ancora non abbiamo letto come avvengono i passaggi e che cos'è una computazione accettante per l'automa. Ok, qua vi viito un po' io perché è un po' più tricky. Allora, pensiamo assieme questa cosa qua. Se noi vogliamo catturare il funzionamento di un automa stati finiti, sostanzialmente noi dobbiamo in qualche modo modellare i passi che quest'utoma fa su una certa stellino. È chiaro per tutti? Cioè, se io devo modellare il funzionamento della macchina su una certa stringa input, io devo in qualche modo catturare la sequenza delle cose che succedono mentre questa macchina gira sulla stringa input. Ok? Adesso, secondo voi, supponiamo che stiamo studiando il funzionamento di questa macchina su una string input e che questa macchina staia già girando, ok? e vogliamo catturare lo stato di avanzamento dei lavori di questa macchina a un certo punto in mezzo alla computazione. Ok? Quindi è chiaro, abbiamo questa macchina ha ricevuto input, una stringa, questa macchina sta iniziando a girare, legge caratteri, abbiamo detto che questa macchina che fa? Legge simboli, si muove in un altro stato, butta quello che ha detto. Ok? Questo è importante. Leggo un simbolo, cambio stato, butto. Leggo simbolo, cambio stato, butto. Ok? Questa macchina processa passo dopo passo in questo modo, a un certo punto arriva a metà. Ma noi vorremmo essere in grado di caratterizzare lo stato di avanzamento dei lavori questa macchina in mezzo alla computazione. Di quale informazione abbiamo bisogno per essere in grado di stabilire cosa a che punto è la macchina del del suo calcolo? Ecco, non ho capito. Vogliamo capire se la macchina si trova del Q0 Q1. Allora, è una cosa che ci stiamo inventando. Noi vogliamo modellare i passaggi della macchina. La mia domanda è: siccome noi vogliamo capire i passi che la macchina fa per arrivare fino a accettare o rifiutare, noi dobbiamo inventarci delle, cioè ci chiediamo quali sono le informazioni che ci servono per stabilire in mezzo al calcolo a che punto la macchina si trova. La fun, usiamo la funzione del tipo io so la sfinga di input, quindi eh car, cioè simbolo per simbolo, prendo poi prendo l'output, sì. e lo uso come input per il successivo simbolo. Sì, l'idea c'è più semplice. Io voglio sapere in mezzo al guado, stiamo attraversando questo fiume da un arrivo all'altra, dalla partenza all'arrivo, noi siamo in mezzo all'acqua. Come Quali sono le informazioni che mi servono per sapere da lì in poi come la macchina procederà? Stato corrente input un po' di più. Allora, per sapere, stiamo attraversando il fiume da una riva all'altra. Ok? La macchina si trova in mezzo al guado. Come faccio a sapere di quali informazioni necessito per sapere come evolverà la sua computazione da metà verso la fine? corrente, stringa rimesse, mi serve lo stato corrente e il pezzo di stringa che rimane. Quello è tutto ciò che mi serve perché la funzione delta noi la conosciamo dalla macchina. Quindi se io so in quale stato sono e qual è la parte rimanente di stringa, io posso stabilire quali saranno tutti i passaggi successivi della macchina. Ok? string e non si perché se io voglio sapere quale sarà il resto della computazione devo sapere cosa mi rimane la leggere però stato si bassa si bassa simili ma se un conto è che io sono in uno stato e una c'ho una sequenza di 3A un conto è che c'ho uno stato, una a e una sequenza di 3B, cioè cosa farà la macchina? dipende da quello che leggo ora, ma i suoi passi successivi dipende da quello che leggerò poi. Ok? Questo non è oroato, ce lo stiamo modellando come vogliamo noi. Potete inventarvi altri modi, l'importante è che funziona. Perché facciamo così? Perché in questo modo introduco un concetto che poi ci serve per le macchine di ting. Ok? Ecco perché ce la stiamo un po' complicando, perché poi estendiamo sta cosa le macchine during e siamo belli rilassati. Ok? Allora, ci siamo detti quindi che uno snapshot, cioè una fotografia che ci permette di capire da qui in avanti come la macchina si comporterà sono due generi di informazioni: lo stato corrente e la parte di stringa residua. Ok? Noi a questa informazione gli diamo il nome, così lo possiamo utilizzare. Una configurazione per una macchina D. intuitivamente è semplicemente una sequenza di simboli il cui primo simbolo è un certo stato Q, ok? E gli altri simboli sono tipo C, bla bla bla e il resto della stringa che deve leggere. Ok? Adesso facciamo un esempino. Ah! Ah! Voi i vostri appunti li avete sott'occhio, più o meno, perché no, mi servirebbe più roba. Alright, ripensiamo alla macchina precedente, la macchina che è in grado di distinguere stringhe dispari da stringhe pari, ok? E vogliamo capire come funziona la macchina sulla stringa Ok. No, non mi piace. Facciamo 001 001. Ok, quindi abbiamo la macchina di prima e input riceve la stringa 001. Ok? Adesso noi vogliamo per impratichirci con questa nozione di configurazione vogliamo capire qual è la sequenza delle configurazioni che la macchina attraversa prima di arrivare a dire sì o no. Ok? Allora, la macchina parte in Q0 e all'inizio ha su sul nastro 001. Ok? Quindi la prima configurazione della macchina è stato iniziale tutta la stringa. Ok? Questa configurazione è seguita da un'altra configurazione che sostanzialmente è quella che la macchina raggiunge una volta che legge il primo simbolo. Ok? Vi ricordate? Quindi siamo in Q0, leggiamo questo 0 qui, ok? Che cosa succede alla macchina? Siamo in Q0, leggiamo 0, rimaniamo in Q0 perché c'era quell'anellino, quindi il nuovo stato sarà Q0. Ci siamo detti che il simbolo appena letto è stracciato va a finire nell'immondizia e quindi quello che rimane in input è 01. Ok? Quindi questa configurazione, questa configurazione qui è la next legal, la configurazione legale successiva rispetto a questo e alla funzione di transizione di D. Ok? Cioè, quindi questa segue questa secondo delta, ok? La delta della macchina che stiamo considerando non una delta generica, ok? Alri, siamo in Q0, leggiamo zero. Che fa con la macchina? Rimane in Q0 e all'input che succede? diventa uno uno. Ok, questo è l'altro stato, l'altra configurazione. Ok, sto andando lento perché poi quando faremo Turing machines queste cose le facciamo più astratte e andiamo più veloci. Ok. Alright. Quindi adesso siamo in Q0. La macchina legge uno. Che cosa succede? La macchina va in Q1. Che succede all'input? si svuota. Segniamo epil. Ok. E questa è l'ultima configurazione. Ok. Che peculiarità ha l'ultima configurazione che non ha nessun cioè nessuna funzione associata, cioè non ha nessuno scambio di stato in questo non c'è nessuno scambio di stato. Ok. Poi c'è un'altra caratteristica. Cos'è lo Stato? stato accettando e lo state accettando. Quanta parte di stringa è rimasta? Nessuna. Ok, la stringa si è svuotata. Ah, ok. Perché ci stiamo focalizzando su questo? Perché la condizione di accept reject di una macchina la possiamo definire in tanti modi, ok? Basta che è coerente. Su alcuni libri troverete un modo, su altri libri troverete altro. Questo è il modo che in genere uso io. La macchina accetta se e solo se a fine computazione si trova in uno stato accettante e sul nastro non è rimasto niente. Ok? M questa informazione ovviamente adesso formalizzeremo il tutto, ok? Però questa informazione, questa definizione ci dà un'informazione importante. La macchina per dire sì devono succedere due cose. Deve consumare l'input, cioè deve arrivare che dell'input non ci rimane niente e lo stato in cui si trova alla fine deve essere uno stato accettabile. Quindi due cose devono accaderebbe, non una solo input finish, stato finale è uno stato accettante. Ok? La macchina accetta solo in presenza di queste due condizioni. Di conseguenza, quand'è che la macchina rifiuta? quando ha finito di leggere non è un stato finale. Una condizione è che abbiamo finito di leggere e non siamo in uno stato accettante oppure oppure perché io a differenza di altre definizioni non uso gli stati di rifiuto. Ok? Quindi abbiamo una definizione un po' più sofisticata. Quindi la macchina accetta se leggo tutto e quando arriva alla fine e c sta cadiamo in uno stato accettante. Ok? Due cose devono succedere, basta che una delle due non accade e quindi sto rifiutando. Quindi la macchina rifiuta quando? O arriviamo in fondo e siamo piombati in uno stato non categorizzato come accettante, cioè uno degli altri stati oppure finale completamente oppure la macchina è arrivata a un punto della computazione per le quali l'input non è finito e la funzione di transizione non stabilisce due prossime mosse, quindi la macchina si va a bloccare in un punto, ok? Nel quale ah da lì non si schioda. Ok? Quindi un automa stati finiti accetta perché almeno nella definizione che usiamo qua, ma vi ripeto ce ne sono 1000 equivalenti. Se andate a leggere in giro ci saranno le definizioni che parlano degli stati di reject, ok? io non lo trovo particolarmente utile per le cose che dovremmo fare poi. Quindi la definizione che è che un automa stati finiti accetta se consume il suo input e termina in uno stato accettato. Quindi se non consume il suo input o lo consuma e va a finire in uno stato non tra quelli accettanti, la macchina rifiuta. Ok? E questa cosa adesso la formalizziamo. Quindi partiamo, per definire questa cosa, partiamo dal concetto di ehm configurazione. Ok? Quindi è chiaro cos'è una configurazione? è una sequenza di simboli il cui il primo è lo stato in cui la macchina si trova, l'automa si trova e gli altri simboli sono la parte residua della stringa da processare. Ok? una computazione parziale per per un automa D su una stringa W caratterizzata dai simboli V1 1 VN una sequenza di m + 1 via m + 1 configurazioni con mug n e le configurazioni sono R0 V1 bla bla VN R1 V2 VN bla bla bla R + 1 1 N. Quindi cos'è una computazione parziale per un automa stati finiti? È semplicemente per noi una sequenza. Ancora non ho finito la definizione, eh, la sto solo ripetendo. Cos'è una computazione parziale? Poi diremo cos'è una computazione completa. Una computazione parziale di un automa a stati finiti è semplicemente una sequenza di configurazioni, la zeresima, l'unesima, la seconda, l'emmesima, ok? in cui m non è più grosso di n. Ovviamente non possiamo fare un numero di passi più grande dei simboli presenti sullo scontrino, sul nastro, tale per cui R0 è uguale a Q0, cioè quindi la prima configurazione deve avere come stato lo stato iniziale della macchina. Ok? Quindi questo partenza corretta, start correct. Ok? E poi semplicemente dobbiamo dire che da un passaggio all'altro questa sequenza caratterizza mosse leite per la macchina D. Come lo facciamo a dire? semplicemente che lo stato al passo i + 1 è quello che si ottiene andando a guardare la funzione di transizione in cui lo stato la coppia R v + 1 viene letta, ok? E questo deve essere vero per tutti gli indici tra 0 e m - 1. Ok? Allora, cosa abbiamo scritto formalmente? Questo è un modo difficile per formalizzare quello che abbiamo detto prima, cioè che una computazione di una macchina è caratterizzata da una sequenza di configurazioni la cui prima configurazione ha com'è stato lo stato iniziale della macchina, cioè la prima configurazione della lista deve rispecchiare il fatto che la macchina viene accesa e c'è l'input. Quindi la prima configurazione deve essere stato iniziale e poi tutti i simboli della stringa tutti. Ok? Dopodiché la computazione noi la modelliamo come una sequenza di fotografie in cui lo stato della fotografia al passo i + 1 deve essere quello ottenuto dall'applicazione della funzione di transizione dello stato al passo precedente e del simbolo letto in quel momento. Ok? Cioè, noi asbiamo semplicemente scritto in un modo complicato che cosa? Che una computazione parziale è una sequenza di foto in cui la prima deve rispecchiare la partenza della macchina e la sequenza deve essere sensata. Quindi a ogni passaggio, come vedete, 1 qua, qua partiamo da V1, qua c'è V2, quindi a ogni passaggio un simbolo dallo scontrino sparisce e R1 è ottenuto da R0 tramite l'applicazione della funzione di transizione. Ok? Chiaro per tutti? Prof? Ma perché m - 1 e non è? Perché? Perché l'ultimo stato è RM e quindi tu lo applichi al passaggio N - 1. Ah, ok. Sì, sì, sì, sì. Ah, alright. Stiamo andando più lento del previsto. Ehm. Ok? Quindi questa è la definizione di computazione parziale. Da questa deriviamo la definizione di computazione, cioè la computazione totale. Ok? Cos'è una computazione? una computazione, dobbiamo semplicemente dire, adesso facciamolo assieme, dobbiamo una computazione sarà una computazione parziale che non possiamo estendere di più, ok? Questo è è il senso che che non c'ha altri passi, cioè è una lista completa, è una lista massimale che altra roba in coda non si ci può infilare. Allora, una computazione è una computazione parziale, quindi è una computazione è una sequenza di di configurazioni che rispetta queste proprietà che però ha una proprietà aggiuntiva. l'ultima configurazione della lista o non ammette passi successivi, cioè la funzione di transizione applicata allo stato dell'ultima configurazione, mentre legge il simbolo che c'ha di fronte, non c'è uno stato successivo, quindi lì la macchina si impalla. Oppure l'ultima configurazione ha come stringa residua la stringa vuota. Ripeto, una computazione. L'intuizione è questa. Come otteniamo la definizione di computazione dal dalla definizione di computazione parziale? Una computazione intuitivamente è una computazione parziale che non possiamo tirare di più, che non ci ci si può aggiungere roba. Ok? Quali sono le condizioni per le quali a una computazione parziale non possiamo aggiungere roba? Sono due: o l'ultima configurazione non ammette una prossima mossa perché non è definita, oppure la stita. Ok, è chiaro? Ci siamo quasi, dai. Ok. una computazione. È chiaro per tutti come si definisce una computazione partendo dalla computazione parziale? Ok? Qua ovviamente la computazione parziale su una stringa, la computazione su una stringa non è che esiste la computazione, ok? Una computazione su una stringa w cos'è una computazione parziale su W massimale? Cioè che non ci appiccichiamo altre, ok? una computazione, una computazione su una stringa W la chiamiamo accettante se nella sua ultima configurazione lo stato è accettante e la stringa residua è vuota. Dopo Ok? Scusate la sua configurazione, cioè quindi se noi abbiamo tutta sta lista di foto è una computazione, quindi non una computazione parziale, perché significa che questa è una lista massimale, non possiamo, cioè non succede altro, lì arriva e lì si ferma. Andiamo a guardare l'ultima foto. Se nell'ultima foto abbiamo che lo Stato è accettante e di stringa non c'è rimasta niente, allora vuol dire che quella è ci sta raccontando la storia di una computazione che alla fine dice sì. Ok, questo è il senso. Capito? Spiega nella soluta configurazione quella di Nell'ultima configurazione lo stato è accettante, è uno degli stati accettanti e il la stringa residua è ep è vuota. Ok? Ragazzi, vorrei solo sottolinearvi che stiamo formalizzando cose di cui dovete avere un'intuizione. Cioè, cos'è una computazione? intuitivamente nella mia testa cos'è una computazione? Perché se iniziate a vedere i simboli impazziti, cos'è nella mia testa una una computazione? È una sequenza di foto di foto che mi dicono lo stato di avanzamento dei lavori della macchina. Una computazione è una lista di foto che non ci posso appiccicare niente dopo. Ok? Come faccio a stabilire se questa lista di foto mi sta raccontando la storia di una computazione accettante? E vado a guardare l'ultima. Vado a guardare l'ultima foto. Se la macchina ha finito il suo input e si è fermata e non state accettato, allora vuol dire che quella è una computazione accettabile. Adesso tutta sta simbologia che usiamo è solo per formalizzare dell'intuizione che abbiamo. Però dovete partire dallle intuizione, senò è impossibile da capire sta cosa. Cioè manipolare simboli in testa senza avere un'intuizione viene difficilissimo. Come faccio io, io vi faccio queste immagini. Cos'è una configurazione? una storia di foto. Ta ta ta. Ok, cioè questa è la metafora che uso. Prego. Potrei definire unazione una conazione parziale in cui n uguale m Sì, sì, sì, sì, sì, sì. Eh, non sempre, perché tu pu potresti avere si potrebbe avere il caso in cui la macchina si arresta prima. Allora, nell'esempio visto ieri nella macchina di prima, quella macchina ha una funzione che la funzione di transizione ha la caratteristica di essere una funzione totale, cioè per ogni coppia stato simbolo so cosa fare. Altre macchine e avrei voluto avere il tempo di farvele vedere. La funzione è parziale, cioè arrivo in uno stato e io mi aspetto di leggere un certo simbolo. Se leggo altro la macchina si ferma là, non fa nient'altro. Quindi la sua computazione potrebbe avere una lunghezza inferiore se si è bloccata prima. In quel caso non potremmo eh distendere la funzione con dei cicli o la fai la butti verso degli stati spazzatura. Ognuno se la può definire come vuole, ok? Cioè sono tutte equivalenti, uno la definisce come vuole. Di nuovo non è orocolato, cioè noi abbiamo questa intuizione di come funziona una macchina. La sua formalizzazione può avvenire in tanti modi. L'importante è che sia. Ok? le ultime cose, quindi abbiamo detto che una computazione accettante è una computazione che termina di cui l'ultima configurazione ci sta raccontando la storia di una macchina che si è letta tutto lì ed è finita nello stato accettato. Ok? Una macchina, un automa sta definita accetta una stringa W. Se la computazione che parte dalla configurazione Q0W [Musica] termina in uno stato accettato. che una macchina accetta una stringa W se la configur se la computazione la cui prima foto è quella della macchina che parte nello stato iniziale e legge tutta l'astenita W è la prima foto di una sequenza che arriverà a quella in cui la macchina si è letto tutto e sta accettando. Ok? Quindi la macchina accetta W. Se la computazione che parte con la configurazione in cui la macchina sta leggendo W andrà a terminare in una configurazione accettante. È chiaro? Scusi, ma le varie definizioni che stiamo dando si intercambano tra di loro oppure sono scresse? No, si costruiscono una sull'altra perché quindi abbiamo al piano al piano terra abbiamo computazione parziale, poi computazione che è costruita sopra una computazione parziale. Poi abbiamo dato la definizione di computazione accettante, che è un sotto caso delle computazioni. E che cosa diciamo? una macchina accetta una stringa W se la computazione che inizia con la lettura di W è una computazione accettante, cioè arrivo in fondo e accettiamo. Ma quella che definiamo per ultimo che quindi tra virgolette è solo stack nel primo punto non si può definire se non abbiamo definito i teatre no perché sono tuttef specificazioni delle precedenti una comput una computazione accettante è una computazione. una computazione è una computazione parziale, cioè perché noi stiamo intuitivamente che stiamo facendo? Stiamo aggiungendo aggettivi, no? Quindi l'oggetto di analisi è sempre lo stesso. Ok? Stiamo restringendo l'insieme, abbiamo l'insieme di tutte le computazioni parziali. Tra tutte le computazioni parziali ci sono quelle di lunghezza massimale e quelle per noi le chiamiamo computazioni, puoi chiamarle totali? Computazioni totali. Tra tutte le computazioni totali ci sono quelle che vanno a finire in uno stato accettante. Quelle per noi sono le computazioni accettate parziali totali computazioni accettiremo quando un automa potrà eh risolvere o meno un problema decidibile. Ci siamo. L'ultimo passaggio. Un automa. Sì. No, no. Volevo chiedere di riprendere un attimo la definizione di accettazione. No, ha detto un automast accetta una stringa W se la computazione la cui prima configurazione è Q0 W va a terminare in una una computazione in una configurazione accettata. Ok? Cioè accetta W, cioè la storia delle foto in cui la prima foto è quella in cui la macchina sta leggendo W va a finire Sì, sì, sì. con quella e accetto. Ok? Cioè, poi ovviamente uno si può dare anche altre cose, eh? Un attimo, un attimo che sennò non terminiamo. Quindi questa è la definizione di accettazione. La macchina rifiuta una stringa quando questa cosa non è vera. Intuitivamente la macchina rifiuta la stringa quando o si impalla mentre la sta processando in uno stato non accettante oppure arriva alla fine, ma si è fermata in uno stato non accettante. Ok? E adesso la definizione che ci serve è quella che ci chiedeva il nostro collega, una macchina D. Ho visto, ho visto. Stava registrando l'audio. Questo I guess so. I hope so. Ah, dice che se Ah, sì, penso di sì. Ultimo passaggio. Un automa D decide un linguaggio L. Se ogni stringa W che appartiene ad L è accettata da D? E ogni stringa W che non appartiene ad L è rifiutata da D. Ok? Chiaro per tutti questa definizione. Quindi un auto, una macchina decide un linguaggio. Qual è l'intuizione? Cioè, ogni volta che gli diamo una stringa che appartiene a L, quella ci dice sì. Ogni volta che gli diamo input una stringa che non appartiene a L, la macchina ci dice no. Ok, chiaro per tutti? Vi ho fracassato bene la testa. Facciamo un po' di pausa 10 meno poi ho visto. Ok, ripartiamo. Avevo messo di far tutta una serie di cose, vabboh, sono il minimo indispensabile. Ok, abbiamo visto cos'è un automa. Abbiamo visto che ha stati infiniti, significa che il numero delle pallette è finito e non può crescere durante il calcolo. Ci sta lui. What else? Abbiamo dato la definizione formale, bla bla. Facciamo un salto. Facciamo un salto verso un'altra cosa, ok? Che ci introduce questo concetto che poi ci serve per touring machines più sofisticate per chi non avesse questi concetti. Ok? Supponiamo di voler riconoscere questo linguaggio. Eh, certo, [Musica] lo scriviamo con un'espressione regolare, così vediamo pure questo. La spieghiamo senza. Allora, vogliamo riconoscere questo linguaggio. Il linguaggio delle stringhe binarie in cui abbiamo una sequenza di zeri o uni. All'inizio, spiego un po' a chi non l'ha mai visto prima. Questa cosa qua significa che all'inizio abbiamo una sequenza di 0 o questa linea verticale dice o una sequenza di 0 o 1 ripetuta 0 o più volte, quindi può essere 00 101 10 bla bla bla che potrebbe non esserci perché c'è l'asterisco e però si deve concludere con tre zeri di fila. Ok? Consideriamo questa macchina. Siamo in Q0 è lo stato iniziale. Noi partiamo da qua e facciamo questo. Se leggiamo 0 rimaniamo in Q0. Se leggiamo 1 rimaniamo in Q0. Se leggo 0 vado in Q1, leggo un altro 0 vado in Q2, leggo un altro 0 vado in Q3. È intuitiva questa macchina, no? Cioè l'intuizione di questa macchina è in Q0 salto una sequenza di zeri e uni bla bla bla bla bla bla bla, poi a un certo punto leggo gli ultimi tre zeri. È chiaro il significato? C'è una semantica di questa cosa? Cioè, che cosa mi piacerebbe che questa macchina facesse? Chiaro per tutti? Che problema ha questa macchina? Un attimo. Hai seguito linguaggi? Non ho no più una domanda. Se io sono in Q2 Q2 con uno io devo tornare indietro? No, se vecchio rimare bloccato là perché la funzione di transizione la definita così come è scritto questo grafo. Ok? Allora, dove aspetta che chi ha seguito linguaggi? La risposta la sapete, voglio sentire gli altri. Che problema c'ha questa macchina? Guardate che è intuitiva. A morì sta macchina salta un po' di zeri e un bla bla bla. A un certo punto mi leggo gli ultimi tre zeri. Ok. Lei non ha seguito linguaggi? No. Ok. Esattamente. Questa macchina ha questo piccolissimo problema. In Q0 se legge zero non sa che fare, cioè fa rimango in V0, vado in Q1. Ok? Però siccome siccome queste macchine, no, da un punto di vista intuitivo sono fantastiche perché ci permettono di programmare in maniera molto semplice delle cose, noi ok, le consideriamo lo stesso. Ok? Una macchina di questo tipo noi la chiamiamo non deterministica. e non deterministica perché ci sono delle configurazioni, cioè quindi delle foto, degli snapshot, del funzionamento corrente della macchina, delle configurazioni, le cui configurazioni legali successive possono essere più di una. È chiaro? Cioè, questo è il senso di macchina non deterministica. Questa è una macchina un pochino strana perché è una macchina che durante il suo calcolo ha dei punti di scelta non determinati. Cioè, non è che noi gli stiamo dicendo che fare in presenza nello stato Q0 quando legge zero. Noi non gli stiamo dicendo niente, gli stiamo dicendo queste sono le tue possibilità. Puoi rimanere il Q0, puoi transire il Q1. Ok? E questo è una è alla base del concetto di non determinismo. Definizione formale di macchina non deterministica. Allora, where is it? Questo qua N è automa stati finito non deterministico. Si definisce in maniera veramente similare a quello che abbiamo visto prima. Quindi rivediamola assieme. Da che cosa è caratterizzato un automa? Dagli stati. Dall'alfabeto. Ok. Quindi è pure una macchina non deterministica, è caratterizzata da un alfabeto e poi è caratterizzato da stati dagli stati, poi è caratterizzato da iniziale lo stato iniziale, poi è caratterizzato da gli stati accettanti E fino a qui la definizione è identica, ok? Dopodiché dobbiamo definire il suo programma, che è un pochino strano rispetto ai programmi della delle macchine deterministiche. Quindi avremo delta che è il programma di una macchina non deterministica. Ok? Poi faremo un po' di esempi e definiamo cos'è l'accettazione, trucchi di programmazione, perché qua si deve un po' giocare. Il programma che nelle macchine deterministiche era una funzione macchine deterministiche abbiamo che delta è una funzione che dato uno stato è un simbolo corrente andiamo in uno stato successivo. Nelle macchine non deterministiche delta è una la chiamiamo relazione. Possiamo definirla come funzione, però a volte la chiamiamo relazione di transizione perché dato lo stato corrente Q, vedete, fin qui è tutto uguale, è il simbolo che leggiamo scritto proprio da me dove sta? Qua è sigma. Ok, vedete? Cioè, la parte iniziale è uguale. Cambia l'output. L'output di questa funzione è invece di dirci qual è lo stato successivo ci dà un insieme di stati successivi, cioè mappiamo verso l'insieme delle parti, il powers set di Q. Ok? Quindi la funzione di relazione, quindi una macchina non deterministica, la sua definizione è quasi uguale a quella deterministica. Abbiamo i simboli, abbiamo gli stati, abbiamo lo stato iniziale, abbiamo lo stato accettante e fino a lì è la stessissima cosa. Quello che cambia è il suo programma. Il programma di una macchina deterministica è dato uno stato e un simbolo so che fare dopo per una macchina non deterministica e dato uno stato e un simbolo o una serie di posso avere una serie di scel. Come vedete non è che è sempre così. Nella macchina che abbiamo visto qua, il neterminismo avviene qua, ma il resto della macchina è deterministica, ok? Cioè, non è che una macchina non deterministica deve essere non deterministica in tutta la sua fase di esecuzione, cioè può avere del non determinismo. Ok? Quindi la differenza nella definizione di funzione di transizione che è una relazione dato lo stato corrente e il singolo letto correntemente. Non ho soltanto qual è il prossimo passo, ma ho un insieme di prossimi passi. Ok? Cos'è a questo punto una computazione parziale per una macchina non deterministica? Allora, se guardate i vostri appunti intuitivamente, che cos'era una computazione parziale? una computazione parziale è una sequenza di foto in cui la prima foto ci dice come la macchina svavia. La macchina si avvia nello stato iniziale con tutta la stend. Quindi è una sequenza di foto in cui avevamo detto che ogni foto deve essere il legal successor della sua precedente, cioè ogni foto deve essere la prossima configurazione legale secondo la funzione di transizione. Per le macchine non deterministiche è la stessima cosa, cioè una foto può seguire un'altra se lo stato nella seconda configurazione appartiene fra quelli disponibili che si possono raggiungere secondo la funzione, la relazione di transizione nella configurazione precedente. Tutto qua. Allora, nelle macchine deterministiche noi abbiamo che ogni configurazione determina qual è la sua successiva, perché sappiamo questo è lo stato, questo è il simbolo, la funzione ci dà un solo next step. Quindi date una configurazione, date una foto, noi sappiamo che è quella di do qual è. Lo stato è quello dato dalla funzione di transizione. La striga è che noi gli togliamo un singolo che è facilissimo. Nelle macchine non deterministiche una foto può seguirne un'altra. Basta che lo stato nella seconda foto è uno di quelli ammessi dalla dalla relazione di transizione a partire dallo stato e simbolo. Ok? Quindi in realtà adesso e potete capire che un automa non deterministico quando eh computa su una stringa può avere più computazioni differenti. Ad esempio, nell'esempio che abbiamo visto prima, questo qua, eh voi voi l'avete l'appunto. Ok? Supponiamo, ok, che vogliamo riconoscere questa stringa qua, 0. Ok? Allora, una computazione potrebbe essere Q00 seguito da Q0 seguito da Q 00 seguito da Q100 seguito da Q20 seguito da E seguito da Q3 vuoto. È chiaro? Cioè quella macchina quando legge abbiamo detto 01 che cosa fa? Legge il primo 0 e rimane qua. Legge 1 e rimane qua. Poi legge 0 0 e accetta. Questa cosa è fotografata da questa sequenza qui. Però questa macchina potrebbe fare pure un'altra cosa. Al primo zero, invece di rimanere qua, se ne va avanti. Quindi un'altra questa è una computazione legale su 0100 per la macchina N. Però un'altra è questa qui. Partiamo sempre da Q0. Ok? Vedete? La prima foto è sempre la stessa, Q0. Poi andiamo avanti e facciamo Q1. Dopodiché la macchina si blocca perché in Q1 non abbiamo Ei, in Q1 non abbiamo la definizione di lettura del simbolo 1. Ok? E quindi questa è una computazione e questa è un'altra computazione. Tutte e due sono legali, ok? Perché rispettano il fatto che le foto in sequenza aderiscono al alle regole dettate dalla relazione di transizione. Ok? Però che cosa abbiamo? che questa qui, la prima, è una computazione accettante perché andiamo a finire in una configurazione accettante. Mentre la seconda, sebbene sia una computazione legale, è una computazione rigettante, come si dice in italiano, rejecting rifiutante. Ok, è chiaro dov'è qua il bous della questione? Noi abbiamo questa macchina che riceve input su, una stringa, ha due computazioni legali, ok? In una accetta e in un'altra rifiuta. Allora, la questione qui è ma questa macchina la stringa 0100 l'accetta o la rifiuta? L'accetta. Come? Perché noi cambiamo la definizione di accettazione per una un'automa a stati finiti non deterministico N accetta una stringa W se esiste [Musica] una computazione di n su w che sia accettabile. L'intuizione qual è? Una macchina non deterministica accetta una stringa se esiste un modo per accettarlo. Questo è Ok. E siccome la esiste un modo per la stringa 0100 di essere accettata da questa macchina qua, allora vuol dire che quella macchina la stringa l'accetta. Ok? Ok. Questo è il passaggio importante, eh, una macchina non deterministica accetta una stringa input se esiste un modo per accettarla. Ok, prego. Scusi, l'automa che ha disegnato lei è un è un automa D errato e un mentre un automa N corretto. Sì, è un automa non deterministico. Sì, una macchina non deterministico. accetto una stringa input se esiste un modo per la macchina di accettare la stringa. Quindi proprio quando per capire se effettivamente una stringa do W è accettata dovrà provare tutte le possibili combinazioni. Sì, adesso adesso vi spiego un po' sta faccendata. Allora, è interessante questa domanda qui che ci ha fatto la nostra collega. Ho detto "Ma allora una macchina non deterministica per accettare la propria stringa prova tutte le strade?" Oppure la domanda che ci ha fatto il nostro collega, ma se una una macchina non deterministica, mentre nel calcolo a un certo punto si accorge che ha sbagliato, che fa? Torna indietro? Ok? Oppure altri dicono "No, non fa questa cosa qua." Una macchina non deterministica prova tutte le strade contemporaneamente. Questa è un'altra metafora. Ok? Adesso, seconda volta, una macchina non deterministica che fa? Le prova tutti assieme, le prova una dopo l'altra, torna indietro, fa backtracking quando sbaglia, che fa una macchina non deterministica? Non è il path problem, cioè non è il problem, è anche un path problem, però supponiamo di avere questa macchina, ok? Ma una bellissima automa stati finiti non deterministico. Eh, gli infiliamo un input come quello là, quindi sul quale la scelta che fa sul primo zero fa la differenza. È chiaro per tutti? Quindi se la macchina sul primo zero rimane in q0 alla fine accetterà. Se la macchina sul primo 0 si sposta in Q1 rifiuterà. Ok? Ma allora sta macchina che fa? li prova tutti contemporaneamente, li prova uno dopo l'altro, fa backtracking. Che fa sta macchina? Essendo un deterministic prova casualmente la prima strada che Ok, questa è un'altra metafora. La macchina tira un bel dado e cerca di stabilire da che lato andare. E se il dado, se la Flipcoin non funziona, si impalla e muore. Si impalla e muore. Questa è una possibilità. Eh sì. un'altra possibilità se fisse dal fondo, cioè nel senso parte da uno stato da uno stato accettante e poi va e ok, però ci sono quelle che per esempio avresti non determinismo a tornare indietro, ok? Che fa sta macchina? le fai in parallelo, tira la monetina, usa la palla di cristallo. Eh, non abbiamo definito un algoritmo, quindi, cioè, io immagino prova a fare a eseguire, cioè a leggere la stringa e se sarà stata accettata sarà stata accettata, altrimenti se sarà stata riata, cioè perché non abbiamo definito un algoritmo, l'algoritmo è quello, eh però ed è dato dalla relazione di transizione. Eh, però siccome non è deterministico, allora quello che farà fare una volta e basta. Ma lo fa una volta e basta e se prende la strada sbagliata e la B andiamo a sbattere al muro. Eccolo e questa è anche una possibilità. Prego. Può guardare più simboli? Può guardare più simboli? No, la macchina ne guarda uno solo, guys. Oh, prego. Io penso che faccio un backing. Back tracking. Ok. Allora, volete una soluzione? La domanda è mal posta. Questa macchina non fa niente perché questa macchina non esiste. Non esiste un una macchina fisica in grado di fare una cosa di questo tipo. Questo è un modello astratto. Punto. Quindi non va né in parallelo, non falli tentativi, non usa la palla di cristallo, non tira la monetina. Questa macchina non esiste. Questo è solamente un modello astratto di calcolo che ci siamo inventati per semplificarci lo studio dei linguaggi. Tutto qua. Però ovviamente quando noi poi dobbiamo andarle a programmare queste strade non queste macchine non deterministiche una metafora in testa la dovremmo avere. Questa è la metafora che uso io e in genere mi ci trovo bene. La macchina quando arriva un punto di scelta se c'è un punto corretto, se c'è una scelta corretta la prende bene come Eh, certo. Non esiste, me la invento come voglio. Devo stare attento però che poi io verifichi, poi questo lo vedremo di più sulle sulle macchine di Touring, faremo degli esempi più specifici perché là poi dobbiamo stare attenti, eh, ci inventiamo, cioè dobbiamo stare attenti, vi faccio vedere velocemente questo qua. Voi state voglio far notare una cosa su questa macchina qui. La macchina sta facendo il guess, cioè sta indovinando che fare. Ok? Però una volta che la macchina ha risolto la questione su un certo zero, se andare avanti verso Q1, rimanere in Q0, come vedete questa macchina fa un controllo deterministico, cioè io poi alla fine devo verificare che non ho preso una cantonata perché perché questa macchina non esiste, quindi non è che è una macchina che veramente ha la palla di cristallo ed è in grado di fare questa cosa. La condizione di accettazione di questa macchina è la macchina accetta se esiste un modo per accettare. Ma quindi allora dobbiamo definire la sua relazione di transizione in maniera tale che se la stringa va rifiutata non ci siano modi per accettare. Ecco perché intuitivamente, poi vedremo più nel dettaglio, io metto questo controllo finale. È chiaro? Allora, perché perché ci siamo quasi, dai. Perché? Scusi. Sì, ma quindi la definizione la relazione del dell'emn Sì. Eh, dobbiamo formalizzare meglio oppure basta quello che abbiamo già dato? Ah, basta quello che abbiamo già dato. Ok. La ripeto, la definizione di macchina di automa non deterministico a che delta è una relazione di transizione invece che di una funzione di transizione. Ok? Questa è la differenza. Cos'è una computazione? Va semplicemente cambiata. Eh, qui, vedete qua nella definizione di computazione noi abbiamo che lo stato al passo i + 1 è dato dal risultato dell'applicazione della funzione di transizione sulla coppia stato al passo i simbolo che mi devo leggere. Nel caso di macchina non deterministica, questo pezzo qua è semplicemente sostituito che invece dell'uguale ciò appartiene, capito? Tutto qua. Quindi questo è il pezzettino che dobbiamo cambiare. Poi una computazione accettante si definisce allo stesso modo, quindi è una computazione legale la cui ultima foto è una configurazione accettante. Cambia la definizione di accettazione. Una macchina non deterministica accetta una stringa W se esiste una computazione accettante della macchina su doppia B. Questa è l'unica differenza per le macchine deterministiche dalta W c'è un'unica computazione, quindi quella o è accettante o non accettante. Sulle macchine non deterministiche, siccome possono esserci più computazioni sulla stessa W, allora noi diciamo che la macchina accetta W se fra tutte le computazioni che può fare sul W almeno una è accettabile. Questa è la differenza di definizione. Una macchina, un automa non deterministico decide un certo linguaggio L se accetta tutte le stringhe che appartengono a L e rifiuta tutte le stringhe che non appartengono a L. Ok? Quindi cambia giusto la definizione di computazione, relazione di transizione e la condizione di accettamento accettazione. Chiaro? Ok. Allora, le stiamo facendo perché poi le rivedremo su tuning machines. Su tuning machines rivedremo queste definizioni con dei pezzi in più. Ok? Son voluto partire da qua perché sono proprio base, poi ci aggiungiamo dei pezzi e qua magicamente abbiamo delle definizioni di teorie di machine. Ok? Perché la gente si è rotta la testa a studiare questo tipo di di automi? Perché, come avete visto, sebbene siano strani, hanno una certa semplicità di programmazione perché dici "Oh, cavolo, la macchina indovina" è è facile. Ok, esiste un risultato che chi ha fatto il corso di linguaggi conosce, però non rivediamo qui, che dimostra che tutto ciò che è decidibile da un automa non deterministico è decidibile anche da un automa deterministico. Ok? esiste un modo per convertire uno nell'altro, non lo vediamo, se ne andrebbero due lezioni, è una cosa che non abbiamo il tempo di fare. Ok, quindi perché si fa? Perché programmare un automa non deterministico è intuitivamente più semplice e poi lo do in pasta un traduttore. Il traduttore prende la macchina non deterministica, tira fuori la macchina deterministica e abbiamo quello che ci serve. Perché se vogliamo eseguirlo su una macchina fisica ci serve un programma deterministico. Ok. Ultimo pezzo. Eh eh eh eh eh. Ultimo pezzo, vediamo di fare tutto in 10 minuti. Do un'intuizione di un risultato che non dimostreremo in tutti i dettagli perché non c'è tempo, però giusto per farvi vedere che insomma con queste macchine non è che possiamo fare quello che vogliamo. sono macchine semplici che riconoscono linguaggi semplici sostanzialmente. Ok? Allora, supponiamo di voler riconoscere questo linguaggio qui. Abbiamo l'alfabeto dei simboli AB e il linguaggio è questo, l'insieme delle stringhe ammale che M è un intero maggiore o uguale di 0. Che cosa significa? Questo è il linguaggio, un linguaggio sull'alfabeto dei simboli A e B che contiene tutte le stringhe formate da un primo gruppo di ma, quindi a elevato M per noi significa che ci sono m simboli a seguito da un gruppo di Moli B. Devono essere M. Se ce ne stanno 3A ci devono essere 3B. Se ci stanno 4 A ci devono essere 4B. Ok? È chiaro questo linguaggio? Che cos'è? Adesso questo linguaggio che è semplicissimo. In Python sapreste scrivere un programmino che date in input una stringa di A e di B è in grado di dire sì. C'è la stringa ha quella forma. Sì, in fondo sì. Ok. è un linguaggio riconoscibile, cioè un computer standard per noi è in grado di farlo. Però un automa stati definiti deterministico e non deterministico perché vi ho detto che hanno lo stesso potere espressivo, non è in grado di farlo. Ok? E adesso cerchiamo di dare solamente un velocissimo perché in 10 minuti non ce la facciamo, un'intuizione del perché non può esistere un automa stati definiti che è in grado di riconoscere questo linguaggio. Mi ero preparato pure delle slide, vediamo un po'. E mi sono dimenticato di prendere giustamente. Allora, vediamo un po'. Alri, me lo fa scaricare sta Geg? Eh, poi poi non funziona perché non si vede bene. Ok, zoomiamo qua. Alrgri. Ok. Allora, che problema ha sto cavolo di linguaggio? Allora, il problema di questo di questo linguaggio è, come abbiamo detto amm in cui m è maggiore o uguale di 0. Il ciò significa che la stringa vuota dobbiamo essere in grado di accettarlo. Quindi un primo automa, un primo pezzo di questo automa potrebbe essere uno stato iniziale che è anche accettante perché se non leggiamo niente dobbiamo rispondere sì. Ok? Quindi quest'automa qua è in grado di accettare la stringa vuota. è in grado di accettare la stringa AB? No, ci serve un pezzo aggiuntivo e andiamo qua. Ok? Questo automa è in grado di riconoscere EP, è in grado di conoscere AB perché che legge A e va su, legge B scende giù e accetta. Ok? Ma questo automa è in grado di accettare A BB? Sì. No, no, no, perché A perché una volta che è arrivato qua non c'è la seconda a, no? Ok, ci aggiungiamo un pezzo. Ok. A A B. Ok. Adesso saremmo in grado di riconoscer è sufficiente? No, perché non saremmo in grado di conoscere nemmeno a A a A B b. Ok? Allora, ci serve un altro pezzo, ma questo non riconoscerebbe stringhe più lunghe, ci servirebbe un pezzo ancora più lungo, ma questo non riconoscerebbe stringhe ancora più lunghe, ci servirebbe qualcosa di ancora più lungo. Allora, l'intuizione è che un autonoma stati finiti, come in questo caso, non è in grado di contare perché non ha, poiché il suo numero di stati è finito, non è in grado di tenere traccia di una storia di computazione di lunghezza. Cioè non è in grado di fare 1 2 3 4 e poi di nuovo 1 2 3 4. Questa cosa un automa stati finiti non lo sa fare, cioè non sa contare le cose e ricordarsi il conteggio. Se deve sapere che se deve, come abbiamo visto prima, vedere tre zeri di fila e sa fin da subito che devono essere tre, allora si fa tre passaggi di stato. Ma se io devo contare, ricordarmi sto numero e poi ricontare di nuovo per vedere che i miei numeri sono uguali, allora questa cosa non è in grado di farla. Ok? Questa ovviamente è un'intuizione, esiste una dimostrazione formale che mi sa che il tempo non l'abbiamo, però cerco di darvi un'intuizione su come si mostra. Ok? Supponiamo supponiamo che invece siamo in grado di costruire un automa a stati finiti, no? Che in grado di riconoscere queste stringhe a a b. Ok? Supponiamo noi lo assumiamo deterministico perché sappiamo che non è meno potente di un non deterministico. Ok? Quindi supponiamo che esista un automa stati finiti deterministico in grado di riconoscere questa questo linguaggio strano. Ok? E siccome un automa stati finiti avrà un numero finito di stati. Diciamo che sono P, sono 5 10 18 32 P gli diamo un nome, ok? Quindi questa automa ha un numero P di stati. Ok? Allora, noi che cosa facciamo? Se questo automa riconosce questo linguaggio, deve essere in grado di decidere tutte le stringhe di questo linguaggio, non solo quelle piccole, anche quelle grandi. E allora gliene diamo in input un enorme. Ok? Che ne so? L'automa c'ha 18 stati, gli diamo in input una stringa di 2000 caratteri. Ci sono 1000 A e 1000 B. Ok, chiaro che cosa stiamo facendo? Alr, proviamo a visualizzare un po' nella nostra mente che cosa fa questa macchina mentre calcola questa macchina di solo 18 stati mentre processa questa stringona, ok? 2000 caratteri. Quindi partiamo e la macchinia sarà in un primo stato. Poi andrà leggerà una a una a e andrà non sia meglio. Yes. Legge una A e andrà in un secondo stato. Poi legge un'altra A, andrà in un terzo stato. Legge un'altra a, andrà in un quarto stato, in un quinto, in un sesto, bla, bla bla bla, fino a quando arriva alla lunghezza 2m che per noi è 2000. Ok? Cosa sta facendo questa macchina? Sta, come abbiamo visto, transendo da uno stato all'altro mentre si sta guardando questi caratteri. Ok? Allora, noi abbiamo una sequenza di 2000 passi, ma la macchina ne ha, diciamo, solo 18, come dicevamo prima. Sto dicendo 18, potrebbe essere 172. Ok? È un numero piccolo, quindi facciamo 2000 passi, ma la macchina ha un numero di stati molto piccolo. Che cosa possiamo dire su questa sequenza di stati? [Musica] Sì, qualcuno di quegli stati si deve ripetere, no? Per il pigon all principle, se io vado avanti 2000 stati e ne devo pescare da un insieme di 18, a un certo punto sti stati si devono ripetere, ok? Cioè non è possibile che siano tutte e 2000 differenti. Vuol dire che la macchina mentre sta girando a un certo punto deve per forza rivedere uno stato da cui c'era stata prima, ok? perché il suo numero di stati è limitato e la stringa che sta processando è catastroficamente enorme. Ok? Quindi la sequenza di passi che la macchina fa non è tanto lineare, ma è più qualcosa di questo tipo. Cioè a un certo punto la macchina deve tornare su una cosa da cui è già passata. Ok? Adesso poi se volete vi leggete il commentino, visto che ho 2 minuti e non posso andare oltre. L'unica cosa a cui dobbiamo stare attento è siccome stiamo assumendo che la macchina è deterministica, qui in questo stato qua, non posso avere A qui e A qui, altrimenti sarebbe non deterministica. Quindi questo anello si deve appendere alla fine delle A. per forza. Di conseguenza, questa macchina che cosa riconosce? Legge A a A a A, poi legge a A a A a A a A, poi ci stanno le B. Quindi questo qui potrebbe essere un giro di MA e poi seguito da MB. Però se la macchina ha questa forma, in realtà accetta anche a a a ah tutte queste, poi si fanno un altro giro, un'altra ancora, un altro ancora e poi si legge le B. Di conseguenza questa macchina non ha il vincolo di vedere tante B quante A. Può vedere più A di B per la sua struttura di com'è fatto, perché perché questa macchina non sa contare. Ok. Cosa tiriamo fuori da ciò? Che ci sono linguaggi e problemi, no? Questo qua è leggere se ci sono tante AT B. È come avere un problema del tipo conta gli elementi di questi due insieme e dimmi che è lo stesso numero, ok? È lo stesso identico problema. Allora, questo problema che noi sappiamo essere risolvibile tramite un semplicissimo programma Python in realtà non è risolvibile su un automa stati finiti e infatti gli automi a Stati Uniti non sono un formalismo sufficiente sufficientemente potente da permetterci di dire cosa è decidibile e cosa non è decidibile. Questi automi dobbiamo arricchire in qualcosa di più sofisticato che siano in grado di riconoscere i linguaggi più tosti e otterremo il modello che è il modello della macchina di touring, che è un automa più potente di quello che abbiamo visto e mostreremo che ha la potenza di tutti i computer. Questa cosa la vedremo dalla prossima settimana, ok? Chiaro per tutti? Ok. Grazie mille. Buona giornata. [Musica] Eh