This interactive tutorial will teach you how to use the
sequent calculus, a simple set of rules with which you can use
to show the truth of statements in first order logic. It
is geared towards anyone with some background in writing software
for computers, with knowledge of basic boolean logic.

Introduction

Proving theorems is not for the mathematicians anymore: with
theorem provers, it's now a job for the hacker. — Martin Rinard

I want to tell you about a neat system called the sequent
calculus. It's a way of deducing whether or not a statement is
true, but unlike proofs where the prover makes wild leaps
of deduction from one statement to another, the sequent calculus
always has a simple set of rules that is easy to check the
validity of.

An ordinary software engineer rarely has any need for proof,
even though he deals with the issues of truth and falsehood on a
daily basis. His tool is boolean logic, where there are
propositions, and they are either true or false, and even in the
most complicated cases, the truth of a statement like "A or not A"
can be checked by checking all of the possible cases using a truth
table.

However, as a tool for describing the world, Boolean logic is
inflexible. Suppose I claim "all men are mortal" and "Socrates is
a man". I should then be able to deduce "Socrates is mortal";
however, in Boolean logic, these three propositions have no
relationship with each other. Instead, I would like a way to say the word "all", a
quantifier, is special in some sense. It deserves to be
an operator like AND/OR/NOT, and have some meaning assigned to it.

However, now there's a problem: we can't figure out if a
logical statement is true anymore by writing out the truth table.
We can't check that a statement about "all" individuals is true by
checking each individual one-by-one: there may be too many. We need another way of
reasoning about these statements, which are called statements
in first-order logic.

There are a lot of ways to think about first-order logic. In
this tutorial, we'll focus on one fundamental way of dealing with
statements. It will be a little unintuitive at times, but it will
have the benefit of being precise, unambiguous and simple. It is
so precise and simple we can program it into a computer. But it
is also powerful enough to let us derive any true statement in
first-order logic. You should come out of this tutorial with
an appreciation of how to do the symbolic manipulation of
the sequent calculus.

How it works

The sequent calculus operates by a set of rules, not all of
which are intuitively obvious. Our goal is to learn the rules
of the game, while at the same time becoming familiar with the
notation and terminology which is conventionally
used by mathematicians on pen and paper.

All of the examples in this document are interactive.
Technical terms are underlined; you can mouse over them for a
definition. You can reset your changes to an example by clicking
the turnstile symbol (⊢).

Sequents and axioms. The turnstile is always included
in a sequent, an example of which is displayed below. You can
interact with it by clicking on the A, which are clauses. You
can read the sequent as "A implies A": the turnstile can be
thought of as a sort of implication. In this example, when you
click on the A, a bar appears on top, which indicates the sequent
is axiomatically true. The only axioms in this system
are when some atomic clause appears on both sides of the
turnstile. We're done when all sequents have bars
over them.

Hypotheses on the left. Read the following sequent as "Γ and A imply A."
If you click on A, you will successfully complete the proof, but if you click
on Γ, you will fail (because it is not a conclusion you are proving.) Γ (a capital Greek gamma)
conventionally indicates hypotheses which are not relevant.

Conclusions on the right. Read the following sequent as
"A implies A or Δ". Δ (a capital Greek delta) conventionally
indicates conclusions which are not relevant. Notice that the
comma means conjunction on the left but disjunction
on the right. One reason for this is that it makes it very easy to
identify axiomatically true statements: if an atomic clause is
on the left and on the right, then you're done.)

Backwards deduction. Up until now, clicking on a clause has either
told us "this sequent is axiomatically true" (completing the
proof) or given us an error. These make for very boring proofs:
what about logical operators? When you click on a clause that contains
a logical operator, the system generates one or more further goals,
which you need to prove. It's its way of saying, "In order to show
A ∨ B ⊢ A, B is true, you need to show A ⊢ A, B is true and B ⊢ A, B is true."
Notice that in both of the subgoals, there no longer is a disjunction; in
sequent calculus, we use backwards deduction to get rid of logical
operators until we have atomic clauses.

Inference rules. Now, it is great that the computer has
told you what new goals you need to prove, but what if you
wanted to write out the proof by hand? You need to know what to
write down. Fortunately, for each logical operator, there are
exactly two inference rules which say what new goals are
generated: one for when it's on the left side of the turnstile
(hypothesis), and one when it's on the right (conclusion).
You applied the rule for left-disjunction in the previous example:
here is the rule written out in general.

