Chapter 6

Predicate Logic Proofs

Now that we have seen how to translate statements to predicate logic, we will learn new deduction rules for working with universal and existential quantifiers. We will be able to add those rules to our propositional logic deduction rules and show that a set of premises proves a conclusion in predicate logic. Predicate logic is also referred to as first order logic.

As with propositional logic, we can use the Logika tool to help check the correctness of our new deduction rules. However, these new rules also exist outside of Logika, and we could express the same proofs with our rules in a different environment or on paper – the concepts are the same.

Logika predicate logic proof syntax

We will use the following format in Logika to start a natural deduction proof for predicate logic. Each proof will be saved in a new file with a .sc (Scala) extension:

// #Sireum #Logika
//@Logika: --manual --background type

import org.sireum._
import org.sireum.justification._
import org.sireum.justification.natded.prop._
import org.sireum.justification.natded.pred._

@pure def ProofName[T](pred1: T => B @pure, pred2: T => B @pure, ..., indiv1: T, indiv2: T, ...): Unit = {
    Deduce(
        //@formatter:off
        (comma-separated list of premises with variable1, variable2, ...)  ⊒  (conclusion)
            Proof(
                //the actual proof steps go here
            )
        //@formatter:on
    )
}

Here, T is the type of elements in our domain. Usually, we will just use T to denote a generic type (much like generics in Java and C#), but occasionally we will use specific types like Z (which means “integer”). Next, pred1, pred2, etc. are the predicates for our proofs. The T => B means that they take an element in our domain as a parameter (which has type T) and return a boolean (which has type B). Finally, indiv1, indiv2, etc. are specific individuals within our domain, each of which have type T.

A proof function like the example above can have as many or few predicates and individuals as are needed for the proof.

As was the case with propositional logic, the examples in this chapter will omit the imports, proof function definition, deduce call, and formatter changes are omitted here for readability. We will start each example with the sequent followed by the Proof call.

For all statements in Logika

The syntax of a statement like βˆ€ x P(x) in Logika is a little different, since we must specify that each x is an element in our domain. When we are using Logika to do a predicate logic proof, we express βˆ€ x P(x) as:

βˆ€ ((x: T) => P(x))

The above statement is saying, “for all x that are of the type T, P(x) is true”.

We can alternatively use curly braces instead of standard parentheses to surround our predicate:

βˆ€ {(x: T) => P(x)}

Such statements can be a pain to type out manually, so there is a way to insert them using a template. If you right-click where you wish to write a predicate logic statement, you can select Slang->Insert Template->Forall. This will insert the statement:

βˆ€((ID: TYPE) => CLAIM)

You can type your variable name (often x, y, etc.) in place of ID, the domain type (usually T) in place of TYPE, and your claim (with predicates and propositional logic operators) in place of CLAIM.

Finally, you can type the keyboard shortcut Ctrl+Shift+, A to insert a for all statement.

There exists statements in Logika

Statements with existential quantifiers like βˆƒ x P(x) must also be treated differently. When we are using Logika to do a predicate logic proof, we express βˆƒ x P(x) as:

βˆƒ ((x: T) => P(x))

The above statement is saying, “there exists an x with type T where P(x) is true”.

We can alternatively use curly braces instead of standard parentheses to surround our predicate:

βˆƒ {(x: T) => P(x)}

Such statements can be a pain to type out manually, so there is a way to insert them using a template. If you right-click where you wish to write a predicate logic statement, you can select Slang->Insert Template->Exists. This will insert the statement:

βˆƒ((ID: TYPE) => CLAIM)

You can type your variable name (often x, y, etc.) in place of ID, the domain type (usually T) in place of TYPE, and your claim (with predicates and propositional logic operators) in place of CLAIM.

Finally, you can type the keyboard shortcut Ctrl+Shift+, E to insert a there exists statement.

Subsections of Predicate Logic Proofs

Rules with βˆ€

Just as with our propositional logic operators, there will be two inference rules for each of our predicate logic quanitifiers – an “introduction rule and an “elimination” rule.

In this section, we will see the two inference rules for the universal (βˆ€) quantifier.

For all elimination

For all elimination allows us to take a claim that uses a universal quantifier – a statement about ALL individuals in a domain – and make the same statement about a specific individual in the domain. After all, if the statement is true for ALL individuals, then it follows that it should be true for a particular individual. We can formalize the rule as follows:

           βˆ€ ((x: T) => P(x))
AllE[T]:  ---------------------
                   P(v)     where v is a particular individual in the domain (i.e, v has type T)

Here is a simple example showing the syntax of the AllE[T] rule. It shows that given the premises: All humans are mortal and Socrates is a human, that we can prove that Socrates is mortal:

    (   βˆ€ ((x: T) => (isHuman(x) β†’ isMortal(x))),  
        isHuman(Socrates)    
    ) 
⊒ 
    (   
        isMortal(Socrates) 
    )
Proof(
    1 (     βˆ€ ((x: T) => (isHuman(x) β†’ isMortal(x)))        )   by Premise,
    2 (     isHuman(Socrates)                               )   by Premise,
    3 (     isHuman(Socrates) β†’ isMortal(Socrates)          )   by AllE[T](1),
    4 (     isMortal(Socrates)                              )   by ImplyE(3, 2)
)

We can read the justification AllE[T](1) as: “for all elimination of the for all statement on line 1.

While our AllE[T] justification does not mention the particular individual that was plugged in to the for all statement (Socrates, in this case), it is required that whatever individual we plug in has already been show to be of type T. This is done by accepting the individual as a parameter of type T to the proof function. The full proof function would look like this:

@pure def socMortal[T](isHuman: T => B @pure, isMortal: T => B @pure, Socrates: T): Unit = {
    Deduce (
        (   
            βˆ€ ((x: T) => (isHuman(x) β†’ isMortal(x))),  
            isHuman(Socrates)    
        ) 
        ⊒ 
        (   
            isMortal(Socrates) 
        )
        Proof(
            1 (     βˆ€ ((x: T) => (isHuman(x) β†’ isMortal(x)))      )   by Premise,
            2 (     isHuman(Socrates)                             )   by Premise,
            3 (     isHuman(Socrates) β†’ isMortal(Socrates)        )   by AllE[T](1),
            4 (     isMortal(Socrates)                            )   by ImplyE(3, 2)
        )
    )
}

In similar examples of AllE[T], it is assumed that the named individual was accepted as a parameter of type T to the proof function.

For all introduction

If we can show that a property of the form P(a) holds for an arbitrary member a of a domain, then we can use for all introduction to conclude that the property must hold for ALL individuals in the domain – i.e., that βˆ€ x P(x) (which we write in Logika as βˆ€ ((x: T) => P(x))). We can formalize the rule as follows:

            Let (   (a: T) => SubProof(
                ... 
                P(a)  
            )),
AllI[T] : -------------------------------
                 βˆ€ ((x: T) => P(x)) 

Here is a simple example showing the syntax of the AllI[T] rule: “Everyone is healthy; everyone is happy. Therefore, everyone is both healthy and happy.”:

    (   
        βˆ€((x: T) => isHealthy(x)), βˆ€((y: T) => isHappy(y))
    )  
⊒  
    (
        βˆ€((z: T) => isHealthy(z) ∧ isHappy(z))
    )
Proof (
    1 (     βˆ€((x: T) => isHealthy(x))               )   by Premise,
    2 (     βˆ€((y: T) => isHappy(y))                 )   by Premise,
    
    3 Let ((a: T) => SubProof(
        4 (     isHealthy(a)                        )   by AllE[T](1),
        5 (     isHappy(a)                          )   by AllE[T](2),
        6 (     isHealthy(a) ∧ isHappy(a)           )   by AndI(4, 5)
    )),
    7 (     βˆ€((z: T) => isHealthy(z) ∧ isHappy(z))  )   by AllI[T](3)
)

If we wish to introduce a for all statement, the pattern is:

  • Open a subproof where you introduce an arbitrary/fresh individual in the domain with “Let” (in the example above, we used a). It MUST be a name that we have not used elsewhere in the proof. The idea is that your individual could have been anyone/anything in the domain.

  • When you introduce the individual with “Let” and then open the subproof, you do NOT include a justification on that line

  • If you have other for all statements available within the scope of the subproof, then it is often useful to use AllE[T] to plug your fresh individual into them. After all, if those statements are true for ALL individuals, then they are also true for your fresh individual.

  • If you are trying to prove something of the form βˆ€ ((x: T) => P(x)), then you need to reach P(a) by the end of the subproof. You need to show that your goal for all statement holds for your fresh individual. In our case, we wished to prove βˆ€((z: T) => isHealthy(z) ∧ isHappy(z)), so we reached isHealthy(a) ∧ isHappy(a) by the end of the subproof.

  • After the subproof, you can use βˆ€i to introduce a for-all statement for your last claim in the subproof – that since the individual could have been anyone, then the proposition holds for ALL individuals. The βˆ€i justification needs the line number of the subproof.

  • When you use AllI[T], it does not matter what variable you introduce into the for all statement. In the example above, we introduced βˆ€((z: T) – but that was only to match the goal conclusion in the proof. We could have instead introduced βˆ€((x: T), βˆ€((y: T), βˆ€((people T), etc. We would use whatever variable we chose in the rest of that proposition – i.e., βˆ€((z: T) => isHealthy(z) ∧ isHappy(z)), or βˆ€((people: T) => isHealthy(people) ∧ isHappy(people)), etc.

Examples

In this section, we will look at additional proofs involving the universal quantifier.

Example 1

Suppose we wish to prove that, given the following premises in the domain of people:

  • All students have a phone and/or a laptop
  • Everyone is a student

Then we can conclude:

  • Everyone has a phone and/or a laptop

First, we identify the following predicates:

  • isStudent(x) - whether person x is a student
  • hasPhone(x) - whether person x has a phone
  • hasLaptop(x) = whether person x has a laptop

Then, we can translate our premises and goal conclusion to predicate logic:

  • All students have a phone and/or a laptop translates to: βˆ€ x (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x))
  • Everyone is a student translates to: βˆ€ x isStudent(x)
  • Everyone has a phone and/or a laptop translates to: βˆ€ x (hasPhone(x) ∨ hasLaptop(x))

We need to prove the following sequent (where we rewrite the above predicate logic statements in our Logika format):

    (
        βˆ€((x: T) => (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x))), 
        βˆ€((x: T) => isStudent(x))
    ) 
⊒ 
    (
        βˆ€((y: T) => (hasPhone(y) ∨ hasLaptop(y)))
    )

As with our previous example, we see that we are trying to prove a for-all statement (βˆ€((y: T) => (hasPhone(y) ∨ hasLaptop(y)))). This means we will need to open a subproof and introduce a fresh individual – perhaps bob. By the end of the subproof, we must show that our goal for-all statement holds for that individual – that hasPhone(bob) ∨ hasLaptop(bob). We start the proof as follows:

    (
        βˆ€((x: T) => (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x))), 
        βˆ€((x: T) => isStudent(x))
    ) 
⊒ 
    (
        βˆ€((y: T) => (hasPhone(y) ∨ hasLaptop(y)))
    )
Proof (
    1 (     βˆ€((x: T) => (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x)))        )   by Premise,
    2 (     βˆ€((x: T) => isStudent(x))                                       )   by Premise,

    3 Let ( (bob: T) => SubProof(
        
        //goal: hasPhone(bob) ∨ hasLaptop(bob)
    )),
    
    //use AllI to conclude βˆ€((y: T) => (hasPhone(y) ∨ hasLaptop(y)))
)

We have two available for-all statements within the subproof – βˆ€((x: T) => (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x))) and βˆ€((x: T) => isStudent(x)). Since those propositions hold for all individuals, they also hold for bob. We use AllE[T] to plug in bob to those two propositions:

    (
        βˆ€((x: T) => (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x))), 
        βˆ€((x: T) => isStudent(x))
    ) 
