Where Propositions Run Out

Propositional logic cannot say “every integer has a successor” or “some key hashes to slot 3.” It only knows whole propositions, true or false, with no way to reach inside them and talk about the objects. Predicate logic adds that reach. It introduces predicates over a domain and quantifiers that range across it, which is exactly the expressiveness a formal specification needs.

A predicate is a symbol that “represents a property or a relation.” Applied to arguments it becomes a proposition: Prime(7) is true, Prime(8) is false. Written with a free variable, Prime(x) is an open formula with no truth value until you either substitute a specific value or bind the variable with a quantifier.

Note

The payload is that quantifiers turn open formulas into claims about a whole domain, and with nested quantifiers the order is the meaning. Swapping for is not a stylistic choice; it changes the specification. This is the single most common place a “correct-sounding” requirement is actually wrong.

The Two Quantifiers

A quantifier, per Wikipedia, is “an operator that specifies how many individuals in the domain of discourse satisfy an open formula.” Two of them dominate:

  • Universal, : the universal quantifier “expresses that everything in the domain satisfies the property denoted by P.” Read it “for all , .”
  • Existential, : the existential quantifier “expresses that there exists something in the domain which satisfies that property.” Read it “there exists an such that .”

Every quantified statement is relative to a domain of discourse. "" is false over the integers and true over the positive reals. The domain is not decoration; leave it unstated and the claim is ill-defined.

Negating a Quantifier

Pushing a negation through a quantifier flips it. Formally, : the negation of “everything satisfies ” is “something fails .” Symmetrically, .

This is the daily-use rule. To refute “all swans are white” you exhibit one non-white swan, which is the existential negation made concrete, and the same move as disproof by counterexample. In testing, the negation of a “for all inputs” postcondition is a single failing input, which is what a bug report is.

Nested Quantifiers and Order

Stacking quantifiers is where predicate logic earns its keep and where mistakes hide. Compare two statements over a domain of people:

  • : everyone loves someone (the someone may differ per person).
  • : there is one specific person whom everyone loves.

Same predicate, quantifiers reordered, and the second is a far stronger claim that implies the first but not conversely. The rule of thumb: a later quantifier’s variable may depend on an earlier one, so coming after allows to be chosen per , while first fixes one up front.

Example

The definition of a limit is a nested-quantifier spec. "" unfolds to Read the dependency order: given any tolerance , you must produce a (which may depend on ), and then it must work for all within . Swap the first two quantifiers and you would be demanding a single good for every at once, which is a different and usually false statement.

Warning

When a requirement mixes “every” and “some,” write it with explicit quantifiers before writing code. “Every order can be assigned to a courier” () and “some courier can take every order” () sound alike in English and describe different systems. The quantifier order is the requirement.

Sources