\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,calc,arrows.meta} % Added arrows.meta for better arrow styles

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

% Comandi personalizzati per i colori degli archi
\tikzset{
    green_arrow/.style={-Latex, thick, draw=green!70!black},
    red_arrow/.style={-Latex, thick, draw=red!70!black},
    black_arrow/.style={-Latex, thick, draw=black},
    double_black_arrow/.style={-Latex, thick, draw=black, double},
    node_style/.style={circle, draw, fill=white, inner sep=1pt},
    small_node_style/.style={circle, draw, fill=lightgray, inner sep=0.5pt},
    diamond_node_style/.style={diamond, draw, fill=white, inner sep=1pt},
    clause_node_style/.style={rectangle, draw, fill=white, inner sep=2pt},
}


\hypersetup{
    pdftitle={Lezione di Informatica Teorica - TSP e Gerarchia Polinomiale},
    pdfauthor={Appunti da Trascrizione AI}
}

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

\title{Lezione di Informatica Teorica\\{\Large Traveling Salesperson Problem (TSP)}}
\author{Appunti da Trascrizione Automatica}
\date{\today}

\begin{document}
\maketitle
\tableofcontents
\newpage

\section{Richiami: Macchine Oracolo e Gerarchia Polinomiale}

Riprendiamo il concetto di macchine oracolo e gerarchia polinomiale, già introdotto per problemi come il Vertex Cover.

\begin{definition}[Funzioni in $\text{FP}^{\text{NP}}$]
$\text{FP}^{\text{NP}}$ è l'insieme delle funzioni calcolabili da trasduttori deterministici in tempo polinomiale che hanno accesso a un oracolo in $\text{NP}$.
\end{definition}

\begin{remark}
Un \textbf{oracolo} è una subroutine che risponde a interrogazioni sull'appartenenza di stringhe a un linguaggio (es. un linguaggio in $\text{NP}$) in un singolo passo di calcolo. Un oracolo può essere molto potente (es. oracolo $\text{NP}$, $\text{NEXP}$).
\end{remark}

Le macchine oracolo permettono di definire gerarchie di complessità, come la Gerarchia Polinomiale ($\text{PH}$).
\begin{definition}[$\Sigma_k^P$]
$\Sigma_k^P$ è il $k$-esimo livello della Gerarchia Polinomiale. In particolare, $\Sigma_2^P$ è la classe dei linguaggi decidibili da macchine in $\text{NP}$ con accesso a un oracolo in $\text{NP}$.
\end{definition}

\begin{remark}
I problemi $\Sigma_k^P$-completi sono intrinsecamente più difficili dei problemi $\text{NP}$-completi. Un problema $\Sigma_2^P$-completo, ad esempio, richiede algoritmi con due livelli di "backtracking" annidati, suggerendo un tempo di esecuzione doppiamente esponenziale su macchine deterministiche (se P $\neq$ NP). Conoscere la classe di complessità di un problema aiuta a progettare algoritmi appropriati e a capire i limiti computazionali.
\end{remark}

\section{Traveling Salesperson Problem (TSP)}

Vediamo il Traveling Salesperson Problem (TSP) sia nella sua versione computazionale (funzionale) che decisionale.

\begin{definition}[Grafo Pesato]
Un grafo pesato è una tupla $G = (V, E, \lambda)$, dove $V$ è l'insieme dei vertici, $E$ è l'insieme degli archi (orientati o meno), e $\lambda: E \to \mathbb{N}^+$ è una funzione di pesatura che associa un peso (intero positivo) a ciascun arco.
\end{definition}

\begin{definition}[Ciclo Hamiltoniano]
Un ciclo Hamiltoniano in un grafo $G=(V, E)$ è un percorso che parte da un vertice, visita tutti gli altri vertici esattamente una volta, e termina nel vertice di partenza. Il peso di un percorso o ciclo è la somma dei pesi degli archi che lo compongono.
\end{definition}

\begin{definition}[FTSP - Functional Traveling Salesperson Problem]
Dato un grafo $G=(V, E, \lambda)$ non orientato e pesato, calcolare il peso del ciclo Hamiltoniano di peso minimo.
Formalmente, $\text{FTSP}(G) = \min \{ \lambda(\pi) \mid \pi \text{ è un ciclo Hamiltoniano di } G \}$.
\end{definition}

\begin{definition}[TSP - Decision Traveling Salesperson Problem]
Dato un grafo $G=(V, E, \lambda)$ non orientato e pesato, e un intero $K$, decidere se esiste un ciclo Hamiltoniano in $G$ di peso al più $K$.
Le istanze di TSP sono coppie $(G, K)$.
\end{definition}

\subsection{Risoluzione di FTSP usando un Oracolo per TSP}

Supponiamo di avere un oracolo per TSP. Vogliamo risolvere FTSP usando chiamate a questo oracolo.

