While propositional logic is a good starting point, most interesting
statements in mathematics contain variables over domains larger than
simply
A statement whose truth value depends on one or more variables from
any set is a predicate. Formally, a predicate is a
function whose codomain is
As with all functions, predicates can depend on more than one
variable. For example, if we define the predicate
We usually define a predicate by giving the statement that involves
the variables, e.g., “
Unlike propositional formulas, a predicate by itself does not have a
truth value: as we discussed earlier, “
However, we often don’t care about whether a specific value satisfies
a predicate, but rather some aggregation of the predicate’s truth values
over all elements of its domain. For example, the statement
“every real number
There are two types of “truth value aggregation” we want to express; each type is represented by a quantifier that modifies a predicate by specifying how a certain variable should be interpreted.
The existential quantifier is written as
For example, the statement
Note that there are many more natural numbers that are greater than
or equal to
One should think of
The universal quantifier is written as
For example, the statement
One should think of
Let us look at a simple example of these quantifiers. Suppose we
define
For example, the diagram below defines the relation “Loves” for two
collections of people:
Consider the following statements.
any
and all
In Python, the built-in function any
allows us to
represent logical statements using the existential quantifier. The
function any
takes a collection of boolean values and
returns True
when there exists a True
value in
the collection:
>>> any([False, False, True])
True
>>> any([]) # An empty collection has no True values!
False
This might not seem useful by itself, but remember that we can use
comprehensions to transform one collection of data into another. For
example, suppose we are given a set of strings 'D'
. In predicate logic, we
could write this as the statement
>>> strings = ['Hello', 'Goodbye', 'David']
>>> any([s[0] == 'D' for s in strings])
True
This example serves to highlight several elegant parallels between our mathematical statement and equivalent Python expression:
any
functionfor s in strings
The naming conventions are a bit different, however:
in mathematics, we tend to represent collections using capital letters,
whereas in Python all variables are lower-case words.s[0] == 'D'
Python includes another built-in function all
that can
be used as a universal quantifier. The all
function is
given a collection of values and evaluates to True
when
every element has the value True
. For example, if we wanted
to express
>>> strings = ['Hello', 'Goodbye', 'David']
>>> all([s[0] == 'D' for s in strings])
False
Of course, Python is more limited than mathematics because there are
limits on the size of the collections, and so we cannot easily express
existential statement quantified over infinite domains like
Now that we have introduced the existential and universal
quantifiers, we have a complete set of tools needed to represent all
statements we’ll see in this course. A general formula in predicate
logic is built up using the existential and universal quantifiers, the
propositional operators
However, don’t confuse a formula being a sentence with a formula being True! As we’ll see repeatedly throughout the course, it is quite possible to express both True and False sentences, and part of our job will be to determine whether a given sentence is True or False, and to prove it.
Here is a common question from students who are first learning symbolic logic: “does the comma mean ‘and’ or ‘then’?” As we discussed at the start of the course, we study to predicate logic to provide us with an unambiguous way of representing ideas. The English language is filled with ambiguities that can make it hard to express even relatively simple ideas, much less the complex definitions and concepts used in many fields of computer science. We have seen one example of this ambiguity in the English word “or,” which can be inclusive or exclusive, and often requires additional words of clarification to make precise. In everyday communication, these ambiguous aspects of the English language contribute to its richness of expression. But in a technical context, ambiguity is undesirable: it is much more useful to limit the possible meanings to make them unambiguous and precise.
There is another, more insidious example of ambiguity with which you are probably more familiar: the comma, a tiny, easily-glazed-over symbol that people often infuse with different meanings. Consider the following statements:
Our intuitions tell us very different things about what the commas
mean in each case. In the first, the comma means then,
separating the hypothesis and conclusion of an implication. But in the
second, the comma is used to mean and, the implicit joining of
two separate
sentences.Grammar-savvy folks will recognize this as a comma
splice, which is often frowned upon but informs our reading
nonetheless. The fact that we are all fluent in English means
that our prior intuition hides the ambiguity in this symbol, but it is
quite obvious when we put this into the more unfamiliar context of
predicate logic, as in the formula:
This, of course, is where the confusion lies, and is the origin of
the question posed at the beginning of this section. Because of this
ambiguity, never use the comma to connect propositions.
We already have a rich enough set of symbols, including
That said, keep in mind that commas do have two valid uses in predicate formulas:
You can see both of these usages illustrated below, but please do
remember that these are the only valid places for the comma
within symbolic notation!
We have already seen some equivalences among logical formulas, such
as the equivalence of
Given any formula, we can state its negation simply by preceding it
by a
Instead, given a formula using negations, we apply some simplification rules to “push” the negation symbol to the right, closer the to individual predicates. Each simplification rule shows how to “move the negation inside” by one step, giving a pair of equivalent formulas, one with the negation applied to one of the logical operator or quantifiers, and one where the negation is applied to inner subexpressions.
It is usually easy to remember the simplification rules for
What about the quantifiers? Consider a statement of the form