⊒ 
    (
        βˆ€((y: T) => (hasPhone(y) ∨ hasLaptop(y)))
    )
Proof (
    1 (     βˆ€((x: T) => (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x)))        )   by Premise,
    2 (     βˆ€((x: T) => isStudent(x))                                       )   by Premise,

    3 Let ( (bob: T) => SubProof(
        4 (     isStudent(bob) β†’ hasPhone(bob) ∨ hasLaptop(bob)             )   by AllET(1),
        5 (     isStudent(bob)                                              )   by AllE[T](2),

        //goal: hasPhone(bob) ∨ hasLaptop(bob)
    )),
    
    //use AllI to conclude βˆ€((y: T) => (hasPhone(y) ∨ hasLaptop(y)))
)

Line 5 is an implies statement the form p β†’ q, and line 6 is a statement of the form p. Thus we can use β†’e to conclude hasPhone(bob) ∨ hasLaptop(bob) (the “q” in that statement) – which is exactly what we needed to end the subproof. All that remains is to apply our AlI rule after the subproof. Here is the completed proof:

    (
        βˆ€((x: T) => (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x))), 
        βˆ€((x: T) => isStudent(x))
    ) 
⊒ 
    (
        βˆ€((y: T) => (hasPhone(y) ∨ hasLaptop(y)))
    )
Proof (
    1 (     βˆ€((x: T) => (isStudent(x) β†’ hasPhone(x) ∨ hasLaptop(x)))        )   by Premise,
    2 (     βˆ€((x: T) => isStudent(x))                                       )   by Premise,

    3 Let ( (bob: T) => SubProof(
        4 (     isStudent(bob) β†’ hasPhone(bob) ∨ hasLaptop(bob)             )   by AllET(1),
        5 (     isStudent(bob)                                              )   by AllE[T](2),
        6 (     hasPhone(bob) ∨ hasLaptop(bob)                              )   by ImplyE(4, 5)
    )),
    7 (     βˆ€((y: T) => (hasPhone(y) ∨ hasLaptop(y)))                       )   by AllI[T](3)
)