\subsubsection{Prima Soluzione (Naive)}
1.  Inizializza $K=1$.
2.  Chiedi all'oracolo: "Esiste un ciclo Hamiltoniano di peso al più $K$ in $G$?"
3.  Se l'oracolo risponde "Sì", allora $K$ è il peso minimo. Termina.
4.  Se l'oracolo risponde "No", incrementa $K$ e ripeti dal passo 2.
5.  Se $G$ non ammette alcun ciclo Hamiltoniano, l'oracolo risponderà sempre "No". Per garantire la terminazione, il valore massimo di $K$ da testare può essere la somma di tutti i pesi degli archi in $G$ (chiamiamo questo valore $S_{total}$). Se l'oracolo risponde "No" anche per $S_{total}$, allora non esiste un ciclo Hamiltoniano.

\begin{remark}
Questa procedura non colloca FTSP in $\text{FP}^{\text{NP}}$. Il numero di chiamate all'oracolo è proporzionale a $S_{total}$. Poiché $S_{total}$ può essere esponenziale nella dimensione dell'input (se i pesi sono grandi e rappresentati in binario), il trasduttore impiega un tempo esponenziale per effettuare le chiamate. La complessità è una funzione della taglia dell'input, non del suo valore numerico.
\end{remark}

\subsubsection{Seconda Soluzione (Ricerca Binaria)}
Questa procedura è quella corretta per collocare FTSP in $\text{FP}^{\text{NP}}$.

1.  Calcola $S_{total}$, la somma di tutti i pesi degli archi in $G$.
2.  Chiedi all'oracolo: "Esiste un ciclo Hamiltoniano di peso al più $S_{total}$ in $G$?"
    *   Se l'oracolo risponde "No", allora $G$ non ammette alcun ciclo Hamiltoniano. Termina.
    *   Se l'oracolo risponde "Sì", allora esiste almeno un ciclo Hamiltoniano. Procedi con una ricerca binaria nell'intervallo $[0, S_{total}]$ per trovare il peso minimo.
3.  Esegui una ricerca binaria sull'intervallo $[L, R]$, inizialmente $[0, S_{total}]$:
    *   Sia $M = \lfloor (L+R)/2 \rfloor$.
    *   Chiedi all'oracolo: "Esiste un ciclo Hamiltoniano di peso al più $M$ in $G$?"
    *   Se l'oracolo risponde "Sì", allora il peso minimo è $\le M$, quindi imposta $R = M$.
    *   Se l'oracolo risponde "No", allora il peso minimo è $> M$, quindi imposta $L = M+1$.
    *   Ripeti finché $L=R$. Il valore finale di $L$ (o $R$) è il peso minimo.

