\documentclass[a4paper]{article}
\usepackage{amsmath, amssymb, amsfonts}
\usepackage[italian]{babel}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{hyperref}
\usepackage[a4paper, total={6in, 8in}]{geometry}
\usepackage{minted}
\usepackage{mathpazo}
\usepackage{fancyhdr}
\usepackage{amsthm}
\usepackage{tikz}
\usetikzlibrary{automata,positioning, arrows}

% Definizione degli ambienti
\newtheorem{theorem}{Teorema}
\newtheorem{definition}{Definizione}
\newtheorem{example}{Esempio}
\newtheorem{lemma}{Lemma}
\newtheorem{proposition}{Proposizione}

\hypersetup{
    pdftitle={Lezione di Informatica Teorica: Varianti delle Macchine di Turing},
    pdfauthor={Appunti da Trascrizione AI}
}

\pagestyle{fancy}
\fancyhf{}
\fancyhead[L]{\textit{Lezione di Informatica Teorica}}
\fancyfoot[C]{\thepage}

\title{Lezione di Informatica Teorica: Varianti delle Macchine di Turing}
\author{Appunti da Trascrizione Automatica}
\date{\today}

\begin{document}
\maketitle
\tableofcontents
\newpage

\section{Introduzione alle Varianti delle Macchine di Turing}
Le Macchine di Turing (MT) standard, pur essendo fondamentali per la teoria della computabilità, sono spesso complesse da programmare a causa della loro semplicità definitoria. Oggi esploreremo alcune varianti delle MT che, sebbene sembrino più potenti, si dimostreranno equivalenti alle MT standard in termini di potere computazionale, ma molto più facili da programmare.

\subsection{Consigli per lo Studio}
È utile estrapolare domande chiave dai concetti visti. Ad esempio:
\begin{itemize}
    \item Cos'è un problema? Come si caratterizza?
    \item Problemi di ricerca vs. problemi di decisione: qual è il loro rapporto?
    \item Che ruolo hanno i linguaggi nei problemi di decisione?
    \item Cos'è una Macchina di Turing? Come è definita?
    \item Qual è la condizione di accettazione per una MT?
    \item Cosa significa che una MT decide un linguaggio vs. accetta un linguaggio? Qual è la differenza?
\end{itemize}

\section{Macchine di Turing con Memoria nello Stato}
Riprendiamo l'esempio del linguaggio $WW^R = \{w w^R \mid w \in \{0,1\}^*\}$. Nella MT standard per questo linguaggio, eravamo costretti a creare rami di computazione separati a seconda del primo carattere letto (0 o 1), perché la macchina doveva "ricordarsi" quel carattere. L'idea è: non sarebbe più semplice se la macchina potesse memorizzare direttamente il simbolo letto?

\begin{definition}[Macchina di Turing con Memoria nello Stato]
Una Macchina di Turing con memoria nello stato è una MT che può memorizzare un simbolo dell'alfabeto del nastro all'interno del suo stato finito. Lo stato è quindi una coppia $(q_i, \text{simbolo_memorizzato})$, dove $q_i$ è lo stato del controllo finito e $\text{simbolo_memorizzato}$ è il contenuto della "memoria interna".
\begin{itemize}
    \item La macchina può memorizzare uno o più simboli (un numero fissato al momento della progettazione).
    \item La memoria non cresce durante l'esecuzione; è pre-determinata dal design.
\end{itemize}
\end{definition}