The Γ and Δ are placeholders for other hypotheses and conclusions:
in the previous example Γ was empty, and Δ was "A, B" (two clauses).
The text on the right of the bar indicates what rule was
applied: the first letter indicates the logical operator involved,
and the second letter indicates left or right.
Together, axioms and inference rules make up the entirety of our
deductive system: they are all you need. We'll now go on a
tour of all the inference rules in first-order logic.

Trivial rules. Recall that all of the hypotheses on the
left side of the turnstile can be thought of as ANDed together, and
the conclusions on the right side ORed together. Thus, if I have a hypothesis
which is an AND, or a conclusion which is an OR, we can very easily get
rid of the logical operator.

Meta-implication rule. The turnstile itself can be thought
of as implication, so to prove A → B, I can assume A as a hypothesis
and prove B instead ("moving" the clause to the left side of the turnstile.)

It's worth noting that, because this is classical logic, you can use
any hypothesis generated this way for any other conclusion (a sort
of "bait and switch"). It's worth taking some time to convince yourself why this
is allowed, since it shows up in other inference rules too. Here is a simple example of this:

Branching rules. What about conjunction, disjunction and implication
on the other side of the turnstile? All of these generate two new
goals, both of which need to be proved.

Negation rules. Negation is a strange operator: applying its inference
rule moves the un-negated clause to the other side of the turnstile.

Quantifier rules. The rules for the quantifiers are
quite interesting. Which of these four statements is true?

You should only be able to prove two of the four: forall left
(∀l) and exists right (∃r). In both cases, the system asks you
for an individual to instantiate the variable with. This variable
can be anything, including variables which already exist in the
expression. Intuitively, it should make sense why these are the
two true statements: in the case of forall, if I know something
about all individuals, I know something about a particular
individual too; in the case of exists, in order to show the
existence of something, all you need to do is produce it. The
"particular individual" and "the individual which exists" are
precisely what the system asks you for.

In the case of the forall right (∀r) rule and the exists left
(∃l), the system picks a variable for you. But it doesn't pick any
old variable: the variable it picks is required to be distinct from
anything pre-existing in the sequent: this is often referred to as
the "no free occurrence" rule. One intuition for why the system
is constrained in this way is to consider this: it is generally
harder to prove something is true for all individuals than it is
to show it is true for only one.

In practice, this means is that the order you apply tactics is
important:

If you start off with the left-forall, when you apply the
right-forall, the system will always give you something that
doesn't match what you originally picked, and then you are stuck!
But it is easy to complete in the other direction.

One last note: the "contraction" button duplicates a hypothesis
or goal, so you can reuse it later (say, you want to say that
because all people are mortal, then Bob is mortal, AND Sally is
mortal). Use of this structural rule may be critical to
certain proofs; you will get stuck otherwise. (This rule is
somewhat paradoxically called contraction because when you read the
rule in the normal top-down direction, it "contracts" two identical
hypotheses into a single one.)

Summary. Here are all the inference rules for first order logic:

With these inference rules, you have the capability to
prove everything in first-order logic.

Exercises

Hint: these two require contraction.

Conclusion

I want to leave you with some parting words about why I find
this topic interesting.

First-order logic is well worth studying, because it is a
simple yet powerful tool for modelling the world and writing
specifications and constraints. These constraints can be given to
tools called SMT solvers, which can then automatically determine
how to satisfy these constraints. You can't do that with plain
English!

A common complaint with a formal systems like the sequent
calculus is the "I clicked around and managed to prove this, but
I'm not really sure what happened!" This is what Martin means by
the hacker mentality: it is now possible for people to prove
things, even when they don't know what they're doing. The
computer will ensure that, in the end, they will have gotten it
right. (You don't even have to test it, and there are no
bugs! Of course, it does help to know what you are doing.) Writ
large, working with this demo is like working with a proof
assistant. If you're interested in tackling more complicated
problems than presented here, I suggest checking out a textbook
like Software
Foundations.

One primary motivation for this tutorial, which constrained the
user interface design considerably, was to demonstrate the
notation and concepts relied upon heavily in the academic type
theory literature. As an undergraduate, I always found inference
rules to be some of the most intimidating parts of academic papers
in programming languages. Studying how these conventions work in
a simpler setting is a key step on the way to being able to "read
the Greek." While some of the notational choices may seem
hair-brained to a modern viewer, overall the system is very well
optimized. Inference rules are a remarkably compact and efficient
way to describe many types of systems: the space savings are
analogous to using BNFs to specify grammars.

Overall, my hope is that this tutorial has helped you take your
first step into the fascinating world of formal systems, type
theory and theorem proving. Return to the main
page, and try coming up with some theorems of your own!