\begin{theorem}
$\text{FTSP} \in \text{FP}^{\text{NP}}$.
\end{theorem}
\begin{proof}
Il numero di chiamate all'oracolo effettuate dalla procedura di ricerca binaria è logaritmico rispetto alla dimensione del dominio di ricerca $[0, S_{total}]$.
La dimensione del dominio è $S_{total}$, che può essere esponenziale nella taglia dell'input (numero di bit per rappresentare $S_{total}$).
Tuttavia, $\log(S_{total})$ è polinomiale nella taglia della rappresentazione binaria di $S_{total}$ (e quindi polinomiale nella taglia dell'input).
Ad esempio, se $S_{total} \approx 2^N$ dove $N$ è la taglia dell'input, allora $\log(S_{total}) \approx N$, che è polinomiale.
Il trasduttore deterministico esegue un numero polinomiale di chiamate all'oracolo e le operazioni ausiliarie (calcolo $S_{total}$, calcolo $M$, aggiornamento $L, R$) sono polinomiali. Pertanto, FTSP appartiene a $\text{FP}^{\text{NP}}$.
\end{proof}

\subsection{È FTSP in FP?}

Ci chiediamo se $\text{FTSP} \in \text{FP}$, ovvero se può essere risolto da un algoritmo deterministico in tempo polinomiale senza l'ausilio di un oracolo.

\begin{proposition}
Se $\text{FTSP} \in \text{FP}$, allora $\text{TSP} \in \text{P}$.
\end{proposition}
\begin{proof}
Supponiamo che esista un algoritmo deterministico polinomiale per FTSP. Per risolvere un'istanza $(G, K)$ di TSP:
1.  Usa l'algoritmo per FTSP per calcolare il peso minimo di un ciclo Hamiltoniano in $G$, sia esso $W_{min}$.
2.  Confronta $W_{min}$ con $K$. Se $W_{min} \le K$, la risposta è "Sì"; altrimenti, la risposta è "No".
Poiché sia il calcolo di $W_{min}$ che il confronto sono polinomiali, anche TSP sarebbe risolvibile in tempo polinomiale.
\end{proof}

Dato che P $\neq$ NP è un problema aperto e si ritiene improbabile che P = NP, la proposizione precedente implica che è altamente improbabile che FTSP sia in FP, a meno che NP non collassi su P. Questo sposta il nostro focus sulla complessità di TSP.

\section{TSP è NP-Completo}

Dimostriamo ora che TSP è NP-completo. Per fare ciò, dobbiamo mostrare due cose:
1.  $\text{TSP} \in \text{NP}$ (membership).
2.  $\text{TSP}$ è $\text{NP}$-arduo (hardness).

\subsection{Membership: TSP $\in$ NP}

\begin{theorem}
$\text{TSP} \in \text{NP}$.
\end{theorem}
\begin{proof}
Per mostrare che TSP è in NP, dobbiamo esibire un certificato di dimensione polinomiale che possa essere verificato in tempo polinomiale da una macchina deterministica.
Sia $(G, K)$ un'istanza di TSP.
\begin{itemize}
    \item \textbf{Guess (Certificato):} La macchina non deterministica "indovina" una sequenza di vertici $v_1, v_2, \dots, v_{|V|}, v_1$ che rappresenta un potenziale ciclo Hamiltoniano. Questa sequenza ha lunghezza $|V|+1$, quindi è polinomiale nella dimensione dell'input.
    \item \textbf{Check (Verifica):} Una macchina deterministica può verificare in tempo polinomiale che la sequenza:
    \begin{enumerate}
        \item Formi un ciclo: $v_1 \to v_2 \to \dots \to v_{|V|} \to v_1$. Questo significa controllare che per ogni $i \in \{1, \dots, |V|-1\}$, esista un arco $(v_i, v_{i+1})$ e un arco $(v_{|V|}, v_1)$ in $E$.
        \item Visiti tutti i vertici: Controllare che ogni vertice in $V$ appaia esattamente una volta nella sequenza $v_1, \dots, v_{|V|}$.
        \item Abbia peso al più $K$: Calcolare la somma dei pesi degli archi lungo il ciclo $\sum_{i=1}^{|V|-1} \lambda(v_i, v_{i+1}) + \lambda(v_{|V|}, v_1)$ e verificare che sia $\le K$.
    \end{enumerate}
Tutti questi passaggi possono essere eseguiti in tempo polinomiale rispetto a $|V|$ e $|E|$.
Pertanto, TSP è in NP.
\end{proof}

\subsection{Hardness: TSP è NP-arduo}

Per dimostrare che TSP è NP-arduo, mostreremo una catena di riduzioni polinomiali da un problema noto $\text{NP}$-completo (3SAT) a TSP:
$$ \text{3SAT} \le_P \text{DHC} \le_P \text{HC} \le_P \text{TSP} $$
dove:
\begin{itemize}
    \item \textbf{DHC (Directed Hamiltonian Cycle):} Dato un grafo orientato $G$, decidere se $G$ ammette un ciclo Hamiltoniano.
    \item \textbf{HC (Undirected Hamiltonian Cycle):} Dato un grafo non orientato $G$, decidere se $G$ ammette un ciclo Hamiltoniano.
\end{itemize}

\subsubsection{Riduzione: 3SAT $\le_P$ DHC}

Questa è la riduzione più complessa. Dobbiamo trasformare una formula booleana in 3CNF in un grafo orientato $G$ tale che $G$ ammetta un ciclo Hamiltoniano se e solo se la formula è soddisfacibile.

Sia $\Phi = C_1 \land C_2 \land \dots \land C_m$ una formula 3CNF con $m$ clausole e $n$ variabili $X = \{x_1, x_2, \dots, x_n\}$. Assumiamo che nessuna clausola contenga un letterale e la sua negazione (es. $x \lor \neg x$).

\textbf{Costruzione del Grafo $G_\Phi$:}
Il grafo $G_\Phi$ sarà costruito in modo da codificare sia gli assegnamenti di verità delle variabili che la soddisfazione delle clausole.
\begin{itemize}
    \item \textbf{Sezioni Variabili:} Per ogni variabile $x_i \in X$, creiamo una "catena" di nodi composta da $m$ coppie di nodi, una per ogni clausola. Ogni coppia è $(x_{i,j}', x_{i,j}'')$ per $j=1, \dots, m$. Aggiungiamo nodi intermedi ausiliari (piccoli pallini) tra le coppie e nodi diamante all'inizio e alla fine di ciascuna catena.

    \begin{figure}[h]
    \centering
    \begin{tikzpicture}[node distance=1.5cm, auto, thick, scale=0.8, every node/.style={transform shape}]
        \node[diamond_node_style] (start_xi) at (0,0) {};
        \node[small_node_style] (aux_0) at (1.5,0) {};
        \node[node_style] (xi_1_prime) at (3,0.5) {$x_{i,1}'$};
        \node[node_style] (xi_1_second) at (3,-0.5) {$x_{i,1}''$};
        \node[small_node_style] (aux_1) at (4.5,0) {};
        \node[node_style] (xi_2_prime) at (6,0.5) {$x_{i,2}'$};
        \node[node_style] (xi_2_second) at (6,-0.5) {$x_{i,2}''$};
        \node[small_node_style] (aux_2) at (7.5,0) {};
        \node (dots) at (9,0) {\dots};
        \node[small_node_style] (aux_m_minus_1) at (10.5,0) {};
        \node[node_style] (xi_m_prime) at (12,0.5) {$x_{i,m}'$};
        \node[node_style] (xi_m_second) at (12,-0.5) {$x_{i,m}''$};
        \node[small_node_style] (aux_m) at (13.5,0) {};
        \node[diamond_node_style] (end_xi) at (15,0) {};

        % Green path (True)
        \draw[green_arrow] (start_xi) -- (aux_0);
        \draw[green_arrow] (aux_0) -- (xi_1_prime);
        \draw[green_arrow] (xi_1_prime) -- (aux_1);
        \draw[green_arrow] (aux_1) -- (xi_2_prime);
        \draw[green_arrow] (xi_2_prime) -- (aux_2);
        \draw[green_arrow] (aux_2) -- (dots);
        \draw[green_arrow] (dots) -- (aux_m_minus_1);
        \draw[green_arrow] (aux_m_minus_1) -- (xi_m_prime);
        \draw[green_arrow] (xi_m_prime) -- (aux_m);
        \draw[green_arrow] (aux_m) -- (end_xi);

        % Red path (False)
        \draw[red_arrow] (start_xi) -- (aux_0);
        \draw[red_arrow] (aux_0) -- (xi_1_second);
        \draw[red_arrow] (xi_1_second) -- (aux_1);
        \draw[red_arrow] (aux_1) -- (xi_2_second);
        \draw[red_arrow] (xi_2_second) -- (aux_2);
        \draw[red_arrow] (aux_2) -- (dots);
        \draw[red_arrow] (dots) -- (aux_m_minus_1);
        \draw[red_arrow] (aux_m_minus_1) -- (xi_m_second);
        \draw[red_arrow] (xi_m_second) -- (aux_m);
        \draw[red_arrow] (aux_m) -- (end_xi);
    \end{tikzpicture}
    \caption{Struttura della Catena per la Variabile $x_i$}
    \label{fig:xi_chain}
    \end{figure}

    \item \textbf{Struttura Generale del Grafo:} Connettiamo le $n$ sezioni di variabili in serie. Ci sarà un nodo di inizio globale $S$ e un nodo di fine globale $T$.
    \begin{figure}[h]
    \centering
    \begin{tikzpicture}[node distance=2cm, auto, thick, scale=0.8, every node/.style={transform shape}]
        \node[node_style] (S) {$S$};
        \node[diamond_node_style] (start_x1) [right=of S] {};
        \node[small_node_style] (mid_x1) [right=1.5cm of start_x1] {}; % Placeholder for variable chain
        \node[diamond_node_style] (end_x1) [right=1.5cm of mid_x1] {};
        \node[diamond_node_style] (start_x2) [right=of end_x1] {};
        \node[small_node_style] (mid_x2) [right=1.5cm of start_x2] {}; % Placeholder for variable chain
        \node[diamond_node_style] (end_x2) [right=1.5cm of mid_x2] {};
        \node (dots) [right=of end_x2] {\dots};
        \node[diamond_node_style] (start_xn) [right=of dots] {};
        \node[small_node_style] (mid_xn) [right=1.5cm of start_xn] {}; % Placeholder for variable chain
        \node[diamond_node_style] (end_xn) [right=1.5cm of mid_xn] {};
        \node[node_style] (T) [right=of end_xn] {$T$};

        \draw[black_arrow] (S) -- (start_x1);
        \draw[black_arrow] (start_x1) -- (mid_x1); % Represents traversing the x1 chain
        \draw[black_arrow] (mid_x1) -- (end_x1); % Represents traversing the x1 chain
        \draw[black_arrow] (end_x1) -- (start_x2);
        \draw[black_arrow] (start_x2) -- (mid_x2); % Represents traversing the x2 chain
        \draw[black_arrow] (mid_x2) -- (end_x2); % Represents traversing the x2 chain
        \draw[black_arrow] (end_x2) -- (dots);
        \draw[black_arrow] (dots) -- (start_xn);
        \draw[black_arrow] (start_xn) -- (mid_xn); % Represents traversing the xn chain
        \draw[black_arrow] (mid_xn) -- (end_xn); % Represents traversing the xn chain
        \draw[black_arrow] (end_xn) -- (T);
        \draw[black_arrow] (T) .. controls +(0,2cm) and +(0,2cm) .. (S); % Arc from T to S to close the cycle

        % Indicate choices for each variable chain (simplified)
        \node[align=center] at ($(start_x1)!0.5!(mid_x1) + (0, 0.8cm)$) {Verde (True)};
        \node[align=center] at ($(start_x1)!0.5!(mid_x1) + (0, -0.8cm)$) {Rosso (False)};
    \end{tikzpicture}
    \caption{Struttura Generale del Grafo $G_\Phi$}
    \label{fig:general_graph}
    \end{figure}

    In ogni sezione di variabile (es. tra `start_x1` e `end_x1`), un ciclo Hamiltoniano dovrà scegliere di percorrere o tutti gli archi "verdi" (associati a $x_i = \text{TRUE}$) o tutti gli archi "rossi" (associati a $x_i = \text{FALSE}$) per passare tutti i nodi interni di quella sezione. Questo crea $2^n$ percorsi distinti da $S$ a $T$, uno per ogni possibile assegnamento di verità.

    \item \textbf{Nodi Clausola:} Per ogni clausola $C_j$, aggiungiamo un nodo $c_j$. Questi nodi devono essere visitati da qualsiasi ciclo Hamiltoniano. I nodi clausola sono agganciati alle catene delle variabili.
    \begin{itemize}
        \item Se il letterale $x_i$ appare positivamente in $C_j$: Aggiungi archi orientati da $x_{i,j}'$ a $c_j$ e da $c_j$ a $x_{i,j}''$. Questo crea un "detour" dalla catena "verde" (True) di $x_i$.
        \item Se il letterale $\neg x_i$ appare negativamente in $C_j$: Aggiungi archi orientati da $x_{i,j}''$ a $c_j$ e da $c_j$ a $x_{i,j}'$. Questo crea un "detour" dalla catena "rossa" (False) di $x_i$.
    \end{itemize}

    \begin{figure}[h]
    \centering
    \begin{tikzpicture}[node distance=1.5cm, auto, thick, scale=0.8, every node/.style={transform shape}]
        % Common nodes for context
        \node[small_node_style] (prev_aux) at (0,0) {};
        \node[node_style] (xi_j_prime) at (1.5,0.5) {$x_{i,j}'$};
        \node[node_style] (xi_j_second) at (1.5,-0.5) {$x_{i,j}''$};
        \node[small_node_style] (next_aux) at (3,0) {};
        \node[clause_node_style] (cj_node) at (4.5,0) {$C_j$};

        % Standard path
        \draw[green_arrow] (prev_aux) -- (xi_j_prime);
        \draw[green_arrow] (xi_j_prime) -- (next_aux);
        \draw[red_arrow] (prev_aux) -- (xi_j_second);
        \draw[red_arrow] (xi_j_second) -- (next_aux);

        % Detour for positive literal xi in Cj
        \node[align=center] at (1.5, 1.5) {\small $x_i \in C_j$};
        \draw[green_arrow, dashed] (xi_j_prime) to[out=45,in=135] (cj_node);
        \draw[red_arrow, dashed] (cj_node) to[out=-135,in=-45] (xi_j_second);

        % Detour for negative literal not xi in Cj
        \node[align=center] at (1.5, -1.5) {\small $\neg x_i \in C_j$};
        \draw[red_arrow, dashed] (xi_j_second) to[out=-45,in=-135] (cj_node);
        \draw[green_arrow, dashed] (cj_node) to[out=135,in=45] (xi_j_prime);
    \end{tikzpicture}
    \caption{Agganci tra Nodi Variabile e Nodi Clausola}
    \label{fig:clause_attachment}
    \end{figure}
\end{itemize}

\textbf{Dimostrazione:}
\begin{theorem}
$\Phi$ è soddisfacibile se e solo se $G_\Phi$ ammette un ciclo Hamiltoniano.
\end{theorem}
\begin{proof}
\textbf{($\Rightarrow$) Se $\Phi$ è soddisfacibile:}
Sia $\sigma$ un assegnamento di verità che soddisfa $\Phi$. Costruiamo un ciclo Hamiltoniano $\pi$ in $G_\Phi$ come segue:
1.  Inizia da $S$.
2.  Per ogni variabile $x_i$, se $\sigma(x_i) = \text{TRUE}$, attraversa la catena della variabile $x_i$ (ovvero, da `start_xi` a `end_xi`) seguendo gli archi "verdi" (da $x_{i,j}'$ a $x_{i,j+1}'$ tramite nodi ausiliari). Se $\sigma(x_i) = \text{FALSE}$, segui gli archi "rossi" (da $x_{i,j}''$ a $x_{i,j+1}''$).
3.  Quando si arriva a un nodo $x_{i,j}'$ (se stiamo sul percorso verde) o $x_{i,j}''$ (se stiamo sul percorso rosso), controlla se la clausola $C_j$ è soddisfatta da questo assegnamento di $x_i$. Poiché $\sigma$ è un assegnamento che soddisfa $\Phi$, ogni clausola $C_j$ è soddisfatta da almeno un letterale.
    *   Se $x_i \in C_j$ e $\sigma(x_i) = \text{TRUE}$, allora mentre si passa per $x_{i,j}'$, possiamo deviare verso $c_j$ (arco da $x_{i,j}'$ a $c_j$) e poi tornare a $x_{i,j}''$ (arco da $c_j$ a $x_{i,j}''$), e poi proseguire il percorso principale.
    *   Se $\neg x_i \in C_j$ e $\sigma(x_i) = \text{FALSE}$, allora mentre si passa per $x_{i,j}''$, possiamo deviare verso $c_j$ (arco da $x_{i,j}''$ a $c_j$) e poi tornare a $x_{i,j}'$ (arco da $c_j$ a $x_{i,j}'$), e poi proseguire il percorso principale.
4.  Questo meccanismo assicura che tutti i nodi clausola $c_j$ vengano visitati (dato che ogni $C_j$ è soddisfatta da almeno un letterale $x_i$ o $\neg x_i$ il cui percorso si sta già attraversando). I nodi intermedi (pallini) e i nodi $x_{i,j}', x_{i,j}''$ vengono tutti visitati.
5.  Infine, da $T$ si torna a $S$ chiudendo il ciclo.
Questo percorso $\pi$ visita tutti i nodi esattamente una volta (inclusi $S, T$, tutti i nodi delle catene $x_i$, e tutti i nodi clausola $c_j$) e forma un ciclo. Quindi $G_\Phi$ ammette un ciclo Hamiltoniano.

\textbf{($\Leftarrow$) Se $G_\Phi$ ammette un ciclo Hamiltoniano:}
Sia $\pi$ un ciclo Hamiltoniano in $G_\Phi$. Dobbiamo dimostrare che da $\pi$ si può derivare un assegnamento di verità $\sigma$ che soddisfa $\Phi$.

\begin{lemma}
In un ciclo Hamiltoniano $\pi$ di $G_\Phi$:
\begin{itemize}
    \item Il percorso attraverso ciascuna sezione di variabile $x_i$ (da `start_xi` a `end_xi`) deve seguire esclusivamente gli archi "verdi" (da $x_{i,j}'$ a $x_{i,j+1}'$) o esclusivamente gli archi "rossi" (da $x_{i,j}''$ a $x_{i,j+1}''$). Non è possibile alternare tra percorsi verdi e rossi all'interno della stessa sezione, altrimenti si lascerebbero nodi non visitati o si violerebbe la proprietà di ciclo.
    \item Se $\pi$ devia in un nodo clausola $c_j$ da $x_{i,j}'$, deve tornare a $x_{i,j}''$. Simmetricamente, se devia da $x_{i,j}''$, deve tornare a $x_{i,j}'$. Non sono possibili "salti" a nodi di altre sezioni di variabili o altre clausole.
\end{itemize}
\end{lemma}
\begin{proof}[Dimostrazione del Lemma (Sketch)]
La prima proprietà è assicurata dalla struttura delle catene: se si alterna, si lascerebbe un "lato" della catena non visitato (es. tutti i nodi $x_{i,k}''$ se si sceglie il percorso verde e poi si cambia). Per la seconda proprietà, consideriamo il nodo $c_j$. Ha solo due archi in ingresso e due in uscita, provenienti dalle sezioni variabili. Se si entra in $c_j$ da $x_{i,j}'$, l'unica via per visitare $x_{i,j}''$ (che deve essere visitato se non lo è già) è tornare a $x_{i,j}''$ direttamente da $c_j$. Un salto verso un altro $x_{k,l}$ impedirebbe di visitare correttamente i nodi rimanenti della catena di $x_i$ o violerebbe il ciclo Hamiltoniano.
\end{proof}

Grazie al Lemma, un ciclo Hamiltoniano $\pi$ ha una struttura ben definita:
1.  Per ogni variabile $x_i$, $\pi$ o attraversa tutti i nodi $x_{i,j}'$ (usando gli archi "verdi") o tutti i nodi $x_{i,j}''$ (usando gli archi "rossi"). Questo ci permette di definire un assegnamento $\sigma$:
    *   Se $\pi$ attraversa la sezione $x_i$ sul percorso verde, poniamo $\sigma(x_i) = \text{TRUE}$.
    *   Se $\pi$ attraversa la sezione $x_i$ sul percorso rosso, poniamo $\sigma(x_i) = \text{FALSE}$.
2.  Poiché $\pi$ è un ciclo Hamiltoniano, deve visitare tutti i nodi del grafo, inclusi tutti i nodi clausola $c_j$.
3.  Per ogni nodo $c_j$ visitato, $\pi$ deve aver eseguito un detour da un nodo $x_{i,j}'$ o $x_{i,j}''$.
    *   Se il detour è da $x_{i,j}'$ (percorso verde), significa che $\sigma(x_i)=\text{TRUE}$ e $x_i \in C_j$. Questo rende la clausola $C_j$ vera.
    *   Se il detour è da $x_{i,j}''$ (percorso rosso), significa che $\sigma(x_i)=\text{FALSE}$ e $\neg x_i \in C_j$. Questo rende la clausola $C_j$ vera.
Poiché tutti i nodi $c_j$ sono visitati, tutte le clausole $C_j$ devono essere soddisfatte dall'assegnamento $\sigma$.
Quindi $\Phi$ è soddisfacibile.
\end{proof}

Questo conclude la riduzione $\text{3SAT} \le_P \text{DHC}$. La trasformazione è polinomiale perché il numero di nodi e archi nel grafo $G_\Phi$ è polinomiale rispetto a $n$ e $m$ (circa $O(nm)$ nodi e $O(nm)$ archi).

\subsubsection{Riduzione: DHC $\le_P$ HC}

Dobbiamo trasformare un grafo orientato $G=(V, E)$ in un grafo non orientato $H=(V', E')$ tale che $G$ ammette un ciclo Hamiltoniano se e solo se $H$ ammette un ciclo Hamiltoniano.

\textbf{Costruzione del Grafo $H$:}
Per ogni vertice $v \in V$ in $G$, creiamo tre vertici in $H$: $v_{in}$, $v_{mid}$, $v_{out}$.
\begin{figure}[h]
\centering
\begin{tikzpicture}[node distance=1.5cm, auto, thick, scale=0.8, every node/.style={transform shape}]
    % Original nodes in G
    \node[node_style] (a) at (0,0) {$a$};
    \node[node_style] (b) at (3,0) {$b$};

    % Corresponding nodes in H
    \node[node_style] (a_in) at (0,-2) {$a_{in}$};
    \node[node_style] (a_mid) at (1,-2) {$a_{mid}$};
    \node[node_style] (a_out) at (2,-2) {$a_{out}$};

    \node[node_style] (b_in) at (3,-2) {$b_{in}$};
    \node[node_style] (b_mid) at (4,-2) {$b_{mid}$};
    \node[node_style] (b_out) at (5,-2) {$b_{out}$};

    % Edges within triplets in H (undirected)
    \draw[thick, black] (a_in) -- (a_mid);
    \draw[thick, black] (a_mid) -- (a_out);
    \draw[thick, black] (b_in) -- (b_mid);
    \draw[thick, black] (b_mid) -- (b_out);

    % Directed edge in G
    \draw[black_arrow] (a) -- (b) node[midway, above] {$G$};

    % Corresponding edge in H (undirected)
    \draw[thick, black] (a_out) -- (b_in) node[midway, below] {$H$};

    \node at (-1,-2) {\dots};
    \node at (6,-2) {\dots};

    % Pi in G
    \node at (0,1) {$\pi$};
    \node at (1.5,1) {$v_1, v_2, v_3 \dots$};

    % Gamma in H
    \node at (0,-3) {$\gamma$};
    \node at (1.5,-3) {$v_1^{in}, v_1^{mid}, v_1^{out}$};
    \node at (4.5,-3) {$v_2^{in}, v_2^{mid}, v_2^{out}$};
    \node at (7.5,-3) {$v_3^{in}, v_3^{mid}, v_3^{out}$};

\end{tikzpicture}
\caption{Struttura della Riduzione DHC $\le_P$ HC}
\label{fig:dhc_to_hc}
\end{figure}

\begin{itemize}
    \item \textbf{Nodi in $H$:} $V' = \{v_{in}, v_{mid}, v_{out} \mid v \in V\}$. Quindi $|V'| = 3|V|$.
    \item \textbf{Archi in $H$:}
    \begin{enumerate}
        \item Per ogni $v \in V$, aggiungi archi non orientati $(v_{in}, v_{mid})$ e $(v_{mid}, v_{out})$. Questi archi "forzano" l'attraversamento in sequenza.
        \item Per ogni arco orientato $(u, v) \in E$ in $G$, aggiungi un arco non orientato $(u_{out}, v_{in})$ in $H$.
    \end{enumerate}
\end{itemize}

\textbf{Dimostrazione:}
\begin{theorem}
$G$ ammette un ciclo Hamiltoniano se e solo se $H$ ammette un ciclo Hamiltoniano.
\end{theorem}
\begin{proof}
\textbf{($\Rightarrow$) Se $G$ ammette un ciclo Hamiltoniano:}
Sia $\pi = v_1 \to v_2 \to \dots \to v_k \to v_1$ un ciclo Hamiltoniano in $G$ (dove $k=|V|$).
Costruiamo un ciclo in $H$ come segue:
$\gamma = v_{1,in} \to v_{1,mid} \to v_{1,out} \to v_{2,in} \to v_{2,mid} \to v_{2,out} \to \dots \to v_{k,in} \to v_{k,mid} \to v_{k,out} \to v_{1,in}$.
Questo percorso visita tutti i $3|V|$ nodi di $H$ esattamente una volta:
\begin{itemize}
    \item Le transizioni $v_{i,in} \to v_{i,mid} \to v_{i,out}$ sono garantite dalla costruzione degli archi all'interno di ogni tripletto.
    \item Le transizioni $v_{i,out} \to v_{i+1,in}$ (e $v_{k,out} \to v_{1,in}$ per chiudere il ciclo) sono garantite dall'esistenza degli archi $(v_i, v_{i+1})$ in $G$, che corrispondono agli archi $(v_{i,out}, v_{i+1,in})$ in $H$.
\end{itemize}
Pertanto, $\gamma$ è un ciclo Hamiltoniano in $H$.

\textbf{($\Leftarrow$) Se $H$ ammette un ciclo Hamiltoniano:}
Sia $\gamma$ un ciclo Hamiltoniano in $H$. Tutti i nodi $v_{mid}$ hanno solo due vicini: $v_{in}$ e $v_{out}$. Pertanto, qualsiasi ciclo Hamiltoniano che passi per $v_{mid}$ deve per forza percorrere gli archi $(v_{in}, v_{mid})$ e $(v_{mid}, v_{out})$ in sequenza (o viceversa). Questo implica che i nodi di ogni tripletto $(v_{in}, v_{mid}, v_{out})$ devono essere visitati consecutivamente in $\gamma$ in una delle due direzioni.
Quindi $\gamma$ deve essere della forma:
$\dots \to u_{out} \to v_{in} \to v_{mid} \to v_{out} \to w_{in} \to \dots$
Da questa sequenza, possiamo costruire un ciclo Hamiltoniano in $G$: $u \to v \to w \to \dots \to u$.
Ogni volta che $\gamma$ si sposta da $u_{out}$ a $v_{in}$, ciò implica l'esistenza dell'arco $(u_{out}, v_{in})$ in $H$, che a sua volta significa che esisteva l'arco orientato $(u, v)$ in $G$.
Poiché $\gamma$ visita tutti i nodi di $H$, ogni vertice di $G$ (rappresentato dal suo tripletto di nodi in $H$) deve essere visitato. Poiché ogni tripletto è visitato esattamente una volta, ogni vertice in $G$ è visitato esattamente una volta. Questo forma un ciclo Hamiltoniano in $G$.
\end{proof}
Questa riduzione è polinomiale poiché $|V'|=3|V|$ e il numero di archi in $H$ è $2|V| + |E|$, il che è polinomiale in $|V|$ e $|E|$.

\subsubsection{Riduzione: HC $\le_P$ TSP}

Dobbiamo trasformare un grafo non orientato $G=(V, E)$ in un'istanza $(H, K)$ di TSP.

\textbf{Costruzione dell'Istanza $(H, K)$ per TSP:}
1.  Il grafo $H$ è uguale a $G$: $H=G$. Tutti i vertici e gli archi di $G$ sono i vertici e gli archi di $H$.
2.  Assegna un peso a tutti gli archi di $H$: Per ogni arco $e \in E$, imposta il peso $\lambda(e)=1$.
3.  Imposta il valore limite $K$: $K=|V|$ (il numero di vertici in $G$).

\textbf{Dimostrazione:}
\begin{theorem}
$G$ ammette un ciclo Hamiltoniano se e solo se $H$ ammette un ciclo Hamiltoniano di peso al più $K$.
\end{theorem}
\begin{proof}
\textbf{($\Rightarrow$) Se $G$ ammette un ciclo Hamiltoniano:}
Sia $\pi$ un ciclo Hamiltoniano in $G$. Per definizione, $\pi$ visita tutti i $|V|$ vertici esattamente una volta e consiste di esattamente $|V|$ archi.
Poiché tutti gli archi in $H$ hanno peso 1, il peso del ciclo $\pi$ in $H$ è $1 \times |V| = |V|$.
Dato che $K=|V|$, il ciclo $\pi$ in $H$ ha peso esattamente $K$, che è al più $K$.
Pertanto, $H$ ammette un ciclo Hamiltoniano di peso al più $K$.

\textbf{($\Leftarrow$) Se $H$ ammette un ciclo Hamiltoniano di peso al più $K$:}
Sia $\gamma$ un ciclo Hamiltoniano in $H$ con peso $\lambda(\gamma) \le K$.
Per definizione di ciclo Hamiltoniano, $\gamma$ visita tutti i $|V|$ vertici di $H$ (e quindi di $G$) esattamente una volta e consiste di esattamente $|V|$ archi.
Il peso di $\gamma$ è la somma dei pesi di questi $|V|$ archi. Dato che tutti i pesi degli archi in $H$ sono $1$ (e sono positivi), l'unico modo per avere un peso $\le K=|V|$ per un ciclo di $|V|$ archi è che ogni arco nel ciclo abbia peso esattamente 1.
Questo significa che $\gamma$ è un ciclo Hamiltoniano in $G$ (che non ha pesi o ha pesi unitari).
\end{proof}

Questa riduzione è chiaramente polinomiale poiché la trasformazione consiste solo nell'aggiungere pesi unitari e definire $K$, operazioni che richiedono tempo polinomiale.

\subsection{Conclusione della NP-Completezza di TSP}

Avendo dimostrato che:
\begin{itemize}
    \item TSP $\in$ NP.
    \item 3SAT $\le_P$ DHC $\le_P$ HC $\le_P$ TSP.
\end{itemize}
E sapendo che 3SAT è NP-completo, per la transitività delle riduzioni polinomiali, concludiamo che TSP è NP-completo.

\begin{theorem}
$\text{TSP}$ è $\text{NP}$-completo.
\end{theorem}

Ciò rafforza l'idea che $\text{FTSP}$ è improbabile che sia in $\text{FP}$, a meno di una sorprendente risoluzione di $\text{P}$ vs $\text{NP}$.

\end{document}