Ok. Ok.
[Musica]
Ok. Quello che vedremo oggi sono un po'
di eh
sprills
di optionals che si possono aggiungere a
macchine di touring, perché le macchine
di touring che abbiamo visto finora sono
molto semplici da trattare, molto
semplici da definire, però sono
difficili da programmare perché,
insomma, abbiamo visto è un gran casino.
Quello che vedremo oggi sono delle
varianti di macchine touring che
scopriremo
essere equivalenti a quello che abbiamo
visto. Ok?
Eh,
allora
consiglio su come studiare, almeno anche
torno alla cosa che potreste fare,
quindi facciamo un recapissimo
stamattina al termine delle lezioni o
comunque quando vi rivedete gli appunti
cercate di estrapolarvi le domande
chiave di quello che abbiamo visto. Ok?
Ok. Ma quello che abbiamo spiegato oggi
a cosa sta rispondendo? Questa è la cosa
è lo stesso gruppo di quilibri, ma
questo paragrafo a cosa sta rispondendo?
Quindi proviamo a vedere che concetto
abbiamo visto finora.
Abbiamo visto problemi. Cos'è un
problema? Di cosa è caratterizzato un
problema? Che cos sono i problemi delle
di ricerca? Che sono i problemi di
decisione? Qual è il loro rapporto? Che
c'entrano i linguaggi con i problemi di
decisione? Perché usiamo i linguaggi?
Cos'è una macchina di touring? Com'è
definita? Qual è la condizione di
accettazione per una macchina di
touring? Ok, cioè queste sono possibili
domande. Che significa che una macchina
di Touring decide un linguaggio? Che
significa che una macchina di Touring
accetta un linguaggio? Che differenza ci
sta? Ok, questo, per esempio, sono un
po' di cose che abbiamo visto finora.
Ok? E quello che introdurremo oggi,
quindi, abbiamo delle varianti di
macchine. Delle varianti di macchine.
Allora, riprendiamo un esercizio che
abbiamo visto ieri
che era
che succido, ok? che era quello VRR,
vi ricordate tale che W appartiene a 01.
Ok? Allora, chi aveva quella macchina?
Quella macchina, praticamente, per come
l'abbiamo progettata,
il suo principio di funzionamento era
becco un carattere all'inizio, vado a
cercare lo stesso carattere alla fine.
Quindi se leggo zero all'inizio cerco
zero alla fine, se leggo uno all'inizio
cerco uno alla fine. Quindi avevamo
sostanzialmente due parti di macchina.
Facciamo uno sketch veloce. Qua avevamo
Q0 e avevamo questa parte che si gestiva
la lettura dello zero e poi arrivava a
un certo punto e questa parte che si
gestiva la lettura dell'uno e poi
tornavamo indietro. Era una cosa di
questo tipo. Ok?
Quindi noi avevamo necessità di due
branch di computazione della macchina
perché la macchina aveva necessità di
ricordarsi
se l'ultimo carattere, se il carattere
che aveva letto all'inizio della
steringa, era 0 o 1. Ok? Allora, l'idea
è non sarebbe molto più bello se la
macchina potesse memorizzare quello che
che ha letto in maniera tale che non
dobbiamo fare sto gran casino, ok? Ed è
quello che facciamo ora. introduciamo un
modello di macchina leggermente più
sofisticato che la macchina con la
memoria nello stato, ok? Cioè è una
macchina
[Musica]
che ha come dei registri di memoria
nello stato nel quale può memorizzare
dei simboli, ok? Un po' come i
processori che hanno i registri,
assumiamo che questa macchina abbia un
certo numero di registri interni.
tipo certo stato O1
c'è uno spazietto. Ok? Nel quale il
primo pezzo dello stato ci dice la
modalità di funzionamento della macchina
e poi quest'altra cosa qui, adesso
vedremo come usarla.
Sorry guys.
[Musica]
Allamo.
Memoria. Memoria. Ok.
Non entreremo nei dettagli delle
definizioni, guarderemo giusto un po'
come sta macchina funziona. Faremo un
esempio di eh di utilizzo. Dopodiché
vedremo che questa macchina non aggiunge
niente a quello che abbiamo già visto.
Ok? Però siccome poi saranno
equivalenti,
possiamo assumere di poter demonizzare
roba, ok? per semplificarci il nostro
lavoro. Prima detto, assignamo che la
macchina non c'è il tuo di stati
di stati e nello stato la macchina può
memorizzare delle informazioni, può
memorizzare i singoli, ok? Come se
avesse delle cellette di memoria insieme
nel suo nella fine controllo nel suo
nella sua funzione di transizione, cioè
nel processore, diciamo, della macchina.
È come se la macchina avesse delle
cellette di memoria. Ok? Queste cellette
possono memorizzare, ogni cella può
memorizzare un simbolo soltanto, un
simbolo di nastro. Ok?
Quante celle può avere la memoria? Per
esempio, in questo caso noi potremmo
definire, che ne so, uno stato così in
cui abbiamo che Q1 è la modalità di
funzionamento della macchina e questo
spazio qui e che cosa sta memorizzando
in quel momento. Con questa notazione
noi intendiamo che la macchina può
memorizzare un simbolo soltanto. Ok?
Quanti simboli può memorizzare la
macchina? Ne può memorizzare uno, ne può
memorizzare due, ne può memorizzare 10,
100000, ne può memorizzare quanti ne
vogliamo.
La caratteristica è che il numero di
simboli, cioè quanti registri, quanto
spazio ha la macchina nello stato per
memorizzare, viene deciso al momento
della progettazione. Ok? Cioè la memoria
non cresce durante l'esecuzione. Non è
che la macchina mentre esegue "Oh, dai,
qua mi serve più memoria, me la
espando." Ok, la memoria è fissata. È
fissata nel progetto della macchina non
cambia. Nel momento in cui diciamo che
ci stanno 10 celle di memoria, 10 celle
ci stanno, non più di quelle si possono
usare. Ok,
chiaro questo?
Please,
se non siete interessate lasciate
seguire i vostri commenti.
Allora,
come sfruttiamo questa cosa? Supponiamo
di voler riconoscere questo linguaggio
qui.
Cioè, e questa qui è un'espressione
regolare, no? linguaggio descritto
tramite espressione regolare. Noi
vogliamo riconoscere le stringhe binarie
che iniziano con un simbolo e tutti gli
altri sono differenti,
quindi è 1 seguito da zeri o è 0 seguito
da 1. Ok? Da uni. Alrght allora quello
che noi sostanzialmente facciamo, giusto
per vedere come funziona questa macchina
è che noi leggiamo il primo simbolo, lo
mettiamo nel registro, ok? Dopodiché ci
aspettiamo di leggere cose diverse da
quello che è in memoria. Tutto qua? Ok?
Quindi velocemente noi possiamo
descrivere questa cosa così. Q0
blan.
Questo è lo stato iniziale che ci dice
che iniziamo in q0, abbiamo una cella di
memoria e all'inizio nella memoria non
ci sta niente, cioè il simbolo vuoto.
Ok?
Dopodiché
leggiamo
dopodiché leggiamo il primo carattere e
lo induiamo in memoria. Questa cosa la
scriviamo così: leggo un generico
carattere alfa,
lascio lo stesso carattere sul nastro
e vado avanti. Ok.
Come scrivo che lo memorizzo. Si scrive
così: transisco in uno stato Q1 e nella
cella di memoria metto alfa che è quello
che abbiamo letto prima. Ok?
Quindi siamo in Q0, in memoria non ci
sta niente.
Leggiamo un carattere alfa,
un simbolo alfa, dove alfa è generico.
Alfa è un simbolo generico che
appartiene a 0 1. Ok?
Leggo alfa, lascio alfa, vado avanti e
alfa lo metto nella memoria disponibile.
Ok? Fatto quello,
sostanzialmente devo saltare, devo
ciclare cose diverse da alfa.
Possiamo scrivere una cosa del tipo alfa
soprasegnato o alfa negato per dire che
è il contrario di alfa. Quindi mi
aspetto alfa negato, vado avanti e salto
tutto. Ok?
Elementi in alfa però bene un elemento
alfa.
ripetere se fosse alfa avessenti sempre
lo so. No, 0 1 e 2. Ah, ok, ho capito.
Eh,
questo dire potrebbe essere 1 e 2. Se
fossero Sì, possiamo scrivere se alfa,
come il nostro collega ci suggerisce è 0
1 2, noi potremmo definire un simbolo
beta, ok? e poi stabilire che beta
che beta è diverso da alfa. Ok? Basta
che lo scriviamo che cosa intendiamo e
ne va bene. Ok? Cioè deve essere chiaro.
Adesso, siccome i simboli di Aon due,
mettiamo alfa. Eh, così avremmo potuto
scrivere beta con beta che appartiene a
01 e beta diverso l'alfa. È la stessima
cosa. Ok?
Dopodiché quand'è che ci accorgiamo che
abbiamo finito?
Quando arriviamo al blend, ok? Blan blan
e andiamo avanti. Andiamo nello stato Q2
in cui nella memoria non ci serve più
niente. Ok? E a quel punto accettiamo.
Ok?
È chiaro? Come funziona? Funziona il
principio? La definizione richiederebbe
il fatto di stabilire stati aggiuntivi
eccetera. Non la guardiamo, non ci
interessa. Ok? Vogliamo solo vedere come
funziona, perché quello a cui noi
puntiamo è la macchina che vedremo dopo
la base. Stiamo adesso costruendo dei
pezzi intermedi per arrivare fin. Ok.
Allora, secondo voi questa macchina che
può memorizzare l'oppa è più potente?
Quando quando dico più potente intendo è
in grado di accettare i linguaggi che
macchine standard non sono in grado di
accettare?
Sì. No,
che per sì,
che per no. Ok. Perché no?
che questa cosa della memoria è una cosa
sintattica tra virgolette per evitare
indicazione. Sì, perché sostanzialmente
questa questa descrizione qui
questa descrizione qua è semplicemente
un modo compatto,
ok? di
scrivere una macchina più grossa che è
sostanzialmente questa qua.
Sono in Q0 e non c'ho niente.
Ok,
leggo 0, lascio 0, vado avanti e vado in
Q1,0.
Oppure leggo 1, lascio 1 e vado avanti e
vado in Q1,1.
Poi qui salto i zeri,
qui salito gli uni
e dopodiché
se leggo bianco lascio bianco per vado
avanti in entrambi i casi e vado in uno
stato accelente V2 bianco. Ok? Cioè,
sostanzialmente noi stiamo scrivendo in
modo compatto questa macchina qua. Di
fatto gli stati di una macchina con
memoria nello stato sono gli stati che
sono ottenibili tramite il prodotto
cartesiano del simbolo di stato e i
possibili simboli gamma. Ok? Cioè noi
basta che diamo nomi diversi a questo,
questo, questo e questo e fatto?
Cioè il fatto di avere coppia, stato
simbolo è un modo di dare nomi a stati.
Questo si poteva chiamare Gigi, Luto,
Paperino e Topolino. Ok, prego. Prima ha
citato una macchina standard macchina di
Turing, quella che abbiamo visto. Sì,
ieri. Ahah.
Ok. Quindi quello che abbiamo visto
finora
è una macchina che pare sappia
memorizzare, in realtà è semplicemente
un modo convenient per noi per
pensare che stiamo memorizzando cosa
negli stati. è semplicemente un modo per
scrivere in maniera compatte macchine e
quello e questo tipo di macchine sono
riscrivibili macchine standard nel quale
semplicemente incrementiamo il numero
degli stati e gli stati gli diamo il
nome stato simbolo.
Ok? Questo lo potevamo chiamare 0 1 2 e
3 e alla fine è la stessa cosa. Ok?
Tutto qua. Quindi questo ci semplifica
la scrittura delle macchine, però non ci
dà più potere. Ok.
Alright. Introduciamo ora
un altro modello
che è il modello della macchina
multitraccia.
macchine multitracce. Allora, chi sono
le macchine multitracce? Di nuovo sono
un trucchettino che ci inventiamo per
riuscire a gestire più cose
contemporaneamente, ok? E semplificarci
la la il design di macchine di Ok?
Allora, le macchine multitraccia sono
macchine che hanno un nastro
e questo nastro è diviso in più traccia.
Ok?
Facciamo un esempino.
Quindi abbiamo una macchina con un
nastro bello grosso
e sul nastro si possono scrivere più
simboli inonati. Ok.
Quindi, per esempio, abbiamo X, Y
a B.
Ok? Quindi abbiamo un nastro
diviso in più tracce. Sono come le
corsie della strada, no? Le corsie
dell'autostrada che in autostrada ci
stanno 3 4 sette corsie, ok? Non so se
siete stati a Las Vegas, c'è
l'autostrada di sette corsie che dentro
la città. Divertentissimo guidarci.
Allora, è tipo quello. Il nastro è come
la strada e abbiamo più corsie sul
nastro. Ok. Abbiamo una testina bella
grossa
che è in grado di leggere tutte le
corsie, tutte le tracce. Ok?
Quindi il nastro è diviso
orizzontalmente in tracce.
Ogni traccia su ogni cella può contenere
un simbolo
che non è non è necessariamente legato
agli altri. Ok? Abbiamo una testina
bella grossa che è in grado di leggere
il nastro. Ok? Pecculiarità della
testina è che la testina è una. Ok? E
quando la spostiamo da un lato o
dall'altro, la testina si sposta come
monoblocco, ok? Quindi si sposta di una
cella e va a leggere tutte le tracce
dell'altra cella, ok? Non è che la
possiamo piegare o fare cose strane, ok?
La testina è un unico blocco, questa
tipa si sposta avanti e indietro e si
sposta tutta assieme.
Ok?
Come definiamo il funzionamento della
macchina? cioè come programmiamo la
funzione di transizione di questa
macchina. È una cosa molto simile alle
macchine standard
e funziona così. La funzione di
transizione è determinata
da tutti i simboli che vedo su tutte le
tracce, ok?
Quindi,
ad esempio, se io ho due tracce, no? E
supponiamo di avere un alfabeto.
Scriviamo, supponiamo di avere due
tracce.
Ok, quindi abbiamo due tracce.
Su queste tracce ci possono apparire
simboli e la testina legge 0 1 o 1 1.
Questi sono due casi distritti per la
macchina. Quindi se sono in uno stato Q
leggere 01
e leggere 1 per la macchina è una cosa
diversa. Ok? Quindi la macchina che fa?
Guarda tutti i simboli su tutte le
tracce per stabilire che fare. E che
cosa può fare la macchina? Può
sovrascrivere tutti i simboli di tutte
le tracce con i simboli che vuole. Cioè
può scrivere una cosa sulla prima
traccia, una cosa sulla seconda. Ok? E
poi sposta l'unica testina o a destra o
a sinistra. Ok? Vi ripeto, la testina
non si smonta, non è che andiamo sulla
prima traccia da un lato e sull'altra da
un altro lato, cioè la testina si piglia
e si sposta a blocco. Ok. Sì, ma le
singole tracce possono muoversi eh a
velocità diverse? No, la traccia tu eh
voi non l'avete mai visto un
registratore multitraccia, cioè abbiamo
un nastro
che negli anni 60 quando si andava gli
studio li ho visti, però quando si
registrava la musica ora ci stanno
no digital audio water station quando si
fa la registrazione multitraccia della
musica e mi servono più tracce degli
strumenti, si hanno vari file. Quando
non si facevano ste cose, come si
faceva? Si usava un nastro magnetico
bello grosso, che era diviso in
pezzettini, in tracce. Nella prima
traccia ci stava il cantato, nella
seconda traccia ci stava la batteria,
eccetera. Ok? Però la testina era una
sola, quindi andava tutto alla stessa
velocità perché sto nastro scorreva e la
testina leggeva le tracce differenti.
Dopodiché uno potrà decidere: "Ok,
adesso cancello la voce perché è uscita
male" e ci sopra scrivevano sopra, ok?
solo su un pezzettino del nastro. Quindi
la traccia è una cosa del nastro, cioè
il nastro è caratterizzato da queste
linee, diciamo. Quindi quando la testina
si sposta si sposta sopra il nastro e la
traccia non è che io posso,
come si dice in italiana, che non
schiudo, ma non le posso fare cose
strane, ok? Si sposta sempre assieme,
ok? e solidare. Poi vedremo dopo la
pausa un modello più sofisticato ancora,
ok? Chiaro? Quindi proviamo a fare un
esempio
di utilizzo di una macchina del genere.
Ok? Allora,
vogliamo riconoscere il linguaggio L.
W che è un altro degli esempi
tale che W appartieno a o P plus.
Ok? Questo è l'ultimo esercizio che
abbiamo visto ieri. Adesso utilizziamo
una macchina multitraccia per vedere
come si può si può fare.
La prima traccia. Noi supponiamo che
sulla prima traccia ci sia l'input, ok?
Sulla prima traccia del nastro,
all'accensione della macchina c'è
l'input. Le altre tracce all'accensione
sono tutte vuote, se c'è blan o. Ok?
Adesso il principio di funzionamento
della macchina che vediamo ora non è
molto differente da quello che abbiamo
visto ieri, però mi serve perché poi lo
sfrutteremo per una cosa che facciamo
dopo la pausa. Ok?
Allora,
tra i 1000 modi di nuovo, cioè non è che
stiamo facendo una cosa molto differente
da quella che abbiamo visto ieri, ok?
Tra i 1000 modi
in cui possiamo progettare una macchina
multitraccia per il riconoscimento di
questa macchina di questo linguaggio,
c'è quello in cui
noi abbiamo la testina, la partenza.
Sostanzialmente noi dobbiamo matchare il
simbolo iniziale col simbolo finale.
Sfrutteremo il fatto che possiamo
memorizzare roba nello stato e il fatto
che possiamo scrivere su più tracce. Ok?
Allora, l'idea è questa. Leggo
il primo simbolo,
metto un marcatore qua per ricordarmi
che è il simbolo che ho letto e quel
simbolo me lo metto costato, me lo
memorizzo. Dopodiché vado in fondo,
cerco il primo simbolo non marcato sulla
seconda traccia e verifico che è uguale
a quello che ho memoria. Dopodiché torno
indietro.
Ok? Questo è il principio di
funzionamento. Non è molto dissimile da
quello che abbiamo fatto. Ok. Alri.
Quindi partiamo da Q0.
Eh, non abbiamo niente in memoria.
Allora, scriviamo così. ci dobbiamo
inventare una notazione. Qualsiasi
notazione. Va bene, adesso la scriviamo.
Tanto le macchine multitraccia non le
useremo un granché, eh. Ci serve solo,
come vi ho detto, come passaggio
intermedio per arrivare alla macchina
che facciamo al giro di dopo. Ok?
Quindi
uso questa notazione qua. Parentesi
graffa.
Leggo un carattere alfa sul primo sulla
prima traccia. Leggo blanco sulla
seconda traccia. Chiudo la parentesi
grave al quadra.
Quindi questo è quello che leggo. Quello
che scrivo è sulla prima traccia lascio
alfa, sulla seconda traccia metto un
asterisco
e vado avanti. Ok? Quindi metto fra
parentesi quadra tutti i simboli che
leggo sulle tracce partendo dalla prima,
prima, seconda, terza, qua.
Quindi andiamo in uno stato Q1 in cui
abbiamo memorizzato il simbolo alfa. Ok?
Alri, quindi abbiamo messo per esempio
qui un asterisco, dobbiamo spostare
adesso la testina in avanti, quindi
dobbiamo saltare tutto quello che c'è di
residuo, arrivare al cancelletto e poi
arrivare a cercare il primo il primo
simbolo non marcato sulla seconda
traccia. Ok?
La cosa positiva di utilizzare una
macchina multitraccia in questo caso è
che non stiamo perdendo il contenuto
dell'input semmai dovessimo
riutilizzarlo, ok? Perché nella macchina
di ieri noi scrivevamo x sul simbolo e
quello era andato, cioè l'avevamo perso.
Semmai avessimo avuto necessità di
rileggerlo, quello lì era perso per
sempre perché l'avevamo sovrascritto. In
questo caso noi stiamo lasciando l'input
sulla prima traccia. Siamo dei marcatori
sulla seconda. Sì. Una domanda stupida,
ma come mai in questa macchina, anche
nella macchina precedente, cercano
registri, noi usiamo una
generalizzazione dei simboli del nostro
alfabeto? Cioè solo per convenzione?
Solo per convenzione? Sì, sì, sì, sì.
Ok.
Alright. Quindi noi saltiamo tutto.
Quindi su primo nastro trovo beta, su
sul primo traccia trovo beta, sul
secondo traccia trovo blan.
Lascio beta, lascio blank e vado avanti.
Ok.
Come beta. Allora, che cosa abbiamo?
Scriviamole da qualche parte.
Scriviamolo qua.
Alfa appartiene ad AB,
beta appartiene ad AB
e fra alfa e beta non c'è nessuna
relazione. Possono essere le stesse,
possono essere uguali, possono essere
diverse, ok? Perché dobbiamo saltare
qualsiasi cosa, ok? Slegata ad alfa. Se
noi qui
avessimo messo alfa,
avrebbe significato che noi ci
aspettiamo di trovare simboli uguali a
quello che ci sta in memoria. Ok?
Siccome noi vogliamo slegare questi
simboli dalla memoria, usiamo due nomi
diversi. Ok?
Quindi salto tutto. Poi a un certo
punto, quindi stiamo saltando tutto
quello che ci sta qui. A un certo punto
arriviamo al cancelletto.
Quindi sulla prima traccia leggo
cancelletto. Sulla seconda lascio c'è
blank. Che cosa faccio? Lascio il
cancelletto lì dov'è, lascio il blank lì
dov'è e vado avanti e vado in Q2 dove
ancora ricordo il simbolo alfa. Ok?
Quindi io alfa me lo sto portando dallo
stato precedente. Ok?
A questo punto noi dobbiamo andare alla
ricerca qui
del primo simbolo sulla destra che non
sia stato marcato sulla seconda traccia.
Ok? Quindi io mi salto tutti i simboli
che hanno l'asterisco sotto. Vado alla
ricerca del primo simbolo che in seconda
traccia non c'ha assolutamente nulla.
Alri,
quindi
prima traccia c'è B, seconda traccia ci
asterisco, lascio tutto com'è
e vado avanti.
Qual è la condizione di uscita? Quand'è
che sappiamo che ci dobbiamo fermare?
Quando leggo alfa e blank. Quando leggo
alfa e blend, cioè, noi ci fermiamo
quando gli asterischi in seconda traccia
finiscono, ok?
E il primo simbolo senza l'asterisco
sotto è lo stesso di quello che avevo
memorizzato prima. Ok?
Vado qua, quindi c'è
leggo alfa e blank sul secondo
sulla seconda traccia. Lascio alfa di
dov'è, scrivo, asserisco sulla seconda
traccia e torno indietro
e vado in Q3
dove non ho più bisogno di ricordarmi il
simbolo, quindi cancello la memoria.
Adesso noi dobbiamo
andare riavvolgere tutto tutto. Quindi,
stiamo tornando qui indietro. Questi qua
che noi incontreremo saranno stati tutti
marcati e quindi c'è
sul primo leggo alfa,
sul secondo leggo asterisco,
lascio alfa lì dov'è, lascio l'asterisco
lì dov'è e vado indietro.
A un certo punto arriverò al
cancelletto. Quindi cancelletto su prima
traccia, blank su seconda traccia,
lascio tutto lì com'è
e vado dietro. E siamo in Q4. Q4 dove
non memorizziamo niente.
Chiaro che stiamo facendo? Stiamo
semplicemente andando indietro. Ok?
Arriviamo al cancelletto. A quel punto,
una volta che superiamo il cancelletto,
arriviamo in questa zona qui
e dobbiamo andare alla ricerca del primo
simbolo non marcato da unas asterismo,
ok? Cioè è esattamente quello che
abbiamo fatto la scorsa volta. Ok? Vado
un po' veloce perché dobbiamo fare un
po' di commenti su questa cosa qua.
Allora, questa cosa la spezziamo in due
per una ragione che vi risulterà
evidente fra un attimo.
Quindi
abbiamo appena superato il cancelletto,
quindi eravamo qua e ci siamo spostati
qui.
e c'è alfa su prima traccia, blank su
seconda traccia. Lascio tutto così com'è
alfa blank e mi sposto dietro. Lo scrivo
così perché mi serve per
Q5 e non memorizzo niente.
Dopodiché salto tutti i caratteri alfa
blank
alfa blank e vado dietro.
Dopodiché quando arrivo al simbolo alla
all'asterisco so che posso ripartire
alfa asterisco
e vado avanti. Ok.
Allora, questa parte di macchina
semplicemente si occupa di leggo un
carattere, lo marco, con l'asterisco, lo
memorizzo, vado in fondo, mi cerco la
prima cosa non marcata, verifico che è
la stessa cosa che abbiamo letto
all'inizio, torno indietro, quindi mi
devo superare prima le cose marcate a
destra, poi supero il cancelletto, poi
le cose non marcate a sinistra, fino a
quando trovo qualcosa di marcato e so
che il carattere che mi serve è il primo
sulla destra e sposto avanti. e riparto.
Ta ta ta. Ok. Quand'è che sappiamo che
possiamo fermarci e andare verso un
check di accettazione?
Quando Sì,
quando in questa fase qua, superando il
cancelletto nel movimento di ritorno
nel carattere dietro, invece di leggere
alfa e blank, leggo alfa e asterisco. A
quel punto so che ho finito e me ne
esco. Ok? Ecco perché ho diviso gli
stati.
Quindi vado di qua, c'è alfa asterisco,
lascio alfa asterisco e vado avanti.
E siamo in Q6. Q6 blend.
Dopodiché c'è il cancelletto,
no,
il cancelletto da superare.
Complet sulla seconda traccia e vado
avanti e sono in Q7.
Dopodiché devo saltare che cosa? Tutti i
simboli che stanno qua e mi aspetto che
siano tutti marcati.
Quindi, che c'ho?
alfa,
asterisco,
lascio tutto così com'è e vado avanti.
Quand'è che mi posso fermare?
Guardate il filmato che succede a un
certo punto se è quello
blank blank blank blank, mi fermo quando
su prima traccia c'è blank, su seconda
traccia c'è blank, lascio tutto così
com'è.
e vado in quotto
e accetto.
Chiaro per tutti?
Ok, ci siete? Perché ora dobbiamo fare
un po' di considerazioni prima della
pausa perché poi sfrutteremo questo
modello per fare un passaggio ex. È
chiaro come funziona questa macchina?
Cioè, non è molto più sofisticata di
quello che facevamo. La differenza è che
memorizziamo nello Stato, però abbiamo
già detto che memorizzare nello Stato
non comporta niente di fantascientifico,
si tratta solamente di replicare stati e
sfruttiamo la multitraccia. La
peculiarità è che possiamo non toccare
la traccia dell'input, cioè quindi se
per linguaggi più sofisticati a noi
l'input serve due volte, ok? Quello ci
torna comodo perché le marcature noi le
mettiamo sulla seconda traccia,
quindi abbiamo più spazio, possiamo fare
più cose sostanzialmente. La mia domanda
adesso è: una macchina multitraccia è in
grado di riconoscere i linguaggi che una
macchina monotraccia non è in grado di
fare?
Pensiamoci un pochino.
Mh mh. Vendo di noi per il fatto che
alla fine possiamo replicare la session
tipo ragionamento
col discorso la multitraccia. usiamo un
simbolo aggiuntivo nel dove eh nella
comunque nella macchina standard. Che
simbolo vorreste vorreste aggiungere?
Per fare l'esempio in questo caso mi
viene da dire m per esempio noi comunque
segniamo soltanto m le A B a tilde B
tilde e che equivale a questo discorso
contatto perché alla fine abbiamo la
prima tr se c'è la stistol Ok. Ok,
questo è esattamente la l'idea. Allora,
ci sono un paio di modi per fare la
cosa, ok? In cui potremmo simulare una
macchina multiraccia tramite una
macchina monotraccia. Uno
che è quello su cui si basa la prova
formale che queste macchine sono
equivalenti, è quello che ci sta
suggerendo il nostro collega. Cioè alla
fine, siccome noi abbiamo una testina
che legge gruppi di simboli, noi
potremmo assumere che quella, se le
tracce sono K, che quella K tupla di
simboli è il nome di un simbolo
soltanto, no? Quindi, che ne so, noi
potremmo avere altri simboli, come
diceva il vostro collega, A blank lo
chiamiamo solo A. A asterisco lo
chiamiamo Atilde,
AB lo possiamo chiamare nuvoletta, AC lo
possiamo chiamare casetta. Ok? Noi
aggiungiamo simboli. Noi potremmo tirare
fuori un simbolo diverso per ognuna
delle possibili combinazioni di simboli
che la macchina potrà mai vedere sulle
tracce. Ok? Quindi, nel primo caso con
la memoria nello stato stiamo
moltiplicando gli stati. In questo caso
stiamo moltiplicando i simboli. Tutto
qua. Quindi noi possiamo definire una
macchina di Touring monotraccia,
ok? Nella quale noi semplicemente
utilizziamo un alfabeto più ricco. Un
alfabeto più ricco che ci permette di
simulare, ok?
una eh il fatto che stiamo leggendo cose
diverse su tracce diverse.
Ok? Questo è un modo. Un altro modo in
cui noi possiamo potremmo simulare una
macchina multitraccia
è che noi ricevut tramite una macchina
monotraccia è questa che la macchina
monotraccia
riceve il proprio input. Ok? che
supponiamo che la macchina M' e la
macchina monotraccia e la macchina M è
la macchina multitraccia. E noi vogliamo
essere in grado tramite M' di
riconoscere lo stesso linguaggio di M.
Allora, che fa M'? m' riceve l'input che
riceverebbe M. lo devo un attimo
manipolare per riuscirci a a lavorare.
Vi ricordo che il numero di tracce sul
nastro è fissato al momento della
progettazione. Possono essere cinque,
possono essere 10, possono essere 1000,
ma una volta che lo fissiamo è fissato,
non si cambia esattamente come la
memoria nello stato. Ok? Non è che la
macchina dice "Oh, cavolo, questa
stringa è un po' più lunga mo sai, con
lo scotch ci attacco un pezzo
aggiuntivo, così c'ho due tracce che mi
servono." Ok, non si può fa'. Si decide
all'inizio tre tracce, quattro tracce,
quindi quella è una cosa fissata. Quindi
quando m'
deve simulare m e supponiamo che m
abbia, che ne so, quattro tracce, è un
esempio, eh, dico quattro perché senò
dovrei dire. Supponiamo che m ha quattro
tracce. Cosa fa m primo? prende il suo
input e inizia a separare i simboli e
mette qua tre spazi tra ognuno dei
simboli. Quindi c'ho il simbolo
dell'input, tre bianchi, un altro
simbolo dell'input, tre bianchi, un
altro s un altro simbolo dell'input, tre
bianchi. E così, quindi la macchina M'O
all'inizio allarga l'input,
dopodiché che fa? In queste cellette
aggiuntive la macchina simola il
contenuto delle tracce della macchina M.
Quindi ogni volta che M'
deve fare deve simulare una transizione
di M,
m' si legge quattro simboli dal nastro,
cioè l'input più il contenuto delle
altre tracce. Che ci fa con sti simboli?
si rimette in tre memorie dello Stato,
in quattro memorie dello Stato. Noi
sappiamo che si può organizzare una cosa
così. Una volta che c'ha in memoria
tutto fa la stessa transizione di M e
poi va avanti. Ovviamente quando deve
scrivere deve scrivere i gruppi di
quattro, quando deve sovrascrivere deve
sovrascrivere i gruppi di quattro,
eccetera. Cioè, quindi questi sono due
modi distinti di simulare una macchina
multitraccia con tramite una macchina
monotraccia, magari con uno stato nella
memoria. Ok? Possiamo quindi dire che le
macchine multitraccia
hanno lo stesso potere delle macchine
con uno stato nella memoria.
Sì. No. Sì.
È vero, no, che le macchine con uno
stato della memoria hanno lo stesso
potere delle macchine standard? Sì.
Quindi possiamo concludere che le
macchine multitraccia, sebbene sembrino
più sofisticate, hanno lo stesso potere
di calcolo delle macchine standard. Ok?
Quindi ci siamo inventati questa cosa
aggiuntiva, ma nemmeno questa cosa
aggiuntiva è in grado di darci una
macchina più potente. Lo usiamo perché
sono più facili da programmare.
Sfrutteremo questa cosa dopo la pausa
per mettere mano su una macchina ancora
più sofisticata che è quelle che poi in
realtà andremo a utilizzare gran parte
del tempo perché sono quelle più in
assoluto facili da programmare. Ok. e
facciamo un quarto d'ora di base.
[Applauso]
Ok, cara, per tutti come funzionano
queste macchine? Memoria dello stato,
macchina multitraccia, abbiamo visto che
tutta roba equivalente
a la macchina standard.
Questo va
ok.
Giusto una cosa in caso fosse sfuggito.
[Musica]
Questo simbolo alfa che leggiamo
e alfa sta per una cosa generifica fra A
o B, ok? Non è che vediamo alfa. Lì
intendiamo leggiamo una cosa che sia A o
B, la chiamiamo alfa e alfa la mettiamo
nel registro, ok?
Ok, quello che facciamo ora è introdurre
il modello di marketoring che
concuseremo per il resto del corso che
è molto molto convenient. Si chiamano
macchine, Sì, come no?
Macchine
multi
nastro.
Ok?
Qual è la differenza fra macchine
multitraccia e macchine multinastro?
La differenza fra queste due macchine è
sostanziale perché una macchina
multitraccia
è una macchina con un nastro soltanto,
mentre le macchine multinastro
sono macchine che hanno più nastri
completamente indipendenti.
Questi nastri non sa una traps in questo
caso. Sì, ma non ci serve. Ok, quindi
sono
macchine
che hanno tanti nastri.
Ogni nastro
ha la propria testina indipendente. Ok?
Quindi una macchina con tre nastri
e una macchina che ha anche
tre testine.
Tre testine
completamente indipendenti.
Ognuna può scrivere quello che vuole.
Ognuna si può muovere dove vuole. Ok?
Quindi, a differenza della multitraccia,
avevamo una testina grossa che andava
spostata in blocco. Nelle macchine
multinastro abbiamo testine indipendenti
che possiamo spostare come ci piace,
quindi magari una va a destra, una va a
sinistra e una sta ferma. Ok? Quindi
introduciamo la possibilità
per le testine di una macchina
multinastro di stare ferme, ok? Non è
nulla di fensi perché possiamo simulare
la testina ferma e in maniera tale che
faccia un passaggio destra sinistra o
sinistra destra. Ok? Quindi non è tutta
sta gran cosa che la testina sia ferma,
lo facciamo perché ci torna comodo. Ok?
Allora, la cosa interessante, quindi, di
queste macchine rispetto alle macchine
multiccia
e che noi possiamo spostare le testine a
piacimento. Ok?
Noi assumiamo che l'input della macchina
si trovi sempre sul primo nastro
all'avvio. Quando la macchina si avvia
trova il proprio input sul primo nastro.
Come al solito assumiamo che la testina
del nastro di input sia sul simbolo più
a sinistra, quindi sul primo simbolo.
Gli altri nastri sono completamente
vuoti. Ok.
Sì, ma si può prendere l'input e di
spezzarlo sui vari nastri oppure non si
può fare? In che senso? Per esempio, per
fare un check se una stringa è falla,
magari potrebbe aver senso ore a priori
dividere a metà la stringa e metterla
sui due nastri giù. Sì, sì, sì, possiamo
fare quello che vogliamo. Adesso, adesso
lo vediamo. Ok. I nastri aggiuntivi che
noi chiamiamo work tapes, cioè
nastri di lavoro. Quindi il primo è
input tape, il secondo, gli altri sono
work tapes.
Li chiamiamo così perché ci servirà poi
più avanti quando parleremo di
complessità. Sui work tapes possiamo
fare quello che vogliamo, leggere,
scrivere, spostare le testine come si
vuole, ok?
La cosa importante è che le testine sono
completamente diendenti, cioè io le
posso spostare in direzioni differenti,
posso tenerne una ferma e spostare le
altre, posso fare quello che voglio.
Come nei casi precedenti, il numero di
nastri che costituisce una macchina di
Turing è deciso all'inizio. Ok? Tre
nastri, tre nastri, 100 nastri, 100
nastri. Una volta che lo decidiamo al
momento della progettazione questo
numero di nastri non può cambiare. Non è
che la macchina a un certo punto si
accorge che la stringa di input è troppo
lunga, dice "Ah, mi serve più spazio, ma
sai che faccio? Tiro fuori il nastro
aggiuntivo." Ok. No, si stabilisce
all'inizio questa macchina funziona con
due nastri, questa macchina funziona con
tre nastri. Ok? E quindi, esattamente
come le macchine multitracci e le
macchine con la memoria nello stato, noi
dobbiamo fissare sin dal principio
quanti registri di memoria abbiamo,
quante tracce ci stanno, allo stesso
modo noi decidiamo quante nastri ci
stanno. Ok?
Questo modello di macchina è molto
conveniente, è molto utile perché
abbiamo l'indipendenza delle destine e
quindi possiamo spostarle come vogliamo.
Per far vedere un po' come possiamo
programmare questo tipo di macchina di
Touring, riconosciamo,
scriviamo una macchina che decida questo
linguaggio. Allora, abbiamo il
linguaggio L delle stringhe W tali che V
w appartiene a 0 or 1 or 2 star.
è il numero
di zeri
1
e 2
in lo st è lo stesso.
Chiaro questo linguaggio? Quindi abbiamo
un linguaggio su tre simboli 0 1 2.
Gli zeri un due possono apparire come ci
gira
tipo 0
1 2 1 2 0 bla bla bla. Ah, ok. Sorry.
Too much. Ahia. Ok. Quindi abbiamo una
cosa tipa,
quindi è qui, poi qua. Ok? Eh, quindi
abbiamo una cosa del tipo 0 1
2 0 2 2 bla bla bla bla. Sono capiti,
non sono in sequenza, come avevamo visto
negli esercizi precedenti, possono
essere completamente sparsi. Ok? Quello
che noi dobbiamo fare è
eh andarli a contare. Vogliamo contare
il numero degli zeri. Vogliamo contare
il numero degli uno, vogliamo contare il
numero dei due e vogliamo verificare che
siano lo stesso. Ok?
Adesso vi faccio notare che se noi
dovessimo risolvere questa
questo problema, questo linguaggio,
dovessimo decidere questo linguaggio su
una macchina
mononastro, su una macchina standard,
allora noi dovremmo iniziare a marcare
le cose come abbiamo visto in
precedenza, solo che poiché non non è
che abbiamo blocchi di zero, blocchi di
uno e blocchi di due, ma questi sono
sparsi fra di loro e diventa un po'
intricato perché che dobbiamo iniziarci
a scorrere tutta la stringa per andare
alla ricerca. Dov'è che è finito il
primo zero? Dov'è che sta il primo uno?
Eh, dovremmo cercarli tutti. Sarebbe,
insomma, una gran scocciatura, si può
fare, eh, non è che non si può fare,
però, insomma, sarebbe un po' difficile
da programmare. Vogliamo decidere questo
linguaggio tramite una macchina
multinastro. Ok?
Che approccio proponete?
Sì, io metterei tutti zero suo nastro,
il suo secondo e il due sul terzo e poi
però la stringa si mantiene la stessa,
qua in mezzo c'è il blank e quindi
quando c'è il blank noi passiamo avanti.
Eh, il blank di cosa, scusi? Cioè la
stringa
è la stessa nastro e eh nel punto in cui
c'è una mancanza di simbolo che compare
in un altro nastro, noi abbiamo degli
empi, dei blanket. buchini. Ok, questa è
una strategia. Ok, avete sentito altre
idee? Questa è già buona. Eh,
posso scambire la stringa e mettere uno
vicino all'altro sul nastro ugro
gli ultimi tre nastri se ho un simbolo
simbolo simbolo. Sì, sì, sì, sì, sì, sì,
sì. Avete sentito? Questo è un
improvement della prima tecnica, cioè
invece di ricopiare la stringa di input
sugli altri nastri e gli togliamo i
pezzi a cui non siamo interessati, il
che ci renderebbe le cose un po'
complicate perché stiamo iniziando ad
inserire degli app. Quello che ci
suggerisce la nostra collega è che ogni
volta che c'è uno zero lo mettiamo su un
nastro, ogni volta che c'è un uno lo
mettiamo su un altro nastro, ogni volta
che c'è un due lo mettiamo su un altro
nastro e iniziamo a sommarli come se
fossero le barre di un istogramma.
Arrivati alla fine dobbiamo controllare
che queste tre barre sono la stessa
cosa, quindi le scorriamo indietro tutte
uguali, tutti assieme. Facciamo un
disegnino.
Quindi c'ho 0 1 0 1 2
1 2 2. Ok, sono loro, sono loro. Ok,
quindi abbiamo il primo nastro che è
l'impul,
poi abbiamo un secondo nastro dove
raccoglieremo gli zeri.
1/3,
Beh, non si vede quello che vedete,
un terzo nastro
dove raccoglieremo tutti gli uno e un
quarto nastro dove raccoglieremo tutti e
due. Ok? Quindi, come funziona questo
approccio?
Iniziamo. Leggiamo uno 0, quello è zero,
lo scriviamo qua. Andiamo avanti.
Leggiamo. C'è uno, lo scriviamo qui.
Andiamo avanti. C'è un altro zero, lo
scriviamo qua. C'è un altro zero, lo
scriviamo qua. Poi c'è uno, lo scriviamo
qui. Poi c'è un lo scriviamo qui e così
via. Ok? Alla fine avremo 00 1 1 1 2 2 2
2. Ok? avremo le testine
qui.
Alla fine quello che dobbiamo fare a
quel punto è riavvolgerle tutti assieme,
ok? E verificare che se le spostiamo
assieme
tutte quante di un passo per volta
arriveranno insieme al fondo. Ok? A quel
punto noi sappiamo che il numero di zeri
letti e il numero di 1 e due eletti era
lo stesso identico. Ok? Vediamo un po'
come scrivere questa cosa in una
notazione.
Vedete? Questo bene. In questo caso
anche trasferni cancellando ecciando
tutta la prima e spostando tutto a
destra.
cancelliamo a destra
dice sulla stringa di input input siamo
tre string alla fine di 0,
cioè lei vuole praticamente riordinare
la prima stringa la prima
seconda stringa zero seconda lui sua
prima che c
ah cioè qualsiasi modo va bene cioè
l'importante è che funziona c Ok,
Q0. Questo è lo stato iniziale.
Allora, usiamo questa notazione.
Eh, cosa che ci inventiamo. Noi dobbiamo
dire,
iniziamo a scrivere l'echichetta che ci
dice che se leggiamo zero sul primo
nastro lo scriviamo sul secondo. Scrivo
così,
un due punti. due puntini per dire cosa
succede sul primo nastro.
Sul primo nastro c'è zero,
lascio zero,
vado avanti.
Cosa dobbiamo fare? Lo dobbiamo
ricopiare sul secondo nastro e lo
scriviamo così.
2.
Sul secondo nastro c'è blank,
scrivo zero e vado avanti. Ok? Quindi
questa etichetta per convenzione noi
stabiliamo che significhi? Che sul primo
nastro c'è zero, scrivo zero e vado
avanti. Sul secondo nastro c'è blank,
scrivo zero e vado avanti. Ok?
Siccome
non stiamo menzionando
i restanti nastri, per convenzione
assumiamo che significhi che sugli altri
nastri ci può essere qualsiasi cosa,
lasciamo quello che c'è e non muoviamo
le testine. Ok? Questa è l'assunzione
che facciamo sul significato di questa
etichetta, ok?
Però ovviamente poi dobbiamo fare altre
cose. E allora per distinguere questa
etichetta dalle altre ci mettiamo una
parentesi graffa
come
per raggruppare questa etichetta perché
adesso ne scriviamo altro.
Altra etichetta per questo anello. Sul
primo nastro c'è uno. Che ci facciamo?
Lo lasciamo là. Dov'è la testina? La
spostiamo. Dove?
Ok. Dove andiamo a scrivere il simicolo
un? Sul terzo nastro. Quindi sul terzo
nastro cosa leggiamo sul terzo nastro?
Len cosa scriviamo su terzo nastro?
Uno. Dove spostiamo la testina?
A destra. Ok. E questa è una seconda
etichetta per lo stesso arma. Ok. Quindi
là stiamo dicendo se leggiamo un uno sul
primo nastro, lo scriviamo sul secondo
nastro, gli sul terzo nastro, gli altri
nastri non li tocchiamo, ci può essere
qualsiasi cosa. Lasciamo tutto com'è, le
testine rimangono per
potremmo dare ai nastri un nome che sia
uguale a quello del singolo in modo che
possiamo scrivere in modo parametrizzato
questa cosa. Le facciamo tutti insieme.
nome
potresti Sì, l'importante, insomma, che
ci riconosciamo quello che stiamo
facendo. State vedendo? Sì. Ok. Qua
altra etichetta. Sul primo nastro c'è un
due. Sul secondo nastro, su primo nastro
c'è un due. Lascio due e dai.
E vado avanti.
Su quarto nastro c'è blank. scrivo due e
vado avanti. Ok? Quindi in Q0 noi stiamo
facendo tutta la processamento iniziale
della stia. Ogni zero che compare in
input viene scritto sul primo nastro sul
secondo nastro. Ogni uno che compare in
input viene scritto sul terzo nastro.
Ogni due che compare in input viene
scritto sul quarto nastro. Ok? E andiamo
avanti. Lo facciamo per tutti i simboli
che stanno nell'input. Quand'è che ci
fermiamo?
Legk sul primo nastro. Leggiamo blank
sul primo nastro. Quindi sul primo
nastro c'è blank. Lascio blank. E
siccome il primo nastro non abbiamo
necessità di fare chissà che cosa, lo
lasciamo fermo. Ok? Quindi quando
mettiamo il trattino là significa che su
primo, cioè su quel nastro la testina
sta ferma, non la spostiamo. Che
dobbiamo fare? Guardiamo il nostro
filmato che dobbiamo fare sugli altri
sugli altri nastri. Dove stanno le
testine del secondo, terzo e quarto
nastro?
Stanno sul primo blank dopo quello che
abbiamo scritto. Ok? Quindi, mentre sul
primo nastro troviamo un blank e
manteniamo la testina ferma, cosa
facciamo sugli altri tre nastri?
Leggiamo che cosa? Blend. E che facciamo
con le testine? Le portiamo un passo
dietro. Ok?
Quindi sul secondo nastro c'è blank,
lascio blank e vado dietro. Sul terzo
nastro c'è blank, lascio blank e vado
dietro. Sul quarto nastro c'è blank,
lascio blank e vado dietro. Ok. E
andiamo in uno.
Esiste unazione per scrivere se fare la
sensazione suas diverso. In questo caso
scrivere quanto
2,
potresti Sì, sì, sì, sì, sì.
Ok. Una volta che siamo in Q1, che
dobbiamo fare? Qual era il piano?
[Musica]
Qual è il piano? Ora
miavolgiavolgere
2 3 4 in concomitanza assieme un passo
per volta e dobbiamo essere sicuri di
arrivare in fondo tutti i pezzi. Ok?
Quindi che facciamo? in V1
c'è sul secondo c'è 0 lascio 0 e vado
dietro sul terzo c'è uno, lascio uno e
vado dietro. Sul quarto c'è due, lascio
due e vado dietro. Ok?
Chio per tutti?
Quindi ora stiamo verificando che il
numero di simboli scritti su secondo,
terzo e quarto nastro sia lo stesso.
Come ci facciamo ad accorgere che il
numero è effettivamente lo stesso?
Troviamo blank all'inizio su tutti e tre
i nastri nello stesso momento. Ok?
Perché quella è la cosa importante, c'è
la contemporaneità. Quindi sul secondo
c'è blank, lascio blank e sto fermo. Sul
terzo c'è blank, lascio il blank e sto
fermo. Sul quarto c'è blank, lascio
blank e sto fermo. Vado Q2 e al centro.
Ok,
ci devoare la parentesi. Cioè, eh sì,
potresti. Allora, io metto la parentesi
quando io c'ho più etichette sull'arco
perché mi devo rabcare in qualche modo,
però sì, dovresti farlo, eh? Dovresti
mettere questo così, questo così e
questo così. Qui su Quno è
indispensabile perché sennò mi perdo.
Chi bat cosa?
Quando è intendo solo un'etichetta
allora posso anche metterlo. Ok?
Però io dicevo, cioè se hai che le tre
cose si verifichino in contemporanea,
uno che questo e questo
se devo fare questo o questo o questo
possiamo usare questa notazione.
Ok? Per dire che sono tre etichette
distritte, ok? E quando non metto niente
intendo che è un'etichetta o per esempio
una parentisona per dire che stanno
tutti assieme. Ok.
Allora, qui mettiamo com'era.
Ok, iniziamo a fare un po' di
considerazione su questa macchina.
Questo tipo di macchina sono molto
interessanti perché sostanzialmente
simulano
quello che per noi sui computer standard
e la memoria, cioè che quindi possiamo
avere aree diverse di memoria che usiamo
un po' principale. Ok? Da questo punto
di vista le macchine multinastro sono
molto comode perché riusciamo a fare
cose, ok? Poi lo vedremo nelle
esercitazioni eccetera, però per esempio
WW cancelletto WB, una macchina
multinastro come potrebbe riconoscerla?
Sì, prendo la prima parte, cioè o la
prima o la seconda dopo il cancelletto,
la metto sul nastro e poi semplicemente
faccio Sì. Cioè una macchina, quindi,
che può gestirsi un secondo nastro a
piacimento, si prende la prima W, la
ricopia, dopodiché va sulla stringa in
input dopo il cancelletto e verifica che
sono le stesse. Ok? Quindi per una
macchina multinastro fare questa cosa è
molto più semplice. Bene, la questione a
questo punto è: "Ma queste macchine
sono più potenti delle macchine
standard? Cioè una macchina multinastro
è in grado di fare cose che una macchina
standard non è in grado di fare?
Voi dite di no perché
sì è sempre una convenzione, cioè sono
dei metodi che ci semplificano la Eh,
vabbè, ma questo lo afferma lei. Come
facciamo a dire che non posso fare più
cose che una macchina standard non possa
fare?
Sono diverse macchine sinceramente.
M No, perché una macchina multinastro la
sta muovendo i nastri allo stesso
momento, non è che faccio prima una cosa
e poi un'altra. Quello sarebbero due
cose diverse, cioè se c'ho una macchina
e poi gli ne appiccico unaltro in coda,
ok, sto riconoscendo due linguaggi, uno
attaccato all'altro. No, questa macchina
fa robe strane, cioè questa macchina può
spostare le testine come vuole, cioè e
più che altro son nemmeno macchine e
pariero, cioè possiamo fa cose. Sì,
forse secondo un po' quello che è stato
detto prima per la multitraccia io posso
fare tutto questa cosa che faccio qua
sui nastri diversi in un unico nastro e
poi semplicemente me la devo giocare del
tipo io so che il mio terzo nastro parte
dopo un simbolo che ho messo io e quindi
ogni volta mi devo spostare e fare la
computazione in quella parte lì. Ok. Ok.
Questa è una buona idea. Cioè, quindi
lei sta suggerendo di utilizzare una
macchina mononastro ma multitraccia e
usare le più tracce per simulare i più
nastri.
Ok? Questo è essenzialmente quello che
andremo a fare. Noi possiamo mostrare
che una macchina multinastro può essere
simulata da una macchina multitraccia
al costo di una certa perdita di tempo.
Ok?
Perché l'intuizione che ci dà, per
esempio, è W, cancelletto W,
un conto è una macchina mononastro che
deve spostare la testina avanti indietro
per match, no, ogni un simbolo con un
altro, il primo col primo, il secondo
col secondo, il terzo col terzo. Quindi
stiamo portando avanti indietro la
testina per fare questa cosa.
Un conto è una macchina multinastro
che prende la prima doppia P, se la
copia sul secondo nastro, lo riavvolge,
dopodiché fa una scansione assieme e ha
finito. Ok? Cioè, sembra che una
macchina multinastro
può essere in linea di principio più
veloce. Ok, ora diamo qualche concetto
sul tempo di esecuzione. Non entriamo
nei dettagli perché è una cosa che
voglio affrontare più di preciso quando
faremo lo studio delle complessità, ok?
Intuitivamente, cos'è il tempo di
esecuzione di una teorema in C su una
certa stringa? Ok?
Allora, per noi il tempo di esecuzione
di una tinguring machine su una certa
stringa input
è pari
al numero di passi
che la macchina fa
prima di arrestarsi.
Ok, quindi il tempo di esecuzione di una
turing machine
su un certo input W è il numero di
passi, cioè quante volte sta testina
viene spostato, quante transizioni
di stato la macchina
performance. Perfetto. Ok.
prima di arrestarsi. Ok? Notate come
precisa è questa definizione rispetto
alla definizione di complessità per gli
algoritmi che in genere avete visto, che
in che cosa dicevamo? Ah, il numero di
operazioni base, no? Però la cosa era un
po' vaga perché ad esempio non è che
moltiplicare due numeri è più è tanto
semplice quando sommarli. Moltiplicare
due numeri è più difficile che sommare
due numeri. Ok? Cioè, quindi qui andiamo
proprio di fino, siccome abbiamo un
algoritmo che è semplicissimo, è
semplicemente una macchina che si muove
da stato in stato esposta a testine, no?
E questi passaggi noi li possiamo
notare. Per noi la complessità è questa
misura basica, è il numero di passi che
la macchina fa mentre processa quella
stringa prima di arrestarsi e noi questi
li possiamo contare. E se noi ci
focalizziamo su questo possiamo scoprire
che moltiplicare due numeri prende più
passi che sommarli. Ok? Quindi possiamo
fare proprio questa analisi di fino che
in genere sugli algoritmi quando
ragioniamo sui linguaggi ad alto livello
non riusciamo a fare. Prego. Ma col
numero di passi sentite quante volte la
testina si muove o quante volte
transisci, cioè quante volte tu
applichi, più preciso ancora voi quante
configurazioni
ci stanno nella computazione, cioè
quanti passaggi di configurazione, vi
ricordate la definizione di
configurazione o istantaneous
description? Ok?
Quanto e qual è il tempo di esecuzione
di una macchina su una certa stringa W?
è la lunghezza
della sua computazione, cioè il numero
di configurazioni che compaiono nella
sua computazione. Quindi quelle si
contano proprio. Ok. Ma incide per caso
la complessità della funzione di
transizione? Nel senso che in questa
macchina noi per ogni transizione
dobbiamo leggere su quattro nastri
diversi, scrivere su quattro nastri
diversi? No, no, no. Noi intendiamo il
passaggio a una configurazione, quindi
la configurazione
di una macchina, cioè non ce ne
interesseremo più di tanto perché non ci
non ci interessa, però che cosa può
essere una configurazione per una
macchina multinastro? Non, detto che le
configurazioni sono delle foto dello
stato di avanzamento dei lavori. Quindi
una configurazione per una macchina
multinastro potrebbe essere una codifica
di tutto quello che c'è su tutti i
nastri, dello stato in cui è la macchina
e della posizione della testina su tutti
i nastri. Ok?
Allora, quindi il tempo di esecuzione di
una macchina di Touring è una cosa
veramente semplice, si definisce in
maniera molto pulita rispetto a quella
degli algoritmi ad alto livello ed è il
numero di passi che la macchina fa prima
di fermarsi, ok? Se la macchina non si
ferma, il suo tempo di esecuzione è
infinito, non si ferma, è altissimo. Ok?
È unbounded. Ok?
Allora, quello che adesso noi vedremo,
noi vogliamo simulare il funzionamento
di una macchina multinastro che
chiamiamo M.
Allora, M è una macchina multi.
Leggete? Sì.
Multi
nastro.
Noi la trasformeremo in una macchina S a
singolo nastro,
però multitraccia. Ok? S è una macchina
multitraccia.
Ok?
Quindi il nostro claim è il seguente.
Teorema
sia m una macchina
multinastro.
Allora,
esiste
una macchina
S multipccia
tale che il linguaggio riconosciuto da M
è uguale al linguaggio riconosciuto da
S. Ok?
Quindi noi stiamo affermando che data
una qualsiasi macchina di touring
multinastro, noi siamo sempre in grado
di costruirne
una equivalente. Per equivalente
intendiamo una macchina che è in grado
di conoscere lo stesso linguaggio. Ok?
Come funziona?
Sì,
vedete? Sì.
[Musica]
Ora funziona funziona così. Il principio
è esattamente quello che ci ha detto la
nostra collega, cioè noi vogliamo
usare le tracce della macchina S in un
modo furbo
tale per cui noi possiamo replicare il
funzionamento di m su S. Ok?
Quindi vorremo fare un funzionamento
simile, non lo stesso un funzionamento
simile, però l'importante è che noi
accettiamo, rispondiamo sì su tutte le
stringhe accettate da m e rispondiamo no
su tutte le stringhe rifiutate da m. Ok?
Allora, funziona così. Per semplicità
questa cosa è generalizzabile, no?
Vabbè, facciamo un po' più generale.
Supponiamo che la macchina M
è una macchina
a K nastri. Ok?
Noi la simuliamo
tramite una macchina S che ha
2* K tracce.
Supponiamo di avere le nostre cellette
qua e quindi abbiamo A B C
0 1 0.
Supponiamo che la testina sia leggendo
questa a
e la testina sia leggendo questo zero.
Come la simuliamo su S?
Le tracce, ok, qua è una convenzione,
eh, ci possiamo inventare quello che
vogliamo. Le tracce dispari della
macchina S conterranno il contenuto dei
nastri della macchina M. Quindi qui che
cosa avrò?
Qua avrò A B C. Qui avrò
0 1 0 En sono. Ok?
Le tracce aggiuntive della macchina S
conterranno dei marcatori
per dirci
dove sta la testina della macchina.
nastro che stiamo simulando. Ok? Quindi,
per esempio, avremo un asterisco qua e
un asterisco qua. Ok? Quindi l'idea è
questa.
Stiamo vogliamo simulare il
comportamento di una macchina con K
nastri. Lo vogliamo fare su una macchina
a singolo nastro, però assumiamo che
siacce.
Le tracce della macchina Sono pari al
doppio dei nastri della macchina M.
Metà dei nastri verranno utilizzati per
simulare per
memorizzare il contenuto dei nastri
della macchina multinastro.
Le altre tracce verranno usate in
maniera molto banale, giusto per tenere
traccia con un marcatore di dove sta
dove starebbe la testina della macchina
multinastro durante la sua
pubblicazione. Ok.
Chiaro?
Allora, vediamo il
la
il principio di funzionamento.
Supponiamo che questo è uno stato Qi.
Ci muoviamo su uno stato QJ della
macchina multinastro
e abbiamo che su primo nastro leggiamo
A, scriviamo B e andiamo avanti. Sul
secondo nastro
leggiamo 0, scriviamo 1 e andiamo
indietà. Ok?
Allora, la macchina S funziona in questo
modo, cioè simula passo per passo tutto
quello che fa la macchina M. Però
siccome a differenza della macchina M
che ha tanti nastri, la macchina S c'ha
solo un nastro, non può fare questa cosa
in un in un passo soldato, deve fare che
cosa. Allora, il principio di
funzionamento è questo.
Noi portiamo la testina della macchina
Sempre
alla sinistra, all'inizio. Ok?
Dobbiamo scoprire che cosa sta leggendo
la macchina Mentre processo. Quindi
prendiamo la mega testina su tutte le
tracce, la iniziamo a spostare verso
destra.
Ogni volta che troviamo un marcatore
su una traccia, noi sappiamo qual è il
simbolo che la macchina multinastro
starebbe leggendo.
Chiaro per tutti? Quel simbolo lo prendo
e lo metto in memoria.
Alla fine la macchina multinastro, è
vero che ha cani di nastri, ma la
macchina multinastro ha un numero
fissato di nastri, quindi io so quanti
marcatori devo andarmi a beccare. K.
Quindi io prendo la testina, me la
sposto verso destra, mi becco K
marcatori
e mi memorizzo nello stato tutti i
simboli
che sto leggendo. Una volta che ho letto
tutto, posso fare il passo che farebbe
la macchina multinastro, cioè so qual è
la transizione che farebbe la macchina
multinastro. Ovviamente pure questa cosa
qui va simulata, non si può fare
l'impasto soltanto. Che cosa facciamo?
Quindi la macchina è partita con la
testina a destra, si è letta tutto
quanto. Arriviamo in fondo, dopo che ci
siamo letti tutti, inizia tutto,
iniziamo ad andare indietro.
troviamo i marcatori per sapere dove
stanno le testine dei vari nastri e in
corrispondenza di quelle posizioni
iniziamo a sovrascrivere i nuovi simboli
che noi conosciamo perché noi conosciamo
qual è la funzione di transizione della
macchina. Ok? Stiamo solo ricodificando
questa cosa con molti più stati. Prendo
la testina, la sposto in avanti, leggo
tutto, metto nello stato, dopodiché so
che devo fare, torno indietro e vado a
modificare le cose con l'accortezza però
che dovremo spostare gli asterischi, o
un passo in avanti o un passo indietro,
indipendenza di dove la macchina
multinastro sposterebbe la testina.
È chiaro per tutti che facciamo?
Sì. Quindi la macchina multraccia,
diciamo, deve essere più veloce della
macchina multifraccia. Aspetta, aspetta.
No, non è che deve essere più veloce, fa
più passi. Ok. Fa più fa più step per
fare un solo step della macchina
multinastro. Però se
se io con la macchina multitraccia segno
eh la testina di una marca multinastro,
però quando già la testina della marca
multinastro è dall'altra parte. No, no,
no, ma non è che sto facendo la gara con
la macchina che io ce l'ho di fianco e
gli devo sta appresso, no. Io sto
simulando il suo comportamento e io
posso prendere il tempo che mi serve. S
può prendere il tempo che ne serve per
simulare M, non è che la deve
rincorrere.
Per simulare ogni passo di M però S ha
bisogno di tanti di tanti di tanti
steps. Ok? Che quali sono?
Intuitivamente me testina.
Iniziamo a sinistra. Leggiamo tutti i
simboli in corrispondenza degli
asterischi. Noi sappiamo quanti ne
dobbiamo leggere. Dobbiamo leggere
esattamente K perché quel K è fissato.
Una volta che li abbiamo letti tutti e
abbiamo memorizzato tutto nello stato,
sappiamo che fare, sappiamo come i
simboli vadano cambiati e dove vanno
spostati gli asterischi. Quindi da
sinistra torniamo indietro e andiamo in
corrispondenza degli asteristi ad
alterare i simboli e a spostare la
posizione degli asterischi. Dopodiché la
portiamo all'inizio e continuiamo a fare
questa cosa. Ok?
capite che questo ci costa del tempo
perché ogni passo della macchina
multinastro
comporta per la macchina a singolo
nastro multitracce di andare una volta
avanti e una volta indietro.
Cerchiamo di stimare quanto è questo
costo. È chiaro come funziona questa
simulazione?
intuitivamente costa del tempo e in
effetti costa del tempo.
Allora, supponiamo,
no, che stiamo simulando una macchina
con due nastri. Questa cosa si fa anche
col K nastri, è la stessima cosa. Ma
diciamo ancora K nastri, va.
Allora, qual è la condizione peggiore
per la macchina mononastro?
La cosa peggiore che può capitare è che
la macchina multinastro spara a ovest
una testina e a est l'altro, cioè che
dopo M passi
una testina è a distanza M dall'inizio e
l'altra testina è a distanza M
dall'inizio. Cioè questa è la cosa
peggiore che può capitare, ok? che la
macchina multinastro spedisce a Roma una
cosa e a Cana l'altra testina.
È chiaro
l'inizio, quindi lo prendiamo in mezzo.
Eh, cioè è normale, tu non hai un punto
di riferimento perché sono nastri
infiniti,
quindi tutto è il centro, tutto è il
posto dei diinizi. Ok? Quindi la cosa
peggiore è che sul nastro di input ce ne
andiamo avanti, sul secondo nastro ce ne
andiamo indietro e questi dopo M passi
saranno uno M passi avanti e l'altro M
passi indietro. Meri avanti ed McDo
indietro. Ok? Qual è la loro distanza?
2m.
Quindi la loro distanza è 2m.
per la macchina mononastro
per simulare il funzionamento, quindi un
passo dopo M della macchina
multinastro, la macchina monostro si
deve scansionare tutte le tracce, però
siccome avrà le testine una a nord e
l'altro a sud, dovrà avrà gli asterischi
a distanza 2 m celle, quindi devo andare
avanti e mi servono 2 m passi per vedere
tutti gli asteristi. È chiaro? Quindi
abbiamo 2m
più
devo tornare indietro, no?
Devo tornare indietro e quindi sono
altri 2 m passi.
2 N bassi.
Dopodiché c'è un altro elemento. Andiamo
qua.
Ve lo faccio vedere qui. Vedete? Sì.
Allora,
nel momento in cui la testina l'abbiamo
Dov'è questo? Nel momento in cui la
testina l'abbiamo spostata qui, noi poi
dobbiamo tornare indietro per aggiornare
i simboli e per aggiornare la posizione
degli asterischi.
Allora, se noi stiamo andando indietro e
questo asterisco qui va spostato qua,
allora lo stiamo spostando nella
direzione in cui ci stiamo muovendo. E
questo non ci costa niente perché stiamo
andando là e
stiamo andando in quella direzione è di
strada.
Il problema è se andando indietro
questo asterisco da qui va spostato qua,
cioè dobbiamo andare contromano. Quello
là ci costa ci costa due passi. Dobbiamo
andare avanti e poi indietro nuovamente
e poi riprendere a indietreggiare.
È chiaro? Quindi nella peggiore delle
ipotesi, per simulare
l'ennemmesimo passo, la macchina
monastro deve fare 2m + 2m + 2k.
Ok, abbiamo quasi chiuso, eh.
E queste sono 4m + 2k.
Vedete? Sì. Ok. Sommiamo.
Sommi. Allora, vogliamo vedere, quindi
assumiamo che la macchina multinastro
faccia N step. Ok? N steps. La macchina
mononastro
farà per i che va da 0 a n cosa? 4 * i +
2k pas. Ok. Allesimo passo per quello
che abbiamo visto facciamo 4i + 2k
passi.
Adesso facciamo giusto un minimo di
rielaborazione.
Questo è minore o uguale della
sommatoria che va da 0 a n
+ 2k.
E questo è
minore o uguale qua mettiamo uno. Stessa
cosa n * 4n + 2k. Ok?
Cioè alesimo passo
la macchina monopomastro deve fare 4 +
2k. Alles + 1 passo dovrà fare 4 * 1 +
dk. Alleso + 2 passi passo dovrà fare 4
per i + 2 + dk. Insomma, sono numeri che
si sommano sommato tutto, guardate qui,
questo è di ordine quadratico,
cioè la macchina mononastro
per simulare
la macchina multinastro
ci mette un tempo che è aggiuntivo che è
di ordine quadratico.
Se la computazione della macchina
multinastro era n qu, la macchina
mononastro ci mette n^ qu. Ok? Però
sempre nel reame della stessa classe di
funzioni rimaniamo. Se la macchina
multinastro ci mette tempo esponenziale,
la macchina mononastro ci mette il
quadrato di una funzione esponenziale
che è ancora esponenziale, cioè quindi
non c'è un grosso C. rallenta che
rallenta, però rimaniamo più o meno
nella stessa classe di funzioni. Se era
polinomiale rimane polinomiale. Se
esponenziale rimane esponenziale. Se era
doppiamente esponenziale rimane
doppiamente esponenziale e così via. Ok?
C'erano un paio di domande? Sì.
No. Ok. Sopra non riesco a leggere la
somatoria. Ah, la prima. No, la
secondaoria i s un attimo. Scrivo
meglio. Oplà. Oplà.
I che va da 1 a N.
[Musica]
Quindi siamo tardi. Cosa abbiamo
mostrato? Abbiamo mostrato che
una macchina multinastro
può essere simulata da una macchina
multitraccia, ma la macchina
multitraccia ha lo stesso potere delle
macchine standard. Di conseguenza una
macchina multinastro, sebbene anche a
questa cosa pensi di avere più nastri e
più testine, in realtà non è più potente
di una macchina non mononastro, può
essere più veloce, però non è in grado
di fare cose che una macchina standard
di fare. Ok? Per questa ragione ci
tenderemo a concentrare su macchine
multimastro perché sono molto più
facilmente gestibili. Ok? E con questo
concludiamo per oggi. Grazie mille.