Formal Logic - UBC Computer Science

Formal Logic
CPSC 509: Programming Language Principles
Ronald Garcia∗
13 September 2016
(Time Stamp: 11:03, Friday 14th October, 2016)
1
What is Logic?
Logic is the process of systematically deducing new knowledge from assumed knowledge. That’s a mouthful, so let’s consider this in a slightly more...well hunger-inducing way:1
A prominent logician was trying to explain logic to his young son, and he said, ”Well, you know
when we’re out for dinner, and the waiter says, ’So, who had the chicken?’, and Mommy says
yes, and the waiter says, ’And who had the beef?’, and Daddy says yes, ... and then the waiter
says, ’And you must have ordered the fish!’, without asking? That’s logic.”
In this example the key event is that last one, when the waiter somehow gets from the assumed knowledge
that the father and mother ordered the other dishes to the fact that the son ordered the fish. To do so, the
waiter internally appealed to some other bits of assumed knowledge (e.g., that parents do not hoard all of
the food) and in several steps of lightning-quick reasoning arrived at the answer to the question that need
not be asked (“who had the fish?”).
The steps of reasoning that the waiter took internally are called deductions and in the end the result is that
assumptions about the beef and chicken eaters, combined with codes of civility together entail knowledge
about the fish eater. In short, we use steps of deduction to establish entailment relationships between facts.
2
The Proof-theoretic Approach to Formal Logic
This set of notes develops a particular system of formal logic, which allows us to precisely apply formal
deduction steps to establish entailment relations in our system. In this context, formal refers to the fact that
we are using precise symbols (or forms) to build an extremely systematic reasoning system that amounts to
pure calculation. Before there were computers that could mechanize our symbolic reasoning, people did
develop calculational methods but had to run them by hand (think long-division, for example). Here we
do the same for logical reasoning: in practice we can implement this system on a computer, but since our
goal is to internalize logical reasoning, we work on paper instead.
If you’ve studied logic in a previous computer science course, you probably learned specifically about
connectives like “and”, “or”, “not”, and “implies”, and how to use truth tables to determine whether a
logical statement (often called a formula or proposition) is true or not. This approach to logic, called the
model-theoretic approach is particularly well suited to reasoning about the behaviour of digital electronic
circuits, which are built up from via and-gates, not-gates, and others. When extended to account for “objects
in the universe” like numbers, tables, and trees, it also leads to powerful reasoning tools for quite abstract
endeavors.
∗
c
Ronald Garcia. Not to be copied, used, or revised without explicit written permission from the copyright owner.
by William Lovas from a scenario due to Johan van Benthem.
1 Adapted
1
Time Stamp: 11:03, Friday 14th October, 2016
Logic
However, truth tables in particular, and model theory in general, are not well suited to understanding
how we typically write and read typical mathematical proofs, which say things like “assume n is a number:”
or “thus n is prime.” Nor is it so helpful for debugging your prose-based proofs. And it does not have as
good of an affinity with programming languages, which are much higher-level than digital circuits.
This set of notes introduces a different approach to logic, one that is more well suited to thinking about
the structure of mathematical proofs and also more closely connected to modern principles in programming
languages. The key difference is that instead of focusing on truth, we focus on formal proofs, which you can
view as data structures built up step-by-step from primitive reasoning principles. What’s amazing is how
these formal proofs codify in precise terms many of the kinds of informal reasoning that mathematicians
use. This is by design.
2.1
Formal (Logic) Proofs versus Informal (Math) Proofs
The plan of attack is to present a proof theory2 for precisely and systematically reasoning about logical
propositions. By starting with such a precise style, we can develop a strong sense of “what counts as a
proof.” These proofs are based on a very very (i.e. painfully) strict set of rules. The nice thing about these
rules is that they force the structure of your proof to very closely follow the structure of the proposition
you intend to prove. This is good guidance at first in that it leaves little room for creativity (almost all you
can do is change the order in which you construct the proof). In that way we hope to clarify what counts
as a legal proof move, so that you need not worry about whether the steps of reasoning you are taking are
“rigorous” enough. In essence, we’re showing how you could build a “type checker”, just like for C or
Java, which tells you whether your proof is legal. In fact we can go further and check whether your proof is
right, that is, a proof of the thing you intended to prove. This material is in fact the underpinnings for many
computerized proof-checkers and automated theorem-provers. Since this course isn’t focused primarily
on logic, we won’t push things quite that far, but you may get some hints at how you could build such
software, even as we focus primarily on paper-based proofs of programming language properties.
Bear in mind that our ultimate goal here is to work toward understanding how these formal models
of proofs correspond to the kinds of proofs that you see in math textbooks. Proofs in mathematics tend
to be more free-form, and take huge steps at a time, tying everything together in prose. This is quite a
contrast to what you will see in this section. The way to think about the relationship between these two
traditions of proof is to think of textbook mathematical proofs as “pseudocode”, and formal logic proofs
as “actual code.” In principle you can take a mathematical proof and fill in all the details until you get a
machine-checkable formal proof, just as you can take pseudocode from an algorithms textbook and tern it
into a running C implementation. So paper proofs are “algorithms”, and formal proofs are “programs.”
For a less formal approach to the same ideas, with a twist, I recommend the book “How to Prove It”.
3
Growing A Proof System
Our main goal in these notes is to give you a good intuition for how proofs work, as well as some guardrails to push you in the direction of the proof you want. With that in mind, we start with a system that is
strict but sufficient.
The rules that we start with are way too strict though...if we used them exclusively, our proofs would be
painfully big to write. A computer, on the other hand would really appreciate this small system because
it makes it easy to both prove theorems and refute them, i.e., demonstrate that a proposition doesn’t hold
because there cannot possibly be a proof for it. Think of our first system as low-level proof assembly
language. It needs to be good enough to write all proofs, but not necessarily as friendly as we want for
day-to-day proving.
Then, we want to build at least a slightly higher-level language that lets us write proofs more succinctly,
knowing that we could “compile” them to “assembly language”. In short we want at least a “FORTRANlike” proof language.3
2 There
3 you
are many different ones
could call it PROOFTRAN!
Page 2
Time Stamp: 11:03, Friday 14th October, 2016
Logic
3.1
Verifications (and Uses)
Let’s lay out our logical system. We’ll use formal notation, but explain it partly informally for now since
your intuitions (and prior C.S. knowledge) will likely send you in the right direction.4
We will begin with propositional logic, which allows us to reason about opaque atomic propositions. That
is to say, the system can’t directly reason about objects like chocolate or cookies, but we can use atomic
symbols to stand in for propositional statements like “cookies are the best.” Here are some examples of
atomic propositions:
C ≡ Chocolate is delicious
A ≡ Apples are delicious
G ≡ Apples are good for you
S ≡ Chocolate is good for you
What makes them propositions is that they are statements that either “hold” or “do not hold”. It doesn’t
matter which is the case at this point, but we want to reason about what would hold if other things did
hold.
We use atomic propositions to build up more complicated propositions. These are built using a variety
of connectives which allow us to build up propositions from smaller ones. Here is an example proposition
built up from our atomic ones:
(C ∧ A ∧ G) ⊃ S
This proposition represents the (obviously correct ,) statement “If chocolate is delicious and apples are
delicious and apples are good for you, then chocolate is good for you.”
In logic, we try to reason by using assumed propositions to verify other propositions. We call these
steps of reasoning entailment. So our goal is to build a formal system in which we can formally describe
entailment relations.
3.1.1
Syntax
We start with the syntax of constructive propositional logic. Here’s the BNF first:
A ∈ ATOMIC P ROP, p ∈ P ROP,
p ::= A | > | ⊥ | p ∧ p | p ∨ p | p ⊃ p
We use A to stand for any atomic proposition (like C, G, and so on). The symbol > represents propositional truth and ⊥ represents falsity. The symbol ∧ represents conjunction (“and”), and ∨ represents disjunction (“or”). Finally ⊃ represents implication (“if...then”). We’ll see that our system of proof theory
gives precise and explicit meaning to propositions
3.1.2
Deduction Rules
Now that we have defined the set of propositional formulas, we can establish what counts as proofs of
propositions. In actuality, what we will define is a relation called entailment, which establishes the following:
given the knowledge of certain truths, what other truths can we deduce (i.e., what truths are entailed by
other truths)?
To define entailment, we define the structure of proofs by laying out a set of deduction rules. Our deduction rules have the form:
J1 · · · Jn
J
where J represents a judgment: i.e., a statement about a proposition p. The judgments on top of the horizontal bar are called premises, and the single judgment on the bottom is called the conclusion. Roughly speaking
the rule says that if the premises can be established, then the conclusion follows immediately.
4 Some
of the below text is stolen straight from the notes on inductive definitions.
Page 3
Time Stamp: 11:03, Friday 14th October, 2016
Logic
In logic, there are many judgments about propositions, like p true which says that p is true (more on
this later), p@t, which says that p is true exactly at time t (which arises in temporal logic, a logic of truth
over time), and p poss which says that p is true in some possible world (which arises in modal logic, a logic of
necessity and possibility).
In our system, we develop a simple propositional logic based on rules that tell us how to use the assumption that some propositions hold (regardless of whether or not they actually do) as a means to verify
that some other proposition holds. This is the essence of hypothetical reasoning.
In line with the above informal reasoning, we define our logic, we introduce two judgments: p ↓ pronounced “use p”, and p ↑ pronounced “verify p”.
J ∈ J UDGMENT
J ::= p ↑ | p ↓
We use arrows of this form because our proofs will typically take the form:
p1 ↓ · · · pn ↓
..
..
p↑
which represents a proof tree with uses at the top and a verification at the bottom. We write the entailment
relation p1 ↓ · · · pn ↓ ` p ↑ to say that we have such a proof tree, that is, we can use p1 , . . . , pn to verify p, or
p1 , . . . , pn entails p.
Each rule is defined in terms of the top-most logical connective that appears in a proposition.
Ultimately we will build proofs by building proof trees, which you can think of as structures built up
from “lego-blocks”, so very systematic. These lego-block structures have strict rules about how to combine
them and how you know you are done. You can think of this as a data structure that has strict and easy to
check, rules for building up data.
We’ll introduce each of the rules one-by one, then summarize all the rules at the end.
Atomic Propositions As we will see, each propositional connective introduces rules about how to use
propositions that have that connective and rules about how to verify a proposition with a connective. Since
atomic propositions are totally opaque, there’s not much that you can do...they represent abstract facts.
Our basic principle is this “You can only verify an atomic proposition if you already have license to use it”,
alternatively “Using an atomic proposition amounts to verifying it.”
A↓
(↓↑)
A↑
Conjunction A conjunction p1 ∧ p2 expresses the idea that both p1 and p2 hold. Without knowing anything
about the structure of p1 or p2 , we can specify what it takes to verify p1 ∧ p2 :
p1 ↑ p2 ↑
(∧↑)
p1 ∧ p2 ↑
Similarly, without knowing the structure of either underlying proposition, we know how to use an
assumption that the conjunction is true. First, if we can use the conjunction, then we can safely use either
individual conjunct.
p1 ∧ p2 ↓
(∧↓1)
p1 ↓
p1 ∧ p2 ↓
(∧↓2)
p2 ↓
At first it may seem odd that we can’t squeeze out both propositions at the same time with one rule,
but somehow we have to represent two separate propositions. In this system, we are allowed to use our
assumptions zero or more times, so we can use conjunction twice to get both pieces. We’ll see an example
of this later.
Page 4
Time Stamp: 11:03, Friday 14th October, 2016
Logic
Disjunction A disjunction p1 ∨ p2 expresses the idea that one of p1 and p2 must hold. Following this
intuition, we get two rules for verifying disjunction.
p1 ↑
(∨↑1)
p1 ∨ p2 ↑
p2 ↑
(∨↑2)
p1 ∨ p2 ↑
In short, in order to verify a disjunction, it suffices to verify either one of the disjuncts.
Now to use a disjunction, we must be able to deduce some conclusion regardless of which disjunct holds.
p1 ↓
..
..
p1 ∨ p2 ↓ p3 ↑
p3 ↑
x
p2 ↓
..
..
p3 ↑
y
(∨↓x,y )
This rule is different from the previous ones that we have seen because two of the premises are hypothetical judgments of the form:
p1 ↓
..
..
p2 ↑
Each of these stands for a subtree that may have p1 ↓ free at the top, and must conclude in p2 . Previous
rules simply noted that p2 is directly above, so only focuses on the conclusion: a hypothetical judgment
talks about judgments that may be used throughout the subproof. Given such a subproof, the rule for
disjunction essentially introduces the hypothesis. This corresponds to temporarily supposing the premise
and using it to deduce a conclusion. If successful, then we close the hypotheses, and mark them with an
identifier, e.g., x, y, etc. which matches an identifier listed in the rule. Identifiers helps us keep track of
which rule locally introduced (and dispatched) a hypothesis that was used internally in the proof.
To use p1 ∨ p2 , we must produce two hypothetical judgments: the first supposes that we can use p1 and
from it deduces p3 ; the second independently does the same for p2 . Thus, even though we do not know
which of p1 and p2 will be available for us to use, we are prepared to deduce p3 from either.
This ought to become clearer later when we write some proofs.
Truthhood The > proposition is one of two propositional constants. It represents contentless truthhood. As
such it has a rule that says that you can always verify truthness, with no assumptions needed.
>↑
(>↑)
There is no rule to use truthhood. Why not? Well, essentially because there is no “information content”
to squeeze out of truthhood. In principle, we could introduce a rule for truthhood that matches the rule for
atomic propositions: you can use > to verify >. However, that rule is totally redundant because you can
always verify > already, with no assumptions. So you might as well never bother using truth. In contrast,
for atomic propositions, you need license to use it in order to verify it.
Falsehood The ⊥ proposition is one of two propositional constants, i.e. 0-ary propositional connectives.
This connective represents absurdity, or falsehood. In essence this is something that can never happen.
While it may sound odd to codify falsehood, it is actually quite useful to be able to talk about things that
are absurd, i.e. “that could never be true” and other negative statements. We’ll find that ⊥ is exactly what
we need to do that.
By design, there is no direct rule for verifying ⊥. This is because we intend that it be impossible to verify
⊥ unless we have previously assumed it. This is in line with the idea that logic is reasoning under hypotheses: we can assume anything, regardless of whether it holds or not, and armed with such assumptions, we
still deduce their implications. This is akin to “if pigs could fly:” we can make a lot of deductions from such
a hypothetical, but we may never be able to take advantage of them.
Page 5
Time Stamp: 11:03, Friday 14th October, 2016
Logic
Though we cannot directly verify ⊥, we can use it. The basic idea is that “if you have license to use ⊥
then you’ve gone off the rails, everything has broken loose, etc., so you can verify anything.”
⊥↓
(⊥↓)
p↑
This rule is hard to grasp on its own, but it fits within the larger reasoning framework. We need it to reason
about negation, i.e. claims that certain propositions are impossible. This is called the principle of explosion, or
ex falso quodlibet, which is latin for “from absurdity, anything follows.” The basic idea is that since we know
that ⊥ can never be verified, than any hypothetical deduction that leads to it can never be used, so you might
as well deduce any fact.
Another way to think about it is this: think of ⊥ as the 0-ary version of disjunction ∨. If p1 ∨ p2 is verified
, then we would know that one or the other of the two is verified. As such, p1 ∨ p2 can be used to deduce p
if we can deduce it from both p1 and p2 . In contrast, if ⊥ is verified, then nothing is verified. Then ⊥ can be
used to verify p right away, without verifying any side deductions. Indeed, ⊥ acts like an identity operator
for ∨: (p ∨ ⊥) ⊃ p and p ⊃ (p ∨ ⊥). When an implication holds in both directions, we call it a “bi-implication”,
and it means that the two propositions are logically equivalent. We’ll prove these theorems shortly, and you
will then see that the first implication depends critically on (⊥↓).
Similarly, truth > acts as identity for conjunction: p ⊃ (p ∧ >) and vice-versa, and the first proposition
depends critically on (>↑).
Implication To verify an implication, we must establish the conclusion assuming that we can use the
assumption. This directly embodies hypothetical reasoning.
x
p1 ↓
..
..
p2 ↑
(⊃↑x )
p1 ⊃ p2 ↑
This rule, like (∨↓) is premised with a hypothetical judgment. In essence, this rule says that an implication internalizes the hypothetical proof p1 ` p2 as a proposition that may be mixed with others. This is
quite analogous to how some programming languages have first-class functions, which may be treated as
data.
To use an implication, we must first verify the premise. If we have done so, then we have license to use
the conclusion.
p1 ⊃ p2 ↓ p1 ↑
(⊃↓)
p2 ↓
The rough idea is that is if we knew the implication p1 ⊃p2 , it would mean that we knew some methodology
for transforming a verification of the premise p1 into a verification of the conclusion p2 . Thus we can safely
use the knowledge of p2 so long as we can verify p1 . Indeed, you can think of an implication as a form of
function on proofs. We’ll hear more about this later in the course.
Page 6
Time Stamp: 11:03, Friday 14th October, 2016
Logic
We now summarize all of the rules of the logic.
A↓
(↓↑)
A↑
>↑
p1 ↑ p2 ↑
(∧↑)
p1 ∧ p2 ↑
p1 ↑
(∨↑1)
p1 ∨ p2 ↑
⊥↓
(⊥↓)
p↑
(>↑)
p1 ∧ p2 ↓
(∧↓1)
p1 ↓
p2 ↑
(∨↑2)
p1 ∨ p2 ↑
x
p1 ↓
..
..
p2 ↑
(⊃↑x )
p1 ⊃ p2 ↑
p1 ∧ p2 ↓
(∧↓2)
p2 ↓
p1 ↓
..
..
p1 ∨ p2 ↓ p3 ↑
p3 ↑
x
p2 ↓
..
..
p3 ↑
y
(∨↓x,y )
p1 ⊃ p2 ↓ p1 ↑
(⊃↓)
p2 ↓
Negation: a derived notion If you learned logic before, then you may have been shown the negation
logical operator ¬ p, which means “not p.” In our system of logic, we do not introduce a primitive ¬
operator, but rather we define it in terms of notions that we already have:
¬p ≡ p ⊃ ⊥
In short, “not b” is defined to mean “if b held, then absurdity would follow.” In our setting, this is the
essence of statements of falsehood: p ⊃ ⊥ represents a claim that there is a means by which a verification
of p could be transformed into a verification of ⊥, but we know that there is no way to verify ⊥, therefore
there is no way to verify p. We will find that this interpretation of negation can usefully guide our reasoning
about propositions that we claim cannot be proven, especially with regards to what other propositions in
turn cannot be proven either.
3.2
Precedence Conventions
We typically do not want to place parentheses around every single subformula of a proposition. To avoid
doing so, we adopt a common set of precedence conventions that appear throughout the literature:
1. Not has the highest precedence: for example, ¬ A ∨ B means (¬ A) ∨ B.
2. implication has the lowest precedence: for example, A ∨ C ⊃ D means (A ∨ C) ⊃ D.
3. implication associates to the right: for example, A ⊃ B ⊃ C ⊃ D means A ⊃ (B ⊃ (C ⊃ D)).
3.3
Examples
Example 1. A ⊃ (B ⊃ (A ∧ B))
Here is what the formula looks like with minimal parentheses: A ⊃ B ⊃ A ∧ B
And here is the proof:
y
x
A↓
B↓
(↓ ↑)
(↓ ↑)
A↑
B↑
(∧ ↑)
A ∧ B↑
(⊃ ↑)y
B ⊃ (A ∧ B) ↑
(⊃ ↑)x
A ⊃ (B ⊃ (A ∧ B) ↑
Page 7
Time Stamp: 11:03, Friday 14th October, 2016
Logic
Example 2. (A ∧ B) ⊃ (B ∧ A)
Here is what the formula looks like with minimal parentheses: A ∧ B ⊃ B ∧ A
And here is the proof:
x
x
A ∧ B↓
A ∧ B↓
(∧ ↓ 1)
(∧ ↓ 2)
A↓
B↓
(↓ ↑)
(↓ ↑)
A↑
B↑
(B ∧ A) ↑
(⊃ ↑x )
(A ∧ B) ⊃ (B ∧ A) ↑
Example 3. (A ⊃ B ∧ C) ⊃ (A ⊃ B) ∧ (A ⊃ C)
Here is the proof:
y
x
x
z
A ⊃ B ∧ C↓
A↓
A ⊃ B ∧ C↓
A↓
(⊃↓)
(⊃↓)
B ∧ C↓
B ∧ C↓
(∧↓1)
(∧↓2)
B↓
C↓
(↓↑)
(↓↑)
B↑
C↑
(⊃↑y )
(⊃↑z )
A ⊃ B↑
A ⊃ C↑
(∧↑)
(A ⊃ B) ∧ (A ⊃ C) ↑
(⊃↑x )
(A ⊃ B ∧ C) ⊃ (A ⊃ B) ∧ (A ⊃ C) ↑
Example 4. (A ⊃ B) ∧ (B ⊃ C) ⊃ (A ⊃ C)
Here is the proof:
x
(A ⊃ B) ∧ (B ⊃ C) ↓
x
y
(∧↓2)
(A ⊃ B) ∧ (B ⊃ C) ↓
A ⊃ B↓
A↓
(∧↓1)
(⊃↓)
B ⊃ C↓
B↓
(⊃↓)
C↓
(↓↑)
C↑
(⊃↑y )
A ⊃ C↑
(⊃↑x )
(A ⊃ B) ∧ (B ⊃ C) ⊃ (A ⊃ C) ↑
Example 5. A ∧ (A ⊃ ⊥) ⊃ C This theorem makes necessary use of ⊥ to deduce C.
Here is the proof, presented in steps.
Step 0:
..
..
A ∧ (A ⊃ ⊥) ⊃ C ↑
Page 8
Time Stamp: 11:03, Friday 14th October, 2016
Logic
Step 1:
Step 2:
Step 2:
x
A ∧ (A ⊃ ⊥) ↓
..
..
C↑
(⊃↑x )
A ∧ (A ⊃ ⊥) ⊃ C ↑
x
A ∧ (A ⊃ ⊥) ↓
x
(∧↓1)
A↓
A ∧ (A ⊃ ⊥) ↓
..
..
C↑
(⊃↑x )
A ∧ (A ⊃ ⊥) ⊃ C ↑
x
x
A ∧ (A ⊃ ⊥) ↓
A ∧ (A ⊃ ⊥) ↓
x
(∧↓1)
(∧↓2)
A↓
A ⊃ ⊥↓
A ∧ (A ⊃ ⊥) ↓
..
..
C↑
(⊃↑x )
A ∧ (A ⊃ ⊥) ⊃ C ↑
Step 3:
x
A ∧ (A ⊃ ⊥) ↓
(∧↓1)
A↓
x
..
A ∧ (A ⊃ ⊥) ↓
..
(∧↓2)
A ⊃ ⊥↓
A↑
x
(⊃↓)
⊥↓
A ∧ (A ⊃ ⊥) ↓
..
..
C↑
(⊃↑x )
A ∧ (A ⊃ ⊥) ⊃ C ↑
Step 4:
x
A ∧ (A ⊃ ⊥) ↓
(∧↓2)
A ⊃ ⊥↓
⊥↓
Step 5:
x
A ∧ (A ⊃ ⊥) ↓
(∧↓1)
A↓
(↓↑)
A↑
x
(⊃↓)
A ∧ (A ⊃ ⊥) ↓
..
..
C↑
(⊃↑x )
A ∧ (A ⊃ ⊥) ⊃ C ↑
x
A ∧ (A ⊃ ⊥) ↓
x
(∧↓1)
A ∧ (A ⊃ ⊥) ↓
A↓
(∧↓2)
(↓↑)
A ⊃ ⊥↓
A↑
(⊃↓)
⊥↓
(⊥↓)
C↑
(⊃↑x )
A ∧ (A ⊃ ⊥) ⊃ C ↑
Notice that if you replace ⊥ in the above theorem with C, the result is still provable, but using (↓↑)
instead of (⊥↓). But replacing ⊥ with B would not be provable. Many formulae that involve ⊥ could also
be proven with an arbitrary atomic proposition in its place. Only for some proofs is the full power of ⊥
necessary. This is an example of such a formula, since ⊥ cannot be replaced with any arbitrary constant.
Page 9
Time Stamp: 11:03, Friday 14th October, 2016
Logic
3.4
Refutations
One of the nice things about the proof system that we’ve presented is that we can exploit it to show not
only that some propositions are theorems, but also to show that some propositions are most definitely NOT
theorems. This is called refuting a theorem. We give an example here, which also exposes an interesting
aspect of the logic that we have defined.
Consider the formula A ∨ ¬ A, which we would read informally as “A is true or false.” In the approach to
logic that you may have learned in prior classes, the classical approach, this formula is true. In this course,
the formula doesn’t hold. What the...??? Well, before we get into detail about this, let’s show that this is so.
Suppose you try to verify this formula. First we translate ¬ A into its primitive form, and prepare to
verify it:
..
..
A ∨ (A ⊃ ⊥) ↑
At this point, there are only two rules that could possibly apply. Let’s try (∨↑1):
..
..
A↑
(∨↑1)
A ∨ (A ⊃ ⊥) ↑
Now we know we are stuck! In principle, we could use (↓↑) to get A ↓ on top, but in practice, when proving
a theorem we only want to use that rule to finish a proof: it’s better to work toward the middle then fill in
the gap. In this case we have no uses to work down from, so we can throw in the towel now.
Ok, so if that doesn’t work, let’s try (∨↑2):
..
..
A ⊃ ⊥↑
(∨↑2)
A ∨ (A ⊃ ⊥) ↑
We can then apply (⊃↑x ):
x
A↓
..
..
⊥↑
(⊃↑x )
A ⊃ ⊥↑
(∨↑2)
A ∨ (A ⊃ ⊥) ↑
And we’re stuck again! The problem is that we want to meet in the middle, either using (↓↑) or (⊥↓) to
bridge a gap. We can do neither of those things here, and we are out of options. Thus we know that the
theorem cannot be proven.
Thus A ∨ ¬ A is not a theorem of our logic. This may seem a bit unusual, but the intuition is that in this
logic, any proof of A ∨ B must include enough information to establish which of A or B is in fact true (or at
least which one was used to justify the theorem, in case both are in fact true). This gets at the very heart of
constructive logic. We cannot simply claim that everything is true or false...we must figure out which one it
is exactly.
The proposition A ∨ ¬ A is called the law of the excluded middle (LEM), because it explicitly rules out the
possibility that something is neither true nor false but something in the middle. This proposition cannot
be proven in our logic because it demands that you demonstrate which one in particular is true: without
more information than A, that’s not possible. By restricting ourselves in this way, all of our proofs have
constructive content. Given a disjunction, a proof must commit to one of the disjuncts.
Page 10
Time Stamp: 11:03, Friday 14th October, 2016
Logic
Even though the LEM is not provable, it is not false: ¬ ¬(A ∨ ¬ A) is a theorem. Here is the proof:
y
A↓
(↓↑)
A↑
x
(∨↑1)
¬(A ∨ ¬ A) ↓
A ∨ ¬A↑
(⊃↓)
⊥↑
(⊥↓)
⊥↑
(⊃↑y )
¬A↑
x
(∨↑2)
¬(A ∨ ¬ A) ↓
A ∨ ¬A↑
(⊃↓)
⊥↓
(⊥↓)
⊥↑
(⊃↑x )
¬ ¬(A ∨ ¬ A) ↑
Let’s unpack this proposition: it says that if you had a proof of (A ∨ ¬ A) ⊃ ⊥, then you would be in
trouble, because ((A ∨ ¬ A) ⊃ ⊥) ⊃ ⊥. Considering these two formula, the LEM and its double-negation,
tells us essentially that we do not have a general method for proving which of a proof or its negation holds
(i.e., LEM is not a theorem), but we could never prove that neither a formula nor its negation is possible
(i.e., double-negation of LEM is a theorem).
It’s worth noting, though, that replacing all of the (implicit) instances of ⊥ with C, getting
((A ∨ (A ⊃ C)) ⊃ C) ⊃ C, still yields a provable a theorem (what changes must you make to the proof?).
In essence, ⊥ in particular is not needed to make sense of this theorem: any atomic proposition will do
instead!
On a related note, another proof that you cannot prove is “double-negation elimination” (DNE): we can
prove that any verifiable proposition is not false (A ⊃ ¬ ¬ A holds), but knowledge that a proposition is not
false does not tell us how to verify that proposition holds (¬ ¬ A ⊃ A does not hold). Both LEM and DNE
can be proven in classical logic, which is focused more on establishing Platonic abstract truth rather than
general constructive methodology. In essence, A ∨ ¬ A does not constructively hold because there does not
exist a constructive method that for all possible A computes which one of the two is true.
More To Come!
A
Classical Logic
If you’ve learned about logic before, then in all likelihood, you were taught classical logic. This section
extends our logical system to classical logic, just so that you have some understanding of the difference.
In essence, classical logic supports more reasoning from falsehood than constructive logic. As such we
introduce two new judgments: p false, which is used to assume that a proposition p is indeed false, and #,
which expresses that a contradiction has been deduced.
In addition to our new judgments, we add two new rules and modify two of our previous rules. The
first new rule determines how to deduce a contradiction.
p false p ↑
(contra)
#
The (contra) rule says that one can deduce a contradiction by verifying any proposition that has previously
been assumed false.
The second rule introduces our primary mechanism for classically verifying more propositions.
k
p false
..
..
#
(pbc)k
p↑
Page 11
Time Stamp: 11:03, Friday 14th October, 2016
Logic
This rule captures proof by contradiction: it is sufficient to verify a proposition by merely assuming it is false
and deriving a contradiction.
Finally we modify two of our previous rules: specifically the two rules for using disjunctions and false.
In particular, each can now be used to deduce contradictions, i.e.:
p1 ↓
..
..
p1 ∨ p2 ↓ #
#
x
p2 ↓
..
..
#
y
(∨↓x,y )
⊥↓
(⊥↓)
#
Adding these mechanisms to constructive logic is sufficient to get you classical logic. To demonstrate,
here is a proof of the law of excluded middle. You can see here that the proof makes essential use of proof
by contradiction.
x
A↓
(↓↑)
A↑
(∨↑1)
k
A ∨ ¬ A false
A ∨ ¬A↑
(contra)
#
h
(pbc)
⊥↑
(⊃↑x )
¬A↑
(∨↑2)
k
A ∨ ¬ A false
A ∨ ¬A↑
(contra)
#
k
(pbc)
A ∨ ¬A↑
This proof is quite peculiar compared to some of our earlier proofs. First, notice the use of proof-byh
contradiction that introduces an assumption ⊥ false which is never used. This allows us to introduce
whatever proposition we desire (here ⊥). As such, we can see that A ∨ (A ⊃ C) is also verifiable classically.
Notice as well that ultimately we verify this disjunction without producing a definitive verification of
either disjunction. indeed there are two instances of disjunction verification, but each is fundamentally
dependent on our assumption that A ∨ ¬ A is false. This reasoning is very similar to our “double-negation”
reasoning, except that proof-by-contradiction transforms double-negations into affirmations.
What makes Constructive Logic “Constructive” One of the key differences between constructive logic
and classical logic is exactly the global nature of disjunctions, especially verifications of disjunctions. In
fact, in constructive logic, it is a metatheorem (i.e. theorem about the system, as opposed to a theorem
proven in the system) that:
..
..
..
..
..
..
Theorem 1. If A ∨ B ↑ then either A ↑ or B ↑.
What that means is that if you give me a proof that verifies a disjunction, then I can systematically
deconstruct it and find inside a standalone proof of one of the two disjuncts. As we saw in the above example, this metatheorem doesn’t hold in classical logic: you can verify a disjunction without ever definitively
verifying one of the disjuncts along the way. This may matter even more when we get to first-order logic:
constructive proof of the existence of a mathematical object with certain properties must provide that very
object. Classical existence proofs need not do so: they may simply prove that it’s not possible that such an
object doesn’t exist.
The key point in favour of classical logic is that in practice we often you don’t care about which disjunct
holds (or which mathematical object has a property): in essence we often just want to know that something
is ”not false”, without worrying about constructive evidence that it is verified. That’s where classical logic
shines.
Page 12