An Athena tutorial. Konstantine Arkoudas

Similar documents
CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Chapter p. 1/27

CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Sections p.

Proving Theorems with Athena

Semantics via Syntax. f (4) = if define f (x) =2 x + 55.

CSC 501 Semantics of Programming Languages

Programming Languages Third Edition

A computer implemented philosophy of mathematics

Induction and Semantics in Dafny

Introduction to dependent types in Coq

Formal Methods of Software Design, Eric Hehner, segment 1 page 1 out of 5

Topic 3: Propositions as types

AXIOMS FOR THE INTEGERS

Part I Logic programming paradigm

SOFTWARE ENGINEERING DESIGN I

STABILITY AND PARADOX IN ALGORITHMIC LOGIC

Overview. CS389L: Automated Logical Reasoning. Lecture 6: First Order Logic Syntax and Semantics. Constants in First-Order Logic.

3.7 Denotational Semantics

CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Chapter 11 p. 1/38

Goals: Define the syntax of a simple imperative language Define a semantics using natural deduction 1

Lecture 5. Logic I. Statement Logic

CS Bootcamp Boolean Logic Autumn 2015 A B A B T T T T F F F T F F F F T T T T F T F T T F F F

Chapter 3. Set Theory. 3.1 What is a Set?

Definition: A context-free grammar (CFG) is a 4- tuple. variables = nonterminals, terminals, rules = productions,,

Lecture 3: Recursion; Structural Induction

Outcome-Oriented Programming (5/12/2004)

Automated Reasoning. Natural Deduction in First-Order Logic

CSE 20 DISCRETE MATH. Winter

CSE 20 DISCRETE MATH. Fall

Module 6. Knowledge Representation and Logic (First Order Logic) Version 2 CSE IIT, Kharagpur

Polymorphic lambda calculus Princ. of Progr. Languages (and Extended ) The University of Birmingham. c Uday Reddy

1. true / false By a compiler we mean a program that translates to code that will run natively on some machine.

First Order Predicate Logic CIS 32

CS4215 Programming Language Implementation. Martin Henz

Foundations of AI. 9. Predicate Logic. Syntax and Semantics, Normal Forms, Herbrand Expansion, Resolution

CS103 Spring 2018 Mathematical Vocabulary

To prove something about all Boolean expressions, we will need the following induction principle: Axiom 7.1 (Induction over Boolean expressions):

Section 2.4: Arguments with Quantified Statements

Introduction to Automata Theory. BİL405 - Automata Theory and Formal Languages 1

Propositional Logic Formal Syntax and Semantics. Computability and Logic

Propositional Logic. Part I

Reasoning About Programs Panagiotis Manolios

Recursively Enumerable Languages, Turing Machines, and Decidability

CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Section 17.2

RSL Reference Manual

6.001 Notes: Section 15.1

1.3. Conditional expressions To express case distinctions like

Operational Semantics

This is already grossly inconvenient in present formalisms. Why do we want to make this convenient? GENERAL GOALS

if s has property P and c char, then c s has property P.

3.4 Deduction and Evaluation: Tools Conditional-Equational Logic

CSL105: Discrete Mathematical Structures. Ragesh Jaiswal, CSE, IIT Delhi

Z Notation. June 21, 2018

(Refer Slide Time: 4:00)

P Is Not Equal to NP. ScholarlyCommons. University of Pennsylvania. Jon Freeman University of Pennsylvania. October 1989

First-Order Logic PREDICATE LOGIC. Syntax. Terms

This book is licensed under a Creative Commons Attribution 3.0 License

A Small Interpreted Language

3 Pairs and Lists. 3.1 Formal vs. Informal Proofs

Intro to semantics; Small-step semantics Lecture 1 Tuesday, January 29, 2013

Lecture Notes on Contracts

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

THREE LECTURES ON BASIC TOPOLOGY. 1. Basic notions.

Introduction to Homotopy Type Theory

To prove something about all Boolean expressions, we will need the following induction principle: Axiom 7.1 (Induction over Boolean expressions):

CS 161 Computer Security

Mathematical Logic Prof. Arindama Singh Department of Mathematics Indian Institute of Technology, Madras. Lecture - 37 Resolution Rules

Intro. Scheme Basics. scm> 5 5. scm>

6.001 Notes: Section 8.1

CMPSCI 250: Introduction to Computation. Lecture #7: Quantifiers and Languages 6 February 2012

Workbook Unit 13: Natural Deduction Proofs (IV)

CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Section 17.1

2 Introduction to operational semantics

Lecture 5: Predicate Calculus. ffl Predicate Logic ffl The Language ffl Semantics: Structures

Semantics. A. Demers Jan This material is primarily from Ch. 2 of the text. We present an imperative

14.1 Encoding for different models of computation

LOGIC AND DISCRETE MATHEMATICS

c constructor P, Q terms used as propositions G, H hypotheses scope identifier for a notation scope M, module identifiers t, u arbitrary terms

Coq quick reference. Category Example Description. Inductive type with instances defined by constructors, including y of type Y. Inductive X : Univ :=

15-819M: Data, Code, Decisions

HOL DEFINING HIGHER ORDER LOGIC LAST TIME ON HOL CONTENT. Slide 3. Slide 1. Slide 4. Slide 2 WHAT IS HIGHER ORDER LOGIC? 2 LAST TIME ON HOL 1

Lecture 6,

Propositional Logic. Andreas Klappenecker

Basic concepts. Chapter Toplevel loop

Mathematically Rigorous Software Design Review of mathematical prerequisites

Bootcamp. Christoph Thiele. Summer An example of a primitive universe

Typed Lambda Calculus

6.001 Notes: Section 6.1

Appendix 1. Description Logic Terminology

Appendix 1. Description Logic Terminology

1 Introduction. 3 Syntax

Warm-Up Problem. Let L be the language consisting of as constant symbols, as a function symbol and as a predicate symbol. Give an interpretation where

Consider a description of arithmetic. It includes two equations that define the structural types of digit and operator:

ELEMENTARY NUMBER THEORY AND METHODS OF PROOF

Module 6. Knowledge Representation and Logic (First Order Logic) Version 2 CSE IIT, Kharagpur

Formal Predicate Calculus. Michael Meyling

Lecture 5: The Halting Problem. Michael Beeson

CIS 194: Homework 8. Due Wednesday, 8 April. Propositional Logic. Implication

CS 6110 S14 Lecture 1 Introduction 24 January 2014

CS233:HACD Introduction to Relational Databases Notes for Section 4: Relational Algebra, Principles and Part I 1. Cover slide

Resolution (14A) Young W. Lim 6/14/14

Transcription:

An Athena tutorial Konstantine Arkoudas March 29, 2005

Chapter 1 Preliminaries 1.1 What is Athena? Athena is a new language that integrates computation and deduction. As a programming language, Athena is a higher-order dynamically typed functional programming language with side effects, similar to Scheme. As a logic tool, Athena is a proof checker for a novel formulation of Fitch-style natural deduction for first-order logic with equality, sorts, and polymorphism; and an interactive theorem proving system for discovering theorems. It incorporates facilities for high-performance automated theorem proving and for model generation. It has a rich and fluid language for writing tactics for proof search, and supports inductive reasoning over arbitrary first-order datatypes. This tutorial is preliminary and far from exhaustive. It describes only those aspects of the language that a complete newcomer would need to know in order to start doing non-trivial proofs fairly quickly. By the end of the tutorial, you should be able to do some pretty interesting proofs in Athena, including inductive proofs over structures such as numbers, lists, and trees. To report errors or to make comments, please email me at konstantine@alum.mit.edu. 1.2 Interacting with Athena Athena can be used either in batch mode or interactively. The interactive mode is used in most cases. It consists of a read-eval-print loop similar to that used by other functional and logic programming languages (Scheme, ML, Prolog, etc.). The user enters some input in response to the Athena prompt >, Athena evaluates that input, displays the result, and the process is repeated. The user can quit at any time by typing quit at the prompt. Typing directly at the prompt all the time is tiresome. It is often more convenient to edit all the desired Athena text (declarations, definitions, assertions, proofs, etc.) into a file, say foo.ath, and then have Athena read the contents of that file at once, processing the inputs sequentially from the top of the file to bottom as if they had been entered directly at the prompt. This can be done with the load-file command. Typing (load-file "foo.ath") at the Athena prompt will process foo.ath in that manner. Note that load-file commands can themselves appear inside files. If the command (load-file "groups.ath") 1

was encountered while loading foo.ath, Athena would proceed to load groups.ath and then return to loading foo.ath, resuming at the point immediately after the (load-file "groups.ath") command. 1.3 Domains, terms, and propositions 1.3.1 Domains A universe of discourse is introduced with a domain declaration. The syntax is (domain I), for any identifier I. 1 Here is an example: >(domain Person) New domain Person introduced. Athena responds by confirming that a new domain named Person has been introduced. If the user attempts to reintroduce the same domain later on, Athena will issue a warning reminding the user that the domain already exists. Multiple domains can be introduced in a single line with the keyword domains. For instance, the following introduces a domain for rational numbers, a domain Element of individuals, and a domain Set intended to represent sets of objects from Element. >(domains Rational Element Set) New domain Rational introduced. New domain Element introduced. New domain Set introduced. There are some domains that are predefined in Athena. Boolean is the most important of them. 2 1.3.2 Function symbols Once a domain has been introduced we can go ahead and declare function symbols, for instance: >(declare father (-> (Person) Person)) New symbol father declared. This simply says that father denotes an operation (function) that takes a person and produces another person. We refer to the expression (-> (Person) Person) as the signature of father. Nothing else is known about father at this point, only its signature. Any identifier can be used as a function symbol, including non-alphanumeric strings, e.g.: 1 An identifier in Athena is any non-empty string of printable characters (i.e., with ASCII codes ranging from 33 to 126) that satisfies the following constraints: (a) The first character can be anything except these fourteen characters:! " # $ ( ), : ;? [ ] (b) It does not contain any of the following seven characters: " # ), : ; ] 2 Boolean is actually a special type of domain: a datatype. Those are discussed in Section 4.1. 2

>(declare + (-> (Rational Rational) Rational)) New symbol + declared. The general syntax form for a function symbol declaration is (declare f (-> (D 1 D n ) D)) where f is an identifier and the D i and D are domains, n 0. We refer to D 1 D n as the input domains of f, and to D as the result domain, or as the range of f. The number of input domains, n, is the arity of f. Function symbols must be unique, so they cannot be redeclared. In particular, there is no overloading. A function symbol of arity zero is called a constant symbol. A constant symbol c of domain D can be introduced simply by writing (declare c D), instead of (declare c (-> () D)). The two forms are equivalent, though the first is more convenient. Example: >(declare joe Person) New symbol joe declared. >(declare zero Rational) New symbol zero declared. >(declare null Set) New symbol null declared. There are several built-in constant symbols in Athena. Two of them are true and false, both of which are elements of the built-in domain Boolean. Relations are simply functions whose range is Boolean. For instance: >(declare <= (-> (Rational Rational) Rational)) New symbol <= declared. >(declare member (-> (Element Set) Boolean)) New symbol member declared. Here <= stands for a function that maps any two Rational numbers to true or false, according to whether or not the first number is less than or equal to the second (assuming that we have this standard interpretation of <= in mind). Therefore, we can think of <= as a binary predicate on the domain Rational the usual less-than-or-equal-to relation. Likewise, member is a binary relation that holds between a given Element and a given Set iff the first is a member of the second. We also introduce two relation symbols empty? and subset with the obvious intended interpretations: >(declare empty? (-> (Set) Boolean)) New symbol empty? declared. 3

>(declare subset (-> (Set Set) Boolean)) New symbol subset declared. For brevity, multiple function symbols that share the same signature can be declared in a single line by listing them within parentheses: (declare (f 1 f n ) (-> (D 1 D n ) D)) For example: >(declare (male female) (-> (Person) Boolean)) New symbol male declared. New symbol female declared. >(declare (union intersection) (-> (Set Set) Set)) New symbol union declared. New symbol intersection declared. Multiple constant symbols of the same domain can also be likewise introduced: >(declare (ann peter sue) Person) New symbol ann declared. New symbol peter declared. New symbol sue declared. Some function symbols are built-in. One of them is the binary equality symbol =, which takes any two objects of the same domain D and returns a Boolean. D can be arbitrary. 3 1.3.3 Terms A term is a syntactic object that represents an element of some domain. The simplest type of term is a constant symbol. For instance, assuming the declarations of the previous section, if we type joe at the Athena prompt, Athena will recognize the input as a term: >joe Term: joe 3 More precisely, = is a polymorphic function symbol. We discuss those in Section??. 4

A variable is also a term it denotes an indeterminate individual in some domain. Variables are of the form?i, for any identifier I. 4 The following are all legal variables:?x,?foo-bar,?v_1,?789,?@sd%&. There is no restriction on the length of a variable, and very few restrictions on the kind of characters that can appear inside a variable. Constant symbols and variables serve as the primitive building blocks of terms. More complex terms can be formed by applying a function symbol f to n given terms t 1 t n, where n is the arity of f. Such an application is written in prefix form as (f t 1 t n ). For instance, the following are all legal terms: 1. (father joe) 2. (+?m?n) 3. (father (father joe)) 4. (= peter (father joe)) 5. (male (father joe)) 6. (<= zero (+ zero?n)) 7. (= (member?x null) (male ann)) 8. (subset?s1 (union?s1?s2)) Every term is of a certain sort. The sort of (father joe), for example, is Person; the sort of (+ zero?n) is Rational; and so on. In general, the sort of a term (f t 1 t n) is D, where D is the range of f. Given an interpretation of the various domains and function symbols, a term designates an element of its sort. For example, given the expected interpretation of the domain Person, the function symbol father, etc., the term (father joe) would designate the father of the person named joe. The term (male (father joe)) designates true, etc. If a term contains variables then it does not designate any specific individual, unless we explicitly assign denotations to all the variables. For instance, we do not know what (+ zero?n) is, since we do not know what?n stands for. A term that does not contain any variables is called ground. Ground terms always denote domain elements (again, with respect to a given interpretation). Some terms are ill-sorted, e.g., (father zero). This is a type error (only we speak of sorts instead of types), because the function symbol father requires an argument from the Person domain and we are applying it to an Rational instead. Athena performs sort-checking automatically, and will detect and report any ill-sorted terms as errors: >(+ zero joe) Error, top level, 1.1: Ill-sorted term: (+ zero joe). Here 1.1 indicates line 1, column 1, the precise position where the offending term was located; and top level means that the input was entered directly into the Athena promt. If the term (+ zero joe) had been read in batch mode from a file foo.ath instead, and the term was found, say, on line 279, column 35, the message would have been: Error, foo.ath, 279.35: Ill-sorted term: (+ zero joe). The user does not need to declare the sorts of variables explicitly. Athena infers them automatically. For instance, it is not necessary to write something like (+ zero?n:rational); we just write (+ zero?n). Athena will realize that the sort of?n must be Rational for this term to be well-sorted. 4 Actually,?I is an abbreviation for the built-in syntax form (var I). 5

1.3.4 Propositions Propositions are the bread and butter of Athena. Every successful proof derives a proposition. Propositions make statements about relationships that may (or may not) hold amongst elements of various sorts. There are three types of propositions: 1. Atomic propositions, or just atoms. Those are simply terms of sort Boolean. Examples are (male joe), (<= zero zero), (subset?s1 (union?s1?s2)), and (= peter (father ann)). 2. Sentential combinations, obtained from other propositions through one of the five sentential connectives: not, and, or, if, and iff. Those have the expected interpretations: (not P ) negates proposition P ; (and P Q) expresses the conjunction of P and Q; (or P Q) expresses their alternation (disjunction); (if P Q) expresses the material conditional if P then Q; and (iff P Q) expresses the equivalence P if and only if Q. 3. Quantified propositions. There are two main quantifiers in Athena, forall and exists. A quantified proposition is of the form (q x P ) where q is a quantifier (either forall or exists), x is a variable, and P is a proposition the body of the quantification. An example: (forall?n (= (+?n zero)?n)) A proposition of the form (forall x P ) says that P holds for every element x (of a certain sort), while (exists x P ) says that there is some object x for which P holds. The following shows what happens when the user types this proposition at the Athena prompt: >(forall?n (= (+?n zero)?n)) Proposition: (forall?n:rational (= (+?n?m)?n)) Athena acknowledges that a proposition was entered, and displays that proposition in a neat format using standard s-expression indentation. Note that the user did not have to explicitly indicate the sort of the quantified variable. Athena inferred that?n ranges over Rational, and annotated the quantified occurrence of?n in the output with that sort. As a shorthand for iterated occurrences of the same quantifier, the user may enter propositions of the form (q x 1 x n P ) for a quantifier q and any number n > zero of variables x 1 x n. For instance: >(forall?n?m (= (+?n?m) (+?m?n))) Proposition: (forall?n:rational (forall?m:rational (= (+?n?m) (+?m?n)))) A similar shorthand exists for the sentential connectives and and or. Both of these can take an arbitrary number n > zero of arguments: (and P 1 P n ) and (or P 1 P n ). For example: 6

>(and (empty? null) (male (father joe)) (= (+?n zero)?n)) Proposition: (and (empty? null) (male (father joe)) (= (+?n zero)?n)) Free and bound variable occurrences are defined as usual. 5 Variables with free occurrences must have consistent sorts across a given proposition. For instance, (and (<= zero?n) (=?n (+?m1?m2))) is legal, but (and (male?n) (=?n (+?m1?m2))) is not, and would generate an error. However, bound variable occurrences can have different sorts in the same proposition: >(and (forall?x (male (father?x))) (forall?x (<=?x (+?x?x)))) Proposition: (and (forall?x:person (male (father?x))) (forall?x:rational (<=?x (+?x?x)))) Intuitively, this is because the specific name of a bound variable is immaterial. For instance, there is no real difference between (forall?x (male (father?x))) and (forall?p (male (father?p))) Both propositions say the exact same thing, even though one of them uses?x as a bound variable and the other uses?p. We say that the two propositions are alphabetically equivalent. This means that each can be obtained from the other by consistently renaming bound variables. Alphabetically equivalent propositions are essentially identical, and indeed we will see later on that Athena treats them as such for deduction purposes. 1.4 Definitions The ability to abbreviate a complex object by giving it a name and then subsequently referring to it by that name is crucial for managing complexity. There are several naming mechanisms in Athena. One of the most useful is the top-level directive define. The general syntax form for it is (define I F ) where I is any identifier (name) and F is a phrase denoting the object that we want to define. Once a definition has been made, the defined object can be referred to by its name: >(define P (forall?s (subset?s?s))) Proposition P defined. >(define Q (forall?x (exists?y (and (<=?x?y) 5 Refer, for instance, to The Logic Book [3]. 7

Proposition Q defined. >(and P Q) (not (=?x?y)))))) Proposition: (and (forall?s:set (subset?s?s)) (forall?x:rational (exists?y:rational (and (<=?x?y) (not (=?x?y)))))) Athena has lexical scoping. New definitions override older ones: >(define t joe) Term t defined. >t Term: joe >(define t (+ zero zero)) Term t defined. >t Term: (+ zero zero) We stress that define is a top-level directive, not a procedure. A define can only appear at the top level by itself, i.e., typed directly in response to Athena s input prompt. It cannot be nested inside other code. So something like (let ((s null)) (define P (empty? s))) is a syntax error that would be rejected by the Athena parser. 1.5 Assumption bases Athena maintains a global set of propositions called the assumption base. We can think of the elements of the assumption base as our premises propositions that we regard as true. Initially the system starts with the empty assumption base. Every time an axiom is postulated or a theorem is proved, the corresponding proposition is inserted into the assumption base. The assumption base can be inspected with the built-in procedure 6 show-assumption-base. It does not take any arguments, so it is invoked as (show-assumption-base). When Athena is first started, the assumption base is empty: >(show-assumption-base) 6 Procedures are discussed in the second part of the tutorial. 8

The assumption base is currently empty. Unit: () A proposition can be inserted in the assumption base with the top-level directive assert: >(assert (= (father ann) joe)) The proposition (= (father ann) joe) has been added to the assumption base. Unit: () The above assertion postulated the proposition that the father of ann is joe. We can verify that the proposition was indeed added to the assumption base by invoking show-assumption-base again: >(show-assumption-base) There is one proposition in the current assumption base: (= (father ann) joe) Unit: () Multiple propositions can be asserted at the same time; the general syntax form is (assert P 1 P n ): >(assert (forall?x (male (father?x))) (forall?n (exists?m (and (<=?n?m) (not (=?n?m)))))) The proposition (forall?x:person (male (father?x))) has been added to the assumption base. The proposition (forall?n:rational (exists?m:rational (and (<=?n?m) (not (=?n?m))))) has been added to the assumption base. >(show-assumption-base) There are 3 propositions in the current assumption base: 9

(= (father ann) joe) (forall?x:person (male (father?x))) (forall?n:rational (exists?m:rational (and (<=?n?m) (not (=?n?m))))) Unit: () Lists of propositions can also appear as arguments to assert. We will have more to say about lists later on. For now it suffices to say that a list of n zero values V 1 V n can be formed simply by enclosing the values inside square brackets: [V 1 V n ]. (For the time being a value will mean a term or a proposition, or perhaps another list). For instance: >[joe ann] List: [joe ann] >[] List: [] >(define L [joe (father ann) (forall?n (<=?n (+?n zero))) []]) List L defined. >L List: [joe (father ann) (forall?n (<=?n (+?n zero))) []] Note that Athena lists, like those of Scheme (but unlike those of ML or Haskell) can be heterogeneous: elements of different types can appear in the same list. A list of axioms can be introduced, given a name, and then asserted by that name. For instance: >(define father-facts [(= (father ann) joe) (= (father sue) peter) (= (father peter) joe)]) List father-facts defined. >(assert father-facts) The proposition (= (father ann) joe) 10

has been added to the assumption base. The proposition (= (father sue) peter) has been added to the assumption base. The proposition (= (father peter) joe) has been added to the assumption base. There are also two mechanisms for removing propositions from the global assumption base: clear-assumption-base and retract. The former will delete every element of the assumption base, while the second will remove a single specified proposition from it: >clear-assumption-base Assumption base cleared, blank-slate state. >(show-assumption-base) The assumption base is currently empty. Unit: () >(assert (male joe)) The proposition (male joe) has been added to the assumption base. >(show-assumption-base) There is one proposition in the current assumption base: Proposition: (male joe) Unit: () >(retract (male joe)) The proposition (male joe) has been removed from the assumption base. >(show-assumption-base) 11

The assumption base is currently empty. Unit: () Like define, the forms assert, clear-assumption-base and retract are top-level directives; they cannot appear inside other code. 12

Chapter 2 Proofs 2.1 Primitive methods The simplest type of proof is a single application of an inference rule. Inference rules in Athena are called methods. Athena comes with a small collection of predefined methods the so-called primitive methods. We will see later that users can define their own methods. A method application is of the form (!E F 1 F n ), where E is an expression denoting a method and F 1 F n are the arguments supplied to the method. Perhaps the simplest primitive method is claim, a unary reiteration method that takes an arbitrary proposition P as its sole argument. If P is in the assumption base, then claim simply returns P (i.e., it reiterates P ); otherwise, if P is not in the current a.b., then claim reports an error. Suppose, for example, that the current assumption base contains the proposition (male joe) but does not contain the proposition (female ann). Then here is what will happen if we try to claim these propositions: >(!claim (male joe)) Theorem: (male joe) >(!claim (female ann)) Error, top level, 1.9: Failed application of claim---the proposition (female ann) is not in the assumption base. The first claim succeeds, but the second fails. Note that Athena reports the precise position of the failed claim (line 1, column 9 of the input stream). Also note that Athena pronounces the successful claim a theorem. In fact every time a proof is successfully evaluated at the top level, Athena refers to the resulting proposition as a theorem. There is a reason for this: It can be proved formally that if an Athena proof produces a proposition P in the context of an assumption base β, then P is a logical consequence of β. This is the main soundness guarantee provided by Athena, and it is the sense in which the result of a proof is understood to be a theorem. One question about claim that comes up sometimes is this: If a proposition P is in the assumption base and we try to claim P, where P is a variant of P that is logically equivalent to P but is not itself in the assumption base, will the claim succeed? The answer is no. An application (!claim P ) succeeds if and only if P itself, as a syntactic object, is in the assumption base. For instance, 13

suppose that P is the proposition (male joe) and P is (and true (male joe)), where P is in the assumption base but P is not. Then (!claim P ) will succeed, but (claim P ) will fail, even though P is logically equivalent to P. There is a reason for this too: The problem of deciding whether two propositions are logically equivalent is very difficult. If fact it is undecidable, meaning that there is no algorithm that can solve every instance the problem. However, claim, like all other primitive Athena methods, determines propositional identity up to alphabetic equivalence. E.g., if P is (forall?x (male (father?x))) and P is (forall?y (male (father?y))) then (!claim P ) will succeed if and only if (!claim P ) suceeds: >clear-assumption-base Assumption base cleared, blank-slate state. >(assert (forall?x (male (father?x)))) The proposition (forall?x:person (male (father?x))) has been added to the assumption base. >(!claim (forall?foo (male (father?foo)))) Theorem: (forall?foo:person (male (father?foo))) All of the remaining primitive methods can be classified as either introduction or elimination rules for one of the sentential connectives or quantifiers. That is, an application of a primitive method M either produces a proposition of the form ( ) for {not, and, or, if, iff, forall, exists}, in which case we say that M is an introduction method for ; or else it takes such a proposition as an input premise and produces a part of it as its conclusion, in which case we say that M is an elimination method for. Consider, for instance, conjunctions of the form (and P 1 P 2 ). There are two elimination methods for conjunctions, left-and and right-and. The former will produce P 1, the left part of the conjunction, while the latter will produce P 2, the right part. Specifically, left-and is a unary primitive method that takes a conjunction (and P 1 P 2 ) as its sole argument. If the conjunction is in the current assumption base, then the application (!left-and (and P 1 P 2 )) will produce P 1 as the result; otherwise it will fail. For example: >clear-assumption-base Assumption base cleared, blank-slate state. >(define P (and (male joe) (female ann))) Proposition P defined. 14

>(assert P) The proposition (and (male joe) (female ann)) has been added to the assumption base. >(!left-and P) Theorem: (male joe) An application of left-and will fail if the given conjunction is not in the assumption base; or if the given argument is not a conjunction at all; or if the wrong number of arguments are given: >(!left-and (and true true)) Error, top level, 1.12: Failed application of left-and---the proposition (and true true) is not in the assumption base. >(!left-and (not false)) Error, top level, 1.12: Failed application of left-and---the given proposition must be a conjunction, but here it was a negation: (not false). >(!left-and true false true) Error, top level, 1.1: Wrong number of arguments (3) given to left-and---exactly one argument is required. The method right-and works exactly like left-and, except that it produces the right component of the given conjunction. It is instructive to compare Athena s formulation of these inference rules with a more conventional presentation. For instance, the left conjunction-elimination rule is usually depicted graphically as follows: P Q P This says that if the premise P Q above the horizontal line has already shown to be a theorem (where theoremhood is signified by the turnstile ), then we may also derive P as a theorem. Or, more loosely, if we already know that P Q holds, then we may conclude P. In the case of Athena, P Q holds boils down to no more and no less than it being in the assumption base. Therefore, the Athena semantics of left-and can be understood as saying that if (and P Q) is in the assumption base, then we may conclude P. The semantics of a proof form D can often be expressed succinctly using judgments of the form β D P, which can be read as follows: In the context of assumption base β, evaluating D produces the conclusion P. For instance, the semantics of left-and can be captured by the following rule: β {P Q} (!left-and (and P Q)) P (2.1) 15

which says that applying left-and to a conjunction of the form (and P Q) in any assumption base that contains this conjunction will result in the conclusion P. Rule (2.1) can be viewed as a pattern that gives rise to infinitely many rule instances depending on what particular values we choose to substitute for β, P, and Q. For instance, both of the following are instances of (2.1): {(and true true)} (!left-and (and true true)) true {false, (and (male joe) (female ann)))} (!left-and (and (male joe) (female ann))) (male joe) The first is obtained from (2.1) via the substitution β, P true, Q true while the second is obtained through the substitution β {false}, P (male joe), Q (female ann). The rule does not tell us what happens when the assumption base does not contain the premise (and P Q); or what happens when the argument to left-and is not of the form (and P Q); or when left-and is applied to a different number of arguments. We will make the convention that in all such cases the result will be an error token, and we will follow that convention in the sequel when we come to state similar rules for other methods. Below we list all the remaining primitive Athena methods and describe their semantics: both (conjunction introduction): This is a binary method which takes two propositions P and Q and returns the conjunction (and P Q), provided that both P and Q are in the assumption base: β {P, Q} (!both P Q) (and P Q) It is an error if either P or Q is not in the assumption base. Of course it is also an error if any other type or number of arguments are given to both. (From now on we will not bother to make this point explicitly.) mp (conditional elimimation): mp an abbreviation for modus ponens is a binary method which takes two propositions of the form (if P Q) and P as arguments. If both of these are in the assumption base, the conclusion Q is returned: β {(if P Q), Q} (!mp (if P Q) P ) Q dn (negation elimination): This is a unary method that performs double negation elimination. It takes an argument of the form (not (not P )) and produces P, provided that the premise (not (not P )) is in the assumption base: β {(not (not P ))} (!dn (not (not P ))) P either (disjunction introduction): This is a binary method which takes two propositions P and Q and returns the disjunction (or P Q), provided that at least one of them is in the assumption base. Its semantics can be expressed by the following two rules: and β {P } (!either P Q) (or P Q) β {Q} (!either P Q) (or P Q) If neither P nor Q is in the assumption base, an error is generated. 16

cd (disjunction elimination): This ternary method captures the inference rule traditionally known as constructive dilemma : If we know that either P 1 or P 2 holds and we also know that both P 1 and P 2 imply Q, then we may conclude Q. In terms of assumption bases: if the disjunction (or P 1 P 2 ) and the two conditionals (if P 1 Q) and (if P 2 Q) are in the assumption base, then the application (!cd (or P 1 P 2 ) (if P 1 Q) (if P 2 Q)) will produce the conclusion Q. More succinctly: β {(or P 1 P 2 ), (if P 1 Q), (if P 2 Q)} (!cd (or P 1 P 2 ) (if P 1 Q) (if P 2 Q)) Q equiv (biconditional introduction): This is a binary method that takes two conditionals of the form (if P Q) and (if Q P ) as arguments. Provided that both of these are in the assumption base, equiv produces the biconditional (iff P Q): β {(if P Q), (if Q P )} (!equiv (if P Q) (if Q P )) (iff P Q) left-iff (biconditional elimination): This is a binary method that takes a premise of the form (iff P Q) and returns (if P Q), provided that the given biconditional is in the assumption base: β {(iff P Q)} (!left-iff (iff P Q)) (if P Q) right-iff (biconditional elimination): Just like left-iff, but returns (if Q P ) instead: β {(iff P Q)} (!right-iff (iff P Q)) (if Q P ) absurd (negation introduction): This is a binary method that takes two propositions of the form P and (not P ) and returns false, provided that both P and (not P ) are in the assumption base: β {P, (not P )} (!absurd P (not P )) false true-intro (true introduction): This is a nullary method that introduces the atom true in every assumption base: β (!true-intro) true. uspec (universal quantifier elimination): uspec short for universal specialization is a binary method that takes a proposition of the form (forall x P ) and a term t as arguments. If the proposition is in the assumption base, then the conclusion P [x t] is produced, where P [x t] denotes the proposition obtained from P by replacing every free occurrence of x by t. It is an error if the resulting proposition is ill-sorted. β {(forall x P )} (!uspec (forall x P ) t) P [x t] egen (existential quantifier introduction): egen short for existential generalization takes a proposition of the form (exists x P ) and a term t as arguments. If the proposition P [x t] is in the assumption base, then the conclusion (exists x P ) is produced: β {P [x t]} (!egen (exists x P ) t) (exists x P ) Here t is a witness term: we know that P holds for t, therefore we may conclude that there is something for which P holds. For instance, if (male joe) is in the assumption base, then the application (!egen (exists?x (male?x)) joe) will successfully produce the conclusion (exists?x (male?x)). We know that joe is male, hence it is sound to conclude that some individual is male. 17

It should be noted that the introduction and elimination rules for conjunction and disjunction work properly even when given arbitrarily long arguments. Specifically, if P is a conjunction of the form (and P 1 P n ) for n > 2, then (!left-and P ) and (!right-and P ) will produce P 1 and (and P 2 P n ), respectively, in any assumption base containing P. Likewise, (!either P 1 P n ) will yield the disjunction (or P 1 P n ) as long as at least one P i is in the assumption base. Finally, (!cd (or P 1 P n ) (if P 1 Q) (if P n Q)) will derive the conclusion Q provided that the disjunction (or P 1 P n ) and the conditionals (if P i Q) are in the assumption base, i = 1,..., n. We have covered all of Athena s primitive methods for dealing with the sentential connectives and quantifiers. Figure 2.1 presents a summary. There are also some primitive methods for dealing with equality (recall that the equality symbol = is built-in): reflex (Reflexivity): This is a unary method that takes an arbitrary term t and produces the proposition (= t t), in any assumption base: β (!reflex t) (= t t) sym (Symmetry): This is a unary method that takes an equality (= s t) as an argument. If the proposition (= s t) is in the assumption base, then the conclusion (= t s) is produced: β {(= s t)} (!sym (= s t)) (= t s) tran (Transitivity): This is a binary method that takes two equalities of the form (= t 1 t 2 ) and (= t 2 t 3 ) as arguments. If both of these are in the assumption base, the conclusion (= t 1 t 3 ) is produced: β {(= t 1 t 2 ), (= t 2 t 3 )} (!tran (= t 1 t 2 ) (= t 2 t 3 )) (= t 1 t 3 ) rcong (Relational congruence): This is a binary method that takes two atomic propositions of the form (R s 1 s n ) and (R t 1 t n ) as arguments, where R is a relation symbol of arity n. If the assumption base contains the first proposition, (R s 1 s n ), along with the n equalities (= s 1 t 1 ),..., (= s n t n ), then the second proposition (R t 1 t n ) is produced: β {(R s 1 s n ), (= s 1 t 1 ),..., (= s n t n )} (!rcong (R s 1 s n ) (R t 1 t n )) (R t 1 t n ) fcong (Functional congruence): This is a unary method that takes an equality of the form (= (f s 1 s n ) (f t 1 t n )) as an argument. If the n equalities (= s i t i ), i = 1,..., n are in the assumption base, then the given proposition (= (f s 1 s n ) (f t 1 t n )) is returned as the conclusion: β {(= s 1 t 1 ),..., (= s n t n )} (!fcong (= (f s 1 s n ) (f t 1 t n ))) (= (f s 1 s n ) (f t 1 t n )) These are the main primitive methods of Athena. There are three additional methods dealing with datatypes; we will discuss those in Section??. In terms of the introduction and elimination of sentential connectives and quantifiers, the reader may have noticed that so far we have not introced any primitive methods for performing the following: 1. Conditional introduction 18

Name Arity Semantics claim 1 β {P} (!claim P) P mp 2 β {(if P Q), P} (!mp (if P Q) P) Q absurd 2 β {P, (not P)} (!absurd P (not P)) false dn 1 β {(not (not P))} (!dn (not (not P))) P both 2 β {P, Q} (!both P Q) (and P Q) left-and 1 β {(and P Q} (!left-and (and P Q)) P right-and 1 β {(and P Q} (!right-and (and P Q)) Q equiv 2 β {(if P Q), (if Q P)} (!equiv (if P Q) (if Q P)) (iff P Q) left-iff 1 β {(iff P Q)} (!left-iff (iff P Q)) (if P Q) right-iff 1 β {(iff P Q} (!right-iff (iff P Q)) (if Q P) either 2 β (!either P Q) (or P Q) when P β or Q β cd 3 β {(or P P ), (if P Q), (if P Q)} (!cd (or P P ) (if P Q) (if P Q)) Q true-intro 0 β (!true-intro) true uspec 2 β {(forall x P)} (!uspec (forall x P) t) P[t/x] egen 2 β {P[t/x]} (!egen (exists x P) t) (exists x P) leibniz 4 β {(= s t)} (!leibniz s t x P) (iff P[s/x] P[t/x]) eq-reflex 1 β (!eq-reflex t) (= t t) Figure 2.1: Athena s primitive methods. 2. Negation introduction 3. Universal quantifier introduction 4. Existential quantifier elimination In Athena all four of these are performed by primitive (built-in) syntax forms, not by methods. The corresponding syntax forms are assume, suppose-absurd, pick-any, and pick-witness. We will describe these in Section 2.3, Section 2.4, Section 2.5, and Section??, respectively. But first we need to talk about composite proofs. 2.2 Proof composition How do we put together two or more simple proofs to form a single bigger proof? The simplest way to combine inferences in Athena is the dseq ( deduction sequence ) mechanism. For any two proofs D 1 and D 2, the phrase (dseq D 1 D 2 ) is a new composite proof that performs D 1 and D 2 sequentially. First, D 1 is evaluated in the current assumption base β, producing some conclusion P 1. Then P 1 is added to the assumption base, and we continue with the second proof D 2. 1 Thus D 2 is evaluated in β {P 1 }. The result of D 2 becomes the result of the entire dseq. This allows for lemma formation: the conclusion of D 1 (P 1 ) serves as a lemma inside D 2. The following rule expresses the semantics of dseq succinctly: β D 1 P 1 β {P 1 } D 2 P 2 β (dseq D 1 D 2 ) P 2 1 The phrase P 1 is added to the assumption base is somewhat misleading, as it implies that there is a single persistent assumption base that gets destructively modified (updated) like a store. In fact assumption bases in Athena are functional, so it would be more appropriate to say that D 2 is evaluated in a new assumption base β = β {P 1 }. However, for exposition purposes it is simpler to just say we add P 1 to the assumption base and continue with D 2. We will continue that practice, but the reader should keep in mind that under the hood assumption bases are functional. 19

More than two deductions can appear inside a dseq. For n > 2, the semantics of (dseq D 1 D n ) are given by desugaring to the n 1 case. For instance, (dseq D 1 D 2 D 3 ) is defined as (dseq D 1 (dseq D 2 D 3 )). Likewise, (dseq D 1 D 2 D 3 D 4 ) is defined as (dseq D 1 (dseq D 2 D 3 D 4 )); etc. For instance, suppose that A and B are Boolean constants and that the assumption base contains exactly one proposition, the conjunction (and A B). Then the proof below will derive the reverse conjunction (and B A) (a pound sign # starts a comment that extends to the end of the line): >(declare (A B) Boolean) New symbol A declared. New symbol B declared. >clear-assumption-base Assumption base cleared, blank-slate state. >(assert (and A B)) The proposition (and A B) has been added to the assumption base. >(dseq (!left-and (and A B)) # this derives A; the a.b. now is {(and A B), A} (!right-and (and A B)) # this gets B; the a.b. now is {(and A B), A, B} (!both B A)) # and finally this results in (and B A) Theorem: (and B A) The application of left-and above succeeds because the premise (and A B) is in the assumption base, as required by the semantics of left-and. Accordingly, the conclusion A is obtained, added to the assumption base, and we continue with the subsequent elements of dseq, starting with the right-and application. At this point the assumption base contains two propositions: the original premise (and A B), and the intermediate conclusion A that was derived by left-and. The application of right-and succeeds, the conclusion B is added to the assumption base, and we proceed to the next and last step, the application of both. At this point the assumption base contains three elements: (and A B), A, and B. The application of both succeeds (since both of the required premises B and A are in the current assumption base), and hence the conclusion (and B A) is returned, which becomes the conclusion of the entire dseq. At the end of the entire dseq proof, only the final conclusion (and B A) is retained and added to the original assumption base. The intermediate conclusions generated during thhe evaluation of the dseq (namely, the propositions A and B generated by the left-and and right-and applications) are not retained. For instance, here is what we get if we try to view the a.b. immediately after the preceding dialogue: >(show-assumption-base) There are 2 propositions in the current assumption base: 20

(and A B) (and B A) Unit: () In general, whenever we evaluate a deduction D at the top level and obtain a result P : >D Theorem: P only the conclusion P is added to the global assumption base. Any auxiliary conclusions derived in the course of evaluating D are discarded. 2.3 Conditional proofs In common mathematical reasoning, conditionals propositions of the form (if P Q) are usually derived by adding the antecedent P to our working assumptions and then inferring the consequent Q. That is, we supply a proof that derives Q from the hypothesis P along with whatever other assumptions are currently in effect. If we succeed, we then discharge the hypothesis P and conclude the desired conditional (if P Q). This mode of reasoning is captured in Athena by proofs of the form (assume P D) (2.2) which are called hypothetical or conditional proofs. The proposition P is called the hypothesis of the proof, and D is its body. We also say that D represents the scope of the hypothesis P. The operational semantics of hypothetical deductions are straightforward: To evaluate a proof of the form (2.2) in some assumption base β, we add the hypothesis P to β and proceed to evaluate the body D in the extended assumption base β {P }. If and when that produces a conclusion Q, we return the conditional (if P Q) as the result of the entire assume. Symbolically: β {P } D Q β (assume P D) (if P Q) We illustrate with some examples. First, let us introduce A, B, and C as propositional atoms: >(declare (A B C) Boolean) New symbol A declared. New symbol B declared. New symbol C declared. The following deduction will derive the conditional (if A A) no matter what is in the assumption base: >(assume A (!claim A)) Theorem: (if A A) 21

Here the hypothesis is A and the body is (!claim A). The conclusion (if A A) will be successfully derived in any (every) assumption base β, because, no matter what β contains, the body (!claim A) will always be evaluated in an assumption base that contains A (namely, in β {A}), and will therefore succeed, as prescribed by the semantics of claim. Here are three additional examples that respectively derive the following tautologies: >(assume (and A B) (dseq (!left-and (and A B)) (!right-and (and A B)) (!both B A))) Theorem: (if (and A B) (and B A)) A B B A (A B) [(B C) (A C)] [A (B C)] [(A B) C] >(assume (if A B) (assume (if B C) (assume A (dseq (!mp (if A B) A) (!mp (if B C) B))))) # this gives B # and this gets C Theorem: (if (if A B) (if (if B C) (if A C))) >(assume (if A (if B C)) (assume (and A B) (dseq (!left-and (and A B)) # first get A (!mp (if A (if B C)) A) # then get (if B C) (!right-and (and A B)) # then B (!mp (if B C) B)))) # and finally C Theorem: (if (if A (if B C)) (if (and A B) C)) Observe that it is not necessary to disharge assumptions explicitly. That is done automatically by the semantics of assume. This is a better model of informal reasoning, where assumption discharge does not occur explicitly but is rather tacitly understood by the lexical subdivision of the proof text into syntactic blocks such as paragraphs. 2.4 Proofs by contradiction Oftentimes when we need to establish a proposition P it is convenient to take a somewhat indirect route: we suppose that P does not hold, and show that this supposition is absurd, in that it leads to 22

a contradiction. From this we are entitled to conclude P. In Athena this type of reasoning is captured by deductions of the form (suppose-absurd P D) (2.3) Deductions of this form are called proofs by contradiction. As with conditional proofs, we refer to P as the hypothesis and to D as the body of the proof and the scope of the hypothesis P. To evaluate a deduction of the form (2.3) in an assumption base β, we add the hypothesis P to β and proceed to evaluate the body D in the extended assumption base β {P }. If and when that produces the atom false, we return the negation (not P ) as the result of the entire suppose-absurd. Symbolically: β {P } D false β (suppose-absurd P D) (not P ) Below are a couple of sample proofs using suppose-absurd. The first establishes the conditional A A, while the second derives the tautology ( A B) (A B). Recall that absurd is a binary primitive method that takes two propositions of the form P and (not P ) and derives false, provided that both P and (not P ) are in the assumption base (an error occurs otherwise). >(assume A (suppose-absurd (not A) (!absurd A (not A)))) Theorem: (if A (not (not A))) >(assume (or (not A) (not B)) # assume we either have (not A) or (not B) (suppose-absurd (and A B) # suppose, by way of contradiction, (and A B) (dseq (!left-and (and A B)) # this gives A (!right-and (and A B)) # this gives B (assume (not A) # this show that (not A) implies false (!absurd A (not A))) (assume (not B) # and this show that (not B) implies false (!absurd B (not B))) (!cd (or (not A) (not B)) # but (not A) OR (not B) holds by assumption (if (not A) false) # hence we get false by constructive dilemma (if (not B) false))))) Theorem: (if (or (not A) (not B)) (not (and A B))) Athena offers one more way to perform reasoning by contradiction, apart from suppose-absurd: a unary method by-contradiction, which takes a conditional of the form (if P false) and produces (not P ), provided that the argument (if P false) is in the assumption base. In addition, if P is of the form (not Q), then the proposition Q is directly returned (instead of (not (not Q))). This is convenient because many times when we wish to establish a proposition Q we end up showing that the negation of Q engenders an absurdity, i.e., we show (if (not Q) false). This allows us to conclude (not (not Q)), but then we need to apply the double-negation method (dn) to that in order to arrive at the desired Q. The by-contradiction method does this automatically. This method is not built-in it is implemented in an Athena library in terms of suppose-absurd. 23

2.5 Universal generalizations Universal generalizations are propositions of the form x. P, asserting that every object x (of some sort) has a property P. Mathematicians often prove such statements by reasoning as follows: Consider any x (of such-and-such sort). Then D (2.4) where D is some deduction that derives the proposition P (x). The variable x in this context is called an eigenvariable. The idea is that x represents an arbitrary object. If we can show that any object i.e., an arbitrary object has P, then it follows that every object has P. To ensure that x is arbitrary, we must be careful to avoid making any special assumptions about it. In particular, D must not rely on any previous assumptions that might happen to contain free occurrences of x. This is captured in Athena by deductions of the form (pick-any I D) (2.5) for any identifier I. To evaluate a deduction of this form in an assumption base β, we first generate a fresh variable x, say,?v135, or?foo1999. We then evaluate D in β, where D is the deduction obtained from D by replacing every free occurrence of I by the fresh variable x. 2 If and when the evaluation of D produces a proposition P, we generalize and return the conclusion (forall x P ) as the result of (2.5). Symbolically, if we write D[I x] to denote the deduction obtained from D by replacing every free occurrence of I by x, we have: β D[I x] P β (pick-any I D) (forall x P ) where x is a fresh variable The replacement of I by a fresh variable is what ensures that I refers to an arbitrary object inside the body D. Consider, for example, the deduction (pick-any x (!reflex x)). Recall that reflex is a unary primitive method that takes any term t and produces the equality (= t t). To evaluate this deduction in some assumption base β, Athena will first generate a fresh variable, i.e., a variable that is guaranteed not to have appeared anywhere since the beginning of the current Athena session, say?v18. It will then evaluate the body of the pick-any deduction, namely (!reflex x), in a context in which x refers to?v18. Thus Athena will essentially be evaluating the deduction (!reflex?v18). According to the semantics of reflex, that will produce the equality (=?v18?v18). Finally, Athena will generalize and return the conclusion (forall?v18 (=?v18?v18)) as the result of the entire pick-any. Note that for readability purposes Athena might present the conclusion as (forall?x (=?x?x)) instead of (forall?v18 (=?v18?v18)). This is legitimate because the two propositions are alphabetically equivalent, and as we mentioned earlier, Athena views alphabetically equivalent propositions as identical. As another example, here is a proof that the equality relation is symmetric. Recall that sym is a unary primitive method that takes an equality (= s t) and returns (= t s), provided that (= s t) is in the assumption base: 2 We are being somewhat vague here, as we are relying on an intuitive understanding of what it means for an identifier I to have a free occurrence inside a deduction D. To be perfectly rigorous, we should say that Athena generates a fresh variable x and then evaluates the body D in a lexical environment in which I denotes x (a lexical environment is a finite function from identifiers to denotable values terms, propositions, etc.). Athena evaluates a deduction not only in the context of an assumption base, but also in the context of a given environment and a given store. So the proof evaluation judgments of the language are really of the form ρ, σ, β D P, where ρ is an environment, σ is a store, and β is an assumption base. A more rigorous presentation of Athena s semantics is given elsewhere [2]. 24

>(pick-any x (pick-any y (assume (= x y) (!sym (= x y))))) Theorem: (forall?x: S (forall?y: S (if (=?x?y) (=?y?x)))) Observe the sort of the quantified variables?x and?y in the displayed conclusion: S. Here S is a sort variable, representing a completely arbitrary sort. Athena marks sort variables with an apostrophe, so an annotation such as?x: S means that the variable?x can range over any domain whatsoever. The only sort constraint in the above proposition is that?x and?y range over the same sort. That sort could be anything, but it has to be the same for both variables. We will discuss polymorphism in detail in Section??. Nested pick-any deductions (pick-any I 1 (pick-any I 2 (pick-any I 3 )) can be abbreviated as (pick-any I 1 I 2 I 3 ). For instance, the preceding proof could also be written as follows: (pick-any x y (assume (= x y) (!sym (= x y))))) As another example, let us prove the tautology [( x. P (x)) ( x. Q(x))] ( x. P (x) Q(x)), where P and Q are unary predicates on some domain. (E.g., if everything is green and everything is large, then everything is both green and large.) >(domain Object) New domain Object introduced. >(declare (P Q) (-> (Object) Boolean)) New symbol P declared. New symbol Q declared. >(define hypothesis (and (forall?x (P?x)) (forall?x (Q?x)))) Proposition hypothesis defined. >(assume hypothesis (pick-any z (dseq (!left-and hypothesis) # this will give (forall?x (P?x)) (!uspec (forall?x (P?x)) z) # this will give (P z) (!right-and hypothesis) # this will give (forall?x (Q?x)) (!uspec (forall?x (Q?x)) z) # this gives (Q z) (!both (P z) (Q z))))) # finally we get (and (P z) (Q z)) Theorem: (if (and (forall?x:object (P?x)) 25