Example 2

Next, suppose we wish to prove the following sequent:

    (
        βˆ€((x: T) => (S(x) β†’ Pz(x))),
        βˆ€((x: T) => (Pz(x) β†’ D(x))),
        βˆ€((x: T) => Β¬D(x))
    )
⊒
    (
        βˆ€((x: T) => Β¬S(x))
    )

We again see that the top-level operator of what we are trying to prove is a universal quantifier. We use our strategy to open a subproof with a fresh individual (maybe a), and plug that individual into any available for-all statements. Since we wish to prove βˆ€((x: T) => Β¬S(x)), then we will want to reach Β¬S(a) by the end of the subproof. Here is a sketch:

    (
        βˆ€((x: T) => (S(x) β†’ Pz(x))),
        βˆ€((x: T) => (Pz(x) β†’ D(x))),
        βˆ€((x: T) => Β¬D(x))
    )
⊒
    (
        βˆ€((x: T) => Β¬S(x))
    )

Proof(
    1 (     βˆ€((x: T) => (S(x) β†’ Pz(x)))     )   by Premise,
    2 (     βˆ€((x: T) => (Pz(x) β†’ D(x))      )   by Premise,
    3 (     βˆ€((x: T) => Β¬D(x))              )   by Premise,

    4 Let ((a: T) => SubProof (
        5 (     S(a) β†’ Pz(a)                )   by AllE[T](1),
        6 (     Pz(a) β†’ D(a)                )   by AllE[T](2),
        7 (     Β¬D(a)                       )   by AllE[T](3),

        //goal: Β¬S(a)
    )),
    //use AllI[T] to conclude βˆ€((x: T) => Β¬S(x))
)

Now, we see that our goal is to reach Β¬S(a) by the end of the subproof – so we need to prove something whose top-level operator is a NOT. We recall that we have a strategy to prove NOT(something) from propositional logic – we open a subproof, assuming something (S(a), in our case), try to get a contradiction, and use negation introduction after the subproof to conclude NOT (something) (Β¬S(a) for us). Here is the strategy:

    (
        βˆ€((x: T) => (S(x) β†’ Pz(x))),
        βˆ€((x: T) => (Pz(x) β†’ D(x))),
        βˆ€((x: T) => Β¬D(x))
    )
⊒
    (
        βˆ€((x: T) => Β¬S(x))
    )

Proof(
    1 (     βˆ€((x: T) => (S(x) β†’ Pz(x)))     )   by Premise,
    2 (     βˆ€((x: T) => (Pz(x) β†’ D(x))      )   by Premise,
    3 (     βˆ€((x: T) => Β¬D(x))              )   by Premise,

    4 Let ((a: T) => SubProof(
        5 (     S(a) β†’ Pz(a)                )   by AllE[T](1),
        6 (     Pz(a) β†’ D(a)                )   by AllE[T](2),
        7 (     Β¬D(a)                       )   by AllE[T](3),

        8 SubProof(
            10 Assume( S(a) ),
            
            //goal: contradiction
        ),
        //use NegI to conclude Β¬S(a)

        //goal: Β¬S(a)
    )),
    //use AllI[T] to conclude βˆ€((x: T) => Β¬S(x))
)

We can complete the proof as follows:

    (
        βˆ€((x: T) => (S(x) β†’ Pz(x))),
        βˆ€((x: T) => (Pz(x) β†’ D(x))),
        βˆ€((x: T) => Β¬D(x))
    )
⊒
    (
        βˆ€((x: T) => Β¬S(x))
    )

Proof(
    1 (     βˆ€((x: T) => (S(x) β†’ Pz(x)))     )   by Premise,
    2 (     βˆ€((x: T) => (Pz(x) β†’ D(x))      )   by Premise,
    3 (     βˆ€((x: T) => Β¬D(x))              )   by Premise,

    4 Let ((a: T) => SubProof(
        5 (     S(a) β†’ Pz(a)                )   by AllE[T](1),
        6 (     Pz(a) β†’ D(a)                )   by AllE[T](2),
        7 (     Β¬D(a)                       )   by AllE[T](3),

        8 SubProof(
            10 Assume( S(a) ),
            11 (    Pz(a)                   )   by ImplyE(5, 10),
            12 (    D(a)                    )   by ImplyE(6, 11),
            13 (    F                       )   by NegE(12, 7)
            
            //goal: contradiction
        ),
        //use Β¬i to conclude Β¬S(a)
        14 (    Β¬S(a)                       )   by NegI(8)

        //goal: Β¬S(a)
    )),
    //use AllI[T] to conclude βˆ€((x: T) => Β¬S(x))
    15 (    βˆ€((x: T) => Β¬S(x))              )   by AllI[T](4)
)

Rules with βˆƒ

In this section, we will see the two inference rules for the existential (βˆƒ) quantifier.

Exists introduction

We can use the exists introduction rule, ExistsI[T], when we have a proposition of the form P(a) for an arbitrary member a of a domain. Since we found one individual where a proposition held, then we can also say that there exists an individual for which the proposition is true. We can formalize the rule as follows:

                   P(d)         where  d  is an individual of type T
ExistsI[T]: ---------------------
              βˆƒ((x: T) => P(x))

Here is a simple example showing the syntax of the ExistsI[T] rule (where Socrates is a parameter of type T to our proof function):

(   isHuman(Socrates)   ) ⊒ (   βˆƒ x isHuman(x)  )
    
    Proof(
        1 (     isHuman(Socrates)   )   by Premise,
        2 (     βˆƒ((x: T) => P(x))   )   by ExistsI[T](1)
    )

When we use the ExistsI[T] rule to justify a claim like βˆƒ((x: T) => P(x)), we include the line number of where the proposition held for a particular individual. In the proof above, we claim βˆƒ((x: T) => P(x)) with justification ExistsI[T](1) – line 1 corresponds to isHuman(Socrates), where our βˆƒ x isHuman(x) proposition held for a particular individual. The full proof function, which shows how Socrates can be accepted as a parameter of type T, is here:

@pure def ExistsExample[T](isHuman: T => B @pure, Socrates: T): Unit = {
    Deduce(
        (   isHuman(Socrates)   ) ⊒ (   βˆƒ x isHuman(x)  )
    
        Proof(
            1 (     isHuman(Socrates)   )   by Premise,
            2 (     βˆƒ((x: T) => P(x))   )   by ExistsI[T](1)
        )
    )
}

Note that we can use the ExistsI[T] rule to introduce any variable, not just x. You can choose which variable to introduce based on the variables used in the conclusion. For example, the following proof is also valid:

(   isHuman(Socrates)   ) ⊒ (   βˆƒ x isHuman(z)  )
    
    Proof(
        1 (     isHuman(Socrates)   )   by Premise,
        2 (     βˆƒ((z: T) => P(z))   )   by ExistsI[T](1)
    )

Exists elimination

Since the ExistsI[T]-rule constructs propositions that begin with βˆƒ, the ExistsE[T]-rule (exists elimination) disassembles propositions that begin with βˆƒ.

Here is a quick example (where our domain is living things):

  • All humans are mortal
  • Someone is human
  • Therefore, someone is mortal

We don’t know the name of the human, but it does not matter. Since ALL humans are mortal and SOMEONE is human, then our anonymous human must be mortal. The steps will go like this:

  • Since “someone is human” and since we do not know his/her name, we will just make up our own name for them – “Jane”. So, we assume that “Jane is human”.

  • We use the logic rules we already know to prove that “Jane is mortal”.

  • Therefore, SOMEONE is mortal and their name does not matter.

This approach is coded into the last logic law, ExistsE[T] (exists elimination).

Suppose we have a premise of the form βˆƒ((x: T) => P(x)). Since we do not know the name of the individual “hidden” behind the βˆƒ(x: T), we make up a name for it, say a, and discuss what must follow from the assumption that P(a) holds true. Here is the formalization of the ExistsE[T] rule:

                                        Let ((a: T) => SubProof(          // where  a  is a new, fresh name
                                             Assume( P(a) ),              // a  MUST NOT appear in  Q
                βˆƒ((x: T) => P(x))            ...
                                             Q         
                                        )),             
ExistsE[T]: ----------------------------------------------------
                     Q

That is, if we can deduce Q from P(a), and we do not mention a within Q, then it means Q can be deduced no matter what name the hidden individual has. So, Q follows from βˆƒ((x: T) => P(x)).

We can work the previous example, with ExistsE[T]:

All humans are mortal
Someone is human
Therefore, someone is mortal

We make up the name, jane, for the human whose name we do not know:

    (
        βˆ€((h: T) => (isHuman(h) β†’ isMortal(h))),
        βˆƒ((x: T) => isHuman(x))
    )
⊒
    (
        βˆƒ((y: T) => (isMortal(y)))
    )
Proof(
    1 (     βˆ€((h: T) => (isHuman(h) β†’ isMortal(h)))     )   by Premise,
    2 (     βˆƒ((x: T) => isHuman(x))                     )   by Premise,

    3 Let ( (jane: T) => SubProof (
        4 Assume(   isHuman(jane)                       ),
        5 (         isHuman(jane) β†’ isMortal(jane)      )   by AllE[T](1),
        6 (         isMortal(jane)                      )   by ImplyE(5, 4)
    )),
    7 (     βˆƒ((y: T) => (isMortal(y)))                  )   by ExistsE[T](2, 3)
)

Line 3 proposes the name jane for our subproof and line 4 makes the assumption isHuman(jane) (based on the premise βˆƒ((x: T) => isHuman(x))). The subproof leads to Line 6, which says that someone is mortal. (We never learned the individual’s name!) Since Line 6 does not explicitly mention the made-up name, jane, we use Line 7 to repeat Line 6 – without knowing the name of the individual “hiding” inside Line 2, we made a subproof that proves the result, anyway. This is how ExistsE[T] works.

Note that when we use the ExistsE[T] rule as a justification we include first the line number of the there exists statement that we processed (by naming the hidden individual) in the previous subproof, and then the line number of that subproof. In the example above, we say ExistsE[T](2, 3) because line 2 includes the there-exists statement we processed (βˆƒ βˆƒ((x: T) => isHuman(x))) in the previous subproof and line 3 is the subproof.

When using ExistsE[T], the previous subproof must begin with introducing a name for a hidden individual in a there-exists statement and then immediately make an assumption that substitutes the name into the there exists statement. The last line in the subproof should contain NO mention of the chosen name. Whatever we claim on the last line in the subproof, we must claim EXACTLY the same thing immediately afterwards when we use the ExistsE[T] rule.

You are welcome to use any name for the hidden individual – not just jane or a. The only restriction is that you cannot have used the name anywhere else in the proof.

Examples

In this section, we will look at other proofs involving the existential quantifier.

Example 1

Suppose we wish to prove the following sequent:

(   βˆƒ((x: T) => (Adult(x) ∨ Kid(x)))  ) ⊒ (   βˆƒ((x: T) => Adult(x) )) ∨ βˆƒ((x: T) => Kid(x)  )

We will begin as we did previously: by introducing an alias for our person that is either an adult or a kid (say, alice):

(   βˆƒ((x: T) => (Adult(x) ∨ Kid(x)))  ) ⊒ (   βˆƒ((x: T) => Adult(x) )) ∨ βˆƒ((x: T) => Kid(x)  )

Proof(
    1 (     βˆƒ((x: T) => (Adult(x) ∨ Kid(x)) )       )   by Premise,

    2 Let ( (alice: T) => SubProof(
        3 Assume(   Adult(alice) ∨ Kid(alice)       ),
        
        //goal: get to our conclusion, βˆƒ( (x: T) => Adult(x) )) ∨ βˆƒ( (x: T) => Kid(x)
    )),

    //use ExistsE[T] to restate our conclusion, since we know SOME such person is either an adult or kid
)

To finish our proof, we can use OR elimination on Adult(alice) ∨ Kid(alice), and then ExistsE[T] afterwards to restate our conclusion. Here is the completed proof:

(   βˆƒ((x: T) => (Adult(x) ∨ Kid(x)))  ) ⊒ (   βˆƒ((x: T) => Adult(x) )) ∨ βˆƒ((x: T) => Kid(x)  )

Proof(
    1 (     βˆƒ((x: T) => (Adult(x) ∨ Kid(x)) )                   )   by Premise,

    2 Let ( (alice: T) => SubProof(
        3 Assume(   Adult(alice) ∨ Kid(alice)                   ),

        4 SubProof(
            5 Assume (  Adult(alice)                            ),
            6 (     βˆƒ((x: T) => Adult(x)                        )   by ExistsI[T](5),
            7 (     βˆƒ((x: T) => Adult(x) ∨ βˆƒ((x: T) => Kid(x)   )   by OrI1(6)
        ),
        8 SubProof(
            9 Assume (  Kid(alice)                              ),
            10 (    βˆƒ((x: T) => Kid(x)                          )   by ExistsI[T](9),
            11 (    βˆƒ((x: T) => Adult(x) ∨ βˆƒ((x: T) => Kid(x)   )   by OrI2(10)
        ),
        12 (    βˆƒ((x: T) => Adult(x) ∨ βˆƒ((x: T) => Kid(x)       )   by OrE(3, 4, 8)
        
        //goal: get to our conclusion, βˆƒ( (x: T) => Adult(x) )) ∨ βˆƒ( (x: T) => Kid(x)
    )),
    //use ExistsE[T] to restate our conclusion, since we know SOME such person is either an adult or kid

    13 (        βˆƒ((x: T) => Adult(x) ∨ βˆƒ((x: T) => Kid(x)       )   by ExistsE[T](1, 2)
)

Example 2

Suppose we wish to prove the following (in the domain of living things):

  • All bunnies are fluffy
  • There is a fast bunny
  • Therefore, there is a creature that is fast and fluffy

We can translate our premises and desired conclusion to predicate logic, and write the following sequent:

    (
        βˆ€((x: T) => (Bunny(x) β†’ Fluffy(x))),
        βˆƒ((x: T) => (Fast(x) & Bunny(x))) 
    )
⊒
    (
        βˆƒ((x: T) => (Fast(x) & Fluffy(x)))
    )

Since we are trying to prove a claim about some individual, it makes sense that we would start the process of an ExistsE[T] subproof where we introduce an alias (thumper) for the fast bunny. We will try to reach the conclusion by the end of that subproof. Here is the setup:

    (
        βˆ€((x: T) => (Bunny(x) β†’ Fluffy(x))),
        βˆƒ((x: T) => (Fast(x) & Bunny(x))) 
    )
⊒
    (
        βˆƒ((x: T) => (Fast(x) & Fluffy(x)))
    )
Proof(
    1 (     βˆ€((x: T) => (Bunny(x) β†’ Fluffy(x)))     )   by Premise,
    2 (     βˆƒ((x: T) => (Fast(x) & Bunny(x)))       )   by Premise,

    3 Let ( (thumper: T) => SubProof(
        4 Assume(   Fast(thumper) ∧ Bunny(thumper)  ),
        5 (         Fast(thumper)                   )   by AndE1(4),
        6 (         Bunny(thumper)                  )   by AndE2(4),

        //goal: βˆƒ((x: T) => (Fast(x) & Fluffy(x)))
    )),

    //use ExistsE[T] to restate βˆƒ((x: T) => (Fast(x) & Fluffy(x))), since we know there is SOME fast bunny
)

To finish our subproof, we see that we have a proposition about all creatures (βˆ€((x: T) => (Bunny(x) β†’ Fluffy(x)))) and that we are working with an individual creature (thumper). We can use AllE[T] to prove Bunny(thumper) β†’ Fluffy(thumper). After that, we have a few more manipulations using propositional logic rules, our ExistsI[T] rule to transition our claim from being about our alias thumper to being about an unnamed individual, and then our ExistsE[T] rule to pull our final claim out of the subproof. Here is the completed proof:

    (
        βˆ€((x: T) => (Bunny(x) β†’ Fluffy(x))),
        βˆƒ((x: T) => (Fast(x) & Bunny(x))) 
    )
⊒
    (
        βˆƒ((x: T) => (Fast(x) & Fluffy(x)))
    )
Proof(
    1 (     βˆ€((x: T) => (Bunny(x) β†’ Fluffy(x)))         )   by Premise,
    2 (     βˆƒ((x: T) => (Fast(x) & Bunny(x)))           )   by Premise,

    3 Let ( (thumper: T) => SubProof(
        4 Assume(   Fast(thumper) ∧ Bunny(thumper)      ),
        5 (         Fast(thumper)                       )   by AndE1(4),
        6 (         Bunny(thumper)                      )   by AndE2(4),
        7 (         Bunny(thumper) β†’ Fluffy(thumper)    )   by AllE[T](1),
        8 (         Fluffy(thumper)                     )   by ImplyE(7, 6),
        9 (         Fast(thumper) ∧ Fluffy(thumper)     )   by AndI(5, 8),
        10 (        βˆƒ((x: T) => (Fast(x) & Fluffy(x)))  )   by ExistsE[T](9)

        //goal: βˆƒ((x: T) => (Fast(x) & Fluffy(x)))
    )),
    //use ExistsE[T] to restate βˆƒ((x: T) => (Fast(x) & Fluffy(x))), since we know there is SOME fast bunny

    11 (    βˆƒ((x: T) => (Fast(x) & Fluffy(x)))          )   by ExistsE[T](2, 3)
)

Nested Quantifiers

Our examples so far have included propositions with single quantifiers. This section will discuss how to prove sequents that use nested quantifers. We will see that the approach is the same as before, but that we must take caution to process the quantifiers in the correct order. Recall that quantifier precedence is from right to left (i.e., from the outside in), so that βˆ€ x βˆ€ y P(x, y) is equivalent to βˆ€ x (βˆ€ y P(x, y)).

//<——————COME UP WITH DIFFERENT EXAMPLE 1!!!!!——————->

Example 1

Suppose we wish to prove the following sequent:

    (
        βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y)))),
        βˆ€((x: T) => βˆ€((y: T) => P(x, y)))
    )
⊒
    (
        βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
    )

Since we wish to prove a for-all statement, βˆ€((x: T) => (SOMETHING), we know we must start with our for all introduction template:

    (
        βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y)))),
        βˆ€((x: T) => βˆ€((y: T) => P(x, y)))
    )
⊒
    (
        βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
    )
Proof(
    1 (     βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y))))       )   by Premise,
    2 (     βˆ€((x: T) => βˆ€((y: T) => P(x, y)))                   )   by Premise,
    
    3 Let (  (a: T)  => SubProof(

        //need: βˆ€((y: T) => Q(a, y))
    )),
    //want to use AllI[T] to conclude βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
)

But now we see that we want to prove ANOTHER for-all statement, βˆ€((y: T) => Q(a, y)). So we again use our for all introduction strategy in a nested subproof:

    (
        βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y)))),
        βˆ€((x: T) => βˆ€((y: T) => P(x, y)))
    )
