\[ \probThreeSAT = \setbuild{\encoding{\phi}}{\phi \text{ is a satisfiable 3-CNF formula}} \]
\[ \probIndSet = \setbuild{\encoding{G, k}}{ G \text{ is an undirected graph with a } k\text{-independent set}} \]
Theorem: \(\probThreeSAT \le^\P \probIndSet\).
Proof:
Given a 3-CNF formula \(\phi\), our reduction must produce a pair \((G, k)\) such that: \[ \encoding{\phi} \in \probThreeSAT \; \iff \; \encoding{G, k} \in \probIndSet \]
Set \(k\) equal to the number of clauses in \(\phi\).
Write \(\phi\) as: \[ \phi = (a_1 \lor b_1 \lor c_1) \land (a_2 \lor b_2 \lor c_2) \land \ldots \land (a_k \lor b_k \lor c_k) \] where \(a_i, b_i, c_i\) are the three literals in clause \(i\).
G will have \(3k\) nodes,
one for each literal in \(\phi\).
\[ \phi = (x \lor x \lor y) \land (\overline{x} \lor \overline{y} \lor \overline{y}) \land (\overline{x} \lor y \lor y) \hspace{6em} \]
Is this formula satisfiable?
Yes: \(x = 0, y = 1\).
\(\encoding{\phi} \in \probThreeSAT\) iff we can pick
one literal from each clause
to set to “1” without conflicts!
Theorem: \(\probThreeSAT \le^\P \probIndSet\).
Proof:
Given a 3-CNF formula \(\phi\): \[ \phi = (a_1 \lor b_1 \lor c_1) \land (a_2 \lor b_2 \lor c_2) \land \ldots \land (a_k \lor b_k \lor c_k) \] we produce a pair \((G, k)\) such that: \[ \encoding{\phi} \in \probThreeSAT \; \iff \; \encoding{G, k} \in \probIndSet \]
Set \(k\) equal to the number of clauses in \(\phi\).
We can generate these edges in polynomial time by looping over all pairs of nodes (\(O(|V|^2)\))
and checking the these two conditions by scanning through \(\phi\). (Python code in lecture notes)
Proof that \(\encoding{\phi} \in \probThreeSAT \; \iff \; \encoding{G, k} \in \probIndSet\):
Let \(A, B \subseteq \binary^*\) be decision problems. We say \(A\) is polynomial-time reducible to \(B\)
if there is a polynomial-time computable function \(f\) such that for all \(x \in \binary^*\):
\[ x \in A \iff f(x) \in B \]
We denote this by \(A \le^P B\).
\(A \le^P B\) means: “B is at least as hard as A” (to within a polynomial-time factor).
A language \(B\) is called NP-hard if for every language \(A \in \NP\), \(A \le^P B\).
A language \(B\) is called NP-complete if:
Theorem: If \(B\) is NP-complete and if \(B \in \P\) then \(\P = \NP\).
Proof:
A language \(B\) is called NP-hard if for every language \(A \in \NP\), \(A \le^P B\).
A language \(B\) is called NP-complete if:
Theorem: If \(B\) is NP-complete and if \(B \in \P\) then \(\P = \NP\).
Corollary: If \(\P \ne \NP\) then no NP-complete problem is in \(\P\).
This is the significance of NP-completeness:
if you show your problem is NP-hard, then there is (probably) no efficient algorithm for it.
We can chain reductions together!
Observation: \(\le^P\) is transitive
(if \(A \le^P B\) and \(B \le^P C\), then \(A \le^P C\))
def reduce_A_to_B(x):
"""
reduction from NP prob
A to NP-hard prob B
"""
raise NotImplementedError()
def reduce_B_to_C(x):
"""
reduction from B
to NP-hard prob C
"""
raise NotImplementedError()
def C_decider(x):
"""
hypothetical polynomial-time
decider
"""
raise NotImplementedError()
def A_decider(x):
"""
polynomial time
"""
y = reduce_A_to_B(x)
z = reduce_B_to_C(y)
return C_decider(z)
\(A\) will be a stand-in for any problem in \(\NP\).
Theorem: If \(B\) is \(\NP\)-hard and \(B \le^P C\) for some language \(C\),
then \(C\) is also \(\NP\)-hard.
Proof:
Corollary: If \(B\) is \(\NP\)-complete, \(B \le^P C\),
and \(C \in \NP\), then \(C\) is \(\NP\)-complete.
Finding a reduction from any known-NP-hard problem \(B\) to \(C\) proves that all problems in \(\NP\) are reducible to \(C\)! (\(C\) is NP-hard too.)
Cook-Levin Theorem: \(\probSAT\) and \(\probThreeSAT\) are NP-complete.
Theorem: \(\probIndSet\) and \(\probClique\) are NP-complete.
Proof: