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.
10.
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.