⊒
    (
        βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
    )
Proof(
    1 (     βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y))))       )   by Premise,
    2 (     βˆ€((x: T) => βˆ€((y: T) => P(x, y)))                   )   by Premise,
    
    3 Let (  (a: T)  => SubProof(
        4 ( (b: T) => SubProof(

            //need: Q(a, b)
        )),
        //want to use AllI[T] to conclude βˆ€((y: T) => Q(a, y))

        //need: βˆ€((y: T) => Q(a, y))
    )),
    //want to use AllI[T] to conclude βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
)

Now, in subproof 4, we see that we must use AllE[T] on our both of our premises to work towards our goal of Q(a, b). We have two available individuals – a and b. When we use AllE[T], we must eliminate the OUTER (top-level) quantifier and its variable. In the case of the premise βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y)))), we see that we must eliminate the βˆ€((x: T) ...). Since the x is the first parameter in Q(x, y), and since we are hoping to reach Q(a, b) by the end of subproof 4, we can see that we need to plug in the a for the x so that it will be in the desired position. We make a similar substitution with AllE[T] on our second premise:

    (
        βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y)))),
        βˆ€((x: T) => βˆ€((y: T) => P(x, y)))
    )
⊒
    (
        βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
    )
Proof(
    1 (     βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y))))       )   by Premise,
    2 (     βˆ€((x: T) => βˆ€((y: T) => P(x, y)))                   )   by Premise,
    
    3 Let (  (a: T)  => SubProof(
        4 ( (b: T) => SubProof(

            5 (     βˆ€(y: T) => (P(a, y) β†’ Q(a, y)))             )   by AllE[T](1),
            6 (     βˆ€(y: T) => P(a, y)                          )   by AllE[T](2),

            //need: Q(a, b)
        )),
        //want to use AllI[T] to conclude βˆ€((y: T) => Q(a, y))

        //need: βˆ€((y: T) => Q(a, y))
    )),
    //want to use AllI[T] to conclude βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
)

Note that on line 5, we could NOT have used AllE[T] to eliminate the βˆ€(y: T) in βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y)))) , as it was not the top-level operator.

Next, we apply AllE[T] again to our results on lines 5 and 6, this time plugging in b for y in both cases. This leaves us with P(a, b) β†’ Q(a, b) and P(a, b). We can use implies elimination to reach our goal of Q(a, b), and then all that remains ais to use AllI[T] twice as planned to wrap up the two subproofs. Here is the completed proof:

    (
        βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y)))),
        βˆ€((x: T) => βˆ€((y: T) => P(x, y)))
    )
⊒
    (
        βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
    )
Proof(
    1 (     βˆ€((x: T) => βˆ€((y: T) => (P(x, y) β†’ Q(x, y))))       )   by Premise,
    2 (     βˆ€((x: T) => βˆ€((y: T) => P(x, y)))                   )   by Premise,
    
    3 Let (  (a: T)  => SubProof(
        4 ( (b: T) => SubProof(

            5 (     βˆ€(y: T) => (P(a, y) β†’ Q(a, y))              )   by AllE[T](1),
            6 (     βˆ€(y: T) => P(a, y)                          )   by AllE[T](2),
            7 (     P(a, b) β†’ Q(a, b)                           )   by AllE[T](5),
            8 (     P(a, b)                                     )   by ALlE[T](6),
            9 (     Q(a, b)                                     )   by ImplyE(7, 8)

            //need: Q(a, b)
        )),
        //want to use AllI[T] to conclude βˆ€((y: T) => Q(a, y))
        10 (    βˆ€((y: T) => Q(a, y))                            )   by AllI[T](4)

        //need: βˆ€((y: T) => Q(a, y))
    )),
    //want to use AllI[T] to conclude βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))
    11 (    βˆ€((x: T) => βˆ€((y: T) => Q(x, y)))                   )   by AllI[T](3)
)

Example 2

Suppose we have the predicate IsBossOf(x, y) in the domain of people, which describes whether person x is the boss of person y. We wish to prove the following sequent:

    (
        βˆƒ((x: T) => βˆ€((y: T) => IsBossOf(x, y)))
    )
⊒
    (
        βˆ€((y: T) => βˆƒ((x: T) => IsBossOf(x, y)))
    )

You can read the premise as “There is a person that is everyone’s boss”. From this statement, we are trying to prove the conclusion: “All people have a boss”. Here is the completed proof:

    (
        βˆƒ((x: T) => βˆ€((y: T) => IsBossOf(x, y)))
    )
⊒
    (
        βˆ€((y: T) => βˆƒ((x: T) => IsBossOf(x, y)))
    )

Proof(
    1 (     βˆƒ((x: T) => βˆ€((y: T) => IsBossOf(x, y)))            )   by Premise,

    2 Let ( (a: T) => SubProof(
        3 Assume(   βˆ€((y: T) => IsBossOf(a, y)                  )

        4 Let ( (b: T) => SubProof(
            5 (         IsBossOf(a, b)                          )   by AllE[T](3),
            6 (         βˆƒ((x: T) => IsBossOf(x, b))             )   by ExistsI[T](5)
        )),
        7 (   βˆ€((y: T) => βˆƒ((x: T) => IsBossOf(x, y)))          )   by AllI[T](4)
    )),
    8 (   βˆ€((y: T) => βˆƒ((x: T) => IsBossOf(x, y)))              )  by ExistsE[T](1, 2)
)

In the above proof, we let a be our made-up name for the boss-of-everyone. So, we have the assumption that βˆ€((y: T) => IsBossOf(a, y)). Next, we let b be “anybody at all” who we might examine in the domain of people. The proof exposes that the boss of “anybody at all” in the domain must always be a. AllI[T] and then ExistsE[T] finish the proof.

Here is the proof worked again, with the subproofs swapped:

    (
        βˆƒ((x: T) => βˆ€((y: T) => IsBossOf(x, y)))
    )
⊒
    (
        βˆ€((y: T) => βˆƒ((x: T) => IsBossOf(x, y)))
    )

Proof(
    1 (     βˆƒ((x: T) => βˆ€((y: T) => IsBossOf(x, y)))            )   by Premise,

    2 Let ( (b: T) => SubProof(

        3 Let ( (a: T) => SubProof(
            4 Assume(   βˆ€((y: T) => IsBossOf(a, y))             ),
            5 (         IsBossOf(a, b)                          )   by AllE[T](4),
            6 (         βˆƒ((x: T) => IsBossOf(x, b))             )   by ExistsI[T](5)
        )),
        7 (       βˆƒ((x: T) => IsBossOf(x, b))                   )   by ExistsE[T](1, 3)
    )),
    8 (   βˆ€((y: T) => βˆƒ((x: T) => IsBossOf(x, y)))              )  by AllI[T](2)
)

Can we prove the converse? That is, if everyone has a boss, then there is one boss who is the boss of everyone? NO. We can try, but we get stuck:

    (
        βˆ€((y: T) => βˆƒ((x: T) => IsBossOf(x, y)))
    )
⊒
    (
        βˆƒ((x: T) => βˆ€((y: T) => IsBossOf(x, y)))
    )

Proof(
    1 (     βˆ€((y: T) => βˆƒ((x: T) => IsBossOf(x, y)))            )   by Premise,

    2 Let ( (a: T) => SubProof(
        3 (     βˆƒ((x: T) => IsBossOf(x, a))                     )   by AllE[T](1),
        
        4 Let ( (b: T) => SubProof(
            5 (     Assume (    IsBossOf(b, a)                  ),
        )),
        6 (     βˆ€((y: T) => IsBossOf(b, y))                     )   AllI[T](4),

        //STEP 6 IS INVALID -- we cannot refer to b after the end of the subproof
        //where it was introduced

    )),
    
    //...can't finish
)

We see that the “block structure” of the proofs warns us when we are making invalid deductions.

Equivalence

In Chapter 5, we saw DeMorgan’s laws for quantifiers – that if we have some domain, and if P(x) is a predicate for individuals in that domain, then the following statements are equivalent:

  • Β¬(βˆƒ x P(x)) is equivalent to βˆ€ x Β¬P(x)
  • Β¬(βˆ€ x P(x)) is equivalent to βˆƒ x Β¬P(x)

The process of proving that two predicate logic statements are equivalent is the same as it was in propositional logic – we must prove the second proposition using the first as a premise, and we must prove the first given the second as a premise.

Example - how to prove equivalence

For example, to prove that Β¬(βˆƒ x P(x)) is equivalent to βˆ€ x Β¬P(x), we must prove the sequents:

    (
        Β¬(βˆƒ((x: T) => P(x)))
    )
⊒
    (
        βˆ€((x: T) => Β¬P(x))
    )

and

    (
        βˆ€((x: T) => Β¬P(x))
    )
⊒
    (
        Β¬(βˆƒ((x: T) => P(x)))
    )

We prove both directions below:

    (
        Β¬(βˆƒ((x: T) => P(x)))
    )
⊒
    (
        βˆ€((x: T) => Β¬P(x))
    )
Proof(
    1 (     Β¬(βˆƒ((x: T) => P(x)))        ) by Premise,

    2 Let ( (a: T) => SubProof(

        3 SubProof(
            4 Assume (  P(a)  ),
            5 (     βˆƒ((x: T) => P(x))   ) by ExistsI[T](3),
            6 (     F                   ) by NegE(4, 1)
        ),
        7 (     Β¬P(a)                   ) by NegI(3)

    )),
    8 (  βˆ€((x: T) => Β¬P(x))             ) by AllI[T](2)
)

And:

    (
        βˆ€((x: T) => Β¬P(x))
    )
⊒
    (
        Β¬(βˆƒ((x: T) => P(x)))
    )
Proof(
    1 (     βˆ€((x: T) => Β¬P(x))          )   by Premise,

    2 SubProof(
        3 Assume (  βˆƒ((x: T) => P(x))   ),

        4 Let ( (a: T) => SubProof(
            5 Assume (  P(a)  ),
            6 (     Β¬P(x)               )   by AllE[T](1),
            7 (     F                   )   by NegE(5, 6),
        )),
        8 (     F                       )   By ExistsE[T](3, 4)
    
    ),
    9 (     Β¬(βˆƒ((x: T) => P(x)))        )   by NegI(2)
)

More extensive list of equivalences

Here is a more extensive list of equivalences in predicate logic. The remaining proofs are left as exercises for the reader:

  • Β¬(βˆƒ x P(x)) is equivalent to βˆ€ x Β¬P(x)
  • Β¬(βˆ€ x P(x)) is equivalent to βˆƒ x Β¬P(x)
  • βˆ€ x (P(x) β†’ Β¬Q(x)) is equivalent to Β¬(βˆƒ x P(x) ∧ Q(x))
  • βˆ€ x βˆ€ y P(x, y) is equivalent to βˆ€ y βˆ€ x P(x, y)
  • βˆƒ x βˆƒ y P(x, y) is equivalent to βˆƒ y βˆƒ x P(x, y)
  • Q ∧ (βˆ€ x P(x)) is equivalent to βˆ€ x (Q ∧ P(x)) (where x does not appear in Q)
  • Q v (βˆ€ x P(x)) is equivalent to βˆ€ x (Q V P(x)) (where x does not appear in Q)
  • Q ∧ (βˆƒ x P(x)) is equivalent to βˆƒ x (Q ∧ P(x)) (where x does not appear in Q)
  • Q V (βˆƒ x P(x)) is equivalent to βˆƒ x (Q V P(x)) (where x does not appear in Q)

Summary and Strategies

In this section, we summarize all available rules in propositional logic, and discuss strategies for approaching proofs.

Rules with universal quantifier (βˆ€)

Rule summaries:

           βˆ€ ((x: T) => P(x))
AllE[T]:  ---------------------
                   P(v)     where v is a particular individual in the domain (i.e, v has type T)
            Let (   (a: T) => SubProof(
                ... 
                P(a)  
            )),
AllI[T] : -------------------------------
                 βˆ€ ((x: T) => P(x)) 

Rule syntax summaries:

( 
    ...
    r (     βˆ€ ((x: T) => P(x))      )   by SomeJustification,
    s (     P(v)                    )   by AllE[T](r),      //where v has been previously shown to have type T    
    ...
)
( 
    ...
    r Let (  (a: T) => SubProof(    //where a is a fresh, previously unused, individual
        ...
        t (     P(a)            )   by SomeJustification
    )),
    u (     βˆ€ ((x: T) => P(x))  )   by AllI[T](r),
)

Rules with existential quantifier (βˆƒ)

Rule summaries:

                   P(d)         where  d  is an individual of type T
ExistsI[T]: ---------------------
              βˆƒ((x: T) => P(x))
                                        Let ((a: T) => SubProof(          // where  a  is a new, fresh name
                                             Assume( P(a) ),              // a  MUST NOT appear in  Q
                βˆƒ((x: T) => P(x))            ...
                                             Q         
                                        )),             
ExistsE[T]: ----------------------------------------------------
                     Q

Rule syntax summaries:

(
    ...
    r (     P(d)                )   by SomeJustification,   //where d has been shown to have type T
    s (     βˆƒ((x: T) => P(x))   )   by ExistsI[T](r),
    ...
)
(
    ...
    b (     βˆƒ((x: T) => P(x))       )   by SomeJustification,
    c Let ( (a: T) => SubProof(     //where a is a previously unused individual
        d Assume(  P(a)  ),
        ...
        f (     Q                   )   by SomeJustification    //where a does NOT appear in Q
    )),
    g (     Q                       )   by ExistsE[T](b, c),
    ...
)

Reminder: propositional logic rules are still available

When doing proofs in predicate logic, remember that all the deduction rules from propositional logic are still available. You will often want to use the same strategies we saw there – not introduction to prove a NOT, implies introduction to create an implies statement, OR elimination to process an OR statement, etc.

However, keep in mind that propositional logic rules can only be used on claims without quantifiers as their top-level operator. For example, if we have the statement βˆ€ ( x: T) => (S(x) ∧ Pz(x)) ), then we cannot use AndE – the top-level operator is a universal quantifier, and the ∧ statement is “bound up” in that quantifier. We would only be able to use AndE after we had used AllE[T] to eliminate the quantifier.

Strategies

  1. Write down all premises first. Can you extract anything from the premises?

    • If you have a for-all statement and an available individual, use AndE[T] to plug that individual into the for-all statement.
    • If you have p∧q, use AndE1 to extract p by itself and then AndE2 to extract q by itself.
    • If you have p β†’: q and p, use ImplyE to get q.
    • If you have p and Β¬p, use NegE to claim a contradiction, F.
  2. Look at the top-level operator of what you are trying to prove.

    • Are you trying to prove something of the form βˆ€ ((x: T) => P(x))?

      • Use AllI[T]. Open a subproof, introduce a fresh a, and get to P(a) by the end of the subproof. After the subproof, use AllI[T] to conclude βˆ€ ((x: T) => P(x)).
    • Are you trying to prove something of the form βˆƒ((x: T) => P(x))?

      • You will often have another there-exists (βˆƒ) statement available as a premise or previous claim. Open a subproof, and assume an alias for the individual in your there-exists statement. Get to βˆƒ((x: T) => P(x)) by the last line of the subproof. After the subproof, use ExistsE[T] to restate βˆƒ((x: T) => P(x)).
    • Are you trying to prove something of the form p β†’: q?

      • Use ImplyI. Open a subproof, assume p, and get to q by the end of the subproof. After the subproof, use ImplyI to conclude p β†’: q.
    • Are you trying to prove something of the form Β¬p?

      • Use NegI. Open a subproof, assume p, and get a contradiction, F, by the end of the subproof. After the subproof, use NegI to conclude Β¬p.
    • Are you trying to prove something of the form p ∧ q?

      • Try to prove p by itself and then q by itself. Afterward, use AndI to conclude p ∧ q.
    • Are you trying to prove something of the form p ∨ q?

      • See if you have either p or q by itself – if you do, use either OrI1 or OrI2 to conclude p ∨ q.
  3. You’ll need to nest the approaches from step 2. Once you are in a subproof, think about what you are trying to prove by the end of that subproof. Follow the strategy in step 2 to prove your current goal, nesting subproofs as needed. As you work, stop and scan the claims that you have available. See if you can extract anything from them as you did for the premises in step 1.

  4. No match, or still stuck?

    • Do you have a there-exists statement available? Try using ExistsE[T] to reach your goal.
    • Do you have an OR statement available? Try using OR elimination to prove your goal conclusion.
    • Do your statements have NOT operators, but don’t fit the form for using Β¬i? Try using PbC. If you are trying to prove something of the form p, open a subproof, assume Β¬p, and try to reach a contradiction by the end of the subproof. Afterward, use PbC to conclude p.
    • As a last resort, try pasting in the proof for the law of the excluded middle (see section 4.5). Then use OR elimination on p ∨ Β¬p.

Think of doing a proof as solving a maze, and of all our deduction rules as possible directions you can turn. If you have claims that match a deduction rule, then you can try applying the rule (i.e, “turning that direction”). As you work, you may apply more and more rules until the proof falls into place (you exit the maze)…or, you might get stuck. If this happens, it doesn’t mean that you have done anything wrong – it just means that you have reached a dead end and need to try something else. You backtrack, and try a different approach instead (try turning in a different direction).

Soundness and Completeness

Soundness and completeness definitions

We now revisit the notions of soundness and completeness. We recall from propositional logic that a proof system is sound if everything that is provable is actually true. A proof system is complete if everything that is true can be proved.

Interpretations

When we write statements in logic, we use predicates and function symbols (e.g., βˆ€ i (i * 2) > i). An interpretation gives the meaning of:

  • The underlying domain – what set of elements it names

  • Each function symbol – what answers it computes from its parameters from the domain

  • Each predicate – which combinations of arguments from the domain lead to true answers and false answers

Interpretation example - integers

Here is an example. Say we have the function symbols: +, -, *, and /, and the predicate symbols: > and =. What do these names and symbols mean? We must interpret them.

The standard interpretation of arithmetic is that:

  • int names the set of all integers

  • +, -, *, and / name the integer addition, subtraction, multiplication, and division functions (that take two integers as “parameters” and “return” an integer result)

  • = and > name integer equality comparison and integer less-than comparison predicates (that take two integers as “parameters” and “return” the boolean result of the comparison)

With this interpretation of arithmetic, we can interpret statements. For example,βˆ€ i (i * 2) > i interprets to false, as when i is negative, then i * 2 < i. Similarly, βˆƒ j (j * j) = j interprets to true, as 1 * 1 = 1.

Now, given the function names +, -, *, /, and the predicates, =, >, we can choose to interpret them in another way. For example, we might interpret the underlying domain as just the nonnegative integers. We can interpret +, *, /, >, = as the usual operations on ints, but we must give a different meaning to -. We might define m - n == 0, whenever n > m.

Yet another interpretation is to say that the domain is just {0, 1}; the functions are the usual arithmetic operations on 0 and 1 under the modulus of 2. For example, we would define 1 + 1 == 0 because (1 + 1) mod 2 == 0. We would define 1 > 0 as true and any other evaluation of < as false.

These three examples show that the symbols in a logic can be interpreted in multiple different ways.

Interpretation example - predicates

Here is a second example. There are no functions, and the predicates are IsMortal(_), IsLeftHanded(_) and IsMarriedTo(,). An interpretation might make all (living) members of the human race as the domain; make IsMortal(h) defined as true for every human h; make IsLeftHanded(j) defined as true for exactly those humans, j, who are left handed; and set IsMarriedTo(x, y) as true for all pairs of humans (x, y) who have their marriage document in hand.

We can ask whether a proposition is true within ONE specific interpretation, and we can ask whether a proposition is true within ALL possible interpretations. This leads to the notions of soundness and completeness for predicate logic.

Valid sequents in predicate logic

A sequent, P_1, P_2, ..., P_n ⊒ Q is valid in an interpretation, I, provided that when all of P_1, P_2, …, P_n are true in interpretation I, then so is Q. The sequent is valid exactly when it is valid in ALL possible interpretations.

Soundness and completeness in predicate logic

We can then define soundness and completeness for predicate logic:

soundness: When we use the deduction rules to prove that P_1, P_2, ..., P_n ⊒ Q, then the sequent is valid (in all possible interpretations)

completeness: When P_1, P_2, ..., P_n ⊒ Q is valid (in all possible interpretations), then we can use the deduction rules to prove the sequent.

Note that, if P_1, P_2, ..., P_n ⊒ Q is valid in just ONE specific interpretation, then we are not guaranteed that our rules will prove it. This is a famous trouble spot: For centuries, mathematicians were searching for a set of deduction rules that could be used to build logic proofs of all the true propositions of arithmetic, that is, the language of int, +, -, *, /, >, and =. No appropriate rule set was devised.

In the early 20th century, Kurt GΓΆdel showed that it is impossible to formulate a sound set of rules customized for arithmetic that will prove exactly the true facts of arithmetic. GΓΆdel showed this by formulating true propositions in arithmetic notation that talked about the computational power of the proof rules themselves, making it impossible for the proof rules to reason completely about themselves. The form of proposition he coded in logic+arithmetic stated “I cannot be proved”. If this proposition is false, it means the proposition can be proved. But this would make the rule set unsound, because it proved a false claim. The only possibility is that the proposition is true (and it cannot be proved). Hence, the proof rules remain sound but are incomplete.

GΓΆdel’s construction, called diagonalization, opened the door to the modern theory of computer science, called computability theory, where techniques from logic are used to analyze computer programs. You can study these topics more in CIS 570 and CIS 575.

Computability theory includes the notion of decidability – a problem that is decidable CAN be solved by a computer, and one that is undecidable cannot. A famous example of an undecidable problem is the Halting problem: given an arbitrary computer program and program input, can we write a checker program that will tell if the input program will necessarily terminate (halt) on its input? The answer is NO - the checker wouldn’t work on itself.