Logical Connectives and Normal Forms

Propositional logic gives you a small toolbox of connectives\neg (not), \wedge (and), \vee (or) — and lets you bolt them together into formulas of any size. A single formula can be written in a bewildering number of equivalent ways, so logicians agreed on two tidy normal forms that any formula can be squeezed into. Once you can put a formula into one of these shapes, machines can reason about it, chips can compute it, and truth tables read off almost by themselves.

This matters far beyond the whiteboard. Every silicon chip in your phone is a sea of NAND gates — one humble connective, repeated a billion times, is enough to build every logical function. And a SAT solver — the workhorse behind chip verification, timetabling, and AI planning — insists on being fed its input in one specific normal form, CNF. This page is about those normal forms and the surprising fact that so little machinery goes such a long way.

Literals, clauses, and terms

Three small words unlock everything that follows.

Clauses and terms are mirror images: OR of literals versus AND of literals. Stack one kind on top of the other and you get exactly the two normal forms.

CNF and DNF

A formula is in Conjunctive Normal Form (CNF) when it is an AND of clauses — an AND of ORs:

(P \vee \neg Q) \wedge (\neg P \vee Q \vee R) \wedge (\neg R)

A formula is in Disjunctive Normal Form (DNF) when it is an OR of terms — an OR of ANDs:

(P \wedge \neg Q) \vee (\neg P \wedge Q \wedge R) \vee (\neg R)

The names describe the outermost operator: CNF is one big conjunction (AND) at the top, DNF is one big disjunction (OR) at the top. A handy mnemonic: CNF = AND of ORs, DNF = OR of ANDs. Every formula is equivalent to some CNF and to some DNF — and the truth table hands them to you for free.

For every propositional formula there is: Both can be read straight off the formula's truth table, so no formula is beyond reach.

Reading DNF off the true rows, CNF off the false rows

Here is the trick that makes normal forms feel like magic. Take any formula's truth table:

The figure works the first recipe on the exclusive-or table F = P \oplus Q, which is true in exactly two rows. Step through it to watch each true row turn into a term and the terms join into a DNF.

The resulting DNF is

P \oplus Q \;\equiv\; (\neg P \wedge Q) \vee (P \wedge \neg Q).

Two true rows, two terms. Had the table been true in five rows, the DNF would have five terms — the recipe never fails, it just gets longer.

Worked example: build a DNF, then simplify

Consider the formula F = P \vee (\neg P \wedge Q). Its truth table is:

\begin{array}{cc|c} P & Q & F \\ \hline 0 & 0 & 0 \\ 0 & 1 & 1 \\ 1 & 0 & 1 \\ 1 & 1 & 1 \end{array}

Read the DNF off the three true rows. Rows (0,1), (1,0) and (1,1) give the terms (\neg P \wedge Q), (P \wedge \neg Q) and (P \wedge Q), so the "full" DNF is

(\neg P \wedge Q) \vee (P \wedge \neg Q) \vee (P \wedge Q).

Now simplify. The last two terms share the factor P: (P \wedge \neg Q) \vee (P \wedge Q) = P \wedge (\neg Q \vee Q) = P. That collapses the whole thing to

(\neg P \wedge Q) \vee P \;\equiv\; P \vee Q.

The truth table for P \vee Q is indeed exactly those same three true rows — so P \vee (\neg P \wedge Q) was just a dressed-up P \vee Q all along. Reading a normal form off the table is mechanical; shrinking it back down is where the cleverness lives.

Functional completeness: how little you actually need

A set of connectives is functionally complete if every truth function can be built from it. Because the DNF recipe writes any formula using only \neg, \wedge and \vee, that set is complete straight away:

\{\neg, \wedge, \vee\} \text{ is functionally complete.}

But we can trim it. De Morgan's laws let you rewrite an OR using AND and NOT, or an AND using OR and NOT:

P \vee Q \equiv \neg(\neg P \wedge \neg Q), \qquad P \wedge Q \equiv \neg(\neg P \vee \neg Q).

So you can throw away \vee (keeping \{\neg, \wedge\}) or throw away \wedge (keeping \{\neg, \vee\}) — each of those two-element sets is still complete. What you may not drop is \neg: \{\wedge, \vee\} alone can never make the constant-false function, because with all inputs true it can only ever output true.

The showstopper: a single connective can be complete on its own. The NAND (\uparrow, "not-and") and NOR (\downarrow, "not-or") each do it:

P \uparrow Q \;\equiv\; \neg(P \wedge Q), \qquad P \downarrow Q \;\equiv\; \neg(P \vee Q).

From NAND alone you rebuild the whole toolkit: \neg P \equiv P \uparrow P, P \wedge Q \equiv (P \uparrow Q) \uparrow (P \uparrow Q), and P \vee Q \equiv (P \uparrow P) \uparrow (Q \uparrow Q). That is why a chip fab can build any circuit from one gate design — and why NAND is called the Sheffer stroke.

Every gate from one gate

Here is the Sheffer stroke earning its keep. Starting from a single \mathrm{nand} function (using 1 for true and 0 for false, so AND is just multiplication), we reconstruct NOT, AND, and OR — and check them against every input.

// NAND is the only primitive. For a,b in {0,1}, (a AND b) = a*b, so NAND = 1 - a*b. const nand = (a: number, b: number): number => 1 - a * b; // Rebuild the whole toolkit from NAND alone. const not = (a: number): number => nand(a, a); const and = (a: number, b: number): number => not(nand(a, b)); const or = (a: number, b: number): number => nand(not(a), not(b)); for (const a of [0, 1]) { for (const b of [0, 1]) { console.log(`a=${a} b=${b} not(a)=${not(a)} and=${and(a, b)} or=${or(a, b)}`); } }

Every output matches the ordinary truth tables — all conjured from one connective.

The classic mix-up: reading DNF off the false rows, or CNF off the true ones. Keep the pairing straight:

The reason for the flip: a DNF term should be true on its own row, while a CNF clause should be false only on its own row (so its negation matches the row). Sanity-check by counting: if the table has 3 true and 1 false row, the DNF has 3 terms and the CNF has 1 clause.

You can turn any formula into CNF by pushing negations inward and distributing \vee over \wedge — but beware, the result can explode. Distributing (P_1 \wedge Q_1) \vee (P_2 \wedge Q_2) \vee \dots \vee (P_n \wedge Q_n) into CNF produces on the order of 2^{n} clauses — the formula's size can grow exponentially.

This is not a quirk of clumsy algebra; it is genuinely unavoidable for naive conversion. Real tools dodge it with the Tseitin transformation, which introduces fresh helper variables to produce an equisatisfiable CNF (same yes/no answer to "is it satisfiable?") that is only linearly bigger. So when a SAT solver wants CNF, it does not blindly distribute — and neither should you on anything larger than a toy formula.