\begin{example}[Linguaggio $L = \{w \mid w \in \{0,1\}^*, \text{inizia con } \alpha \text{ e prosegue solo con } \bar{\alpha} \}$, cioè $01^* \cup 10^*$]
Vogliamo riconoscere stringhe binarie che iniziano con un simbolo e tutti gli altri sono diversi (es. $0111$, $1000$).
\begin{itemize}
    \item \textbf{Stato Iniziale}: $(q_0, \emptyset)$, dove $\emptyset$ indica memoria vuota.
    \item \textbf{Lettura Primo Simbolo}:
        \begin{itemize}
            \item Leggiamo un carattere $\alpha \in \{0,1\}$.
            \item Lo lasciamo sul nastro.
            \item Spostiamo la testina a destra (R).
            \item Transitiamo allo stato $(q_1, \alpha)$, memorizzando $\alpha$.
        \end{itemize}
    \item \textbf{Ciclo di Verifica}:
        \begin{itemize}
            \item Nello stato $(q_1, \alpha)$, leggiamo il simbolo $\bar{\alpha}$ (il complemento di $\alpha$).
            \item Lo lasciamo sul nastro.
            \item Spostiamo la testina a destra (R).
            \item Rimaniamo nello stato $(q_1, \alpha)$.
        \end{itemize}
    \item \textbf{Accettazione}:
        \begin{itemize}
            \item Nello stato $(q_1, \alpha)$, se leggiamo un simbolo \texttt{blank} ($\sqcup$).
            \item Lasciamo $\sqcup$ sul nastro.
            \item Spostiamo la testina a destra (R).
            \item Transitiamo allo stato $(q_2, \emptyset)$ (o semplicemente $q_2$), e accettiamo.
        \end{itemize}
\end{itemize}
Questo approccio evita la necessità di duplicare gli stati per 0 e 1, rendendo la programmazione più compatta.

\subsubsection{Potere Computazionale delle MT con Memoria nello Stato}
Le MT con memoria nello stato \emph{non} sono più potenti delle MT standard.
\begin{itemize}
    \item Questa descrizione è un modo compatto per rappresentare una MT standard più grande.
    \item Gli stati di una MT con memoria nello stato sono di fatto ottenibili tramite il prodotto cartesiano degli stati del controllo finito e dei possibili simboli memorizzabili.
    \item Se lo stato $(q_i, \alpha)$ è uno stato, questo può essere semplicemente rinominato come $q_{i,\alpha}$ in una MT standard. Il numero di stati aumenta, ma la natura computazionale rimane la stessa.
\end{itemize}

\section{Macchine di Turing Multitraccia}
Le macchine multitraccia sono un altro trucchetto per semplificare la progettazione delle MT.

\begin{definition}[Macchina di Turing Multitraccia]
Una Macchina di Turing multitraccia ha un singolo nastro, ma questo nastro è diviso orizzontalmente in più \textbf{tracce} (es. 2, 3, 7 tracce).
\begin{itemize}
    \item Ogni cella del nastro può contenere un simbolo per ogni traccia.
    \item La macchina ha una \textbf{singola testina} di grandi dimensioni, capace di leggere e scrivere contemporaneamente su tutte le tracce di una data cella.
    \item Quando la testina si sposta (destra o sinistra), si sposta come un \textbf{monoblocco}, mantenendo la sua posizione relativa su tutte le tracce.
    \item La \textbf{funzione di transizione} è determinata dalla tupla di simboli letti su tutte le tracce nella posizione corrente. Può scrivere una tupla di nuovi simboli su tutte le tracce.
    \item Il numero di tracce è fissato al momento della progettazione e non può variare durante l'esecuzione.
\end{itemize}
\end{definition}

\begin{example}[Linguaggio $L = \{w\#w \mid w \in \{a,b\}^+\}$]
Simuliamo il riconoscimento di questo linguaggio con una MT multitraccia, usando due tracce: la prima per l'input e la seconda per i marcatori.
\begin{itemize}
    \item \textbf{Stato Iniziale} $(q_0, \emptyset)$.
    \item \textbf{Passo 1: Lettura e Marcatura del Primo $w$}
        \begin{itemize}
            \item $(q_0, \emptyset)$: Legge $[\alpha, \sqcup]$ (traccia 1: $\alpha$, traccia 2: blank).
            \item Scrive $[\alpha, *]$ (traccia 1: $\alpha$, traccia 2: asterisco).
            \item Sposta la testina a destra (R).
            \item Transisce a $(q_1, \alpha)$ (memorizza $\alpha$).
            \item Questo processo si ripete per tutti i simboli di $w$.
            \item $(q_1, \alpha)$: Legge $[\beta, \sqcup]$ (qualsiasi simbolo $\beta$ diverso da $\alpha$).
            \item Scrive $[\beta, \sqcup]$.
            \item Sposta la testina a destra (R).
            \item Rimane in $(q_1, \alpha)$.
            \item Al cancelletto:
                \begin{itemize}
                    \item $(q_1, \alpha)$: Legge $[\#, \sqcup]$.
                    \item Scrive $[\#, \sqcup]$.
                    \item Sposta la testina a destra (R).
                    \item Transisce a $(q_2, \alpha)$.
                \end{itemize}
        \end{itemize}
    \item \textbf{Passo 2: Verifica del Secondo $w$}
        \begin{itemize}
            \item $(q_2, \alpha)$: Salta i simboli già marcati (cercando il primo simbolo non marcato di $w^R$).
            \item Legge $[\beta, *]$ (su traccia 1: $\beta$, su traccia 2: asterisco).
            \item Scrive $[\beta, *]$.
            \item Sposta la testina a destra (R).
            \item Rimane in $(q_2, \alpha)$.
            \item Quando trova il simbolo corrispondente a $\alpha$:
                \begin{itemize}
                    \item $(q_2, \alpha)$: Legge $[\alpha, \sqcup]$.
                    \item Scrive $[\alpha, *]$.
                    \item Sposta la testina a sinistra (L).
                    \item Transisce a $(q_3, \emptyset)$ (non serve più memorizzare $\alpha$).
                \end{itemize}
        \end{itemize}
    \item \textbf{Passo 3: Ritorno all'Inizio del Primo $w$}
        \begin{itemize}
            \item $(q_3, \emptyset)$: Salta i simboli marcati (su traccia 2).
            \item Legge $[\beta, *]$.
            \item Scrive $[\beta, *]$.
            \item Sposta la testina a sinistra (L).
            \item Rimane in $(q_3, \emptyset)$.
            \item Al cancelletto:
                \begin{itemize}
                    \item $(q_3, \emptyset)$: Legge $[\#, \sqcup]$.
                    \item Scrive $[\#, \sqcup]$.
                    \item Sposta la testina a sinistra (L).
                    \item Transisce a $(q_4, \emptyset)$.
                \end{itemize}
        \end{itemize}
    \item \textbf{Passo 4: Preparazione per il Prossimo Simbolo}
        \begin{itemize}
            \item $(q_4, \emptyset)$: Salta i simboli non marcati (sulla traccia 2) per trovare il prossimo simbolo da marcare in $w$.
            \item Legge $[\beta, \sqcup]$.
            \item Scrive $[\beta, \sqcup]$.
            \item Sposta la testina a sinistra (L).
            \item Rimane in $(q_5, \emptyset)$. (Separato in $q_5$ e $q_6$ per distinguere tra simboli non marcati e marcati)
            \item Quando trova il prossimo simbolo marcato:
                \begin{itemize}
                    \item $(q_5, \emptyset)$: Legge $[\beta, *]$.
                    \item Scrive $[\beta, *]$.
                    \item Sposta la testina a destra (R).
                    \item Torna a $(q_0, \emptyset)$ per ripetere il ciclo per il prossimo simbolo.
                \end{itemize}
            \item \textbf{Condizione di Accettazione (Fine Verifica)}:
                \begin{itemize}
                    \item Se, durante il ritorno da $q_4$, invece di leggere un simbolo non marcato, si legge un simbolo già marcato su traccia 2:
                        \begin{itemize}
                            \item $(q_4, \emptyset)$: Legge $[\alpha, *]$.
                            \item Scrive $[\alpha, *]$.
                            \item Sposta la testina a destra (R).
                            \item Transisce a $(q_6, \emptyset)$. (Indica che tutti i simboli di $w$ sono stati verificati)
                        \end{itemize}
                    \item Ora bisogna verificare che non ci sia più nulla dopo il cancelletto (cioè anche il secondo $w$ è stato verificato).
                        \begin{itemize}
                            \item $(q_6, \emptyset)$: Legge $[\#, \sqcup]$.
                            \item Scrive $[\#, \sqcup]$.
                            \item Sposta la testina a destra (R).
                            \item Transisce a $(q_7, \emptyset)$.
                        \end{itemize}
                    \item $(q_7, \emptyset)$: Salta i simboli marcati su traccia 2 (assicurandosi che tutto il secondo $w$ sia marcato).
                        \begin{itemize}
                            \item Legge $[\alpha, *]$.
                            \item Scrive $[\alpha, *]$.
                            \item Sposta la testina a destra (R).
                            \item Rimane in $(q_7, \emptyset)$.
                        \end{itemize}
                    \item \textbf{Accettazione Finale}:
                        \begin{itemize}
                            \item $(q_7, \emptyset)$: Legge $[\sqcup, \sqcup]$ (blank su entrambe le tracce).
                            \item Scrive $[\sqcup, \sqcup]$.
                            \item Sposta la testina a destra (R).
                            \item Transisce a $(q_8, \emptyset)$ (Accetta).
                        \end{itemize}
                \end{itemize}
        \end{itemize}
\end{itemize}
Questa macchina è più semplice da progettare rispetto alla versione a nastro singolo perché non si perde il contenuto originale dell'input.

\subsubsection{Potere Computazionale delle MT Multitraccia}
Le MT multitraccia \emph{non} sono più potenti delle MT standard.
\begin{enumerate}
    \item \textbf{Simulazione tramite Alfabeto Esteso}:
    Una MT multitraccia con $K$ tracce può essere simulata da una MT standard (a singolo nastro e singola traccia) che usa un alfabeto esteso. Ogni simbolo del nuovo alfabeto è una tupla di $K$ simboli, rappresentando la combinazione di simboli che apparirebbero su ogni traccia in una data cella. Ad esempio, se le tracce sono 2 e gli alfabeti $\{a,b\}$, $\{*, \sqcup\}$, il nuovo alfabeto può includere simboli come $(a, *)$, $(b, \sqcup)$, ecc. Questo aumenta la dimensione dell'alfabeto, ma non il potere computazionale.
    \item \textbf{Simulazione tramite Spazio Aggiuntivo e Memoria nello Stato (meno comune per la dimostrazione di equivalenza):}
    Una MT standard può simulare una MT multitraccia prendendo l'input della MT multitraccia, inserendo delimitatori tra i simboli per creare "spazio" per le tracce aggiuntive. La MT standard userà poi la memoria nello stato per tenere traccia dei simboli che sarebbero sulle altre tracce e simulerà i movimenti della testina leggendo e scrivendo nei blocchi delimitati. Questo dimostra l'equivalenza ma è più complesso.
\end{enumerate}
In sintesi, le MT multitraccia, sebbene sembrino più sofisticate, hanno lo stesso potere computazionale delle MT standard. Sono solo più facili da programmare.

\section{Macchine di Turing Multinastro}
Introduciamo il modello più conveniente per la programmazione: le Macchine di Turing Multinastro.

\begin{definition}[Macchina di Turing Multinastro]
Una Macchina di Turing multinastro ha \textbf{più nastri completamente indipendenti} (es. 2, 3, 4 nastri).
\begin{itemize}
    \item Ogni nastro ha la propria \textbf{testina indipendente}.
    \item Ogni testina può leggere, scrivere e muoversi \textbf{autonomamente} (destra (R), sinistra (L), o stare ferma (S)).
    \item L'input della macchina si trova sempre sul \textbf{primo nastro} all'avvio. Gli altri nastri (chiamati \textbf{nastri di lavoro} o \emph{work tapes}) sono inizialmente vuoti.
    \item Il numero di nastri è fissato al momento della progettazione e non può cambiare durante l'esecuzione.
\end{itemize}
\end{definition}

\begin{example}[Linguaggio $L = \{w \mid w \in \{0,1,2\}^*, \text{count}(0)=\text{count}(1)=\text{count}(2)\}]$
Vogliamo decidere se il numero di '0', '1' e '2' in una stringa di input è uguale.
Approccio con MT multinastro (4 nastri: 1 input, 3 di lavoro):
\begin{enumerate}
    \item \textbf{Nastro 1 (Input)}: Contiene la stringa $w$.
    \item \textbf{Nastro 2 (Zeros)}: Memorizzerà tutti gli '0'.
    \item \textbf{Nastro 3 (Ones)}: Memorizzerà tutti gli '1'.
    \item \textbf{Nastro 4 (Twos)}: Memorizzerà tutti i '2'.
\end{enumerate}
\textbf{Strategia:}
\begin{itemize}
    \item \textbf{Passo 1: Copia e Separazione (Stato $q_0$)}:
        \begin{itemize}
            \item Si scansiona il Nastro 1 da sinistra a destra.
            \item Se si legge '0' sul Nastro 1:
                \begin{itemize}
                    \item Mantiene '0' sul Nastro 1, muove testina 1 a destra (R).
                    \item Scrive '0' sul Nastro 2 (che era $\sqcup$), muove testina 2 a destra (R).
                \end{itemize}
            \item Se si legge '1' sul Nastro 1:
                \begin{itemize}
                    \item Mantiene '1' sul Nastro 1, muove testina 1 a destra (R).
                    \item Scrive '1' sul Nastro 3 (che era $\sqcup$), muove testina 3 a destra (R).
                \end{itemize}
            \item Se si legge '2' sul Nastro 1:
                \begin{itemize}
                    \item Mantiene '2' sul Nastro 1, muove testina 1 a destra (R).
                    \item Scrive '2' sul Nastro 4 (che era $\sqcup$), muove testina 4 a destra (R).
                \end{itemize}
            \item Questo continua finché il Nastro 1 non incontra $\sqcup$.
        \end{itemize}
    \item \textbf{Passo 2: Riavvolgimento Testine di Lavoro (Transizione da $q_0$ a $q_1$)}:
        \begin{itemize}
            \item Quando Nastro 1 legge $\sqcup$:
                \begin{itemize}
                    \item Nastro 1: $[\sqcup, \sqcup]$, testina 1 ferma (S).
                    \item Nastri 2, 3, 4 (che avranno la testina all'inizio della loro area blank): $[\sqcup, \sqcup]$, testine 2, 3, 4 muovono a sinistra (L).
                    \item Transisce allo stato $q_1$.
                \end{itemize}
        \end{itemize}
    \item \textbf{Passo 3: Confronto Conteggi (Stato $q_1$)}:
        \begin{itemize}
            \item Nello stato $q_1$, le testine dei nastri 2, 3, 4 sono posizionate all'inizio dei simboli scritti.
            \item Si muovono simultaneamente a sinistra (L), leggendo i simboli.
            \item Se Nastro 2 legge '0', Nastro 3 legge '1', Nastro 4 legge '2':
                \begin{itemize}
                    \item Mantengono i simboli, muovono testine 2, 3, 4 a sinistra (L).
                    \item Rimangono in $q_1$.
                \end{itemize}
            \item Questo processo continua finché tutti i nastri incontrano il simbolo $\sqcup$ \textbf{contemporaneamente}.
        \end{itemize}
    \item \textbf{Passo 4: Accettazione (Transizione da $q_1$ a $q_2$)}:
        \begin{itemize}
            \item Quando Nastro 2, Nastro 3 e Nastro 4 leggono $\sqcup$ contemporaneamente:
                \begin{itemize}
                    \item Nastri 2, 3, 4: $[\sqcup, \sqcup]$, testine 2, 3, 4 ferme (S).
                    \item Transisce allo stato $q_2$ e accetta.
                \end{itemize}
        \end{itemize}
\end{itemize}
Le MT multinastro sono molto convenienti perché permettono un controllo indipendente delle testine, rendendo algoritmi come questo (che altrimenti richiederebbero complessi vai-e-vieni sul nastro singolo) molto più intuitivi.

\begin{figure}[h!]
    \centering
    \begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto]
        \node[state,initial] (q0) {$q_0$};
        \node[state, right=of q0] (q1) {$q_1$};
        \node[state, right=of q1, accepting] (q2) {$q_2$};

        \path[->] (q0) edge [loop above] node[align=center] {
            $1:0/0, R$; $2:\sqcup/0, R$\\
            $1:1/1, R$; $3:\sqcup/1, R$\\
            $1:2/2, R$; $4:\sqcup/2, R$
        } (q0);

        \path[->] (q0) edge node[align=center] {
            $1:\sqcup/\sqcup, S$\\
            $2:\sqcup/\sqcup, L$\\
            $3:\sqcup/\sqcup, L$\\
            $4:\sqcup/\sqcup, L$
        } (q1);
        
        \path[->] (q1) edge [loop above] node[align=center] {
            $2:0/0, L$\\
            $3:1/1, L$\\
            $4:2/2, L$
        } (q1);
        
        \path[->] (q1) edge node[align=center] {
            $2:\sqcup/\sqcup, S$\\
            $3:\sqcup/\sqcup, S$\\
            $4:\sqcup/\sqcup, S$
        } (q2);
    \end{tikzpicture}
    \caption{Diagramma di una Macchina di Turing Multinastro per il linguaggio $L=\{w \mid \text{count}(0)=\text{count}(1)=\text{count}(2)\}$}
\end{figure}

\section{Equivalenza e Complessità Temporale}
Come per le varianti precedenti, ci si chiede: le MT multinastro sono più potenti delle MT standard? La risposta è no, ma sono potenzialmente più veloci.

\begin{definition}[Tempo di Esecuzione di una MT]
Il tempo di esecuzione di una Macchina di Turing su una certa stringa di input $W$ è definito come il \textbf{numero di passi} (o il numero di configurazioni nella sua computazione) che la macchina compie prima di arrestarsi. Se la macchina non si arresta, il tempo di esecuzione è infinito. Questa definizione è molto precisa e permette un'analisi fine della complessità.
\end{definition}

\begin{theorem}[Equivalenza MT Multinastro e MT Standard]
Sia $M$ una macchina di Turing multinastro. Allora esiste una macchina $S$ a nastro singolo (e multitraccia) tale che il linguaggio riconosciuto da $M$ è uguale al linguaggio riconosciuto da $S$.
\end{theorem}

\subsubsection{Dimostrazione (Sketch)}
L'idea è simulare una MT multinastro $M$ (con $K$ nastri) tramite una MT $S$ a nastro singolo ma multitraccia.
\begin{itemize}
    \item \textbf{Architettura di $S$}: La macchina $S$ avrà $2K$ tracce.
        \begin{itemize}
            \item Le tracce dispari (es. 1, 3, 5, \dots, $2K-1$) conterranno il contenuto dei $K$ nastri di $M$.
            \item Le tracce pari (es. 2, 4, 6, \dots, $2K$) conterranno un marcatore speciale (es. '\texttt{*}') che indica la posizione della testina del nastro corrispondente in $M$.
            \item Il resto della traccia pari sarà $\sqcup$.
        \end{itemize}
    \item \textbf{Simulazione di un passo di $M$ da parte di $S$}: Per simulare un singolo passo della macchina $M$, $S$ deve eseguire i seguenti sottoprocessi:
        \begin{enumerate}
            \item \textbf{Lettura dei Simboli}: $S$ scansiona il suo nastro da sinistra a destra per trovare tutti i $K$ marcatori delle testine. Quando trova un marcatore su una traccia pari, legge il simbolo corrispondente sulla traccia dispari immediatamente superiore e lo memorizza nello stato di $S$.
            \item \textbf{Decisione della Transizione}: Una volta letti tutti e $K$ i simboli (e memorizzati nel suo stato), $S$ sa quale transizione $M$ avrebbe eseguito (basandosi sullo stato attuale di $M$ e i $K$ simboli letti). Questa transizione specifica quali simboli scrivere e in quale direzione muovere ciascuna testina.
            \item \textbf{Aggiornamento del Nastro e Spostamento delle Testine}: $S$ scansiona il suo nastro una seconda volta (es. da destra a sinistra), e in corrispondenza di ogni marcatore di testina:
                \begin{itemize}
                    \item Sovrascrive il simbolo sulla traccia dispari con il nuovo simbolo deciso nel passo precedente.
                    \item Sposta il marcatore '\texttt{*}' sulla traccia pari nella nuova posizione della testina (spostandolo a destra o a sinistra). Se il marcatore deve muoversi nella direzione opposta a quella della scansione attuale di $S$, ciò richiederà due mosse aggiuntive per il marcatore (sposta avanti, poi indietro e riprende la scansione).
                \end{itemize}
            \item \textbf{Ritorno alla Posizione Canonica}: $S$ riporta la sua testina all'inizio del nastro (o a una posizione prefissata) per il prossimo ciclo di simulazione.
        \end{enumerate}
\end{itemize}

\subsubsection{Analisi della Complessità Temporale della Simulazione}
Sia $M$ una MT multinastro che esegue $N$ passi.
\begin{itemize}
    \item Il tempo di esecuzione di $M$ è $N$.
    \item Durante $N$ passi, una testina di $M$ non può allontanarsi più di $N$ celle dalla sua posizione iniziale.
    \item Nella simulazione di $S$, le testine di $M$ possono essere sparse sul nastro di $S$. Nella peggiore delle ipotesi, la testina di un nastro si trova a $i$ posizioni a sinistra dell'inizio del nastro di $S$, e un'altra testina si trova a $i$ posizioni a destra. La distanza massima tra due testine dopo $i$ passi di $M$ è $2i$ celle.
    \item Per simulare il $i$-esimo passo di $M$, $S$ deve scansionare un segmento del suo nastro di lunghezza proporzionale alla massima distanza raggiunta dalle testine fino a quel momento, che è $O(i)$.
    \item Per ogni passo di $M$, $S$ esegue due scansioni complete ($2 \times O(i)$) e potenzialmente $2K$ mosse aggiuntive (per i marcatori che vanno contro-scansione). Quindi, un passo di $M$ costa $S$ un tempo $O(i) + O(i) + O(K) = O(i+K)$.
    \item Il tempo totale per $S$ per simulare $N$ passi di $M$ sarà la somma dei costi per ogni passo:
    \[
    T_S(N) = \sum_{i=1}^{N} C \cdot (i + K) = C \cdot \sum_{i=1}^{N} i + C \cdot \sum_{i=1}^{N} K
    \]
    \[
    T_S(N) = C \cdot \frac{N(N+1)}{2} + C \cdot NK = O(N^2 + NK) = O(N^2)
    \]
    \item Pertanto, una MT multinastro può essere simulata da una MT multitraccia (e quindi standard) con un \textbf{rallentamento quadratico}. Se $M$ impiega $N$ passi, $S$ impiega $O(N^2)$ passi.
\end{itemize}

\subsection{Conclusioni sul Potere Computazionale}
\begin{itemize}
    \item Le Macchine di Turing con memoria nello stato, le Macchine di Turing multitraccia e le Macchine di Turing multinastro sono tutte \textbf{computazionalmente equivalenti} alle Macchine di Turing standard. Non possono riconoscere linguaggi che una MT standard non possa riconoscere.
    \item Tuttavia, offrono notevoli vantaggi in termini di \textbf{facilità di programmazione} e possono garantire un'esecuzione \textbf{più efficiente} (con un rallentamento polinomiale, non esponenziale, nella simulazione).
    \item Per la loro praticità, le Macchine di Turing multinastro sono spesso il modello preferito nella pratica per studiare la complessità degli algoritmi.
\end{itemize}

\end{document}