SE 500: Quantification

Propositional logic is rather limited in its expressive and deductive power. For example, consider this variant of a classic syllogism:

All dogs are mortal.
Fido is a dog.
Therefore, Fido is mortal.

The reasoning displayed here cannot be modeled effectively in a formalism as limited as propositional logic, in which all variables are boolean and the only operators correspond to functions mapping (one or more) boolean values to a boolean value.

Predicate Logic generalizes propositional logic, thereby increasing expressiveness and the ability to model more subtle chains of reasoning. Among the generalizations is that boolean variables are replaced by predicates, which are functions that map values of any types into boolean values. Predicates can be used to express that specified entities possess specified properties (e.g., of being a dog, or being mortal) or that a certain relationship holds between specified entities (e.g., Joe likes chocolate).

Another extension is that values of types other than boolean can be involved in expressions. (This would include not only numbers but also other mathematical structures (e.g., directed graphs) and informal domains (e.g., living things).)

Chapter 8 in Gries & Schneider focuses on quantification, which is yet another construct that predicate logic adds to propositional logic.

8.1 On types

The notion of data type should be familiar to anyone who has written programs in a strongly-typed programming language such as Java. A data type is a (nonempty) set of values along with a set of operations that can be applied to such values.

Within the realm of numbers, it is often useful to distinguish between several types, including naturals, integers, rationals, and reals. (See Table 8.1.) Each type listed here is a subtype of the one that follows it.

Expressions, which are formed using literals (e.g., 15), variables, and function application (often expressed using infix operators such as + and -), have types. Indeed, an expression's type corresponds to the type of its result. Thus, the expression 3 + 5 can be viewed as being of type natural (or any of its supertypes). Meanwhile, x<5 ∧ y≥7 is of type boolean. Variables, too, have types. Implicitly, each of the variables x and y appearing in the previous sentence is of some numeric type, or else the expression is nonsense and thus not type correct, as Gries calls it. An expression that is not type correct is syntactically invalid, just as though a Java compiler had flagged it as such.

We can annotate an expression (and any of its subexpressions) by explicitly identifying its type. However, we rarely do this, because it would clutter up expressions terribly (even more than including parentheses that are made unnecessary by rules of operator precedence). Rather, we usually rely upon context to infer the type of each subexpression within an expression. As an example of an overly-annotated expression, consider

((5:ℕ + 3:ℤ):ℤ < z:ℝ):В

Here we have used (as illustrated in Table 8.1) standard symbols for various data types.

Functions, too, have types, often referred to as signatures. For example, if f is a function that takes as arguments an integer and a real number and yields as its result a boolean value, its type is denoted as ℤ × ℝ ⟶ B

It follows that the function application f(5.7, 3) is not type correct, because the first argument is not an integer. (That the second argument is an integer (even a natural number) is OK, because every integer is also a real number.)

To ensure that applying a textual substitution does not introduce type incorrectness, it is necessary that, in the expression E[x := F] the type of F is a descendant of the type of x.

Also, an application b = c of the equality operator, which is polymorphic, is type correct only if b and c are of the same type (or one of them is a subtype of the other, such as is the case with ℕ and ℤ).


8.2 Quantification (Syntax and Interpretation)

It is likely that the reader is familiar with at least one kind of quantification, which is summation. For example,

n
Σ f(i)
i=1

denotes the sum f(1) + f(2) + ... + f(n). Suppose that f is described by the expression E in which the variable x corresponds to f's argument. (For example, perhaps f is described by the polynomial E: 2x2 − 4x + 3.) Then the function application f(X) (where X is an expression of type ℤ) is just E[x:=X]. Which is to say that the summation above describes the sum

E[x:=1] + E[x:=2] + ... + E[x:=n]

For the summation above (using E in place of f(i)), Gries prefers to use the linear notation

(Σi | 1≤i≤n : E)   or   (+i | 1≤i≤n : E)

Among the advantages of this notation is that the parentheses make explicit the scope of the dummy (or quanitifed) variable i. The scope of a variable includes the region within an expression where it can be referred to.

Another advantage is that it is easier to write more general ranges for the dummy. For example, if we wanted to restrict the sum above so that only odd argument values are considered, we could write it as

(+i | 1≤i≤n ∧ isOdd.i : E)

which, expanded, is

