Actually, Wikipedia cites the Strongly connected components algorithm which is linear:
- Consider a 2SAT problem:
$$(¬a ∨ b) ∧ (¬b ∨ c) ∧ (¬c ∨ b) ∧ (y ∨ b) ∧ (¬z ∨ y)$$
- For each clause, convert it into two material conditionals where the negative of the first literal implies the second literal and vice versa (i.e. the contraposition):
$$(¬a ∨ b)$$ $$=>$$ $$a {\displaystyle \rightarrow } b,$$ $$¬b {\displaystyle \rightarrow } ¬a$$
- You get a graph where the nodes are the literals; you can note that this graph is skew symmetric, due to the nature of the contraposition:
(a) → (b) → (¬y) → (z)
↖ ↙
(c)
(¬a) ← (¬b) ← (y) ← (¬z)
↘ ↗
(¬c)
For the Kosaraju's algorithm, let's create an ordered list L of graph vertices.
For each vertex u of the graph, mark u as unvisited. Let L be empty.
Start to visit the graph from one node (like ¬b) following the arrow and avoiding the visited node.
Each time you're blocked and you have to backtrack to continue, you add the last node in the list:
(a) → (b) → (¬y) → (z)
↖ ↙
(c)
(¬a✓) ← (¬b✓) ← (y) ← (¬z)
↘ ↗
(¬c✓)
L = [¬c, ¬a, ¬b]
- When you are completely blocked, start to explore from an unvisited node and again and again:
(a✓) → (b✓) → (¬y✓) → (z✓)
↖ ↙
(c✓)
(¬a✓) ← (¬b✓) ← (y✓) ← (¬z✓)
↘ ↗
(¬c✓)
L = [¬c, ¬a, ¬b, y, ¬z, c, a, b, ¬y, z]
- Return the list:
L = [z, ¬y, b, a, c, ¬z, y, ¬b, ¬a, ¬c]
- Create the transpose graph; it's just the same with reversed arrows:
(a) ← (b) ← (¬y) ← (z)
↘ ↗
(c)
(¬a) → (¬b) → (y) → (¬z)
↖ ↙
(¬c)
- Visit again the transpose graph starting from the first node of the list:
(a) ← (b) ← (¬y) ← (z)
↘ ↗
(c)
(¬a) → (¬b) → (y) → (¬z✓)
↖ ↙
(¬c)
L = [(z), ¬y, b, a, c, ¬z, y, ¬b, ¬a, ¬c]
- Each time you are blocked, you have found a strongly connected components; you note it and you remove all its nodes from the list; repeat until the list is empty:
L = []
- The Kosaraju's algorithm tells you that you have a first strongly connected component
{a, b, c}, a second one {¬y}, a third one {z} and their opposites:
(a) → (b) (¬y) (z)
↖ ↙
(c)
(¬a) ← (¬b) (y) (¬z)
↘ ↗
(¬c)
If a strongly connected component contains a literal and its opposite, the problem is unsolveable and we halt.
Otherwise, replace the nodes by their strongly connected components:
(a, b, c) ← (¬y) ← (z)
(¬z) → (y) → (¬a, ¬b, ¬c)
- Use the topological order defined by the Kosaraju's algorithm:
(4:a, b, c) ← (6:¬y) ← (5:z)
(2:¬z) → (3:y) → (1:¬a, ¬b, ¬c)
- Reverse the order:
(3:a, b, c) ← (1:¬y) ← (2:z)
(5:¬z) → (4:y) → (6:¬a, ¬b, ¬c)
- Starting from the order, if the variables are not assigned, set the variables of the component to their literal value:
(3:a=false, b=false, c=false) ← (1:¬y) ← (2:z)
(5:¬z) → (4:y) → (6:a=false, b=false, c=false)
- Repeat until all the variables are assigned:
(3:a=true, b=true, c=true) ← (1:y=false) ← (2:z=true)
(5:z=true) → (4:y=false) → (6:a=true, b=true, c=true)
One solution is a=true, b=true, c=true, y=true, z=false