\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.meta}

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

\hypersetup{
    pdftitle={Lezione di Informatica Teorica: Classi di Complessità e Riduzioni},
    pdfauthor={Appunti da Trascrizione AI}
}

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

\title{Lezione di Informatica Teorica: Classi di Complessità e Riduzioni}
\author{Appunti da Trascrizione Automatica}
\date{\today}

\begin{document}
\maketitle
\tableofcontents
\newpage

\section{Introduzione alle Classi di Complessità}

Abbiamo iniziato a definire classi di complessità che sono sottoclassi della classe $\mathbf{R}$ (Problemi Decidibili). Ci chiediamo quali problemi siano facili e quali difficili.

Abbiamo introdotto i concetti di \emph{computation time} e \emph{running time} per Macchine di Turing (MT) e le funzioni di tempo. Da ciò, abbiamo definito le classi:
\begin{itemize}
    \item \textbf{Time($f(n)$)}: L'insieme di tutti i linguaggi decidibili da una Macchina di Turing deterministica in tempo $O(f(n))$.
    \item \textbf{NTime($f(n)$)}: L'insieme di tutti i linguaggi decidibili da una Macchina di Turing non deterministica in tempo $O(f(n))$.
\end{itemize}

Queste classi ci permettono di definire il concetto di risolvibilità in tempo polinomiale, esponenziale, ecc., sia in modalità deterministica che non deterministica.

\subsection{Classi P e NP}

\begin{definition}[Classe P]
La classe \textbf{P} è l'insieme di tutti i problemi di decisione decidibili da una Macchina di Turing deterministica in tempo polinomiale.
Formalmente: $\mathbf{P} = \bigcup_{k \ge 1} \text{Time}(n^k)$.
\end{definition}

\begin{definition}[Classe NP]
La classe \textbf{NP} è l'insieme di tutti i problemi di decisione decidibili da una Macchina di Turing non deterministica in tempo polinomiale.
Formalmente: $\mathbf{NP} = \bigcup_{k \ge 1} \text{NTime}(n^k)$.
\end{definition}

\textbf{Nota Importante:} NP sta per \emph{Non-deterministic Polynomial}, non per \emph{Non-Polynomial}.

\subsubsection{Relazione tra P e NP: Il Problema P vs NP}

È intuitivo che $\mathbf{P} \subseteq \mathbf{NP}$. Tutto ciò che può essere deciso in tempo polinomiale deterministico può anche essere deciso in tempo polinomiale non deterministico (una MT deterministica è un caso particolare di MT non deterministica).

La relazione inversa, ovvero se $\mathbf{NP} \subseteq \mathbf{P}$ (il che implicherebbe $\mathbf{P} = \mathbf{NP}$), è un problema tuttora aperto e uno dei più importanti problemi non risolti dell'informatica teorica (e uno dei problemi del millennio).

Attualmente, sappiamo simulare una Macchina di Turing non deterministica con una deterministica con un overhead esponenziale. Questo significa che un linguaggio in $\mathbf{NP}$ può essere deciso da una MT deterministica in tempo esponenziale. Questo non lo colloca automaticamente in $\mathbf{P}$. Non è stato ancora dimostrato che non esista un metodo più efficiente (polinomiale) per tale simulazione. La congettura comune è che $\mathbf{P} \ne \mathbf{NP}$.

\subsection{Riduzione Polinomiale}

Il concetto di riduzione che abbiamo già visto viene specificato per il contesto delle classi di complessità.

\begin{definition}[Riduzione Polinomiale]
Siano $A$ e $B$ due linguaggi. Una \textbf{riduzione polinomiale} da $A$ a $B$ è una funzione $f: \Sigma^* \to \Sigma^*$ tale che:
\begin{enumerate}
    \item $f$ è calcolabile da una Macchina di Turing deterministica in tempo polinomiale.
    \item Per ogni stringa $w \in \Sigma^*$, $w \in A \iff f(w) \in B$.
\end{enumerate}
La riduzione è denotata con $A \le_p B$.
\end{definition}
Il vincolo cruciale è che la trasformazione $f$ (implementata da un trasduttore) deve avere un tempo di esecuzione polinomiale rispetto alla taglia dell'input.

\section{NP-Hardness e NP-Completezza}

Questi concetti sono fondamentali per classificare la difficoltà dei problemi all'interno e al di fuori di NP.

\begin{definition}[NP-Hardness]
Un linguaggio $L$ è \textbf{NP-hard} se per ogni linguaggio $L' \in \mathbf{NP}$, esiste una riduzione polinomiale da $L'$ a $L$ ($L' \le_p L$).
\end{definition}
Intuitivamente, un linguaggio NP-hard è \emph{almeno altrettanto difficile} quanto qualsiasi problema in NP.

\begin{definition}[NP-Completezza]
Un linguaggio $L$ è \textbf{NP-complete} se:
\begin{enumerate}
    \item $L \in \mathbf{NP}$
    \item $L$ è NP-hard.
\end{enumerate}
\end{definition}
In altre parole, un linguaggio NP-complete è un problema che appartiene a NP ed è tra i più difficili problemi in NP.

\subsubsection{Differenza tra NP-Hard e NP-Complete}
La distinzione è cruciale:
\begin{itemize}
    \item Un problema NP-hard potrebbe non appartenere a NP. Ad esempio, il Linguaggio Universale ($A_{TM}$) è NP-hard (è difficile almeno quanto ogni problema in NP), ma non è NP-complete perché non è decidibile (e quindi non appartiene a NP).
    \item Un problema NP-complete è necessariamente in NP.
\end{itemize}

\subsection{Teorema: Relazione tra $L \in \text{NP-Complete}$ e P vs NP}

\begin{theorem}
Sia $L$ un linguaggio NP-complete. Allora, $L \in \mathbf{P}$ se e solo se $\mathbf{P} = \mathbf{NP}$.
\end{theorem}

\begin{proof}
Dobbiamo dimostrare la doppia implicazione.

\textbf{Direzione 1: Se $\mathbf{P} = \mathbf{NP}$, allora $L \in \mathbf{P}$.}
Poiché $L$ è NP-complete, per definizione $L \in \mathbf{NP}$. Se $\mathbf{P} = \mathbf{NP}$, allora è immediato che $L \in \mathbf{P}$.

\textbf{Direzione 2: Se $L \in \mathbf{P}$, allora $\mathbf{P} = \mathbf{NP}$.}
Sappiamo già che $\mathbf{P} \subseteq \mathbf{NP}$. Per dimostrare che $\mathbf{P} = \mathbf{NP}$, ci resta da dimostrare che $\mathbf{NP} \subseteq \mathbf{P}$.
Assumiamo $L \in \mathbf{P}$.
Poiché $L$ è NP-complete, per definizione $L$ è NP-hard.
Questo significa che per ogni linguaggio $L' \in \mathbf{NP}$, esiste una riduzione polinomiale $f$ da $L'$ a $L$ ($L' \le_p L$).
Consideriamo una Macchina di Turing $M_{L'}$ che decide $L'$ utilizzando la riduzione a $L$. $M_{L'}$ è costruita come segue:
\begin{enumerate}
    \item Input: una stringa $w$.
    \item Calcola $y = f(w)$. Sia $M_f$ la MT che calcola $f$.
    \item Simula la Macchina di Turing $M_L$ (che decide $L$) con input $y$.
    \item $M_{L'}$ accetta se $M_L$ accetta, e $M_{L'}$ rifiuta se $M_L$ rifiuta.
\end{enumerate}

Analizziamo il tempo di esecuzione di $M_{L'}$:
\begin{enumerate}
    \item \textbf{Calcolo di $y = f(w)$:} Poiché $f$ è una riduzione polinomiale, $M_f$ opera in tempo $O(|w|^c)$ per una costante $c \ge 1$.
    \item \textbf{Dimensione di $y$:} Poiché $M_f$ opera in tempo $O(|w|^c)$, la dimensione dell'output $y$ non può essere maggiore di $O(|w|^c)$. Ovvero, $|y| \le O(|w|^c)$. (Una macchina non può scrivere più simboli di quanti passi compie).
    \item \textbf{Simulazione di $M_L$ su $y$:} Poiché abbiamo assunto $L \in \mathbf{P}$, $M_L$ opera in tempo polinomiale. Sia $O(|input|^d)$ il suo tempo di esecuzione, per una costante $d \ge 1$.
    Quindi, $M_L$ opera in tempo $O(|y|^d) = O((|w|^c)^d) = O(|w|^{c \cdot d})$.
\end{enumerate}
Il tempo totale di esecuzione di $M_{L'}$ è $O(|w|^c) + O(|w|^{c \cdot d})$. Poiché $c$ e $d$ sono costanti, $c \cdot d$ è anch'essa una costante. Quindi, il tempo totale è polinomiale rispetto a $|w|$.
Questo significa che per ogni linguaggio $L' \in \mathbf{NP}$, possiamo costruire una Macchina di Turing deterministica che lo decide in tempo polinomiale.
Pertanto, $\mathbf{NP} \subseteq \mathbf{P}$.
Combinando con $\mathbf{P} \subseteq \mathbf{NP}$, otteniamo $\mathbf{P} = \mathbf{NP}$.
\end{proof}

Questo teorema implica che per risolvere il problema P vs NP, è sufficiente trovare un algoritmo polinomiale per un singolo problema NP-complete, oppure dimostrare che tale algoritmo non esiste.

\section{Proprietà delle Riduzioni Polinomiali}

\subsection{Transitivit\`a delle Riduzioni Polinomiali}

\begin{theorem}
Siano $A, B, C$ tre linguaggi. Se $A \le_p B$ e $B \le_p C$, allora $A \le_p C$.
\end{theorem}

\begin{proof}
\begin{itemize}
    \item $A \le_p B$: Esiste una riduzione polinomiale $f: \Sigma^* \to \Sigma^*$ con tempo $O(|w|^c)$ per $c \ge 1$.
    \item $B \le_p C$: Esiste una riduzione polinomiale $g: \Sigma^* \to \Sigma^*$ con tempo $O(|w|^d)$ per $d \ge 1$.
\end{itemize}
Vogliamo dimostrare $A \le_p C$.
Consideriamo la funzione composta $h(w) = g(f(w))$.
\begin{enumerate}
    \item \textbf{Correttezza:} $w \in A \iff f(w) \in B \iff g(f(w)) \in C$. Quindi, $w \in A \iff h(w) \in C$. La correttezza logica è mantenuta.
    \item \textbf{Tempo di calcolo:}
    \begin{itemize}
        \item Il calcolo di $f(w)$ richiede $O(|w|^c)$ tempo. La dimensione dell'output $f(w)$ è $O(|w|^c)$.
        \item Il calcolo di $g(f(w))$ viene eseguito su input di dimensione $O(|w|^c)$. Poiché $g$ richiede tempo $O(|input|^d)$, il tempo per calcolare $g(f(w))$ è $O((|w|^c)^d) = O(|w|^{c \cdot d})$.
    \end{itemize}
    Il tempo totale per calcolare $h(w)$ è $O(|w|^c) + O(|w|^{c \cdot d})$, che è polinomiale.
\end{enumerate}
Quindi, $h$ è una riduzione polinomiale da $A$ a $C$, e $A \le_p C$.
\end{proof}

\subsection{Utilizzo della Transitivit\`a per Dimostrare NP-Hardness}

\begin{theorem}
Sia $A$ un linguaggio NP-hard. Se $A \le_p B$, allora $B$ è NP-hard.
\end{theorem}

\begin{proof}
Per dimostrare che $B$ è NP-hard, dobbiamo mostrare che per ogni linguaggio $L' \in \mathbf{NP}$, $L' \le_p B$.
Sappiamo che $A$ è NP-hard (per ipotesi). Questo significa che per ogni $L' \in \mathbf{NP}$, $L' \le_p A$.
Per ipotesi, sappiamo anche che $A \le_p B$.
Combinando queste due riduzioni usando la transitività (Teorema precedente): $L' \le_p A$ e $A \le_p B \implies L' \le_p B$.
Poiché $L'$ era un linguaggio generico in NP, abbiamo dimostrato che ogni linguaggio in NP può essere ridotto polinomialmente a $B$. Quindi $B$ è NP-hard.
\end{proof}

Questo teorema è di fondamentale importanza: una volta dimostrato che un problema è NP-hard (il primo è stato SAT), possiamo dimostrare l'NP-hardness di altri problemi tramite riduzioni "a catena", partendo da un problema NP-hard già noto.

\subsection{Illustrazione Grafica delle Classi di Complessità}

Immaginiamo una rappresentazione visuale delle classi:
\begin{itemize}
    \item $\mathbf{P}$ come un insieme interno (problemi "facili").
    \item $\mathbf{NP}$ come un insieme più grande che contiene $\mathbf{P}$.
    \item I problemi $\mathbf{NP}$-complete sono i problemi "più difficili" all'interno di $\mathbf{NP}$, formando una specie di "bordo" o "frontiera" di $\mathbf{NP}$. Se uno di questi fosse in $\mathbf{P}$, allora $\mathbf{P}$ e $\mathbf{NP}$ collasserebbero.
    \item I problemi $\mathbf{NP}$-hard sono tutti i problemi "almeno difficili quanto" $\mathbf{NP}$. Essi includono i problemi $\mathbf{NP}$-complete e possono anche includere problemi al di fuori di $\mathbf{NP}$ (es. problemi indecidibili), che sono ancora più difficili.
\end{itemize}

\begin{tikzpicture}[scale=0.8, >=Latex]
    % Draw NP boundary
    \draw[thick, fill=blue!10, draw=blue!50] (0,0) ellipse (3.5cm and 2.0cm) node[below=2.0cm] {\textbf{NP}};
    % Draw P boundary
    \draw[thick, fill=green!10, draw=green!50] (0,0) ellipse (1.5cm and 0.8cm) node[below=0.8cm] {\textbf{P}};

    % NP-Complete - on the boundary of NP
    \node at (3.2, 0.5) {\textbf{NP-Complete}};
    \node at (-3.2, -0.5) {}; % Placeholder to balance

    % NP-Hard - outside and on the boundary
    \node at (5, 1.5) {\textbf{NP-Hard}};
    \node at (4, -1) {};
    \node at (0, 2.5) {};

    % Arrows indicating "at least as hard as"
    \draw[->] (3.5, 0) -- (4.5, 0.5); % From NP boundary to outside NP-Hard
    \draw[->] (3.5, 0) -- (2, 2.2); % From NP boundary to outside NP-Hard
    \draw[->] (-3.5, 0) -- (-4.5, -0.5); % From NP boundary to outside NP-Hard
    \draw[->] (-3.5, 0) -- (-2, -2.2); % From NP boundary to outside NP-Hard
\end{tikzpicture}


\section{Problemi NP-Complete: SAT e 3-SAT}

Il problema \textbf{SAT} (Boolean Satisfiability Problem) è l'insieme delle formule booleane in Forma Normale Congiuntiva (CNF) che sono soddisfacibili. SAT è stato il primo problema dimostrato essere NP-complete (Teorema di Cook-Levin, 1971). Ci fidiamo di questo risultato per ora.

\subsection{Definizione di 3-SAT}

\begin{definition}[Formula 3-CNF]
Una formula booleana è in \textbf{3-CNF} se è in CNF e ogni sua clausola contiene \emph{al più} tre letterali.
\end{definition}

\begin{definition}[Problema 3-SAT]
Il problema \textbf{3-SAT} è l'insieme di tutte le formule booleane in 3-CNF che sono soddisfacibili.
\end{definition}

\begin{example}
Una formula in 3-CNF potrebbe essere:
$F = (x_1 \lor x_2 \lor \neg x_3) \land (\neg x_2 \lor x_4) \land (x_3 \lor x_5)$
Ogni clausola ha al più 3 letterali (la seconda ne ha 2, le altre 3).
\end{example}

Nonostante la restrizione sulla struttura delle clausole, 3-SAT è anch'esso un problema NP-complete.

\subsection{Dimostrazione che 3-SAT è NP-Complete}

Per dimostrare che 3-SAT è NP-complete, dobbiamo provare due cose:
\begin{enumerate}
    \item 3-SAT $\in \mathbf{NP}$
    \item 3-SAT è NP-hard
\end{enumerate}

\subsubsection{3-SAT $\in \mathbf{NP}$}
Un problema è in NP se può essere deciso da una macchina di Turing non deterministica in tempo polinomiale.
Per 3-SAT, una MT non deterministica può:
\begin{enumerate}
    \item \textbf{Guess (indovinare):} Indovinare un'assegnazione di verità per tutte le variabili booleane nella formula. Questo può essere fatto in tempo polinomiale (lineare nel numero di variabili, che è al più lineare nella lunghezza della formula).
    \item \textbf{Check (verificare):} Verificare se l'assegnazione indovinata soddisfa la formula. Questo comporta la valutazione di ogni clausola. Per una formula in 3-CNF, ogni clausola ha al più 3 letterali, quindi la valutazione di una clausola è costante. Verificare tutte le clausole richiede tempo polinomiale (lineare nel numero di clausole).
\end{enumerate}
Poiché entrambe le fasi (guess e check) richiedono tempo polinomiale, 3-SAT $\in \mathbf{NP}$.

\subsubsection{3-SAT è NP-hard (mediante riduzione SAT $\le_p$ 3-SAT)}

Per dimostrare che 3-SAT è NP-hard, useremo il teorema precedente e ridurremo SAT a 3-SAT ($SAT \le_p 3SAT$). Poiché SAT è NP-complete (quindi NP-hard), se $SAT \le_p 3SAT$, allora 3-SAT è NP-hard.

\textbf{Obiettivo:} Data una formula booleana $\phi$ in CNF (un'istanza di SAT), costruire una formula $\psi$ in 3-CNF (un'istanza di 3-SAT) tale che $\phi$ è soddisfacibile se e solo se $\psi$ è soddisfacibile. La trasformazione deve essere polinomiale.

\textbf{Descrizione della Trasformazione:}
Sia $\phi = C_1 \land C_2 \land \dots \land C_m$ una formula in CNF, dove ogni $C_i$ è una clausola.
Il processo di trasformazione da $\phi$ a $\psi$ è iterativo. Costruiamo una serie di formule intermedie $\phi^{(0)}, \phi^{(1)}, \dots, \phi^{(k)} = \psi$, dove $\phi^{(0)} = \phi$.
Ad ogni passo, $\phi^{(j+1)}$ è ottenuta da $\phi^{(j)}$ riscrivendo le clausole che hanno più di tre letterali.

Consideriamo una generica clausola $C_i = (L_1 \lor L_2 \lor \dots \lor L_k)$, dove $L_j$ sono letterali.
\begin{enumerate}
    \item \textbf{Caso 1: $k \le 3$ (la clausola ha al più 3 letterali).}
    La clausola $C_i$ viene copiata direttamente in $\phi^{(j+1)}$ senza modifiche.
    \item \textbf{Caso 2: $k > 3$ (la clausola ha più di 3 letterali).}
    Questa clausola $C_i$ viene sostituita da un insieme di clausole più piccole, introducendo nuove variabili ausiliarie.
    Sostituiamo $C_i = (L_1 \lor L_2 \lor L_3 \lor \dots \lor L_k)$ con due nuove clausole:
    $C'_i = (L_1 \lor L_2 \lor H_i)$
    $C''_i = (H_i \lor L_3 \lor \dots \lor L_k)$
    dove $H_i$ è una nuova variabile booleana non presente in $\phi$ o in altre variabili ausiliarie già introdotte.
    \textbf{Attenzione:} La seconda clausola $C''_i$ ha $k-2+1 = k-1$ letterali (se $k-2 \ge 0$). Quindi, $C''_i$ potrebbe ancora avere più di 3 letterali se $k-1 > 3$.
\end{enumerate}

Questo processo viene ripetuto. Partiamo da $\phi = \phi^{(0)}$. Per ogni clausola in $\phi^{(j)}$ che ha più di 3 letterali, applichiamo la trasformazione del Caso 2 per ottenere clausole per $\phi^{(j+1)}$. Continuiamo questo processo finché tutte le clausole nella formula risultante hanno al più 3 letterali. Questa formula finale sarà $\psi$.

\textbf{Analisi del Tempo di Trasformazione:}
Ogni passo della trasformazione riduce la lunghezza delle clausole "lunghe".
Una clausola con $k$ letterali viene sostituita da una clausola con 3 letterali e una clausola con $k-1$ letterali.
Questo processo garantisce che la dimensione delle clausole si riduca progressivamente. Il numero di iterazioni è al più proporzionale alla lunghezza massima delle clausole in $\phi$.
Il numero di clausole nella formula finale $\psi$ sarà al più polinomiale nel numero di clausole originali di $\phi$ (e nella lunghezza di $\phi$). Il numero di nuove variabili introdotte è anch'esso polinomiale.
Pertanto, la trasformazione è calcolabile in tempo polinomiale.

\textbf{Correttezza della Trasformazione: $\phi$ è soddisfacibile $\iff \psi$ è soddisfacibile.}

\textbf{Direzione 1: $\phi$ è soddisfacibile $\implies \psi$ è soddisfacibile.}
Supponiamo che $\phi$ sia soddisfacibile. Esiste quindi un'assegnazione di verità $\sigma$ per le variabili di $\phi$ che rende $\phi$ vera.
Vogliamo mostrare che esiste un'assegnazione di verità $\tau$ per le variabili di $\psi$ (che include le variabili di $\phi$ più le variabili ausiliarie $H_i$) che rende $\psi$ vera.
Definiamo $\tau$ in modo che valuti le variabili di $\phi$ esattamente come $\sigma$. Per le variabili ausiliarie $H_i$, le valuteremo in modo opportuno.

Consideriamo una clausola $C_i = (L_1 \lor L_2 \lor \dots \lor L_k)$ di $\phi$.
Se $k \le 3$, $C_i$ è copiata in $\psi$. Poiché $\sigma$ soddisfa $C_i$, anche $\tau$ soddisferà $C_i$ (dato che $\tau$ replica $\sigma$).
Se $k > 3$, $C_i$ è sostituita da $C'_i = (L_1 \lor L_2 \lor H_i)$ e $C''_i = (H_i \lor L_3 \lor \dots \lor L_k)$.
Poiché $\sigma$ soddisfa $C_i$, almeno un letterale $L_j$ in $C_i$ è vero sotto $\sigma$.
\begin{itemize}
    \item Se $L_1$ o $L_2$ è vero sotto $\sigma$: Assegniamo $H_i = \text{Falso}$. Allora $C'_i$ è vera (per $L_1$ o $L_2$) e $C''_i$ diventa $(\text{Falso} \lor L_3 \lor \dots \lor L_k)$. Poiché $\sigma$ soddisfaceva $C_i$, se $L_1$ o $L_2$ erano Falsi, ci doveva essere un altro $L_j$ (con $j \ge 3$) vero. Se questo è il caso, $C''_i$ sarà vera.
    \item Se $L_1$ e $L_2$ sono Falsi sotto $\sigma$: Allora deve esserci un $L_j$ con $j \ge 3$ che è vero sotto $\sigma$. Assegniamo $H_i = \text{Vero}$. Allora $C'_i$ diventa $(\text{Falso} \lor \text{Falso} \lor \text{Vero})$, che è vero. E $C''_i$ diventa $(\text{Vero} \lor L_3 \lor \dots \lor L_k)$, che è vero (dato che $H_i$ è Vero).
\end{itemize}
In entrambi i casi, possiamo assegnare un valore a $H_i$ in modo che $C'_i \land C''_i$ sia vera. Questo processo si applica a cascata per tutte le trasformazioni intermedie.
Dunque, se $\phi$ è soddisfacibile, $\psi$ è soddisfacibile.

\textbf{Direzione 2: $\psi$ è soddisfacibile $\implies \phi$ è soddisfacibile.}
Supponiamo che $\psi$ sia soddisfacibile. Esiste quindi un'assegnazione di verità $\tau$ per le variabili di $\psi$ (che include le variabili di $\phi$ e le ausiliarie) che rende $\psi$ vera.
Vogliamo mostrare che l'assegnazione $\sigma$ ottenuta da $\tau$ ignorando le variabili ausiliarie (cioè restringendo $\tau$ alle sole variabili di $\phi$) rende $\phi$ vera.

Consideriamo una clausola $C_i = (L_1 \lor L_2 \lor \dots \lor L_k)$ di $\phi$.
Se $k \le 3$, $C_i$ è identica in $\phi$ e $\psi$. Poiché $C_i$ è vera sotto $\tau$, lo è anche sotto $\sigma$ (dato che $\sigma$ è la restrizione di $\tau$).
Se $k > 3$, $C_i$ è sostituita da $C'_i = (L_1 \lor L_2 \lor H_i)$ e $C''_i = (H_i \lor L_3 \lor \dots \lor L_k)$.
Poiché $\tau$ soddisfa $\psi$, sia $C'_i$ che $C''_i$ sono vere sotto $\tau$.
\begin{itemize}
    \item Se $H_i$ è vera sotto $\tau$: Allora $C'_i$ è vera perché $H_i$ è vera. E $C''_i$ è vera perché $H_i$ è vera.
    \item Se $H_i$ è falsa sotto $\tau$: Allora $C'_i$ deve essere vera per $L_1$ o $L_2$. E $C''_i$ deve essere vera per almeno un $L_j$ ($j \ge 3$).
\end{itemize}
In entrambi i casi, per garantire che $C'_i \land C''_i$ sia vera sotto $\tau$, deve essere vero che $(L_1 \lor L_2 \lor \dots \lor L_k)$ è vero sotto $\tau$ (e quindi sotto $\sigma$ per le sole variabili di $\phi$).
Infatti, $L_1 \lor L_2 \lor \dots \lor L_k \equiv (L_1 \lor L_2 \lor H_i) \land (H_i \lor L_3 \lor \dots \lor L_k)$ non è una tautologia. La trasformazione mantiene la soddisfacibilità se e solo se $H_i$ è considerata una variabile.
Il punto chiave è che se $C'_i \land C''_i$ è vero, allora deve essere vero $(L_1 \lor L_2 \lor \dots \lor L_k)$.
Se $\tau(H_i)=Vero$, allora $L_1 \lor L_2 \lor Vero$ è Vero e $Vero \lor L_3 \lor \dots \lor L_k$ è Vero. Non ci dice nulla sugli $L_j$.
Se $\tau(H_i)=Falso$, allora $L_1 \lor L_2 \lor Falso$ è Vero (quindi $L_1 \lor L_2$ è Vero) e $Falso \lor L_3 \lor \dots \lor L_k$ è Vero (quindi $L_3 \lor \dots \lor L_k$ è Vero).
In entrambi i sottocasi, abbiamo che $(L_1 \lor L_2 \lor \dots \lor L_k)$ è vero.
Questo si propaga a ritroso attraverso le iterazioni della trasformazione.
Dunque, se $\psi$ è soddisfacibile, anche $\phi$ è soddisfacibile.

Avendo dimostrato che $SAT \le_p 3SAT$ e sapendo che SAT è NP-hard, concludiamo che 3-SAT è NP-hard.
Poiché 3-SAT $\in \mathbf{NP}$ e 3-SAT è NP-hard, allora 3-SAT è NP-complete.

\subsection{Problema 2-SAT}
Si può dimostrare che il problema \textbf{2-SAT} (formule in CNF dove ogni clausola ha esattamente due letterali) appartiene alla classe \textbf{P}. Nonostante la somiglianza con 3-SAT, 2-SAT è un problema molto più semplice, risolvibile in tempo polinomiale. Questo sottolinea come anche piccole restrizioni sulla struttura del problema possano avere un impatto enorme sulla sua complessità.

\subsection{Esercizio: EXACT 3-SAT}
\begin{definition}[Problema EXACT 3-SAT]
Il problema \textbf{EXACT 3-SAT} è l'insieme di tutte le formule booleane in CNF in cui ogni clausola contiene \emph{esattamente} tre letterali, e la formula è soddisfacibile.
\end{definition}

\textbf{Esercizio per casa:} Dimostrare che EXACT 3-SAT è NP-complete.
\textbf{Suggerimento:} Ridurre 3-SAT a EXACT 3-SAT.

\end{document}