E[x:=1] + E[x:=3] + ... + E[x:=n']

where n' is either n or n-1 according to whether n is odd or even, respectively.

Note that Gries prefers using the period to indicate function application, rather than the more traditional syntax of placing the argument(s) inside parenthesis (as in isOdd(i)).

Yet a third advantage of the linear notation is that it more easily accommodates the use of multiple dummies, as in

(+i,j | 1≤i≤3 ∧ 0≤j<i : ij)
which, when expanded, is the sum

10 + 20 + 21 + 30 + 31 + 32

Now, how did we know that the dummy variables i and j were intended to range over integers rather than real numbers? From context! To make that fact explicit, we could annotate the expression like this:

(+i,j:ℕ | 1≤i≤3 ∧ 0≤j<i : ij)

The general form of a quantification over (operator) ★ is

(★x,... | R : P)

where

Consider the quantification (★x | R : P), where x:T (i.e., x is of type T). Suppose that the values of type T that satisfy R are precisely those in the set {a1, a2, ..., an}. (One could call this the satisfying set of R.) In other words, suppose that R[x:=E] is true if and only if E is equal to a member of that set. Then what (★x | R : P) denotes (or what might be called its expansion) is

P[x:=a1] ★ P[x:=a2] ★ ··· ★ P[x:=an]

Somewhat inaccurately, we refer to each P[x:=ai] in the expansion as a term.

The reason for requiring ★ to be associative and symmetric is so that the value of a quantification does not depend upon the order in which the terms occur in its expansion, or how they are grouped. If the range R of a quantification is false, so that its satisfying set is empty, the only sensible result is the identity element of ★. (If ★ has no identity, the result is undefined.)

Among the operators that are frequently "quantified over" are addition, multiplication, conjunction, disjunction, min, and max.

If there are multiple dummies, then the satisfying set of the range will contain tuples. For example, the satisfying set for our earlier example (+i,j | 1≤i≤3 ∧ 0≤j<i : ij) is the set of (i,j)-pairs {(1,0), (2,0), (2,1), (3,0), (3,1), (3,2)}.

Gries uses the quantification (8.7) (∧i |: x·i = 0) to illustrate the concept of scope. (When the range of a quantification is omitted, as here, it means the same thing as true.) Intuitively, this quantification says that, for every possible value of i (understood to be of type ℤ, from context), the product x·i is zero. From your knowledge of numbers and multiplication, it should be clear that this statement is equivalent to x = 0.

Now, whether or not this is a true statement depends upon the value of x, and thus depends upon the state in which the expression is evaluated. (Our notion of state as being a mapping from variables to values continues here, but we now admit the use of variables of any types, no longer being limited to the use of only boolean variables.)

On the other hand, the meaning of the statement does not depend upon the value to which the state maps variable i. Indeed, had we written the quantification using j as the dummy rather than i, it would mean exactly the same thing. That is, in every state

(∧i |: x·i = 0)  ≡  (∧j |: x·j = 0)

is true, regardless of the values to which i and/or j are mapped in those states.

This reveals that the roles being played by x and i in (8.7) are different. To distinguish these roles, we say that occurrences of i (in the range and body of the quantification) are bound (to the dummy) and occurrences of x are free. A free occurrence of a variable is one that appears in every term of a quantification's expansion. Meanwhile, a bound occurrence of a variable is one that, in each term of the expansion, will have been substituted for.

For example, the expansion of (+i | 0≤i≤3 : xi) is

x0 + x1 + x2 + x3

Notice that the free occurrence of x is repeated in each term in the expansion, while in each term the bound occurrence of i has been replaced by a value satisfying the range 0≤i≤3.

The scope of a dummy variable includes only the range and body of the quantification.

Gries illustrates this with (8.8) i>0 ∧ (∧i | 0≤i : x·i = 0). The lone occurrence of x is free, as is the first occurrence of i. The occurrences of i "inside" the quantification are bound to the quantification's dummy. Rewriting (8.8) by replacing the quanitification by its expansion, we get

i>0  ∧  (x·0 = 0  ∧  x·1 = 0  ∧  x·2 = 0  ∧  ···)

Notice that, after having substituted for dummy i in each term of the expansion, the only occurrence of i that remains is the one not bound to a dummy (i.e., the free occurrence). Hence, that is the only occurrence of i for which we would, in evaluating the expression, substitute the value to which i is mapped by the state.

Technical definition of free and bound variable occurrences goes here!

To cover expressions in which quantifications occur, we need to extend the rules by which textual substitutions are carried out. (Gries's (8.11) is not quite complete.)

(*x | R : Q)[y:=E]  =  { (*x | R : Q) if 'x'='y'
(1)
(*x | R[y:=E] : Q[y:=E]) if 'x'≠'y' ∧ ¬occurs.'x'.'E' (2)
(*z | R[x:=z] : Q[x:=z])[y:=E] otherwise (3)

By 'x'='y' is meant that x and y are the same variable, whereas 'x'≠'y' means that they are distinct variables.
By occurs.'x'.'E' is meant that there is at least one free occurrence of x in E.

In the case of (3), z is is chosen to be a fresh variable satisfying 'z'≠'x' ∧ 'z'≠'y' ∧ ¬occurs.'z'.'E'. To be explicit, the otherwise condition of (3) is 'x'≠'y' ∧ occurs.'x'.'E'.


8.3 Rules Pertaining to Quantification

Also needed is to introduce a version of the Leibniz Rule of Inference to deal with quantification:

P = Q

(★x | E[z:=P] : S)  =  (★x | E[z:=Q] : S)

R  ⟹  P = Q

(★x | R : E[z:=P])  =  (★x | R : E[z:=Q])

These rules are needed so that, for example, it is possible to have a proof in which replacing, say, x + x by 2x within the body of a quantification having x as a dummy is possible. That is, we'd like to be able to have a step in a proof that looks like this:

    (+x | 0≤x<8 : x+x)

=      < x+x = 2x >

    (+x | 0≤x<8 : 2x)

Axioms and Theorems

(8.13) Axiom, Empty Range: (★x | false : P) = u (identity element of ★)

(8.14) Axiom, One-point Rule: Provided x does not occur free in E,
(★x | x = E : P) = P[x := E]

(8.15) Axiom, Distributivity: Provided each quantification is defined,
(★x | R : P) ★ (★x | R : Q) = (★ | R : P ★ Q)

Justification: Supposing that the satisfying set of R is {a1, a2, ...}:

   (★x | R : P) ★ (★x | R : Q) 

=     < expanding >

   (P[x:=a1] ★ P[x:=a2] ★ ....) ★ (Q[x:=a1] ★ Q[x:=a2] ★ ....)  

=     < symmetry and associativity of ★ >

   (P[x:=a1] ★ Q[x:=a1]) ★ (P[x:=a2] ★ Q[x:=a2]) ★ ...

=     < textual substitution distributes over operators >

   (P★Q)[x:=a1] ★ (P★Q)[x:=a2] ★  ...

=     < contracting (inverse of expanding) >

   (★ | R : P ★ Q)

(8.16) Axiom, Range Split: Provided R∧S ≡ false and each quantification is defined,
(★x | R∨S : P) = (★x | R : P) ★ (★ | S : P)

Justification: Suppose that the satisfying set of R is {a1, a2, ...} and that of S is {b1, b2, ...}. By the proviso R∧S ≡ false, we have that these sets are disjoint (i.e., have no members in common). Then

   (★x | R : P) ★ (★ | S : P)

=     < expanding >

   (P[x:=a1] ★ P[x:=a2] ★ ...) ★ (P[x:=b1] ★ P[x:=b2] ★ ...) 

=     < the satisfying set of R∨S is {a1,a2,...,b1,b2,...} 
        (and there are no duplicates in that list)            >

   (★x | R∨S : P) 

(8.17) Axiom, Range Split: Provided each quantification is defined,
(★x | R∨S : P) ★ (★x | R∧S : P) = (★x | R : P) ★ (★x | S : P)

Justification: Suppose that A = {a1,a2,...}, B = {b1,b2,...}, and C = {c1,c2,...} (each disjoint from the others) are such that the satisfying set of R is A∪C and the satisfying set of S is B∪C. Then

  (★x | R : P) ★ (★x | S : P)

=    < satisfying sets of R and S are, respectively,
       {a1,a2,...,c1,c2,...} and {b1,b2,...,c1,c2,...}  >

  (P[x:=a1] ★ P[x:=a2] ★ ... ★ P[x:=c1] ★ P[x:=c2] ★ ...) ★ (P[x:=b1] ★ P[x:=b2] ★ ... P[x:=c1] ★ P[x:=c2] ★ ...)

=    < associativity of ★ >

  (P[x:=a1] ★ P[x:=a2] ★ ... ★ P[x:=c1] ★ P[x:=c2] ★ ...  ★ P[x:=b1] ★ P[x:=b2] ★ ...) ★ (P[x:=c1] ★ P[x:=c2] ★ ...)

=    < satisfying set of R∨S is {a1,a2,...c1,c2,...,b1,b2,...} and
       satisfying set of R∧S is {c1,c2,...}   >

   (★x | R∨S : P) ★ (★x | R∧S : Q) 

To be continued ...