12.07.2015 Views

Tutorial on Isabelle/HOL

Tutorial on Isabelle/HOL

Tutorial on Isabelle/HOL

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Tobias NipkowMarkus WenzelLawrence C. Pauls<strong>on</strong>=∀<strong>Isabelle</strong>λ β<strong>HOL</strong>→αA Proof Assistant forHigher-Order LogicApril 19, 2009Springer-VerlagBerlin Heidelberg NewYorkL<strong>on</strong>d<strong>on</strong> Paris TokyoH<strong>on</strong>g K<strong>on</strong>g Barcel<strong>on</strong>aBudapest


PrefaceThis volume is a self-c<strong>on</strong>tained introducti<strong>on</strong> to interactive proof in higherorderlogic (<strong>HOL</strong>), using the proof assistant <strong>Isabelle</strong>. It is written for potentialusers rather than for our colleagues in the research world.The book has three parts.– The first part, Elementary Techniques, shows how to model functi<strong>on</strong>alprograms in higher-order logic. Early examples involve lists and the naturalnumbers. Most proofs are two steps l<strong>on</strong>g, c<strong>on</strong>sisting of inducti<strong>on</strong> <strong>on</strong> achosen variable followed by the auto tactic. But even this elementary partcovers such advanced topics as nested and mutual recursi<strong>on</strong>.– The sec<strong>on</strong>d part, Logic and Sets, presents a collecti<strong>on</strong> of lower-leveltactics that you can use to apply rules selectively. It also describes <strong>Isabelle</strong>/<strong>HOL</strong>’streatment of sets, functi<strong>on</strong>s and relati<strong>on</strong>s and explains how todefine sets inductively. One of the examples c<strong>on</strong>cerns the theory of modelchecking, and another is drawn from a classic textbook <strong>on</strong> formal languages.– The third part, Advanced Material, describes a variety of other topics.Am<strong>on</strong>g these are the real numbers, records and overloading. Advancedtechniques for inducti<strong>on</strong> and recursi<strong>on</strong> are described. A whole chapter isdevoted to an extended example: the verificati<strong>on</strong> of a security protocol.The typesetting relies <strong>on</strong> Wenzel’s theory presentati<strong>on</strong> tools. An annotatedsource file is run, typesetting the theory in the form of a L A TEX sourcefile. This book is derived almost entirely from output generated in this way.The final chapter of Part I explains how users may produce their own formaldocuments in a similar fashi<strong>on</strong>.<strong>Isabelle</strong>’s web site 1 c<strong>on</strong>tains links to the download area and to documentati<strong>on</strong>and other informati<strong>on</strong>. Most <strong>Isabelle</strong> sessi<strong>on</strong>s are now run from withinDavid Aspinall’s w<strong>on</strong>derful user interface, Proof General 2 , even together withthe X-Symbol 3 package for XEmacs. This book says very little about ProofGeneral, which has its own documentati<strong>on</strong>. In order to run <strong>Isabelle</strong>, you willneed a Standard ML compiler. We recommend Poly/ML 4 , which is free and1 http://isabelle.in.tum.de/2 http://proofgeneral.inf.ed.ac.uk/3 http://x-symbol.sourceforge.net4 http://www.polyml.org/


viPrefacegives the best performance. The other fully supported compiler is StandardML of New Jersey 5 .This tutorial owes a lot to the c<strong>on</strong>stant discussi<strong>on</strong>s with and the valuablefeedback from the <strong>Isabelle</strong> group at Munich: Stefan Berghofer, Olaf Müller,Wolfgang Naraschewski, David v<strong>on</strong> Oheimb, Le<strong>on</strong>or Prensa Nieto, CorneliaPusch, Norbert Schirmer and Martin Strecker. Stephan Merz was also kindenough to read and comment <strong>on</strong> a draft versi<strong>on</strong>. We received comments fromStefano Bistarelli, Gergely Buday, John Matthews and Tanja Vos.The research has been funded by many sources, including the dfggrants NI 491/2, NI 491/3, NI 491/4, NI 491/6, bmbf project Verisoft,the epsrc grants GR/K57381, GR/K77051, GR/M75440, GR/R01156/01GR/S57198/01 and by the esprit working groups 21900 and IST-1999-29001(the Types project).5 http://www.smlnj.org/index.html


C<strong>on</strong>tentsPart I. Elementary Techniques1. The Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1 Introducti<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Theories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.3 Types, Terms and Formulae . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.4 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.5 Interacti<strong>on</strong> and Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.6 Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82. Functi<strong>on</strong>al Programming in <strong>HOL</strong> . . . . . . . . . . . . . . . . . . . . . . . . . 92.1 An Introductory Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.2 Evaluati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.3 An Introductory Proof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.4 Some Helpful Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.5 Datatypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.5.1 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.5.2 The General Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.5.3 Primitive Recursi<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.5.4 Case Expressi<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.5.5 Structural Inducti<strong>on</strong> and Case Distincti<strong>on</strong> . . . . . . . . . . . 192.5.6 Case Study: Boolean Expressi<strong>on</strong>s . . . . . . . . . . . . . . . . . . . 192.6 Some Basic Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.6.1 Natural Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.6.2 Pairs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.6.3 Datatype opti<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.7 Definiti<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.7.1 Type Syn<strong>on</strong>yms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.7.2 C<strong>on</strong>stant Definiti<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.8 The Definiti<strong>on</strong>al Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253. More Functi<strong>on</strong>al Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.1 Simplificati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.1.1 What is Simplificati<strong>on</strong>? . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.1.2 Simplificati<strong>on</strong> Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28


viiiC<strong>on</strong>tents3.1.3 The simp Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283.1.4 Adding and Deleting Simplificati<strong>on</strong> Rules . . . . . . . . . . . 293.1.5 Assumpti<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.1.6 Rewriting with Definiti<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . 303.1.7 Simplifying let-Expressi<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . 303.1.8 C<strong>on</strong>diti<strong>on</strong>al Simplificati<strong>on</strong> Rules . . . . . . . . . . . . . . . . . . . . 313.1.9 Automatic Case Splits . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313.1.10 Tracing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323.1.11 Finding Theorems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333.2 Inducti<strong>on</strong> Heuristics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.3 Case Study: Compiling Expressi<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . 373.4 Advanced Datatypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393.4.1 Mutual Recursi<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393.4.2 Nested Recursi<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413.4.3 The Limits of Nested Recursi<strong>on</strong> . . . . . . . . . . . . . . . . . . . . 433.4.4 Case Study: Tries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443.5 Total Recursive Functi<strong>on</strong>s: fun . . . . . . . . . . . . . . . . . . . . . . . . . . . 473.5.1 Definiti<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473.5.2 Terminati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483.5.3 Simplificati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493.5.4 Inducti<strong>on</strong>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504. Presenting Theories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534.1 C<strong>on</strong>crete Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534.1.1 Infix Annotati<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534.1.2 Mathematical Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . 544.1.3 Prefix Annotati<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554.1.4 Abbreviati<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564.2 Document Preparati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574.2.1 <strong>Isabelle</strong> Sessi<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584.2.2 Structure Markup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594.2.3 Formal Comments and Antiquotati<strong>on</strong>s . . . . . . . . . . . . . . 604.2.4 Interpretati<strong>on</strong> of Symbols . . . . . . . . . . . . . . . . . . . . . . . . . 624.2.5 Suppressing Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63Part II. Logic and Sets5. The Rules of the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 675.1 Natural Deducti<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 675.2 Introducti<strong>on</strong> Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685.3 Eliminati<strong>on</strong> Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 695.4 Destructi<strong>on</strong> Rules: Some Examples . . . . . . . . . . . . . . . . . . . . . . . 715.5 Implicati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 725.6 Negati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73


C<strong>on</strong>tentsix5.7 Interlude: the Basic Methods for Rules . . . . . . . . . . . . . . . . . . . . 755.8 Unificati<strong>on</strong> and Substituti<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 765.8.1 Substituti<strong>on</strong> and the subst Method . . . . . . . . . . . . . . . . 775.8.2 Unificati<strong>on</strong> and Its Pitfalls . . . . . . . . . . . . . . . . . . . . . . . . . 785.9 Quantifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 805.9.1 The Universal Introducti<strong>on</strong> Rule . . . . . . . . . . . . . . . . . . . 805.9.2 The Universal Eliminati<strong>on</strong> Rule . . . . . . . . . . . . . . . . . . . . 815.9.3 The Existential Quantifier . . . . . . . . . . . . . . . . . . . . . . . . . 825.9.4 Renaming an Assumpti<strong>on</strong>: rename_tac. . . . . . . . . . . . . . 835.9.5 Reusing an Assumpti<strong>on</strong>: frule . . . . . . . . . . . . . . . . . . . . . 835.9.6 Instantiating a Quantifier Explicitly . . . . . . . . . . . . . . . . 845.10 Descripti<strong>on</strong> Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 855.10.1 Definite Descripti<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 865.10.2 Indefinite Descripti<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 865.11 Some Proofs That Fail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 885.12 Proving Theorems Using the blast Method. . . . . . . . . . . . . . . . 895.13 Other Classical Reas<strong>on</strong>ing Methods . . . . . . . . . . . . . . . . . . . . . . . 915.14 Finding More Theorems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 935.15 Forward Proof: Transforming Theorems . . . . . . . . . . . . . . . . . . . 935.15.1 Modifying a Theorem using of, where and THEN . . . . . . 945.15.2 Modifying a Theorem using OF . . . . . . . . . . . . . . . . . . . . . 965.16 Forward Reas<strong>on</strong>ing in a Backward Proof . . . . . . . . . . . . . . . . . . 975.16.1 The Method insert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 985.16.2 The Method subgoal_tac . . . . . . . . . . . . . . . . . . . . . . . . . 995.17 Managing Large Proofs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1005.17.1 Tacticals, or C<strong>on</strong>trol Structures . . . . . . . . . . . . . . . . . . . . 1005.17.2 Subgoal Numbering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1015.18 Proving the Correctness of Euclid’s Algorithm . . . . . . . . . . . . . 1026. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1076.1 Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1076.1.1 Finite Set Notati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1096.1.2 Set Comprehensi<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1096.1.3 Binding Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1106.1.4 Finiteness and Cardinality . . . . . . . . . . . . . . . . . . . . . . . . . 1116.2 Functi<strong>on</strong>s. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1116.2.1 Functi<strong>on</strong> Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1116.2.2 Injecti<strong>on</strong>s, Surjecti<strong>on</strong>s, Bijecti<strong>on</strong>s . . . . . . . . . . . . . . . . . . . 1126.2.3 Functi<strong>on</strong> Image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1136.3 Relati<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1136.3.1 Relati<strong>on</strong> Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1146.3.2 The Reflexive and Transitive Closure . . . . . . . . . . . . . . . 1146.3.3 A Sample Proof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1156.4 Well-Founded Relati<strong>on</strong>s and Inducti<strong>on</strong> . . . . . . . . . . . . . . . . . . . . 1166.5 Fixed Point Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117


xC<strong>on</strong>tents6.6 Case Study: Verified Model Checking . . . . . . . . . . . . . . . . . . . . . 1186.6.1 Propositi<strong>on</strong>al Dynamic Logic — PDL . . . . . . . . . . . . . . . 1206.6.2 Computati<strong>on</strong> Tree Logic — CTL . . . . . . . . . . . . . . . . . . . 1237. Inductively Defined Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1297.1 The Set of Even Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1297.1.1 Making an Inductive Definiti<strong>on</strong> . . . . . . . . . . . . . . . . . . . . 1297.1.2 Using Introducti<strong>on</strong> Rules . . . . . . . . . . . . . . . . . . . . . . . . . . 1307.1.3 Rule Inducti<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1307.1.4 Generalizati<strong>on</strong> and Rule Inducti<strong>on</strong> . . . . . . . . . . . . . . . . . 1317.1.5 Rule Inversi<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1327.1.6 Mutually Inductive Definiti<strong>on</strong>s . . . . . . . . . . . . . . . . . . . . . 1337.1.7 Inductively Defined Predicates . . . . . . . . . . . . . . . . . . . . . 1347.2 The Reflexive Transitive Closure . . . . . . . . . . . . . . . . . . . . . . . . . 1357.3 Advanced Inductive Definiti<strong>on</strong>s. . . . . . . . . . . . . . . . . . . . . . . . . . . 1377.3.1 Universal Quantifiers in Introducti<strong>on</strong> Rules . . . . . . . . . 1387.3.2 Alternative Definiti<strong>on</strong> Using a M<strong>on</strong>ot<strong>on</strong>e Functi<strong>on</strong> . . . . 1397.3.3 A Proof of Equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1407.3.4 Another Example of Rule Inversi<strong>on</strong> . . . . . . . . . . . . . . . . . 1427.4 Case Study: A C<strong>on</strong>text Free Grammar . . . . . . . . . . . . . . . . . . . . 143Part III. Advanced Material8. More about Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1518.1 Pairs and Tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1518.1.1 Pattern Matching with Tuples . . . . . . . . . . . . . . . . . . . . . 1518.1.2 Theorem Proving . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1528.2 Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1548.2.1 Record Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1548.2.2 Extensible Records and Generic Operati<strong>on</strong>s . . . . . . . . . . 1558.2.3 Record Equality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1578.2.4 Extending and Truncating Records . . . . . . . . . . . . . . . . . 1588.3 Axiomatic Type Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1608.3.1 Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1608.3.2 Axioms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1628.4 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1668.4.1 Numeric Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1668.4.2 The Type of Natural Numbers, nat . . . . . . . . . . . . . . . . . 1678.4.3 The Type of Integers, int . . . . . . . . . . . . . . . . . . . . . . . . . 1698.4.4 The Types of Rati<strong>on</strong>al, Real and Complex Numbers . . 1708.4.5 The Numeric Type Classes . . . . . . . . . . . . . . . . . . . . . . . . 1718.5 Introducing New Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1738.5.1 Declaring New Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1738.5.2 Defining New Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174


C<strong>on</strong>tentsxi9. Advanced Simplificati<strong>on</strong> and Inducti<strong>on</strong> . . . . . . . . . . . . . . . . . . . 1779.1 Simplificati<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1779.1.1 Advanced Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1779.1.2 How the Simplifier Works . . . . . . . . . . . . . . . . . . . . . . . . . 1799.2 Advanced Inducti<strong>on</strong> Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . 1809.2.1 Massaging the Propositi<strong>on</strong> . . . . . . . . . . . . . . . . . . . . . . . . . 1809.2.2 Bey<strong>on</strong>d Structural and Recursi<strong>on</strong> Inducti<strong>on</strong> . . . . . . . . . . 1829.2.3 Derivati<strong>on</strong> of New Inducti<strong>on</strong> Schemas . . . . . . . . . . . . . . . 1849.2.4 CTL Revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18410. Case Study: Verifying a Security Protocol . . . . . . . . . . . . . . . . 18910.1 The Needham-Schroeder Public-Key Protocol . . . . . . . . . . . . . . 18910.2 Agents and Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19110.3 Modelling the Adversary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19210.4 Event Traces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19310.5 Modelling the Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19410.6 Proving Elementary Properties . . . . . . . . . . . . . . . . . . . . . . . . . . 19510.7 Proving Secrecy Theorems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197A. Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203


xiiC<strong>on</strong>tents


Part IElementary Techniques


1. The Basics1.1 Introducti<strong>on</strong>This book is a tutorial <strong>on</strong> how to use the theorem prover <strong>Isabelle</strong>/<strong>HOL</strong> as aspecificati<strong>on</strong> and verificati<strong>on</strong> system. <strong>Isabelle</strong> is a generic system for implementinglogical formalisms, and <strong>Isabelle</strong>/<strong>HOL</strong> is the specializati<strong>on</strong> of <strong>Isabelle</strong>for <strong>HOL</strong>, which abbreviates Higher-Order Logic. We introduce <strong>HOL</strong> step bystep following the equati<strong>on</strong><strong>HOL</strong> = Functi<strong>on</strong>al Programming + Logic.We do not assume that you are familiar with mathematical logic. However, wedo assume that you are used to logical and set theoretic notati<strong>on</strong>, as coveredin a good discrete mathematics course [36], and that you are familiar withthe basic c<strong>on</strong>cepts of functi<strong>on</strong>al programming [5, 16, 31, 37]. Although thistutorial initially c<strong>on</strong>centrates <strong>on</strong> functi<strong>on</strong>al programming, do not be misled:<strong>HOL</strong> can express most mathematical c<strong>on</strong>cepts, and functi<strong>on</strong>al programmingis just <strong>on</strong>e particularly simple and ubiquitous instance.<strong>Isabelle</strong> [30] is implemented in ML [21]. This has influenced some of <strong>Isabelle</strong>/<strong>HOL</strong>’sc<strong>on</strong>crete syntax but is otherwise irrelevant for us: this tutorialis based <strong>on</strong> <strong>Isabelle</strong>/Isar [38], an extensi<strong>on</strong> of <strong>Isabelle</strong> which hides the implementati<strong>on</strong>language almost completely. Thus the full name of the systemshould be <strong>Isabelle</strong>/Isar/<strong>HOL</strong>, but that is a bit of a mouthful.There are other implementati<strong>on</strong>s of <strong>HOL</strong>, in particular the <strong>on</strong>e by MikeGord<strong>on</strong> et al., which is usually referred to as “the <strong>HOL</strong> system” [11]. Forus, <strong>HOL</strong> refers to the logical system, and sometimes its incarnati<strong>on</strong> <strong>Isabelle</strong>/<strong>HOL</strong>.A tutorial is by definiti<strong>on</strong> incomplete. Currently the tutorial <strong>on</strong>ly introducesthe rudiments of Isar’s proof language. To fully exploit the power ofIsar, in particular the ability to write readable and structured proofs, youshould start with Nipkow’s overview [26] and c<strong>on</strong>sult the <strong>Isabelle</strong>/Isar ReferenceManual [38] and Wenzel’s PhD thesis [39] (which discusses many proofpatterns) for further details. If you want to use <strong>Isabelle</strong>’s ML level directly(for example for writing your own proof procedures) see the <strong>Isabelle</strong> ReferenceManual [28]; for details relating to <strong>HOL</strong> see the <strong>Isabelle</strong>/<strong>HOL</strong> manual [27].All manuals have a comprehensive index.


4 1. The Basics1.2 TheoriesWorking with <strong>Isabelle</strong> means creating theories. Roughly speaking, a theoryis a named collecti<strong>on</strong> of types, functi<strong>on</strong>s, and theorems, much like a modulein a programming language or a specificati<strong>on</strong> in a specificati<strong>on</strong> language. Infact, theories in <strong>HOL</strong> can be either. The general format of a theory T istheory Timports B 1 . . . B nbegindeclarati<strong>on</strong>s, definiti<strong>on</strong>s, and proofsendwhere B 1 . . . B n are the names of existing theories that T is based <strong>on</strong> anddeclarati<strong>on</strong>s, definiti<strong>on</strong>s, and proofs represents the newly introduced c<strong>on</strong>cepts(types, functi<strong>on</strong>s etc.) and proofs about them. The B i are the direct parenttheories of T. Everything defined in the parent theories (and their parents,recursively) is automatically visible. To avoid name clashes, identifiers canbe qualified by theory names as in T.f and B.f. Each theory T must residein a theory file named T.thy.This tutorial is c<strong>on</strong>cerned with introducing you to the different linguisticc<strong>on</strong>structs that can fill the declarati<strong>on</strong>s, definiti<strong>on</strong>s, and proofs above. A completegrammar of the basic c<strong>on</strong>structs is found in the <strong>Isabelle</strong>/Isar ReferenceManual [38].!!<strong>HOL</strong> c<strong>on</strong>tains a theory Main, the uni<strong>on</strong> of all the basic predefined theories likearithmetic, lists, sets, etc. Unless you know what you are doing, always includeMain as a direct or indirect parent of all your theories.<strong>HOL</strong>’s theory collecti<strong>on</strong> is available <strong>on</strong>line athttp://isabelle.in.tum.de/library/<strong>HOL</strong>/and is recommended browsing. In subdirectory Library you find a growinglibrary of useful theories that are not part of Main but can be included am<strong>on</strong>gthe parents of a theory and will then be loaded automatically.For the more adventurous, there is the Archive of Formal Proofs, ajournal-like collecti<strong>on</strong> of more advanced <strong>Isabelle</strong> theories:http://afp.sourceforge.net/We hope that you will c<strong>on</strong>tribute to it yourself <strong>on</strong>e day.1.3 Types, Terms and FormulaeEmbedded in a theory are the types, terms and formulae of <strong>HOL</strong>. <strong>HOL</strong> isa typed logic whose type system resembles that of functi<strong>on</strong>al programminglanguages like ML or Haskell. Thus there are


1.3 Types, Terms and Formulae 5base types, in particular bool, the type of truth values, and nat, the type ofnatural numbers.type c<strong>on</strong>structors, in particular list, the type of lists, and set, the type ofsets. Type c<strong>on</strong>structors are written postfix, e.g. (nat)list is the typeof lists whose elements are natural numbers. Parentheses around singlearguments can be dropped (as in nat list), multiple arguments are separatedby commas (as in (bool,nat)ty).functi<strong>on</strong> types, denoted by ⇒. In <strong>HOL</strong> ⇒ represents total functi<strong>on</strong>s <strong>on</strong>ly. Asis customary, τ 1 ⇒ τ 2 ⇒ τ 3 means τ 1 ⇒ (τ 2 ⇒ τ 3). <strong>Isabelle</strong> also supportsthe notati<strong>on</strong> [τ 1, . . . , τ n] ⇒ τ which abbreviates τ 1 ⇒ · · · ⇒ τ n⇒ τ.type variables, denoted by ’a, ’b etc., just like in ML. They give rise topolymorphic types like ’a ⇒ ’a, the type of the identity functi<strong>on</strong>.!!Types are extremely important because they prevent us from writing n<strong>on</strong>sense.<strong>Isabelle</strong> insists that all terms and formulae must be well-typed and will print anerror message if a type mismatch is encountered. To reduce the amount of explicittype informati<strong>on</strong> that needs to be provided by the user, <strong>Isabelle</strong> infers the type ofall variables automatically (this is called type inference) and keeps quiet aboutit. Occasi<strong>on</strong>ally this may lead to misunderstandings between you and the system. Ifanything strange happens, we recommend that you ask <strong>Isabelle</strong> to display all typeinformati<strong>on</strong> via the Proof General menu item <strong>Isabelle</strong> > Settings > Show Types (seeSect. 1.5 for details).Terms are formed as in functi<strong>on</strong>al programming by applying functi<strong>on</strong>sto arguments. If f is a functi<strong>on</strong> of type τ 1 ⇒ τ 2 and t is a term of typeτ 1 then f t is a term of type τ 2 . <strong>HOL</strong> also supports infix functi<strong>on</strong>s like +and some basic c<strong>on</strong>structs from functi<strong>on</strong>al programming, such as c<strong>on</strong>diti<strong>on</strong>alexpressi<strong>on</strong>s:if b then t 1 else t 2 Here b is of type bool and t 1 and t 2 are of the sametype.let x = t in u is equivalent to u where all free occurrences of x have beenreplaced by t. For example, let x = 0 in x+x is equivalent to 0+0. Multiplebindings are separated by semicol<strong>on</strong>s: let x 1 = t 1;...; x n = t n inu.case e of c 1 ⇒ e 1 | ... | c n ⇒ e n evaluates to e i if e is of the form c i .Terms may also c<strong>on</strong>tain λ-abstracti<strong>on</strong>s. For example, λx. x+1 is the functi<strong>on</strong>that takes an argument x and returns x+1. Instead of λx.λy.λz. t wecan write λx y z. t.Formulae are terms of type bool. There are the basic c<strong>on</strong>stants Trueand False and the usual logical c<strong>on</strong>nectives (in decreasing order of priority):¬, ∧, ∨, and −→, all of which (except the unary ¬) associate to the right.In particular A −→ B −→ C means A −→ (B −→ C) and is thus logicallyequivalent to A ∧ B −→ C (which is (A ∧ B) −→ C).Equality is available in the form of the infix functi<strong>on</strong> = of type ’a ⇒ ’a⇒ bool. Thus t 1 = t 2 is a formula provided t 1 and t 2 are terms of the same


6 1. The Basicstype. If t 1 and t 2 are of type bool then = acts as if-and-<strong>on</strong>ly-if. The formulat 1 ≠ t 2 is merely an abbreviati<strong>on</strong> for ¬(t 1 = t 2).Quantifiers are written as ∀ x. P and ∃ x. P. There is even ∃! x. P, whichmeans that there exists exactly <strong>on</strong>e x that satisfies P. Nested quantificati<strong>on</strong>scan be abbreviated: ∀ x y z. P means ∀ x.∀ y.∀ z. P.Despite type inference, it is sometimes necessary to attach explicit typec<strong>on</strong>straints to a term. The syntax is t::τ as in x < (y::nat). Note that:: binds weakly and should therefore be enclosed in parentheses. For instance,x < y::nat is ill-typed because it is interpreted as (x < y)::nat. Typec<strong>on</strong>straints may be needed to disambiguate expressi<strong>on</strong>s involving overloadedfuncti<strong>on</strong>s such as +, * and Settings > ShowBrackets (see Sect. 1.5).


1.4 Variables 71.4 Variables<strong>Isabelle</strong> distinguishes free and bound variables, as is customary. Bound variablesare automatically renamed to avoid clashes with free variables. In additi<strong>on</strong>,<strong>Isabelle</strong> has a third kind of variable, called a schematic variable orunknown, which must have a ? as its first character. Logically, an unknownis a free variable. But it may be instantiated by another term during the proofprocess. For example, the mathematical theorem x = x is represented in <strong>Isabelle</strong>as ?x = ?x, which means that <strong>Isabelle</strong> can instantiate it arbitrarily. Thisis in c<strong>on</strong>trast to ordinary variables, which remain fixed. The programminglanguage Prolog calls unknowns logical variables.Most of the time you can and should ignore unknowns and work withordinary variables. Just d<strong>on</strong>’t be surprised that after you have finished theproof of a theorem, <strong>Isabelle</strong> will turn your free variables into unknowns. Itindicates that <strong>Isabelle</strong> will automatically instantiate those unknowns suitablywhen the theorem is used in some other proof. Note that for readability weoften drop the ?s when displaying a theorem.!!For historical reas<strong>on</strong>s, <strong>Isabelle</strong> accepts ? as an ASCII representati<strong>on</strong> of the∃ symbol. However, the ? character must then be followed by a space, as in? x. f(x) = 0. Otherwise, ?x is interpreted as a schematic variable. The preferredASCII representati<strong>on</strong> of the ∃ symbol is EX.1.5 Interacti<strong>on</strong> and InterfacesThe recommended interface for <strong>Isabelle</strong>/Isar is the (X)Emacs-based ProofGeneral [1, 2]. Interacti<strong>on</strong> with <strong>Isabelle</strong> at the shell level, although possible,should be avoided. Most of the tutorial is independent of the interface and isphrased in a neutral language. For example, the phrase “to aband<strong>on</strong> a proof”corresp<strong>on</strong>ds to the obvious acti<strong>on</strong> of clicking <strong>on</strong> the Undo symbol in ProofGeneral. Proof General specific informati<strong>on</strong> is often displayed in paragraphsidentified by a miniature Proof General ic<strong>on</strong>. Here are two examples:Proof General supports a special f<strong>on</strong>t with mathematical symbols known as “xsymbols”.All symbols have ascii-equivalents: for example, you can enter either& or \ to obtain ∧. For a list of the most frequent symbols see table A.1 inthe appendix.Note that by default x-symbols are not enabled. You have to switch them <strong>on</strong>via the menu item Proof-General > Opti<strong>on</strong>s > X-Symbols (and save the opti<strong>on</strong> viathe top-level Opti<strong>on</strong>s menu).Proof General offers the <strong>Isabelle</strong> menu for displaying informati<strong>on</strong> and settingflags. A particularly useful flag is <strong>Isabelle</strong> > Settings > Show Types which causes<strong>Isabelle</strong> to output the type informati<strong>on</strong> that is usually suppressed. This is indispensiblein case of errors of all kinds because often the types reveal the source ofthe problem. Once you have diagnosed the problem you may no l<strong>on</strong>ger want to seethe types because they clutter all output. Simply reset the flag.


8 1. The Basics1.6 Getting StartedAssuming you have installed <strong>Isabelle</strong> and Proof General, you start it by typing<strong>Isabelle</strong> in a shell window. This launches a Proof General window. Bydefault, you are in <strong>HOL</strong> 1 .You can choose a different logic via the <strong>Isabelle</strong> > Logics menu. For example, youmay want to work in the real numbers, an extensi<strong>on</strong> of <strong>HOL</strong> (see Sect. 8.4.4).1 This is c<strong>on</strong>trolled by the ISABELLE_LOGIC setting, see The <strong>Isabelle</strong> System Manualfor more details.


2. Functi<strong>on</strong>al Programming in <strong>HOL</strong>This chapter describes how to write functi<strong>on</strong>al programs in <strong>HOL</strong> and howto verify them. However, most of the c<strong>on</strong>structs and proof procedures introducedare general and recur in any specificati<strong>on</strong> or verificati<strong>on</strong> task. Wereally should speak of functi<strong>on</strong>al modelling rather than functi<strong>on</strong>al programming:our primary aim is not to write programs but to design abstract modelsof systems. <strong>HOL</strong> is a specificati<strong>on</strong> language that goes well bey<strong>on</strong>d what canbe expressed as a program. However, for the time being we c<strong>on</strong>centrate <strong>on</strong>the computable.If you are a purist functi<strong>on</strong>al programmer, please note that all functi<strong>on</strong>s in<strong>HOL</strong> must be total: they must terminate for all inputs. Lazy data structuresare not directly available.2.1 An Introductory TheoryFuncti<strong>on</strong>al programming needs datatypes and functi<strong>on</strong>s. Both of them can bedefined in a theory with a syntax reminiscent of languages like ML or Haskell.As an example c<strong>on</strong>sider the theory in figure 2.1. We will now examine it lineby line.theory ToyListimports Datatypebegin<strong>HOL</strong> already has a predefined theory of lists called List — ToyList is merelya small fragment of it chosen as an example. In c<strong>on</strong>trast to what is recommendedin Sect. 1.2, ToyList is not based <strong>on</strong> Main but <strong>on</strong> Datatype, a theorythat c<strong>on</strong>tains pretty much everything but lists, thus avoiding ambiguitiescaused by defining lists twice.datatype ’a list = Nil ("[]")| C<strong>on</strong>s ’a "’a list" (infixr "#" 65)The datatype list introduces two c<strong>on</strong>structors Nil and C<strong>on</strong>s, the empty listand the operator that adds an element to the fr<strong>on</strong>t of a list. For example,the term C<strong>on</strong>s True (C<strong>on</strong>s False Nil) is a value of type bool list, namelythe list with the elements True and False. Because this notati<strong>on</strong> quickly


2.2 Evaluati<strong>on</strong> 11datatype c<strong>on</strong>structor from <strong>on</strong>e of the arguments. Thus the recursi<strong>on</strong> alwaysterminates, i.e. the functi<strong>on</strong> is total.The terminati<strong>on</strong> requirement is absolutely essential in <strong>HOL</strong>, a logic oftotal functi<strong>on</strong>s. If we were to drop it, inc<strong>on</strong>sistencies would quickly arise: the“definiti<strong>on</strong>” f (n) = f (n) + 1 immediately leads to 0 = 1 by subtracting f (n)<strong>on</strong> both sides.!!As we have indicated, the requirement for total functi<strong>on</strong>s is an essential characteristicof <strong>HOL</strong>. It is <strong>on</strong>ly because of totality that reas<strong>on</strong>ing in <strong>HOL</strong> is comparativelyeasy. More generally, the philosophy in <strong>HOL</strong> is to refrain from assertingarbitrary axioms (such as functi<strong>on</strong> definiti<strong>on</strong>s whose totality has not been proved)because they quickly lead to inc<strong>on</strong>sistencies. Instead, fixed c<strong>on</strong>structs for introducingtypes and functi<strong>on</strong>s are offered (such as datatype and primrec) which areguaranteed to preserve c<strong>on</strong>sistency.A remark about syntax. The textual definiti<strong>on</strong> of a theory follows a fixedsyntax with keywords like datatype and end. Embedded in this syntax arethe types and formulae of <strong>HOL</strong>, whose syntax is extensible (see Sect. 4.1), e.g.by new user-defined infix operators. To distinguish the two levels, everything<strong>HOL</strong>-specific (terms and types) should be enclosed in ". . . ". To lessen thisburden, quotati<strong>on</strong> marks around a single identifier can be dropped, unless theidentifier happens to be a keyword, for example "end". When <strong>Isabelle</strong> printsa syntax error message, it refers to the <strong>HOL</strong> syntax as the inner syntax andthe enclosing theory language as the outer syntax.2.2 Evaluati<strong>on</strong>Assuming you have processed the declarati<strong>on</strong>s and definiti<strong>on</strong>s of ToyListpresented so far, you may want to test your functi<strong>on</strong>s by running them. Forexample, what is the value of rev (True # False # [])? Commandvalue "rev (True # False # [])"yields the correct result False # True # []. But we can go bey<strong>on</strong>d mere functi<strong>on</strong>alprogramming and evaluate terms with variables in them, executingfuncti<strong>on</strong>s symbolically:normal form "rev (a # b # c # [])"yields c # b # a # []. Command normal form works for arbitrary termsbut can be slower than command value, which is restricted to variable-freeterms and executable functi<strong>on</strong>s. To appreciate the subtleties of evaluatingterms with variables, try this <strong>on</strong>e:normal form "rev (a # b # c # xs)"


12 2. Functi<strong>on</strong>al Programming in <strong>HOL</strong>2.3 An Introductory ProofHaving c<strong>on</strong>vinced ourselves (as well as <strong>on</strong>e can by testing) that our definiti<strong>on</strong>scapture our intenti<strong>on</strong>s, we are ready to prove a few simple theorems. Thiswill illustrate not just the basic proof commands but also the typical proofprocess.Main Goal. Our goal is to show that reversing a list twice produces theoriginal list.theorem rev_rev [simp]: "rev(rev xs) = xs"This theorem command does several things:– It establishes a new theorem to be proved, namely rev (rev xs) = xs.– It gives that theorem the name rev_rev, for later reference.– It tells <strong>Isabelle</strong> (via the bracketed attribute simp) to take the eventualtheorem as a simplificati<strong>on</strong> rule: future proofs involving simplificati<strong>on</strong> willreplace occurrences of rev (rev xs) by xs.The name and the simplificati<strong>on</strong> attribute are opti<strong>on</strong>al. <strong>Isabelle</strong>’s resp<strong>on</strong>seis to print the initial proof state c<strong>on</strong>sisting of some header informati<strong>on</strong> (likehow many subgoals there are) followed by1. rev (rev xs) = xsFor compactness reas<strong>on</strong>s we omit the header in this tutorial. Until we havefinished a proof, the proof state proper always looks like this:1. G 1.n. G nThe numbered lines c<strong>on</strong>tain the subgoals G 1 , . . . , G n that we need to prove toestablish the main goal. Initially there is <strong>on</strong>ly <strong>on</strong>e subgoal, which is identicalwith the main goal. (If you always want to see the main goal as well, set theflag Proof.show_main_goal — this flag used to be set by default.)Let us now get back to rev (rev xs) = xs. Properties of recursively definedfuncti<strong>on</strong>s are best established by inducti<strong>on</strong>. In this case there is nothingobvious except inducti<strong>on</strong> <strong>on</strong> xs:apply(induct_tac xs)This tells <strong>Isabelle</strong> to perform inducti<strong>on</strong> <strong>on</strong> variable xs. The suffix tac standsfor tactic, a syn<strong>on</strong>ym for “theorem proving functi<strong>on</strong>”. By default, inducti<strong>on</strong>acts <strong>on</strong> the first subgoal. The new proof state c<strong>on</strong>tains two subgoals, namelythe base case (Nil) and the inducti<strong>on</strong> step (C<strong>on</strong>s):1. rev (rev []) = []2. V a list.rev (rev list) = list =⇒ rev (rev (a # list)) = a # listThe inducti<strong>on</strong> step is an example of the general format of a subgoal:


2.3 An Introductory Proof 13i. V x 1 ...x n. assumpti<strong>on</strong>s =⇒ c<strong>on</strong>clusi<strong>on</strong>The prefix of bound variables ∧ x 1 . . . x n can be ignored most of the time, orsimply treated as a list of variables local to this subgoal. Their deeper significanceis explained in Chapter 5. The assumpti<strong>on</strong>s are the local assumpti<strong>on</strong>sfor this subgoal and c<strong>on</strong>clusi<strong>on</strong> is the actual propositi<strong>on</strong> to be proved. Typicalproof steps that add new assumpti<strong>on</strong>s are inducti<strong>on</strong> and case distincti<strong>on</strong>. Inour example the <strong>on</strong>ly assumpti<strong>on</strong> is the inducti<strong>on</strong> hypothesis rev (rev list)= list, where list is a variable name chosen by <strong>Isabelle</strong>. If there are multipleassumpti<strong>on</strong>s, they are enclosed in the bracket pair [ and ] and separated bysemicol<strong>on</strong>s.Let us try to solve both goals automatically:apply(auto)This command tells <strong>Isabelle</strong> to apply a proof strategy called auto to all subgoals.Essentially, auto tries to simplify the subgoals. In our case, subgoal 1is solved completely (thanks to the equati<strong>on</strong> rev [] = []) and disappears;the simplified versi<strong>on</strong> of subgoal 2 becomes the new subgoal 1:1. V a list.rev (rev list) = list =⇒ rev (rev list @ a # []) = a # listIn order to simplify this subgoal further, a lemma suggests itself.First Lemma. After aband<strong>on</strong>ing the above proof attempt (at the shell leveltype oops) we start a new proof:lemma rev_app [simp]: "rev(xs @ ys) = (rev ys) @ (rev xs)"The keywords theorem and lemma are interchangeable and merely indicatethe importance we attach to a propositi<strong>on</strong>. Therefore we use the wordstheorem and lemma pretty much interchangeably, too.There are two variables that we could induct <strong>on</strong>: xs and ys. Because @ isdefined by recursi<strong>on</strong> <strong>on</strong> the first argument, xs is the correct <strong>on</strong>e:apply(induct_tac xs)This time not even the base case is solved automatically:apply(auto)1. rev ys = rev ys @ []Again, we need to aband<strong>on</strong> this proof attempt and prove another simplelemma first. In the future the step of aband<strong>on</strong>ing an incomplete proof beforeembarking <strong>on</strong> the proof of a lemma usually remains implicit.


14 2. Functi<strong>on</strong>al Programming in <strong>HOL</strong>Sec<strong>on</strong>d Lemma. We again try the can<strong>on</strong>ical proof procedure:lemma app_Nil2 [simp]: "xs @ [] = xs"apply(induct_tac xs)apply(auto)It works, yielding the desired message No subgoals!:xs @ [] = xsNo subgoals!We still need to c<strong>on</strong>firm that the proof is now finished:d<strong>on</strong>eAs a result of that final d<strong>on</strong>e, <strong>Isabelle</strong> associates the lemma just proved withits name. In this tutorial, we sometimes omit to show that final d<strong>on</strong>e if it isobvious from the c<strong>on</strong>text that the proof is finished.Notice that in lemma app_Nil2, as printed out after the final d<strong>on</strong>e, thefree variable xs has been replaced by the unknown ?xs, just as explained inSect. 1.4.Going back to the proof of the first lemmalemma rev_app [simp]: "rev(xs @ ys) = (rev ys) @ (rev xs)"apply(induct_tac xs)apply(auto)we find that this time auto solves the base case, but the inducti<strong>on</strong> step merelysimplifies to1. V a list.rev (list @ ys) = rev ys @ rev list =⇒(rev ys @ rev list) @ a # [] = rev ys @ rev list @ a # []Now we need to remember that @ associates to the right, and that # and @have the same priority (namely the 65 in their infixr annotati<strong>on</strong>). Thus thec<strong>on</strong>clusi<strong>on</strong> really is(rev ys @ rev list) @ (a # []) = rev ys @ (rev list @ (a # []))and the missing lemma is associativity of @.Third Lemma. Aband<strong>on</strong>ing the previous attempt, the can<strong>on</strong>ical proof proceduresucceeds without further ado.lemma app_assoc [simp]: "(xs @ ys) @ zs = xs @ (ys @ zs)"apply(induct_tac xs)apply(auto)d<strong>on</strong>eNow we can prove the first lemma:lemma rev_app [simp]: "rev(xs @ ys) = (rev ys) @ (rev xs)"apply(induct_tac xs)apply(auto)d<strong>on</strong>e


Finally, we prove our main theorem:theorem rev_rev [simp]: "rev(rev xs) = xs"apply(induct_tac xs)apply(auto)d<strong>on</strong>e2.3 An Introductory Proof 15The final end tells <strong>Isabelle</strong> to close the current theory because we are finishedwith its development:endThe complete proof script is shown in Fig. 2.2. The c<strong>on</strong>catenati<strong>on</strong> ofFigs. 2.1 and 2.2 c<strong>on</strong>stitutes the complete theory ToyList and should residein file ToyList.thy.lemma app_Nil2 [simp]: "xs @ [] = xs"apply(induct_tac xs)apply(auto)d<strong>on</strong>elemma app_assoc [simp]: "(xs @ ys) @ zs = xs @ (ys @ zs)"apply(induct_tac xs)apply(auto)d<strong>on</strong>elemma rev_app [simp]: "rev(xs @ ys) = (rev ys) @ (rev xs)"apply(induct_tac xs)apply(auto)d<strong>on</strong>etheorem rev_rev [simp]: "rev(rev xs) = xs"apply(induct_tac xs)apply(auto)d<strong>on</strong>eendFigure 2.2. Proofs about ListsReview This is the end of our toy proof. It should have familiarized youwith– the standard theorem proving procedure: state a goal (lemma or theorem);proceed with proof until a separate lemma is required; prove that lemma;come back to the original goal.– a specific procedure that works well for functi<strong>on</strong>al programs: inducti<strong>on</strong>followed by all-out simplificati<strong>on</strong> via auto.– a basic repertoire of proof commands.


16 2. Functi<strong>on</strong>al Programming in <strong>HOL</strong>!!It is tempting to think that all lemmas should have the simp attribute justbecause this was the case in the example above. However, in that example alllemmas were equati<strong>on</strong>s, and the right-hand side was simpler than the left-handside — an ideal situati<strong>on</strong> for simplificati<strong>on</strong> purposes. Unless this is clearly the case,novices should refrain from awarding a lemma the simp attribute, which has aglobal effect. Instead, lemmas can be applied locally where they are needed, whichis discussed in the following chapter.2.4 Some Helpful CommandsThis secti<strong>on</strong> discusses a few basic commands for manipulating the proof stateand can be skipped by casual readers.There are two kinds of commands used during a proof: the actual proofcommands and auxiliary commands for examining the proof state and c<strong>on</strong>trollingthe display. Simple proof commands are of the form apply(method),where method is typically induct_tac or auto. All such theorem proving operati<strong>on</strong>sare referred to as methods, and further <strong>on</strong>es are introduced throughoutthe tutorial. Unless stated otherwise, you may assume that a methodattacks merely the first subgoal. An excepti<strong>on</strong> is auto, which tries to solve allsubgoals.The most useful auxiliary commands are as follows:Modifying the order of subgoals: defer moves the first subgoal to the endand prefer n moves subgoal n to the fr<strong>on</strong>t.Printing theorems: thm name 1 . . . name n prints the named theorems.Reading terms and types: term string reads, type-checks and prints thegiven string as a term in the current c<strong>on</strong>text; the inferred type is outputas well. typ string reads and prints the given string as a type in thecurrent c<strong>on</strong>text.Further commands are found in the <strong>Isabelle</strong>/Isar Reference Manual [38].Clicking <strong>on</strong> the State butt<strong>on</strong> redisplays the current proof state. This is helpfulin case commands like thm have overwritten it.We now examine <strong>Isabelle</strong>’s functi<strong>on</strong>al programming c<strong>on</strong>structs systematically,starting with inductive datatypes.2.5 DatatypesInductive datatypes are part of almost every n<strong>on</strong>-trivial applicati<strong>on</strong> of <strong>HOL</strong>.First we take another look at an important example, the datatype of lists,before we turn to datatypes in general. The secti<strong>on</strong> closes with a case study.


2.5 Datatypes 172.5.1 ListsLists are <strong>on</strong>e of the essential datatypes in computing. We expect that you arealready familiar with their basic operati<strong>on</strong>s. Theory ToyList is <strong>on</strong>ly a smallfragment of <strong>HOL</strong>’s predefined theory List 1 . The latter c<strong>on</strong>tains many furtheroperati<strong>on</strong>s. For example, the functi<strong>on</strong>s hd (“head”) and tl (“tail”) returnthe first element and the remainder of a list. (However, pattern matching isusually preferable to hd and tl.) Also available are higher-order functi<strong>on</strong>s likemap and filter. Theory List also c<strong>on</strong>tains more syntactic sugar: [x 1 ,. . . ,x n ]abbreviates x 1 #. . . #x n #[]. In the rest of the tutorial we always use <strong>HOL</strong>’spredefined lists by building <strong>on</strong> theory Main.!!Looking ahead to sets and quanifiers in Part II: The best way to express thatsome element x is in a list xs is x ∈ set xs, where set is a functi<strong>on</strong> that turnsa list into the set of its elements. By the same device you can also write boundedquantifiers like ∀x ∈ set xs or embed lists in other set expressi<strong>on</strong>s.2.5.2 The General FormatThe general <strong>HOL</strong> datatype definiti<strong>on</strong> is of the formdatatype (α 1 , . . . , α n ) t = C 1 τ 11 . . . τ 1k1 | . . . | C m τ m1 . . . τ mkmwhere α i are distinct type variables (the parameters), C i are distinct c<strong>on</strong>structornames and τ ij are types; it is customary to capitalize the first letterin c<strong>on</strong>structor names. There are a number of restricti<strong>on</strong>s (such as that thetype should not be empty) detailed elsewhere [27]. <strong>Isabelle</strong> notifies you if youviolate them.Laws about datatypes, such as [] ≠ x#xs and (x#xs = y#ys) = (x=y∧ xs=ys), are used automatically during proofs by simplificati<strong>on</strong>. The sameis true for the equati<strong>on</strong>s in primitive recursive functi<strong>on</strong> definiti<strong>on</strong>s.Every 2 datatype t comes equipped with a size functi<strong>on</strong> from t into thenatural numbers (see Sect. 2.6.1 below). For lists, size is just the length, i.e.size [] = 0 and size(x # xs) = size xs + 1. In general, size returns– zero for all c<strong>on</strong>structors that do not have an argument of type t,– <strong>on</strong>e plus the sum of the sizes of all arguments of type t, for all otherc<strong>on</strong>structors.Note that because size is defined <strong>on</strong> every datatype, it is overloaded; <strong>on</strong> listssize is also called length, which is not overloaded. <strong>Isabelle</strong> will always showsize <strong>on</strong> lists as length.1 http://isabelle.in.tum.de/library/<strong>HOL</strong>/List.html2 Except for advanced datatypes where the recursi<strong>on</strong> involves “⇒” as in Sect. 3.4.3.


18 2. Functi<strong>on</strong>al Programming in <strong>HOL</strong>2.5.3 Primitive Recursi<strong>on</strong>Functi<strong>on</strong>s <strong>on</strong> datatypes are usually defined by recursi<strong>on</strong>. In fact, most ofthe time they are defined by what is called primitive recursi<strong>on</strong> over somedatatype t. This means that the recursi<strong>on</strong> equati<strong>on</strong>s must be of the formf x 1 . . . (C y 1 . . . y k ) . . . x n = rsuch that C is a c<strong>on</strong>structor of t and all recursive calls of f in r are of theform f . . . y i . . . for some i. Thus <strong>Isabelle</strong> immediately sees that f terminatesbecause <strong>on</strong>e (fixed!) argument becomes smaller with every recursive call.There must be at most <strong>on</strong>e equati<strong>on</strong> for each c<strong>on</strong>structor. Their order isimmaterial. A more general method for defining total recursive functi<strong>on</strong>s isintroduced in Sect. 3.5.Exercise 2.5.1 Define the datatype of binary trees:datatype ’a tree = Tip | Node "’a tree" ’a "’a tree"Define a functi<strong>on</strong> mirror that mirrors a binary tree by swapping subtreesrecursively. Provelemma mirror_mirror: "mirror(mirror t) = t"Define a functi<strong>on</strong> flatten that flattens a tree into a list by traversing it ininfix order. Provelemma "flatten(mirror t) = rev(flatten t)"2.5.4 Case Expressi<strong>on</strong>s<strong>HOL</strong> also features case-expressi<strong>on</strong>s for analyzing elements of a datatype. Forexample,case xs of [] ⇒ [] | y # ys ⇒ yevaluates to [] if xs is [] and to y if xs is y # ys. (Since the result in bothbranches must be of the same type, it follows that y is of type ’a list andhence that xs is of type ’a list list.)In general, case expressi<strong>on</strong>s are of the formcase e of pattern 1 ⇒ e 1 | . . . | pattern m ⇒ e mLike in functi<strong>on</strong>al programming, patterns are expressi<strong>on</strong>s c<strong>on</strong>sisting of datatypec<strong>on</strong>structors (e.g. [] and #) and variables, including the wildcard “_”.Not all cases need to be covered and the order of cases matters. However,<strong>on</strong>e is well-advised not to wallow in complex patterns because complex casedistincti<strong>on</strong>s tend to induce complex proofs.


!!2.5 Datatypes 19Internally <strong>Isabelle</strong> <strong>on</strong>ly knows about exhaustive case expressi<strong>on</strong>s with n<strong>on</strong>nestedpatterns: pattern i must be of the form C i x i1 . . . x iki and C 1, . . . , C mmust be exactly the c<strong>on</strong>structors of the type of e. More complex case expressi<strong>on</strong>s areautomatically translated into the simpler form up<strong>on</strong> parsing but are not translatedback for printing. This may lead to surprising output.!!Like if, case-expressi<strong>on</strong>s may need to be enclosed in parentheses to indicatetheir scope.2.5.5 Structural Inducti<strong>on</strong> and Case Distincti<strong>on</strong>Inducti<strong>on</strong> is invoked by induct_tac, as we have seen above; it works for anydatatype. In some cases, inducti<strong>on</strong> is overkill and a case distincti<strong>on</strong> over allc<strong>on</strong>structors of the datatype suffices. This is performed by case_tac. Here isa trivial example:lemma "(case xs of [] ⇒ [] | y#ys ⇒ xs) = xs"apply(case_tac xs)results in the proof state1. xs = [] =⇒ (case xs of [] ⇒ [] | y # ys ⇒ xs) = xs2. V a list.xs = a # list =⇒ (case xs of [] ⇒ [] | y # ys ⇒ xs) = xswhich is solved automatically:apply(auto)Note that we do not need to give a lemma a name if we do not intendto refer to it explicitly in the future. Other basic laws about a datatypeare applied automatically during simplificati<strong>on</strong>, so no special methods areprovided for them.!! Inducti<strong>on</strong> is <strong>on</strong>ly allowed <strong>on</strong> free (or V -bound) variables that should not occuram<strong>on</strong>g the assumpti<strong>on</strong>s of the subgoal; see Sect. 9.2.1 for details. Case distincti<strong>on</strong>(case_tac) works for arbitrary terms, which need to be quoted if they aren<strong>on</strong>-atomic. However, apart from V -bound variables, the terms must not c<strong>on</strong>tainvariables that are bound outside. For example, given the goal ∀ xs. xs = [] ∨(∃ y ys. xs = y # ys), case_tac xs will not work as expected because <strong>Isabelle</strong>interprets the xs as a new free variable distinct from the bound xs in the goal.2.5.6 Case Study: Boolean Expressi<strong>on</strong>sThe aim of this case study is twofold: it shows how to model boolean expressi<strong>on</strong>sand some algorithms for manipulating them, and it dem<strong>on</strong>strates thec<strong>on</strong>structs introduced above.


20 2. Functi<strong>on</strong>al Programming in <strong>HOL</strong>Modelling Boolean Expressi<strong>on</strong>s. We want to represent boolean expressi<strong>on</strong>sbuilt up from variables and c<strong>on</strong>stants by negati<strong>on</strong> and c<strong>on</strong>juncti<strong>on</strong>. Thefollowing datatype serves exactly that purpose:datatype boolex = C<strong>on</strong>st bool | Var nat | Neg boolex| And boolex boolexThe two c<strong>on</strong>stants are represented by C<strong>on</strong>st True and C<strong>on</strong>st False. Variablesare represented by terms of the form Var n, where n is a natural number(type nat). For example, the formula P 0 ∧ ¬P 1 is represented by the termAnd (Var 0) (Neg (Var 1)).The Value of a Boolean Expressi<strong>on</strong>. The value of a boolean expressi<strong>on</strong>depends <strong>on</strong> the value of its variables. Hence the functi<strong>on</strong> value takes an additi<strong>on</strong>alparameter, an envir<strong>on</strong>ment of type nat ⇒ bool, which maps variablesto their values:primrec "value" :: "boolex ⇒ (nat ⇒ bool) ⇒ bool" where"value (C<strong>on</strong>st b) env = b" |"value (Var x) env = env x" |"value (Neg b) env = (¬ value b env)" |"value (And b c) env = (value b env ∧ value c env)"If-Expressi<strong>on</strong>s. An alternative and often more efficient (because in a certainsense can<strong>on</strong>ical) representati<strong>on</strong> are so-called If-expressi<strong>on</strong>s built up fromc<strong>on</strong>stants (CIF), variables (VIF) and c<strong>on</strong>diti<strong>on</strong>als (IF):datatype ifex = CIF bool | VIF nat | IF ifex ifex ifexThe evaluati<strong>on</strong> of If-expressi<strong>on</strong>s proceeds as for boolex:primrec valif :: "ifex ⇒ (nat ⇒ bool) ⇒ bool" where"valif (CIF b) env = b" |"valif (VIF x) env = env x" |"valif (IF b t e) env = (if valif b env then valif t envelse valif e env)"C<strong>on</strong>verting Boolean and If-Expressi<strong>on</strong>s. The type boolex is close tothe customary representati<strong>on</strong> of logical formulae, whereas ifex is designedfor efficiency. It is easy to translate from boolex into ifex:primrec bool2if :: "boolex ⇒ ifex" where"bool2if (C<strong>on</strong>st b) = CIF b" |"bool2if (Var x) = VIF x" |"bool2if (Neg b) = IF (bool2if b) (CIF False) (CIF True)" |"bool2if (And b c) = IF (bool2if b) (bool2if c) (CIF False)"At last, we have something we can verify: that bool2if preserves the valueof its argument:lemma "valif (bool2if b) env = value b env"The proof is can<strong>on</strong>ical:apply(induct_tac b)


apply(auto)d<strong>on</strong>e2.5 Datatypes 21In fact, all proofs in this case study look exactly like this. Hence we do notshow them below.More interesting is the transformati<strong>on</strong> of If-expressi<strong>on</strong>s into a normalform where the first argument of IF cannot be another IF but must be ac<strong>on</strong>stant or variable. Such a normal form can be computed by repeatedlyreplacing a subterm of the form IF (IF b x y) z u by IF b (IF x z u) (IFy z u), which has the same value. The following primitive recursive functi<strong>on</strong>sperform this task:primrec normif :: "ifex ⇒ ifex ⇒ ifex ⇒ ifex" where"normif (CIF b) t e = IF (CIF b) t e" |"normif (VIF x) t e = IF (VIF x) t e" |"normif (IF b t e) u f = normif b (normif t u f) (normif e u f)"primrec norm :: "ifex ⇒ ifex" where"norm (CIF b) = CIF b" |"norm (VIF x) = VIF x" |"norm (IF b t e) = normif b (norm t) (norm e)"Their interplay is tricky; we leave it to you to develop an intuitive understanding.Fortunately, <strong>Isabelle</strong> can help us to verify that the transformati<strong>on</strong>preserves the value of the expressi<strong>on</strong>:theorem "valif (norm b) env = valif b env"The proof is can<strong>on</strong>ical, provided we first show the following simplificati<strong>on</strong>lemma, which also helps to understand what normif does:lemma [simp]:"∀ t e. valif (normif b t e) env = valif (IF b t e) env"Note that the lemma does not have a name, but is implicitly used in theproof of the theorem shown above because of the [simp] attribute.But how can we be sure that norm really produces a normal form in theabove sense? We define a functi<strong>on</strong> that tests If-expressi<strong>on</strong>s for normality:primrec normal :: "ifex ⇒ bool" where"normal(CIF b) = True" |"normal(VIF x) = True" |"normal(IF b t e) = (normal t ∧ normal e ∧(case b of CIF b ⇒ True | VIF x ⇒ True | IF x y z ⇒ False))"Now we prove normal (norm b). Of course, this requires a lemma about normalityof normif:lemma [simp]: "∀ t e. normal(normif b t e) = (normal t ∧ normal e)"How do we come up with the required lemmas? Try to prove the maintheorems without them and study carefully what auto leaves unproved. Thiscan provide the clue. The necessity of universal quantificati<strong>on</strong> (∀ t e) in thetwo lemmas is explained in Sect. 3.2


22 2. Functi<strong>on</strong>al Programming in <strong>HOL</strong>Exercise 2.5.2 We strengthen the definiti<strong>on</strong> of a normal If-expressi<strong>on</strong> asfollows: the first argument of all IFs must be a variable. Adapt the abovedevelopment to this changed requirement. (Hint: you may need to formulatesome of the goals as implicati<strong>on</strong>s (−→) rather than equalities (=).)2.6 Some Basic TypesThis secti<strong>on</strong> introduces the types of natural numbers and ordered pairs. Alsodescribed is type opti<strong>on</strong>, which is useful for modelling excepti<strong>on</strong>al cases.2.6.1 Natural NumbersThe type nat of natural numbers is predefined to have the c<strong>on</strong>structors 0and Suc. It behaves as if it were declared like this:datatype nat = 0 | Suc natIn particular, there are case-expressi<strong>on</strong>s, for examplecase n of 0 ⇒ 0 | Suc m ⇒ mprimitive recursi<strong>on</strong>, for exampleprimrec sum :: "nat ⇒ nat" where"sum 0 = 0" |"sum (Suc n) = Suc n + sum n"and inducti<strong>on</strong>, for examplelemma "sum n + sum n = n*(Suc n)"apply(induct_tac n)apply(auto)d<strong>on</strong>eThe arithmetic operati<strong>on</strong>s +, -, *, div, mod, min and max are predefined,as are the relati<strong>on</strong>s ≤ and


!!!!2.6 Some Basic Types 23The symbols > and ≥ are merely syntax: x > y stands for y < x and similaryfor ≥ and ≤.C<strong>on</strong>stant 1::nat is defined to equal Suc 0. This definiti<strong>on</strong> (see Sect. 2.7.2) isunfolded automatically by some tactics (like auto, simp and arith) but not byothers (especially the single step tactics in Chapter 5). If you need the full set ofnumerals, see Sect. 8.4.1. Novices are advised to stick to 0 and Suc.Both auto and simp (a method introduced below, Sect. 3.1) prove simplearithmetic goals automatically:lemma "[[ ¬ m < n; m < n + (1::nat) ]] =⇒ m = n"For efficiency’s sake, this built-in prover ignores quantified formulae, manylogical c<strong>on</strong>nectives, and all arithmetic operati<strong>on</strong>s apart from additi<strong>on</strong>. Inc<strong>on</strong>sequence, auto and simp cannot prove this slightly more complex goal:lemma "m ≠ (n::nat) =⇒ m < n ∨ n < m"The method arith is more general. It attempts to prove the first subgoalprovided it is a linear arithmetic formula. Such formulas may involve theusual logical c<strong>on</strong>nectives (¬, ∧, ∨, −→, =, ∀ , ∃ ), the relati<strong>on</strong>s =, ≤ and


24 2. Functi<strong>on</strong>al Programming in <strong>HOL</strong>– There is also the type unit, which c<strong>on</strong>tains exactly <strong>on</strong>e element denotedby (). This type can be viewed as a degenerate product with 0 comp<strong>on</strong>ents.– Products, like type nat, are datatypes, which means in particular thatinduct_tac and case_tac are applicable to terms of product type. Bothsplit the term into a number of variables corresp<strong>on</strong>ding to the tuple structure(up to 7 comp<strong>on</strong>ents).– Tuples with more than two or three comp<strong>on</strong>ents become unwieldy; recordsare preferable.For more informati<strong>on</strong> <strong>on</strong> pairs and records see Chapter 8.2.6.3 Datatype opti<strong>on</strong>Our final datatype is very simple but still eminently useful:datatype ’a opti<strong>on</strong> = N<strong>on</strong>e | Some ’aFrequently <strong>on</strong>e needs to add a distinguished element to some existing type.For example, type t opti<strong>on</strong> can model the result of a computati<strong>on</strong> that mayeither terminate with an error (represented by N<strong>on</strong>e) or return some valuev (represented by Some v). Similarly, nat extended with ∞ can be modeledby type nat opti<strong>on</strong>. In both cases <strong>on</strong>e could define a new datatype withcustomized c<strong>on</strong>structors like Error and Infinity, but it is often simpler touse opti<strong>on</strong>. For an applicati<strong>on</strong> see Sect. 3.4.4.2.7 Definiti<strong>on</strong>sA definiti<strong>on</strong> is simply an abbreviati<strong>on</strong>, i.e. a new name for an existing c<strong>on</strong>structi<strong>on</strong>.In particular, definiti<strong>on</strong>s cannot be recursive. <strong>Isabelle</strong> offers definiti<strong>on</strong>s<strong>on</strong> the level of types and terms. Those <strong>on</strong> the type level are called typesyn<strong>on</strong>yms; those <strong>on</strong> the term level are simply called definiti<strong>on</strong>s.2.7.1 Type Syn<strong>on</strong>ymsType syn<strong>on</strong>yms are similar to those found in ML. They are created by atypes command:types number = natgate = "bool ⇒ bool ⇒ bool"(’a,’b)alist = "(’a × ’b)list"Internally all syn<strong>on</strong>yms are fully expanded. As a c<strong>on</strong>sequence <strong>Isabelle</strong>’s outputnever c<strong>on</strong>tains syn<strong>on</strong>yms. Their main purpose is to improve the readabilityof theories. Syn<strong>on</strong>yms can be used just like any other type.


2.8 The Definiti<strong>on</strong>al Approach 252.7.2 C<strong>on</strong>stant Definiti<strong>on</strong>sN<strong>on</strong>recursive definiti<strong>on</strong>s can be made with the definiti<strong>on</strong> command, forexample nand and xor gates (based <strong>on</strong> type gate above):definiti<strong>on</strong> nand :: gate where "nand A B ≡ ¬(A ∧ B)"definiti<strong>on</strong> xor :: gate where "xor A B ≡ A ∧ ¬B ∨ ¬A ∧ B"The symbol ≡ is a special form of equality that must be used in c<strong>on</strong>stantdefiniti<strong>on</strong>s. Pattern-matching is not allowed: each definiti<strong>on</strong> must be of theform f x 1 . . . x n ≡ t. Secti<strong>on</strong> 3.1.6 explains how definiti<strong>on</strong>s are used in proofs.The default name of each definiti<strong>on</strong> is f _def, where f is the name of thedefined c<strong>on</strong>stant.!!A comm<strong>on</strong> mistake when writing definiti<strong>on</strong>s is to introduce extra free variables<strong>on</strong> the right-hand side. C<strong>on</strong>sider the following, flawed definiti<strong>on</strong> (where dvdmeans “divides”):"prime p ≡ 1 < p ∧ (m dvd p −→ m = 1 ∨ m = p)"<strong>Isabelle</strong> rejects this “definiti<strong>on</strong>” because of the extra m <strong>on</strong> the right-hand side, whichwould introduce an inc<strong>on</strong>sistency (why?). The correct versi<strong>on</strong> is"prime p ≡ 1 < p ∧ (∀ m. m dvd p −→ m = 1 ∨ m = p)"2.8 The Definiti<strong>on</strong>al ApproachAs we pointed out at the beginning of the chapter, asserting arbitrary axiomssuch as f (n) = f (n) + 1 can easily lead to c<strong>on</strong>tradicti<strong>on</strong>s. In order toavoid this danger, we advocate the definiti<strong>on</strong>al rather than the axiomatic approach:introduce new c<strong>on</strong>cepts by definiti<strong>on</strong>s. However, <strong>Isabelle</strong>/<strong>HOL</strong> seemsto support many richer definiti<strong>on</strong>al c<strong>on</strong>structs, such as primrec. The pointis that <strong>Isabelle</strong> reduces such c<strong>on</strong>structs to first principles. For example, eachprimrec functi<strong>on</strong> definiti<strong>on</strong> is turned into a proper (n<strong>on</strong>recursive!) definiti<strong>on</strong>from which the user-supplied recursi<strong>on</strong> equati<strong>on</strong>s are automatically proved.This process is hidden from the user, who does not have to understand thedetails. Other commands described later, like fun and inductive, work similarly.This strict adherence to the definiti<strong>on</strong>al approach reduces the risk ofsoundness errors.


3. More Functi<strong>on</strong>al ProgrammingThe purpose of this chapter is to deepen your understanding of the c<strong>on</strong>ceptsencountered so far and to introduce advanced forms of datatypes andrecursive functi<strong>on</strong>s. The first two secti<strong>on</strong>s give a structured presentati<strong>on</strong> oftheorem proving by simplificati<strong>on</strong> (Sect. 3.1) and discuss important heuristicsfor inducti<strong>on</strong> (Sect. 3.2). You can skip them if you are not planning toperform proofs yourself. We then present a case study: a compiler for expressi<strong>on</strong>s(Sect. 3.3). Advanced datatypes, including those involving functi<strong>on</strong>spaces, are covered in Sect. 3.4; it closes with another case study, search trees(“tries”). Finally we introduce fun, a general form of recursive functi<strong>on</strong> definiti<strong>on</strong>that goes well bey<strong>on</strong>d primrec (Sect. 3.5).3.1 Simplificati<strong>on</strong>So far we have proved our theorems by auto, which simplifies all subgoals.In fact, auto can do much more than that. To go bey<strong>on</strong>d toy examples, youneed to understand the ingredients of auto. This secti<strong>on</strong> covers the methodthat auto always applies first, simplificati<strong>on</strong>.Simplificati<strong>on</strong> is <strong>on</strong>e of the central theorem proving tools in <strong>Isabelle</strong> andmany other systems. The tool itself is called the simplifier. This secti<strong>on</strong>introduces the many features of the simplifier and is required reading if youintend to perform proofs. Later <strong>on</strong>, Sect. 9.1 explains some more advancedfeatures and a little bit of how the simplifier works. The serious student shouldread that secti<strong>on</strong> as well, in particular to understand why the simplifier didsomething unexpected.3.1.1 What is Simplificati<strong>on</strong>?In its most basic form, simplificati<strong>on</strong> means repeated applicati<strong>on</strong> of equati<strong>on</strong>sfrom left to right. For example, taking the rules for @ and applying them tothe term [0,1] @ [] results in a sequence of simplificati<strong>on</strong> steps:(0#1#[]) @ [] 0#((1#[]) @ []) 0#(1#([] @ [])) 0#1#[]This is also known as term rewriting and the equati<strong>on</strong>s are referred to asrewrite rules. “Rewriting” is more h<strong>on</strong>est than “simplificati<strong>on</strong>” because theterms do not necessarily become simpler in the process.


28 3. More Functi<strong>on</strong>al ProgrammingThe simplifier proves arithmetic goals as described in Sect. 2.6.1 above.Arithmetic expressi<strong>on</strong>s are simplified using built-in procedures that go bey<strong>on</strong>dmere rewrite rules. New simplificati<strong>on</strong> procedures can be coded andinstalled, but they are definitely not a matter for this tutorial.3.1.2 Simplificati<strong>on</strong> RulesTo facilitate simplificati<strong>on</strong>, the attribute [simp] declares theorems to be simplificati<strong>on</strong>rules, which the simplifier will use automatically. In additi<strong>on</strong>,datatype and primrec declarati<strong>on</strong>s (and a few others) implicitly declaresome simplificati<strong>on</strong> rules. Explicit definiti<strong>on</strong>s are not declared as simplificati<strong>on</strong>rules automatically!Nearly any theorem can become a simplificati<strong>on</strong> rule. The simplifier willtry to transform it into an equati<strong>on</strong>. For example, the theorem ¬ P is turnedinto P = False. The details are explained in Sect. 9.1.2.The simplificati<strong>on</strong> attribute of theorems can be turned <strong>on</strong> and off:declare theorem-name[simp]declare theorem-name[simp del]Only equati<strong>on</strong>s that really simplify, like rev (rev xs) = xs and xs @ [] = xs,should be declared as default simplificati<strong>on</strong> rules. More specific <strong>on</strong>es should<strong>on</strong>ly be used selectively and should not be made default. Distributivity laws,for example, alter the structure of terms and can produce an exp<strong>on</strong>entialblow-up instead of simplificati<strong>on</strong>. A default simplificati<strong>on</strong> rule may need tobe disabled in certain proofs. Frequent changes in the simplificati<strong>on</strong> status ofa theorem may indicate an unwise use of defaults.!!Simplificati<strong>on</strong> can run forever, for example if both f (x) = g(x) and g(x) = f (x)are simplificati<strong>on</strong> rules. It is the user’s resp<strong>on</strong>sibility not to include simplificati<strong>on</strong>rules that can lead to n<strong>on</strong>terminati<strong>on</strong>, either <strong>on</strong> their own or in combinati<strong>on</strong> withother simplificati<strong>on</strong> rules.!!It is inadvisable to toggle the simplificati<strong>on</strong> attribute of a theorem from a parenttheory A in a child theory B for good. The reas<strong>on</strong> is that if some theory Cis based both <strong>on</strong> B and (via a different path) <strong>on</strong> A, it is not defined what thesimplificati<strong>on</strong> attribute of that theorem will be in C : it could be either.3.1.3 The simp MethodThe general format of the simplificati<strong>on</strong> method issimp list of modifierswhere the list of modifiers fine tunes the behaviour and may be empty. Specificmodifiers are discussed below. Most if not all of the proofs seen so far


3.1 Simplificati<strong>on</strong> 29could have been performed with simp instead of auto, except that simp attacks<strong>on</strong>ly the first subgoal and may thus need to be repeated — use simp_allto simplify all subgoals. If nothing changes, simp fails.3.1.4 Adding and Deleting Simplificati<strong>on</strong> RulesIf a certain theorem is merely needed in a few proofs by simplificati<strong>on</strong>, we d<strong>on</strong>ot need to make it a global simplificati<strong>on</strong> rule. Instead we can modify theset of simplificati<strong>on</strong> rules used in a simplificati<strong>on</strong> step by adding rules to itand/or deleting rules from it. The two modifiers for this areadd: list of theorem namesdel: list of theorem namesOr you can use a specific list of theorems and omit all others:<strong>on</strong>ly: list of theorem namesIn this example, we invoke the simplifier, adding two distributive laws:apply(simp add: mod_mult_distrib add_mult_distrib)3.1.5 Assumpti<strong>on</strong>sBy default, assumpti<strong>on</strong>s are part of the simplificati<strong>on</strong> process: they are usedas simplificati<strong>on</strong> rules and are simplified themselves. For example:lemma "[[ xs @ zs = ys @ xs; [] @ xs = [] @ [] ]] =⇒ ys = zs"apply simpd<strong>on</strong>eThe sec<strong>on</strong>d assumpti<strong>on</strong> simplifies to xs = [], which in turn simplifies the firstassumpti<strong>on</strong> to zs = ys, thus reducing the c<strong>on</strong>clusi<strong>on</strong> to ys = ys and henceto True.In some cases, using the assumpti<strong>on</strong>s can lead to n<strong>on</strong>terminati<strong>on</strong>:lemma "∀ x. f x = g (f (g x)) =⇒ f [] = f [] @ []"An unmodified applicati<strong>on</strong> of simp loops. The culprit is the simplificati<strong>on</strong> rulef x = g (f (g x)), which is extracted from the assumpti<strong>on</strong>. (<strong>Isabelle</strong> noticescertain simple forms of n<strong>on</strong>terminati<strong>on</strong> but not this <strong>on</strong>e.) The problem canbe circumvented by telling the simplifier to ignore the assumpti<strong>on</strong>s:apply(simp (no_asm))d<strong>on</strong>eThree modifiers influence the treatment of assumpti<strong>on</strong>s:(no_asm) means that assumpti<strong>on</strong>s are completely ignored.(no_asm_simp) means that the assumpti<strong>on</strong>s are not simplified but are usedin the simplificati<strong>on</strong> of the c<strong>on</strong>clusi<strong>on</strong>.


30 3. More Functi<strong>on</strong>al Programming(no_asm_use) means that the assumpti<strong>on</strong>s are simplified but are not used inthe simplificati<strong>on</strong> of each other or the c<strong>on</strong>clusi<strong>on</strong>.Only <strong>on</strong>e of the modifiers is allowed, and it must precede all other modifiers.3.1.6 Rewriting with Definiti<strong>on</strong>sC<strong>on</strong>stant definiti<strong>on</strong>s (Sect. 2.7.2) can be used as simplificati<strong>on</strong> rules, but bydefault they are not: the simplifier does not expand them automatically.Definiti<strong>on</strong>s are intended for introducing abstract c<strong>on</strong>cepts and not merely asabbreviati<strong>on</strong>s. Of course, we need to expand the definiti<strong>on</strong> initially, but <strong>on</strong>cewe have proved enough abstract properties of the new c<strong>on</strong>stant, we can forgetits original definiti<strong>on</strong>. This style makes proofs more robust: if the definiti<strong>on</strong>has to be changed, <strong>on</strong>ly the proofs of the abstract properties will be affected.For example, givendefiniti<strong>on</strong> xor :: "bool ⇒ bool ⇒ bool" where"xor A B ≡ (A ∧ ¬B) ∨ (¬A ∧ B)"we may want to provelemma "xor A (¬A)"Typically, we begin by unfolding some definiti<strong>on</strong>s:apply(simp <strong>on</strong>ly: xor_def)In this particular case, the resulting goal1. A ∧ ¬ ¬ A ∨ ¬ A ∧ ¬ Acan be proved by simplificati<strong>on</strong>. Thus we could have proved the lemma outrightbyapply(simp add: xor_def)Of course we can also unfold definiti<strong>on</strong>s in the middle of a proof.!!If you have defined f x y ≡ t then you can <strong>on</strong>ly unfold occurrences of f with atleast two arguments. This may be helpful for unfolding f selectively, but it mayalso get in the way. Defining f ≡ λx y. t allows to unfold all occurrences of f .There is also the special method unfold which merely unfolds <strong>on</strong>e orseveral definiti<strong>on</strong>s, as in apply(unfold xor_def). This is can be useful insituati<strong>on</strong>s where simp does too much. Warning: unfold acts <strong>on</strong> all subgoals!3.1.7 Simplifying let-Expressi<strong>on</strong>sProving a goal c<strong>on</strong>taining let-expressi<strong>on</strong>s almost invariably requires the letc<strong>on</strong>structsto be expanded at some point. Since let. . . =. . . in. . . is just syntacticsugar for the predefined c<strong>on</strong>stant Let, expanding let-c<strong>on</strong>structs meansrewriting with Let_def:


3.1 Simplificati<strong>on</strong> 31lemma "(let xs = [] in xs@ys@xs) = ys"apply(simp add: Let_def)d<strong>on</strong>eIf, in a particular c<strong>on</strong>text, there is no danger of a combinatorial explosi<strong>on</strong>of nested lets, you could even simplify with Let_def by default:declare Let_def [simp]3.1.8 C<strong>on</strong>diti<strong>on</strong>al Simplificati<strong>on</strong> RulesSo far all examples of rewrite rules were equati<strong>on</strong>s. The simplifier also acceptsc<strong>on</strong>diti<strong>on</strong>al equati<strong>on</strong>s, for examplelemma hd_C<strong>on</strong>s_tl[simp]: "xs ≠ [] =⇒ hd xs # tl xs = xs"apply(case_tac xs, simp, simp)d<strong>on</strong>eNote the use of “,” to string together a sequence of methods. Assumingthat the simplificati<strong>on</strong> rule (rev xs = []) = (xs = []) is present as well, thelemma below is proved by plain simplificati<strong>on</strong>:lemma "xs ≠ [] =⇒ hd(rev xs) # tl(rev xs) = rev xs"The c<strong>on</strong>diti<strong>on</strong>al equati<strong>on</strong> hd_C<strong>on</strong>s_tl above can simplify hd (rev xs) # tl(rev xs) to rev xs because the corresp<strong>on</strong>ding prec<strong>on</strong>diti<strong>on</strong> rev xs ≠ [] simplifiesto xs ≠ [], which is exactly the local assumpti<strong>on</strong> of the subgoal.3.1.9 Automatic Case SplitsGoals c<strong>on</strong>taining if-expressi<strong>on</strong>s are usually proved by case distincti<strong>on</strong> <strong>on</strong> theboolean c<strong>on</strong>diti<strong>on</strong>. Here is an example:lemma "∀ xs. if xs = [] then rev xs = [] else rev xs ≠ []"The goal can be split by a special method, split:apply(split split_if)1. ∀ xs. (xs = [] −→ rev xs = []) ∧ (xs ≠ [] −→ rev xs ≠ [])where split_if is a theorem that expresses splitting of ifs. Because splittingthe ifs is usually the right proof strategy, the simplifier does it automatically.Try apply(simp) <strong>on</strong> the initial goal above.This splitting idea generalizes from if to case. Let us simplify a caseanalysis over lists:lemma "(case xs of [] ⇒ zs | y#ys ⇒ y#(ys@zs)) = xs@zs"apply(split list.split)1. (xs = [] −→ zs = xs @ zs) ∧(∀ a list. xs = a # list −→ a # list @ zs = xs @ zs)


32 3. More Functi<strong>on</strong>al ProgrammingThe simplifier does not split case-expressi<strong>on</strong>s, as it does if-expressi<strong>on</strong>s, becausewith recursive datatypes it could lead to n<strong>on</strong>terminati<strong>on</strong>. Instead, thesimplifier has a modifier split for adding splitting rules explicitly. The lemmaabove can be proved in <strong>on</strong>e step byapply(simp split: list.split)whereas apply(simp) al<strong>on</strong>e will not succeed.Every datatype t comes with a theorem t.split which can be declaredto be a split rule either locally as above, or by giving it the split attributeglobally:declare list.split [split]The split attribute can be removed with the del modifier, either locallyapply(simp split del: split_if)or globally:declare list.split [split del]Polished proofs typically perform splitting within simp rather than invokingthe split method. However, if a goal c<strong>on</strong>tains several if and caseexpressi<strong>on</strong>s, the split method can be helpful in selectively exploring theeffects of splitting.The split rules shown above are intended to affect <strong>on</strong>ly the subgoal’sc<strong>on</strong>clusi<strong>on</strong>. If you want to split an if or case-expressi<strong>on</strong> in the assumpti<strong>on</strong>s,you have to apply split_if_asm or t.split_asm:lemma "if xs = [] then ys ≠ [] else ys = [] =⇒ xs @ ys ≠ []"apply(split split_if_asm)Unlike splitting the c<strong>on</strong>clusi<strong>on</strong>, this step creates two separate subgoals, whichhere can be solved by simp_all:1. [[xs = []; ys ≠ []]] =⇒ xs @ ys ≠ []2. [[xs ≠ []; ys = []]] =⇒ xs @ ys ≠ []If you need to split both in the assumpti<strong>on</strong>s and the c<strong>on</strong>clusi<strong>on</strong>, use t.splitswhich subsumes t.split and t.split_asm. Analogously, there is if_splits.!!The simplifier merely simplifies the c<strong>on</strong>diti<strong>on</strong> of an if but not the then orelse parts. The latter are simplified <strong>on</strong>ly after the c<strong>on</strong>diti<strong>on</strong> reduces to Trueor False, or after splitting. The same is true for case-expressi<strong>on</strong>s: <strong>on</strong>ly the selectoris simplified at first, until either the expressi<strong>on</strong> reduces to <strong>on</strong>e of the cases or it issplit.3.1.10 TracingUsing the simplifier effectively may take a bit of experimentati<strong>on</strong>. Set theProof General flag <strong>Isabelle</strong> > Settings > Trace Simplifier to get a better ideaof what is going <strong>on</strong>:


3.1 Simplificati<strong>on</strong> 33lemma "rev [a] = []"apply(simp)produces the following trace in Proof General’s Trace buffer:[1]Applying instance of rewrite rule "List.rev.simps_2":rev (?x1 # ?xs1) ≡ rev ?xs1 @ [?x1][1]Rewriting:rev [a] ≡ rev [] @ [a][1]Applying instance of rewrite rule "List.rev.simps_1":rev [] ≡ [][1]Rewriting:rev [] ≡ [][1]Applying instance of rewrite rule "List.op @.append_Nil":[] @ ?y ≡ ?y[1]Rewriting:[] @ [a] ≡ [a][1]Applying instance of rewrite rule?x2 # ?t1 = ?t1 ≡ False[1]Rewriting:[a] = [] ≡ FalseThe trace lists each rule being applied, both in its general form and theinstance being used. The [i] in fr<strong>on</strong>t (where above i is always 1) indicatesthat we are inside the ith invocati<strong>on</strong> of the simplifier. Each attempt to applya c<strong>on</strong>diti<strong>on</strong>al rule shows the rule followed by the trace of the (recursive!)simplificati<strong>on</strong> of the c<strong>on</strong>diti<strong>on</strong>s, the latter prefixed by [i + 1] instead of[i]. Another source of recursive invocati<strong>on</strong>s of the simplifier are proofs ofarithmetic formulae.Many other hints about the simplifier’s acti<strong>on</strong>s may appear.In more complicated cases, the trace can be very lengthy. Thus it is advisableto reset the Trace Simplifier flag after having obtained the desiredtrace.3.1.11 Finding Theorems<strong>Isabelle</strong>’s large database of proved theorems offers a powerful search engine.Its chief limitati<strong>on</strong> is its restricti<strong>on</strong> to the theories currently loaded.The search engine is started by clicking <strong>on</strong> Proof General’s Find ic<strong>on</strong>. You specifyyour search textually in the input buffer at the bottom of the window.


34 3. More Functi<strong>on</strong>al ProgrammingThe simplest form of search finds theorems c<strong>on</strong>taining specified patterns.A pattern can be any term (even a single identifier). It may c<strong>on</strong>tain “ ”, awildcard standing for any term. Here are some examples:length"_ # _ = _ # _""_ + _""_ * (_ - (_::nat))"Specifying types, as shown in the last example, c<strong>on</strong>strains searches involvingoverloaded operators.!!Always use “ ” rather than variable names: searching for "x + y" will usuallynot find any matching theorems because they would need to c<strong>on</strong>tain x and yliterally. When searching for infix operators, do not just type in the symbol, suchas +, but a proper term such as "_ + _". This remark applies to more complicatedsyntaxes, too.If you are looking for rewrite rules (possibly c<strong>on</strong>diti<strong>on</strong>al) that could simplifysome term, prefix the pattern with simp:.simp: "_ * (_ + _)"This finds all equati<strong>on</strong>s—not just those with a simp attribute—whose c<strong>on</strong>clusi<strong>on</strong>has the form_ * (_ + _) = . . .It <strong>on</strong>ly finds equati<strong>on</strong>s that can simplify the given pattern at the root, notsomewhere inside: for example, equati<strong>on</strong>s of the form _ + _ = . . . do notmatch.You may also search for theorems by name—you merely need to specifya substring. For example, you could search for all commutativity theoremslike this:name: commThis retrieves all theorems whose name c<strong>on</strong>tains comm.Search criteria can also be negated by prefixing them with “-”. For example,-name: Listfinds theorems whose name does not c<strong>on</strong>tain List. You can use this to excludeparticular theories from the search: the l<strong>on</strong>g name of a theorem c<strong>on</strong>tains thename of the theory it comes from.Finallly, different search criteria can be combined arbitrarily. The effectis c<strong>on</strong>juctive: Find returns the theorems that satisfy all of the criteria. Forexample,"_ + _" -"_ - _" -simp: "_ * (_ + _)" name: assoclooks for theorems c<strong>on</strong>taining plus but not minus, and which do not simplify_ * (_ + _) at the root, and whose name c<strong>on</strong>tains assoc.Further search criteria are explained in Sect. 5.14.


3.2 Inducti<strong>on</strong> Heuristics 35Proof General keeps a history of all your search expressi<strong>on</strong>s. If you click <strong>on</strong> Find,you can use the arrow keys to scroll through previous searches and just modifythem. This saves you having to type in lengthy expressi<strong>on</strong>s again and again.3.2 Inducti<strong>on</strong> HeuristicsThe purpose of this secti<strong>on</strong> is to illustrate some simple heuristics for inductiveproofs. The first <strong>on</strong>e we have already menti<strong>on</strong>ed in our initial example:Theorems about recursive functi<strong>on</strong>s are proved by inducti<strong>on</strong>.In case the functi<strong>on</strong> has more than <strong>on</strong>e argumentDo inducti<strong>on</strong> <strong>on</strong> argument number i if the functi<strong>on</strong> is defined byrecursi<strong>on</strong> in argument number i.When we look at the proof of (xs@ys) @ zs = xs @ (ys@zs) in Sect. 2.3 wefind– @ is recursive in the first argument– xs occurs <strong>on</strong>ly as the first argument of @– both ys and zs occur at least <strong>on</strong>ce as the sec<strong>on</strong>d argument of @Hence it is natural to perform inducti<strong>on</strong> <strong>on</strong> xs.The key heuristic, and the main point of this secti<strong>on</strong>, is to generalize thegoal before inducti<strong>on</strong>. The reas<strong>on</strong> is simple: if the goal is too specific, theinducti<strong>on</strong> hypothesis is too weak to allow the inducti<strong>on</strong> step to go through.Let us illustrate the idea with an example.Functi<strong>on</strong> rev has quadratic worst-case running time because it calls functi<strong>on</strong>@ for each element of the list and @ is linear in its first argument. A lineartime versi<strong>on</strong> of rev reqires an extra argument where the result is accumulatedgradually, using <strong>on</strong>ly #:primrec itrev :: "’a list ⇒ ’a list ⇒ ’a list" where"itrev [] ys = ys" |"itrev (x#xs) ys = itrev xs (x#ys)"The behaviour of itrev is simple: it reverses its first argument by stackingits elements <strong>on</strong>to the sec<strong>on</strong>d argument, and returning that sec<strong>on</strong>d argumentwhen the first <strong>on</strong>e becomes empty. Note that itrev is tail-recursive: it canbe compiled into a loop.Naturally, we would like to show that itrev does indeed reverse its firstargument provided the sec<strong>on</strong>d <strong>on</strong>e is empty:lemma "itrev xs [] = rev xs"There is no choice as to the inducti<strong>on</strong> variable, and we immediately simplify:apply(induct_tac xs, simp_all)Unfortunately, this attempt does not prove the inducti<strong>on</strong> step:


36 3. More Functi<strong>on</strong>al Programming1. V a list.itrev list [] = rev list =⇒ itrev list [a] = rev list @ [a]The inducti<strong>on</strong> hypothesis is too weak. The fixed argument, [], prevents itfrom rewriting the c<strong>on</strong>clusi<strong>on</strong>. This example suggests a heuristic:Generalize goals for inducti<strong>on</strong> by replacing c<strong>on</strong>stants by variables.Of course <strong>on</strong>e cannot do this naïvely: itrev xs ys = rev xs is just not true.The correct generalizati<strong>on</strong> islemma "itrev xs ys = rev xs @ ys"If ys is replaced by [], the right-hand side simplifies to rev xs, as required.In this instance it was easy to guess the right generalizati<strong>on</strong>. Other situati<strong>on</strong>scan require a good deal of creativity.Although we now have two variables, <strong>on</strong>ly xs is suitable for inducti<strong>on</strong>,and we repeat our proof attempt. Unfortunately, we are still not there:1. V a list.itrev list ys = rev list @ ys =⇒itrev list (a # ys) = rev list @ a # ysThe inducti<strong>on</strong> hypothesis is still too weak, but this time it takes no intuiti<strong>on</strong>to generalize: the problem is that ys is fixed throughout the subgoal, but theinducti<strong>on</strong> hypothesis needs to be applied with a # ys instead of ys. Hencewe prove the theorem for all ys instead of a fixed <strong>on</strong>e:lemma "∀ ys. itrev xs ys = rev xs @ ys"This time inducti<strong>on</strong> <strong>on</strong> xs followed by simplificati<strong>on</strong> succeeds. This leads toanother heuristic for generalizati<strong>on</strong>:Generalize goals for inducti<strong>on</strong> by universally quantifying all free variables(except the inducti<strong>on</strong> variable itself!).This prevents trivial failures like the <strong>on</strong>e above and does not affect the validityof the goal. However, this heuristic should not be applied blindly. It is notalways required, and the additi<strong>on</strong>al quantifiers can complicate matters insome cases. The variables that should be quantified are typically those thatchange in recursive calls.A final point worth menti<strong>on</strong>ing is the orientati<strong>on</strong> of the equati<strong>on</strong> we justproved: the more complex noti<strong>on</strong> (itrev) is <strong>on</strong> the left-hand side, the simpler<strong>on</strong>e (rev) <strong>on</strong> the right-hand side. This c<strong>on</strong>stitutes another, albeit weakheuristic that is not restricted to inducti<strong>on</strong>:The right-hand side of an equati<strong>on</strong> should (in some sense) be simplerthan the left-hand side.This heuristic is tricky to apply because it is not obvious that rev xs @ ys issimpler than itrev xs ys. But see what happens if you try to prove rev xs@ ys = itrev xs ys!


3.3 Case Study: Compiling Expressi<strong>on</strong>s 37If you have tried these heuristics and still find your inducti<strong>on</strong> does not gothrough, and no obvious lemma suggests itself, you may need to generalizeyour propositi<strong>on</strong> even further. This requires insight into the problem at handand is bey<strong>on</strong>d simple rules of thumb. Additi<strong>on</strong>ally, you can read Sect. 9.2 tolearn about some advanced techniques for inductive proofs.Exercise 3.2.1 Define the following additi<strong>on</strong> functi<strong>on</strong>primrec add :: "nat ⇒ nat ⇒ nat" where"add m 0 = m" |"add m (Suc n) = add (Suc m) n"and provelemma "add m n = m+n"Exercise 3.2.2 In Exercise 2.5.1 we defined a functi<strong>on</strong> flatten from treesto lists. The straightforward versi<strong>on</strong> of flatten is based <strong>on</strong> @ and is thus,like rev, quadratic. A linear time versi<strong>on</strong> of flatten again reqires an extraargument, the accumulator. Defineflatten2 :: "’a tree ⇒ ’a list ⇒ ’a list"and provelemma "flatten2 t [] = flatten t"3.3 Case Study: Compiling Expressi<strong>on</strong>sThe task is to develop a compiler from a generic type of expressi<strong>on</strong>s (builtfrom variables, c<strong>on</strong>stants and binary operati<strong>on</strong>s) to a stack machine. Thisgeneric type of expressi<strong>on</strong>s is a generalizati<strong>on</strong> of the boolean expressi<strong>on</strong>sin Sect. 2.5.6. This time we do not commit ourselves to a particular type ofvariables or values but make them type parameters. Neither is there a fixed setof binary operati<strong>on</strong>s: instead the expressi<strong>on</strong> c<strong>on</strong>tains the appropriate functi<strong>on</strong>itself.types ’v binop = "’v ⇒ ’v ⇒ ’v"datatype (’a,’v)expr = Cex ’v| Vex ’a| Bex "’v binop" "(’a,’v)expr" "(’a,’v)expr"The three c<strong>on</strong>structors represent c<strong>on</strong>stants, variables and the applicati<strong>on</strong> ofa binary operati<strong>on</strong> to two subexpressi<strong>on</strong>s.The value of an expressi<strong>on</strong> with respect to an envir<strong>on</strong>ment that mapsvariables to values is easily defined:primrec "value" :: "(’a,’v)expr ⇒ (’a ⇒ ’v) ⇒ ’v" where"value (Cex v) env = v" |"value (Vex a) env = env a" |"value (Bex f e1 e2) env = f (value e1 env) (value e2 env)"


38 3. More Functi<strong>on</strong>al ProgrammingThe stack machine has three instructi<strong>on</strong>s: load a c<strong>on</strong>stant value <strong>on</strong>to thestack, load the c<strong>on</strong>tents of an address <strong>on</strong>to the stack, and apply a binaryoperati<strong>on</strong> to the two topmost elements of the stack, replacing them by theresult. As for expr, addresses and values are type parameters:datatype (’a,’v) instr = C<strong>on</strong>st ’v| Load ’a| Apply "’v binop"The executi<strong>on</strong> of the stack machine is modelled by a functi<strong>on</strong> exec thattakes a list of instructi<strong>on</strong>s, a store (modelled as a functi<strong>on</strong> from addressesto values, just like the envir<strong>on</strong>ment for evaluating expressi<strong>on</strong>s), and a stack(modelled as a list) of values, and returns the stack at the end of the executi<strong>on</strong>— the store remains unchanged:primrec exec :: "(’a,’v)instr list ⇒ (’a⇒’v) ⇒ ’v list ⇒ ’v list"where"exec [] s vs = vs" |"exec (i#is) s vs = (case i ofC<strong>on</strong>st v ⇒ exec is s (v#vs)| Load a ⇒ exec is s ((s a)#vs)| Apply f ⇒ exec is s ((f (hd vs) (hd(tl vs)))#(tl(tl vs))))"Recall that hd and tl return the first element and the remainder of a list.Because all functi<strong>on</strong>s are total, hd is defined even for the empty list, althoughwe do not know what the result is. Thus our model of the machine alwaysterminates properly, although the definiti<strong>on</strong> above does not tell us muchabout the result in situati<strong>on</strong>s where Apply was executed with fewer than twoelements <strong>on</strong> the stack.The compiler is a functi<strong>on</strong> from expressi<strong>on</strong>s to a list of instructi<strong>on</strong>s. Itsdefiniti<strong>on</strong> is obvious:primrec compile :: "(’a,’v)expr ⇒ (’a,’v)instr list" where"compile (Cex v) = [C<strong>on</strong>st v]" |"compile (Vex a) = [Load a]" |"compile (Bex f e1 e2) = (compile e2) @ (compile e1) @ [Apply f]"Now we have to prove the correctness of the compiler, i.e. that the executi<strong>on</strong>of a compiled expressi<strong>on</strong> results in the value of the expressi<strong>on</strong>:theorem "exec (compile e) s [] = [value e s]"This theorem needs to be generalized:theorem "∀ vs. exec (compile e) s vs = (value e s) # vs"It will be proved by inducti<strong>on</strong> <strong>on</strong> e followed by simplificati<strong>on</strong>. First, wemust prove a lemma about executing the c<strong>on</strong>catenati<strong>on</strong> of two instructi<strong>on</strong>sequences:lemma exec_app[simp]:"∀ vs. exec (xs@ys) s vs = exec ys s (exec xs s vs)"This requires inducti<strong>on</strong> <strong>on</strong> xs and ordinary simplificati<strong>on</strong> for the base cases.In the inducti<strong>on</strong> step, simplificati<strong>on</strong> leaves us with a formula that c<strong>on</strong>tains


3.4 Advanced Datatypes 39two case-expressi<strong>on</strong>s over instructi<strong>on</strong>s. Thus we add automatic case splitting,which finishes the proof:apply(induct_tac xs, simp, simp split: instr.split)Note that because both simp_all and auto perform simplificati<strong>on</strong>, they canbe modified in the same way as simp. Thus the proof can be rewritten asapply(induct_tac xs, simp_all split: instr.split)Although this is more compact, it is less clear for the reader of the proof.We could now go back and prove exec (compile e) s [] = [value e s]merely by simplificati<strong>on</strong> with the generalized versi<strong>on</strong> we just proved. However,this is unnecessary because the generalized versi<strong>on</strong> fully subsumes itsinstance.3.4 Advanced DatatypesThis secti<strong>on</strong> presents advanced forms of datatypes: mutual and nested recursi<strong>on</strong>.A series of examples will culminate in a treatment of the trie datastructure.3.4.1 Mutual Recursi<strong>on</strong>Sometimes it is necessary to define two datatypes that depend <strong>on</strong> each other.This is called mutual recursi<strong>on</strong>. As an example c<strong>on</strong>sider a language ofarithmetic and boolean expressi<strong>on</strong>s where– arithmetic expressi<strong>on</strong>s c<strong>on</strong>tain boolean expressi<strong>on</strong>s because there are c<strong>on</strong>diti<strong>on</strong>alexpressi<strong>on</strong>s like “if m < n then n − m else m − n”, and– boolean expressi<strong>on</strong>s c<strong>on</strong>tain arithmetic expressi<strong>on</strong>s because of comparis<strong>on</strong>slike “m < n”.In <strong>Isabelle</strong> this becomesdatatype ’a aexp = IF "’a bexp" "’a aexp" "’a aexp"| Sum "’a aexp" "’a aexp"| Diff "’a aexp" "’a aexp"| Var ’a| Num natand ’a bexp = Less "’a aexp" "’a aexp"| And "’a bexp" "’a bexp"| Neg "’a bexp"Type aexp is similar to expr in Sect. 3.3, except that we have added an IFc<strong>on</strong>structor, fixed the values to be of type nat and declared the two binaryoperati<strong>on</strong>s Sum and Diff. Boolean expressi<strong>on</strong>s can be arithmetic comparis<strong>on</strong>s,c<strong>on</strong>juncti<strong>on</strong>s and negati<strong>on</strong>s. The semantics is given by two evaluati<strong>on</strong> functi<strong>on</strong>s:


40 3. More Functi<strong>on</strong>al Programmingprimrec evala :: "’a aexp ⇒ (’a ⇒ nat) ⇒ nat" andevalb :: "’a bexp ⇒ (’a ⇒ nat) ⇒ bool" where"evala (IF b a1 a2) env =(if evalb b env then evala a1 env else evala a2 env)" |"evala (Sum a1 a2) env = evala a1 env + evala a2 env" |"evala (Diff a1 a2) env = evala a1 env - evala a2 env" |"evala (Var v) env = env v" |"evala (Num n) env = n" |"evalb (Less a1 a2) env = (evala a1 env < evala a2 env)" |"evalb (And b1 b2) env = (evalb b1 env ∧ evalb b2 env)" |"evalb (Neg b) env = (¬ evalb b env)"Both take an expressi<strong>on</strong> and an envir<strong>on</strong>ment (a mapping from variables ’ato values nat) and return its arithmetic/boolean value. Since the datatypesare mutually recursive, so are functi<strong>on</strong>s that operate <strong>on</strong> them. Hence theyneed to be defined in a single primrec secti<strong>on</strong>. Notice the and separatingthe declarati<strong>on</strong>s of evala and evalb. Their defining equati<strong>on</strong>s need not besplit into two groups; the empty line is purely for readability.In the same fashi<strong>on</strong> we also define two functi<strong>on</strong>s that perform substituti<strong>on</strong>:primrec substa :: "(’a ⇒ ’b aexp) ⇒ ’a aexp ⇒ ’b aexp" andsubstb :: "(’a ⇒ ’b aexp) ⇒ ’a bexp ⇒ ’b bexp" where"substa s (IF b a1 a2) =IF (substb s b) (substa s a1) (substa s a2)" |"substa s (Sum a1 a2) = Sum (substa s a1) (substa s a2)" |"substa s (Diff a1 a2) = Diff (substa s a1) (substa s a2)" |"substa s (Var v) = s v" |"substa s (Num n) = Num n" |"substb s (Less a1 a2) = Less (substa s a1) (substa s a2)" |"substb s (And b1 b2) = And (substb s b1) (substb s b2)" |"substb s (Neg b) = Neg (substb s b)"Their first argument is a functi<strong>on</strong> mapping variables to expressi<strong>on</strong>s, the substituti<strong>on</strong>.It is applied to all variables in the sec<strong>on</strong>d argument. As a result,the type of variables in the expressi<strong>on</strong> may change from ’a to ’b. Note thatthere are <strong>on</strong>ly arithmetic and no boolean variables.Now we can prove a fundamental theorem about the interacti<strong>on</strong> betweenevaluati<strong>on</strong> and substituti<strong>on</strong>: applying a substituti<strong>on</strong> s to an expressi<strong>on</strong> aand evaluating the result in an envir<strong>on</strong>ment env yields the same result asevaluati<strong>on</strong> a in the envir<strong>on</strong>ment that maps every variable x to the value ofs(x) under env. If you try to prove this separately for arithmetic or booleanexpressi<strong>on</strong>s (by inducti<strong>on</strong>), you find that you always need the other theoremin the inducti<strong>on</strong> step. Therefore you need to state and prove both theoremssimultaneously:lemma "evala (substa s a) env = evala a (λx. evala (s x) env) ∧evalb (substb s b) env = evalb b (λx. evala (s x) env)"apply(induct_tac a and b)The resulting 8 goals (<strong>on</strong>e for each c<strong>on</strong>structor) are proved in <strong>on</strong>e fell swoop:


apply simp_all3.4 Advanced Datatypes 41In general, given n mutually recursive datatypes τ 1 , . . . , τ n , an inductiveproof expects a goal of the formP 1 (x 1 ) ∧ · · · ∧ P n (x n )where each variable x i is of type τ i . Inducti<strong>on</strong> is started byapply(induct_tac x 1 and ... and x n)Exercise 3.4.1 Define a functi<strong>on</strong> norma of type ’a aexp ⇒ ’a aexp that replacesIFs with complex boolean c<strong>on</strong>diti<strong>on</strong>s by nested IFs; it should eliminatethe c<strong>on</strong>structors And and Neg, leaving <strong>on</strong>ly Less. Prove that norma preservesthe value of an expressi<strong>on</strong> and that the result of norma is really normal, i.e.no more Ands and Negs occur in it. (Hint: proceed as in Sect. 2.5.6 and readthe discussi<strong>on</strong> of type annotati<strong>on</strong>s following lemma subst_id below).3.4.2 Nested Recursi<strong>on</strong>So far, all datatypes had the property that <strong>on</strong> the right-hand side of theirdefiniti<strong>on</strong> they occurred <strong>on</strong>ly at the top-level: directly below a c<strong>on</strong>structor.Now we c<strong>on</strong>sider nested recursi<strong>on</strong>, where the recursive datatype occurs nestedin some other datatype (but not inside itself!). C<strong>on</strong>sider the following modelof terms where functi<strong>on</strong> symbols can be applied to a list of arguments:datatype (’v,’f)"term" = Var ’v | App ’f "(’v,’f)term list"Note that we need to quote term <strong>on</strong> the left to avoid c<strong>on</strong>fusi<strong>on</strong> with the<strong>Isabelle</strong> command term. Parameter ’v is the type of variables and ’f thetype of functi<strong>on</strong> symbols. A mathematical term like f (x, g(y)) becomes Appf [Var x, App g [Var y]], where f, g, x, y are suitable values, e.g. numbersor strings.What complicates the definiti<strong>on</strong> of term is the nested occurrence of terminside list <strong>on</strong> the right-hand side. In principle, nested recursi<strong>on</strong> can be eliminatedin favour of mutual recursi<strong>on</strong> by unfolding the offending datatypes,here list. The result for term would be something likedatatype (’v,’f)"term" = Var ’v | App ’f "(’v,’f)term_list"and (’v,’f)term_list = Nil | C<strong>on</strong>s "(’v,’f)term" "(’v,’f)term_list"Although we do not recommend this unfolding to the user, it shows how tosimulate nested recursi<strong>on</strong> by mutual recursi<strong>on</strong>. Now we return to the initialdefiniti<strong>on</strong> of term using nested recursi<strong>on</strong>.Let us define a substituti<strong>on</strong> functi<strong>on</strong> <strong>on</strong> terms. Because terms involve termlists, we need to define two substituti<strong>on</strong> functi<strong>on</strong>s simultaneously:primrecsubst :: "(’v⇒(’v,’f)term) ⇒ (’v,’f)term⇒ (’v,’f)term" and


42 3. More Functi<strong>on</strong>al Programmingsubsts:: "(’v⇒(’v,’f)term) ⇒ (’v,’f)term list ⇒ (’v,’f)term list"where"subst s (Var x) = s x" |subst_App:"subst s (App f ts) = App f (substs s ts)" |"substs s [] = []" |"substs s (t # ts) = subst s t # substs s ts"Individual equati<strong>on</strong>s in a primrec definiti<strong>on</strong> may be named as shown forsubst_App. The significance of this device will become apparent below.Similarly, when proving a statement about terms inductively, we needto prove a related statement about term lists simultaneously. For example,the fact that the identity substituti<strong>on</strong> does not change a term needs to bestrengthened and proved as follows:lemma subst_id: "subst Var t = (t ::(’v,’f)term) ∧substs Var ts = (ts::(’v,’f)term list)"apply(induct_tac t and ts, simp_all)d<strong>on</strong>eNote that Var is the identity substituti<strong>on</strong> because by definiti<strong>on</strong> it leaves variablesunchanged: subst Var (Var x) = Var x. Note also that the type annotati<strong>on</strong>sare necessary because otherwise there is nothing in the goal to enforcethat both halves of the goal talk about the same type parameters (’v,’f).As a result, inducti<strong>on</strong> would fail because the two halves of the goal would beunrelated.Exercise 3.4.2 The fact that substituti<strong>on</strong> distributes over compositi<strong>on</strong> canbe expressed roughly as follows:subst (f ◦ g) t = subst f (subst g t)Correct this statement (you will find that it does not type-check), strengthenit, and prove it. (Note: ◦ is functi<strong>on</strong> compositi<strong>on</strong>; its definiti<strong>on</strong> is found intheorem o_def).Exercise 3.4.3 Define a functi<strong>on</strong> trev of type (’v, ’f) Nested.term ⇒(’v, ’f) Nested.term that recursively reverses the order of arguments of allfuncti<strong>on</strong> symbols in a term. Prove that trev (trev t) = t.The experienced functi<strong>on</strong>al programmer may feel that our definiti<strong>on</strong> ofsubst is too complicated in that substs is unnecessary. The App-case can bedefined directly assubst s (App f ts) = App f (map (subst s) ts)where map is the standard list functi<strong>on</strong> such that map f [x1,...,xn] = [fx1,...,f xn]. This is true, but <strong>Isabelle</strong> insists <strong>on</strong> the c<strong>on</strong>junctive format.Fortunately, we can easily prove that the suggested equati<strong>on</strong> holds:


3.4 Advanced Datatypes 43lemma [simp]: "subst s (App f ts) = App f (map (subst s) ts)"apply(induct_tac ts, simp_all)d<strong>on</strong>eWhat is more, we can now disable the old defining equati<strong>on</strong> as a simplificati<strong>on</strong>rule:declare subst_App [simp del]The advantage is that now we have replaced substs by map, we can profit fromthe large number of pre-proved lemmas about map. Unfortunately, inductiveproofs about type term are still awkward because they expect a c<strong>on</strong>juncti<strong>on</strong>.One could derive a new inducti<strong>on</strong> principle as well (see Sect. 9.2.3), butsimpler is to stop using primrec and to define functi<strong>on</strong>s with fun instead.Simple uses of fun are described in Sect. 3.5 below. Advanced applicati<strong>on</strong>s,including functi<strong>on</strong>s over nested datatypes like term, are discussed in a separatetutorial [19].Of course, you may also combine mutual and nested recursi<strong>on</strong> of datatypes.For example, c<strong>on</strong>structor Sum in Sect. 3.4.1 could take a list of expressi<strong>on</strong>sas its argument: Sum "’a aexp list".3.4.3 The Limits of Nested Recursi<strong>on</strong>How far can we push nested recursi<strong>on</strong>? By the unfolding argument above,we can reduce nested to mutual recursi<strong>on</strong> provided the nested recursi<strong>on</strong> <strong>on</strong>lyinvolves previously defined datatypes. This does not include functi<strong>on</strong>s:datatype t = C "t ⇒ bool"This declarati<strong>on</strong> is a real can of worms. In <strong>HOL</strong> it must be ruled out becauseit requires a type t such that t and its power set t ⇒ bool have the samecardinality — an impossibility. For the same reas<strong>on</strong> it is not possible to allowrecursi<strong>on</strong> involving the type t set, which is isomorphic to t ⇒ bool.Fortunately, a limited form of recursi<strong>on</strong> involving functi<strong>on</strong> spaces is permitted:the recursive type may occur <strong>on</strong> the right of a functi<strong>on</strong> arrow, butnever <strong>on</strong> the left. Hence the above can of worms is ruled out but the followingexample of a potentially infinitely branching tree is accepted:datatype (’a,’i)bigtree = Tip | Br ’a "’i ⇒ (’a,’i)bigtree"Parameter ’a is the type of values stored in the Branches of the tree, whereas’i is the index type over which the tree branches. If ’i is instantiated to bool,the result is a binary tree; if it is instantiated to nat, we have an infinitelybranching tree because each node has as many subtrees as there are naturalnumbers. How can we possibly write down such a tree? Using functi<strong>on</strong>alnotati<strong>on</strong>! For example, the termBr 0 (λi. Br i (λn. Tip))


44 3. More Functi<strong>on</strong>al Programmingof type (nat, nat) bigtree is the tree whose root is labeled with 0 and whoseith subtree is labeled with i and has merely Tips as further subtrees.Functi<strong>on</strong> map_bt applies a functi<strong>on</strong> to all labels in a bigtree:primrec map_bt :: "(’a ⇒ ’b) ⇒ (’a,’i)bigtree ⇒ (’b,’i)bigtree"where"map_bt f Tip = Tip" |"map_bt f (Br a F) = Br (f a) (λi. map_bt f (F i))"This is a valid primrec definiti<strong>on</strong> because the recursive calls of map_bt involve<strong>on</strong>ly subtrees of F, which is itself a subterm of the left-hand side. Thusterminati<strong>on</strong> is assured. The seas<strong>on</strong>ed functi<strong>on</strong>al programmer might try expressingλi. map_bt f (F i) as map_bt f ◦ F, which <strong>Isabelle</strong> however willreject. Applying map_bt to <strong>on</strong>ly <strong>on</strong>e of its arguments makes the terminati<strong>on</strong>proof less obvious.The following lemma has a simple proof by inducti<strong>on</strong>:lemma "map_bt (g o f) T = map_bt g (map_bt f T)"apply(induct_tac T, simp_all)d<strong>on</strong>eBecause of the functi<strong>on</strong> type, the proof state after inducti<strong>on</strong> looks unusual.Notice the quantified inducti<strong>on</strong> hypothesis:1. map_bt (g ◦ f) Tip = map_bt g (map_bt f Tip)2. V a F. ( V x. map_bt (g ◦ f) (F x) = map_bt g (map_bt f (F x))) =⇒map_bt (g ◦ f) (Br a F) = map_bt g (map_bt f (Br a F))If you need nested recursi<strong>on</strong> <strong>on</strong> the left of a functi<strong>on</strong> arrow, there arealternatives to pure <strong>HOL</strong>. In the Logic for Computable Functi<strong>on</strong>s (LCF),types likedatatype lam = C "lam → lam"do indeed make sense [29]. Note the different arrow, → instead of ⇒, expressingthe type of c<strong>on</strong>tinuous functi<strong>on</strong>s. There is even a versi<strong>on</strong> of LCF <strong>on</strong> topof <strong>HOL</strong>, called <strong>HOL</strong>CF [22].3.4.4 Case Study: TriesTries are a classic search tree data structure [18] for fast indexing with strings.Figure 3.1 gives a graphical example of a trie c<strong>on</strong>taining the words “all”, “an”,“ape”, “can”, “car” and “cat”. When searching a string in a trie, the letters ofthe string are examined sequentially. Each letter determines which subtrie tosearch next. In this case study we model tries as a datatype, define a lookupand an update functi<strong>on</strong>, and prove that they behave as expected.Proper tries associate some value with each string. Since the informati<strong>on</strong>is stored <strong>on</strong>ly in the final node associated with the string, many nodes do notcarry any value. This distincti<strong>on</strong> is modeled with the help of the predefineddatatype opti<strong>on</strong> (see Sect. 2.6.3).


3.4 Advanced Datatypes 45✑◗ ✑ ◗◗◗a ✑✑c✑✑ ◗ ◗◗l n p a✑✑ ◗ ◗◗l e n r tFigure 3.1. A Sample TrieTo minimize running time, each node of a trie should c<strong>on</strong>tain an array thatmaps letters to subtries. We have chosen a representati<strong>on</strong> where the subtriesare held in an associati<strong>on</strong> list, i.e. a list of (letter,trie) pairs. Abstracting overthe alphabet ’a and the values ’v we define a trie as follows:datatype (’a,’v)trie = Trie "’v opti<strong>on</strong>" "(’a * (’a,’v)trie)list"The first comp<strong>on</strong>ent is the opti<strong>on</strong>al value, the sec<strong>on</strong>d comp<strong>on</strong>ent the associati<strong>on</strong>list of subtries. This is an example of nested recursi<strong>on</strong> involving products,which is fine because products are datatypes as well. We define two selectorfuncti<strong>on</strong>s:primrec "value" :: "(’a,’v)trie ⇒ ’v opti<strong>on</strong>" where"value(Trie ov al) = ov"primrec alist :: "(’a,’v)trie ⇒ (’a * (’a,’v)trie)list" where"alist(Trie ov al) = al"Associati<strong>on</strong> lists come with a generic lookup functi<strong>on</strong>. Its result involves typeopti<strong>on</strong> because a lookup can fail:primrec assoc :: "(’key * ’val)list ⇒ ’key ⇒ ’val opti<strong>on</strong>" where"assoc [] x = N<strong>on</strong>e" |"assoc (p#ps) x =(let (a,b) = p in if a=x then Some b else assoc ps x)"Now we can define the lookup functi<strong>on</strong> for tries. It descends into the trieexamining the letters of the search string <strong>on</strong>e by <strong>on</strong>e. As recursi<strong>on</strong> <strong>on</strong> lists issimpler than <strong>on</strong> tries, let us express this as primitive recursi<strong>on</strong> <strong>on</strong> the searchstring argument:primrec lookup :: "(’a,’v)trie ⇒ ’a list ⇒ ’v opti<strong>on</strong>" where"lookup t [] = value t" |"lookup t (a#as) = (case assoc (alist t) a ofN<strong>on</strong>e ⇒ N<strong>on</strong>e| Some at ⇒ lookup at as)"As a first simple property we prove that looking up a string in the emptytrie Trie N<strong>on</strong>e [] always returns N<strong>on</strong>e. The proof merely distinguishes thetwo cases whether the search string is empty or not:lemma [simp]: "lookup (Trie N<strong>on</strong>e []) as = N<strong>on</strong>e"


46 3. More Functi<strong>on</strong>al Programmingapply(case_tac as, simp_all)d<strong>on</strong>eThings begin to get interesting with the definiti<strong>on</strong> of an update functi<strong>on</strong>that adds a new (string, value) pair to a trie, overwriting the old valueassociated with that string:primrec update:: "(’a,’v)trie ⇒ ’a list ⇒ ’v ⇒ (’a,’v)trie" where"update t [] v = Trie (Some v) (alist t)" |"update t (a#as) v =(let tt = (case assoc (alist t) a ofN<strong>on</strong>e ⇒ Trie N<strong>on</strong>e [] | Some at ⇒ at)in Trie (value t) ((a,update tt as v) # alist t))"The base case is obvious. In the recursive case the subtrie tt associatedwith the first letter a is extracted, recursively updated, and then placed infr<strong>on</strong>t of the associati<strong>on</strong> list. The old subtrie associated with a is still in theassociati<strong>on</strong> list but no l<strong>on</strong>ger accessible via assoc. Clearly, there is room herefor optimizati<strong>on</strong>s!Before we start <strong>on</strong> any proofs about update we tell the simplifier to expandall lets and to split all case-c<strong>on</strong>structs over opti<strong>on</strong>s:declare Let_def[simp] opti<strong>on</strong>.split[split]The reas<strong>on</strong> becomes clear when looking (probably after a failed proof attempt)at the body of update: it c<strong>on</strong>tains both let and a case distincti<strong>on</strong>over type opti<strong>on</strong>.Our main goal is to prove the correct interacti<strong>on</strong> of update and lookup:theorem "∀ t v bs. lookup (update t as v) bs =(if as=bs then Some v else lookup t bs)"Our plan is to induct <strong>on</strong> as; hence the remaining variables are quantified.From the definiti<strong>on</strong>s it is clear that inducti<strong>on</strong> <strong>on</strong> either as or bs is required.The choice of as is guided by the intuiti<strong>on</strong> that simplificati<strong>on</strong> of lookup mightbe easier if update has already been simplified, which can <strong>on</strong>ly happen if asis instantiated. The start of the proof is c<strong>on</strong>venti<strong>on</strong>al:apply(induct_tac as, auto)Unfortunately, this time we are left with three intimidating looking subgoals:1. ... =⇒ lookup ... bs = lookup t bs2. ... =⇒ lookup ... bs = lookup t bs3. ... =⇒ lookup ... bs = lookup t bsClearly, if we want to make headway we have to instantiate bs as well now.It turns out that instead of inducti<strong>on</strong>, case distincti<strong>on</strong> suffices:apply(case_tac[!] bs, auto)d<strong>on</strong>eAll methods ending in tac take an opti<strong>on</strong>al first argument that specifies therange of subgoals they are applied to, where [!] means all subgoals, i.e. [1-3]in our case. Individual subgoal numbers, e.g. [2] are also allowed.


3.5 Total Recursive Functi<strong>on</strong>s: fun 47This proof may look surprisingly straightforward. However, note that thiscomes at a cost: the proof script is unreadable because the intermediateproof states are invisible, and we rely <strong>on</strong> the (possibly brittle) magic of auto(simp_all will not do — try it) to split the subgoals of the inducti<strong>on</strong> up insuch a way that case distincti<strong>on</strong> <strong>on</strong> bs makes sense and solves the proof.Exercise 3.4.4 Modify update (and its type) such that it allows both inserti<strong>on</strong>and deleti<strong>on</strong> of entries with a single functi<strong>on</strong>. Prove the corresp<strong>on</strong>dingversi<strong>on</strong> of the main theorem above. Optimize your functi<strong>on</strong> such that itshrinks tries after deleti<strong>on</strong> if possible.Exercise 3.4.5 Write an improved versi<strong>on</strong> of update that does not sufferfrom the space leak (pointed out above) caused by not deleting overwrittenentries from the associati<strong>on</strong> list. Prove the main theorem for your improvedupdate.Exercise 3.4.6 C<strong>on</strong>ceptually, each node c<strong>on</strong>tains a mapping from letters toopti<strong>on</strong>al subtries. Above we have implemented this by means of an associati<strong>on</strong>list. Replay the development replacing (’a × (’a, ’v) trie) list with ’a⇀ (’a, ’v) trie.3.5 Total Recursive Functi<strong>on</strong>s: funAlthough many total functi<strong>on</strong>s have a natural primitive recursive definiti<strong>on</strong>,this is not always the case. Arbitrary total recursive functi<strong>on</strong>s can be definedby means of fun: you can use full pattern matching, recursi<strong>on</strong> need not involvedatatypes, and terminati<strong>on</strong> is proved by showing that the arguments of allrecursive calls are smaller in a suitable sense. In this secti<strong>on</strong> we restrict ourselvesto functi<strong>on</strong>s where <strong>Isabelle</strong> can prove terminati<strong>on</strong> automatically. Moreadvanced functi<strong>on</strong> definiti<strong>on</strong>s, including user supplied terminati<strong>on</strong> proofs,nested recursi<strong>on</strong> and partiality, are discussed in a separate tutorial [19].3.5.1 Definiti<strong>on</strong>Here is a simple example, the Fib<strong>on</strong>acci functi<strong>on</strong>:fun fib :: "nat ⇒ nat" where"fib 0 = 0" |"fib (Suc 0) = 1" |"fib (Suc(Suc x)) = fib x + fib (Suc x)"This resembles ordinary functi<strong>on</strong>al programming languages. Note the obligatorywhere and |. Command fun declares and defines the functi<strong>on</strong> in <strong>on</strong>ego. <strong>Isabelle</strong> establishes terminati<strong>on</strong> automatically because fib’s argumentdecreases in every recursive call.


48 3. More Functi<strong>on</strong>al ProgrammingSlightly more interesting is the inserti<strong>on</strong> of a fixed element between anytwo elements of a list:fun sep :: "’a ⇒ ’a list ⇒ ’a list" where"sep a [] = []" |"sep a [x] = [x]" |"sep a (x#y#zs) = x # a # sep a (y#zs)"This time the length of the list decreases with the recursive call; the firstargument is irrelevant for terminati<strong>on</strong>.Pattern matching need not be exhaustive and may employ wildcards:fun last :: "’a list ⇒ ’a" where"last [x] = x" |"last (_#y#zs) = last (y#zs)"Overlapping patterns are disambiguated by taking the order of equati<strong>on</strong>sinto account, just as in functi<strong>on</strong>al programming:fun sep1 :: "’a ⇒ ’a list ⇒ ’a list" where"sep1 a (x#y#zs) = x # a # sep1 a (y#zs)" |"sep1 _ xs = xs"To guarantee that the sec<strong>on</strong>d equati<strong>on</strong> can <strong>on</strong>ly be applied if the first <strong>on</strong>edoes not match, <strong>Isabelle</strong> internally replaces the sec<strong>on</strong>d equati<strong>on</strong> by the twopossibilities that are left: sep1 a [] = [] and sep1 a [x] = [x]. Thus thefuncti<strong>on</strong>s sep and sep1 are identical.Because of its pattern matching syntax, fun is also useful for the definiti<strong>on</strong>of n<strong>on</strong>-recursive functi<strong>on</strong>s:fun swap12 :: "’a list ⇒ ’a list" where"swap12 (x#y#zs) = y#x#zs" |"swap12 zs = zs"After a functi<strong>on</strong> f has been defined via fun, its defining equati<strong>on</strong>s (or variantsderived from them) are available under the name f .simps as theorems.For example, look (via thm) at sep.simps and sep1.simps to see that theydefine the same functi<strong>on</strong>. What is more, those equati<strong>on</strong>s are automaticallydeclared as simplificati<strong>on</strong> rules.3.5.2 Terminati<strong>on</strong><strong>Isabelle</strong>’s automatic terminati<strong>on</strong> prover for fun has a fixed noti<strong>on</strong> of the size(of type nat) of an argument. The size of a natural number is the numberitself. The size of a list is its length. For the general case see Sect. 2.5.2.A recursive functi<strong>on</strong> is accepted if fun can show that the size of <strong>on</strong>e fixedargument becomes smaller with each recursive call.More generally, fun allows any lexicographic combinati<strong>on</strong> of size measuresin case there are multiple arguments. For example, the following versi<strong>on</strong> ofAckermann’s functi<strong>on</strong> is accepted:fun ack2 :: "nat ⇒ nat ⇒ nat" where


"ack2 n 0 = Suc n" |"ack2 0 (Suc m) = ack2 (Suc 0) m" |"ack2 (Suc n) (Suc m) = ack2 (ack2 n (Suc m)) m"3.5 Total Recursive Functi<strong>on</strong>s: fun 49The order of arguments has no influence <strong>on</strong> whether fun can prove terminati<strong>on</strong>of a functi<strong>on</strong>. For more details see elsewhere [6].3.5.3 Simplificati<strong>on</strong>Up<strong>on</strong> a successful terminati<strong>on</strong> proof, the recursi<strong>on</strong> equati<strong>on</strong>s become simplificati<strong>on</strong>rules, just as with primrec. In most cases this works fine, but thereis a subtle problem that must be menti<strong>on</strong>ed: simplificati<strong>on</strong> may not terminatebecause of automatic splitting of if. Let us look at an example:fun gcd :: "nat ⇒ nat ⇒ nat" where"gcd m n = (if n=0 then m else gcd n (m mod n))"The sec<strong>on</strong>d argument decreases with each recursive call. The terminati<strong>on</strong>c<strong>on</strong>diti<strong>on</strong>n ≠ 0 =⇒ m mod n < nis proved automatically because it is already present as a lemma in <strong>HOL</strong>. Thusthe recursi<strong>on</strong> equati<strong>on</strong> becomes a simplificati<strong>on</strong> rule. Of course the equati<strong>on</strong>is n<strong>on</strong>terminating if we are allowed to unfold the recursive call inside theelse branch, which is why programming languages and our simplifier d<strong>on</strong>’tdo that. Unfortunately the simplifier does something else that leads to thesame problem: it splits each if-expressi<strong>on</strong> unless its c<strong>on</strong>diti<strong>on</strong> simplifies toTrue or False. For example, simplificati<strong>on</strong> reducesgcd m n = kin <strong>on</strong>e step to(if n = 0 then m else gcd n (m mod n)) = kwhere the c<strong>on</strong>diti<strong>on</strong> cannot be reduced further, and splitting leads to(n = 0 −→ m = k) ∧ (n ≠ 0 −→ gcd n (m mod n) = k)Since the recursive call gcd n (m mod n) is no l<strong>on</strong>ger protected by an if, itis unfolded again, which leads to an infinite chain of simplificati<strong>on</strong> steps.Fortunately, this problem can be avoided in many different ways.The most radical soluti<strong>on</strong> is to disable the offending theorem split_if,as shown in Sect. 3.1.9. However, we do not recommend this approach: youwill often have to invoke the rule explicitly when if is involved.If possible, the definiti<strong>on</strong> should be given by pattern matching <strong>on</strong> theleft rather than if <strong>on</strong> the right. In the case of gcd the following alternativedefiniti<strong>on</strong> suggests itself:fun gcd1 :: "nat ⇒ nat ⇒ nat" where"gcd1 m 0 = m" |"gcd1 m n = gcd1 n (m mod n)"


50 3. More Functi<strong>on</strong>al ProgrammingThe order of equati<strong>on</strong>s is important: it hides the side c<strong>on</strong>diti<strong>on</strong> n ≠ 0. Unfortunately,not all c<strong>on</strong>diti<strong>on</strong>als can be expressed by pattern matching.A simple alternative is to replace if by case, which is also available forbool and is not split automatically:fun gcd2 :: "nat ⇒ nat ⇒ nat" where"gcd2 m n = (case n=0 of True ⇒ m | False ⇒ gcd2 n (m mod n))"This is probably the neatest soluti<strong>on</strong> next to pattern matching, and it isalways available.A final alternative is to replace the offending simplificati<strong>on</strong> rules by derivedc<strong>on</strong>diti<strong>on</strong>al <strong>on</strong>es. For gcd it means we have to prove these lemmas:lemma [simp]: "gcd m 0 = m"apply(simp)d<strong>on</strong>elemma [simp]: "n ≠ 0 =⇒ gcd m n = gcd n (m mod n)"apply(simp)d<strong>on</strong>eSimplificati<strong>on</strong> terminates for these proofs because the c<strong>on</strong>diti<strong>on</strong> of the ifsimplifies to True or False. Now we can disable the original simplificati<strong>on</strong>rule:declare gcd.simps [simp del]3.5.4 Inducti<strong>on</strong>Having defined a functi<strong>on</strong> we might like to prove something about it. Since thefuncti<strong>on</strong> is recursive, the natural proof principle is again inducti<strong>on</strong>. But thistime the structural form of inducti<strong>on</strong> that comes with datatypes is unlikelyto work well — otherwise we could have defined the functi<strong>on</strong> by primrec.Therefore fun automatically proves a suitable inducti<strong>on</strong> rule f .induct thatfollows the recursi<strong>on</strong> pattern of the particular functi<strong>on</strong> f . We call this recursi<strong>on</strong>inducti<strong>on</strong>. Roughly speaking, it requires you to prove for each funequati<strong>on</strong> that the property you are trying to establish holds for the left-handside provided it holds for all recursive calls <strong>on</strong> the right-hand side. Here is asimple example involving the predefined map functi<strong>on</strong>al <strong>on</strong> lists:lemma "map f (sep x xs) = sep (f x) (map f xs)"Note that map f xs is the result of applying f to all elements of xs. We provethis lemma by recursi<strong>on</strong> inducti<strong>on</strong> over sep:apply(induct_tac x xs rule: sep.induct)The resulting proof state has three subgoals corresp<strong>on</strong>ding to the threeclauses for sep:


3.5 Total Recursive Functi<strong>on</strong>s: fun 511. V a. map f (sep a []) = sep (f a) (map f [])2. V a x. map f (sep a [x]) = sep (f a) (map f [x])3. V a x y zs.map f (sep a (y # zs)) = sep (f a) (map f (y # zs)) =⇒map f (sep a (x # y # zs)) = sep (f a) (map f (x # y # zs))The rest is pure simplificati<strong>on</strong>:apply simp_alld<strong>on</strong>eThe proof goes smoothly because the inducti<strong>on</strong> rule follows the recursi<strong>on</strong> ofsep. Try proving the above lemma by structural inducti<strong>on</strong>, and you find thatyou need an additi<strong>on</strong>al case distincti<strong>on</strong>.In general, the format of invoking recursi<strong>on</strong> inducti<strong>on</strong> isapply(induct_tac x 1 . . . x n rule: f .induct)where x 1 . . . x n is a list of free variables in the subgoal and f the name of afuncti<strong>on</strong> that takes n arguments. Usually the subgoal will c<strong>on</strong>tain the termfx 1 . . . x n but this need not be the case. The inducti<strong>on</strong> rules do not menti<strong>on</strong>f at all. Here is sep.induct:[[ V a. P a [];V a x. P a [x];V a x y zs. P a (y # zs) =⇒ P a (x # y # zs)]]=⇒ P u vIt merely says that in order to prove a property P of u and v you need toprove it for the three cases where v is the empty list, the singlet<strong>on</strong> list, andthe list with at least two elements. The final case has an inducti<strong>on</strong> hypothesis:you may assume that P holds for the tail of that list.


4. Presenting TheoriesBy now the reader should have become sufficiently acquainted with elementarytheory development in <strong>Isabelle</strong>/<strong>HOL</strong>. The following interlude describeshow to present theories in a typographically pleasing manner. <strong>Isabelle</strong> providesa rich infrastructure for c<strong>on</strong>crete syntax of the underlying λ-calculuslanguage (see Sect. 4.1), as well as document preparati<strong>on</strong> of theory texts based<strong>on</strong> existing PDF-L A TEX technology (see Sect. 4.2).As pointed out by Leibniz more than 300 years ago, noti<strong>on</strong>s are in principlemore important than notati<strong>on</strong>s, but suggestive textual representati<strong>on</strong> ofideas is vital to reduce the mental effort to comprehend and apply them.4.1 C<strong>on</strong>crete SyntaxThe core c<strong>on</strong>cept of <strong>Isabelle</strong>’s framework for c<strong>on</strong>crete syntax is that of mixfixannotati<strong>on</strong>s. Associated with any kind of c<strong>on</strong>stant declarati<strong>on</strong>, mixfixesaffect both the grammar producti<strong>on</strong>s for the parser and output templates forthe pretty printer.In full generality, parser and pretty printer c<strong>on</strong>figurati<strong>on</strong> is a subtle affair[28]. Your syntax specificati<strong>on</strong>s need to interact properly with the existingsetup of <strong>Isabelle</strong>/Pure and <strong>Isabelle</strong>/<strong>HOL</strong>. To avoid creating ambiguities withexisting elements, it is particularly important to give new syntactic c<strong>on</strong>structsthe right precedence.Below we introduce a few simple syntax declarati<strong>on</strong> forms that alreadycover many comm<strong>on</strong> situati<strong>on</strong>s fairly well.4.1.1 Infix Annotati<strong>on</strong>sSyntax annotati<strong>on</strong>s may be included wherever c<strong>on</strong>stants are declared, such asdefiniti<strong>on</strong> and primrec — and also datatype, which declares c<strong>on</strong>structoroperati<strong>on</strong>s. Type-c<strong>on</strong>structors may be annotated as well, although this is lessfrequently encountered in practice (the infix type × comes to mind).Infix declarati<strong>on</strong>s provide a useful special case of mixfixes. The followingexample of the exclusive-or operati<strong>on</strong> <strong>on</strong> boolean values illustrates typicalinfix declarati<strong>on</strong>s.


54 4. Presenting Theoriesdefiniti<strong>on</strong> xor :: "bool ⇒ bool ⇒ bool" (infixl "[+]" 60)where "A [+] B ≡ (A ∧ ¬ B) ∨ (¬ A ∧ B)"Now xor A B and A [+] B refer to the same expressi<strong>on</strong> internally. Any curriedfuncti<strong>on</strong> with at least two arguments may be given infix syntax. Forpartial applicati<strong>on</strong>s with fewer than two operands, there is a notati<strong>on</strong> usingthe prefix op. For instance, xor without arguments is represented as op [+];together with ordinary functi<strong>on</strong> applicati<strong>on</strong>, this turns xor A into op [+] A.The keyword infixl seen above specifies an infix operator that is nestedto the left: in iterated applicati<strong>on</strong>s the more complex expressi<strong>on</strong> appears <strong>on</strong>the left-hand side, and A [+] B [+] C stands for (A [+] B) [+] C. Similarly,infixr means nesting to the right, reading A [+] B [+] C as A [+] (B [+] C).A n<strong>on</strong>-oriented declarati<strong>on</strong> via infix would render A [+] B [+] C illegal, butdemand explicit parentheses to indicate the intended grouping.The string "[+]" in our annotati<strong>on</strong> refers to the c<strong>on</strong>crete syntax to representthe operator (a literal token), while the number 60 determines theprecedence of the c<strong>on</strong>struct: the syntactic priorities of the arguments andresult. <strong>Isabelle</strong>/<strong>HOL</strong> already uses up many popular combinati<strong>on</strong>s of ASCIIsymbols for its own use, including both + and ++. L<strong>on</strong>ger character combinati<strong>on</strong>sare more likely to be still available for user extensi<strong>on</strong>s, such as our [+].Operator precedences have a range of 0–1000. Very low or high prioritiesare reserved for the meta-logic. <strong>HOL</strong> syntax mainly uses the range of 10–100:the equality infix = is centered at 50; logical c<strong>on</strong>nectives (like ∨ and ∧) arebelow 50; algebraic <strong>on</strong>es (like + and *) are above 50. User syntax shouldstrive to coexist with comm<strong>on</strong> <strong>HOL</strong> forms, or use the mostly unused range100–900.4.1.2 Mathematical SymbolsC<strong>on</strong>crete syntax based <strong>on</strong> ASCII characters has inherent limitati<strong>on</strong>s. Mathematicalnotati<strong>on</strong> demands a larger repertoire of glyphs. Several standardsof extended character sets have been proposed over decades, but n<strong>on</strong>e hasbecome universally available so far. <strong>Isabelle</strong> has its own noti<strong>on</strong> of symbolsas the smallest entities of source text, without referring to internal encodings.There are three kinds of such “generalized characters”:1. 7-bit ASCII characters2. named symbols: \3. named c<strong>on</strong>trol symbols: \Here ident is any sequence of letters. This results in an infinite store ofsymbols, whose interpretati<strong>on</strong> is left to further fr<strong>on</strong>t-end tools. For example,the user-interface of Proof General + X-Symbol and the <strong>Isabelle</strong> documentprocessor (see Sect. 4.2) display the \ symbol as ∀ .A list of standard <strong>Isabelle</strong> symbols is given in [38]. You may introduceyour own interpretati<strong>on</strong> of further symbols by c<strong>on</strong>figuring the appropriate


4.1 C<strong>on</strong>crete Syntax 55fr<strong>on</strong>t-end tool accordingly, e.g. by defining certain L A TEX macros (see alsoSect. 4.2.4). There are also a few predefined c<strong>on</strong>trol symbols, such as \and \ for sub- and superscript of the subsequent printable symbol,respectively. For example, A\\ is output as A ⋆ .A number of symbols are c<strong>on</strong>sidered letters by the <strong>Isabelle</strong> lexer and canbe used as part of identifiers. These are the greek letters α (\), β(\), etc. (excluding λ), special letters like A (\) and A (\),and the c<strong>on</strong>trol symbols \ and \ for single letter sub andsuper scripts. This means that the input\\\1. \\1 = \\\is recognized as the term ∀ α 1. α 1 = Π A by <strong>Isabelle</strong>. Note that Π A is a singlesyntactic entity, not an exp<strong>on</strong>entiati<strong>on</strong>.Replacing our previous definiti<strong>on</strong> of xor by the following specifies an <strong>Isabelle</strong>symbol for the new operator:definiti<strong>on</strong> xor :: "bool ⇒ bool ⇒ bool" (infixl "⊕" 60)where "A ⊕ B ≡ (A ∧ ¬ B) ∨ (¬ A ∧ B)"The X-Symbol package within Proof General provides several input methodsto enter ⊕ in the text. If all fails <strong>on</strong>e may just type a named entity \by hand; the corresp<strong>on</strong>ding symbol will be displayed after further input.More flexible is to provide alternative syntax forms through the printmode c<strong>on</strong>cept [28]. By c<strong>on</strong>venti<strong>on</strong>, the mode of “xsymbols” is enabled wheneverProof General’s X-Symbol mode or L A TEX output is active. Now c<strong>on</strong>siderthe following hybrid declarati<strong>on</strong> of xor:definiti<strong>on</strong> xor :: "bool ⇒ bool ⇒ bool" (infixl "[+]" 60)where "A [+] B ≡ (A ∧ ¬ B) ∨ (¬ A ∧ B)"notati<strong>on</strong> (xsymbols) xor (infixl "⊕" 60)The notati<strong>on</strong> command associates a mixfix annotati<strong>on</strong> with a known c<strong>on</strong>stant.The print mode specificati<strong>on</strong>, here (xsymbols), is opti<strong>on</strong>al.We may now write A [+] B or A ⊕ B in input, while output uses the nicersyntax of xsymbols whenever that print mode is active. Such an arrangementis particularly useful for interactive development, where users may typeASCII text and see mathematical symbols displayed during proofs.4.1.3 Prefix Annotati<strong>on</strong>sPrefix syntax annotati<strong>on</strong>s are another form of mixfixes [28], without anytemplate arguments or priorities — just some literal syntax. The followingexample associates comm<strong>on</strong> symbols with the c<strong>on</strong>structors of a datatype.datatype currency =Euro nat (" ")| Pounds nat ("£")


56 4. Presenting Theories| Yen nat ("¥")| Dollar nat ("$")Here the mixfix annotati<strong>on</strong>s <strong>on</strong> the rightmost column happen to c<strong>on</strong>sist of asingle <strong>Isabelle</strong> symbol each: \, \, \, and $. Recall thata c<strong>on</strong>structor like Euro actually is a functi<strong>on</strong> nat ⇒ currency. The expressi<strong>on</strong>Euro 10 will be printed as 10; <strong>on</strong>ly the head of the applicati<strong>on</strong> is subject toour c<strong>on</strong>crete syntax. This rather simple form already achieves c<strong>on</strong>formancewith notati<strong>on</strong>al standards of the European Commissi<strong>on</strong>.Prefix syntax works the same way for other commands that introduce newc<strong>on</strong>stants, e.g. primrec.4.1.4 Abbreviati<strong>on</strong>sMixfix syntax annotati<strong>on</strong>s merely decorate particular c<strong>on</strong>stant applicati<strong>on</strong>forms with c<strong>on</strong>crete syntax, for instance replacing xor A B by A ⊕ B. Occasi<strong>on</strong>ally,the relati<strong>on</strong>ship between some piece of notati<strong>on</strong> and its internal formis more complicated. Here we need abbreviati<strong>on</strong>s.Command abbreviati<strong>on</strong> introduces an uninterpreted notati<strong>on</strong>al c<strong>on</strong>stantas an abbreviati<strong>on</strong> for a complex term. Abbreviati<strong>on</strong>s are unfolded up<strong>on</strong>parsing and re-introduced up<strong>on</strong> printing. This provides a simple mechanismfor syntactic macros.A typical use of abbreviati<strong>on</strong>s is to introduce relati<strong>on</strong>al notati<strong>on</strong> for membershipin a set of pairs, replacing (x, y) ∈ sim by x ≈ y. We assume thata c<strong>on</strong>stant sim of type (’a × ’a) set has been introduced at this point.abbreviati<strong>on</strong> sim2 :: "’a ⇒ ’a ⇒ bool" (infix "≈" 50)where "x ≈ y ≡ (x, y) ∈ sim"The given meta-equality is used as a rewrite rule after parsing (replacingx ≈ y by (x,y) ∈ sim) and before printing (turning (x,y) ∈ sim back intox ≈ y). The name of the dummy c<strong>on</strong>stant sim2 does not matter, as l<strong>on</strong>g asit is unique.Another comm<strong>on</strong> applicati<strong>on</strong> of abbreviati<strong>on</strong>s is to provide variant versi<strong>on</strong>sof fundamental relati<strong>on</strong>al expressi<strong>on</strong>s, such as ≠ for negated equalities.The following declarati<strong>on</strong> stems from <strong>Isabelle</strong>/<strong>HOL</strong> itself:abbreviati<strong>on</strong> not_equal :: "’a ⇒ ’a ⇒ bool" (infixl "~=" 50)where "x ~= y ≡ ¬ (x = y)"notati<strong>on</strong> (xsymbols) not_equal (infix "≠" 50)The notati<strong>on</strong> ≠ is introduced separately to restrict it to the xsymbols mode.Abbreviati<strong>on</strong>s are appropriate when the defined c<strong>on</strong>cept is a simple variati<strong>on</strong><strong>on</strong> an existing <strong>on</strong>e. But because of the automatic folding and unfoldingof abbreviati<strong>on</strong>s, they do not scale up well to large hierarchies of c<strong>on</strong>cepts.Abbreviati<strong>on</strong>s do not replace definiti<strong>on</strong>s.Abbreviati<strong>on</strong>s are a simplified form of the general c<strong>on</strong>cept of syntax translati<strong>on</strong>s;even heavier transformati<strong>on</strong>s may be written in ML [28].


4.2 Document Preparati<strong>on</strong> 574.2 Document Preparati<strong>on</strong><strong>Isabelle</strong>/Isar is centered around the c<strong>on</strong>cept of formal proof documents.The outcome of a formal development effort is meant to be a human-readablerecord, presented as browsable PDF file or printed <strong>on</strong> paper. The overalldocument structure follows traditi<strong>on</strong>al mathematical articles, with secti<strong>on</strong>s,intermediate explanati<strong>on</strong>s, definiti<strong>on</strong>s, theorems and proofs.The <strong>Isabelle</strong> document preparati<strong>on</strong> system essentially acts as a fr<strong>on</strong>tendto L A TEX. After checking specificati<strong>on</strong>s and proofs formally, the theorysources are turned into typesetting instructi<strong>on</strong>s in a schematic manner. Thislets you write authentic reports <strong>on</strong> theory developments with little effort:many technical c<strong>on</strong>sistency checks are handled by the system.Here is an example to illustrate the idea of <strong>Isabelle</strong> document preparati<strong>on</strong>.The following datatype definiti<strong>on</strong> of ’a bintree models binarytrees with nodes being decorated by elements of type ’a.datatype ’a bintree =Leaf | Branch ’a "’a bintree" "’a bintree"The datatype inducti<strong>on</strong> rule generated here is of the form[[P Leaf; V a bintree1 bintree2.[[P bintree1; P bintree2]] =⇒ P (Branch a bintree1 bintree2)]]=⇒ P bintreeThe above document output has been produced as follows:text {*The following datatype definiti<strong>on</strong> of @{text "’a bintree"}models binary trees with nodes being decorated by elementsof type @{typ ’a}.*}datatype ’a bintree =Leaf | Branch ’a "’a bintree" "’a bintree"text {*\noindent The datatype inducti<strong>on</strong> rule generated here isof the form @{thm [display] bintree.induct [no_vars]}*}Here we have augmented the theory by formal comments (using text blocks),the informal parts may again refer to formal entities by means of “antiquotati<strong>on</strong>s”(such as @{text "’a bintree"} or @{typ ’a}), see also Sect. 4.2.3.


58 4. Presenting Theories4.2.1 <strong>Isabelle</strong> Sessi<strong>on</strong>sIn c<strong>on</strong>trast to the highly interactive mode of <strong>Isabelle</strong>/Isar theory development,the document preparati<strong>on</strong> stage essentially works in batch-mode. An<strong>Isabelle</strong> sessi<strong>on</strong> c<strong>on</strong>sists of a collecti<strong>on</strong> of source files that may c<strong>on</strong>tributeto an output document. Each sessi<strong>on</strong> is derived from a single parent, usuallyan object-logic image like <strong>HOL</strong>. This results in an overall tree structure,which is reflected by the output locati<strong>on</strong> in the file system (usually rooted at~/.isabelle/browser_info).The easiest way to manage <strong>Isabelle</strong> sessi<strong>on</strong>s is via isabelle mkdir (generatesan initial sessi<strong>on</strong> source setup) and isabelle make (run sessi<strong>on</strong>s c<strong>on</strong>trolledby IsaMakefile). For example, a new sessi<strong>on</strong> MySessi<strong>on</strong> derived from<strong>HOL</strong> may be produced as follows:isabelle mkdir <strong>HOL</strong> MySessi<strong>on</strong>isabelle makeThe isabelle make job also informs about the file-system locati<strong>on</strong> ofthe ultimate results. The above dry run should be able to produce somedocument.pdf (with dummy title, empty table of c<strong>on</strong>tents etc.). Any failureat this stage usually indicates technical problems of the L A TEX installati<strong>on</strong>.The detailed arrangement of the sessi<strong>on</strong> sources is as follows.– Directory MySessi<strong>on</strong> holds the required theory files T 1 .thy, . . . , T n .thy.– File MySessi<strong>on</strong>/ROOT.ML holds appropriate ML commands for loading allwanted theories, usually just “use_thy"T i ";” for any T i in leaf positi<strong>on</strong>of the dependency graph.– Directory MySessi<strong>on</strong>/document c<strong>on</strong>tains everything required for the L A TEXstage; <strong>on</strong>ly root.tex needs to be provided initially.The latter file holds appropriate L A TEX code to commence a document(\documentclass etc.), and to include the generated files T i .tex for eachtheory. <strong>Isabelle</strong> will generate a file sessi<strong>on</strong>.tex holding L A TEX commandsto include all generated theory output files in topologically sorted order, so\input{sessi<strong>on</strong>} in the body of root.tex does the job in most situati<strong>on</strong>s.– IsaMakefile holds appropriate dependencies and invocati<strong>on</strong>s of <strong>Isabelle</strong>tools to c<strong>on</strong>trol the batch job. In fact, several sessi<strong>on</strong>s may be managedby the same IsaMakefile. See the <strong>Isabelle</strong> System Manual [40] for furtherdetails, especially <strong>on</strong> isabelle usedir and isabelle make.One may now start to populate the directory MySessi<strong>on</strong>, and the fileMySessi<strong>on</strong>/ROOT.ML accordingly. The file MySessi<strong>on</strong>/document/root.texshould also be adapted at some point; the default versi<strong>on</strong> is mostly selfexplanatory.Note that \isabellestyle enables fine-tuning of the generalappearance of characters and mathematical symbols (see also Sect. 4.2.4).Especially observe the included L A TEX packages isabelle (mandatory),isabellesym (required for mathematical symbols), and the final pdfsetup


4.2 Document Preparati<strong>on</strong> 59(provides sane defaults for hyperref, including URL markup). All three aredistributed with <strong>Isabelle</strong>. Further packages may be required in particularapplicati<strong>on</strong>s, say for unusual mathematical symbols.Any additi<strong>on</strong>al files for the L A TEX stage go into the MySessi<strong>on</strong>/documentdirectory as well. In particular, adding a file named root.bib causes an automaticrun of bibtex to process a bibliographic database; see also isabelledocument [40].Any failure of the document preparati<strong>on</strong> phase in an <strong>Isabelle</strong> batch sessi<strong>on</strong>leaves the generated sources in their target locati<strong>on</strong>, identified by theaccompanying error message. This lets you trace L A TEX problems with thegenerated files at hand.4.2.2 Structure MarkupThe large-scale structure of <strong>Isabelle</strong> documents follows existing L A TEX c<strong>on</strong>venti<strong>on</strong>s,with chapters, secti<strong>on</strong>s, subsubsecti<strong>on</strong>s etc. The Isar language includesseparate markup commands, which do not affect the formal meaning of atheory (or proof), but result in corresp<strong>on</strong>ding L A TEX elements.There are separate markup commands depending <strong>on</strong> the textual c<strong>on</strong>text:in header positi<strong>on</strong> (just before theory), within the theory body, or within aproof. The header needs to be treated specially here, since ordinary theoryand proof commands may <strong>on</strong>ly occur after the initial theory specificati<strong>on</strong>.header theory proof default meaningchapter\chapterheader secti<strong>on</strong> sect \secti<strong>on</strong>subsecti<strong>on</strong> subsect \subsecti<strong>on</strong>subsubsecti<strong>on</strong> subsubsect \subsubsecti<strong>on</strong>From the <strong>Isabelle</strong> perspective, each markup command takes a single textargument (delimited by " . . . " or {* . . . *}). After stripping any surroundingwhite space, the argument is passed to a L A TEX macro \isamarkupXYZ forcommand XYZ. These macros are defined in isabelle.sty according tothe meaning given in the rightmost column above.The following source fragment illustrates structure markup of a theory.Note that L A TEX labels may be included inside of secti<strong>on</strong> headings as well.


60 4. Presenting Theoriesheader {* Some properties of Foo Bar elements *}theory Foo_Barimports Mainbeginsubsecti<strong>on</strong> {* Basic definiti<strong>on</strong>s *}definiti<strong>on</strong> foo :: ...definiti<strong>on</strong> bar :: ...subsecti<strong>on</strong> {* Derived rules *}lemma fooI: ...lemma fooE: ...subsecti<strong>on</strong> {* Main theorem \label{sec:main-theorem} *}theorem main: ...endYou may occasi<strong>on</strong>ally want to change the meaning of markup commands,say via \renewcommand in root.tex. For example, \isamarkupheader is agood candidate for some tuning. We could move it up in the hierarchy tobecome \chapter.\renewcommand{\isamarkupheader}[1]{\chapter{#1}}Now we must change the document class given in root.tex to somethingthat supports chapters. A suitable command is \documentclass{report}.The L A TEX macro \isabellec<strong>on</strong>text is maintained to hold the name ofthe current theory c<strong>on</strong>text. This is particularly useful for document headings:\renewcommand{\isamarkupheader}[1]{\chapter{#1}\markright{THEORY~\isabellec<strong>on</strong>text}}Make sure to include something like \pagestyle{headings} in root.tex;the document should have more than two pages to show the effect.4.2.3 Formal Comments and Antiquotati<strong>on</strong>s<strong>Isabelle</strong> source comments, which are of the form (* . . . *), essentially actlike white space and do not really c<strong>on</strong>tribute to the c<strong>on</strong>tent. They mainlyserve technical purposes to mark certain oddities in the raw input text. Inc<strong>on</strong>trast, formal comments are porti<strong>on</strong>s of text that are associated withformal <strong>Isabelle</strong>/Isar commands (marginal comments), or as standal<strong>on</strong>eparagraphs within a theory or proof c<strong>on</strong>text (text blocks).


4.2 Document Preparati<strong>on</strong> 61Marginal comments are part of each command’s c<strong>on</strong>crete syntax [28]; thecomm<strong>on</strong> form is “-- text” where text is delimited by ". . . " or {* . . . *} asbefore. Multiple marginal comments may be given at the same time. Here isa simple example:lemma "A --> A"— a triviality of propositi<strong>on</strong>al logic— (should not really bother)by (rule impI) — implicit assumpti<strong>on</strong> step involved hereThe above output has been produced as follows:lemma "A --> A"-- "a triviality of propositi<strong>on</strong>al logic"-- "(should not really bother)"by (rule impI) -- "implicit assumpti<strong>on</strong> step involved here"From the L A TEX viewpoint, “--” acts like a markup command, associatedwith the macro \isamarkupcmt (taking a single argument).Text blocks are introduced by the commands text and txt, for theoryand proof c<strong>on</strong>texts, respectively. Each takes again a single text argument,which is interpreted as a free-form paragraph in L A TEX (surroundedby some additi<strong>on</strong>al vertical space). This behavior may be changed by redefiningthe L A TEX envir<strong>on</strong>ments of isamarkuptext or isamarkuptxt, respectively(via \renewenvir<strong>on</strong>ment) The text style of the body is determinedby \isastyletext and \isastyletxt; the default setup uses a smaller f<strong>on</strong>twithin proofs. This may be changed as follows:\renewcommand{\isastyletxt}{\isastyletext}The text part of <strong>Isabelle</strong> markup commands essentially inserts quoted materialinto a formal text, mainly for instructi<strong>on</strong> of the reader. An antiquotati<strong>on</strong>is again a formal object embedded into such an informal porti<strong>on</strong>. Theinterpretati<strong>on</strong> of antiquotati<strong>on</strong>s is limited to some well-formedness checks,with the result being pretty printed to the resulting document. Quoted textblocks together with antiquotati<strong>on</strong>s provide an attractive means of referringto formal entities, with good c<strong>on</strong>fidence in getting the technical details right(especially syntax and types).The general syntax of antiquotati<strong>on</strong>s is as follows: @{name arguments},or @{name [opti<strong>on</strong>s] arguments} for a comma-separated list of opti<strong>on</strong>s c<strong>on</strong>sistingof a name or name=value each. The syntax of arguments depends <strong>on</strong>the kind of antiquotati<strong>on</strong>, it generally follows the same c<strong>on</strong>venti<strong>on</strong>s for types,terms, or theorems as in the formal part of a theory.This sentence dem<strong>on</strong>strates quotati<strong>on</strong>s and antiquotati<strong>on</strong>s: λx y. x is awell-typed term.The output above was produced as follows:


62 4. Presenting Theoriestext {*This sentence dem<strong>on</strong>strates quotati<strong>on</strong>s and antiquotati<strong>on</strong>s:@{term "%x y. x"} is a well-typed term.*}The notati<strong>on</strong>al change from the ASCII character % to the symbol λ revealsthat <strong>Isabelle</strong> printed this term, after parsing and type-checking. Documentpreparati<strong>on</strong> enables symbolic output by default.The next example includes an opti<strong>on</strong> to show the type of all variables.The antiquotati<strong>on</strong> @{term [show_types] "%x y. x"} produces the outputλ(x::’a) y::’b. x. Type inference has figured out the most general typings inthe present theory c<strong>on</strong>text. Terms may acquire different typings due to c<strong>on</strong>straintsimposed by their envir<strong>on</strong>ment; within a proof, for example, variablesare given the same types as they have in the main goal statement.Several further kinds of antiquotati<strong>on</strong>s and opti<strong>on</strong>s are available [38]. Hereare a few comm<strong>on</strong>ly used combinati<strong>on</strong>s:@{typ τ}@{c<strong>on</strong>st c}@{term t}@{prop φ}@{prop [display] φ}@{prop [source] φ}@{thm a}@{thm a [no_vars]}@{thm [source] a}@{text s}print type τcheck existence of c and print itprint term tprint propositi<strong>on</strong> φprint large propositi<strong>on</strong> φ (with linebreaks)check propositi<strong>on</strong> φ, print its inputprint fact aprint fact a, fixing schematic variablescheck availability of fact a, print its nameprint uninterpreted text sNote that no_vars given above is not an antiquotati<strong>on</strong> opti<strong>on</strong>, but anattribute of the theorem argument given here. This might be useful with adiagnostic command like thm, too.The @{text s} antiquotati<strong>on</strong> is particularly interesting. Embedding uninterpretedtext within an informal body might appear useless at first sight.Here the key virtue is that the string s is processed as <strong>Isabelle</strong> output, interpreting<strong>Isabelle</strong> symbols appropriately.For example, @{text "\\"} produces ∀ ∃ , accordingto the standard interpretati<strong>on</strong> of these symbol (cf. Sect. 4.2.4). Thus weachieve c<strong>on</strong>sistent mathematical notati<strong>on</strong> in both the formal and informalparts of the document very easily, independently of the term language of <strong>Isabelle</strong>.Manual L A TEX code would leave more c<strong>on</strong>trol over the typesetting, butis also slightly more tedious.4.2.4 Interpretati<strong>on</strong> of SymbolsAs has been pointed out before (Sect. 4.1.2), <strong>Isabelle</strong> symbols are the smallestsyntactic entities — a straightforward generalizati<strong>on</strong> of ASCII characters.


4.2 Document Preparati<strong>on</strong> 63While <strong>Isabelle</strong> does not impose any interpretati<strong>on</strong> of the infinite collecti<strong>on</strong> ofnamed symbols, L A TEX documents use can<strong>on</strong>ical glyphs for certain standardsymbols [38].The L A TEX code produced from <strong>Isabelle</strong> text follows a simple scheme. Youcan tune the final appearance by redefining certain macros, say in root.texof the document.1. 7-bit ASCII characters: letters A...Z and a...z are output directly, digitsare passed as an argument to the \isadigit macro, other charactersare replaced by specifically named macros of the form \isacharXYZ.2. Named symbols: \ is turned into {\isasymXYZ}; note the additi<strong>on</strong>albraces.3. Named c<strong>on</strong>trol symbols: \ is turned into \isactrlXYZ; subsequentsymbols may act as arguments if the c<strong>on</strong>trol macro is defined accordingly.You may occasi<strong>on</strong>ally wish to give new L A TEX interpretati<strong>on</strong>s of namedsymbols. This merely requires an appropriate definiti<strong>on</strong> of \isasymXYZ,for \ (see isabelle.sty for working examples). C<strong>on</strong>trol symbols areslightly more difficult to get right, though.The \isabellestyle macro provides a high-level interface to tune thegeneral appearance of individual symbols. For example, \isabellestyle{it}uses the italics text style to mimic the general appearance of the L A TEX mathmode; double quotes are not printed at all. The resulting quality of typesettingis quite good, so this should be the default style for work that getsdistributed to a broader audience.4.2.5 Suppressing OutputBy default, <strong>Isabelle</strong>’s document system generates a L A TEX file for each theorythat gets loaded while running the sessi<strong>on</strong>. The generated sessi<strong>on</strong>.tex willinclude all of these in order of appearance, which in turn gets included bythe standard root.tex. Certainly <strong>on</strong>e may change the order or suppressunwanted theories by ignoring sessi<strong>on</strong>.tex and load individual files directlyin root.tex. On the other hand, such an arrangement requires additi<strong>on</strong>almaintenance whenever the collecti<strong>on</strong> of theories changes.Alternatively, <strong>on</strong>e may tune the theory loading process in ROOT.ML itself:traversal of the theory dependency graph may be fine-tuned by addinguse_thy invocati<strong>on</strong>s, although topological sorting still has to be observed.Moreover, the ML operator no_document temporarily disables document generati<strong>on</strong>while executing a theory loader command. Its usage is like this:no_document use_thy "T";Theory output may be suppressed more selectively, either via taggedcommand regi<strong>on</strong>s or ignored material.


64 4. Presenting TheoriesTagged command regi<strong>on</strong>s works by annotating commands with namedtags, which corresp<strong>on</strong>d to certain L A TEX markup that tells how to treat particularparts of a document when doing the actual type-setting. By default,certain <strong>Isabelle</strong>/Isar commands are implicitly marked up using the predefinedtags “theory” (for theory begin and end), “proof ” (for proof commands), and“ML” (for commands involving ML code). Users may add their own tags usingthe %tag notati<strong>on</strong> right after a command name. In the subsequent examplewe hide a particularly irrelevant proof:lemma "x = x"The original source has been “lemma "x = x" by %invisible (simp)”.Tags observe the structure of proofs; adjacent commands with the same tagare joined into a single regi<strong>on</strong>. The <strong>Isabelle</strong> document preparati<strong>on</strong> systemallows the user to specify how to interpret a tagged regi<strong>on</strong>, in order to keep,drop, or fold the corresp<strong>on</strong>ding parts of the document. See the <strong>Isabelle</strong> SystemManual [40] for further details, especially <strong>on</strong> isabelle usedir and isabelledocument.Ignored material is specified by delimiting the original formal source withspecial source comments (**). These parts are stripped beforethe type-setting phase, without affecting the formal checking of the theory, ofcourse. For example, we may hide parts of a proof that seem unfit for generalpublic inspecti<strong>on</strong>. The following “fully automatic” proof is actually a fake:lemma "x ≠ (0::int) =⇒ 0 < x * x"by (auto)The real source of the proof has been as follows:by (auto(**))Suppressing porti<strong>on</strong>s of printed text demands care. You should not misrepresentthe underlying theory development. It is easy to invalidate thevisible text by hiding references to questi<strong>on</strong>able axioms, for example.


Part IILogic and Sets


5. The Rules of the GameThis chapter outlines the c<strong>on</strong>cepts and techniques that underlie reas<strong>on</strong>ingin <strong>Isabelle</strong>. Until now, we have proved everything using <strong>on</strong>ly inducti<strong>on</strong> andsimplificati<strong>on</strong>, but any serious verificati<strong>on</strong> project requires more elaborateforms of inference. The chapter also introduces the fundamentals of predicatelogic. The first examples in this chapter will c<strong>on</strong>sist of detailed, low-level proofsteps. Later, we shall see how to automate such reas<strong>on</strong>ing using the methodsblast, auto and others. Backward or goal-directed proof is our usual style,but the chapter also introduces forward reas<strong>on</strong>ing, where <strong>on</strong>e theorem istransformed to yield another.5.1 Natural Deducti<strong>on</strong>In <strong>Isabelle</strong>, proofs are c<strong>on</strong>structed using inference rules. The most familiarinference rule is probably modus p<strong>on</strong>ens:P → QQPThis rule says that from P → Q and P we may infer Q.Natural deducti<strong>on</strong> is an attempt to formalize logic in a way that mirrorshuman reas<strong>on</strong>ing patterns. For each logical symbol (say, ∧), there are twokinds of rules: introducti<strong>on</strong> and eliminati<strong>on</strong> rules. The introducti<strong>on</strong> rulesallow us to infer this symbol (say, to infer c<strong>on</strong>juncti<strong>on</strong>s). The eliminati<strong>on</strong>rules allow us to deduce c<strong>on</strong>sequences from this symbol. Ideally each ruleshould menti<strong>on</strong> <strong>on</strong>e symbol <strong>on</strong>ly. For predicate logic this can be d<strong>on</strong>e, butwhen users define their own c<strong>on</strong>cepts they typically have to refer to othersymbols as well. It is best not to be dogmatic.Natural deducti<strong>on</strong> generally deserves its name. It is easy to use. Each proofstep c<strong>on</strong>sists of identifying the outermost symbol of a formula and applyingthe corresp<strong>on</strong>ding rule. It creates new subgoals in an obvious way from partsof the chosen formula. Expanding the definiti<strong>on</strong>s of c<strong>on</strong>stants can blow upthe goal enormously. Deriving natural deducti<strong>on</strong> rules for such c<strong>on</strong>stantslets us reas<strong>on</strong> in terms of their key properties, which might otherwise beobscured by the technicalities of its definiti<strong>on</strong>. Natural deducti<strong>on</strong> rules also


68 5. The Rules of the Gamelend themselves to automati<strong>on</strong>. <strong>Isabelle</strong>’s classical reas<strong>on</strong>er accepts anysuitable collecti<strong>on</strong> of natural deducti<strong>on</strong> rules and uses them to search forproofs automatically. <strong>Isabelle</strong> is designed around natural deducti<strong>on</strong> and manyof its tools use the terminology of introducti<strong>on</strong> and eliminati<strong>on</strong> rules.5.2 Introducti<strong>on</strong> RulesAn introducti<strong>on</strong> rule tells us when we can infer a formula c<strong>on</strong>taining a specificlogical symbol. For example, the c<strong>on</strong>juncti<strong>on</strong> introducti<strong>on</strong> rule says that ifwe have P and if we have Q then we have P ∧ Q. In a mathematics text, itis typically shown like this:P QP ∧ QThe rule introduces the c<strong>on</strong>juncti<strong>on</strong> symbol (∧) in its c<strong>on</strong>clusi<strong>on</strong>. In <strong>Isabelle</strong>proofs we mainly reas<strong>on</strong> backwards. When we apply this rule, the subgoalalready has the form of a c<strong>on</strong>juncti<strong>on</strong>; the proof step makes this c<strong>on</strong>juncti<strong>on</strong>symbol disappear.In <strong>Isabelle</strong> notati<strong>on</strong>, the rule looks like this:[[?P; ?Q]] =⇒ ?P ∧ ?Q(c<strong>on</strong>jI)Carefully examine the syntax. The premises appear to the left of the arrowand the c<strong>on</strong>clusi<strong>on</strong> to the right. The premises (if more than <strong>on</strong>e) are groupedusing the fat brackets. The questi<strong>on</strong> marks indicate schematic variables(also called unknowns): they may be replaced by arbitrary formulas. If weuse the rule backwards, <strong>Isabelle</strong> tries to unify the current subgoal with thec<strong>on</strong>clusi<strong>on</strong> of the rule, which has the form ?P ∧ ?Q. (Unificati<strong>on</strong> is discussedbelow, Sect. 5.8.) If successful, it yields new subgoals given by the formulasassigned to ?P and ?Q.The following trivial proof illustrates how rules work. It also introducesa style of indentati<strong>on</strong>. If a command adds a new subgoal, then the nextcommand’s indentati<strong>on</strong> is increased by <strong>on</strong>e space; if it proves a subgoal, thenthe indentati<strong>on</strong> is reduced. This provides the reader with hints about thesubgoal structure.lemma c<strong>on</strong>j_rule: "[[P; Q]] =⇒ P ∧ (Q ∧ P)"apply (rule c<strong>on</strong>jI)apply assumpti<strong>on</strong>apply (rule c<strong>on</strong>jI)apply assumpti<strong>on</strong>apply assumpti<strong>on</strong>At the start, <strong>Isabelle</strong> presents us with the assumpti<strong>on</strong>s (P and Q) and withthe goal to be proved, P ∧ (Q ∧ P). We are working backwards, so when weapply c<strong>on</strong>juncti<strong>on</strong> introducti<strong>on</strong>, the rule removes the outermost occurrenceof the ∧ symbol. To apply a rule to a subgoal, we apply the proof methodrule — here with c<strong>on</strong>jI, the c<strong>on</strong>juncti<strong>on</strong> introducti<strong>on</strong> rule.


70 5. The Rules of the GameThe assumpti<strong>on</strong>s [P] and [Q] are bracketed to emphasize that they are localto their subproofs. In <strong>Isabelle</strong> notati<strong>on</strong>, the already-familiar =⇒ syntax servesthe same purpose:[[?P ∨ ?Q; ?P =⇒ ?R; ?Q =⇒ ?R]] =⇒ ?R(disjE)When we use this sort of eliminati<strong>on</strong> rule backwards, it produces a casesplit. (We have seen this before, in proofs by inducti<strong>on</strong>.) The following proofillustrates the use of disjuncti<strong>on</strong> eliminati<strong>on</strong>.lemma disj_swap: "P ∨ Q =⇒ Q ∨ P"apply (erule disjE)apply (rule disjI2)apply assumpti<strong>on</strong>apply (rule disjI1)apply assumpti<strong>on</strong>We assume P ∨ Q and must prove Q ∨ P. Our first step uses the disjuncti<strong>on</strong>eliminati<strong>on</strong> rule, disjE. We invoke it using erule, a method designed to workwith eliminati<strong>on</strong> rules. It looks for an assumpti<strong>on</strong> that matches the rule’sfirst premise. It deletes the matching assumpti<strong>on</strong>, regards the first premise asproved and returns subgoals corresp<strong>on</strong>ding to the remaining premises. Whenwe apply erule to disjE, <strong>on</strong>ly two subgoals result. This is better than applyingit using rule to get three subgoals, then proving the first by assumpti<strong>on</strong>:the other subgoals would have the redundant assumpti<strong>on</strong> P ∨ Q. Most ofthe time, erule is the best way to use eliminati<strong>on</strong> rules, since it replacesan assumpti<strong>on</strong> by its subformulas; <strong>on</strong>ly rarely does the original assumpti<strong>on</strong>remain useful.1. P =⇒ Q ∨ P2. Q =⇒ Q ∨ PThese are the two subgoals returned by erule. The first assumes P and thesec<strong>on</strong>d assumes Q. Tackling the first subgoal, we need to show Q ∨ P. Thesec<strong>on</strong>d introducti<strong>on</strong> rule (disjI2) can reduce this to P, which matches theassumpti<strong>on</strong>. So, we apply the rule method with disjI2 . . .1. P =⇒ P2. Q =⇒ Q ∨ P. . . and finish off with the assumpti<strong>on</strong> method. We are left with the othersubgoal, which assumes Q.1. Q =⇒ Q ∨ PIts proof is similar, using the introducti<strong>on</strong> rule disjI1.The result of this proof is a new inference rule disj_swap, which is neitheran introducti<strong>on</strong> nor an eliminati<strong>on</strong> rule, but which might be useful. We canuse it to replace any goal of the form Q ∨ P by <strong>on</strong>e of the form P ∨ Q.


5.6 Negati<strong>on</strong> 73reas<strong>on</strong> about the other c<strong>on</strong>nectives. You will have to use −→ in any c<strong>on</strong>textthat requires a formula of higher-order logic. Use =⇒ to separate a theorem’sprec<strong>on</strong>diti<strong>on</strong>s from its c<strong>on</strong>clusi<strong>on</strong>.The by command is useful for proofs like these that use assumpti<strong>on</strong> heavily.It executes an apply command, then tries to prove all remaining subgoalsusing assumpti<strong>on</strong>. Since (if successful) it ends the proof, it also replaces thed<strong>on</strong>e symbol. For example, the proof above can be shortened:lemma imp_uncurry: "P −→ (Q −→ R) =⇒ P ∧ Q −→ R"apply (rule impI)apply (erule c<strong>on</strong>jE)apply (drule mp)apply assumpti<strong>on</strong>by (drule mp)We could use by to replace the final apply and d<strong>on</strong>e in any proof, buttypically we use it to eliminate calls to assumpti<strong>on</strong>. It is also a nice way ofexpressing a <strong>on</strong>e-line proof.5.6 Negati<strong>on</strong>Negati<strong>on</strong> causes surprising complexity in proofs. Its natural deducti<strong>on</strong> rulesare straightforward, but additi<strong>on</strong>al rules seem necessary in order to handlenegated assumpti<strong>on</strong>s gracefully. This secti<strong>on</strong> also illustrates the intromethod: a c<strong>on</strong>venient way of applying introducti<strong>on</strong> rules.Negati<strong>on</strong> introducti<strong>on</strong> deduces ¬P if assuming P leads to a c<strong>on</strong>tradicti<strong>on</strong>.Negati<strong>on</strong> eliminati<strong>on</strong> deduces any formula in the presence of ¬P togetherwith P:(?P =⇒ False) =⇒ ¬ ?P(notI)[[¬ ?P; ?P]] =⇒ ?R (notE)Classical logic allows us to assume ¬P when attempting to prove P:(¬ ?P =⇒ ?P) =⇒ ?P (classical)The implicati<strong>on</strong>s P → Q and ¬Q → ¬P are logically equivalent, andeach is called the c<strong>on</strong>trapositive of the other. Four further rules supportreas<strong>on</strong>ing about c<strong>on</strong>trapositives. They differ in the placement of the negati<strong>on</strong>symbols:[[?Q; ¬ ?P =⇒ ¬ ?Q]] =⇒ ?P(c<strong>on</strong>trapos_pp)[[?Q; ?P =⇒ ¬ ?Q]] =⇒ ¬ ?P(c<strong>on</strong>trapos_pn)[[¬ ?Q; ¬ ?P =⇒ ?Q]] =⇒ ?P (c<strong>on</strong>trapos_np)[[¬ ?Q; ?P =⇒ ?Q]] =⇒ ¬ ?P (c<strong>on</strong>trapos_nn)These rules are typically applied using the erule method, where their effectis to form a c<strong>on</strong>trapositive from an assumpti<strong>on</strong> and the goal’s c<strong>on</strong>clusi<strong>on</strong>.The most important of these is c<strong>on</strong>trapos_np. It is useful for applyingintroducti<strong>on</strong> rules to negated assumpti<strong>on</strong>s. For instance, the assumpti<strong>on</strong>


74 5. The Rules of the Game¬(P → Q) is equivalent to the c<strong>on</strong>clusi<strong>on</strong> P → Q and we might want touse c<strong>on</strong>juncti<strong>on</strong> introducti<strong>on</strong> <strong>on</strong> it. Before we can do so, we must move thatassumpti<strong>on</strong> so that it becomes the c<strong>on</strong>clusi<strong>on</strong>. The following proof dem<strong>on</strong>stratesthis technique:lemma "[[¬(P−→Q); ¬(R−→Q)]] =⇒ R"apply (erule_tac Q = "R−→Q" in c<strong>on</strong>trapos_np)apply (intro impI)by (erule notE)There are two negated assumpti<strong>on</strong>s and we need to exchange the c<strong>on</strong>clusi<strong>on</strong>with the sec<strong>on</strong>d <strong>on</strong>e. The method erule c<strong>on</strong>trapos_np would select the firstassumpti<strong>on</strong>, which we do not want. So we specify the desired assumpti<strong>on</strong>explicitly using a new method, erule_tac. This is the resulting subgoal:1. [[¬ (P −→ Q); ¬ R]] =⇒ R −→ QThe former c<strong>on</strong>clusi<strong>on</strong>, namely R, now appears negated am<strong>on</strong>g the assumpti<strong>on</strong>s,while the negated formula R −→ Q becomes the new c<strong>on</strong>clusi<strong>on</strong>.We can now apply introducti<strong>on</strong> rules. We use the intro method, whichrepeatedly applies the given introducti<strong>on</strong> rules. Here its effect is equivalentto rule impI.1. [[¬ (P −→ Q); ¬ R; R]] =⇒ QWe can see a c<strong>on</strong>tradicti<strong>on</strong> in the form of assumpti<strong>on</strong>s ¬ R and R, whichsuggests using negati<strong>on</strong> eliminati<strong>on</strong>. If applied <strong>on</strong> its own, notE will selectthe first negated assumpti<strong>on</strong>, which is useless. Instead, we invoke the ruleusing the by command. Now when <strong>Isabelle</strong> selects the first assumpti<strong>on</strong>, ittries to prove P −→ Q and fails; it then backtracks, finds the assumpti<strong>on</strong> ¬ Rand finally proves R by assumpti<strong>on</strong>. That c<strong>on</strong>cludes the proof.The following example may be skipped <strong>on</strong> a first reading. It involves apeculiar but important rule, a form of disjuncti<strong>on</strong> introducti<strong>on</strong>:(¬ ?Q =⇒ ?P) =⇒ ?P ∨ ?Q (disjCI)This rule combines the effects of disjI1 and disjI2. Its great advantageis that we can remove the disjuncti<strong>on</strong> symbol without deciding which disjuncti<strong>on</strong>to prove. This treatment of disjuncti<strong>on</strong> is standard in sequent andtableau calculi.lemma "(P ∨ Q) ∧ R =⇒ P ∨ (Q ∧ R)"apply (rule disjCI)apply (elim c<strong>on</strong>jE disjE)apply assumpti<strong>on</strong>by (erule c<strong>on</strong>trapos_np, rule c<strong>on</strong>jI)The first proof step to applies the introducti<strong>on</strong> rules disjCI. The resultingsubgoal has the negative assumpti<strong>on</strong> ¬(Q ∧ R).1. [[(P ∨ Q) ∧ R; ¬ (Q ∧ R)]] =⇒ P


5.7 Interlude: the Basic Methods for Rules 75Next we apply the elim method, which repeatedly applies eliminati<strong>on</strong> rules;here, the eliminati<strong>on</strong> rules given in the command. One of the subgoals istrivial (apply assumpti<strong>on</strong>), leaving us with <strong>on</strong>e other:1. [[¬ (Q ∧ R); R; Q]] =⇒ PNow we must move the formula Q ∧ R to be the c<strong>on</strong>clusi<strong>on</strong>. The combinati<strong>on</strong>(erule c<strong>on</strong>trapos_np, rule c<strong>on</strong>jI)is robust: the c<strong>on</strong>jI forces the erule to select a c<strong>on</strong>juncti<strong>on</strong>. The two subgoalsare the <strong>on</strong>es we would expect from applying c<strong>on</strong>juncti<strong>on</strong> introducti<strong>on</strong> toQ ∧ R:1. [[R; Q; ¬ P]] =⇒ Q2. [[R; Q; ¬ P]] =⇒ RThey are proved by assumpti<strong>on</strong>, which is implicit in the by command.5.7 Interlude: the Basic Methods for RulesWe have seen examples of many tactics that operate <strong>on</strong> individual rules. Itmay be helpful to review how they work given an arbitrary rule such as this:P 1 . . . P nQBelow, we refer to P 1 as the major premise. This c<strong>on</strong>cept applies <strong>on</strong>ly toeliminati<strong>on</strong> and destructi<strong>on</strong> rules. These rules act up<strong>on</strong> an instance of theirmajor premise, typically to replace it by subformulas of itself.Suppose that the rule above is called R. Here are the basic rule methods,most of which we have already seen:– Method rule R unifies Q with the current subgoal, replacing it by n newsubgoals: instances of P 1 , . . . , P n . This is backward reas<strong>on</strong>ing and is appropriatefor introducti<strong>on</strong> rules.– Method erule R unifies Q with the current subgoal and simultaneouslyunifies P 1 with some assumpti<strong>on</strong>. The subgoal is replaced by the n −1 newsubgoals of proving instances of P 2 , . . . , P n , with the matching assumpti<strong>on</strong>deleted. It is appropriate for eliminati<strong>on</strong> rules. The method (rule R,assumpti<strong>on</strong>) is similar, but it does not delete an assumpti<strong>on</strong>.– Method drule R unifies P 1 with some assumpti<strong>on</strong>, which it then deletes.The subgoal is replaced by the n − 1 new subgoals of proving P 2 , . . . , P n ;an nth subgoal is like the original <strong>on</strong>e but has an additi<strong>on</strong>al assumpti<strong>on</strong>:an instance of Q. It is appropriate for destructi<strong>on</strong> rules.– Method frule R is like drule R except that the matching assumpti<strong>on</strong> isnot deleted. (See Sect. 5.9.5 below.)


76 5. The Rules of the GameOther methods apply a rule while c<strong>on</strong>straining some of its variables. Thetypical form isrule_tac v 1 = t 1 and ...and v k = t k in RThis method behaves like rule R, while instantiating the variables v 1 , . . . , v kas specified. We similarly have erule_tac, drule_tac and frule_tac. Thesemethods also let us specify which subgoal to operate <strong>on</strong>. By default it isthe first subgoal, as with nearly all methods, but we can specify that rule Rshould be applied to subgoal number i:rule_tac [i] R5.8 Unificati<strong>on</strong> and Substituti<strong>on</strong>As we have seen, <strong>Isabelle</strong> rules involve schematic variables, which begin with aquesti<strong>on</strong> mark and act as placeholders for terms. Unificati<strong>on</strong> — well knownto Prolog programmers — is the act of making two terms identical, possiblyreplacing their schematic variables by terms. The simplest case is whenthe two terms are already the same. Next simplest is pattern-matching,which replaces variables in <strong>on</strong>ly <strong>on</strong>e of the terms. The rule method typicallymatches the rule’s c<strong>on</strong>clusi<strong>on</strong> against the current subgoal. The assumpti<strong>on</strong>method matches the current subgoal’s c<strong>on</strong>clusi<strong>on</strong> against each of its assumpti<strong>on</strong>s.Unificati<strong>on</strong> can instantiate variables in both terms; the rule methodcan do this if the goal itself c<strong>on</strong>tains schematic variables. Other occurrencesof the variables in the rule or proof state are updated at the same time.Schematic variables in goals represent unknown terms. Given a goal suchas ∃x. P, they let us proceed with a proof. They can be filled in later, sometimesin stages and often automatically.If unificati<strong>on</strong> fails when you think it should succeed, try setting the Proof Generalflag <strong>Isabelle</strong> > Settings > Trace Unificati<strong>on</strong>, which makes <strong>Isabelle</strong> show thecause of unificati<strong>on</strong> failures (in Proof General’s Trace buffer).For example, suppose we are trying to prove this subgoal by assumpti<strong>on</strong>:1. P (a, f (b, g (e, a), b), a) =⇒ P (a, f (b, g (c, a), b), a)The assumpti<strong>on</strong> method having failed, we try again with the flag set:apply assumpti<strong>on</strong>In this trivial case, the output clearly shows that e clashes with c:Clash: e =/= c<strong>Isabelle</strong> uses higher-order unificati<strong>on</strong>, which works in the typed λ-calculus. The procedure requires search and is potentially undecidable. Forour purposes, however, the differences from ordinary unificati<strong>on</strong> are straightforward.It handles bound variables correctly, avoiding capture. The two


5.8 Unificati<strong>on</strong> and Substituti<strong>on</strong> 77terms λx. f(x,z) and λy. f(y,z) are trivially unifiable because they differ<strong>on</strong>ly by a bound variable renaming. The two terms λx. ?P and λx. t xare not unifiable; replacing ?P by t x is forbidden because the free occurrenceof x would become bound. Unfortunately, even if trace_unify_fail isset, <strong>Isabelle</strong> displays no informati<strong>on</strong> about this type of failure.!!Higher-order unificati<strong>on</strong> sometimes must invent λ-terms to replace functi<strong>on</strong>variables, which can lead to a combinatorial explosi<strong>on</strong>. However, <strong>Isabelle</strong> proofstend to involve easy cases where there are few possibilities for the λ-term beingc<strong>on</strong>structed. In the easiest case, the functi<strong>on</strong> variable is applied <strong>on</strong>ly to boundvariables, as when we try to unify λx y. f(?h x y) and λx y. f(x+y+a). The<strong>on</strong>ly soluti<strong>on</strong> is to replace ?h by λx y. x+y+a. Such cases admit at most <strong>on</strong>e unifier,like ordinary unificati<strong>on</strong>. A harder case is unifying ?h a with a+b; it admits twosoluti<strong>on</strong>s for ?h, namely λx. a+b and λx. x+b. Unifying ?h a with a+a+b admitsfour soluti<strong>on</strong>s; their number is exp<strong>on</strong>ential in the number of occurrences of a in thesec<strong>on</strong>d term.5.8.1 Substituti<strong>on</strong> and the subst Method<strong>Isabelle</strong> also uses functi<strong>on</strong> variables to express substituti<strong>on</strong>. A typical substituti<strong>on</strong>rule allows us to replace <strong>on</strong>e term by another if we know that twoterms are equal.s = t P[s/x]P[t/x]The rule uses a notati<strong>on</strong> for substituti<strong>on</strong>: P[t/x] is the result of replacing xby t in P. The rule <strong>on</strong>ly substitutes in the positi<strong>on</strong>s designated by x. Forexample, it can derive symmetry of equality from reflexivity. Using x = sfor P replaces just the first s in s = s by t:s = t s = st = sThe <strong>Isabelle</strong> versi<strong>on</strong> of the substituti<strong>on</strong> rule looks like this:[[?t = ?s; ?P ?s]] =⇒ ?P ?t(ssubst)Crucially, ?P is a functi<strong>on</strong> variable. It can be replaced by a λ-term with<strong>on</strong>e bound variable, whose occurrences identify the places in which s will bereplaced by t. The proof above requires ?P to be replaced by λx. x=s; thesec<strong>on</strong>d premise will then be s=s and the c<strong>on</strong>clusi<strong>on</strong> will be t=s.The simp method also replaces equals by equals, but the substituti<strong>on</strong> rulegives us more c<strong>on</strong>trol. C<strong>on</strong>sider this proof:lemma "[[x = f x; odd(f x)]] =⇒ odd x"by (erule ssubst)The assumpti<strong>on</strong> x = f x, if used for rewriting, would loop, replacing x by f xand then by f(f x) and so forth. (Here simp would see the danger and would


78 5. The Rules of the Gamere-orient the equality, but in more complicated cases it can be fooled.) Whenwe apply the substituti<strong>on</strong> rule, <strong>Isabelle</strong> replaces every x in the subgoal by fx just <strong>on</strong>ce. It cannot loop. The resulting subgoal is trivial by assumpti<strong>on</strong>,so the by command proves it implicitly.We are using the erule method in a novel way. Hitherto, the c<strong>on</strong>clusi<strong>on</strong> ofthe rule was just a variable such as ?R, but it may be any term. The c<strong>on</strong>clusi<strong>on</strong>is unified with the subgoal just as it would be with the rule method. Atthe same time erule looks for an assumpti<strong>on</strong> that matches the rule’s firstpremise, as usual. With ssubst the effect is to find, use and delete an equalityassumpti<strong>on</strong>.The subst method performs individual substituti<strong>on</strong>s. In simple cases, itclosely resembles a use of the substituti<strong>on</strong> rule. Suppose a proof has reachedthis point:1. [[P x y z; Suc x < y]] =⇒ f z = x * yNow we wish to apply a commutative law:?m * ?n = ?n * ?m (mult_commute)<strong>Isabelle</strong> rejects our first attempt:apply (simp add: mult_commute)The simplifier notices the danger of looping and refuses to apply the rule. 2The subst method applies mult_commute exactly <strong>on</strong>ce.apply (subst mult_commute)1. [[P x y z; Suc x < y]] =⇒ f z = y * xAs we wanted, x * y has become y * x.This use of the subst method has the same effect as the commandapply (rule mult_commute [THEN ssubst])The attribute THEN, which combines two rules, is described in Sect. 5.15.1 below.The subst method is more powerful than applying the substituti<strong>on</strong> rule.It can perform substituti<strong>on</strong>s in a subgoal’s assumpti<strong>on</strong>s. Moreover, if the subgoalc<strong>on</strong>tains more than <strong>on</strong>e occurrence of the left-hand side of the equality,the subst method lets us specify which occurrence should be replaced.5.8.2 Unificati<strong>on</strong> and Its PitfallsHigher-order unificati<strong>on</strong> can be tricky. Here is an example, which you maywant to skip <strong>on</strong> your first reading:2 More precisely, it <strong>on</strong>ly applies such a rule if the new term is smaller under aspecified ordering; here, x * y is already smaller than y * x.


5.8 Unificati<strong>on</strong> and Substituti<strong>on</strong> 79lemma "[[x = f x; triple (f x) (f x) x]] =⇒ triple x x x"apply (erule ssubst)backbackbackbackapply assumpti<strong>on</strong>d<strong>on</strong>eBy default, <strong>Isabelle</strong> tries to substitute for all the occurrences. Applying erulessubst yields this subgoal:1. triple (f x) (f x) x =⇒ triple (f x) (f x) (f x)The substituti<strong>on</strong> should have been d<strong>on</strong>e in the first two occurrences of x<strong>on</strong>ly. <strong>Isabelle</strong> has g<strong>on</strong>e too far. The back command allows us to reject thispossibility and demand a new <strong>on</strong>e:1. triple (f x) (f x) x =⇒ triple x (f x) (f x)Now <strong>Isabelle</strong> has left the first occurrence of x al<strong>on</strong>e. That is promising butit is not the desired combinati<strong>on</strong>. So we use back again:1. triple (f x) (f x) x =⇒ triple (f x) x (f x)This also is wr<strong>on</strong>g, so we use back again:1. triple (f x) (f x) x =⇒ triple x x (f x)And this <strong>on</strong>e is wr<strong>on</strong>g too. Looking carefully at the series of alternatives, wesee a binary countdown with reversed bits: 111, 011, 101, 001. Invoke backagain:1. triple (f x) (f x) x =⇒ triple (f x) (f x) xAt last, we have the right combinati<strong>on</strong>! This goal follows by assumpti<strong>on</strong>.This example shows that unificati<strong>on</strong> can do strange things with functi<strong>on</strong>variables. We were forced to select the right unifier using the back command.That is all right during explorati<strong>on</strong>, but back should never appear in the finalversi<strong>on</strong> of a proof. You can eliminate the need for back by giving <strong>Isabelle</strong>less freedom when you apply a rule.One way to c<strong>on</strong>strain the inference is by joining two methods in a applycommand. <strong>Isabelle</strong> applies the first method and then the sec<strong>on</strong>d. If the sec<strong>on</strong>dmethod fails then <strong>Isabelle</strong> automatically backtracks. This process c<strong>on</strong>tinuesuntil the first method produces an output that the sec<strong>on</strong>d method can use.We get a <strong>on</strong>e-line proof of our example:lemma "[[x = f x; triple (f x) (f x) x]] =⇒ triple x x x"apply (erule ssubst, assumpti<strong>on</strong>)d<strong>on</strong>eThe by command works too, since it backtracks when proving subgoals byassumpti<strong>on</strong>:


80 5. The Rules of the Gamelemma "[[x = f x; triple (f x) (f x) x]] =⇒ triple x x x"by (erule ssubst)The most general way to c<strong>on</strong>strain unificati<strong>on</strong> is by instantiating variablesin the rule. The method rule_tac is similar to rule, but it makes some ofthe rule’s variables denote specified terms. Also available are drule_tac anderule_tac. Here we need erule_tac since above we used erule.lemma "[[x = f x; triple (f x) (f x) x]] =⇒ triple x x x"by (erule_tac P = "λu. triple u u x" in ssubst)To specify a desired substituti<strong>on</strong> requires instantiating the variable ?P witha λ-expressi<strong>on</strong>. The bound variable occurrences in λu. P u u x indicate thatthe first two arguments have to be substituted, leaving the third unchanged.With this instantiati<strong>on</strong>, backtracking is neither necessary nor possible.An alternative to rule_tac is to use rule with a theorem modified usingof, described in Sect. 5.15 below. But rule_tac, unlike of, can expressinstantiati<strong>on</strong>s that refer to ∧ -bound variables in the current subgoal.5.9 QuantifiersQuantifiers require formalizing syntactic substituti<strong>on</strong> and the noti<strong>on</strong> of arbitraryvalue. C<strong>on</strong>sider the universal quantifier. In a logic book, its introducti<strong>on</strong>rule looks like this:P∀x. PTypically, a proviso written in English says that x must not occur in the assumpti<strong>on</strong>s.This proviso guarantees that x can be regarded as arbitrary, sinceit has not been assumed to satisfy any special c<strong>on</strong>diti<strong>on</strong>s. <strong>Isabelle</strong>’s underlyingformalism, called the meta-logic, eliminates the need for English. Itprovides its own universal quantifier ( ∧ ) to express the noti<strong>on</strong> of an arbitraryvalue. We have already seen another operator of the meta-logic, namely =⇒,which expresses inference rules and the treatment of assumpti<strong>on</strong>s. The <strong>on</strong>lyother operator in the meta-logic is ≡, which can be used to define c<strong>on</strong>stants.5.9.1 The Universal Introducti<strong>on</strong> RuleReturning to the universal quantifier, we find that having a similar quantifieras part of the meta-logic makes the introducti<strong>on</strong> rule trivial to express:( V x. ?P x) =⇒ ∀ x. ?P x (allI)The following trivial proof dem<strong>on</strong>strates how the universal introducti<strong>on</strong>rule works.lemma "∀ x. P x −→ P x"apply (rule allI)by (rule impI)


5.9 Quantifiers 81The first step invokes the rule by applying the method rule allI.1. V x. P x −→ P xNote that the resulting proof state has a bound variable, namely x. The rulehas replaced the universal quantifier of higher-order logic by <strong>Isabelle</strong>’s metalevelquantifier. Our goal is to prove P x −→ P x for arbitrary x; it is animplicati<strong>on</strong>, so we apply the corresp<strong>on</strong>ding introducti<strong>on</strong> rule (impI).1. V x. P x =⇒ P xThis last subgoal is implicitly proved by assumpti<strong>on</strong>.5.9.2 The Universal Eliminati<strong>on</strong> RuleNow c<strong>on</strong>sider universal eliminati<strong>on</strong>. In a logic text, the rule looks like this:∀x. PP[t/x]The c<strong>on</strong>clusi<strong>on</strong> is P with t substituted for the variable x. <strong>Isabelle</strong> expressessubstituti<strong>on</strong> using a functi<strong>on</strong> variable:∀ x. ?P x =⇒ ?P ?x(spec)This destructi<strong>on</strong> rule takes a universally quantified formula and removes thequantifier, replacing the bound variable x by the schematic variable ?x. Recallthat a schematic variable starts with a questi<strong>on</strong> mark and acts as aplaceholder: it can be replaced by any term.The universal eliminati<strong>on</strong> rule is also available in the standard eliminati<strong>on</strong>format. Like c<strong>on</strong>jE, it never appears in logic books:[[∀ x. ?P x; ?P ?x =⇒ ?R]] =⇒ ?R(allE)The methods drule spec and erule allE do precisely the same inference.To see how ∀-eliminati<strong>on</strong> works, let us derive a rule about reducing thescope of a universal quantifier. In mathematical notati<strong>on</strong> we write∀x. P → QP → ∀x. Qwith the proviso “x not free in P.” <strong>Isabelle</strong>’s treatment of substituti<strong>on</strong> makesthe proviso unnecessary. The c<strong>on</strong>clusi<strong>on</strong> is expressed as P −→ (∀ x. Q x).No substituti<strong>on</strong> for the variable P can introduce a dependence up<strong>on</strong> x: thatwould be a bound variable capture. Let us walk through the proof.lemma "(∀ x. P −→ Q x) =⇒ P −→ (∀ x. Q x)"First we apply implies introducti<strong>on</strong> (impI), which moves the P from the c<strong>on</strong>clusi<strong>on</strong>to the assumpti<strong>on</strong>s. Then we apply universal introducti<strong>on</strong> (allI).apply (rule impI, rule allI)1. V x. [[∀ x. P −→ Q x; P]] =⇒ Q x


82 5. The Rules of the GameAs before, it replaces the <strong>HOL</strong> quantifier by a meta-level quantifier, producinga subgoal that binds the variable x. The leading bound variables (here x)and the assumpti<strong>on</strong>s (here ∀ x. P −→ Q x and P) form the c<strong>on</strong>text for thec<strong>on</strong>clusi<strong>on</strong>, here Q x. Subgoals inherit the c<strong>on</strong>text, although assumpti<strong>on</strong>s canbe added or deleted (as we saw earlier), while rules such as allI add boundvariables.Now, to reas<strong>on</strong> from the universally quantified assumpti<strong>on</strong>, we apply theeliminati<strong>on</strong> rule using the drule method. This rule is called spec because itspecializes a universal formula to a particular term.apply (drule spec)1. V x. [[P; P −→ Q (?x2 x)]] =⇒ Q xObserve how the c<strong>on</strong>text has changed. The quantified formula is g<strong>on</strong>e, replacedby a new assumpti<strong>on</strong> derived from its body. We have removed thequantifier and replaced the bound variable by the curious term ?x2 x. Thisterm is a placeholder: it may become any term that can be built from x.(Formally, ?x2 is an unknown of functi<strong>on</strong> type, applied to the argument x.)This new assumpti<strong>on</strong> is an implicati<strong>on</strong>, so we can use modus p<strong>on</strong>ens <strong>on</strong> it,which c<strong>on</strong>cludes the proof.by (drule mp)Let us take a closer look at this last step. Modus p<strong>on</strong>ens yields two subgoals:<strong>on</strong>e where we prove the antecedent (in this case P) and <strong>on</strong>e where we mayassume the c<strong>on</strong>sequent. Both of these subgoals are proved by the assumpti<strong>on</strong>method, which is implicit in the by command. Replacing the by commandby apply (drule mp, assumpti<strong>on</strong>) would have left <strong>on</strong>e last subgoal:1. V x. [[P; Q (?x2 x)]] =⇒ Q xThe c<strong>on</strong>sequent is Q applied to that placeholder. It may be replaced by anyterm built from x, and here it should simply be x. The assumpti<strong>on</strong> need notbe identical to the c<strong>on</strong>clusi<strong>on</strong>, provided the two formulas are unifiable.5.9.3 The Existential QuantifierThe c<strong>on</strong>cepts just presented also apply to the existential quantifier, whoseintroducti<strong>on</strong> rule looks like this in <strong>Isabelle</strong>:?P ?x =⇒ ∃ x. ?P x (exI)If we can exhibit some x such that P(x) is true, then ∃x.P(x) is also true.It is a dual of the universal eliminati<strong>on</strong> rule, and logic texts present it usingthe same notati<strong>on</strong> for substituti<strong>on</strong>.The existential eliminati<strong>on</strong> rule looks like this in a logic text:∃x. PQ[P].Q


It looks like this in <strong>Isabelle</strong>:[[∃ x. ?P x; V x. ?P x =⇒ ?Q]] =⇒ ?Q5.9 Quantifiers 83(exE)Given an existentially quantified theorem and some formula Q to prove, itcreates a new assumpti<strong>on</strong> by removing the quantifier. As with the universalintroducti<strong>on</strong> rule, the textbook versi<strong>on</strong> imposes a proviso <strong>on</strong> the quantifiedvariable, which <strong>Isabelle</strong> expresses using its meta-logic. It is enough to have auniversal quantifier in the meta-logic; we do not need an existential quantifierto be built in as well.Exercise 5.9.1 Prove the lemma∃x. P ∧ Q(x) =⇒ P ∧ (∃x. Q(x)).Hint: the proof is similar to the <strong>on</strong>e just above for the universal quantifier.5.9.4 Renaming an Assumpti<strong>on</strong>: rename_tacWhen you apply a rule such as allI, the quantified variable becomes a newbound variable of the new subgoal. <strong>Isabelle</strong> tries to avoid changing its name,but sometimes it has to choose a new name in order to avoid a clash. Theresult may not be ideal:lemma "x < y =⇒ ∀ x y. P x (f y)"apply (intro allI)1. V xa ya. x < y =⇒ P xa (f ya)The names x and y were already in use, so the new bound variables are calledxa and ya. You can rename them by invoking rename_tac:apply (rename_tac v w)1. V v w. x < y =⇒ P v (f w)Recall that rule_tac instantiates a theorem with specified terms. These termsmay involve the goal’s bound variables, but beware of referring to variableslike xa. A future change to your theories could change the set of names producedat top level, so that xa changes to xb or reverts to x. It is safer torename automatically-generated variables before menti<strong>on</strong>ing them.If the subgoal has more bound variables than there are names given torename_tac, the rightmost <strong>on</strong>es are renamed.5.9.5 Reusing an Assumpti<strong>on</strong>: fruleNote that drule spec removes the universal quantifier and — as usual witheliminati<strong>on</strong> rules — discards the original formula. Sometimes, a universalformula has to be kept so that it can be used again. Then we use a newmethod: frule. It acts like drule but copies rather than replaces the selectedassumpti<strong>on</strong>. The f is for forward.In this example, going from P a to P(h(h a)) requires two uses of thequantified assumpti<strong>on</strong>, <strong>on</strong>e for each h in h(h a).


84 5. The Rules of the Gamelemma "[[∀ x. P x −→ P (h x);Examine the subgoal left by frule:P a]] =⇒ P(h (h a))"apply (frule spec)1. [[∀ x. P x −→ P (h x); P a; P ?x −→ P (h ?x)]] =⇒ P (h (h a))It is what drule would have left except that the quantified assumpti<strong>on</strong> is stillpresent. Next we apply mp to the implicati<strong>on</strong> and the assumpti<strong>on</strong> P a:apply (drule mp, assumpti<strong>on</strong>)1. [[∀ x. P x −→ P (h x); P a; P (h a)]] =⇒ P (h (h a))We have created the assumpti<strong>on</strong> P(h a), which is progress. To c<strong>on</strong>tinue theproof, we apply spec again. We shall not need it again, so we can use drule.apply (drule spec)1. [[P a; P (h a); P ?x2 −→ P (h ?x2)]] =⇒ P (h (h a))The new assumpti<strong>on</strong> bridges the gap between P(h a) and P(h(h a)).by (drule mp)A final remark. Replacing this by command withapply (drule mp, assumpti<strong>on</strong>)would not work: it would add a sec<strong>on</strong>d copy of P(h a) instead of the desiredassumpti<strong>on</strong>, P(h(h a)). The by command forces <strong>Isabelle</strong> to backtrack until itfinds the correct <strong>on</strong>e. Alternatively, we could have used the apply commandand bundled the drule mp with two calls of assumpti<strong>on</strong>. Or, of course, wecould have given the entire proof to auto.5.9.6 Instantiating a Quantifier ExplicitlyWe can prove a theorem of the form ∃x. P x by exhibiting a suitable term tsuch that P t is true. Dually, we can use an assumpti<strong>on</strong> of the form ∀x. P x togenerate a new assumpti<strong>on</strong> P t for a suitable term t. In many cases, <strong>Isabelle</strong>makes the correct choice automatically, c<strong>on</strong>structing the term by unificati<strong>on</strong>.In other cases, the required term is not obvious and we must specify it ourselves.Suitable methods are rule_tac, drule_tac and erule_tac.We have seen (just above, Sect. 5.9.5) a proof of this lemma:lemma "[[∀ x. P x −→ P (h x); P a]] =⇒ P(h (h a))"We had reached this subgoal:1. [[∀ x. P x −→ P (h x); P a; P (h a)]] =⇒ P (h (h a))The proof requires instantiating the quantified assumpti<strong>on</strong> with the term h a.apply (drule_tac x = "h a" in spec)1. [[P a; P (h a); P (h a) −→ P (h (h a))]] =⇒ P (h (h a))


We have forced the desired instantiati<strong>on</strong>.5.10 Descripti<strong>on</strong> Operators 85Existential formulas can be instantiated too. The next example uses thedivides relati<strong>on</strong> of number theory:?m dvd ?n ≡ ∃ k. ?n = ?m * k (dvd_def)Let us prove that multiplicati<strong>on</strong> of natural numbers is m<strong>on</strong>ot<strong>on</strong>e withrespect to the divides relati<strong>on</strong>:lemma mult_dvd_m<strong>on</strong>o: "[[i dvd m; j dvd n]] =⇒ i*j dvd (m*n :: nat)"apply (simp add: dvd_def)Unfolding the definiti<strong>on</strong> of divides has left this subgoal:1. [[∃ k. m = i * k; ∃ k. n = j * k]] =⇒ ∃ k. m * n = i * j * kNext, we eliminate the two existential quantifiers in the assumpti<strong>on</strong>s:apply (erule exE)1. V k. [[∃ k. n = j * k; m = i * k]] =⇒ ∃ k. m * n = i * j * kapply (erule exE)1. V k ka. [[m = i * k; n = j * ka]] =⇒ ∃ k. m * n = i * j * kThe term needed to instantiate the remaining quantifier is k*ka. But ka is anautomatically-generated name. As noted above, references to such variablenames makes a proof less resilient to future changes. So, first we rename themost recent variable to l:apply (rename_tac l)1. V k l. [[m = i * k; n = j * l]] =⇒ ∃ k. m * n = i * j * kWe instantiate the quantifier with k*l:apply (rule_tac x="k*l" in exI)1. V k ka. [[m = i * k; n = j * ka]] =⇒ m * n = i * j * (k * ka)The rest is automatic, by arithmetic.apply simpd<strong>on</strong>e5.10 Descripti<strong>on</strong> Operators<strong>HOL</strong> provides two descripti<strong>on</strong> operators. A definite descripti<strong>on</strong> formalizesthe word “the,” as in “the greatest divisior of n.” It returns an arbitraryvalue unless the formula has a unique soluti<strong>on</strong>. An indefinite descripti<strong>on</strong>formalizes the word “some,” as in “some member of S.” It differs from adefinite descripti<strong>on</strong> in not requiring the soluti<strong>on</strong> to be unique: it uses theaxiom of choice to pick any soluti<strong>on</strong>.!!Descripti<strong>on</strong> operators can be hard to reas<strong>on</strong> about. Novices should try to avoidthem. Fortunately, descripti<strong>on</strong>s are seldom required.


86 5. The Rules of the Game5.10.1 Definite Descripti<strong>on</strong>sA definite descripti<strong>on</strong> is traditi<strong>on</strong>ally written ιx.P(x). It denotes the x suchthat P(x) is true, provided there exists a unique such x; otherwise, it returnsan arbitrary value of the expected type. <strong>Isabelle</strong> uses THE for the Greekletter ι.We reas<strong>on</strong> using this rule, where a is the unique soluti<strong>on</strong>:[[P a; V x. P x =⇒ x = a]] =⇒ (THE x. P x) = a(the_equality)For instance, we can define the cardinality of a finite set A to be that nsuch that A is in <strong>on</strong>e-to-<strong>on</strong>e corresp<strong>on</strong>dence with {1, . . . , n}. We can thenprove that the cardinality of the empty set is zero (since n = 0 satisfies thedescripti<strong>on</strong>) and proceed to prove other facts.A more challenging example illustrates how <strong>Isabelle</strong>/<strong>HOL</strong> defines the leastnumber operator, which denotes the least x satisfying P:(LEAST x. P x) = (THE x. P x ∧ (∀ y. P y −→ x ≤ y))Let us prove the analogue of the_equality for LEAST.theorem Least_equality:"[[P (k::nat); ∀ x. P x −→ k ≤ x]] =⇒ (LEAST x. P x) = k"apply (simp add: Least_def)1. [[P k; ∀ x. P x −→ k ≤ x]]=⇒ (THE x. P x ∧ (∀ y. P y −→ x ≤ y)) = kThe first step has merely unfolded the definiti<strong>on</strong>.apply (rule the_equality)1. [[P k; ∀ x. P x −→ k ≤ x]] =⇒ P k ∧ (∀ y. P y −→ k ≤ y)2. V x. [[P k; ∀ x. P x −→ k ≤ x; P x ∧ (∀ y. P y −→ x ≤ y)]]=⇒ x = kAs always with the_equality, we must show existence and uniqueness of theclaimed soluti<strong>on</strong>, k. Existence, the first subgoal, is trivial. Uniqueness, thesec<strong>on</strong>d subgoal, follows by antisymmetry:[[x ≤ y; y ≤ x]] =⇒ x = y(order_antisym)The assumpti<strong>on</strong>s imply both k ≤ x and x ≤ k. One call to auto does it all:by (auto intro: order_antisym)5.10.2 Indefinite Descripti<strong>on</strong>sAn indefinite descripti<strong>on</strong> is traditi<strong>on</strong>ally written εx.P(x) and is known asHilbert’s ε-operator. It denotes some x such that P(x) is true, provided <strong>on</strong>eexists. <strong>Isabelle</strong> uses SOME for the Greek letter ε.Here is the definiti<strong>on</strong> of inv, which expresses inverses of functi<strong>on</strong>s:inv f ≡ λy. SOME x. f x = y(inv_def)


5.10 Descripti<strong>on</strong> Operators 87Using SOME rather than THE makes inv f behave well even if f is not injective.As it happens, most useful theorems about inv do assume the functi<strong>on</strong> to beinjective.The inverse of f, when applied to y, returns some x such that f x = y.For example, we can prove inv Suc really is the inverse of the Suc functi<strong>on</strong>lemma "inv Suc (Suc n) = n"by (simp add: inv_def)The proof is a <strong>on</strong>e-liner: the subgoal simplifies to a degenerate applicati<strong>on</strong> ofSOME, which is then erased. In detail, the left-hand side simplifies to SOME x.Suc x = Suc n, then to SOME x. x = n and finally to n.We know nothing about what inv Suc returns when applied to zero. Theproof above still treats SOME as a definite descripti<strong>on</strong>, since it <strong>on</strong>ly reas<strong>on</strong>sabout situati<strong>on</strong>s in which the value is described uniquely. Indeed, SOME satisfiesthis rule:[[P a; V x. P x =⇒ x = a]] =⇒ (SOME x. P x) = aTo go further is tricky and requires rules such as these:P x =⇒ P (SOME x. P x)[[P a; V x. P x =⇒ Q x]] =⇒ Q (SOME x. P x)(some_equality)(someI)(someI2)Rule someI is basic: if anything satisfies P then so does SOME x. P x. Therepetiti<strong>on</strong> of P in the c<strong>on</strong>clusi<strong>on</strong> makes it difficult to apply in a backwardproof, so the derived rule someI2 is also provided.For example, let us prove the axiom of choice:theorem axiom_of_choice: "(∀ x. ∃ y. P x y) =⇒ ∃ f. ∀ x. P x (f x)"apply (rule exI, rule allI)1. V x. ∀ x. ∃ y. P x y =⇒ P x (?f x)We have applied the introducti<strong>on</strong> rules; now it is time to apply the eliminati<strong>on</strong>rules.apply (drule spec, erule exE)1. V x y. P (?x2 x) y =⇒ P x (?f x)The rule someI automatically instantiates f to λx. SOME y. P x y, which isthe choice functi<strong>on</strong>. It also instantiates ?x2 x to x.by (rule someI)Historical Note. The original purpose of Hilbert’s ε-operator was to expressan existential destructi<strong>on</strong> rule:∃x. PP[(εx.P)/ x]This rule is seldom used for that purpose — it can cause exp<strong>on</strong>ential blow-up— but it is occasi<strong>on</strong>ally used as an introducti<strong>on</strong> rule for the ε-operator. Itsname in <strong>HOL</strong> is someI_ex.


88 5. The Rules of the Game5.11 Some Proofs That FailMost of the examples in this tutorial involve proving theorems. But not everyc<strong>on</strong>jecture is true, and it can be instructive to see how proofs fail. Here weattempt to prove a distributive law involving the existential quantifier andc<strong>on</strong>juncti<strong>on</strong>.lemma "(∃ x. P x) ∧ (∃ x. Q x) =⇒ ∃ x. P x ∧ Q x"The first steps are routine. We apply c<strong>on</strong>juncti<strong>on</strong> eliminati<strong>on</strong> to break the assumpti<strong>on</strong>into two existentially quantified assumpti<strong>on</strong>s. Applying existentialeliminati<strong>on</strong> removes <strong>on</strong>e of the quantifiers.apply (erule c<strong>on</strong>jE)apply (erule exE)1. V x. [[∃ x. Q x; P x]] =⇒ ∃ x. P x ∧ Q xWhen we remove the other quantifier, we get a different bound variable inthe subgoal. (The name xa is generated automatically.)apply (erule exE)1. V x xa. [[P x; Q xa]] =⇒ ∃ x. P x ∧ Q xThe proviso of the existential eliminati<strong>on</strong> rule has forced the variables todiffer: we can hardly expect two arbitrary values to be equal! There is noway to prove this subgoal. Removing the c<strong>on</strong>clusi<strong>on</strong>’s existential quantifieryields two identical placeholders, which can become any term involving thevariables x and xa. We need <strong>on</strong>e to become x and the other to become xa,but <strong>Isabelle</strong> requires all instances of a placeholder to be identical.apply (rule exI)apply (rule c<strong>on</strong>jI)1. V x xa. [[P x; Q xa]] =⇒ P (?x3 x xa)2. V x xa. [[P x; Q xa]] =⇒ Q (?x3 x xa)We can prove either subgoal using the assumpti<strong>on</strong> method. If we prove thefirst <strong>on</strong>e, the placeholder changes into x.apply assumpti<strong>on</strong>1. V x xa. [[P x; Q xa]] =⇒ Q xWe are left with a subgoal that cannot be proved. Applying the assumpti<strong>on</strong>method results in an error message:*** empty result sequence -- proof command failedWhen interacting with <strong>Isabelle</strong> via the shell interface, you can aband<strong>on</strong> aproof using the oops command.Here is another abortive proof, illustrating the interacti<strong>on</strong> between boundvariables and unknowns. If R is a reflexive relati<strong>on</strong>, is there an x such thatR x y holds for all y? Let us see what happens when we attempt to prove it.lemma "∀ y. R y y =⇒ ∃ x. ∀ y. R x y"


5.12 Proving Theorems Using the blast Method 89First, we remove the existential quantifier. The new proof state has an unknown,namely ?x.apply (rule exI)1. ∀ y. R y y =⇒ ∀ y. R ?x yIt looks like we can just apply assumpti<strong>on</strong>, but it fails. <strong>Isabelle</strong> refuses tosubstitute y, a bound variable, for ?x; that would be a bound variable capture.We can still try to finish the proof in some other way. We remove the universalquantifier from the c<strong>on</strong>clusi<strong>on</strong>, moving the bound variable y into the subgoal.But note that it is still bound!apply (rule allI)1. V y. ∀ y. R y y =⇒ R ?x yFinally, we try to apply our reflexivity assumpti<strong>on</strong>. We obtain a new assumpti<strong>on</strong>whose identical placeholders may be replaced by any term involving y.apply (drule spec)1. V y. R (?z2 y) (?z2 y) =⇒ R ?x yThis subgoal can <strong>on</strong>ly be proved by putting y for all the placeholders, makingthe assumpti<strong>on</strong> and c<strong>on</strong>clusi<strong>on</strong> become R y y. <strong>Isabelle</strong> can replace ?z2 y byy; this involves instantiating ?z2 to the identity functi<strong>on</strong>. But, just as twosteps earlier, <strong>Isabelle</strong> refuses to substitute y for ?x. This example is typicalof how <strong>Isabelle</strong> enforces sound quantifier reas<strong>on</strong>ing.5.12 Proving Theorems Using the blast MethodIt is hard to prove many theorems using the methods described above. Aproof may be hundreds of steps l<strong>on</strong>g. You may need to search am<strong>on</strong>g differentways of proving certain subgoals. Often a choice that proves <strong>on</strong>e subgoalrenders another impossible to prove. There are further complicati<strong>on</strong>s that wehave not discussed, c<strong>on</strong>cerning negati<strong>on</strong> and disjuncti<strong>on</strong>. <strong>Isabelle</strong>’s classicalreas<strong>on</strong>er is a family of tools that perform such proofs automatically. Themost important of these is the blast method.In this secti<strong>on</strong>, we shall first see how to use the classical reas<strong>on</strong>er in itsdefault mode and then how to insert additi<strong>on</strong>al rules, enabling it to work innew problem domains.We begin with examples from pure predicate logic. The following exampleis known as Andrew’s challenge. Peter Andrews designed it to be hardto prove by automatic means. It is particularly hard for a resoluti<strong>on</strong> prover,where c<strong>on</strong>verting the nested bic<strong>on</strong>diti<strong>on</strong>als to clause form produces a combinatorialexplosi<strong>on</strong> [35]. However, the blast method proves it in a fracti<strong>on</strong> ofa sec<strong>on</strong>d.lemma "((∃ x. ∀ y. p(x)=p(y)) = ((∃ x. q(x))=(∀ y. p(y)))) =((∃ x. ∀ y. q(x)=q(y)) = ((∃ x. p(x))=(∀ y. q(y))))"by blast


90 5. The Rules of the GameThe next example is a logic problem composed by Lewis Carroll. The blastmethod finds it trivial. Moreover, it turns out that not all of the assumpti<strong>on</strong>sare necessary. We can experiment with variati<strong>on</strong>s of this formula and seewhich <strong>on</strong>es can be proved.lemma "(∀ x. h<strong>on</strong>est(x) ∧ industrious(x) −→ healthy(x)) ∧¬ (∃ x. grocer(x) ∧ healthy(x)) ∧(∀ x. industrious(x) ∧ grocer(x) −→ h<strong>on</strong>est(x)) ∧(∀ x. cyclist(x) −→ industrious(x)) ∧(∀ x. ¬healthy(x) ∧ cyclist(x) −→ ¬h<strong>on</strong>est(x))−→ (∀ x. grocer(x) −→ ¬cyclist(x))"by blastThe blast method is also effective for set theory, which is described in thenext chapter. The formula below may look horrible, but the blast methodproves it in millisec<strong>on</strong>ds.lemma "( S i∈I. A(i)) ∩ ( S j∈J. B(j)) =( S i∈I. S j∈J. A(i) ∩ B(j))"by blastFew subgoals are couched purely in predicate logic and set theory. We canextend the scope of the classical reas<strong>on</strong>er by giving it new rules. Extendingit effectively requires understanding the noti<strong>on</strong>s of introducti<strong>on</strong>, eliminati<strong>on</strong>and destructi<strong>on</strong> rules. Moreover, there is a distincti<strong>on</strong> between safe and unsaferules. A safe rule is <strong>on</strong>e that can be applied backwards without losinginformati<strong>on</strong>; an unsafe rule loses informati<strong>on</strong>, perhaps transforming the subgoalinto <strong>on</strong>e that cannot be proved. The safe/unsafe distincti<strong>on</strong> affects theproof search: if a proof attempt fails, the classical reas<strong>on</strong>er backtracks to themost recent unsafe rule applicati<strong>on</strong> and makes another choice.An important special case avoids all these complicati<strong>on</strong>s. A logical equivalence,which in higher-order logic is an equality between formulas, can begiven to the classical reas<strong>on</strong>er and simplifier by using the attribute iff. Youshould do so if the right hand side of the equivalence is simpler than theleft-hand side.For example, here is a simple fact about list c<strong>on</strong>catenati<strong>on</strong>. The result ofappending two lists is empty if and <strong>on</strong>ly if both of the lists are themselvesempty. Obviously, applying this equivalence will result in a simpler goal.When stating this lemma, we include the iff attribute. Once we have provedthe lemma, <strong>Isabelle</strong> will make it known to the classical reas<strong>on</strong>er (and to thesimplifier).lemma [iff]: "(xs@ys = []) = (xs=[] ∧ ys=[])"apply (induct_tac xs)apply (simp_all)d<strong>on</strong>eThis fact about multiplicati<strong>on</strong> is also appropriate for the iff attribute:(?m * ?n = 0) = (?m = 0 ∨ ?n = 0)


5.13 Other Classical Reas<strong>on</strong>ing Methods 91A product is zero if and <strong>on</strong>ly if <strong>on</strong>e of the factors is zero. The reas<strong>on</strong>inginvolves a disjuncti<strong>on</strong>. Proving new rules for disjunctive reas<strong>on</strong>ing is hard,but translating to an actual disjuncti<strong>on</strong> works: the classical reas<strong>on</strong>er handlesdisjuncti<strong>on</strong> properly.In more detail, this is how the iff attribute works. It c<strong>on</strong>verts the equivalenceP = Q to a pair of rules: the introducti<strong>on</strong> rule Q =⇒ P and thedestructi<strong>on</strong> rule P =⇒ Q. It gives both to the classical reas<strong>on</strong>er as safe rules,ensuring that all occurrences of P in a subgoal are replaced by Q. The simplifierperforms the same replacement, since iff gives P = Q to the simplifier.Classical reas<strong>on</strong>ing is different from simplificati<strong>on</strong>. Simplificati<strong>on</strong> is deterministic.It applies rewrite rules repeatedly, as l<strong>on</strong>g as possible, transforminga goal into another goal. Classical reas<strong>on</strong>ing uses search and backtracking inorder to prove a goal outright.5.13 Other Classical Reas<strong>on</strong>ing MethodsThe blast method is our main workhorse for proving theorems automatically.Other comp<strong>on</strong>ents of the classical reas<strong>on</strong>er interact with the simplifier. Stillothers perform classical reas<strong>on</strong>ing to a limited extent, giving the user finec<strong>on</strong>trol over the proof.Of the latter methods, the most useful is clarify. It performs all obviousreas<strong>on</strong>ing steps without splitting the goal into multiple parts. It does notapply unsafe rules that could render the goal unprovable. By performing theobvious steps, clarify lays bare the difficult parts of the problem, wherehuman interventi<strong>on</strong> is necessary.For example, the following c<strong>on</strong>jecture is false:lemma "(∀ x. P x) ∧ (∃ x. Q x) −→ (∀ x. P x ∧ Q x)"apply clarifyThe blast method would simply fail, but clarify presents a subgoal thathelps us see why we cannot c<strong>on</strong>tinue the proof.1. V x xa. [[∀ x. P x; Q xa]] =⇒ P x ∧ Q xThe proof must fail because the assumpti<strong>on</strong> Q xa and c<strong>on</strong>clusi<strong>on</strong> Q x refer todistinct bound variables. To reach this state, clarify applied the introducti<strong>on</strong>rules for −→ and ∀ and the eliminati<strong>on</strong> rule for ∧. It did not apply theintroducti<strong>on</strong> rule for ∧ because of its policy never to split goals.Also available is clarsimp, a method that interleaves clarify and simp.Also there is safe, which like clarify performs obvious steps but even appliesthose that split goals.The force method applies the classical reas<strong>on</strong>er and simplifier to <strong>on</strong>e goal.Unless it can prove the goal, it fails. C<strong>on</strong>trast that with the auto method,which also combines classical reas<strong>on</strong>ing with simplificati<strong>on</strong>. The latter’s purposeis to prove all the easy subgoals and parts of subgoals. Unfortunately,


92 5. The Rules of the Gameit can produce large numbers of new subgoals; also, since it proves somesubgoals and splits others, it obscures the structure of the proof tree. Theforce method does not have these drawbacks. Another difference: force triesharder than auto to prove its goal, so it can take much l<strong>on</strong>ger to terminate.Older comp<strong>on</strong>ents of the classical reas<strong>on</strong>er have largely been supersededby blast, but they still have niche applicati<strong>on</strong>s. Most important am<strong>on</strong>g theseare fast and best. While blast searches for proofs using a built-in firstorderreas<strong>on</strong>er, these earlier methods search for proofs using standard <strong>Isabelle</strong>inference. That makes them slower but enables them to work in the presenceof the more unusual features of <strong>Isabelle</strong> rules, such as type classes and functi<strong>on</strong>unknowns. For example, recall the introducti<strong>on</strong> rule for Hilbert’s ε-operator:?P ?x =⇒ ?P (SOME x. ?P x) (someI)The repeated occurrence of the variable ?P makes this rule tricky to apply.C<strong>on</strong>sider this c<strong>on</strong>trived example:lemma "[[Q a; P a]]=⇒ P (SOME x. P x ∧ Q x) ∧ Q (SOME x. P x ∧ Q x)"apply (rule someI)We can apply rule someI explicitly. It yields the following subgoal:1. [[Q a; P a]] =⇒ P ?x ∧ Q ?xThe proof from this point is trivial. Could we have proved the theorem witha single command? Not using blast: it cannot perform the higher-order unificati<strong>on</strong>needed here. The fast method succeeds:apply (fast intro!: someI)The best method is similar to fast but it uses a best-first search insteadof depth-first search. Accordingly, it is slower but is less susceptible to divergence.Transitivity rules usually cause fast to loop where best can oftenmanage.Here is a summary of the classical reas<strong>on</strong>ing methods:– blast works automatically and is the fastest– clarify and clarsimp perform obvious steps without splitting the goal;safe even splits goals– force uses classical reas<strong>on</strong>ing and simplificati<strong>on</strong> to prove a goal; auto issimilar but leaves what it cannot prove– fast and best are legacy methods that work well with rules involvingunusual featuresA table illustrates the relati<strong>on</strong>ships am<strong>on</strong>g four of these methods.no split splitno simp clarify safesimp clarsimp auto


5.14 Finding More Theorems 935.14 Finding More TheoremsIn Sect. 3.1.11, we introduced Proof General’s Find butt<strong>on</strong> for finding theoremsin the database via pattern matching. If we are inside a proof, we canbe more specific; we can search for introducti<strong>on</strong>, eliminati<strong>on</strong> and destructi<strong>on</strong>rules with respect to the current goal. For this purpose, Find provides threeaditi<strong>on</strong>al search criteria: intro, elim and dest.For example, given the goal1. A ∧ Byou can click <strong>on</strong> Find and type in the search expressi<strong>on</strong> intro. You willbe shown a few rules ending in =⇒ ?P ∧ ?Q, am<strong>on</strong>g them c<strong>on</strong>jI. You mayeven discover that the very theorem you are trying to prove is already in thedatabase. Given the goal1. A −→ Athe search for intro finds not just impI but also imp_refl: ?P −→ ?P.As before, search criteria can be combined freely: for example,"_ @ _"introsearches for all introducti<strong>on</strong> rules that match the current goal and menti<strong>on</strong>the @ functi<strong>on</strong>.Searching for eliminati<strong>on</strong> and destructi<strong>on</strong> rules via elim and dest is analogousto intro but takes the assumpti<strong>on</strong>s into account, too.5.15 Forward Proof: Transforming TheoremsForward proof means deriving new facts from old <strong>on</strong>es. It is the most fundamentaltype of proof. Backward proof, by working from goals to subgoals, canhelp us find a difficult proof. But it is not always the best way of presentingthe proof thus found. Forward proof is particularly good for reas<strong>on</strong>ing fromthe general to the specific. For example, c<strong>on</strong>sider this distributive law for thegreatest comm<strong>on</strong> divisor:k × gcd(m, n) = gcd(k × m, k × n)Putting m = 1 we get (since gcd(1, n) = 1 and k × 1 = k)k = gcd(k, k × n)We have derived a new fact; if re-oriented, it might be useful for simplificati<strong>on</strong>.After re-orienting it and putting n = 1, we derive another useful law:gcd(k, k) = kSubstituting values for variables — instantiati<strong>on</strong> — is a forward step. Reorientati<strong>on</strong>works by applying the symmetry of equality to an equati<strong>on</strong>, so ittoo is a forward step.


94 5. The Rules of the Game5.15.1 Modifying a Theorem using of, where and THENLet us reproduce our examples in <strong>Isabelle</strong>. Recall that in Sect. 3.5.3 we declaredthe recursive functi<strong>on</strong> gcd:fun gcd :: "nat ⇒ nat ⇒ nat" where"gcd m n = (if n=0 then m else gcd n (m mod n))"From this definiti<strong>on</strong>, it is possible to prove the distributive law. That takesus to the starting point for our example.?k * gcd ?m ?n = gcd (?k * ?m) (?k * ?n) (gcd_mult_distrib2)The first step in our derivati<strong>on</strong> is to replace ?m by 1. We instantiate thetheorem using of, which identifies variables in order of their appearance fromleft to right. In this case, the variables are ?k, ?m and ?n. So, the expressi<strong>on</strong>[of k 1] replaces ?k by k and ?m by 1.lemmas gcd_mult_0 = gcd_mult_distrib2 [of k 1]The keyword lemmas declares a new theorem, which can be derived from anexisting <strong>on</strong>e using attributes such as [of k 1]. The command thm gcd_mult_0displays the result:k * gcd 1 ?n = gcd (k * 1) (k * ?n)Something is odd: k is an ordinary variable, while ?n is schematic. We didnot specify an instantiati<strong>on</strong> for ?n. In its present form, the theorem does notallow substituti<strong>on</strong> for k. One soluti<strong>on</strong> is to avoid giving an instantiati<strong>on</strong> for?k: instead of a term we can put an underscore (_). For example,gcd_mult_distrib2 [of _ 1]replaces ?m by 1 but leaves ?k unchanged.An equivalent soluti<strong>on</strong> is to use the attribute where.gcd mult distrib2 [where m=1]While of refers to variables by their positi<strong>on</strong>, where refers to variables byname. Multiple instantiati<strong>on</strong>s are separated by and, as in this example:gcd mult distrib2 [where m=1 and k=1]We now c<strong>on</strong>tinue the present example with the versi<strong>on</strong> of gcd_mult_0shown above, which has k instead of ?k. Once we have replaced ?m by 1, wemust next simplify the theorem gcd_mult_0, performing the steps gcd(1, n) =1 and k × 1 = k. The simplified attribute takes a theorem and returns theresult of simplifying it, with respect to the default simplificati<strong>on</strong> rules:lemmas gcd_mult_1 = gcd_mult_0 [simplified]Again, we display the resulting theorem:k = gcd k (k * ?n)To re-orient the equati<strong>on</strong> requires the symmetry rule:


5.15 Forward Proof: Transforming Theorems 95?s = ?t =⇒ ?t = ?s (sym)The following declarati<strong>on</strong> gives our equati<strong>on</strong> to sym:lemmas gcd_mult = gcd_mult_1 [THEN sym]Here is the result:gcd k (k * ?n) = kTHEN sym gives the current theorem to the rule sym and returns the resultingc<strong>on</strong>clusi<strong>on</strong>. The effect is to exchange the two operands of the equality.Typically THEN is used with destructi<strong>on</strong> rules. Also useful is THEN spec, whichremoves the quantifier from a theorem of the form ∀x. P, and THEN mp, whichc<strong>on</strong>verts the implicati<strong>on</strong> P → Q into the rule P . Similar to mp are the followingtwo rules, which extract the two directi<strong>on</strong>s of reas<strong>on</strong>ing about a booleanQequivalence:[[?Q = ?P; ?Q]] =⇒ ?P[[?P = ?Q; ?Q]] =⇒ ?P(iffD1)(iffD2)Normally we would never name the intermediate theorems such as gcd_mult_0and gcd_mult_1 but would combine the three forward steps:lemmas gcd_mult = gcd_mult_distrib2 [of k 1, simplified, THEN sym]The directives, or attributes, are processed from left to right. This declarati<strong>on</strong>of gcd_mult is equivalent to the previous <strong>on</strong>e.Such declarati<strong>on</strong>s can make the proof script hard to read. Better is tostate the new lemma explicitly and to prove it using a single rule methodwhose operand is expressed using forward reas<strong>on</strong>ing:lemma gcd mult [simp]: "gcd k (k*n) = k"by (rule gcd_mult_distrib2 [of k 1, simplified, THEN sym])Compared with the previous proof of gcd_mult, this versi<strong>on</strong> shows the readerwhat has been proved. Also, the result will be processed in the normal way.In particular, <strong>Isabelle</strong> generalizes over all variables: the resulting theorem willhave ?k instead of k.At the start of this secti<strong>on</strong>, we also saw a proof of gcd(k, k) = k. Here isthe <strong>Isabelle</strong> versi<strong>on</strong>:lemma gcd self [simp]: "gcd k k = k"by (rule gcd_mult [of k 1, simplified])!!To give of a n<strong>on</strong>atomic term, enclose it in quotati<strong>on</strong> marks, as in [of "k*m"].The term must not c<strong>on</strong>tain unknowns: an attribute such as [of "?k*m"] willbe rejected.


96 5. The Rules of the Game5.15.2 Modifying a Theorem using OFRecall that of generates an instance of a rule by specifying values for itsvariables. Analogous is OF, which generates an instance of a rule by specifyingfacts for its premises.We again need the divides relati<strong>on</strong> of number theory, which as we recallis defined by?m dvd ?n ≡ ∃ k. ?n = ?m * k (dvd_def)Suppose, for example, that we have proved the following rule. It states thatif k and n are relatively prime and if k divides m × n then k divides m.[[gcd ?k ?n = 1; ?k dvd ?m * ?n]] =⇒ ?k dvd ?m(relprime_dvd_mult)We can use OF to create an instance of this rule. First, we prove an instanceof its first premise:lemma relprime 20 81: "gcd 20 81 = 1"by (simp add: gcd.simps)We have evaluated an applicati<strong>on</strong> of the gcd functi<strong>on</strong> by simplificati<strong>on</strong>. Expressi<strong>on</strong>evaluati<strong>on</strong> involving recursive functi<strong>on</strong>s is not guaranteed to terminate,and it can be slow; <strong>Isabelle</strong> performs arithmetic by rewriting symbolicbit strings. Here, however, the simplificati<strong>on</strong> takes less than <strong>on</strong>e sec<strong>on</strong>d. Wecan give this new lemma to OF. The expressi<strong>on</strong>relprime_dvd_mult [OF relprime_20_81]yields the theorem20 dvd (?m * 81) =⇒ 20 dvd ?mOF takes any number of operands. C<strong>on</strong>sider the following facts about thedivides relati<strong>on</strong>:[[?k dvd ?m; ?k dvd ?n]] =⇒ ?k dvd ?m + ?n(dvd_add)?m dvd ?m (dvd_refl)Let us supply dvd_refl for each of the premises of dvd_add:dvd_add [OF dvd_refl dvd_refl]Here is the theorem that we have expressed:?k dvd (?k + ?k)As with of, we can use the _ symbol to leave some positi<strong>on</strong>s unspecified:dvd_add [OF _ dvd_refl]The result is?k dvd ?m =⇒ ?k dvd ?m + ?k


5.16 Forward Reas<strong>on</strong>ing in a Backward Proof 97You may have noticed that THEN and OF are based <strong>on</strong> the same idea,namely to combine two rules. They differ in the order of the combinati<strong>on</strong>and thus in their effect. We use THEN typically with a destructi<strong>on</strong> rule toextract a subformula of the current theorem. We use OF with a list of factsto generate an instance of the current theorem.Here is a summary of some primitives for forward reas<strong>on</strong>ing:– of instantiates the variables of a rule to a list of terms– OF applies a rule to a list of theorems– THEN gives a theorem to a named rule and returns the c<strong>on</strong>clusi<strong>on</strong>– simplified applies the simplifier to a theorem– lemmas assigns a name to the theorem produced by the attributes above5.16 Forward Reas<strong>on</strong>ing in a Backward ProofWe have seen that the forward proof directives work well within a backwardproof. There are many ways to achieve a forward style using our existingproof methods. We shall also meet some new methods that perform forwardreas<strong>on</strong>ing.The methods drule, frule, drule_tac, etc., reas<strong>on</strong> forward from a subgoal.We have seen them already, using rules such as mp and spec to operate <strong>on</strong>formulae. They can also operate <strong>on</strong> terms, using rules such as these:x = y =⇒ f x = f yi ≤ j =⇒ i * k ≤ j * k(arg_c<strong>on</strong>g)(mult_le_m<strong>on</strong>o1)For example, let us prove a fact about divisibility in the natural numbers:lemma "2 ≤ u =⇒ u*m ≠ Suc(u*n)"apply (intro notI)1. [[2 ≤ u; u * m = Suc (u * n)]] =⇒ FalseThe key step is to apply the functi<strong>on</strong> . . . mod u to both sides of the equati<strong>on</strong>u*m = Suc(u*n):apply (drule_tac f="λx. x mod u" in arg_c<strong>on</strong>g)1. [[2 ≤ u; u * m mod u = Suc (u * n) mod u]] =⇒ FalseSimplificati<strong>on</strong> reduces the left side to 0 and the right side to 1, yielding therequired c<strong>on</strong>tradicti<strong>on</strong>.apply (simp add: mod_Suc)d<strong>on</strong>eOur proof has used a fact about remainder:Suc m mod n =(if Suc (m mod n) = n then 0 else Suc (m mod n))(mod_Suc)


98 5. The Rules of the Game5.16.1 The Method insertThe insert method inserts a given theorem as a new assumpti<strong>on</strong> of all subgoals.This already is a forward step; moreover, we may (as always whenusing a theorem) apply of, THEN and other directives. The new assumpti<strong>on</strong>can then be used to help prove the subgoals.For example, c<strong>on</strong>sider this theorem about the divides relati<strong>on</strong>. The firstproof step inserts the distributive law for gcd. We specify its variables asshown.lemma relprime dvd mult:"[[ gcd k n = 1; k dvd m*n ]] =⇒ k dvd m"apply (insert gcd_mult_distrib2 [of m k n])In the resulting subgoal, note how the equati<strong>on</strong> has been inserted:1. [[gcd k n = 1; k dvd m * n; m * gcd k n = gcd (m * k) (m * n)]]=⇒ k dvd mThe next proof step utilizes the assumpti<strong>on</strong> gcd k n = 1 (note that Suc 0 isanother expressi<strong>on</strong> for 1):apply(simp)1. [[gcd k n = Suc 0; k dvd m * n; m = gcd (m * k) (m * n)]]=⇒ k dvd mSimplificati<strong>on</strong> has yielded an equati<strong>on</strong> for m. The rest of the proof is omitted.Here is another dem<strong>on</strong>strati<strong>on</strong> of insert. Divisi<strong>on</strong> and remainder obey awell-known law:(?m div ?n) * ?n + ?m mod ?n = ?mWe refer to this law explicitly in the following proof:lemma div_mult_self_is_m:"0


5.16.2 The Method subgoal_tac5.16 Forward Reas<strong>on</strong>ing in a Backward Proof 99A related method is subgoal_tac, but instead of inserting a theorem as anassumpti<strong>on</strong>, it inserts an arbitrary formula. This formula must be provedlater as a separate subgoal. The idea is to claim that the formula holds <strong>on</strong>the basis of the current assumpti<strong>on</strong>s, to use this claim to complete the proof,and finally to justify the claim. It gives the proof some structure. If you findyourself generating a complex assumpti<strong>on</strong> by a l<strong>on</strong>g series of forward steps,c<strong>on</strong>sider using subgoal_tac instead: you can state the formula you are aimingfor, and perhaps prove it automatically.Look at the following example.lemma "[[(z::int) < 37; 66 < 2*z; z*z ≠ 1225; Q(34); Q(36)]]=⇒ Q(z)"apply (subgoal_tac "z = 34 ∨ z = 36")apply blastapply (subgoal_tac "z ≠ 35")apply arithapply forced<strong>on</strong>eThe first assumpti<strong>on</strong> tells us that z is no greater than 36. The sec<strong>on</strong>d tellsus that z is at least 34. The third assumpti<strong>on</strong> tells us that z cannot be 35,since 35 × 35 = 1225. So z is either 34 or 36, and since Q holds for both ofthose values, we have the c<strong>on</strong>clusi<strong>on</strong>.The <strong>Isabelle</strong> proof closely follows this reas<strong>on</strong>ing. The first step is to claimthat z is either 34 or 36. The resulting proof state gives us two subgoals:1. [[z < 37; 66 < 2 * z; z * z ≠ 1225; Q 34; Q 36;z = 34 ∨ z = 36]]=⇒ Q z2. [[z < 37; 66 < 2 * z; z * z ≠ 1225; Q 34; Q 36]]=⇒ z = 34 ∨ z = 36The first subgoal is trivial (blast), but for the sec<strong>on</strong>d <strong>Isabelle</strong> needs help toeliminate the case z=35. The sec<strong>on</strong>d invocati<strong>on</strong> of subgoal_tac leaves twosubgoals:1. [[z < 37; 66 < 2 * z; z * z ≠ 1225; Q 34; Q 36;z ≠ 35]]=⇒ z = 34 ∨ z = 362. [[z < 37; 66 < 2 * z; z * z ≠ 1225; Q 34; Q 36]]=⇒ z ≠ 35Assuming that z is not 35, the first subgoal follows by linear arithmetic(arith). For the sec<strong>on</strong>d subgoal we apply the method force, which proceedsby assuming that z=35 and arriving at a c<strong>on</strong>tradicti<strong>on</strong>.Summary of these methods:– insert adds a theorem as a new assumpti<strong>on</strong>– subgoal_tac adds a formula as a new assumpti<strong>on</strong> and leaves the subgoalof proving that formula


100 5. The Rules of the Game5.17 Managing Large ProofsNaturally you should try to divide proofs into manageable parts. Look forlemmas that can be proved separately. Sometimes you will observe that theyare instances of much simpler facts. On other occasi<strong>on</strong>s, no lemmas suggestthemselves and you are forced to cope with a l<strong>on</strong>g proof involving manysubgoals.5.17.1 Tacticals, or C<strong>on</strong>trol StructuresIf the proof is l<strong>on</strong>g, perhaps it at least has some regularity. Then you canexpress it more c<strong>on</strong>cisely using tacticals, which provide c<strong>on</strong>trol structures.Here is a proof (it would be a <strong>on</strong>e-liner using blast, but forget that) thatc<strong>on</strong>tains a series of repeated commands:lemma "[[P−→Q; Q−→R; R−→S; P]] =⇒ S"apply (drule mp, assumpti<strong>on</strong>)apply (drule mp, assumpti<strong>on</strong>)apply (drule mp, assumpti<strong>on</strong>)apply (assumpti<strong>on</strong>)d<strong>on</strong>eEach of the three identical commands finds an implicati<strong>on</strong> and proves itsantecedent by assumpti<strong>on</strong>. The first <strong>on</strong>e finds P−→Q and P, c<strong>on</strong>cluding Q; thesec<strong>on</strong>d <strong>on</strong>e c<strong>on</strong>cludes R and the third <strong>on</strong>e c<strong>on</strong>cludes S. The final step matchesthe assumpti<strong>on</strong> S with the goal to be proved.Suffixing a method with a plus sign (+) expresses <strong>on</strong>e or more repetiti<strong>on</strong>s:lemma "[[P−→Q; Q−→R; R−→S; P]] =⇒ S"by (drule mp, assumpti<strong>on</strong>)+Using by takes care of the final use of assumpti<strong>on</strong>. The new proof is morec<strong>on</strong>cise. It is also more general: the repetitive method works for a chain ofimplicati<strong>on</strong>s having any length, not just three.Choice is another c<strong>on</strong>trol structure. Separating two methods by a verticalbar (|) gives the effect of applying the first method, and if that fails, tryingthe sec<strong>on</strong>d. It can be combined with repetiti<strong>on</strong>, when the choice must bemade over and over again. Here is a chain of implicati<strong>on</strong>s in which most ofthe antecedents are proved by assumpti<strong>on</strong>, but <strong>on</strong>e is proved by arithmetic:lemma "[[Q−→R; P−→Q; x


5.17 Managing Large Proofs 1015.17.2 Subgoal NumberingAnother problem in large proofs is c<strong>on</strong>tending with huge subgoals or manysubgoals. Inducti<strong>on</strong> can produce a proof state that looks like this:1. bigsubgoal12. bigsubgoal23. bigsubgoal34. bigsubgoal45. bigsubgoal56. bigsubgoal6If each bigsubgoal is 15 lines or so, the proof state will be too big to scrollthrough. By default, <strong>Isabelle</strong> displays at most 10 subgoals. The pr commandlets you change this limit:pr 21. bigsubgoal12. bigsubgoal2A total of 6 subgoals...All methods apply to the first subgoal. Sometimes, not <strong>on</strong>ly in a largeproof, you may want to focus <strong>on</strong> some other subgoal. Then you should trythe commands defer or prefer.In the following example, the first subgoal looks hard, while the otherslook as if blast al<strong>on</strong>e could prove them:1. hard2. ¬ ¬ P =⇒ P3. Q =⇒ QThe defer command moves the first subgoal into the last positi<strong>on</strong>.defer 11. ¬ ¬ P =⇒ P2. Q =⇒ Q3. hardNow we apply blast repeatedly to the easy subgoals:apply blast+1. hardUsing defer, we have cleared away the trivial parts of the proof so that wecan devote attenti<strong>on</strong> to the difficult part.The prefer command moves the specified subgoal into the first positi<strong>on</strong>.For example, if you suspect that <strong>on</strong>e of your subgoals is invalid (not a theorem),then you should investigate that subgoal first. If it cannot be proved,then there is no point in proving the other subgoals.1. ok12. ok23. doubtful


102 5. The Rules of the GameWe decide to work <strong>on</strong> the third subgoal.prefer 31. doubtful2. ok13. ok2If we manage to prove doubtful, then we can work <strong>on</strong> the other subgoals,c<strong>on</strong>fident that we are not wasting our time. Finally we revise the proof scriptto remove the prefer command, since we needed it <strong>on</strong>ly to focus our explorati<strong>on</strong>.The previous example is different: its use of defer stops trivialsubgoals from cluttering the rest of the proof. Even there, we should c<strong>on</strong>siderproving hard as a preliminary lemma. Always seek ways to streamline yourproofs.Summary:– the c<strong>on</strong>trol structures +, ? and | help express complicated proofs– the pr command can limit the number of subgoals to display– the defer and prefer commands move a subgoal to the last or first positi<strong>on</strong>Exercise 5.17.1 Explain the use of ? and + in this proof.lemma "[[P∧Q−→R; P−→Q; P]] =⇒ R"by (drule mp, (intro c<strong>on</strong>jI)?, assumpti<strong>on</strong>+)+5.18 Proving the Correctness of Euclid’s AlgorithmA brief development will dem<strong>on</strong>strate the techniques of this chapter, includingblast applied with additi<strong>on</strong>al rules. We shall also see case_tac used toperform a Boolean case split.Let us prove that gcd computes the greatest comm<strong>on</strong> divisor of its two arguments.We use inducti<strong>on</strong>: gcd.induct is the inducti<strong>on</strong> rule returned by fun.We simplify using rules proved in Sect. 3.5.3, since rewriting by the definiti<strong>on</strong>of gcd can loop.lemma gcd dvd both: "(gcd m n dvd m) ∧ (gcd m n dvd n)"The inducti<strong>on</strong> formula must be a c<strong>on</strong>juncti<strong>on</strong>. In the inductive step, eachc<strong>on</strong>junct establishes the other.1. V m n. (n ≠ 0 =⇒gcd n (m mod n) dvd n ∧gcd n (m mod n) dvd m mod n) =⇒gcd m n dvd m ∧ gcd m n dvd nThe c<strong>on</strong>diti<strong>on</strong>al inducti<strong>on</strong> hypothesis suggests doing a case analysis <strong>on</strong>n=0. We apply case_tac with type bool — and not with a datatype, as we haved<strong>on</strong>e until now. Since nat is a datatype, we could have written case_tac ninstead of case_tac "n=0". However, the definiti<strong>on</strong> of gcd makes a Booleandecisi<strong>on</strong>:


5.18 Proving the Correctness of Euclid’s Algorithm 103"gcd m n = (if n=0 then m else gcd n (m mod n))"Proofs about a functi<strong>on</strong> frequently follow the functi<strong>on</strong>’s definiti<strong>on</strong>, so weperform case analysis over the same formula.apply (case_tac "n=0")1. V m n. [[n ≠ 0 =⇒gcd n (m mod n) dvd n ∧ gcd n (m mod n) dvd m mod n;n = 0]]=⇒ gcd m n dvd m ∧ gcd m n dvd n2. V m n. [[n ≠ 0 =⇒gcd n (m mod n) dvd n ∧ gcd n (m mod n) dvd m mod n;n ≠ 0]]=⇒ gcd m n dvd m ∧ gcd m n dvd nSimplificati<strong>on</strong> leaves <strong>on</strong>e subgoal:apply (simp_all)1. V m n. [[gcd n (m mod n) dvd n ∧ gcd n (m mod n) dvd m mod n;0 < n]]=⇒ gcd n (m mod n) dvd mHere, we can use blast. One of the assumpti<strong>on</strong>s, the inducti<strong>on</strong> hypothesis, isa c<strong>on</strong>juncti<strong>on</strong>. The two divides relati<strong>on</strong>ships it asserts are enough to provethe c<strong>on</strong>clusi<strong>on</strong>, for we have the following theorem at our disposal:[[?k dvd (?m mod ?n); ?k dvd ?n]] =⇒ ?k dvd ?m(dvd_mod_imp_dvd)This theorem can be applied in various ways. As an introducti<strong>on</strong> rule, itwould cause backward chaining from the c<strong>on</strong>clusi<strong>on</strong> (namely ?k dvd ?m) tothe two premises, which also involve the divides relati<strong>on</strong>. This process doesnot look promising and could easily loop. More sensible is to apply the rulein the forward directi<strong>on</strong>; each step would eliminate an occurrence of the modsymbol, so the process must terminate.apply (blast dest: dvd_mod_imp_dvd)d<strong>on</strong>eAttaching the dest attribute to dvd_mod_imp_dvd tells blast to use it as destructi<strong>on</strong>rule; that is, in the forward directi<strong>on</strong>.We have proved a c<strong>on</strong>juncti<strong>on</strong>. Now, let us give names to each of the twohalves:lemmas gcd_dvd1 [iff] = gcd_dvd_both [THEN c<strong>on</strong>junct1]lemmas gcd_dvd2 [iff] = gcd_dvd_both [THEN c<strong>on</strong>junct2]Here we see lemmas used with the iff attribute, which supplies the newtheorems to the classical reas<strong>on</strong>er and the simplifier. Recall that THEN isfrequently used with destructi<strong>on</strong> rules; THEN c<strong>on</strong>junct1 extracts the first halfof a c<strong>on</strong>junctive theorem. Given gcd_dvd_both it yieldsgcd ?m1 ?n1 dvd ?m1The variable names ?m1 and ?n1 arise because <strong>Isabelle</strong> renames schematicvariables to prevent clashes. The sec<strong>on</strong>d lemmas declarati<strong>on</strong> yields


104 5. The Rules of the Gamegcd ?m1 ?n1 dvd ?n1To complete the verificati<strong>on</strong> of the gcd functi<strong>on</strong>, we must prove that itreturns the greatest of all the comm<strong>on</strong> divisors of its arguments. The proofis by inducti<strong>on</strong>, case analysis and simplificati<strong>on</strong>.lemma gcd greatest [rule format]:"k dvd m −→ k dvd n −→ k dvd gcd m n"The goal is expressed using <strong>HOL</strong> implicati<strong>on</strong>, −→, because the inducti<strong>on</strong>affects the two prec<strong>on</strong>diti<strong>on</strong>s. The directive rule_format tells <strong>Isabelle</strong> to replaceeach −→ by =⇒ before storing the eventual theorem. This directive canalso remove outer universal quantifiers, c<strong>on</strong>verting the theorem into the usualformat for inference rules. It can replace any series of applicati<strong>on</strong>s of THEN tothe rules mp and spec. We did not have to write this:lemma gcd_greatest [THEN mp, THEN mp]:"k dvd m −→ k dvd n −→ k dvd gcd m n"Because we are again reas<strong>on</strong>ing about gcd, we perform the same inducti<strong>on</strong>and case analysis as in the previous proof:1. V m n. [[n ≠ 0 =⇒k dvd n −→ k dvd m mod n −→ k dvd gcd n (m mod n);n = 0]]=⇒ k dvd m −→ k dvd n −→ k dvd gcd m n2. V m n. [[n ≠ 0 =⇒k dvd n −→ k dvd m mod n −→ k dvd gcd n (m mod n);n ≠ 0]]=⇒ k dvd m −→ k dvd n −→ k dvd gcd m nSimplificati<strong>on</strong> proves both subgoals.apply (simp_all add: dvd_mod)d<strong>on</strong>eIn the first, where n=0, the implicati<strong>on</strong> becomes trivial: k dvd gcd m n goesto k dvd m. The sec<strong>on</strong>d subgoal is proved by an unfolding of gcd, using thisrule about divides:[[?f dvd ?m; ?f dvd ?n]] =⇒ ?f dvd ?m mod ?n(dvd_mod)The facts proved above can be summarized as a single logical equivalence.This step gives us a chance to see another applicati<strong>on</strong> of blast.theorem gcd greatest iff [iff]:"(k dvd gcd m n) = (k dvd m ∧ k dvd n)"by (blast intro!: gcd_greatest intro: dvd_trans)This theorem c<strong>on</strong>cisely expresses the correctness of the gcd functi<strong>on</strong>. We stateit with the iff attribute so that <strong>Isabelle</strong> can use it to remove some occurrencesof gcd. The theorem has a <strong>on</strong>e-line proof using blast supplied withtwo additi<strong>on</strong>al introducti<strong>on</strong> rules. The exclamati<strong>on</strong> mark (intro!) signifies


5.18 Proving the Correctness of Euclid’s Algorithm 105safe rules, which are applied aggressively. Rules given without the exclamati<strong>on</strong>mark are applied reluctantly and their uses can be und<strong>on</strong>e if the searchbacktracks. Here the unsafe rule expresses transitivity of the divides relati<strong>on</strong>:[[?m dvd ?n; ?n dvd ?p]] =⇒ ?m dvd ?p(dvd_trans)Applying dvd_trans as an introducti<strong>on</strong> rule entails a risk of looping, for itmultiplies occurrences of the divides symbol. However, this proof relies <strong>on</strong>transitivity reas<strong>on</strong>ing. The rule gcd greatest is safe to apply aggressivelybecause it yields simpler subgoals. The proof implicitly uses gcd_dvd1 andgcd_dvd2 as safe rules, because they were declared using iff.


6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>sThis chapter describes the formalizati<strong>on</strong> of typed set theory, which is thebasis of much else in <strong>HOL</strong>. For example, an inductive definiti<strong>on</strong> yields a set,and the abstract theories of relati<strong>on</strong>s regard a relati<strong>on</strong> as a set of pairs. Thechapter introduces the well-known c<strong>on</strong>stants such as uni<strong>on</strong> and intersecti<strong>on</strong>,as well as the main operati<strong>on</strong>s <strong>on</strong> relati<strong>on</strong>s, such as c<strong>on</strong>verse, compositi<strong>on</strong>and transitive closure. Functi<strong>on</strong>s are also covered. They are not sets in <strong>HOL</strong>,but many of their properties c<strong>on</strong>cern sets: the range of a functi<strong>on</strong> is a set,and the inverse image of a functi<strong>on</strong> maps sets to sets.This chapter will be useful to anybody who plans to develop a substantialproof. Sets are c<strong>on</strong>venient for formalizing computer science c<strong>on</strong>cepts suchas grammars, logical calculi and state transiti<strong>on</strong> systems. <strong>Isabelle</strong> can provemany statements involving sets automatically.This chapter ends with a case study c<strong>on</strong>cerning model checking for thetemporal logic CTL. Most of the other examples are simple. The chapterpresents a small selecti<strong>on</strong> of built-in theorems in order to point out some keyproperties of the various c<strong>on</strong>stants and to introduce you to the notati<strong>on</strong>.Natural deducti<strong>on</strong> rules are provided for the set theory c<strong>on</strong>stants, butthey are seldom used directly, so <strong>on</strong>ly a few are presented here.6.1 Sets<strong>HOL</strong>’s set theory should not be c<strong>on</strong>fused with traditi<strong>on</strong>al, untyped set theory,in which everything is a set. Our sets are typed. In a given set, all elementshave the same type, say τ, and the set itself has type τ set.We begin with intersecti<strong>on</strong>, uni<strong>on</strong> and complement. In additi<strong>on</strong> tothe membership relati<strong>on</strong>, there is a symbol for its negati<strong>on</strong>. These pointscan be seen below.Here are the natural deducti<strong>on</strong> rules for intersecti<strong>on</strong>. Note the resemblanceto those for c<strong>on</strong>juncti<strong>on</strong>.[[c ∈ A; c ∈ B]] =⇒ c ∈ A ∩ Bc ∈ A ∩ B =⇒ c ∈ Ac ∈ A ∩ B =⇒ c ∈ B(IntI)(IntD1)(IntD2)Here are two of the many installed theorems c<strong>on</strong>cerning set complement.Note that it is denoted by a minus sign.


108 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>s(c ∈ - A) = (c /∈ A) (Compl_iff)- (A ∪ B) = - A ∩ - B (Compl_Un)Set difference is the intersecti<strong>on</strong> of a set with the complement of anotherset. Here we also see the syntax for the empty set and for the universal set.A ∩ (B - A) = {}A ∪ - A = UNIV(Diff_disjoint)(Compl_partiti<strong>on</strong>)The subset relati<strong>on</strong> holds between two sets just if every element of <strong>on</strong>eis also an element of the other. This relati<strong>on</strong> is reflexive. These are its naturaldeducti<strong>on</strong> rules:( V x. x ∈ A =⇒ x ∈ B) =⇒ A ⊆ B (subsetI)[[A ⊆ B; c ∈ A]] =⇒ c ∈ B(subsetD)In harder proofs, you may need to apply subsetD giving a specific term for c.However, blast can instantly prove facts such as this <strong>on</strong>e:(A ∪ B ⊆ C) = (A ⊆ C ∧ B ⊆ C) (Un_subset_iff)Here is another example, also proved automatically:lemma "(A ⊆ -B) = (B ⊆ -A)"by blastThis is the same example using ascii syntax, illustrating a pitfall:lemma "(A


6.1 Sets 1096.1.1 Finite Set Notati<strong>on</strong>Finite sets are expressed using the c<strong>on</strong>stant insert, which is a form of uni<strong>on</strong>:insert a A = {a} ∪ A(insert_is_Un)The finite set expressi<strong>on</strong> {a,b} abbreviates insert a (insert b {}). Manyfacts about finite sets can be proved automatically:lemma "{a,b} ∪ {c,d} = {a,b,c,d}"by blastNot everything that we would like to prove is valid. C<strong>on</strong>sider this attempt:lemma "{a,b} ∩ {b,c} = {b}"apply autoThe proof fails, leaving the subgoal b=c. To see why it fails, c<strong>on</strong>sider a correctversi<strong>on</strong>:lemma "{a,b} ∩ {b,c} = (if a=c then {a,b} else {b})"apply simpby blastOur mistake was to suppose that the various items were distinct. Anotherremark: this proof uses two methods, namely simp and blast. Calling simpeliminates the if-then-else expressi<strong>on</strong>, which blast cannot break down. Thecombined methods (namely force and auto) can prove this fact in <strong>on</strong>e step.6.1.2 Set Comprehensi<strong>on</strong>The set comprehensi<strong>on</strong> {x. P} expresses the set of all elements that satisfy thepredicate P. Two laws describe the relati<strong>on</strong>ship between set comprehensi<strong>on</strong>and the membership relati<strong>on</strong>:(a ∈ {x. P x}) = P a (mem_Collect_eq){x. x ∈ A} = A(Collect_mem_eq)Facts such as these have trivial proofs:lemma "{x. P x ∨ x ∈ A} = {x. P x} ∪ A"lemma "{x. P x −→ Q x} = -{x. P x} ∪ {x. Q x}"<strong>Isabelle</strong> has a general syntax for comprehensi<strong>on</strong>, which is best describedthrough an example:lemma "{p*q | p q. p∈prime ∧ q∈prime} ={z. ∃ p q. z = p*q ∧ p∈prime ∧ q∈prime}"The left and right hand sides of this equati<strong>on</strong> are identical. The syntax usedin the left-hand side abbreviates the right-hand side: in this case, all numbersthat are the product of two primes. The syntax provides a neat way of expressingany set given by an expressi<strong>on</strong> built up from variables under specific


110 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>sc<strong>on</strong>straints. The drawback is that it hides the true form of the expressi<strong>on</strong>,with its existential quantifiers.Remark. We do not need sets at all. They are essentially equivalent topredicate variables, which are allowed in higher-order logic. The main benefitof sets is their notati<strong>on</strong>; we can write x∈A and {z. P} where predicates wouldrequire writing A(x) and λz. P.6.1.3 Binding OperatorsUniversal and existential quantificati<strong>on</strong>s may range over sets, with the obviousmeaning. Here are the natural deducti<strong>on</strong> rules for the bounded universalquantifier. Occasi<strong>on</strong>ally you will need to apply bspec with an explicit instantiati<strong>on</strong>of the variable x:( V x. x ∈ A =⇒ P x) =⇒ ∀ x∈A. P x (ballI)[[∀ x∈A. P x; x ∈ A]] =⇒ P x(bspec)Dually, here are the natural deducti<strong>on</strong> rules for the bounded existential quantifier.You may need to apply bexI with an explicit instantiati<strong>on</strong>:[[P x; x ∈ A]] =⇒ ∃ x∈A. P x[[∃ x∈A. P x; V x. [[x ∈ A; P x]] =⇒ Q]] =⇒ Q(bexI)(bexE)Uni<strong>on</strong>s can be formed over the values of a given set. The syntax isS x∈A. B or UN x:A. B in ascii. Indexed uni<strong>on</strong> satisfies this basic law:(b ∈ ( S x∈A. B x)) = (∃ x∈A. b ∈ B x) (UN_iff)It has two natural deducti<strong>on</strong> rules similar to those for the existential quantifier.Sometimes UN_I must be applied explicitly:[[a ∈ A; b ∈ B a]] =⇒ b ∈ ( S x∈A. B x)[[b ∈ ( S x∈A. B x); V x. [[x ∈ A; b ∈ B x]] =⇒ R]] =⇒ R(UN_I)(UN_E)The following built-in abbreviati<strong>on</strong> (see Sect. 4.1.4) lets us express the uni<strong>on</strong>over a type:( S x. B x) ≡ ( S x∈UNIV. B x)We may also express the uni<strong>on</strong> of a set of sets, written Uni<strong>on</strong> C in ascii:(A ∈ S C) = (∃ X∈C. A ∈ X) (Uni<strong>on</strong>_iff)Intersecti<strong>on</strong>s are treated dually, although they seem to be used less oftenthan uni<strong>on</strong>s. The syntax below would be INT x: A. B and Inter C in ascii.Am<strong>on</strong>g others, these theorems are available:(b ∈ ( T x∈A. B x)) = (∀ x∈A. b ∈ B x) (INT_iff)(A ∈ T C) = (∀ X∈C. A ∈ X) (Inter_iff)<strong>Isabelle</strong> uses logical equivalences such as those above in automatic proof.Uni<strong>on</strong>s, intersecti<strong>on</strong>s and so forth are not simply replaced by their definiti<strong>on</strong>s.Instead, membership tests are simplified. For example, x ∈ A ∪ B is replacedby x ∈ A ∨ x ∈ B.


6.2 Functi<strong>on</strong>s 111The internal form of a comprehensi<strong>on</strong> involves the c<strong>on</strong>stant Collect,which occasi<strong>on</strong>ally appears when a goal or theorem is displayed. For example,Collect P is the same term as {x. P x}. The same thing can happen withquantifiers: All P is ∀ x. P x and Ex P is ∃ x. P x; also Ball A P is ∀ x∈A. Px and Bex A P is ∃ x∈A. P x. For indexed uni<strong>on</strong>s and intersecti<strong>on</strong>s, you maysee the c<strong>on</strong>stants UNION and INTER. The internal c<strong>on</strong>stant for εx.P(x) is Eps.We have <strong>on</strong>ly scratched the surface of <strong>Isabelle</strong>/<strong>HOL</strong>’s set theory, whichprovides hundreds of theorems for your use.6.1.4 Finiteness and CardinalityThe predicate finite holds of all finite sets. <strong>Isabelle</strong>/<strong>HOL</strong> includes manyfamiliar theorems about finiteness and cardinality (card). For example, wehave theorems c<strong>on</strong>cerning the cardinalities of uni<strong>on</strong>s, intersecti<strong>on</strong>s and thepowerset:[[finite A; finite B]]=⇒ card A + card B = card (A ∪ B) + card (A ∩ B) (card_Un_Int)finite A =⇒ card (Pow A) = 2 ^ card A(card_Pow)finite A =⇒card {B. B ⊆ A ∧ card B = k} = card A choose k(n_subsets)Writing |A| as n, the last of these theorems says that the number of k-elementsubsets of A is ( nk).6.2 Functi<strong>on</strong>sThis secti<strong>on</strong> describes a few c<strong>on</strong>cepts that involve functi<strong>on</strong>s. Some of the moreimportant theorems are given al<strong>on</strong>g with the names. A few sample proofsappear. Unlike with set theory, however, we cannot simply state lemmas andexpect them to be proved using blast.6.2.1 Functi<strong>on</strong> BasicsTwo functi<strong>on</strong>s are equal if they yield equal results given equal arguments.This is the principle of extensi<strong>on</strong>ality for functi<strong>on</strong>s:( V x. f x = g x) =⇒ f = g (ext)Functi<strong>on</strong> update is useful for modelling machine states. It has the obviousdefiniti<strong>on</strong> and many useful facts are proved about it. In particular, thefollowing equati<strong>on</strong> is installed as a simplificati<strong>on</strong> rule:(f(x:=y)) z = (if z = x then y else f z)(fun_upd_apply)


112 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>sTwo syntactic points must be noted. In (f(x:=y)) z we are applying anupdated functi<strong>on</strong> to an argument; the outer parentheses are essential. A seriesof two or more updates can be abbreviated as shown <strong>on</strong> the left-hand side ofthis theorem:f(x:=y, x:=z) = f(x:=z)(fun_upd_upd)Note also that we can write f(x:=z) with <strong>on</strong>ly <strong>on</strong>e pair of parentheses whenit is not being applied to an argument.The identity functi<strong>on</strong> and functi<strong>on</strong> compositi<strong>on</strong> are defined:id ≡ λx. xf ◦ g ≡ λx. f (g x)(id_def)(o_def)Many familiar theorems c<strong>on</strong>cerning the identity and compositi<strong>on</strong> are proved.For example, we have the associativity of compositi<strong>on</strong>:f ◦ (g ◦ h) = f ◦ g ◦ h(o_assoc)6.2.2 Injecti<strong>on</strong>s, Surjecti<strong>on</strong>s, Bijecti<strong>on</strong>sA functi<strong>on</strong> may be injective, surjective or bijective:inj_<strong>on</strong> f A ≡ ∀ x∈A. ∀ y∈A. f x = f y −→ x = ysurj f ≡ ∀ y. ∃ x. y = f xbij f ≡ inj f ∧ surj f(inj_<strong>on</strong>_def)(surj_def)(bij_def)The sec<strong>on</strong>d argument of inj_<strong>on</strong> lets us express that a functi<strong>on</strong> is injective overa given set. This refinement is useful in higher-order logic, where functi<strong>on</strong>s aretotal; in some cases, a functi<strong>on</strong>’s natural domain is a subset of its domain type.Writing inj f abbreviates inj_<strong>on</strong> f UNIV, for when f is injective everywhere.The operator inv expresses the inverse of a functi<strong>on</strong>. In general theinverse may not be well behaved. We have the usual laws, such as these:inj f =⇒ inv f (f x) = x (inv_f_f)surj f =⇒ f (inv f y) = y(surj_f_inv_f)bij f =⇒ inv (inv f) = f (inv_inv_eq)Theorems involving these c<strong>on</strong>cepts can be hard to prove. The followingexample is easy, but it cannot be proved automatically. To begin with, weneed a law that relates the equality of functi<strong>on</strong>s to equality over all arguments:(f = g) = (∀ x. f x = g x) (expand_fun_eq)This is just a restatement of extensi<strong>on</strong>ality. Our lemma states that an injecti<strong>on</strong>can be cancelled from the left side of functi<strong>on</strong> compositi<strong>on</strong>:lemma "inj f =⇒ (f o g = f o h) = (g = h)"apply (simp add: expand_fun_eq inj_<strong>on</strong>_def)apply autod<strong>on</strong>eThe first step of the proof invokes extensi<strong>on</strong>ality and the definiti<strong>on</strong>s ofinjectiveness and compositi<strong>on</strong>. It leaves <strong>on</strong>e subgoal:


6.3 Relati<strong>on</strong>s 1131. ∀ x y. f x = f y −→ x = y =⇒(∀ x. f (g x) = f (h x)) = (∀ x. g x = h x)This can be proved using the auto method.6.2.3 Functi<strong>on</strong> ImageThe image of a set under a functi<strong>on</strong> is a most useful noti<strong>on</strong>. It has theobvious definiti<strong>on</strong>:f ‘ A ≡ {y. ∃ x∈A. y = f x}Here are some of the many facts proved about image:(image_def)(f ◦ g) ‘ r = f ‘ g ‘ r (image_compose)f‘(A ∪ B) = f‘A ∪ f‘B(image_Un)inj f =⇒ f‘(A ∩ B) = f‘A ∩ f‘B(image_Int)Laws involving image can often be proved automatically. Here are twoexamples, illustrating c<strong>on</strong>necti<strong>on</strong>s with indexed uni<strong>on</strong> and with the generalsyntax for comprehensi<strong>on</strong>:lemma "f‘A ∪ g‘A = ( S x∈A. {f x, g x})"lemma "f ‘ {(x,y). P x y} = {f(x,y) | x y. P x y}"A functi<strong>on</strong>’s range is the set of values that the functi<strong>on</strong> can take <strong>on</strong>. Itis, in fact, the image of the universal set under that functi<strong>on</strong>. There is noc<strong>on</strong>stant range. Instead, range abbreviates an applicati<strong>on</strong> of image to UNIV:range f ⇋ f‘UNIVFew theorems are proved specifically for range; in most cases, you shouldlook for a more general theorem c<strong>on</strong>cerning images.Inverse image is also useful. It is defined as follows:f -‘ B ≡ {x. f x ∈ B}This is <strong>on</strong>e of the facts proved about it:f -‘ (- A) = - f -‘ A(vimage_def)(vimage_Compl)6.3 Relati<strong>on</strong>sA relati<strong>on</strong> is a set of pairs. As such, the set operati<strong>on</strong>s apply to them. Forinstance, we may form the uni<strong>on</strong> of two relati<strong>on</strong>s. Other primitives are definedspecifically for relati<strong>on</strong>s.


114 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>s6.3.1 Relati<strong>on</strong> BasicsThe identity relati<strong>on</strong>, also known as equality, has the obvious definiti<strong>on</strong>:Id ≡ {p. ∃ x. p = (x,x)}Compositi<strong>on</strong> of relati<strong>on</strong>s (the infix O) is also available:r O s ≡ {(x,z). ∃ y. (x,y) ∈ s ∧ (y,z) ∈ r}This is <strong>on</strong>e of the many lemmas proved about these c<strong>on</strong>cepts:R O Id = R(Id_def)(rel_comp_def)(R_O_Id)Compositi<strong>on</strong> is m<strong>on</strong>ot<strong>on</strong>ic, as are most of the primitives appearing in thischapter. We have many theorems similar to the following <strong>on</strong>e:[[r’ ⊆ r; s’ ⊆ s]] =⇒ r’ O s’ ⊆ r O s(rel_comp_m<strong>on</strong>o)The c<strong>on</strong>verse or inverse of a relati<strong>on</strong> exchanges the roles of the twooperands. We use the postfix notati<strong>on</strong> r −1 or r^-1 in ASCII.((a,b) ∈ r −1 ) = ((b,a) ∈ r)Here is a typical law proved about c<strong>on</strong>verse and compositi<strong>on</strong>:(c<strong>on</strong>verse_iff)(r O s) −1 = s −1 O r −1 (c<strong>on</strong>verse_rel_comp)The image of a set under a relati<strong>on</strong> is defined analogously to image undera functi<strong>on</strong>:(b ∈ r ‘‘ A) = (∃ x∈A. (x,b) ∈ r) (Image_iff)It satisfies many similar laws.The domain and range of a relati<strong>on</strong> are defined in the standard way:(a ∈ Domain r) = (∃ y. (a,y) ∈ r) (Domain_iff)(a ∈ Range r) = (∃ y. (y,a) ∈ r) (Range_iff)Iterated compositi<strong>on</strong> of a relati<strong>on</strong> is available. The notati<strong>on</strong> overloads thatof exp<strong>on</strong>entiati<strong>on</strong>. Two simplificati<strong>on</strong> rules are installed:R ^ 0 = IdR ^ Suc n = R O R^n6.3.2 The Reflexive and Transitive ClosureThe reflexive and transitive closure of the relati<strong>on</strong> r is written with apostfix syntax. In ASCII we write r^* and in symbol notati<strong>on</strong> r ∗ . It is theleast soluti<strong>on</strong> of the equati<strong>on</strong>r ∗ = Id ∪ (r O r ∗ ) (rtrancl_unfold)Am<strong>on</strong>g its basic properties are three that serve as introducti<strong>on</strong> rules:(a, a) ∈ r ∗p ∈ r =⇒ p ∈ r ∗[[(a,b) ∈ r ∗ ; (b,c) ∈ r ∗ ]] =⇒ (a,c) ∈ r ∗(rtrancl_refl)(r_into_rtrancl)(rtrancl_trans)


Inducti<strong>on</strong> over the reflexive transitive closure is available:6.3 Relati<strong>on</strong>s 115[[(a, b) ∈ r ∗ ; P a; V y z. [[(a, y) ∈ r ∗ ; (y, z) ∈ r; P y]] =⇒ P z]]=⇒ P b (rtrancl_induct)Idempotence is <strong>on</strong>e of the laws proved about the reflexive transitive closure:(r ∗ ) ∗ = r ∗ (rtrancl_idemp)The transitive closure is similar. The ASCII syntax is r^+. It has twointroducti<strong>on</strong> rules:p ∈ r =⇒ p ∈ r +[[(a, b) ∈ r + ; (b, c) ∈ r + ]] =⇒ (a, c) ∈ r +(r_into_trancl)(trancl_trans)The inducti<strong>on</strong> rule resembles the <strong>on</strong>e shown above. A typical lemma statesthat transitive closure commutes with the c<strong>on</strong>verse operator:(r −1 ) + = (r + ) −1 (trancl_c<strong>on</strong>verse)6.3.3 A Sample ProofThe reflexive transitive closure also commutes with the c<strong>on</strong>verse operator. Letus examine the proof. Each directi<strong>on</strong> of the equivalence is proved separately.The two proofs are almost identical. Here is the first <strong>on</strong>e:lemma rtrancl_c<strong>on</strong>verseD: "(x,y) ∈ (r −1 ) ∗ =⇒ (y,x) ∈ r ∗ "apply (erule rtrancl_induct)apply (rule rtrancl_refl)apply (blast intro: rtrancl_trans)d<strong>on</strong>eThe first step of the proof applies inducti<strong>on</strong>, leaving these subgoals:1. (x, x) ∈ r ∗2. V y z. [[(x,y) ∈ (r −1 ) ∗ ; (y,z) ∈ r −1 ; (y,x) ∈ r ∗ ]]=⇒ (z,x) ∈ r ∗The first subgoal is trivial by reflexivity. The sec<strong>on</strong>d follows by first eliminatingthe c<strong>on</strong>verse operator, yielding the assumpti<strong>on</strong> (z,y) ∈ r, and thenapplying the introducti<strong>on</strong> rules shown above. The same proof script handlesthe other directi<strong>on</strong>:lemma rtrancl_c<strong>on</strong>verseI: "(y,x) ∈ r ∗ =⇒ (x,y) ∈ (r −1 ) ∗ "apply (erule rtrancl_induct)apply (rule rtrancl_refl)apply (blast intro: rtrancl_trans)d<strong>on</strong>eFinally, we combine the two lemmas to prove the desired equati<strong>on</strong>:lemma rtrancl_c<strong>on</strong>verse: "(r −1 ) ∗ = (r ∗ ) −1 "by (auto intro: rtrancl_c<strong>on</strong>verseI dest: rtrancl_c<strong>on</strong>verseD)


116 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>s!!This trivial proof requires auto rather than blast because of a subtle issueinvolving ordered pairs. Here is a subgoal that arises internally after the rulesequalityI and subsetI have been applied:1. V x. x ∈ (r −1 ) ∗ =⇒ x ∈ (r ∗ ) −1We cannot apply rtrancl_c<strong>on</strong>verseD. It refers to ordered pairs, while x is a variableof product type. The simp and blast methods can do nothing, so let us tryclarify:1. V a b. (a,b) ∈ (r −1 ) ∗ =⇒ (b,a) ∈ r ∗Now that x has been replaced by the pair (a,b), we can proceed. Other methodsthat split variables in this way are force, auto, fast and best. Secti<strong>on</strong> 8.1 willdiscuss proof techniques for ordered pairs in more detail.6.4 Well-Founded Relati<strong>on</strong>s and Inducti<strong>on</strong>A well-founded relati<strong>on</strong> captures the noti<strong>on</strong> of a terminating process. Complexrecursive functi<strong>on</strong>s definiti<strong>on</strong>s must specify a well-founded relati<strong>on</strong> thatjustifies their terminati<strong>on</strong> [19]. Most of the forms of inducti<strong>on</strong> found in mathematicsare merely special cases of inducti<strong>on</strong> over a well-founded relati<strong>on</strong>.Intuitively, the relati<strong>on</strong> ≺ is well-founded if it admits no infinite descendingchains· · · ≺ a 2 ≺ a 1 ≺ a 0 .Well-foundedness can be hard to show. The various formulati<strong>on</strong>s are all complicated.However, often a relati<strong>on</strong> is well-founded by c<strong>on</strong>structi<strong>on</strong>. <strong>HOL</strong> providestheorems c<strong>on</strong>cerning ways of c<strong>on</strong>structing a well-founded relati<strong>on</strong>. Themost familiar way is to specify a measure functi<strong>on</strong> f into the natural numbers,when x ≺ y ⇐⇒ f x < f y; we write this particular relati<strong>on</strong> asmeasure f.!!You may want to skip the rest of this secti<strong>on</strong> until you need to perform acomplex recursive functi<strong>on</strong> definiti<strong>on</strong> or inducti<strong>on</strong>. The inducti<strong>on</strong> rule returnedby fun is good enough for most purposes. We use an explicit well-founded inducti<strong>on</strong><strong>on</strong>ly in Sect. 9.2.4.<strong>Isabelle</strong>/<strong>HOL</strong> declares less_than as a relati<strong>on</strong> object, that is, a set ofpairs of natural numbers. Two theorems tell us that this relati<strong>on</strong> behaves asexpected and that it is well-founded:((x,y) ∈ less_than) = (x < y)wf less_than(less_than_iff)(wf_less_than)The noti<strong>on</strong> of measure generalizes to the inverse image of a relati<strong>on</strong>.Given a relati<strong>on</strong> r and a functi<strong>on</strong> f, we express a new relati<strong>on</strong> using f as ameasure. An infinite descending chain <strong>on</strong> this new relati<strong>on</strong> would give riseto an infinite descending chain <strong>on</strong> r. <strong>Isabelle</strong>/<strong>HOL</strong> defines this c<strong>on</strong>cept andproves a theorem stating that it preserves well-foundedness:


inv_image r f ≡ {(x,y). (f x, f y) ∈ r}wf r =⇒ wf (inv_image r f)6.5 Fixed Point Operators 117(inv_image_def)(wf_inv_image)A measure functi<strong>on</strong> involves the natural numbers. The relati<strong>on</strong> measuresize justifies primitive recursi<strong>on</strong> and structural inducti<strong>on</strong> over a datatype.<strong>Isabelle</strong>/<strong>HOL</strong> defines measure as shown:measure ≡ inv_image less_thanwf (measure f)(measure_def)(wf_measure)Of the other c<strong>on</strong>structi<strong>on</strong>s, the most important is the lexicographicproduct of two relati<strong>on</strong>s. It expresses the standard dicti<strong>on</strong>ary ordering overpairs. We write ra rb, where ra and rb are the two operands. Thelexicographic product satisfies the usual definiti<strong>on</strong> and it preserves wellfoundedness:ra rb ≡{((a,b),(a’,b’)). (a,a’) ∈ ra ∨a=a’ ∧ (b,b’) ∈ rb}[[wf ra; wf rb]] =⇒ wf (ra rb)(lex_prod_def)(wf_lex_prod)The multiset ordering, useful for hard terminati<strong>on</strong> proofs, is availablein the Library [4]. Baader and Nipkow [3, Sect. 2.5] discuss it.Inducti<strong>on</strong> comes in many forms, including traditi<strong>on</strong>al mathematical inducti<strong>on</strong>,structural inducti<strong>on</strong> <strong>on</strong> lists and inducti<strong>on</strong> <strong>on</strong> size. All are instancesof the following rule, for a suitable well-founded relati<strong>on</strong> ≺:[∀y. y ≺ x → P(y)].P(x)P(a)To show P(a) for a particular term a, it suffices to show P(x) for arbitraryx under the assumpti<strong>on</strong> that P(y) holds for y ≺ x. Intuitively, thewell-foundedness of ≺ ensures that the chains of reas<strong>on</strong>ing are finite.In <strong>Isabelle</strong>, the inducti<strong>on</strong> rule is expressed like this:[[wf r; V x. ∀ y. (y,x) ∈ r −→ P y =⇒ P x]] =⇒ P a(wf_induct)Here wf r expresses that the relati<strong>on</strong> r is well-founded.Many familiar inducti<strong>on</strong> principles are instances of this rule. For example,the predecessor relati<strong>on</strong> <strong>on</strong> the natural numbers is well-founded; inducti<strong>on</strong>over it is mathematical inducti<strong>on</strong>. The “tail of” relati<strong>on</strong> <strong>on</strong> lists is wellfounded;inducti<strong>on</strong> over it is structural inducti<strong>on</strong>.6.5 Fixed Point OperatorsFixed point operators define sets recursively. They are invoked implicitlywhen making an inductive definiti<strong>on</strong>, as discussed in Chap. 7 below. However,


118 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>sthey can be used directly, too. The least or str<strong>on</strong>gest fixed point yields aninductive definiti<strong>on</strong>; the greatest or weakest fixed point yields a coinductivedefiniti<strong>on</strong>. Mathematicians may wish to note that the existence of these fixedpoints is guaranteed by the Knaster-Tarski theorem.!!Casual readers should skip the rest of this secti<strong>on</strong>. We use fixed point operators<strong>on</strong>ly in Sect. 6.6.The theory applies <strong>on</strong>ly to m<strong>on</strong>ot<strong>on</strong>ic functi<strong>on</strong>s. <strong>Isabelle</strong>’s definiti<strong>on</strong> ofm<strong>on</strong>ot<strong>on</strong>e is overloaded over all orderings:m<strong>on</strong>o f ≡ ∀ A B. A ≤ B −→ f A ≤ f B(m<strong>on</strong>o_def)For fixed point operators, the ordering will be the subset relati<strong>on</strong>: if A ⊆ Bthen we expect f (A) ⊆ f (B). In additi<strong>on</strong> to its definiti<strong>on</strong>, m<strong>on</strong>ot<strong>on</strong>icity hasthe obvious introducti<strong>on</strong> and destructi<strong>on</strong> rules:( V A B. A ≤ B =⇒ f A ≤ f B) =⇒ m<strong>on</strong>o f (m<strong>on</strong>oI)[[m<strong>on</strong>o f; A ≤ B]] =⇒ f A ≤ f B(m<strong>on</strong>oD)The most important properties of the least fixed point are that it is afixed point and that it enjoys an inducti<strong>on</strong> rule:m<strong>on</strong>o f =⇒ lfp f = f (lfp f)[[a V ∈ lfp f; m<strong>on</strong>o f;x. x ∈ f (lfp f ∩ {x. P x}) =⇒ P x]] =⇒ P a(lfp_unfold)(lfp_induct)The inducti<strong>on</strong> rule shown above is more c<strong>on</strong>venient than the basic <strong>on</strong>e derivedfrom the minimality of lfp. Observe that both theorems demand m<strong>on</strong>o f asa premise.The greatest fixed point is similar, but it has a coinducti<strong>on</strong> rule:m<strong>on</strong>o f =⇒ gfp f = f (gfp f)[[m<strong>on</strong>o f; a ∈ X; X ⊆ f (X ∪ gfp f)]] =⇒ a ∈ gfp f(gfp_unfold)(coinduct)A bisimulati<strong>on</strong> is perhaps the best-known c<strong>on</strong>cept defined as a greatestfixed point. Exhibiting a bisimulati<strong>on</strong> to prove the equality of two agents ina process algebra is an example of coinducti<strong>on</strong>. The coinducti<strong>on</strong> rule can bestrengthened in various ways.6.6 Case Study: Verified Model CheckingThis chapter ends with a case study c<strong>on</strong>cerning model checking for Computati<strong>on</strong>Tree Logic (CTL), a temporal logic. Model checking is a populartechnique for the verificati<strong>on</strong> of finite state systems (implementati<strong>on</strong>s) withrespect to temporal logic formulae (specificati<strong>on</strong>s) [8, 17]. Its foundati<strong>on</strong>s areset theoretic and this secti<strong>on</strong> will explore them in <strong>HOL</strong>. This is d<strong>on</strong>e in twosteps. First we c<strong>on</strong>sider a simple modal logic called propositi<strong>on</strong>al dynamiclogic (PDL). We then proceed to the temporal logic CTL, which is used in


6.6 Case Study: Verified Model Checking 119many real model checkers. In each case we give both a traditi<strong>on</strong>al semantics(|=) and a recursive functi<strong>on</strong> mc that maps a formula into the set of all statesof the system where the formula is valid. If the system has a finite numberof states, mc is directly executable: it is a model checker, albeit an inefficient<strong>on</strong>e. The main proof obligati<strong>on</strong> is to show that the semantics and the modelchecker agree.Our models are transiti<strong>on</strong> systems: sets of states with transiti<strong>on</strong>s betweenthem. Here is a simple example:✛✘p, q s 0s 1✚✙ ✒ ❅❅✛✘✠ ❅❅❘ ✛✘ s 2✛q, r✲ r✚✙✚✙Each state has a unique name or number (s 0 , s 1 , s 2 ), and in each state certainatomic propositi<strong>on</strong>s (p, q, r) hold. The aim of temporal logic is to formalizestatements such as “there is no path starting from s 2 leading to a statewhere p or q holds,” which is true, and “<strong>on</strong> all paths starting from s 0 , qalways holds,” which is false.Abstracting from this c<strong>on</strong>crete example, we assume there is a type ofstates:typedecl stateCommand typedecl merely declares a new type but without defining it (seeSect. 8.5.1). Thus we know nothing about the type other than its existence.That is exactly what we need because state really is an implicit parameterof our model. Of course it would have been more generic to make state atype parameter of everything but declaring state globally as above reducesclutter. Similarly we declare an arbitrary but fixed transiti<strong>on</strong> system, i.e. arelati<strong>on</strong> between states:c<strong>on</strong>sts M :: "(state × state)set"This is <strong>Isabelle</strong>’s way of declaring a c<strong>on</strong>stant without defining it. Finally weintroduce a type of atomic propositi<strong>on</strong>stypedecl "atom"and a labelling functi<strong>on</strong>c<strong>on</strong>sts L :: "state ⇒ atom set"telling us which atomic propositi<strong>on</strong>s are true in each state.


120 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>s6.6.1 Propositi<strong>on</strong>al Dynamic Logic — PDLThe formulae of PDL are built up from atomic propositi<strong>on</strong>s via negati<strong>on</strong> andc<strong>on</strong>juncti<strong>on</strong> and the two temporal c<strong>on</strong>nectives AX and EF. Since formulae areessentially syntax trees, they are naturally modelled as a datatype: 1datatype formula = Atom "atom"| Neg formula| And formula formula| AX formula| EF formulaThis resembles the boolean expressi<strong>on</strong> case study in Sect. 2.5.6. A validityrelati<strong>on</strong> between states and formulae specifies the semantics. The syntax annotati<strong>on</strong>allows us to write s |= f instead of valid s f. The definiti<strong>on</strong> is byrecursi<strong>on</strong> over the syntax:primrec valid :: "state ⇒ formula ⇒ bool" ("(_ |= _)" [80,80] 80)where"s |= Atom a = (a ∈ L s)" |"s |= Neg f = (¬(s |= f))" |"s |= And f g = (s |= f ∧ s |= g)" |"s |= AX f = (∀ t. (s,t) ∈ M −→ t |= f)" |"s |= EF f = (∃ t. (s,t) ∈ M ∗ ∧ t |= f)"The first three equati<strong>on</strong>s should be self-explanatory. The temporal formulaAX f means that f is true in All neX t states whereas EF f means that thereExists some F uture state in which f is true. The future is expressed via ∗ ,the reflexive transitive closure. Because of reflexivity, the future includes thepresent.Now we come to the model checker itself. It maps a formula into the setof states where the formula is true. It too is defined by recursi<strong>on</strong> over thesyntax:primrec mc :: "formula ⇒ state set" where"mc(Atom a) = {s. a ∈ L s}" |"mc(Neg f) = -mc f" |"mc(And f g) = mc f ∩ mc g" |"mc(AX f) = {s. ∀ t. (s,t) ∈ M −→ t ∈ mc f}" |"mc(EF f) = lfp(λT. mc f ∪ (M −1 ‘‘ T))"Only the equati<strong>on</strong> for EF deserves some comments. Remember that the postfix−1and the infix ‘‘ are predefined and denote the c<strong>on</strong>verse of a relati<strong>on</strong> andthe image of a set under a relati<strong>on</strong>. Thus M −1 ‘‘ T is the set of all predecessorsof T and the least fixed point (lfp) of λT. mc f ∪ M −1 ‘‘ T is the least setT c<strong>on</strong>taining mc f and all predecessors of T. If you find it hard to see thatmc (EF f) c<strong>on</strong>tains exactly those states from which there is a path to a statewhere f is true, do not worry — this will be proved in a moment.1 The customary definiti<strong>on</strong> of PDL [14] looks quite different from ours, but thetwo are easily shown to be equivalent.


6.6 Case Study: Verified Model Checking 121First we prove m<strong>on</strong>ot<strong>on</strong>icity of the functi<strong>on</strong> inside lfp in order to makesure it really has a least fixed point.lemma m<strong>on</strong>o_ef: "m<strong>on</strong>o(λT. A ∪ (M −1 ‘‘ T))"apply(rule m<strong>on</strong>oI)apply blastd<strong>on</strong>eNow we can relate model checking and semantics. For the EF case we need aseparate lemma:lemma EF_lemma:"lfp(λT. A ∪ (M −1 ‘‘ T)) = {s. ∃ t. (s,t) ∈ M ∗ ∧ t ∈ A}"The equality is proved in the can<strong>on</strong>ical fashi<strong>on</strong> by proving that each setincludes the other; the inclusi<strong>on</strong> is shown pointwise:apply(rule equalityI)apply(rule subsetI)apply(simp)Simplificati<strong>on</strong> leaves us with the following first subgoal1. V s. s ∈ lfp (λT. A ∪ M −1 ‘‘ T) =⇒ ∃ t. (s, t) ∈ M ∗ ∧ t ∈ Awhich is proved by lfp-inducti<strong>on</strong>:apply(erule lfp_induct_set)apply(rule m<strong>on</strong>o_ef)apply(simp)Having disposed of the m<strong>on</strong>ot<strong>on</strong>icity subgoal, simplificati<strong>on</strong> leaves us withthe following goal:1. V x. x ∈ A ∨x ∈ M −1 ‘‘ (lfp (...) ∩ {x. ∃ t. (x, t) ∈ M ∗ ∧ t ∈ A})=⇒ ∃ t. (x, t) ∈ M ∗ ∧ t ∈ AIt is proved by blast, using the transitivity of M ∗ .apply(blast intro: rtrancl_trans)We now return to the sec<strong>on</strong>d set inclusi<strong>on</strong> subgoal, which is again provedpointwise:apply(rule subsetI)apply(simp, clarify)After simplificati<strong>on</strong> and clarificati<strong>on</strong> we are left with1. V x t. [[(x, t) ∈ M ∗ ; t ∈ A]] =⇒ x ∈ lfp (λT. A ∪ M −1 ‘‘ T)This goal is proved by inducti<strong>on</strong> <strong>on</strong> (s, t) ∈ M ∗ . But since the modelchecker works backwards (from t to s), we cannot use the inducti<strong>on</strong> theoremrtrancl_induct: it works in the forward directi<strong>on</strong>. Fortunately the c<strong>on</strong>verseinducti<strong>on</strong> theorem c<strong>on</strong>verse_rtrancl_induct already exists:


122 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>s[[(a, b) ∈ r ∗ ; P b;V y z. [[(y, z) ∈ r; (z, b) ∈ r ∗ ; P z]] =⇒ P y]]=⇒ P aIt says that if (a, b) ∈ r ∗ and we know P b then we can infer P a providedeach step backwards from a predecessor z of b preserves P.apply(erule c<strong>on</strong>verse_rtrancl_induct)The base case1. V x t. t ∈ A =⇒ t ∈ lfp (λT. A ∪ M −1 ‘‘ T)is solved by unrolling lfp <strong>on</strong>ceapply(subst lfp_unfold[OF m<strong>on</strong>o_ef])1. V x t. t ∈ A =⇒ t ∈ A ∪ M −1 ‘‘ lfp (λT. A ∪ M −1 ‘‘ T)and disposing of the resulting trivial subgoal automatically:apply(blast)The proof of the inducti<strong>on</strong> step is identical to the <strong>on</strong>e for the base case:apply(subst lfp_unfold[OF m<strong>on</strong>o_ef])apply(blast)d<strong>on</strong>eThe main theorem is proved in the familiar manner: inducti<strong>on</strong> followedby auto augmented with the lemma as a simplificati<strong>on</strong> rule.theorem "mc f = {s. s |= f}"apply(induct_tac f)apply(auto simp add: EF_lemma)d<strong>on</strong>eExercise 6.6.1 AX has a dual operator EN (“there exists a next state suchthat”) 2 with the intended semanticss |= EN f = (∃ t. (s, t) ∈ M ∧ t |= f)Fortunately, EN f can already be expressed as a PDL formula. How?Show that the semantics for EF satisfies the following recursi<strong>on</strong> equati<strong>on</strong>:s |= EF f = (s |= f ∨ s |= EN (EF f))2 We cannot use the customary EX: it is reserved as the ascii-equivalent of ∃ .


6.6.2 Computati<strong>on</strong> Tree Logic — CTL6.6 Case Study: Verified Model Checking 123The semantics of PDL <strong>on</strong>ly needs reflexive transitive closure. Let us be adventurousand introduce a more expressive temporal operator. We extend thedatatype formula by a new c<strong>on</strong>structor| AF formulawhich stands for “Always in the F uture”: <strong>on</strong> all infinite paths, at some pointthe formula holds. Formalizing the noti<strong>on</strong> of an infinite path is easy in <strong>HOL</strong>:it is simply a functi<strong>on</strong> from nat to state.definiti<strong>on</strong> Paths :: "state ⇒ (nat ⇒ state)set" where"Paths s ≡ {p. s = p 0 ∧ (∀ i. (p i, p(i+1)) ∈ M)}"This definiti<strong>on</strong> allows a succinct statement of the semantics of AF: 3"s |= AF f = (∀ p ∈ Paths s. ∃ i. p i |= f)"Model checking AF involves a functi<strong>on</strong> which is just complicated enough towarrant a separate definiti<strong>on</strong>:definiti<strong>on</strong> af :: "state set ⇒ state set ⇒ state set" where"af A T ≡ A ∪ {s. ∀ t. (s, t) ∈ M −→ t ∈ T}"Now we define mc (AF f) as the least set T that includes mc f and all statesall of whose direct successors are in T:"mc(AF f) = lfp(af(mc f))"Because af is m<strong>on</strong>ot<strong>on</strong>e in its sec<strong>on</strong>d argument (and also its first, but thatis irrelevant), af A has a least fixed point:lemma m<strong>on</strong>o_af: "m<strong>on</strong>o(af A)"apply(simp add: m<strong>on</strong>o_def af_def)apply blastd<strong>on</strong>eAll we need to prove now is mc (AF f) = {s. s |= AF f}, which statesthat mc and |= agree for AF. This time we prove the two inclusi<strong>on</strong>s separately,starting with the easy <strong>on</strong>e:theorem AF_lemma1: "lfp(af A) ⊆ {s. ∀ p ∈ Paths s. ∃ i. p i ∈ A}"In c<strong>on</strong>trast to the analogous proof for EF, and just for a change, we do notuse fixed point inducti<strong>on</strong>. Park-inducti<strong>on</strong>, named after David Park, is weakerbut sufficient for this proof:f S ≤ S =⇒ lfp f ≤ S(lfp_lowerbound)The instance of the premise f S ⊆ S is proved pointwise, a decisi<strong>on</strong> that autotakes for us:apply(rule lfp_lowerbound)apply(auto simp add: af_def Paths_def)3 Do not be misled: neither datatypes nor recursive functi<strong>on</strong>s can be extendedby new c<strong>on</strong>structors or equati<strong>on</strong>s. This is just a trick of the presentati<strong>on</strong> (seeSect. 4.2.5). In reality <strong>on</strong>e has to define a new datatype and a new functi<strong>on</strong>.


124 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>s1. V p. [[∀ t. (p 0, t) ∈ M −→(∀ p. t = p 0 ∧ (∀ i. (p i, p (Suc i)) ∈ M) −→(∃ i. p i ∈ A));∀ i. (p i, p (Suc i)) ∈ M]]=⇒ ∃ i. p i ∈ AIn this remaining case, we set t to p 1. The rest is automatic, which issurprising because it involves finding the instantiati<strong>on</strong> λi. p (i + 1) for ∀ p.apply(erule_tac x = "p 1" in allE)apply(auto)d<strong>on</strong>eThe opposite inclusi<strong>on</strong> is proved by c<strong>on</strong>tradicti<strong>on</strong>: if some state s is not inlfp (af A), then we can c<strong>on</strong>struct an infinite A-avoiding path starting from s.The reas<strong>on</strong> is that by unfolding lfp we find that if s is not in lfp (af A),then s is not in A and there is a direct successor of s that is again not inlfp (af A). Iterating this argument yields the promised infinite A-avoidingpath. Let us formalize this sketch.The <strong>on</strong>e-step argument in the sketch above is proved by a variant ofc<strong>on</strong>trapositi<strong>on</strong>:lemma not_in_lfp_afD:"s /∈ lfp(af A) =⇒ s /∈ A ∧ (∃ t. (s,t) ∈ M ∧ t /∈ lfp(af A))"apply(erule c<strong>on</strong>trapos_np)apply(subst lfp_unfold[OF m<strong>on</strong>o_af])apply(simp add: af_def)d<strong>on</strong>eWe assume the negati<strong>on</strong> of the c<strong>on</strong>clusi<strong>on</strong> and prove s ∈ lfp (af A). Unfoldinglfp <strong>on</strong>ce and simplifying with the definiti<strong>on</strong> of af finishes the proof.Now we iterate this process. The following c<strong>on</strong>structi<strong>on</strong> of the desiredpath is parameterized by a predicate Q that should hold al<strong>on</strong>g the path:primrec path :: "state ⇒ (state ⇒ bool) ⇒ (nat ⇒ state)" where"path s Q 0 = s" |"path s Q (Suc n) = (SOME t. (path s Q n,t) ∈ M ∧ Q t)"Element n + 1 <strong>on</strong> this path is some arbitrary successor t of element n suchthat Q t holds. Remember that SOME t. R t is some arbitrary but fixed tsuch that R t holds (see Sect. 5.10). Of course, such a t need not exist, butthat is of no c<strong>on</strong>cern to us since we will <strong>on</strong>ly use path when a suitable t doesexist.Let us show that if each state s that satisfies Q has a successor that againsatisfies Q, then there exists an infinite Q-path:lemma infinity_lemma:"[[ Q s; ∀ s. Q s −→ (∃ t. (s,t) ∈ M ∧ Q t) ]] =⇒∃ p∈Paths s. ∀ i. Q(p i)"First we rephrase the c<strong>on</strong>clusi<strong>on</strong> slightly because we need to prove simultaneouslyboth the path property and the fact that Q holds:


6.6 Case Study: Verified Model Checking 125apply(subgoal_tac"∃ p. s = p 0 ∧ (∀ i::nat. (p i, p(i+1)) ∈ M ∧ Q(p i))")From this propositi<strong>on</strong> the original goal follows easily:apply(simp add: Paths_def, blast)The new subgoal is proved by providing the witness path s Q for p:apply(rule_tac x = "path s Q" in exI)apply(clarsimp)After simplificati<strong>on</strong> and clarificati<strong>on</strong>, the subgoal has the following form:1. V i. [[Q s; ∀ s. Q s −→ (∃ t. (s, t) ∈ M ∧ Q t)]]=⇒ (path s Q i, SOME t. (path s Q i, t) ∈ M ∧ Q t) ∈ M ∧Q (path s Q i)It invites a proof by inducti<strong>on</strong> <strong>on</strong> i:apply(induct_tac i)apply(simp)After simplificati<strong>on</strong>, the base case boils down to1. [[Q s; ∀ s. Q s −→ (∃ t. (s, t) ∈ M ∧ Q t)]]=⇒ (s, SOME t. (s, t) ∈ M ∧ Q t) ∈ MThe c<strong>on</strong>clusi<strong>on</strong> looks exceedingly trivial: after all, t is chosen such that (s,t) ∈ M holds. However, we first have to show that such a t actually exists!This reas<strong>on</strong>ing is embodied in the theorem someI2_ex:[[∃ a. ?P a; V x. ?P x =⇒ ?Q x]] =⇒ ?Q (SOME x. ?P x)When we apply this theorem as an introducti<strong>on</strong> rule, ?P x becomes (s, x) ∈M ∧ Q x and ?Q x becomes (s, x) ∈ M and we have to prove two subgoals:∃ a. (s, a) ∈ M ∧ Q a, which follows from the assumpti<strong>on</strong>s, and (s, x) ∈M ∧ Q x =⇒ (s, x) ∈ M, which is trivial. Thus it is not surprising that fastcan prove the base case quickly:apply(fast intro: someI2_ex)What is worth noting here is that we have used fast rather than blast. Thereas<strong>on</strong> is that blast would fail because it cannot cope with someI2_ex: unifyingits c<strong>on</strong>clusi<strong>on</strong> with the current subgoal is n<strong>on</strong>-trivial because of the nestedschematic variables. For efficiency reas<strong>on</strong>s blast does not even attempt suchunificati<strong>on</strong>s. Although fast can in principle cope with complicated unificati<strong>on</strong>problems, in practice the number of unifiers arising is often prohibitiveand the offending rule may need to be applied explicitly rather than automatically.This is what happens in the step case.The inducti<strong>on</strong> step is similar, but more involved, because now we facenested occurrences of SOME. As a result, fast is no l<strong>on</strong>ger able to solve thesubgoal and we apply someI2_ex by hand. We merely show the proof commandsbut do not describe the details:apply(simp)


126 6. Sets, Functi<strong>on</strong>s and Relati<strong>on</strong>sapply(rule someI2_ex)apply(blast)apply(rule someI2_ex)apply(blast)apply(blast)d<strong>on</strong>eFuncti<strong>on</strong> path has fulfilled its purpose now and can be forgotten. It wasmerely defined to provide the witness in the proof of the infinity_lemma.Afici<strong>on</strong>ados of minimal proofs might like to know that we could have giventhe witness without having to define a new functi<strong>on</strong>: the termnat_rec s (λn t. SOME u. (t, u) ∈ M ∧ Q u)is extensi<strong>on</strong>ally equal to path s Q, where nat_rec is the predefined primitiverecursor <strong>on</strong> nat.At last we can prove the opposite directi<strong>on</strong> of AF_lemma1:theorem AF_lemma2: "{s. ∀ p ∈ Paths s. ∃ i. p i ∈ A} ⊆ lfp(af A)"The proof is again pointwise and then by c<strong>on</strong>trapositi<strong>on</strong>:apply(rule subsetI)apply(erule c<strong>on</strong>trapos_pp)apply simp1. V x. x /∈ lfp (af A) =⇒ ∃ p∈Paths x. ∀ i. p i /∈ AApplying the infinity_lemma as a destructi<strong>on</strong> rule leaves two subgoals, thesec<strong>on</strong>d premise of infinity_lemma and the original subgoal:apply(drule infinity_lemma)1. V x. ∀ s. s /∈ lfp (af A) −→ (∃ t. (s, t) ∈ M ∧ t /∈ lfp (af A))2. V x. ∃ p∈Paths x. ∀ i. p i /∈ lfp (af A) =⇒∃ p∈Paths x. ∀ i. p i /∈ ABoth are solved automatically:apply(auto dest: not_in_lfp_afD)d<strong>on</strong>eIf you find these proofs too complicated, we recommend that you readSect. 9.2.4, where we show how inductive definiti<strong>on</strong>s lead to simpler arguments.The main theorem is proved as for PDL, except that we also derive thenecessary equality lfp(af A) = ... by combining AF_lemma1 and AF_lemma2<strong>on</strong> the spot:theorem "mc f = {s. s |= f}"apply(induct_tac f)apply(auto simp add: EF_lemma equalityI[OF AF_lemma1 AF_lemma2])d<strong>on</strong>e


6.6 Case Study: Verified Model Checking 127The language defined above is not quite CTL. The latter also includes anuntil-operator EU f g with semantics “there Exists a path where f is trueU ntil g becomes true”. We need an auxiliary functi<strong>on</strong>:primrecuntil:: "state set ⇒ state set ⇒ state ⇒ state list ⇒ bool" where"until A B s [] = (s ∈ B)" |"until A B s (t#p) = (s ∈ A ∧ (s,t) ∈ M ∧ until A B t p)"Expressing the semantics of EU is now straightforward:s |= EU f g = (∃ p. until {t. t |= f} {t. t |= g} s p)Note that EU is not definable in terms of the other operators!Model checking EU is again a least fixed point c<strong>on</strong>structi<strong>on</strong>:mc(EU f g) = lfp(λT. mc g ∪ mc f ∩ (M −1‘‘ T))Exercise 6.6.2 Extend the datatype of formulae by the above until operatorand prove the equivalence between semantics and model checking, i.e. thatmc (EU f g) = {s. s |= EU f g}For more CTL exercises see, for example, Huth and Ryan [17].Let us close this secti<strong>on</strong> with a few words about the executability of ourmodel checkers. It is clear that if all sets are finite, they can be represented aslists and the usual set operati<strong>on</strong>s are easily implemented. Only lfp requiresa little thought. Fortunately, theory While_Combinator in the Library [4] providesa theorem stating that in the case of finite sets and a m<strong>on</strong>ot<strong>on</strong>e functi<strong>on</strong>F, the value of lfp F can be computed by iterated applicati<strong>on</strong> of F to {}until a fixed point is reached. It is actually possible to generate executablefuncti<strong>on</strong>al programs from <strong>HOL</strong> definiti<strong>on</strong>s, but that is bey<strong>on</strong>d the scope ofthe tutorial.


7. Inductively Defined SetsThis chapter is dedicated to the most important definiti<strong>on</strong> principle afterrecursive functi<strong>on</strong>s and datatypes: inductively defined sets.We start with a simple example: the set of even numbers. A slightlymore complicated example, the reflexive transitive closure, is the subjectof Sect. 7.2. In particular, some standard inducti<strong>on</strong> heuristics are discussed.Advanced forms of inductive definiti<strong>on</strong>s are discussed in Sect. 7.3. To dem<strong>on</strong>stratethe versatility of inductive definiti<strong>on</strong>s, the chapter closes with a casestudy from the realm of c<strong>on</strong>text-free grammars. The first two secti<strong>on</strong>s arerequired reading for anybody interested in mathematical modelling.Predicates can also be defined inductively. See Sect. 7.1.7.!!7.1 The Set of Even NumbersThe set of even numbers can be inductively defined as the least set c<strong>on</strong>taining0 and closed under the operati<strong>on</strong> +2. Obviously, even can also be expressedusing the divides relati<strong>on</strong> (dvd). We shall prove below that the two formulati<strong>on</strong>scoincide. On the way we shall examine the primary means of reas<strong>on</strong>ingabout inductively defined sets: rule inducti<strong>on</strong>.7.1.1 Making an Inductive Definiti<strong>on</strong>Using inductive set, we declare the c<strong>on</strong>stant even to be a set of naturalnumbers with the desired properties.inductive set even :: "nat set" wherezero[intro!]: "0 ∈ even" |step[intro!]: "n ∈ even =⇒ (Suc (Suc n)) ∈ even"An inductive definiti<strong>on</strong> c<strong>on</strong>sists of introducti<strong>on</strong> rules. The first <strong>on</strong>e abovestates that 0 is even; the sec<strong>on</strong>d states that if n is even, then so is n +2. Giventhis declarati<strong>on</strong>, <strong>Isabelle</strong> generates a fixed point definiti<strong>on</strong> for even and provestheorems about it, thus following the definiti<strong>on</strong>al approach (see Sect. 2.8).These theorems include the introducti<strong>on</strong> rules specified in the declarati<strong>on</strong>,


130 7. Inductively Defined Setsan eliminati<strong>on</strong> rule for case analysis and an inducti<strong>on</strong> rule. We can refer tothese theorems by automatically-generated names. Here are two examples:0 ∈ even (even.zero)n ∈ even =⇒ Suc (Suc n) ∈ even(even.step)The introducti<strong>on</strong> rules can be given attributes. Here both rules are specifiedas intro!, directing the classical reas<strong>on</strong>er to apply them aggressively.Obviously, regarding 0 as even is safe. The step rule is also safe becausen + 2 is even if and <strong>on</strong>ly if n is even. We prove this equivalence later.7.1.2 Using Introducti<strong>on</strong> RulesOur first lemma states that numbers of the form 2 × k are even. Introducti<strong>on</strong>rules are used to show that specific values bel<strong>on</strong>g to the inductive set. Suchproofs typically involve inducti<strong>on</strong>, perhaps over some other inductive set.lemma two_times_even[intro!]: "2*k ∈ even"apply (induct_tac k)apply autod<strong>on</strong>eThe first step is inducti<strong>on</strong> <strong>on</strong> the natural number k, which leaves two subgoals:1. 2 * 0 ∈ even2. V n. 2 * n ∈ even =⇒ 2 * Suc n ∈ evenHere auto simplifies both subgoals so that they match the introducti<strong>on</strong> rules,which are then applied automatically.Our ultimate goal is to prove the equivalence between the traditi<strong>on</strong>aldefiniti<strong>on</strong> of even (using the divides relati<strong>on</strong>) and our inductive definiti<strong>on</strong>.One directi<strong>on</strong> of this equivalence is immediate by the lemma just proved,whose intro! attribute ensures it is applied automatically.lemma dvd_imp_even: "2 dvd n =⇒ n ∈ even"by (auto simp add: dvd_def)7.1.3 Rule Inducti<strong>on</strong>From the definiti<strong>on</strong> of the set even, <strong>Isabelle</strong> has generated an inducti<strong>on</strong> rule:[[x ∈ even; P 0;V n. [[n ∈ even; P n]] =⇒ P (Suc (Suc n))]]=⇒ P x (even.induct)A property P holds for every even number provided it holds for 0 and is closedunder the operati<strong>on</strong> Suc(Suc ·). Then P is closed under the introducti<strong>on</strong> rulesfor even, which is the least set closed under those rules. This type of inductiveargument is called rule inducti<strong>on</strong>.Apart from the double applicati<strong>on</strong> of Suc, the inducti<strong>on</strong> rule above resemblesthe familiar mathematical inducti<strong>on</strong>, which indeed is an instance of rule


7.1 The Set of Even Numbers 131inducti<strong>on</strong>; the natural numbers can be defined inductively to be the least setc<strong>on</strong>taining 0 and closed under Suc.Inducti<strong>on</strong> is the usual way of proving a property of the elements of aninductively defined set. Let us prove that all members of the set even aremultiples of two.lemma even_imp_dvd: "n ∈ even =⇒ 2 dvd n"We begin by applying inducti<strong>on</strong>. Note that even.induct has the form ofan eliminati<strong>on</strong> rule, so we use the method erule. We get two subgoals:apply (erule even.induct)1. 2 dvd 02. V n. [[n ∈ even; 2 dvd n]] =⇒ 2 dvd Suc (Suc n)We unfold the definiti<strong>on</strong> of dvd in both subgoals, proving the first <strong>on</strong>e andsimplifying the sec<strong>on</strong>d:apply (simp_all add: dvd_def)1. V n. [[n ∈ even; ∃ k. n = 2 * k]] =⇒ ∃ k. Suc (Suc n) = 2 * kThe next command eliminates the existential quantifier from the assumpti<strong>on</strong>and replaces n by 2 * k.apply clarify1. V n k. 2 * k ∈ even =⇒ ∃ ka. Suc (Suc (2 * k)) = 2 * kaTo c<strong>on</strong>clude, we tell <strong>Isabelle</strong> that the desired value is Suc k. With this hint,the subgoal falls to simp.apply (rule_tac x = "Suc k" in exI, simp)Combining the previous two results yields our objective, the equivalencerelating even and dvd.theorem even_iff_dvd: "(n ∈ even) = (2 dvd n)"by (blast intro: dvd_imp_even even_imp_dvd)7.1.4 Generalizati<strong>on</strong> and Rule Inducti<strong>on</strong>Before applying inducti<strong>on</strong>, we typically must generalize the inducti<strong>on</strong> formula.With rule inducti<strong>on</strong>, the required generalizati<strong>on</strong> can be hard to findand sometimes requires a complete reformulati<strong>on</strong> of the problem. In this example,our first attempt uses the obvious statement of the result. It fails:lemma "Suc (Suc n) ∈ even =⇒ n ∈ even"apply (erule even.induct)oopsRule inducti<strong>on</strong> finds no occurrences of Suc (Suc n) in the c<strong>on</strong>clusi<strong>on</strong>,which it therefore leaves unchanged. (Look at even.induct to see why thishappens.) We have these subgoals:


132 7. Inductively Defined Sets1. n ∈ even2. V na. [[na ∈ even; n ∈ even]] =⇒ n ∈ evenThe first <strong>on</strong>e is hopeless. Rule inducti<strong>on</strong> <strong>on</strong> a n<strong>on</strong>-variable term discardsinformati<strong>on</strong>, and usually fails. How to deal with such situati<strong>on</strong>s in general isdescribed in Sect. 9.2.1 below. In the current case the soluti<strong>on</strong> is easy becausewe have the necessary inverse, subtracti<strong>on</strong>:lemma even_imp_even_minus_2: "n ∈ even =⇒ n - 2 ∈ even"apply (erule even.induct)apply autod<strong>on</strong>eThis lemma is trivially inductive. Here are the subgoals:1. 0 - 2 ∈ even2. V n. [[n ∈ even; n - 2 ∈ even]] =⇒ Suc (Suc n) - 2 ∈ evenThe first is trivial because 0 - 2 simplifies to 0, which is even. The sec<strong>on</strong>d istrivial too: Suc (Suc n) - 2 simplifies to n, matching the assumpti<strong>on</strong>.Using our lemma, we can easily prove the result we originally wanted:lemma Suc_Suc_even_imp_even: "Suc (Suc n) ∈ even =⇒ n ∈ even"by (drule even_imp_even_minus_2, simp)We have just proved the c<strong>on</strong>verse of the introducti<strong>on</strong> rule even.step. Thissuggests proving the following equivalence. We give it the iff attribute becauseof its obvious value for simplificati<strong>on</strong>.lemma [iff]: "((Suc (Suc n)) ∈ even) = (n ∈ even)"by (blast dest: Suc_Suc_even_imp_even)7.1.5 Rule Inversi<strong>on</strong>Case analysis <strong>on</strong> an inductive definiti<strong>on</strong> is called rule inversi<strong>on</strong>. It is frequentlyused in proofs about operati<strong>on</strong>al semantics. It can be highly effectivewhen it is applied automatically. Let us look at how rule inversi<strong>on</strong> is d<strong>on</strong>e in<strong>Isabelle</strong>/<strong>HOL</strong>.Recall that even is the minimal set closed under these two rules:0 ∈ evenn ∈ even =⇒ Suc (Suc n) ∈ evenMinimality means that even c<strong>on</strong>tains <strong>on</strong>ly the elements that these rules forceit to c<strong>on</strong>tain. If we are told that a bel<strong>on</strong>gs to even then there are <strong>on</strong>ly twopossibilities. Either a is 0 or else a has the form Suc (Suc n), for some suitablen that bel<strong>on</strong>gs to even. That is the gist of the cases rule, which <strong>Isabelle</strong> provesfor us when it accepts an inductive definiti<strong>on</strong>:[[a ∈ even; a = 0 =⇒ P;V n. [[a = Suc (Suc n); n ∈ even]] =⇒ P]]=⇒ P (even.cases)


7.1 The Set of Even Numbers 133This general rule is less useful than instances of it for specific patterns. Forexample, if a has the form Suc (Suc n) then the first case becomes irrelevant,while the sec<strong>on</strong>d case tells us that n bel<strong>on</strong>gs to even. <strong>Isabelle</strong> will generatethis instance for us:inductive cases Suc_Suc_cases [elim!]: "Suc(Suc n) ∈ even"The inductive cases command generates an instance of the cases rulefor the supplied pattern and gives it the supplied name:[[Suc (Suc n) ∈ even; n ∈ even =⇒ P]] =⇒ P(Suc_Suc_cases)Applying this as an eliminati<strong>on</strong> rule yields <strong>on</strong>e case where even.cases wouldyield two. Rule inversi<strong>on</strong> works well when the c<strong>on</strong>clusi<strong>on</strong>s of the introducti<strong>on</strong>rules involve datatype c<strong>on</strong>structors like Suc and # (list “c<strong>on</strong>s”); freenessreas<strong>on</strong>ing discards all but <strong>on</strong>e or two cases.In the inductive cases command we supplied an attribute, elim!, indicatingthat this eliminati<strong>on</strong> rule can be applied aggressively. The originalcases rule would loop if used in that manner because the pattern a matcheseverything.The rule Suc_Suc_cases is equivalent to the following implicati<strong>on</strong>:Suc (Suc n) ∈ even =⇒ n ∈ evenJust above we devoted some effort to reaching precisely this result. Yet wecould have obtained it by a <strong>on</strong>e-line declarati<strong>on</strong>, dispensing with the lemmaeven_imp_even_minus_2. This example also justifies the terminology rule inversi<strong>on</strong>:the new rule inverts the introducti<strong>on</strong> rule even.step. In general, arule can be inverted when the set of elements it introduces is disjoint fromthose of the other introducti<strong>on</strong> rules.For <strong>on</strong>e-off applicati<strong>on</strong>s of rule inversi<strong>on</strong>, use the ind_cases method. Hereis an example:apply (ind_cases "Suc(Suc n) ∈ even")The specified instance of the cases rule is generated, then applied as aneliminati<strong>on</strong> rule.To summarize, every inductive definiti<strong>on</strong> produces a cases rule. The inductivecases command stores an instance of the cases rule for a givenpattern. Within a proof, the ind_cases method applies an instance of thecases rule.The even numbers example has shown how inductive definiti<strong>on</strong>s can beused. Later examples will show that they are actually worth using.7.1.6 Mutually Inductive Definiti<strong>on</strong>sJust as there are datatypes defined by mutual recursi<strong>on</strong>, there are sets definedby mutual inducti<strong>on</strong>. As a trivial example we c<strong>on</strong>sider the even and oddnatural numbers:


134 7. Inductively Defined Setsinductive setEven :: "nat set" andOdd :: "nat set"wherezero: "0 ∈ Even"| EvenI: "n ∈ Odd =⇒ Suc n ∈ Even"| OddI: "n ∈ Even =⇒ Suc n ∈ Odd"The mutually inductive definiti<strong>on</strong> of multiple sets is no different from thatof a single set, except for inducti<strong>on</strong>: just as for mutually recursive datatypes,inducti<strong>on</strong> needs to involve all the simultaneously defined sets. In the abovecase, the inducti<strong>on</strong> rule is called Even_Odd.induct (simply c<strong>on</strong>catenate thenames of the sets involved) and has the c<strong>on</strong>clusi<strong>on</strong>(?x ∈ Even −→ ?P ?x) ∧ (?y ∈ Odd −→ ?Q ?y)If we want to prove that all even numbers are divisible by two, we haveto generalize the statement as follows:lemma "(m ∈ Even −→ 2 dvd m) ∧ (n ∈ Odd −→ 2 dvd (Suc n))"The proof is by rule inducti<strong>on</strong>. Because of the form of the inducti<strong>on</strong> theorem,it is applied by rule rather than erule as for ordinary inductive definiti<strong>on</strong>s:apply(rule Even_Odd.induct)1. 2 dvd 02. V n. [[n ∈ Odd; 2 dvd Suc n]] =⇒ 2 dvd Suc n3. V n. [[n ∈ Even; 2 dvd n]] =⇒ 2 dvd Suc (Suc n)The first two subgoals are proved by simplificati<strong>on</strong> and the final <strong>on</strong>e canbe proved in the same manner as in Sect. 7.1.3 where the same subgoal wasencountered before. We do not show the proof script.7.1.7 Inductively Defined PredicatesInstead of a set of even numbers <strong>on</strong>e can also define a predicate <strong>on</strong> nat:inductive evn :: "nat ⇒ bool" wherezero: "evn 0" |step: "evn n =⇒ evn(Suc(Suc n))"Everything works as before, except that you write inductive instead of inductiveset and evn n instead of n ∈ even. The notati<strong>on</strong> is more lightweightbut the usual set-theoretic operati<strong>on</strong>s, e.g. Even ∪ Odd, are not directly available<strong>on</strong> predicates.When defining an n-ary relati<strong>on</strong> as a predicate it is recommended to currythe predicate: its type should be τ 1 ⇒ . . . ⇒ τ n ⇒ bool rather than τ 1 ×. . . × τ n ⇒ bool. The curried versi<strong>on</strong> facilitates inducti<strong>on</strong>s.


7.2 The Reflexive Transitive Closure7.2 The Reflexive Transitive Closure 135An inductive definiti<strong>on</strong> may accept parameters, so it can express functi<strong>on</strong>sthat yield sets. Relati<strong>on</strong>s too can be defined inductively, since they are justsets of pairs. A perfect example is the functi<strong>on</strong> that maps a relati<strong>on</strong> to itsreflexive transitive closure. This c<strong>on</strong>cept was already introduced in Sect. 6.3,where the operator ∗ was defined as a least fixed point because inductivedefiniti<strong>on</strong>s were not yet available. But now they are:inductive setrtc :: "(’a × ’a)set ⇒ (’a × ’a)set" ("_*" [1000] 999)for r :: "(’a × ’a)set"wherertc_refl[iff]: "(x,x) ∈ r*"| rtc_step: "[[ (x,y) ∈ r; (y,z) ∈ r* ]] =⇒ (x,z) ∈ r*"The functi<strong>on</strong> rtc is annotated with c<strong>on</strong>crete syntax: instead of rtc r we canwrite r*. The actual definiti<strong>on</strong> c<strong>on</strong>sists of two rules. Reflexivity is obvious andis immediately given the iff attribute to increase automati<strong>on</strong>. The sec<strong>on</strong>drule, rtc_step, says that we can always add <strong>on</strong>e more r-step to the left.Although we could make rtc_step an introducti<strong>on</strong> rule, this is dangerous: therecursi<strong>on</strong> in the sec<strong>on</strong>d premise slows down and may even kill the automatictactics.The above definiti<strong>on</strong> of the c<strong>on</strong>cept of reflexive transitive closure may besufficiently intuitive but it is certainly not the <strong>on</strong>ly possible <strong>on</strong>e: for a start,it does not even menti<strong>on</strong> transitivity. The rest of this secti<strong>on</strong> is devoted toproving that it is equivalent to the standard definiti<strong>on</strong>. We start with a simplelemma:lemma [intro]: "(x,y) ∈ r =⇒ (x,y) ∈ r*"by(blast intro: rtc_step)Although the lemma itself is an unremarkable c<strong>on</strong>sequence of the basic rules,it has the advantage that it can be declared an introducti<strong>on</strong> rule withoutthe danger of killing the automatic tactics because r* occurs <strong>on</strong>ly in thec<strong>on</strong>clusi<strong>on</strong> and not in the premise. Thus some proofs that would otherwiseneed rtc_step can now be found automatically. The proof also shows thatblast is able to handle rtc_step. But some of the other automatic tactics aremore sensitive, and even blast can be lead astray in the presence of largenumbers of rules.To prove transitivity, we need rule inducti<strong>on</strong>, i.e. theorem rtc.induct:[[(?x1.0, ?x2.0) ∈ ?r*; V x. ?P x x;V x y z. [[(x, y) ∈ ?r; (y, z) ∈ ?r*; ?P y z]] =⇒ ?P x z]]=⇒ ?P ?x1.0 ?x2.0It says that ?P holds for an arbitrary pair (?x1.0, ?x2.0) ∈ ?r* if ?P ispreserved by all rules of the inductive definiti<strong>on</strong>, i.e. if ?P holds for the c<strong>on</strong>clusi<strong>on</strong>provided it holds for the premises. In general, rule inducti<strong>on</strong> for ann-ary inductive relati<strong>on</strong> R expects a premise of the form (x 1 , . . . , x n ) ∈ R.


136 7. Inductively Defined SetsNow we turn to the inductive proof of transitivity:lemma rtc_trans: "[[ (x,y) ∈ r*; (y,z) ∈ r* ]] =⇒ (x,z) ∈ r*"apply(erule rtc.induct)Unfortunately, even the base case is a problem:1. V x. (y, z) ∈ r* =⇒ (x, z) ∈ r*We have to aband<strong>on</strong> this proof attempt. To understand what is going <strong>on</strong>,let us look again at rtc.induct. In the above applicati<strong>on</strong> of erule, the firstpremise of rtc.induct is unified with the first suitable assumpti<strong>on</strong>, which is(x, y) ∈ r* rather than (y, z) ∈ r*. Although that is what we want, it ismerely due to the order in which the assumpti<strong>on</strong>s occur in the subgoal, whichit is not good practice to rely <strong>on</strong>. As a result, ?xb becomes x, ?xa becomesy and ?P becomes λu v. (u, z) ∈ r*, thus yielding the above subgoal. Sowhat went wr<strong>on</strong>g?When looking at the instantiati<strong>on</strong> of ?P we see that it does not depend<strong>on</strong> its sec<strong>on</strong>d parameter at all. The reas<strong>on</strong> is that in our original goal, ofthe pair (x, y) <strong>on</strong>ly x appears also in the c<strong>on</strong>clusi<strong>on</strong>, but not y. Thus ourinducti<strong>on</strong> statement is too general. Fortunately, it can easily be specialized:transfer the additi<strong>on</strong>al premise (y, z) ∈ r* into the c<strong>on</strong>clusi<strong>on</strong>:lemma rtc_trans[rule_format]:"(x,y) ∈ r* =⇒ (y,z) ∈ r* −→ (x,z) ∈ r*"This is not an obscure trick but a generally applicable heuristic:When proving a statement by rule inducti<strong>on</strong> <strong>on</strong> (x 1 , . . . , x n ) ∈ R, pullall other premises c<strong>on</strong>taining any of the x i into the c<strong>on</strong>clusi<strong>on</strong> using−→.A similar heuristic for other kinds of inducti<strong>on</strong>s is formulated in Sect. 9.2.1.The rule_format directive turns −→ back into =⇒: in the end we obtain theoriginal statement of our lemma.apply(erule rtc.induct)Now inducti<strong>on</strong> produces two subgoals which are both proved automatically:1. V x. (x, z) ∈ r* −→ (x, z) ∈ r*2. V x y za.[[(x, y) ∈ r; (y, za) ∈ r*; (za, z) ∈ r* −→ (y, z) ∈ r*]]=⇒ (za, z) ∈ r* −→ (x, z) ∈ r*apply(blast)apply(blast intro: rtc_step)d<strong>on</strong>eLet us now prove that r* is really the reflexive transitive closure of r, i.e.the least reflexive and transitive relati<strong>on</strong> c<strong>on</strong>taining r. The latter is easilyformalizedinductive set


7.3 Advanced Inductive Definiti<strong>on</strong>s 137rtc2 :: "(’a × ’a)set ⇒ (’a × ’a)set"for r :: "(’a × ’a)set"where"(x,y) ∈ r =⇒ (x,y) ∈ rtc2 r"| "(x,x) ∈ rtc2 r"| "[[ (x,y) ∈ rtc2 r; (y,z) ∈ rtc2 r ]] =⇒ (x,z) ∈ rtc2 r"and the equivalence of the two definiti<strong>on</strong>s is easily shown by the obvious ruleinducti<strong>on</strong>s:lemma "(x,y) ∈ rtc2 r =⇒ (x,y) ∈ r*"apply(erule rtc2.induct)apply(blast)apply(blast)apply(blast intro: rtc_trans)d<strong>on</strong>elemma "(x,y) ∈ r* =⇒ (x,y) ∈ rtc2 r"apply(erule rtc.induct)apply(blast intro: rtc2.intros)apply(blast intro: rtc2.intros)d<strong>on</strong>eSo why did we start with the first definiti<strong>on</strong>? Because it is simpler. Itc<strong>on</strong>tains <strong>on</strong>ly two rules, and the single step rule is simpler than transitivity.As a c<strong>on</strong>sequence, rtc.induct is simpler than rtc2.induct. Since inductiveproofs are hard enough anyway, we should always pick the simplest inducti<strong>on</strong>schema available. Hence rtc is the definiti<strong>on</strong> of choice.Exercise 7.2.1 Show that the c<strong>on</strong>verse of rtc_step also holds:[[(x, y) ∈ r*; (y, z) ∈ r]] =⇒ (x, z) ∈ r*Exercise 7.2.2 Repeat the development of this secti<strong>on</strong>, but starting witha definiti<strong>on</strong> of rtc where rtc_step is replaced by its c<strong>on</strong>verse as shown inexercise 7.2.1.7.3 Advanced Inductive Definiti<strong>on</strong>sThe premises of introducti<strong>on</strong> rules may c<strong>on</strong>tain universal quantifiers andm<strong>on</strong>ot<strong>on</strong>e functi<strong>on</strong>s. A universal quantifier lets the rule refer to any numberof instances of the inductively defined set. A m<strong>on</strong>ot<strong>on</strong>e functi<strong>on</strong> lets the rulerefer to existing c<strong>on</strong>structi<strong>on</strong>s (such as “list of”) over the inductively definedset. The examples below show how to use the additi<strong>on</strong>al expressiveness andhow to reas<strong>on</strong> from the resulting definiti<strong>on</strong>s.


138 7. Inductively Defined Sets7.3.1 Universal Quantifiers in Introducti<strong>on</strong> RulesAs a running example, this secti<strong>on</strong> develops the theory of ground terms:terms c<strong>on</strong>structed from c<strong>on</strong>stant and functi<strong>on</strong> symbols but not variables. Tosimplify matters further, we regard a c<strong>on</strong>stant as a functi<strong>on</strong> applied to thenull argument list. Let us declare a datatype gterm for the type of groundterms. It is a type c<strong>on</strong>structor whose argument is a type of functi<strong>on</strong> symbols.datatype ’f gterm = Apply ’f "’f gterm list"To try it out, we declare a datatype of some integer operati<strong>on</strong>s: integerc<strong>on</strong>stants, the unary minus operator and the additi<strong>on</strong> operator.datatype integer_op = Number int | UnaryMinus | PlusNow the type integer_op gterm denotes the ground terms built over thosesymbols.The type c<strong>on</strong>structor gterm can be generalized to a functi<strong>on</strong> over sets. Itreturns the set of ground terms that can be formed over a set F of functi<strong>on</strong>symbols. For example, we could c<strong>on</strong>sider the set of ground terms formed fromthe finite set {Number 2, UnaryMinus, Plus}.This c<strong>on</strong>cept is inductive. If we have a list args of ground terms over Fand a functi<strong>on</strong> symbol f in F, then we can apply f to args to obtain anotherground term. The <strong>on</strong>ly difficulty is that the argument list may be of anylength. Hitherto, each rule in an inductive definiti<strong>on</strong> referred to the inductivelydefined set a fixed number of times, typically <strong>on</strong>ce or twice. A universalquantifier in the premise of the introducti<strong>on</strong> rule expresses that every elementof args bel<strong>on</strong>gs to our inductively defined set: is a ground term over F. Thefuncti<strong>on</strong> set denotes the set of elements in a given list.inductive setgterms :: "’f set ⇒ ’f gterm set"for F :: "’f set"wherestep[intro!]: "[[∀ t ∈ set args. t ∈ gterms F;=⇒ (Apply f args) ∈ gterms F"f ∈ F]]To dem<strong>on</strong>strate a proof from this definiti<strong>on</strong>, let us show that the functi<strong>on</strong>gterms is m<strong>on</strong>ot<strong>on</strong>e. We shall need this c<strong>on</strong>cept shortly.lemma gterms_m<strong>on</strong>o: "F⊆G =⇒ gterms F ⊆ gterms G"apply clarifyapply (erule gterms.induct)apply blastd<strong>on</strong>eIntuitively, this theorem says that enlarging the set of functi<strong>on</strong> symbolsenlarges the set of ground terms. The proof is a trivial rule inducti<strong>on</strong>. Firstwe use the clarify method to assume the existence of an element of gtermsF. (We could have used intro subsetI.) We then apply rule inducti<strong>on</strong>. Hereis the resulting subgoal:


7.3 Advanced Inductive Definiti<strong>on</strong>s 1391. V x args f.[[F ⊆ G; ∀ t∈set args. t ∈ gterms F ∧ t ∈ gterms G; f ∈ F]]=⇒ Apply f args ∈ gterms GThe assumpti<strong>on</strong>s state that f bel<strong>on</strong>gs to F, which is included in G, and thatevery element of the list args is a ground term over G. The blast methodfinds this chain of reas<strong>on</strong>ing easily.!!Why do we call this functi<strong>on</strong> gterms instead of gterm? A c<strong>on</strong>stant may havethe same name as a type. However, name clashes could arise in the theoremsthat <strong>Isabelle</strong> generates. Our choice of names keeps gterms.induct separate fromgterm.induct.Call a term well-formed if each symbol occurring in it is applied to thecorrect number of arguments. (This number is called the symbol’s arity.)We can express well-formedness by generalizing the inductive definiti<strong>on</strong> ofgterms. Suppose we are given a functi<strong>on</strong> called arity, specifying the aritiesof all symbols. In the inductive step, we have a list args of such terms and afuncti<strong>on</strong> symbol f. If the length of the list matches the functi<strong>on</strong>’s arity thenapplying f to args yields a well-formed term.inductive setwell_formed_gterm :: "(’f ⇒ nat) ⇒ ’f gterm set"for arity :: "’f ⇒ nat"wherestep[intro!]: "[[∀ t ∈ set args. t ∈ well_formed_gterm arity;length args = arity f]]=⇒ (Apply f args) ∈ well_formed_gterm arity"The inductive definiti<strong>on</strong> neatly captures the reas<strong>on</strong>ing above. The universalquantificati<strong>on</strong> over the set of arguments expresses that all of them arewell-formed.7.3.2 Alternative Definiti<strong>on</strong> Using a M<strong>on</strong>ot<strong>on</strong>e Functi<strong>on</strong>An inductive definiti<strong>on</strong> may refer to the inductively defined set through anarbitrary m<strong>on</strong>ot<strong>on</strong>e functi<strong>on</strong>. To dem<strong>on</strong>strate this powerful feature, let uschange the inductive definiti<strong>on</strong> above, replacing the quantifier by a use of thefuncti<strong>on</strong> lists. This functi<strong>on</strong>, from the <strong>Isabelle</strong> theory of lists, is analogousto the functi<strong>on</strong> gterms declared above: if A is a set then lists A is the set oflists whose elements bel<strong>on</strong>g to A.In the inductive definiti<strong>on</strong> of well-formed terms, examine the <strong>on</strong>e introducti<strong>on</strong>rule. The first premise states that args bel<strong>on</strong>gs to the lists of wellformedterms. This formulati<strong>on</strong> is more direct, if more obscure, than using auniversal quantifier.inductive setwell_formed_gterm’ :: "(’f ⇒ nat) ⇒ ’f gterm set"for arity :: "’f ⇒ nat"


140 7. Inductively Defined Setswherestep[intro!]: "[[args ∈ lists (well_formed_gterm’ arity);length args = arity f]]=⇒ (Apply f args) ∈ well_formed_gterm’ arity"m<strong>on</strong>os lists_m<strong>on</strong>oWe cite the theorem lists_m<strong>on</strong>o to justify using the functi<strong>on</strong> lists. 1A ⊆ B =⇒ lists A ⊆ lists B(lists_m<strong>on</strong>o)Why must the functi<strong>on</strong> be m<strong>on</strong>ot<strong>on</strong>e? An inductive definiti<strong>on</strong> describes aniterative c<strong>on</strong>structi<strong>on</strong>: each element of the set is c<strong>on</strong>structed by a finite numberof introducti<strong>on</strong> rule applicati<strong>on</strong>s. For example, the elements of even arec<strong>on</strong>structed by finitely many applicati<strong>on</strong>s of the rules0 ∈ evenn ∈ even =⇒ Suc (Suc n) ∈ evenAll references to a set in its inductive definiti<strong>on</strong> must be positive. Applicati<strong>on</strong>sof an introducti<strong>on</strong> rule cannot invalidate previous applicati<strong>on</strong>s, allowing thec<strong>on</strong>structi<strong>on</strong> process to c<strong>on</strong>verge. The following pair of rules do not c<strong>on</strong>stitutean inductive definiti<strong>on</strong>:0 ∈ evenn /∈ even =⇒ Suc n ∈ evenShowing that 4 is even using these rules requires showing that 3 is not even.It is far from trivial to show that this set of rules characterizes the evennumbers.Even with its use of the functi<strong>on</strong> lists, the premise of our introducti<strong>on</strong>rule is positive:args ∈ lists (well_formed_gterm’ arity)To apply the rule we c<strong>on</strong>struct a list args of previously c<strong>on</strong>structed wellformedterms. We obtain a new term, Apply f args. Because lists is m<strong>on</strong>ot<strong>on</strong>e,applicati<strong>on</strong>s of the rule remain valid as new terms are c<strong>on</strong>structed.Further lists of well-formed terms become available and n<strong>on</strong>e are taken away.7.3.3 A Proof of EquivalenceWe naturally hope that these two inductive definiti<strong>on</strong>s of “well-formed” coincide.The equality can be proved by separate inclusi<strong>on</strong>s in each directi<strong>on</strong>.Each is a trivial rule inducti<strong>on</strong>.lemma "well_formed_gterm arity ⊆ well_formed_gterm’ arity"apply clarifyapply (erule well_formed_gterm.induct)apply auto1 This particular theorem is installed by default already, but we include the m<strong>on</strong>osdeclarati<strong>on</strong> in order to illustrate its syntax.


7.3 Advanced Inductive Definiti<strong>on</strong>s 141d<strong>on</strong>eThe clarify method gives us an element of well_formed_gterm arity <strong>on</strong>which to perform inducti<strong>on</strong>. The resulting subgoal can be proved automatically:1. V x args f.[[∀ t∈set args.t ∈ well_formed_gterm arity ∧ t ∈ well_formed_gterm’ arity;length args = arity f]]=⇒ Apply f args ∈ well_formed_gterm’ arityThis proof resembles the <strong>on</strong>e given in Sect. 7.3.1 above, especially in the formof the inducti<strong>on</strong> hypothesis. Next, we c<strong>on</strong>sider the opposite inclusi<strong>on</strong>:lemma "well_formed_gterm’ arity ⊆ well_formed_gterm arity"apply clarifyapply (erule well_formed_gterm’.induct)apply autod<strong>on</strong>eThe proof script is virtually identical, but the subgoal after applying inducti<strong>on</strong>may be surprising:1. V x args f.[[args∈ lists(well_formed_gterm’ arity ∩{a. a ∈ well_formed_gterm arity});length args = arity f]]=⇒ Apply f args ∈ well_formed_gterm arityThe inducti<strong>on</strong> hypothesis c<strong>on</strong>tains an applicati<strong>on</strong> of lists. Using a m<strong>on</strong>ot<strong>on</strong>efuncti<strong>on</strong> in the inductive definiti<strong>on</strong> always has this effect. The subgoal maylook uninviting, but fortunately lists distributes over intersecti<strong>on</strong>:lists (A ∩ B) = lists A ∩ lists B(lists_Int_eq)Thanks to this default simplificati<strong>on</strong> rule, the inducti<strong>on</strong> hypothesis is quicklyreplaced by its two parts:args ∈ lists (well_formed_gterm’ arity)args ∈ lists (well_formed_gterm arity)Invoking the rule well_formed_gterm.step completes the proof. The call toauto does all this work.This example is typical of how m<strong>on</strong>ot<strong>on</strong>e functi<strong>on</strong>s can be used. In particular,many of them distribute over intersecti<strong>on</strong>. M<strong>on</strong>ot<strong>on</strong>icity implies <strong>on</strong>edirecti<strong>on</strong> of this set equality; we have this theorem:m<strong>on</strong>o f =⇒ f (A ∩ B) ⊆ f A ∩ f B(m<strong>on</strong>o_Int)


142 7. Inductively Defined Sets7.3.4 Another Example of Rule Inversi<strong>on</strong>Does gterms distribute over intersecti<strong>on</strong>? We have proved that this functi<strong>on</strong>is m<strong>on</strong>ot<strong>on</strong>e, so m<strong>on</strong>o_Int gives <strong>on</strong>e of the inclusi<strong>on</strong>s. The opposite inclusi<strong>on</strong>asserts that if t is a ground term over both of the sets F and G then it is alsoa ground term over their intersecti<strong>on</strong>, F ∩ G.lemma gterms_IntI:"t ∈ gterms F =⇒ t ∈ gterms G −→ t ∈ gterms (F∩G)"Attempting this proof, we get the assumpti<strong>on</strong> Apply f args ∈ gterms G,which cannot be broken down. It looks like a job for rule inversi<strong>on</strong>:inductive cases gterm_Apply_elim [elim!]: "Apply f args ∈ gterms F"Here is the result.[[Apply f args ∈ gterms F;[[∀ t∈set args. t ∈ gterms F; f ∈ F]] =⇒ P]]=⇒ P (gterm_Apply_elim)This rule replaces an assumpti<strong>on</strong> about Apply f args by assumpti<strong>on</strong>s aboutf and args. No cases are discarded (there was <strong>on</strong>ly <strong>on</strong>e to begin with) butthe rule applies specifically to the pattern Apply f args. It can be appliedrepeatedly as an eliminati<strong>on</strong> rule without looping, so we have given the elim!attribute.Now we can prove the other half of that distributive law.lemma gterms_IntI [rule_format, intro!]:"t ∈ gterms F =⇒ t ∈ gterms G −→ t ∈ gterms (F∩G)"apply (erule gterms.induct)apply blastd<strong>on</strong>eThe proof begins with rule inducti<strong>on</strong> over the definiti<strong>on</strong> of gterms, whichleaves a single subgoal:1. V args f.[[∀ t∈set args.t ∈ gterms F ∧ (t ∈ gterms G −→ t ∈ gterms (F ∩ G));f ∈ F]]=⇒ Apply f args ∈ gterms G −→Apply f args ∈ gterms (F ∩ G)To prove this, we assume Apply f args ∈ gterms G. Rule inversi<strong>on</strong>, in theform of gterm_Apply_elim, infers that every element of args bel<strong>on</strong>gs to gtermsG; hence (by the inducti<strong>on</strong> hypothesis) it bel<strong>on</strong>gs to gterms (F ∩ G). Ruleinversi<strong>on</strong> also yields f ∈ G and hence f ∈ F ∩ G. All of this reas<strong>on</strong>ing isd<strong>on</strong>e by blast.Our distributive law is a trivial c<strong>on</strong>sequence of previously-proved results:lemma gterms_Int_eq [simp]:"gterms (F ∩ G) = gterms F ∩ gterms G"by (blast intro!: m<strong>on</strong>o_Int m<strong>on</strong>oI gterms_m<strong>on</strong>o)


7.4 Case Study: A C<strong>on</strong>text Free Grammar 143Exercise 7.3.1 A functi<strong>on</strong> mapping functi<strong>on</strong> symbols to their types is calleda signature. Given a type ranging over type symbols, we can represent afuncti<strong>on</strong>’s type by a list of argument types paired with the result type. Completethis inductive definiti<strong>on</strong>:inductive setwell_typed_gterm :: "(’f ⇒ ’t list * ’t) ⇒ (’f gterm * ’t)set"for sig :: "’f ⇒ ’t list * ’t"7.4 Case Study: A C<strong>on</strong>text Free GrammarGrammars are nothing but shorthands for inductive definiti<strong>on</strong>s of n<strong>on</strong>terminalswhich represent sets of strings. For example, the producti<strong>on</strong> A → Bc isshort forw ∈ B =⇒ wc ∈ AThis secti<strong>on</strong> dem<strong>on</strong>strates this idea with an example due to Hopcroft andUllman, a grammar for generating all words with an equal number of a’sand b’s:S → ɛ | bA | aBA → aS | bAAB → bS | aBBAt the end we say a few words about the relati<strong>on</strong>ship between the originalproof [15, p. 81] and our formal versi<strong>on</strong>.We start by fixing the alphabet, which c<strong>on</strong>sists <strong>on</strong>ly of a’s and b’s:datatype alfa = a | bFor c<strong>on</strong>venience we include the following easy lemmas as simplificati<strong>on</strong> rules:lemma [simp]: "(x ≠ a) = (x = b) ∧ (x ≠ b) = (x = a)"by (case_tac x, auto)Words over this alphabet are of type alfa list, and the three n<strong>on</strong>terminalsare declared as sets of such words. The producti<strong>on</strong>s above are recast as amutual inductive definiti<strong>on</strong> of S, A and B:inductive setS :: "alfa list set" andA :: "alfa list set" andB :: "alfa list set"where"[] ∈ S"| "w ∈ A =⇒ b#w ∈ S"| "w ∈ B =⇒ a#w ∈ S"| "w ∈ S =⇒ a#w ∈ A"


144 7. Inductively Defined Sets| "[[ v∈A; w∈A ]] =⇒ b#v@w ∈ A"| "w ∈ S =⇒ b#w ∈ B"| "[[ v ∈ B; w ∈ B ]] =⇒ a#v@w ∈ B"First we show that all words in S c<strong>on</strong>tain the same number of a’s and b’s.Since the definiti<strong>on</strong> of S is by mutual inducti<strong>on</strong>, so is the proof: we show atthe same time that all words in A c<strong>on</strong>tain <strong>on</strong>e more a than b and all wordsin B c<strong>on</strong>tain <strong>on</strong>e more b than a.lemma correctness:"(w ∈ S −→ size[x←w. x=a] = size[x←w. x=b]) ∧(w ∈ A −→ size[x←w. x=a] = size[x←w. x=b] + 1) ∧(w ∈ B −→ size[x←w. x=b] = size[x←w. x=a] + 1)"These propositi<strong>on</strong>s are expressed with the help of the predefined filter functi<strong>on</strong><strong>on</strong> lists, which has the c<strong>on</strong>venient syntax [x←xs. P x], the list of all elementsx in xs such that P x holds. Remember that <strong>on</strong> lists size and lengthare syn<strong>on</strong>ymous.The proof itself is by rule inducti<strong>on</strong> and afterwards automatic:by (rule S_A_B.induct, auto)This may seem surprising at first, and is indeed an indicati<strong>on</strong> of the powerof inductive definiti<strong>on</strong>s. But it is also quite straightforward. For example,c<strong>on</strong>sider the producti<strong>on</strong> A → bAA: if v, w ∈ A and the elements of A c<strong>on</strong>tain<strong>on</strong>e more a than b’s, then bvw must again c<strong>on</strong>tain <strong>on</strong>e more a than b’s.As usual, the correctness of syntactic descripti<strong>on</strong>s is easy, but completenessis hard: does S c<strong>on</strong>tain all words with an equal number of a’s and b’s? Itturns out that this proof requires the following lemma: every string with twomore a’s than b’s can be cut somewhere such that each half has <strong>on</strong>e more athan b. This is best seen by imagining counting the difference between thenumber of a’s and b’s starting at the left end of the word. We start with0 and end (at the right end) with 2. Since each move to the right increasesor decreases the difference by 1, we must have passed through 1 <strong>on</strong> our wayfrom 0 to 2. Formally, we appeal to the following discrete intermediate valuetheorem nat0_intermed_int_val[[∀ i


7.4 Case Study: A C<strong>on</strong>text Free Grammar 145lemma step1: "∀ i < size w.|(int(size[x←take (i+1) w. P x])-int(size[x←take (i+1) w. ¬P x]))- (int(size[x←take i w. P x])-int(size[x←take i w. ¬P x]))| ≤ 1"The lemma is a bit hard to read because of the coerci<strong>on</strong> functi<strong>on</strong> int :: nat⇒ int. It is required because size returns a natural number, but subtracti<strong>on</strong><strong>on</strong> type nat will do the wr<strong>on</strong>g thing. Functi<strong>on</strong> take is predefined and takei xs is the prefix of length i of xs; below we also need drop i xs, which iswhat remains after that prefix has been dropped from xs.The proof is by inducti<strong>on</strong> <strong>on</strong> w, with a trivial base case, and a not so trivialinducti<strong>on</strong> step. Since it is essentially just arithmetic, we do not discuss it.apply(induct_tac w)apply(auto simp add: abs_if take_C<strong>on</strong>s split: nat.split)d<strong>on</strong>eFinally we come to the above-menti<strong>on</strong>ed lemma about cutting in half aword with two more elements of <strong>on</strong>e sort than of the other sort:lemma part1:"size[x←w. P x] = size[x←w. ¬P x]+2 =⇒∃ i≤size w. size[x←take i w. P x] = size[x←take i w. ¬P x]+1"This is proved by force with the help of the intermediate value theorem,instantiated appropriately and with its first premise disposed of by lemmastep1:apply(insert nat0_intermed_int_val[OF step1, of "P" "w" "1"])by forceLemma part1 tells us <strong>on</strong>ly about the prefix take i w. An easy lemmadeals with the suffix drop i w:lemma part2:"[[size[x←take i w @ drop i w. P x] =size[x←take i w @ drop i w. ¬P x]+2;size[x←take i w. P x] = size[x←take i w. ¬P x]+1]]=⇒ size[x←drop i w. P x] = size[x←drop i w. ¬P x]+1"by(simp del: append_take_drop_id)In the proof we have disabled the normally useful lemmatake n xs @ drop n xs = xsto allow the simplifier to apply the following lemma instead:[x∈xs@ys. P x] = [x∈xs. P x] @ [x∈ys. P x](append_take_drop_id)To dispose of trivial cases automatically, the rules of the inductive definiti<strong>on</strong>are declared simplificati<strong>on</strong> rules:declare S_A_B.intros[simp]This could have been d<strong>on</strong>e earlier but was not necessary so far.The completeness theorem tells us that if a word has the same number ofa’s and b’s, then it is in S, and similarly for A and B:


146 7. Inductively Defined Setstheorem completeness:"(size[x←w. x=a] = size[x←w. x=b] −→ w ∈ S) ∧(size[x←w. x=a] = size[x←w. x=b] + 1 −→ w ∈ A) ∧(size[x←w. x=b] = size[x←w. x=a] + 1 −→ w ∈ B)"The proof is by inducti<strong>on</strong> <strong>on</strong> w. Structural inducti<strong>on</strong> would fail here because,as we can see from the grammar, we need to make bigger steps than merelyappending a single letter at the fr<strong>on</strong>t. Hence we induct <strong>on</strong> the length of w,using the inducti<strong>on</strong> rule length_induct:apply(induct_tac w rule: length_induct)apply(rename_tac w)The rule parameter tells induct_tac explicitly which inducti<strong>on</strong> rule to use.For details see Sect. 9.2.2 below. In this case the result is that we may assumethe lemma already holds for all words shorter than w. Because the inducti<strong>on</strong>step renames the inducti<strong>on</strong> variable we rename it back to w.The proof c<strong>on</strong>tinues with a case distincti<strong>on</strong> <strong>on</strong> w, <strong>on</strong> whether w is emptyor not.apply(case_tac w)apply(simp_all)Simplificati<strong>on</strong> disposes of the base case and leaves <strong>on</strong>ly a c<strong>on</strong>juncti<strong>on</strong> of twostep cases to be proved: if w = a # v andlength (if x = a then [x ∈ v] else []) =length (if x = b then [x ∈ v] else []) + 2then b # v ∈ A, and similarly for w = b # v. We <strong>on</strong>ly c<strong>on</strong>sider the first casein detail.After breaking the c<strong>on</strong>juncti<strong>on</strong> up into two cases, we can apply part1 tothe assumpti<strong>on</strong> that w c<strong>on</strong>tains two more a’s than b’s.apply(rule c<strong>on</strong>jI)apply(clarify)apply(frule part1[of "λx. x=a", simplified])apply(clarify)This yields an index i ≤ length v such thatlength [x←take i v . x = a] = length [x←take i v . x = b] + 1With the help of part2 it follows thatlength [x←drop i v . x = a] = length [x←drop i v . x = b] + 1apply(drule part2[of "λx. x=a", simplified])apply(assumpti<strong>on</strong>)Now it is time to decompose v in the c<strong>on</strong>clusi<strong>on</strong> b # v ∈ A into take i v @drop i v,apply(rule_tac n1=i and t=v in subst[OF append_take_drop_id])


7.4 Case Study: A C<strong>on</strong>text Free Grammar 147(the variables n1 and t are the result of composing the theorems subst andappend_take_drop_id) after which the appropriate rule of the grammar reducesthe goal to the two subgoals take i v ∈ A and drop i v ∈ A:apply(rule S_A_B.intros)Both subgoals follow from the inducti<strong>on</strong> hypothesis because both take iv and drop i v are shorter than w:apply(force simp add: min_less_iff_disj)apply(force split add: nat_diff_split)The case w = b # v is proved analogously:apply(clarify)apply(frule part1[of "λx. x=b", simplified])apply(clarify)apply(drule part2[of "λx. x=b", simplified])apply(assumpti<strong>on</strong>)apply(rule_tac n1=i and t=v in subst[OF append_take_drop_id])apply(rule S_A_B.intros)apply(force simp add: min_less_iff_disj)by(force simp add: min_less_iff_disj split add: nat_diff_split)We c<strong>on</strong>clude this secti<strong>on</strong> with a comparis<strong>on</strong> of our proof with Hopcroftand Ullman’s [15, p. 81]. For a start, the textbook grammar, for no goodreas<strong>on</strong>, excludes the empty word, thus complicating matters just a little bit:they have 8 instead of our 7 producti<strong>on</strong>s.More importantly, the proof itself is different: rather than separating thetwo directi<strong>on</strong>s, they perform <strong>on</strong>e inducti<strong>on</strong> <strong>on</strong> the length of a word. Thisdeprives them of the beauty of rule inducti<strong>on</strong>, and in the easy directi<strong>on</strong>(correctness) their reas<strong>on</strong>ing is more detailed than our auto. For the hardpart (completeness), they c<strong>on</strong>sider just <strong>on</strong>e of the cases that our simp_alldisposes of automatically. Then they c<strong>on</strong>clude the proof by saying about theremaining cases: “We do this in a manner similar to our method of prooffor part (1); this part is left to the reader”. But this is precisely the partthat requires the intermediate value theorem and thus is not at all similar tothe other cases (which are automatic in <strong>Isabelle</strong>). The authors are at leastcavalier about this point and may even have overlooked the slight difficultylurking in the omitted cases. Such errors are found in many pen-and-paperproofs when they are scrutinized formally.


Part IIIAdvanced Material


8. More about TypesSo far we have learned about a few basic types (for example bool and nat),type abbreviati<strong>on</strong>s (types) and recursive datatypes (datatype). This chapterwill introduce more advanced material:– Pairs (Sect. 8.1) and records (Sect. 8.2), and how to reas<strong>on</strong> about them.– Type classes: how to specify and reas<strong>on</strong> about axiomatic collecti<strong>on</strong>s oftypes (Sect. 8.3). This secti<strong>on</strong> leads <strong>on</strong> to a discussi<strong>on</strong> of <strong>Isabelle</strong>’s numerictypes (Sect. 8.4).– Introducing your own types: how to define types that cannot be c<strong>on</strong>structedwith any of the basic methods (Sect. 8.5).The material in this secti<strong>on</strong> goes bey<strong>on</strong>d the needs of most novices. Serioususers should at least skim the secti<strong>on</strong>s as far as type classes. That materialis fairly advanced; read the beginning to understand what it is about, butc<strong>on</strong>sult the rest <strong>on</strong>ly when necessary.8.1 Pairs and TuplesOrdered pairs were already introduced in Sect. 2.6.2, but <strong>on</strong>ly with a minimalrepertoire of operati<strong>on</strong>s: pairing and the two projecti<strong>on</strong>s fst and snd. Inany n<strong>on</strong>-trivial applicati<strong>on</strong> of pairs you will find that this quickly leads tounreadable nests of projecti<strong>on</strong>s. This secti<strong>on</strong> introduces syntactic sugar toovercome this problem: pattern matching with tuples.8.1.1 Pattern Matching with TuplesTuples may be used as patterns in λ-abstracti<strong>on</strong>s, for example λ(x,y,z).x+y+zand λ((x,y),z).x+y+z. In fact, tuple patterns can be used in most variablebinding c<strong>on</strong>structs, and they can be nested. Here are some typical examples:let (x, y) = f z in (y, x)case xs of [] ⇒ 0 | (x, y) # zs ⇒ x + y∀ (x,y)∈A. x=y{(x,y,z). x=z}S(x, y)∈A {x + y}


152 8. More about TypesThe intuitive meanings of these expressi<strong>on</strong>s should be obvious. Unfortunately,we need to know in more detail what the notati<strong>on</strong> really stands for <strong>on</strong>cewe have to reas<strong>on</strong> about it. Abstracti<strong>on</strong> over pairs and tuples is merely ac<strong>on</strong>venient shorthand for a more complex internal representati<strong>on</strong>. Thus theinternal and external form of a term may differ, which can affect proofs. Ifyou want to avoid this complicati<strong>on</strong>, stick to fst and snd and write λp. fstp + snd p instead of λ(x,y). x+y. These terms are distinct even though theydenote the same functi<strong>on</strong>.Internally, λ(x, y). t becomes split (λx y. t), where split is the uncurryingfuncti<strong>on</strong> of type (’a ⇒ ’b ⇒ ’c) ⇒ ’a × ’b ⇒ ’c defined assplit ≡ λc p. c (fst p) (snd p)(split_def)Pattern matching in other variable binding c<strong>on</strong>structs is translated similarly.Thus we need to understand how to reas<strong>on</strong> about such c<strong>on</strong>structs.8.1.2 Theorem ProvingThe most obvious approach is the brute force expansi<strong>on</strong> of split:lemma "(λ(x,y).x) p = fst p"by(simp add: split_def)This works well if rewriting with split_def finishes the proof, as it doesabove. But if it does not, you end up with exactly what we are trying toavoid: nests of fst and snd. Thus this approach is neither elegant nor verypractical in large examples, although it can be effective in small <strong>on</strong>es.If we c<strong>on</strong>sider why this lemma presents a problem, we realize that we needto replace variable p by some pair (a, b). Then both sides of the equati<strong>on</strong>would simplify to a by the simplificati<strong>on</strong> rules split f (a, b) = f a b andfst (a, b) = a. To reas<strong>on</strong> about tuple patterns requires some way of c<strong>on</strong>vertinga variable of product type into a pair. In case of a subterm of theform split f p this is easy: the split rule split_split replaces p by a pair:lemma "(λ(x,y).y) p = snd p"apply(split split_split)1. ∀ x y. p = (x, y) −→ y = snd pThis subgoal is easily proved by simplificati<strong>on</strong>. Thus we could have combinedsimplificati<strong>on</strong> and splitting in <strong>on</strong>e command that proves the goal outright:by(simp split: split_split)Let us look at a sec<strong>on</strong>d example:lemma "let (x,y) = p in fst p = x"apply(simp <strong>on</strong>ly: Let_def)1. (λ(x, y). fst p = x) p


8.1 Pairs and Tuples 153A paired let reduces to a paired λ-abstracti<strong>on</strong>, which can be split as above.The same is true for paired set comprehensi<strong>on</strong>:lemma "p ∈ {(x,y). x=y} −→ fst p = snd p"apply simp1. split op = p −→ fst p = snd pAgain, simplificati<strong>on</strong> produces a term suitable for split_split as above. Ifyou are worried about the strange form of the premise: split (op =) is shortfor λ(x, y). x = y. The same proof procedure works forlemma "p ∈ {(x,y). x=y} =⇒ fst p = snd p"except that we now have to use split_split_asm, because split occurs in theassumpti<strong>on</strong>s.However, splitting split is not always a soluti<strong>on</strong>, as no split may bepresent in the goal. C<strong>on</strong>sider the following functi<strong>on</strong>:primrec swap :: "’a × ’b ⇒ ’b × ’a" where "swap (x,y) = (y,x)"Note that the above primrec definiti<strong>on</strong> is admissible because × is a datatype.When we now try to provelemma "swap(swap p) = p"simplificati<strong>on</strong> will do nothing, because the defining equati<strong>on</strong> for swap expectsa pair. Again, we need to turn p into a pair first, but this time there is nosplit in sight. The <strong>on</strong>ly thing we can do is to split the term by hand:apply(case_tac p)1. V a b. p = (a, b) =⇒ swap (swap p) = pAgain, case_tac is applicable because × is a datatype. The subgoal is easilyproved by simp.Splitting by case_tac also solves the previous examples and may thusappear preferable to the more arcane methods introduced first. However, seethe warning about case_tac in Sect. 2.5.5.Alternatively, you can split all V -quantified variables in a goal with therewrite rule split_paired_all:lemma " V p q. swap(swap p) = q −→ p = q"apply(simp <strong>on</strong>ly: split_paired_all)1. V a b aa ba. swap (swap (a, b)) = (aa, ba) −→ (a, b) = (aa, ba)apply simpd<strong>on</strong>eNote that we have intenti<strong>on</strong>ally included <strong>on</strong>ly split_paired_all in the firstsimplificati<strong>on</strong> step, and then we simplify again. This time the reas<strong>on</strong> was notmerely pedagogical: split_paired_all may interfere with other functi<strong>on</strong>s of


154 8. More about Typesthe simplifier. The following command could fail (here it does not) where twoseparate simp applicati<strong>on</strong>s succeed.apply(simp add: split_paired_all)Finally, the simplifier automatically splits all ∀ and ∃ -quantified variables:lemma "∀ p. ∃ q. swap p = swap q"by simpTo turn off this automatic splitting, disable the resp<strong>on</strong>sible simplificati<strong>on</strong>rules:(∀ x. P x) = (∀ a b. P (a, b)) (split_paired_All)(∃ x. P x) = (∃ a b. P (a, b)) (split_paired_Ex)8.2 RecordsRecords are familiar from programming languages. A record of n fields isessentially an n-tuple, but the record’s comp<strong>on</strong>ents have names, which canmake expressi<strong>on</strong>s easier to read and reduces the risk of c<strong>on</strong>fusing <strong>on</strong>e fieldfor another.A record of <strong>Isabelle</strong>/<strong>HOL</strong> covers a collecti<strong>on</strong> of fields, with select andupdate operati<strong>on</strong>s. Each field has a specified type, which may be polymorphic.The field names are part of the record type, and the order of the fields issignificant — as it is in Pascal but not in Standard ML. If two differentrecord types have field names in comm<strong>on</strong>, then the ambiguity is resolved inthe usual way, by qualified names.Record types can also be defined by extending other record types. Extensiblerecords make use of the reserved pseudo-field more, which is present inevery record type. Generic record operati<strong>on</strong>s work <strong>on</strong> all possible extensi<strong>on</strong>sof a given type scheme; polymorphism takes care of structural sub-typingbehind the scenes. There are also explicit coerci<strong>on</strong> functi<strong>on</strong>s between fixedrecord types.8.2.1 Record BasicsRecord types are not primitive in <strong>Isabelle</strong> and have a delicate internal representati<strong>on</strong>[23], based <strong>on</strong> nested copies of the primitive product type. Arecord declarati<strong>on</strong> introduces a new record type scheme by specifying itsfields, which are packaged internally to hold up the percepti<strong>on</strong> of the recordas a distinguished entity. Here is a simple example:record point =Xcoord :: intYcoord :: int


8.2 Records 155Records of type point have two fields named Xcoord and Ycoord, both oftype int. We now define a c<strong>on</strong>stant of type point:definiti<strong>on</strong> pt1 :: point where"pt1 ≡ (| Xcoord = 999, Ycoord = 23 |)"We see above the ASCII notati<strong>on</strong> for record brackets. You can also use thesymbolic brackets (| and |). Record type expressi<strong>on</strong>s can be also written directlywith individual fields. The type name above is merely an abbreviati<strong>on</strong>.definiti<strong>on</strong> pt2 :: "(|Xcoord :: int, Ycoord :: int|)" where"pt2 ≡ (|Xcoord = -45, Ycoord = 97|)"For each field, there is a selector functi<strong>on</strong> of the same name. For example,if p has type point then Xcoord p denotes the value of the Xcoord fieldof p. Expressi<strong>on</strong>s involving field selecti<strong>on</strong> of explicit records are simplifiedautomatically:lemma "Xcoord (|Xcoord = a, Ycoord = b|) = a"by simpThe update operati<strong>on</strong> is functi<strong>on</strong>al. For example, p(|Xcoord := 0|) is arecord whose Xcoord value is zero and whose Ycoord value is copied from p.Updates of explicit records are also simplified automatically:lemma "(|Xcoord = a, Ycoord = b|)(|Xcoord := 0|) =(|Xcoord = 0, Ycoord = b|)"by simp!!Field names are declared as c<strong>on</strong>stants and can no l<strong>on</strong>ger be used as variables. Itwould be unwise, for example, to call the fields of type point simply x and y.8.2.2 Extensible Records and Generic Operati<strong>on</strong>sNow, let us define coloured points (type cpoint) to be points extended witha field col of type colour:datatype colour = Red | Green | Bluerecord cpoint = point +col :: colourThe fields of this new type are Xcoord, Ycoord and col, in that order.definiti<strong>on</strong> cpt1 :: cpoint where"cpt1 ≡ (|Xcoord = 999, Ycoord = 23, col = Green|)"We can define generic operati<strong>on</strong>s that work <strong>on</strong> arbitrary instances of arecord scheme, e.g. covering point, cpoint, and any further extensi<strong>on</strong>s. Everyrecord structure has an implicit pseudo-field, more, that keeps the extensi<strong>on</strong>as an explicit value. Its type is declared as completely polymorphic: ’a. Whena fixed record value is expressed using just its standard fields, the value of


156 8. More about Typesmore is implicitly set to (), the empty tuple, which has type unit. Within therecord brackets, you can refer to the more field by writing “. . . ” (three dots):lemma "Xcoord (|Xcoord = a, Ycoord = b, . . . = p|) = a"by simpThis lemma applies to any record whose first two fields are Xcoordand Ycoord. Note that (|Xcoord = a, Ycoord = b, . . . = ()|) is exactly thesame as (|Xcoord = a, Ycoord = b|). Selectors and updates are always polymorphicwrt. the more part of a record scheme, its value is just ignored (forselect) or copied (for update).The more pseudo-field may be manipulated directly as well, but the identifierneeds to be qualified:lemma "point.more cpt1 = (|col = Green|)"by (simp add: cpt1_def)We see that the colour part attached to this point is a rudimentary recordin its own right, namely (|col = Green|). In order to select or update col, thisfragment needs to be put back into the c<strong>on</strong>text of the parent type scheme,say as more part of another point.To define generic operati<strong>on</strong>s, we need to know a bit more about records.Our definiti<strong>on</strong> of point above has generated two type abbreviati<strong>on</strong>s:point = (|Xcoord :: int, Ycoord :: int|)’a point_scheme = (|Xcoord :: int, Ycoord :: int, . . . :: ’a|)Type point is for fixed records having exactly the two fields Xcoord and Ycoord,while the polymorphic type ’a point_scheme comprises all possible extensi<strong>on</strong>sto those two fields. Note that unit point_scheme coincides with point, and(|col :: colour|) point_scheme with cpoint.In the following example we define two operati<strong>on</strong>s — methods, if we regardrecords as objects — to get and set any point’s Xcoord field.definiti<strong>on</strong> getX :: "’a point_scheme ⇒ int" where"getX r ≡ Xcoord r"definiti<strong>on</strong> setX :: "’a point_scheme ⇒ int ⇒ ’a point_scheme" where"setX r a ≡ r(|Xcoord := a|)"Here is a generic method that modifies a point, incrementing its Xcoordfield. The Ycoord and more fields are copied across. It works for any recordtype scheme derived from point (including cpoint etc.):definiti<strong>on</strong> incX :: "’a point_scheme ⇒ ’a point_scheme" where"incX r ≡(|Xcoord = Xcoord r + 1, Ycoord = Ycoord r, . . . = point.more r|)"Generic theorems can be proved about generic methods. This triviallemma relates incX to getX and setX:lemma "incX r = setX r (getX r + 1)"by (simp add: getX_def setX_def incX_def)


!!8.2 Records 157If you use the symbolic record brackets (| and |), then you must also use thesymbolic ellipsis, “. . . ”, rather than three c<strong>on</strong>secutive periods, “...”. Mixingthe ASCII and symbolic versi<strong>on</strong>s causes a syntax error. (The two versi<strong>on</strong>s are moredistinct <strong>on</strong> screen than they are <strong>on</strong> paper.)8.2.3 Record EqualityTwo records are equal if all pairs of corresp<strong>on</strong>ding fields are equal. C<strong>on</strong>creterecord equalities are simplified automatically:lemma "((|Xcoord = a, Ycoord = b|) = (|Xcoord = a’, Ycoord = b’|)) =(a = a’ ∧ b = b’)"by simpThe following equality is similar, but generic, in that r can be any instanceof ’a point_scheme:lemma "r(|Xcoord := a, Ycoord := b|) = r(|Ycoord := b, Xcoord := a|)"by simpWe see above the syntax for iterated updates. We could equivalently havewritten the left-hand side as r(|Xcoord := a|)(|Ycoord := b|).Record equality is extensi<strong>on</strong>al: a record is determined entirely by thevalues of its fields.lemma "r = (|Xcoord = Xcoord r, Ycoord = Ycoord r|)"by simpThe generic versi<strong>on</strong> of this equality includes the pseudo-field more:lemma "r = (|Xcoord = Xcoord r, Ycoord = Ycoord r, . . . = point.more r|)"by simpThe simplifier can prove many record equalities automatically, but generalequality reas<strong>on</strong>ing can be tricky. C<strong>on</strong>sider proving this obvious fact:lemma "r(|Xcoord := a|) = r(|Xcoord := a’|) =⇒ a = a’"apply simp?oopsHere the simplifier can do nothing, since general record equality is not eliminatedautomatically. One way to proceed is by an explicit forward step thatapplies the selector Xcoord to both sides of the assumed record equality:lemma "r(|Xcoord := a|) = r(|Xcoord := a’|) =⇒ a = a’"apply (drule_tac f = Xcoord in arg_c<strong>on</strong>g)1. Xcoord (r(|Xcoord := a|)) = Xcoord (r(|Xcoord := a’|)) =⇒ a = a’Now, simp will reduce the assumpti<strong>on</strong> to the desired c<strong>on</strong>clusi<strong>on</strong>.apply simpd<strong>on</strong>e


158 8. More about TypesThe cases method is preferable to such a forward proof. We state thedesired lemma again:lemma "r(|Xcoord := a|) = r(|Xcoord := a’|) =⇒ a = a’"The cases method adds an equality to replace the named record term byan explicit record expressi<strong>on</strong>, listing all fields. It even includes the pseudo-fieldmore, since the record equality stated here is generic for all extensi<strong>on</strong>s.apply (cases r)1. V Xcoord Ycoord more.[[r(|Xcoord := a|) = r(|Xcoord := a’|);r = (|Xcoord = Xcoord, Ycoord = Ycoord, . . . = more|)]]=⇒ a = a’Again, simp finishes the proof. Because r is now represented as an explicitrecord c<strong>on</strong>structi<strong>on</strong>, the updates can be applied and the record equality canbe replaced by equality of the corresp<strong>on</strong>ding fields (due to injectivity).apply simpd<strong>on</strong>eThe generic cases method does not admit references to locally boundparameters of a goal. In l<strong>on</strong>ger proof scripts <strong>on</strong>e might have to fall back <strong>on</strong>the primitive rule_tac used together with the internal field representati<strong>on</strong>rules of records. The above use of (cases r) would become (rule_tac r = rin point.cases_scheme).8.2.4 Extending and Truncating RecordsEach record declarati<strong>on</strong> introduces a number of derived operati<strong>on</strong>s to refercollectively to a record’s fields and to c<strong>on</strong>vert between fixed record types.They can, for instance, c<strong>on</strong>vert between types point and cpoint. We can adda colour to a point or c<strong>on</strong>vert a cpoint to a point by forgetting its colour.– Functi<strong>on</strong> make takes as arguments all of the record’s fields (including thoseinherited from ancestors). It returns the corresp<strong>on</strong>ding record.– Functi<strong>on</strong> fields takes the record’s very own fields and returns a recordfragment c<strong>on</strong>sisting of just those fields. This may be filled into the morepart of the parent record scheme.– Functi<strong>on</strong> extend takes two arguments: a record to be extended and a recordc<strong>on</strong>taining the new fields.– Functi<strong>on</strong> truncate takes a record (possibly an extensi<strong>on</strong> of the originalrecord type) and returns a fixed record, removing any additi<strong>on</strong>al fields.These functi<strong>on</strong>s provide useful abbreviati<strong>on</strong>s for standard record expressi<strong>on</strong>sinvolving c<strong>on</strong>structors and selectors. The definiti<strong>on</strong>s, which are not unfoldedby default, are made available by the collective name of defs (point.defs,


8.2 Records 159cpoint.defs, etc.). For example, here are the versi<strong>on</strong>s of those functi<strong>on</strong>s generatedfor record point. We omit point.fields, which happens to be the sameas point.make.point.make Xcoord Ycoord ≡ (|Xcoord = Xcoord, Ycoord = Ycoord|)point.extend r more ≡(|Xcoord = Xcoord r, Ycoord = Ycoord r, . . . = more|)point.truncate r ≡ (|Xcoord = Xcoord r, Ycoord = Ycoord r|)C<strong>on</strong>trast those with the corresp<strong>on</strong>ding functi<strong>on</strong>s for record cpoint. Observecpoint.fields in particular.cpoint.make Xcoord Ycoord col ≡(|Xcoord = Xcoord, Ycoord = Ycoord, col = col|)cpoint.fields col ≡ (|col = col|)cpoint.extend r more ≡(|Xcoord = Xcoord r, Ycoord = Ycoord r, col = col r, . . . = more|)cpoint.truncate r ≡(|Xcoord = Xcoord r, Ycoord = Ycoord r, col = col r|)To dem<strong>on</strong>strate these functi<strong>on</strong>s, we declare a new coloured point byextending an ordinary point. Functi<strong>on</strong> point.extend augments pt1 with acolour value, which is c<strong>on</strong>verted into an appropriate record fragment bycpoint.fields.definiti<strong>on</strong> cpt2 :: cpoint where"cpt2 ≡ point.extend pt1 (cpoint.fields Green)"The coloured points cpt1 and cpt2 are equal. The proof is trivial, byunfolding all the definiti<strong>on</strong>s. We deliberately omit the definiti<strong>on</strong> of pt1 inorder to reveal the underlying comparis<strong>on</strong> <strong>on</strong> type point.lemma "cpt1 = cpt2"apply (simp add: cpt1_def cpt2_def point.defs cpoint.defs)1. Xcoord pt1 = 999 ∧ Ycoord pt1 = 23apply (simp add: pt1_def)d<strong>on</strong>eIn the example below, a coloured point is truncated to leave a point. Weuse the truncate functi<strong>on</strong> of the target record.lemma "point.truncate cpt2 = pt1"by (simp add: pt1_def cpt2_def point.defs)Exercise 8.2.1 Extend record cpoint to have a further field, intensity, oftype nat. Experiment with generic operati<strong>on</strong>s (using polymorphic selectorsand updates) and explicit coerci<strong>on</strong>s (using extend, truncate etc.) am<strong>on</strong>g thethree record types.Exercise 8.2.2 (For Java programmers.) Model a small class hierarchy usingrecords.


160 8. More about Types8.3 Axiomatic Type ClassesThe programming language Haskell has popularized the noti<strong>on</strong> of typeclasses. In its simplest form, a type class is a set of types with a comm<strong>on</strong>interface: all types in that class must provide the functi<strong>on</strong>s in the interface.<strong>Isabelle</strong> offers the related c<strong>on</strong>cept of an axiomatic type class. Roughlyspeaking, an axiomatic type class is a type class with axioms, i.e. an axiomaticspecificati<strong>on</strong> of a class of types. Thus we can talk about a type τbeing in a class C , which is written τ :: C . This is the case if τ satisfies theaxioms of C . Furthermore, type classes can be organized in a hierarchy. Thusthere is the noti<strong>on</strong> of a class D being a subclass of a class C , written D < C .This is the case if all axioms of C are also provable in D. We introduce thesec<strong>on</strong>cepts by means of a running example, ordering relati<strong>on</strong>s.!!The material in this secti<strong>on</strong> describes a low-level approach to type classes. Itis recommended to use the new class command instead. For details see theappropriate tutorial [12] and the related article [13].8.3.1 OverloadingWe start with a c<strong>on</strong>cept that is required for type classes but already useful<strong>on</strong> its own: overloading. <strong>Isabelle</strong> allows overloading: a c<strong>on</strong>stant may havemultiple definiti<strong>on</strong>s at n<strong>on</strong>-overlapping types.An Initial Example. If we want to introduce the noti<strong>on</strong> of an inverse forarbitrary types we give it a polymorphic typec<strong>on</strong>sts inverse :: "’a ⇒ ’a"and provide different definiti<strong>on</strong>s at different instances:defs (overloaded)inverse_bool: "inverse(b::bool) ≡ ¬ b"inverse_set: "inverse(A::’a set) ≡ -A"inverse_pair: "inverse(p) ≡ (inverse(fst p), inverse(snd p))"<strong>Isabelle</strong> will not complain because the three definiti<strong>on</strong>s do not overlap: notwo of the three types bool, ’a set and ’a × ’b have a comm<strong>on</strong> instance.What is more, the recursi<strong>on</strong> in inverse_pair is benign because the type ofinverse becomes smaller: <strong>on</strong> the left it is ’a × ’b ⇒ ’a × ’b but <strong>on</strong> theright ’a ⇒ ’a and ’b ⇒ ’b. The annotati<strong>on</strong> (overloaded) tells <strong>Isabelle</strong>that the definiti<strong>on</strong>s do intenti<strong>on</strong>ally define inverse <strong>on</strong>ly at instances of itsdeclared type ’a ⇒ ’a — this merely suppresses warnings to that effect.However, there is nothing to prevent the user from forming terms suchas inverse [] and proving theorems such as inverse [] = inverse [] wheninverse is not defined <strong>on</strong> lists. Proving theorems about unspecified c<strong>on</strong>stantsdoes not endanger soundness, but it is pointless. To prevent such terms fromeven being formed requires the use of type classes.


8.3 Axiomatic Type Classes 161C<strong>on</strong>trolled Overloading with Type Classes. We now start with thetheory of ordering relati<strong>on</strong>s, which we shall phrase in terms of the two binarysymbols


162 8. More about Typesprefix_def:"xs


8.3 Axiomatic Type Classes 163restricted the axioms to class parord. For example, the axiom refl really is(?x::?’a::parord)


164 8. More about TypesLinear Orders. If any two elements of a partial order are comparable it isa linear or total order:axclass linord < parordlinear: "x


8.3 Axiomatic Type Classes 165axclass wellord < linord, wfordThe last line expresses the usual definiti<strong>on</strong>: a well-ordering is a linear wellfoundedordering. The result is the subclass diagram in Figure 8.1.Figure 8.1. Subclass Diagramlinordtype|ordrel|strord|parord/ \\ /wellordwfordSince class wellord does not introduce any new axioms, it can simply beviewed as the intersecti<strong>on</strong> of the two classes linord and wford. Such intersecti<strong>on</strong>sneed not be given a new name but can be created <strong>on</strong> the fly: theexpressi<strong>on</strong> {C 1 , . . . , C n }, where the C i are classes, represents the intersecti<strong>on</strong>of the C i . Such an expressi<strong>on</strong> is called a sort, and sorts can appear inmost places where we have <strong>on</strong>ly shown classes so far, for example in typec<strong>on</strong>straints: ’a::{linord,wford}. In fact, ’a::C is short for ’a::{C}. However,we do not pursue this rarefied c<strong>on</strong>cept further.This c<strong>on</strong>cludes our dem<strong>on</strong>strati<strong>on</strong> of type classes based <strong>on</strong> orderings. Weremind our readers that Main c<strong>on</strong>tains a theory of orderings phrased in termsof the usual ≤ and


166 8. More about Types8.4 NumbersUntil now, our numerical examples have used the type of natural numbers,nat. This is a recursive datatype generated by the c<strong>on</strong>structors zeroand successor, so it works well with inductive proofs and primitive recursivefuncti<strong>on</strong> definiti<strong>on</strong>s. <strong>HOL</strong> also provides the type int of integers, which lackinducti<strong>on</strong> but support true subtracti<strong>on</strong>. With subtracti<strong>on</strong>, arithmetic reas<strong>on</strong>ingis easier, which makes the integers preferable to the natural numbers forcomplicated arithmetic expressi<strong>on</strong>s, even if they are n<strong>on</strong>-negative. The logic<strong>HOL</strong>-Complex also has the types rat, real and complex: the rati<strong>on</strong>al, realand complex numbers. <strong>Isabelle</strong> has no subtyping, so the numeric types aredistinct and there are functi<strong>on</strong>s to c<strong>on</strong>vert between them. Most numeric operati<strong>on</strong>sare overloaded: the same symbol can be used at all numeric types.Table A.2 in the appendix shows the most important operati<strong>on</strong>s, togetherwith the priorities of the infix symbols. Algebraic properties are organizedusing type classes around algebraic c<strong>on</strong>cepts such as rings and fields; a propertysuch as the commutativity of additi<strong>on</strong> is a single theorem (add_commute)that applies to all numeric types.Many theorems involving numeric types can be proved automatically by<strong>Isabelle</strong>’s arithmetic decisi<strong>on</strong> procedure, the method arith. Linear arithmeticcomprises additi<strong>on</strong>, subtracti<strong>on</strong> and multiplicati<strong>on</strong> by c<strong>on</strong>stant factors; subtermsinvolving other operators are regarded as variables. The procedure canbe slow, especially if the subgoal to be proved involves subtracti<strong>on</strong> over typenat, which causes case splits. On types nat and int, arith can deal withquantifiers—this is known as Presburger arithmetic—whereas <strong>on</strong> type realit cannot.The simplifier reduces arithmetic expressi<strong>on</strong>s in other ways, such as dividingthrough by comm<strong>on</strong> factors. For problems that lie outside the scopeof automati<strong>on</strong>, <strong>HOL</strong> provides hundreds of theorems about multiplicati<strong>on</strong>, divisi<strong>on</strong>,etc., that can be brought to bear. You can locate them using ProofGeneral’s Find butt<strong>on</strong>. A few lemmas are given below to show what is available.8.4.1 Numeric LiteralsThe c<strong>on</strong>stants 0 and 1 are overloaded. They denote zero and <strong>on</strong>e, respectively,for all numeric types. Other values are expressed by numeric literals, whichc<strong>on</strong>sist of <strong>on</strong>e or more decimal digits opti<strong>on</strong>ally preceeded by a minus sign(-). Examples are 2, -3 and 441223334678. Literals are available for the typesof natural numbers, integers, rati<strong>on</strong>als, reals, etc.; they denote integer valuesof arbitrary size.Literals look like c<strong>on</strong>stants, but they abbreviate terms representing thenumber in a two’s complement binary notati<strong>on</strong>. <strong>Isabelle</strong> performs arithmetic<strong>on</strong> literals by rewriting rather than using the hardware arithmetic. In most


8.4 Numbers 167cases arithmetic is fast enough, even for numbers in the milli<strong>on</strong>s. The arithmeticoperati<strong>on</strong>s provided for literals include additi<strong>on</strong>, subtracti<strong>on</strong>, multiplicati<strong>on</strong>,integer divisi<strong>on</strong> and remainder. Fracti<strong>on</strong>s of literals (expressed usingdivisi<strong>on</strong>) are reduced to lowest terms.!!The arithmetic operators are overloaded, so you must be careful to ensure thateach numeric expressi<strong>on</strong> refers to a specific type, if necessary by inserting typec<strong>on</strong>straints. Here is an example of what can go wr<strong>on</strong>g:lemma "2 * m = m + m"Carefully observe how <strong>Isabelle</strong> displays the subgoal:1. (2::’a) * m = m + mThe type ’a given for the literal 2 warns us that no numeric type has been specified.The problem is underspecified. Given a type c<strong>on</strong>straint such as nat, int or real,it becomes trivial.!!Numeric literals are not c<strong>on</strong>structors and therefore must not be used in patterns.For example, this declarati<strong>on</strong> is rejected:recdef h "{}""h 3 = 2""h i = i"You should use a c<strong>on</strong>diti<strong>on</strong>al expressi<strong>on</strong> instead:"h i = (if i = 3 then 2 else i)"8.4.2 The Type of Natural Numbers, natThis type requires no introducti<strong>on</strong>: we have been using it from the beginning.Hundreds of theorems about the natural numbers are proved in the theoriesNat and Divides. Basic properties of additi<strong>on</strong> and multiplicati<strong>on</strong> are availablethrough the axiomatic type class for semirings (Sect. 8.4.5).Literals. The notati<strong>on</strong>al opti<strong>on</strong>s for the natural numbers are c<strong>on</strong>fusing. Recallthat an overloaded c<strong>on</strong>stant can be defined independently for each type;the definiti<strong>on</strong> of 1 for type nat is1 ≡ Suc 0 (One_nat_def)This is installed as a simplificati<strong>on</strong> rule, so the simplifier will replace everyoccurrence of 1::nat by Suc 0. Literals are obviously better than nested Sucsat expressing large values. But many theorems, including the rewrite rulesfor primitive recursive functi<strong>on</strong>s, can <strong>on</strong>ly be applied to terms of the formSuc n.The following default simplificati<strong>on</strong> rules replace small literals by zero andsuccessor:


168 8. More about Types2 + n = Suc (Suc n) (add_2_eq_Suc)n + 2 = Suc (Suc n)(add_2_eq_Suc’)It is less easy to transform 100 into Suc 99 (for example), and the simplifierwill normally reverse this transformati<strong>on</strong>. Novices should express naturalnumbers using 0 and Suc <strong>on</strong>ly.Divisi<strong>on</strong>. The infix operators div and mod are overloaded. <strong>Isabelle</strong>/<strong>HOL</strong>provides the basic facts about quotient and remainder <strong>on</strong> the natural numbers:m mod n = (if m < n then m else (m - n) mod n)m div n * n + m mod n = m(mod_if)(mod_div_equality)Many less obvious facts about quotient and remainder are also provided.Here is a selecti<strong>on</strong>:a * b div c = a * (b div c) + a * (b mod c) div c (div_mult1_eq)a * b mod c = a * (b mod c) mod c(mod_mult_right_eq)a div (b*c) = a div b div c(div_mult2_eq)a mod (b*c) = b * (a div b mod c) + a mod b(mod_mult2_eq)0 < c =⇒ (c * a) div (c * b) = a div b (div_mult_mult1)(m mod n) * k = (m * k) mod (n * k) (mod_mult_distrib)m ≤ n =⇒ m div k ≤ n div k(div_le_m<strong>on</strong>o)Surprisingly few of these results depend up<strong>on</strong> the divisors’ being n<strong>on</strong>zero.That is because divisi<strong>on</strong> by zero yields zero:a div 0 = 0a mod 0 = a(DIVISION_BY_ZERO_DIV)(DIVISION_BY_ZERO_MOD)In div_mult_mult1 above, <strong>on</strong>e of the two divisors (namely c) must still ben<strong>on</strong>zero.The divides relati<strong>on</strong> has the standard definiti<strong>on</strong>, which is overloaded overall numeric types:m dvd n ≡ ∃ k. n = m * k(dvd_def)Secti<strong>on</strong> 5.18 discusses proofs involving this relati<strong>on</strong>. Here are some of thefacts proved about it:[[m dvd n; n dvd m]] =⇒ m = n[[k dvd m; k dvd n]] =⇒ k dvd (m + n)(dvd_anti_sym)(dvd_add)Subtracti<strong>on</strong>. There are no negative natural numbers, so m - n equals zerounless m exceeds n. The following is <strong>on</strong>e of the few facts about m - n that isnot subject to the c<strong>on</strong>diti<strong>on</strong> n ≤ m.(m - n) * k = m * k - n * k (diff_mult_distrib)Natural number subtracti<strong>on</strong> has few nice properties; often you should removeit by simplifying with this split rule.P(a-b) = ((a


8.4 Numbers 169lemma "(n - 2) * (n + 2) = n * n - (4::nat)"apply (simp split: nat_diff_split, clarify)1. V d. [[n < 2; n * n = 4 + d]] =⇒ d = 0The result lies outside the scope of linear arithmetic, but it is easily found ifwe explicitly split n


170 8. More about Typeswhen the left-hand side of zdiv_zmult2_eq is −2 while the right-hand sideis −1. The prefix z in many theorem names recalls the use of Z to denote theset of integers.Inducti<strong>on</strong> is less important for integers than it is for the natural numbers,but it can be valuable if the range of integers has a lower or upper bound.There are four rules for integer inducti<strong>on</strong>, corresp<strong>on</strong>ding to the possible relati<strong>on</strong>sof the bound (≥, >, ≤ and Logics > <strong>HOL</strong>-Complex.Also available in <strong>HOL</strong>-Complex is the theory Hyperreal, which define thetype hypreal of n<strong>on</strong>-standard reals. These hyperreals include infinitesimals,which represent infinitely small and infinitely large quantities; they facilitateproofs about limits, differentiati<strong>on</strong> and integrati<strong>on</strong> [9]. The development definesan infinitely large number, omega and an infinitely small positive number,epsil<strong>on</strong>. The relati<strong>on</strong> x ≈ y means “x is infinitely close to y.” Theory


8.4 Numbers 171Hyperreal also defines transcendental functi<strong>on</strong>s such as sine, cosine, exp<strong>on</strong>entialand logarithm — even the versi<strong>on</strong>s for type real, because they aredefined using n<strong>on</strong>standard limits.8.4.5 The Numeric Type Classes<strong>Isabelle</strong>/<strong>HOL</strong> organises its numeric theories using axiomatic type classes.Hundreds of basic properties are proved in the theory Ring_and_Field. Theselemmas are available (as simprules if they were declared as such) for allnumeric types satisfying the necessary axioms. The theory defines dozens oftype classes, such as the following:– semiring and ordered_semiring: a semiring provides the associative operators+ and *, with 0 and 1 as their respective identities. The operatorsenjoy the usual distributive law, and additi<strong>on</strong> (+) is also commutative. Anordered semiring is also linearly ordered, with additi<strong>on</strong> and multiplicati<strong>on</strong>respecting the ordering. Type nat is an ordered semiring.– ring and ordered_ring: a ring extends a semiring with unary minus (theadditive inverse) and subtracti<strong>on</strong> (both denoted -). An ordered ring includesthe absolute value functi<strong>on</strong>, abs. Type int is an ordered ring.– field and ordered_field: a field extends a ring with the multiplicativeinverse (called simply inverse and divisi<strong>on</strong> (/)). An ordered field is based<strong>on</strong> an ordered ring. Type complex is a field, while type real is an orderedfield.– divisi<strong>on</strong>_by_zero includes all types where inverse 0 = 0 and a / 0 = 0.These include all of <strong>Isabelle</strong>’s standard numeric types. However, the basicproperties of fields are derived without assuming divisi<strong>on</strong> by zero.Hundreds of basic lemmas are proved, each of which holds for all types inthe corresp<strong>on</strong>ding type class. In most cases, it is obvious whether a propertyis valid for a particular type. No abstract properties involving subtracti<strong>on</strong>hold for type nat; instead, theorems such as diff_mult_distrib are provedspecifically about subtracti<strong>on</strong> <strong>on</strong> type nat. All abstract properties involvingdivisi<strong>on</strong> require a field. Obviously, all properties involving orderings requiredan ordered structure.The class ring_no_zero_divisors of rings without zero divisors satisfiesa number of natural cancellati<strong>on</strong> laws, the first of which characterizes thisclass:(a * b = (0::’a)) = (a = (0::’a) ∨ b = (0::’a)) (mult_eq_0_iff)(a * c = b * c) = (c = (0::’a) ∨ a = b) (mult_cancel_right)Setting the flag <strong>Isabelle</strong> > Settings > Show Sorts will display the type classes ofall type variables.Here is how the theorem mult_cancel_left appears with the flag set.


172 8. More about Types((c::’a::ring_no_zero_divisors) * (a::’a::ring_no_zero_divisors) =c * (b::’a::ring_no_zero_divisors)) =(c = (0::’a::ring_no_zero_divisors) ∨ a = b)Simplifying with the AC-Laws. Suppose that two expressi<strong>on</strong>s are equal,differing <strong>on</strong>ly in associativity and commutativity of additi<strong>on</strong>. Simplifying withthe following equati<strong>on</strong>s sorts the terms and groups them to the right, makingthe two expressi<strong>on</strong>s identical.a + b + c = a + (b + c)a + b = b + aa + (b + c) = b + (a + c)(add_assoc)(add_commute)(add_left_commute)The name add_ac refers to the list of all three theorems; similarly there ismult_ac. They are all proved for semirings and therefore hold for all numerictypes.Here is an example of the sorting effect. Start with this goal, which involvestype nat.1. Suc (i + j * l * k + m * n) = f (n * m + i + k * j * l)Simplify using add_ac and mult_ac.apply (simp add: add_ac mult_ac)Here is the resulting subgoal.1. Suc (i + (m * n + j * (k * l))) = f (i + (m * n + j * (k * l)))Divisi<strong>on</strong> Laws for Fields. Here is a selecti<strong>on</strong> of rules about the divisi<strong>on</strong>operator. The following are installed as default simplificati<strong>on</strong> rules in orderto express combinati<strong>on</strong>s of products and quotients as rati<strong>on</strong>al expressi<strong>on</strong>s:a * (b / c) = a * b / cb / c * a = b * a / ca / (b / c) = a * c / ba / b / c = a / (b * c)(times_divide_eq_right)(times_divide_eq_left)(divide_divide_eq_right)(divide_divide_eq_left)Signs are extracted from quotients in the hope that complementary termscan then be cancelled:- (a / b) = - a / b (minus_divide_left)- (a / b) = a / - b (minus_divide_right)The following distributive law is available, but it is not installed as asimplificati<strong>on</strong> rule.(a + b) / c = a / c + b / c (add_divide_distrib)Absolute Value. The absolute value functi<strong>on</strong> abs is available for all orderedrings, including types int, rat and real. It satisfies many properties, such asthe following:|x * y| = |x| * |y| (abs_mult)(|a| ≤ b) = (a ≤ b ∧ - a ≤ b)(abs_le_iff)|a + b| ≤ |a| + |b| (abs_triangle_ineq)


!!8.5 Introducing New Types 173The absolute value bars shown above cannot be typed <strong>on</strong> a keyboard. They canbe entered using the X-symbol package. In ascii, type abs x to get |x|.Raising to a Power. Another type class, ringppower, specifies rings thatalso have exp<strong>on</strong>entati<strong>on</strong> to a natural number power, defined using the obviousprimitive recursi<strong>on</strong>. Theory Power proves various theorems, such as thefollowing.a ^ (m + n) = a ^ m * a ^ n(power_add)a ^ (m * n) = (a ^ m) ^ n(power_mult)|a ^ n| = |a| ^ n (power_abs)8.5 Introducing New TypesFor most applicati<strong>on</strong>s, a combinati<strong>on</strong> of predefined types like bool and ⇒with recursive datatypes and records is quite sufficient. Very occasi<strong>on</strong>allyyou may feel the need for a more advanced type. If you are certain that yourtype is not definable by any of the standard means, then read <strong>on</strong>.!!Types in <strong>HOL</strong> must be n<strong>on</strong>-empty; otherwise the quantifier rules would beunsound, because ∃x. x = x is a theorem.8.5.1 Declaring New TypesThe most trivial way of introducing a new type is by a type declarati<strong>on</strong>:typedecl my_new_typeThis does not define my_new_type at all but merely introduces its name. Thuswe know nothing about this type, except that it is n<strong>on</strong>-empty. Such declarati<strong>on</strong>swithout definiti<strong>on</strong>s are useful if that type can be viewed as a parameterof the theory. A typical example is given in Sect. 6.6, where we define a transiti<strong>on</strong>relati<strong>on</strong> over an arbitrary type of states.In principle we can always get rid of such type declarati<strong>on</strong>s by makingthose types parameters of every other type, thus keeping the theory generic.In practice, however, the resulting clutter can make types hard to read.If you are looking for a quick and dirty way of introducing a new type togetherwith its properties: declare the type and state its properties as axioms.Example:axiomsjust_<strong>on</strong>e: "∃ x::my_new_type. ∀ y. x = y"However, we str<strong>on</strong>gly discourage this approach, except at explorative stagesof your development. It is extremely easy to write down c<strong>on</strong>tradictory setsof axioms, in which case you will be able to prove everything but it willmean nothing. In the example above, the axiomatic approach is unnecessary:a <strong>on</strong>e-element type called unit is already defined in <strong>HOL</strong>.


174 8. More about Types8.5.2 Defining New TypesNow we come to the most general means of safely introducing a new type,the type definiti<strong>on</strong>. All other means, for example datatype, are based <strong>on</strong>it. The principle is extremely simple: any n<strong>on</strong>-empty subset of an existingtype can be turned into a new type. More precisely, the new type is specifiedto be isomorphic to some n<strong>on</strong>-empty subset of an existing type.Let us work a simple example, the definiti<strong>on</strong> of a three-element type. Itis easily represented by the first three natural numbers:typedef three = "{0::nat, 1, 2}"In order to enforce that the representing set <strong>on</strong> the right-hand side is n<strong>on</strong>empty,this definiti<strong>on</strong> actually starts a proof to that effect:1. ∃ x. x ∈ {0, 1, 2}Fortunately, this is easy enough to show, even auto could do it. In general,<strong>on</strong>e has to provide a witness, in our case 0:apply(rule_tac x = 0 in exI)by simpThis type definiti<strong>on</strong> introduces the new type three and asserts that it is acopy of the set {0, 1, 2}. This asserti<strong>on</strong> is expressed via a bijecti<strong>on</strong> betweenthe type three and the set {0, 1, 2}. To this end, the command declares thefollowing c<strong>on</strong>stants behind the scenes:three :: nat setRep_three :: three ⇒ natAbs_three :: nat ⇒ threewhere c<strong>on</strong>stant three is explicitly defined as the representing set:three ≡ {0, 1, 2}(three_def)The situati<strong>on</strong> is best summarized with the help of the following diagram,where squares denote types and the irregular regi<strong>on</strong> denotes a set:natthree{0,1,2}Finally, typedef asserts that Rep_three is surjective <strong>on</strong> the subset three andAbs_three and Rep_three are inverses of each other:


Rep_three x ∈ threeAbs_three (Rep_three x) = xy ∈ three =⇒ Rep_three (Abs_three y) = y8.5 Introducing New Types 175(Rep_three)(Rep_three_inverse)(Abs_three_inverse)From this example it should be clear what typedef does in general given aname (here three) and a set (here {0, 1, 2}).Our next step is to define the basic functi<strong>on</strong>s expected <strong>on</strong> the new type.Although this depends <strong>on</strong> the type at hand, the following strategy works well:– define a small kernel of basic functi<strong>on</strong>s that can express all other functi<strong>on</strong>syou anticipate.– define the kernel in terms of corresp<strong>on</strong>ding functi<strong>on</strong>s <strong>on</strong> the representingtype using Abs and Rep to c<strong>on</strong>vert between the two levels.In our example it suffices to give the three elements of type three names:definiti<strong>on</strong> A :: three where "A ≡ Abs_three 0"definiti<strong>on</strong> B :: three where "B ≡ Abs_three 1"definiti<strong>on</strong> C :: three where "C ≡ Abs_three 2"So far, everything was easy. But it is clear that reas<strong>on</strong>ing about threewill be hell if we have to go back to nat every time. Thus our aim must be toraise our level of abstracti<strong>on</strong> by deriving enough theorems about type threeto characterize it completely. And those theorems should be phrased in termsof A, B and C, not Abs_three and Rep_three. Because of the simplicity of theexample, we merely need to prove that A, B and C are distinct and that theyexhaust the type.In processing our typedef declarati<strong>on</strong>, <strong>Isabelle</strong> proves several helpful lemmas.The first two express injectivity of Rep_three and Abs_three:(Rep_three x = Rep_three y) = (x = y)[[x ∈ three; y ∈ three ]]=⇒ (Abs_three x = Abs_three y) = (x = y)(Rep_three_inject)(Abs_three_inject)The following <strong>on</strong>es allow to replace some x::three by Abs_three(y::nat), andc<strong>on</strong>versely y by Rep_three x:[[y ∈ three; V x. y = Rep_three x =⇒ P]] =⇒ P (Rep_three_cases)( V y. [[x = Abs_three y; y ∈ three]] =⇒ P) =⇒ P (Abs_three_cases)[[y ∈ three; V x. P (Rep_three x)]] =⇒ P y (Rep_three_induct)( V y. y ∈ three =⇒ P (Abs_three y)) =⇒ P x (Abs_three_induct)These theorems are proved for any type definiti<strong>on</strong>, with three replaced bythe name of the type in questi<strong>on</strong>.Distinctness of A, B and C follows immediately if we expand their definiti<strong>on</strong>sand rewrite with the injectivity of Abs_three:lemma "A ≠ B ∧ B ≠ A ∧ A ≠ C ∧ C ≠ A ∧ B ≠ C ∧ C ≠ B"by(simp add: Abs_three_inject A_def B_def C_def three_def)Of course we rely <strong>on</strong> the simplifier to solve goals like 0 ≠ 1.


176 8. More about TypesThe fact that A, B and C exhaust type three is best phrased as a casedistincti<strong>on</strong> theorem: if you want to prove P x (where x is of type three) itsuffices to prove P A, P B and P C:lemma three_cases: "[[ P A; P B; P C ]] =⇒ P x"Again this follows easily using the inducti<strong>on</strong> principle stemming from thetype definiti<strong>on</strong>:apply(induct_tac x)1. V y. [[P A; P B; P C; y ∈ three]] =⇒ P (Abs_three y)Simplificati<strong>on</strong> with three_def leads to the disjuncti<strong>on</strong> y = 0 ∨ y = 1 ∨ y =2 which auto separates into three subgoals, each of which is easily solved bysimplificati<strong>on</strong>:apply(auto simp add: three_def A_def B_def C_def)d<strong>on</strong>eThis c<strong>on</strong>cludes the derivati<strong>on</strong> of the characteristic theorems for type three.The attentive reader has realized l<strong>on</strong>g ago that the above lengthy definiti<strong>on</strong>can be collapsed into <strong>on</strong>e line:datatype better_three = A | B | CIn fact, the datatype command performs internally more or less the samederivati<strong>on</strong>s as we did, which gives you some idea what life would be likewithout datatype.Although three could be defined in <strong>on</strong>e line, we have chosen this exampleto dem<strong>on</strong>strate typedef because its simplicity makes the key c<strong>on</strong>ceptsparticularly easy to grasp. If you would like to see a n<strong>on</strong>-trivial examplethat cannot be defined more directly, we recommend the definiti<strong>on</strong> of finitemultisets in the Library [4].Let us c<strong>on</strong>clude by summarizing the above procedure for defining a newtype. Given some abstract axiomatic descripti<strong>on</strong> P of a type ty in terms ofa set of functi<strong>on</strong>s F , this involves three steps:1. Find an appropriate type τ and subset A which has the desired propertiesP, and make a type definiti<strong>on</strong> based <strong>on</strong> this representati<strong>on</strong>.2. Define the required functi<strong>on</strong>s F <strong>on</strong> ty by lifting analogous functi<strong>on</strong>s <strong>on</strong>the representati<strong>on</strong> via Abs ty and Rep ty.3. Prove that P holds for ty by lifting P from the representati<strong>on</strong>.You can now forget about the representati<strong>on</strong> and work solely in terms of theabstract functi<strong>on</strong>s F and properties P.


9. Advanced Simplificati<strong>on</strong> and Inducti<strong>on</strong>Although we have already learned a lot about simplificati<strong>on</strong> and inducti<strong>on</strong>,there are some advanced proof techniques that we have not covered yet andwhich are worth learning. The secti<strong>on</strong>s of this chapter are independent ofeach other and can be read in any order.9.1 Simplificati<strong>on</strong>This secti<strong>on</strong> describes features not covered until now. It also outlines thesimplificati<strong>on</strong> process itself, which can be helpful when the simplifier doesnot do what you expect of it.9.1.1 Advanced FeaturesC<strong>on</strong>gruence Rules. While simplifying the c<strong>on</strong>clusi<strong>on</strong> Q of P =⇒ Q, it islegal to use the assumpti<strong>on</strong> P. For =⇒ this policy is hardwired, but c<strong>on</strong>textualinformati<strong>on</strong> can also be made available for other operators. For example, xs= [] −→ xs @ xs = xs simplifies to True because we may use xs = [] whensimplifying xs @ xs = xs. The generati<strong>on</strong> of c<strong>on</strong>textual informati<strong>on</strong> duringsimplificati<strong>on</strong> is c<strong>on</strong>trolled by so-called c<strong>on</strong>gruence rules. This is the <strong>on</strong>efor −→:[[P = P’; P’ =⇒ Q = Q’]] =⇒ (P −→ Q) = (P’ −→ Q’)It should be read as follows: In order to simplify P −→ Q to P’ −→ Q’,simplify P to P’ and assume P’ when simplifying Q to Q’.Here are some more examples. The c<strong>on</strong>gruence rules for bounded quantifierssupply c<strong>on</strong>textual informati<strong>on</strong> about the bound variable:[[A = B; V x. x ∈ B =⇒ P x = Q x]]=⇒ (∀ x∈A. P x) = (∀ x∈B. Q x)One c<strong>on</strong>gruence rule for c<strong>on</strong>diti<strong>on</strong>al expressi<strong>on</strong>s supplies c<strong>on</strong>textual informati<strong>on</strong>for simplifying the then and else cases:[[b = c; c =⇒ x = u; ¬ c =⇒ y = v]]=⇒ (if b then x else y) = (if c then u else v)


178 9. Advanced Simplificati<strong>on</strong> and Inducti<strong>on</strong>An alternative c<strong>on</strong>gruence rule for c<strong>on</strong>diti<strong>on</strong>al expressi<strong>on</strong>s actually preventssimplificati<strong>on</strong> of some arguments:b = c =⇒ (if b then x else y) = (if c then x else y)Only the first argument is simplified; the others remain unchanged. Thismakes simplificati<strong>on</strong> much faster and is faithful to the evaluati<strong>on</strong> strategy inprogramming languages, which is why this is the default c<strong>on</strong>gruence rule forif. Analogous rules c<strong>on</strong>trol the evaluati<strong>on</strong> of case expressi<strong>on</strong>s.You can declare your own c<strong>on</strong>gruence rules with the attribute c<strong>on</strong>g, eitherglobally, in the usual manner,declare theorem-name [c<strong>on</strong>g]or locally in a simp call by adding the modifierc<strong>on</strong>g: list of theorem namesThe effect is reversed by c<strong>on</strong>g del instead of c<strong>on</strong>g.!!The c<strong>on</strong>gruence rule c<strong>on</strong>j_c<strong>on</strong>g[[P = P’; P’ =⇒ Q = Q’]] =⇒ (P ∧ Q) = (P’ ∧ Q’)is occasi<strong>on</strong>ally useful but is not a default rule; you have to declare it explicitly.Permutative Rewrite Rules. An equati<strong>on</strong> is a permutative rewriterule if the left-hand side and right-hand side are the same up to renaming ofvariables. The most comm<strong>on</strong> permutative rule is commutativity: x + y = y +x. Other examples include x - y - z = x - z - y in arithmetic and insert x(insert y A) = insert y (insert x A) for sets. Such rules are problematicbecause <strong>on</strong>ce they apply, they can be used forever. The simplifier is aware ofthis danger and treats permutative rules by means of a special strategy, calledordered rewriting: a permutative rewrite rule is <strong>on</strong>ly applied if the termbecomes smaller with respect to a fixed lexicographic ordering <strong>on</strong> terms. Forexample, commutativity rewrites b + a to a + b, but then stops because a +b is strictly smaller than b + a. Permutative rewrite rules can be turned intosimplificati<strong>on</strong> rules in the usual manner via the simp attribute; the simplifierrecognizes their special status automatically.Permutative rewrite rules are most effective in the case of associativecommutativefuncti<strong>on</strong>s. (Associativity by itself is not permutative.) Whendealing with an AC-functi<strong>on</strong> f , keep the following points in mind:– The associative law must always be oriented from left to right, namelyf (f (x, y), z) = f (x, f (y, z)). The opposite orientati<strong>on</strong>, if used with commutativity,can lead to n<strong>on</strong>terminati<strong>on</strong>.– To complete your set of rewrite rules, you must add not just associativity(A) and commutativity (C) but also a derived rule, left-commutativity(LC): f (x, f (y, z)) = f (y, f (x, z)).


9.1 Simplificati<strong>on</strong> 179Ordered rewriting with the combinati<strong>on</strong> of A, C, and LC sorts a term lexicographically:f (f (b, c), a)A f (b, f (c, a))C f (b, f (a, c)) LC f (a, f (b, c))Note that ordered rewriting for + and * <strong>on</strong> numbers is rarely necessarybecause the built-in arithmetic prover often succeeds without such tricks.9.1.2 How the Simplifier WorksRoughly speaking, the simplifier proceeds bottom-up: subterms are simplifiedfirst. A c<strong>on</strong>diti<strong>on</strong>al equati<strong>on</strong> is <strong>on</strong>ly applied if its c<strong>on</strong>diti<strong>on</strong> can be proved,again by simplificati<strong>on</strong>. Below we explain some special features of the rewritingprocess.Higher-Order Patterns. So far we have pretended the simplifier can dealwith arbitrary rewrite rules. This is not quite true. For reas<strong>on</strong>s of feasibility,the simplifier expects the left-hand side of each rule to be a so-called higherorderpattern [25]. This restricts where unknowns may occur. Higher-orderpatterns are terms in β-normal form. (This means there are no subtermsof the form (λx.M )(N ).) Each occurrence of an unknown is of the form?f x 1 . . . x n , where the x i are distinct bound variables. Thus all ordinaryrewrite rules, where all unknowns are of base type, for example ?a + ?b + ?c= ?a + (?b + ?c), are acceptable: if an unknown is of base type, it cannothave any arguments. Additi<strong>on</strong>ally, the rule (∀ x. ?P x ∧ ?Q x) = ((∀ x. ?Px) ∧ (∀ x. ?Q x)) is also acceptable, in both directi<strong>on</strong>s: all arguments of theunknowns ?P and ?Q are distinct bound variables.If the left-hand side is not a higher-order pattern, all is not lost. Thesimplifier will still try to apply the rule provided it matches directly: withoutmuch λ-calculus hocus pocus. For example, (?f ?x ∈ range ?f) = Truerewrites g a ∈ range g to True, but will fail to match g(h b) ∈ range(λx.g(h x)). However, you can eliminate the offending subterms — those that arenot patterns — by adding new variables and c<strong>on</strong>diti<strong>on</strong>s. In our example, weeliminate ?f ?x and obtain ?y = ?f ?x =⇒ (?y ∈ range ?f) = True, whichis fine as a c<strong>on</strong>diti<strong>on</strong>al rewrite rule since c<strong>on</strong>diti<strong>on</strong>s can be arbitrary terms.However, this trick is not a panacea because the newly introduced c<strong>on</strong>diti<strong>on</strong>smay be hard to solve.There is no restricti<strong>on</strong> <strong>on</strong> the form of the right-hand sides. They may notc<strong>on</strong>tain extraneous term or type variables, though.The Preprocessor. When a theorem is declared a simplificati<strong>on</strong> rule, itneed not be a c<strong>on</strong>diti<strong>on</strong>al equati<strong>on</strong> already. The simplifier will turn it into aset of c<strong>on</strong>diti<strong>on</strong>al equati<strong>on</strong>s automatically. For example, f x = g x ∧ h x =k x becomes the two separate simplificati<strong>on</strong> rules f x = g x and h x = k x.In general, the input theorem is c<strong>on</strong>verted as follows:


180 9. Advanced Simplificati<strong>on</strong> and Inducti<strong>on</strong>¬P ↦→ P = FalseP −→ Q ↦→ P =⇒ QP ∧ Q ↦→ P, Q∀x. P x ↦→ P ?x∀x ∈ A. P x ↦→ ?x ∈ A =⇒ P ?xif P then Q else R ↦→ P =⇒ Q, ¬P =⇒ ROnce this c<strong>on</strong>versi<strong>on</strong> process is finished, all remaining n<strong>on</strong>-equati<strong>on</strong>s P areturned into trivial equati<strong>on</strong>s P = True. For example, the formulais c<strong>on</strong>verted into the three rules(p −→ t = u ∧ ¬ r) ∧ sp =⇒ t = u, p =⇒ r = False, s = True.9.2 Advanced Inducti<strong>on</strong> TechniquesNow that we have learned about rules and logic, we take another look atthe finer points of inducti<strong>on</strong>. We c<strong>on</strong>sider two questi<strong>on</strong>s: what to do if thepropositi<strong>on</strong> to be proved is not directly amenable to inducti<strong>on</strong> (Sect. 9.2.1),and how to utilize (Sect. 9.2.2) and even derive (Sect. 9.2.3) new inducti<strong>on</strong>schemas. We c<strong>on</strong>clude with an extended example of inducti<strong>on</strong> (Sect. 9.2.4).9.2.1 Massaging the Propositi<strong>on</strong>Often we have assumed that the theorem to be proved is already in a formthat is amenable to inducti<strong>on</strong>, but sometimes it isn’t. Here is an example.Since hd and last return the first and last element of a n<strong>on</strong>-empty list, thislemma looks easy to prove:lemma "xs ≠ [] =⇒ hd(rev xs) = last xs"apply(induct_tac xs)But inducti<strong>on</strong> produces the warningInducti<strong>on</strong> variable occurs also am<strong>on</strong>g premises!and leads to the base case1. xs ≠ [] =⇒ hd (rev []) = last []Simplificati<strong>on</strong> reduces the base case to this:1. xs ≠ [] =⇒ hd [] = last []


9.2 Advanced Inducti<strong>on</strong> Techniques 181We cannot prove this equality because we do not know what hd and lastreturn when applied to [].We should not have ignored the warning. Because the inducti<strong>on</strong> formulais <strong>on</strong>ly the c<strong>on</strong>clusi<strong>on</strong>, inducti<strong>on</strong> does not affect the occurrence of xs in thepremises. Thus the case that should have been trivial becomes unprovable.Fortunately, the soluti<strong>on</strong> is easy: 1Pull all occurrences of the inducti<strong>on</strong> variable into the c<strong>on</strong>clusi<strong>on</strong> using−→.Thus we should state the lemma as an ordinary implicati<strong>on</strong> (−→), lettingrule_format (Sect. 5.15) c<strong>on</strong>vert the result to the usual =⇒ form:lemma hd_rev [rule_format]: "xs ≠ [] −→ hd(rev xs) = last xs"This time, inducti<strong>on</strong> leaves us with a trivial base case:1. [] ≠ [] −→ hd (rev []) = last []And auto completes the proof.If there are multiple premises A 1 , . . . , A n c<strong>on</strong>taining the inducti<strong>on</strong> variable,you should turn the c<strong>on</strong>clusi<strong>on</strong> C intoA 1 −→ · · · A n −→ C .Additi<strong>on</strong>ally, you may also have to universally quantify some other variables,which can yield a fairly complex c<strong>on</strong>clusi<strong>on</strong>. However, rule_format can removeany number of occurrences of ∀ and −→.A sec<strong>on</strong>d reas<strong>on</strong> why your propositi<strong>on</strong> may not be amenable to inducti<strong>on</strong>is that you want to induct <strong>on</strong> a complex term, rather than a variable. Ingeneral, inducti<strong>on</strong> <strong>on</strong> a term t requires rephrasing the c<strong>on</strong>clusi<strong>on</strong> C as∀y 1 . . . y n . x = t −→ C . (9.1)where y 1 . . . y n are the free variables in t and x is a new variable. Now youcan perform inducti<strong>on</strong> <strong>on</strong> x. An example appears in Sect. 9.2.2 below.The very same problem may occur in c<strong>on</strong>necti<strong>on</strong> with rule inducti<strong>on</strong>.Remember that it requires a premise of the form (x 1 , . . . , x k ) ∈ R, where Ris some inductively defined set and the x i are variables. If instead we have apremise t ∈ R, where t is not just an n-tuple of variables, we replace it with(x 1 , . . . , x k ) ∈ R, and rephrase the c<strong>on</strong>clusi<strong>on</strong> C as∀y 1 . . . y n . (x 1 , . . . , x k ) = t −→ C .For an example see Sect. 9.2.4 below.Of course, all premises that share free variables with t need to be pulledinto the c<strong>on</strong>clusi<strong>on</strong> as well, under the ∀ , again using −→ as shown above.1 A similar heuristic applies to rule inducti<strong>on</strong>s; see Sect. 7.2.


182 9. Advanced Simplificati<strong>on</strong> and Inducti<strong>on</strong>Readers who are puzzled by the form of statement (9.1) above shouldremember that the transformati<strong>on</strong> is <strong>on</strong>ly performed to permit inducti<strong>on</strong>.Once inducti<strong>on</strong> has been applied, the statement can be transformed backinto something quite intuitive. For example, applying wellfounded inducti<strong>on</strong><strong>on</strong> x (w.r.t. ≺) to (9.1) and transforming the result a little leads to the goal∧y. ∀z. t z ≺ t y −→ C z =⇒ C ywhere y stands for y 1 . . . y n and the dependence of t and C <strong>on</strong> the freevariables of t has been made explicit. Unfortunately, this inducti<strong>on</strong> schemacannot be expressed as a single theorem because it depends <strong>on</strong> the numberof free variables in t — the notati<strong>on</strong> y is merely an informal device.9.2.2 Bey<strong>on</strong>d Structural and Recursi<strong>on</strong> Inducti<strong>on</strong>So far, inductive proofs were by structural inducti<strong>on</strong> for primitive recursivefuncti<strong>on</strong>s and recursi<strong>on</strong> inducti<strong>on</strong> for total recursive functi<strong>on</strong>s. But sometimesstructural inducti<strong>on</strong> is awkward and there is no recursive functi<strong>on</strong> thatcould furnish a more appropriate inducti<strong>on</strong> schema. In such cases a generalpurposeinducti<strong>on</strong> schema can be helpful. We show how to apply such inducti<strong>on</strong>schemas by an example.Structural inducti<strong>on</strong> <strong>on</strong> nat is usually known as mathematical inducti<strong>on</strong>.There is also complete inducti<strong>on</strong>, where you prove P(n) under theassumpti<strong>on</strong> that P(m) holds for all m < n. In <strong>Isabelle</strong>, this is the theoremnat_less_induct:( V n. ∀ m


9.2 Advanced Inducti<strong>on</strong> Techniques 1831. V n. ∀ m


184 9. Advanced Simplificati<strong>on</strong> and Inducti<strong>on</strong>which is a special case of measure_induct( V x. ∀ y. f y < f x −→ P y =⇒ P x) =⇒ P awhere f may be any functi<strong>on</strong> into type nat.9.2.3 Derivati<strong>on</strong> of New Inducti<strong>on</strong> SchemasInducti<strong>on</strong> schemas are ordinary theorems and you can derive new <strong>on</strong>eswhenever you wish. This secti<strong>on</strong> shows you how, using the example ofnat_less_induct. Assume we <strong>on</strong>ly have structural inducti<strong>on</strong> available for natand want to derive complete inducti<strong>on</strong>. We must generalize the statement asshown:lemma induct_lem: "( V n::nat. ∀ m


9.2 Advanced Inducti<strong>on</strong> Techniques 185due to the SOME operator involved. Below we give a simpler proof of AF_lemma2based <strong>on</strong> an auxiliary inductive definiti<strong>on</strong>.Let us call a (finite or infinite) path A-avoiding if it does not touch anynode in the set A. Then AF_lemma2 says that if no infinite path from some states is A-avoiding, then s ∈ lfp (af A). We prove this by inductively definingthe set Avoid s A of states reachable from s by a finite A-avoiding path:inductive setAvoid :: "state ⇒ state set ⇒ state set"for s :: state and A :: "state set"where"s ∈ Avoid s A"| "[[ t ∈ Avoid s A; t /∈ A; (t,u) ∈ M ]] =⇒ u ∈ Avoid s A"It is easy to see that for any infinite A-avoiding path f with f 0 ∈ Avoids A there is an infinite A-avoiding path starting with s because (by definiti<strong>on</strong>of Avoid) there is a finite A-avoiding path from s to f 0. The proof is byinducti<strong>on</strong> <strong>on</strong> f 0 ∈ Avoid s A. However, this requires the following reformulati<strong>on</strong>,as explained in Sect. 9.2.1 above; the rule_format directive undoes thereformulati<strong>on</strong> after the proof.lemma ex_infinite_path[rule_format]:"t ∈ Avoid s A =⇒∀ f∈Paths t. (∀ i. f i /∈ A) −→ (∃ p∈Paths s. ∀ i. p i /∈ A)"apply(erule Avoid.induct)apply(blast)apply(clarify)apply(drule_tac x = "λi. case i of 0 ⇒ t | Suc i ⇒ f i" in bspec)apply(simp_all add: Paths_def split: nat.split)d<strong>on</strong>eThe base case (t = s) is trivial and proved by blast. In the inducti<strong>on</strong> step,we have an infinite A-avoiding path f starting from u, a successor of t. Nowwe simply instantiate the ∀ f∈Paths t in the inducti<strong>on</strong> hypothesis by thepath starting with t and c<strong>on</strong>tinuing with f. That is what the above λ-termexpresses. Simplificati<strong>on</strong> shows that this is a path starting with t and thatthe instantiated inducti<strong>on</strong> hypothesis implies the c<strong>on</strong>clusi<strong>on</strong>.Now we come to the key lemma. Assuming that no infinite A-avoidingpath starts from s, we want to show s ∈ lfp (af A). For the inductive proofthis must be generalized to the statement that every point t “between” sand A, in other words all of Avoid s A, is c<strong>on</strong>tained in lfp (af A):lemma Avoid_in_lfp[rule_format(no_asm)]:"∀ p∈Paths s. ∃ i. p i ∈ A =⇒ t ∈ Avoid s A −→ t ∈ lfp(af A)"The proof is by inducti<strong>on</strong> <strong>on</strong> the “distance” between t and A. Remember thatlfp (af A) = A ∪ M −1 ‘‘ lfp (af A). If t is already in A, then t ∈ lfp (afA) is trivial. If t is not in A but all successors are in lfp (af A) (inducti<strong>on</strong>hypothesis), then t ∈ lfp (af A) is again trivial.The formal counterpart of this proof sketch is a well-founded inducti<strong>on</strong><strong>on</strong> M restricted to Avoid s A - A, roughly speaking:


186 9. Advanced Simplificati<strong>on</strong> and Inducti<strong>on</strong>{(y, x). (x, y) ∈ M ∧ x ∈ Avoid s A ∧ x /∈ A}As we shall see presently, the absence of infinite A-avoiding paths startingfrom s implies well-foundedness of this relati<strong>on</strong>. For the moment we assumethis and proceed with the inducti<strong>on</strong>:apply(subgoal_tac "wf{(y,x). (x,y) ∈ M ∧ x ∈ Avoid s A ∧ xapply(erule_tac a = t in wf_induct)apply(clarsimp)1. V t. [[∀ p∈Paths s. ∃ i. p i ∈ A;∀ y. (t, y) ∈ M ∧ t /∈ A −→y ∈ Avoid s A −→ y ∈ lfp (af A);t ∈ Avoid s A]]=⇒ t ∈ lfp (af A)2. ∀ p∈Paths s. ∃ i. p i ∈ A =⇒wf {(y, x). (x, y) ∈ M ∧ x ∈ Avoid s A ∧ x /∈ A}/∈ A}")Now the inducti<strong>on</strong> hypothesis states that if t /∈ A then all successors of tthat are in Avoid s A are in lfp (af A). Unfolding lfp in the c<strong>on</strong>clusi<strong>on</strong> ofthe first subgoal <strong>on</strong>ce, we have to prove that t is in A or all successors oft are in lfp (af A). But if t is not in A, the sec<strong>on</strong>d Avoid-rule implies thatall successors of t are in Avoid s A, because we also assume t ∈ Avoid s A.Hence, by the inducti<strong>on</strong> hypothesis, all successors of t are indeed in lfp (afA). Mechanically:apply(subst lfp_unfold[OF m<strong>on</strong>o_af])apply(simp (no_asm) add: af_def)apply(blast intro: Avoid.intros)Having proved the main goal, we return to the proof obligati<strong>on</strong> that therelati<strong>on</strong> used above is indeed well-founded. This is proved by c<strong>on</strong>tradicti<strong>on</strong>: ifthe relati<strong>on</strong> is not well-founded then there exists an infinite A-avoiding pathall in Avoid s A, by theorem wf_iff_no_infinite_down_chain:wf r = (¬ (∃ f. ∀ i. (f (Suc i), f i) ∈ r))From lemma ex_infinite_path the existence of an infinite A-avoiding pathstarting in s follows, c<strong>on</strong>tradicti<strong>on</strong>.apply(erule c<strong>on</strong>trapos_pp)apply(simp add: wf_iff_no_infinite_down_chain)apply(erule exE)apply(rule ex_infinite_path)apply(auto simp add: Paths_def)d<strong>on</strong>eThe (no_asm) modifier of the rule_format directive in the statement ofthe lemma means that the assumpti<strong>on</strong> is left unchanged; otherwise the ∀ pwould be turned into a V p, which would complicate matters below. As it is,Avoid_in_lfp is now[[∀ p∈Paths s. ∃ i. p i ∈ A; t ∈ Avoid s A]] =⇒ t ∈ lfp (af A)


9.2 Advanced Inducti<strong>on</strong> Techniques 187The main theorem is simply the corollary where t = s, when the assumpti<strong>on</strong>t ∈ Avoid s A is trivially true by the first Avoid-rule. <strong>Isabelle</strong> c<strong>on</strong>firms this:theorem AF_lemma2: "{s. ∀ p ∈ Paths s. ∃ i. p i ∈ A} ⊆ lfp(af A)"by(auto elim: Avoid_in_lfp intro: Avoid.intros)


10. Case Study: Verifying a Security ProtocolCommunicati<strong>on</strong>s security is an ancient art. Julius Caesar is said to haveencrypted his messages, shifting each letter three places al<strong>on</strong>g the alphabet.Mary Queen of Scots was c<strong>on</strong>victed of treas<strong>on</strong> after a cipher used in herletters was broken. Today’s postal system incorporates security features. Theenvelope provides a degree of secrecy. The signature provides authenticity(proof of origin), as do departmental stamps and letterheads.Networks are vulnerable: messages pass through many computers, any ofwhich might be c<strong>on</strong>trolled by an adversary, who thus can capture or redirectmessages. People who wish to communicate securely over such a network canuse cryptography, but if they are to understand each other, they need tofollow a protocol: a pre-arranged sequence of message formats.Protocols can be attacked in many ways, even if encrypti<strong>on</strong> is unbreakable.A splicing attack involves an adversary’s sending a message composedof parts of several old messages. This fake message may have the correct format,fooling an h<strong>on</strong>est party. The adversary might be able to masquerade assomebody else, or he might obtain a secret key.N<strong>on</strong>ces help prevent splicing attacks. A typical n<strong>on</strong>ce is a 20-byte randomnumber. Each message that requires a reply incorporates a n<strong>on</strong>ce. The replymust include a copy of that n<strong>on</strong>ce, to prove that it is not a replay of a pastmessage. The n<strong>on</strong>ce in the reply must be cryptographically protected, sinceotherwise an adversary could easily replace it by a different <strong>on</strong>e. You shouldbe starting to see that protocol design is tricky!Researchers are developing methods for proving the correctness of securityprotocols. The Needham-Schroeder public-key protocol [24] has become astandard test case. Proposed in 1978, it was found to be defective nearly twodecades later [20]. This toy protocol will be useful in dem<strong>on</strong>strating how toverify protocols using <strong>Isabelle</strong>.10.1 The Needham-Schroeder Public-Key ProtocolThis protocol uses public-key cryptography. Each pers<strong>on</strong> has a private key,known <strong>on</strong>ly to himself, and a public key, known to everybody. If Alice wantsto send Bob a secret message, she encrypts it using Bob’s public key (which


190 10. Case Study: Verifying a Security Protocoleverybody knows), and sends it to Bob. Only Bob has the matching privatekey, which is needed in order to decrypt Alice’s message.The core of the Needham-Schroeder protocol c<strong>on</strong>sists of three messages:1. A → B : {|Na, A|} Kb2. B → A : {|Na, Nb|} Ka3. A → B : {|Nb|} KbFirst, let’s understand the notati<strong>on</strong>. In the first message, Alice sends Bob amessage c<strong>on</strong>sisting of a n<strong>on</strong>ce generated by Alice (Na) paired with Alice’sname (A) and encrypted using Bob’s public key (Kb). In the sec<strong>on</strong>d message,Bob sends Alice a message c<strong>on</strong>sisting of Na paired with a n<strong>on</strong>ce generatedby Bob (Nb), encrypted using Alice’s public key (Ka). In the last message,Alice returns Nb to Bob, encrypted using his public key.When Alice receives Message 2, she knows that Bob has acted <strong>on</strong> hermessage, since <strong>on</strong>ly he could have decrypted {|Na, A|} Kband extracted Na.That is precisely what n<strong>on</strong>ces are for. Similarly, message 3 assures Bob thatAlice is active. But the protocol was widely believed [7] to satisfy a furtherproperty: that Na and Nb were secrets shared by Alice and Bob. (Manyprotocols generate such shared secrets, which can be used to lessen the reliance<strong>on</strong> slow public-key operati<strong>on</strong>s.) Lowe found this claim to be false: ifAlice runs the protocol with some<strong>on</strong>e untrustworthy (Charlie say), then hecan start a new run with another agent (Bob say). Charlie uses Alice as anoracle, masquerading as Alice to Bob [20].1. A → C : {|Na, A|} Kc1 ′ . C → B : {|Na, A|} Kb2. B → A : {|Na, Nb|} Ka3. A → C : {|Nb|} Kc3 ′ . C → B : {|Nb|} KbIn messages 1 and 3, Charlie removes the encrypti<strong>on</strong> using his private keyand re-encrypts Alice’s messages using Bob’s public key. Bob is left thinkinghe has run the protocol with Alice, which was not Alice’s intenti<strong>on</strong>, and Bobis unaware that the “secret” n<strong>on</strong>ces are known to Charlie. This is a typicalman-in-the-middle attack launched by an insider.Whether this counts as an attack has been disputed. In protocols ofthis type, we normally assume that the other party is h<strong>on</strong>est. To be h<strong>on</strong>estmeans to obey the protocol rules, so Alice’s running the protocol withCharlie does not make her dish<strong>on</strong>est, just careless. After Lowe’s attack, Alicehas no grounds for complaint: this protocol does not have to guarantee anythingif you run it with a bad pers<strong>on</strong>. Bob does have grounds for complaint,however: the protocol tells him that he is communicating with Alice (who ish<strong>on</strong>est) but it does not guarantee secrecy of the n<strong>on</strong>ces.Lowe also suggested a correcti<strong>on</strong>, namely to include Bob’s name in message2:


10.2 Agents and Messages 1911. A → B : {|Na, A|} Kb2. B → A : {|Na, Nb, B|} Ka3. A → B : {|Nb|} KbIf Charlie tries the same attack, Alice will receive the message {|Na, Nb, B|} Kawhen she was expecting to receive {|Na, Nb, C |} Ka. She will aband<strong>on</strong> the run,and eventually so will Bob. Below, we shall look at parts of this protocol’scorrectness proof.In ground-breaking work, Lowe [20] showed how such attacks could befound automatically using a model checker. An alternative, which we shallexamine below, is to prove protocols correct. Proofs can be d<strong>on</strong>e under morerealistic assumpti<strong>on</strong>s because our model does not have to be finite. The strategyis to formalize the operati<strong>on</strong>al semantics of the system and to provesecurity properties using rule inducti<strong>on</strong>.10.2 Agents and MessagesAll protocol specificati<strong>on</strong>s refer to a syntactic theory of messages. Datatypeagent introduces the c<strong>on</strong>stant Server (a trusted central machine, needed forsome protocols), an infinite populati<strong>on</strong> of friendly agents, and the Spy:datatype agent = Server | Friend nat | SpyKeys are just natural numbers. Functi<strong>on</strong> invKey maps a public key to thematching private key, and vice versa:types key = natc<strong>on</strong>sts invKey :: "key ⇒ key"Datatype msg introduces the message forms, which include agent names,n<strong>on</strong>ces, keys, compound messages, and encrypti<strong>on</strong>s.datatypemsg = Agent agent| N<strong>on</strong>ce nat| Key key| MPair msg msg| Crypt key msgThe notati<strong>on</strong> {|X 1 , . . . X n−1 , X n |} abbreviates MPair X 1 . . . (MPair X n−1 X n ).Since datatype c<strong>on</strong>structors are injective, we have the theoremCrypt K X = Crypt K’ X’ =⇒ K = K’ ∧ X = X’A ciphertext can be decrypted using <strong>on</strong>ly <strong>on</strong>e key and can yield <strong>on</strong>ly <strong>on</strong>eplaintext. In the real world, decrypti<strong>on</strong> with the wr<strong>on</strong>g key succeeds butyields garbage. Our model of encrypti<strong>on</strong> is realistic if encrypti<strong>on</strong> adds someredundancy to the plaintext, such as a checksum, so that garbage can bedetected.


192 10. Case Study: Verifying a Security Protocol10.3 Modelling the AdversaryThe spy is part of the system and must be built into the model. He is a malicioususer who does not have to follow the protocol. He watches the networkand uses any keys he knows to decrypt messages. Thus he accumulates additi<strong>on</strong>alkeys and n<strong>on</strong>ces. These he can use to compose new messages, whichhe may send to anybody.Two functi<strong>on</strong>s enable us to formalize this behaviour: analz and synth.Each functi<strong>on</strong> maps a sets of messages to another set of messages. The setanalz H formalizes what the adversary can learn from the set of messages H .The closure properties of this set are defined inductively.inductive setanalz :: "msg set ⇒ msg set"for H :: "msg set"whereInj [intro,simp] : "X ∈ H =⇒ X ∈ analz H"| Fst: "{|X,Y|} ∈ analz H =⇒ X ∈ analz H"| Snd: "{|X,Y|} ∈ analz H =⇒ Y ∈ analz H"| Decrypt [dest]:"[[Crypt K X ∈ analz H; Key(invKey K) ∈ analz H]]=⇒ X ∈ analz H"Note the Decrypt rule: the spy can decrypt a message encrypted withkey K if he has the matching key, K −1 . Properties proved by rule inducti<strong>on</strong>include the following:G ⊆ H =⇒ analz G ⊆ analz Hanalz (analz H) = analz H(analz_m<strong>on</strong>o)(analz_idem)The set of fake messages that an intruder could invent starting from H issynth(analz H), where synth H formalizes what the adversary can build fromthe set of messages H .inductive setsynth :: "msg set ⇒ msg set"for H :: "msg set"whereInj [intro]: "X ∈ H =⇒ X ∈ synth H"| Agent [intro]: "Agent agt ∈ synth H"| MPair [intro]:"[[X ∈ synth H; Y ∈ synth H]] =⇒ {|X,Y|} ∈ synth H"| Crypt [intro]:"[[X ∈ synth H; Key K ∈ H]] =⇒ Crypt K X ∈ synth H"The set includes all agent names. N<strong>on</strong>ces and keys are assumed to beunguessable, so n<strong>on</strong>e are included bey<strong>on</strong>d those already in H . Two elementsof synth H can be combined, and an element can be encrypted using a keypresent in H .Like analz, this set operator is m<strong>on</strong>ot<strong>on</strong>e and idempotent. It also satisfiesan interesting equati<strong>on</strong> involving analz:


analz (synth H) = analz H ∪ synth H10.4 Event Traces 193(analz_synth)Rule inversi<strong>on</strong> plays a major role in reas<strong>on</strong>ing about synth, through declarati<strong>on</strong>ssuch as this <strong>on</strong>e:inductive cases N<strong>on</strong>ce_synth [elim!]: "N<strong>on</strong>ce n ∈ synth H"The resulting eliminati<strong>on</strong> rule replaces every assumpti<strong>on</strong> of the form N<strong>on</strong>ce n∈ synth H by N<strong>on</strong>ce n ∈ H, expressing that a n<strong>on</strong>ce cannot be guessed.A third operator, parts, is useful for stating correctness properties. The setparts H c<strong>on</strong>sists of the comp<strong>on</strong>ents of elements of H . This set includes H andis closed under the projecti<strong>on</strong>s from a compound message to its immediateparts. Its definiti<strong>on</strong> resembles that of analz except in the rule corresp<strong>on</strong>dingto the c<strong>on</strong>structor Crypt:Crypt K X ∈ parts H =⇒ X ∈ parts HThe body of an encrypted message is always regarded as part of it. We canuse parts to express general well-formedness properties of a protocol, forexample, that an uncompromised agent’s private key will never be includedas a comp<strong>on</strong>ent of any message.10.4 Event TracesThe system’s behaviour is formalized as a set of traces of events. The mostimportant event, Says A B X, expresses A → B : X , which is the attemptby A to send B the message X . A trace is simply a list, c<strong>on</strong>structed inreverse using #. Other event types include recepti<strong>on</strong> of messages (when wewant to make it explicit) and an agent’s storing a fact.Sometimes the protocol requires an agent to generate a new n<strong>on</strong>ce. Theprobability that a 20-byte random number has appeared before is effectivelyzero. To formalize this important property, the set used evs denotes the set ofall items menti<strong>on</strong>ed in the trace evs. The functi<strong>on</strong> used has a straightforwardrecursive definiti<strong>on</strong>. Here is the case for Says event:used (Says A B X # evs) = parts {X} ∪ used evsThe functi<strong>on</strong> knows formalizes an agent’s knowledge. Mostly we <strong>on</strong>ly careabout the spy’s knowledge, and knows Spy evs is the set of items availableto the spy in the trace evs. Already in the empty trace, the spy starts withsome secrets at his disposal, such as the private keys of compromised users.After each Says event, the spy learns the message that was sent:knows Spy (Says A B X # evs) = insert X (knows Spy evs)Combinati<strong>on</strong>s of functi<strong>on</strong>s express other important sets of messages derivedfrom evs:– analz (knows Spy evs) is everything that the spy could learn by decrypti<strong>on</strong>


194 10. Case Study: Verifying a Security Protocol– synth (analz (knows Spy evs)) is everything that the spy could generateThe functi<strong>on</strong> pubK maps agents to their public keys. The functi<strong>on</strong> priKmaps agents to their private keys. It is merely an abbreviati<strong>on</strong> (cf. Sect. 4.1.4)defined in terms of invKey and pubK.c<strong>on</strong>sts pubK :: "agent ⇒ key"abbreviati<strong>on</strong> priK :: "agent ⇒ key"where "priK x ≡ invKey(pubK x)"The set bad c<strong>on</strong>sists of those agents whose private keys are known to the spy.Two axioms are asserted about the public-key cryptosystem. No twoagents have the same public key, and no private key equals any public key.axiomsinj_pubK: "inj pubK"priK_neq_pubK: "priK A ≠ pubK B"10.5 Modelling the Protocolinductive set ns_public :: "event list set"whereNil:"[] ∈ ns_public"| Fake: "[[evsf ∈ ns_public; X ∈ synth (analz (knows Spy evsf))]]=⇒ Says Spy B X # evsf ∈ ns_public"| NS1: "[[evs1 ∈ ns_public; N<strong>on</strong>ce NA /∈ used evs1]]=⇒ Says A B (Crypt (pubK B) {|N<strong>on</strong>ce NA, Agent A|})# evs1 ∈ ns_public"| NS2: "[[evs2 ∈ ns_public; N<strong>on</strong>ce NB /∈ used evs2;Says A’ B (Crypt (pubK B) {|N<strong>on</strong>ce NA, Agent A|}) ∈ set evs2]]=⇒ Says B A (Crypt (pubK A) {|N<strong>on</strong>ce NA, N<strong>on</strong>ce NB, Agent B|})# evs2 ∈ ns_public"| NS3: "[[evs3 ∈ ns_public;Says A B (Crypt (pubK B) {|N<strong>on</strong>ce NA, Agent A|}) ∈ set evs3;Says B’ A (Crypt (pubK A) {|N<strong>on</strong>ce NA, N<strong>on</strong>ce NB, Agent B|})∈ set evs3]]=⇒ Says A B (Crypt (pubK B) (N<strong>on</strong>ce NB)) # evs3 ∈ ns_public"Figure 10.1. An Inductive Protocol Definiti<strong>on</strong>


10.6 Proving Elementary Properties 195Let us formalize the Needham-Schroeder public-key protocol, as correctedby Lowe:1. A → B : {|Na, A|} Kb2. B → A : {|Na, Nb, B|} Ka3. A → B : {|Nb|} KbEach protocol step is specified by a rule of an inductive definiti<strong>on</strong>. Anevent trace has type event list, so we declare the c<strong>on</strong>stant ns_public to bea set of such traces.Figure 10.1 presents the inductive definiti<strong>on</strong>. The Nil rule introduces theempty trace. The Fake rule models the adversary’s sending a message builtfrom comp<strong>on</strong>ents taken from past traffic, expressed using the functi<strong>on</strong>s synthand analz. The next three rules model how h<strong>on</strong>est agents would perform thethree protocol steps.Here is a detailed explanati<strong>on</strong> of rule NS2. A trace c<strong>on</strong>taining an event ofthe formSays A’ B (Crypt (pubK B) {|N<strong>on</strong>ce NA, Agent A|})may be extended by an event of the formSays B A (Crypt (pubK A) {|N<strong>on</strong>ce NA, N<strong>on</strong>ce NB, Agent B|})where NB is a fresh n<strong>on</strong>ce: N<strong>on</strong>ce NB ∈ used evs2. Writing the sender as A’indicates that B does not know who sent the message. Calling the trace variableevs2 rather than simply evs helps us know where we are in a proof aftermany case-splits: every subgoal menti<strong>on</strong>ing evs2 involves message 2 of theprotocol.Benefits of this approach are simplicity and clarity. The semantic modelis set theory, proofs are by inducti<strong>on</strong> and the translati<strong>on</strong> from the informalnotati<strong>on</strong> to the inductive rules is straightforward.10.6 Proving Elementary PropertiesSecrecy properties can be hard to prove. The c<strong>on</strong>clusi<strong>on</strong> of a typical secrecytheorem is X /∈ analz (knows Spy evs). The difficulty arises from having toreas<strong>on</strong> about analz, or less formally, showing that the spy can never learn X.Much easier is to prove that X can never occur at all. Such regularity propertiesare typically expressed using parts rather than analz.The following lemma states that A’s private key is potentially known to thespy if and <strong>on</strong>ly if A bel<strong>on</strong>gs to the set bad of compromised agents. The statementuses parts: the very presence of A’s private key in a message, whetherprotected by encrypti<strong>on</strong> or not, is enough to c<strong>on</strong>firm that A is compromised.The proof, like nearly all protocol proofs, is by inducti<strong>on</strong> over traces.


196 10. Case Study: Verifying a Security Protocollemma Spy_see_priK [simp]:"evs ∈ ns_public=⇒ (Key (priK A) ∈ parts (knows Spy evs)) = (A ∈ bad)"apply (erule ns_public.induct, simp_all)The inducti<strong>on</strong> yields five subgoals, <strong>on</strong>e for each rule in the definiti<strong>on</strong> ofns_public. The idea is to prove that the protocol property holds initially (ruleNil), is preserved by each of the legitimate protocol steps (rules NS1–3), andeven is preserved in the face of anything the spy can do (rule Fake).The proof is trivial. No legitimate protocol rule sends any keys at all,so <strong>on</strong>ly Fake is relevant. Indeed, simplificati<strong>on</strong> leaves <strong>on</strong>ly the Fake case, asindicated by the variable name evsf:1. V evsf X.[[evsf ∈ ns_public;(Key (priK A) ∈ parts (knows Spy evsf)) = (A ∈ bad);X ∈ synth (analz (knows Spy evsf))]]=⇒ (Key (priK A) ∈ parts (insert X (knows Spy evsf))) =(A ∈ bad)by blastThe Fake case is proved automatically. If priK A is in the extended tracethen either (1) it was already in the original trace or (2) it was generated bythe spy, who must have known this key already. Either way, the inducti<strong>on</strong>hypothesis applies.Unicity lemmas are regularity lemmas stating that specified items canoccur <strong>on</strong>ly <strong>on</strong>ce in a trace. The following lemma states that a n<strong>on</strong>ce cannotbe used both as Na and as Nb unless it is known to the spy. Intuitively,it holds because h<strong>on</strong>est agents always choose fresh values as n<strong>on</strong>ces; <strong>on</strong>lythe spy might reuse a value, and he doesn’t know this particular value. Theproof script is short: inducti<strong>on</strong>, simplificati<strong>on</strong>, blast. The first line uses therule rev_mp to prepare the inducti<strong>on</strong> by moving two assumpti<strong>on</strong>s into theinducti<strong>on</strong> formula.lemma no_n<strong>on</strong>ce_NS1_NS2:"[[Crypt (pubK C) {|NA’, N<strong>on</strong>ce NA, Agent D|} ∈ parts (knows Spy evs);Crypt (pubK B) {|N<strong>on</strong>ce NA, Agent A|} ∈ parts (knows Spy evs);evs ∈ ns_public]]=⇒ N<strong>on</strong>ce NA ∈ analz (knows Spy evs)"apply (erule rev_mp, erule rev_mp)apply (erule ns_public.induct, simp_all)apply (blast intro: analz_insertI)+d<strong>on</strong>eThe following unicity lemma states that, if NA is secret, then its appearancein any instance of message 1 determines the other comp<strong>on</strong>ents. Theproof is similar to the previous <strong>on</strong>e.lemma unique_NA:"[[Crypt(pubK B) {|N<strong>on</strong>ce NA, Agent A |} ∈ parts(knows Spy evs);Crypt(pubK B’) {|N<strong>on</strong>ce NA, Agent A’|} ∈ parts(knows Spy evs);


10.7 Proving Secrecy Theorems 197N<strong>on</strong>ce NA /∈ analz (knows Spy evs); evs ∈ ns_public]]=⇒ A=A’ ∧ B=B’"10.7 Proving Secrecy TheoremsThe secrecy theorems for Bob (the sec<strong>on</strong>d participant) are especially importantbecause they fail for the original protocol. The following theorem statesthat if Bob sends message 2 to Alice, and both agents are uncompromised,then Bob’s n<strong>on</strong>ce will never reach the spy.theorem Spy_not_see_NB [dest]:"[[Says B A (Crypt (pubK A) {|N<strong>on</strong>ce NA, N<strong>on</strong>ce NB, Agent B|}) ∈ set evs;A /∈ bad; B /∈ bad; evs ∈ ns_public]]=⇒ N<strong>on</strong>ce NB /∈ analz (knows Spy evs)"To prove it, we must formulate the inducti<strong>on</strong> properly (<strong>on</strong>e of the assumpti<strong>on</strong>smenti<strong>on</strong>s evs), apply inducti<strong>on</strong>, and simplify:apply (erule rev_mp, erule ns_public.induct, simp_all)The proof states are too complicated to present in full. Let’s examine thesimplest subgoal, that for message 1. The following event has just occurred:1. A ′ → B ′ : {|Na ′ , A ′ |} Kb ′The variables above have been primed because this step bel<strong>on</strong>gs to a differentrun from that referred to in the theorem statement — the theorem refers to apast instance of message 2, while this subgoal c<strong>on</strong>cerns message 1 being sentjust now. In the <strong>Isabelle</strong> subgoal, instead of primed variables like B ′ and Na ′we have Ba and NAa:1. V evs1 NAa Ba.[[A /∈ bad; B /∈ bad; evs1 ∈ ns_public;Says B A (Crypt (pubK A) {|N<strong>on</strong>ce NA, N<strong>on</strong>ce NB, Agent B|})∈ set evs1 −→N<strong>on</strong>ce NB /∈ analz (knows Spy evs1);N<strong>on</strong>ce NAa /∈ used evs1]]=⇒ Ba ∈ bad −→Says B A (Crypt (pubK A) {|N<strong>on</strong>ce NA, N<strong>on</strong>ce NB, Agent B|})∈ set evs1 −→NB ≠ NAaThe simplifier has used a default simplificati<strong>on</strong> rule that does a case analysisfor each encrypted message <strong>on</strong> whether or not the decrypti<strong>on</strong> key is compromised.analz (insert (Crypt K X) H) =(if Key (invKey K) ∈ analz Hthen insert (Crypt K X) (analz (insert X H))else insert (Crypt K X) (analz H))(analz_Crypt_if)


198 10. Case Study: Verifying a Security ProtocolThe simplifier has also used Spy_see_priK, proved in Sect. 10.6 above, to yieldBa ∈ bad.Recall that this subgoal c<strong>on</strong>cerns the case where the last message to besent was1. A ′ → B ′ : {|Na ′ , A ′ |} Kb ′.This message can compromise Nb <strong>on</strong>ly if Nb = Na ′ and B ′ is compromised,allowing the spy to decrypt the message. The <strong>Isabelle</strong> subgoal says preciselythis, if we allow for its choice of variable names. Proving NB ≠ NAa is easy: NBwas sent earlier, while NAa is fresh; formally, we have the assumpti<strong>on</strong> N<strong>on</strong>ceNAa /∈ used evs1.Note that our reas<strong>on</strong>ing c<strong>on</strong>cerned B’s participati<strong>on</strong> in another run.Agents may engage in several runs c<strong>on</strong>currently, and some attacks work byinterleaving the messages of two runs. With model checking, this possibilitycan cause a state-space explosi<strong>on</strong>, and for us it certainly complicates proofs.The biggest subgoal c<strong>on</strong>cerns message 2. It splits into several cases, such aswhether or not the message just sent is the very message menti<strong>on</strong>ed in thetheorem statement. Some of the cases are proved by unicity, others by theinducti<strong>on</strong> hypothesis. For all those complicati<strong>on</strong>s, the proofs are automaticby blast with the theorem no_n<strong>on</strong>ce_NS1_NS2.The remaining theorems about the protocol are not hard to prove. Thefollowing <strong>on</strong>e asserts a form of authenticity: if B has sent an instance ofmessage 2 to A and has received the expected reply, then that reply reallyoriginated with A. The proof is a simple inducti<strong>on</strong>.theorem B_trusts_NS3:"[[Says B A (Crypt (pubK A) {|N<strong>on</strong>ce NA, N<strong>on</strong>ce NB, Agent B|}) ∈ set evs;Says A’ B (Crypt (pubK B) (N<strong>on</strong>ce NB)) ∈ set evs;A /∈ bad; B /∈ bad; evs ∈ ns_public]]=⇒ Says A B (Crypt (pubK B) (N<strong>on</strong>ce NB)) ∈ set evs"From similar assumpti<strong>on</strong>s, we can prove that A started the protocol runby sending an instance of message 1 involving the n<strong>on</strong>ce NA. For this theorem,the c<strong>on</strong>clusi<strong>on</strong> isSays A B (Crypt (pubK B) {|N<strong>on</strong>ce NA, Agent A|}) ∈ set evsAnalogous theorems can be proved for A, stating that n<strong>on</strong>ce NA remains secretand that message 2 really originates with B. Even the flawed protocolestablishes these properties for A; the flaw <strong>on</strong>ly harms the sec<strong>on</strong>d participant.Detailed informati<strong>on</strong> <strong>on</strong> this protocol verificati<strong>on</strong> technique can be foundelsewhere [32], including proofs of an Internet protocol [33]. We must stressthat the protocol discussed in this chapter is trivial. There are <strong>on</strong>ly threemessages; no keys are exchanged; we merely have to prove that encrypteddata remains secret. Real world protocols are much l<strong>on</strong>ger and distributemany secrets to their participants. To be realistic, the model has to includethe possibility of keys being lost dynamically due to carelessness. If thosekeys have been used to encrypt other sensitive informati<strong>on</strong>, there may be


10.7 Proving Secrecy Theorems 199cascading losses. We may still be able to establish a bound <strong>on</strong> the losses andto prove that other protocol runs functi<strong>on</strong> correctly [34]. Proofs of real-worldprotocols follow the strategy illustrated above, but the subgoals can be muchbigger and there are more of them.


200


201You know my methods. Apply them!Sherlock Holmes


A. Appendix≠[[ [| \]] |] \=⇒ V ==> \!! \≡ == \⇋ == \⇀ => \↽ \∧ & \∨ | \−→ --> \¬ ~ \~= \∀ ALL, ! \∃ EX, ? \∃! EX!, ?! \!ε SOME, @ \◦ o \| | abs \ \≤


204 A. AppendixC<strong>on</strong>stant Type Syntax0 ’a::zero1 ’a::<strong>on</strong>e+ (’a::plus) ⇒ ’a ⇒ ’a (infixl 65)- (’a::minus) ⇒ ’a ⇒ ’a (infixl 65)- (’a::minus) ⇒ ’a* (’a::times) ⇒ ’a ⇒ ’a (infixl 70)div (’a::div) ⇒ ’a ⇒ ’a (infixl 70)mod (’a::div) ⇒ ’a ⇒ ’a (infixl 70)dvd (’a::times) ⇒ ’a ⇒ bool (infixl 50)/ (’a::inverse) ⇒ ’a ⇒ ’a (infixl 70)^ (’a::power) ⇒ nat ⇒ ’a (infixr 80)abs (’a::minus) ⇒ ’a |x|≤ (’a::ord) ⇒ ’a ⇒ bool (infixl 50)< (’a::ord) ⇒ ’a ⇒ bool (infixl 50)min (’a::ord) ⇒ ’a ⇒ ’amax (’a::ord) ⇒ ’a ⇒ ’aLeast (’a::ord ⇒ bool) ⇒ ’a LEAST x. PTable A.2. Overloaded C<strong>on</strong>stants in <strong>HOL</strong>ALL BIT CHR EX GREATEST INT Int LEAST OOFCLASS PI PROP SIGMA SOME THE TYPE UN UnWRT case choose div dvd else funcset if inlet mem mod o of op thenTable A.3. Reserved Words in <strong>HOL</strong> Terms


Bibliography[1] David Aspinall. Proof General. http://proofgeneral.inf.ed.ac.uk/.[2] David Aspinall. Proof General: A generic tool for proof development.In Tools and Algorithms for the C<strong>on</strong>structi<strong>on</strong> and Analysis of Systems(TACAS), volume 1785 of Lecture Notes in Computer Science, pages38–42. Springer-Verlag, 2000.[3] Franz Baader and Tobias Nipkow. Term Rewriting and All That. CambridgeUniversity Press, 1998.[4] Gertrud Bauer, Tobias Nipkow, David v<strong>on</strong> Oheimb, Lawrence C Pauls<strong>on</strong>,Thomas M Rasmussen, Christophe Tabacznyj, and Markus Wenzel. Thesupplemental <strong>Isabelle</strong>/<strong>HOL</strong> library. Part of the <strong>Isabelle</strong> distributi<strong>on</strong>,http://isabelle.in.tum.de/library/<strong>HOL</strong>/Library/document.pdf, 2002.[5] Richard Bird. Introducti<strong>on</strong> to Functi<strong>on</strong>al Programming using Haskell.Prentice-Hall, 1998.[6] Lukas Bulwahn, Alexander Krauss, and Tobias Nipkow. Finding lexicographicorders for terminati<strong>on</strong> proofs in <strong>Isabelle</strong>/<strong>HOL</strong>. In K. Schneiderand J. Brandt, editors, Theorem Proving in Higher Order Logics:TP<strong>HOL</strong>s 2007, volume 4732 of Lecture Notes in Computer Science,pages 38–53. Springer-Verlag, 2007.[7] M. Burrows, M. Abadi, and R. M. Needham. A logic of authenticati<strong>on</strong>.Proceedings of the Royal Society of L<strong>on</strong>d<strong>on</strong>, 426:233–271, 1989.[8] Edmund Clarke, Orna Grumberg, and Dor<strong>on</strong> Peled. Model Checking.MIT Press, 1999.[9] Jacques Fleuriot and Lawrence C. Pauls<strong>on</strong>. Mechanizing n<strong>on</strong>standardreal analysis. LMS Journal of Computati<strong>on</strong> and Mathematics, 3:140–190,2000. http://www.lms.ac.uk/jcm/3/lms1999-027/.[10] Jean-Yves Girard. Proofs and Types. Cambridge University Press, 1989.Translated by Yves LaF<strong>on</strong>t and Paul Taylor.[11] M. J. C. Gord<strong>on</strong> and T. F. Melham, editors. Introducti<strong>on</strong> to <strong>HOL</strong>:A Theorem Proving Envir<strong>on</strong>ment for Higher Order Logic. CambridgeUniversity Press, 1993.[12] Florian Haftmann. Haskell-style type classes with <strong>Isabelle</strong>/Isar. http://isabelle.in.tum.de/doc/classes.pdf.


206 BIBLIOGRAPHY[13] Florian Haftmann and Makarius Wenzel. C<strong>on</strong>structive type classes in<strong>Isabelle</strong>. In T. Altenkirch and C. McBride, editors, Types for Proofs andPrograms, TYPES 2006, volume 4502 of LNCS. Springer, 2007.[14] David Harel, Dexter Kozen, and Jerzy Tiuryn. Dynamic Logic. MITPress, 2000.[15] John E. Hopcroft and Jeffrey D. Ullman. Introducti<strong>on</strong> to AutomataTheory, Languages, and Computati<strong>on</strong>. Addis<strong>on</strong>-Wesley, 1979.[16] Paul Hudak. The Haskell School of Expressi<strong>on</strong>. Cambridge UniversityPress, 2000.[17] Michael Huth and Mark Ryan. Logic in Computer Science. Modellingand reas<strong>on</strong>ing about systems. Cambridge University Press, 2000.[18] D<strong>on</strong>ald E. Knuth. The Art of Computer Programming, Volume 3: Sortingand Searching. Addis<strong>on</strong>-Wesley, 1975.[19] Alexander Krauss. Defining Recursive Functi<strong>on</strong>s in <strong>Isabelle</strong>/<strong>HOL</strong>. http://isabelle.in.tum.de/doc/functi<strong>on</strong>s.pdf.[20] Gavin Lowe. Breaking and fixing the Needham-Schroeder public-keyprotocol using CSP and FDR. In T. Margaria and B. Steffen, editors,Tools and Algorithms for the C<strong>on</strong>structi<strong>on</strong> and Analysis of Systems:sec<strong>on</strong>d internati<strong>on</strong>al workshop, TACAS ’96, LNCS 1055, pages 147–166.Springer, 1996.[21] Robin Milner, Mads Tofte, and Robert Harper. The Definiti<strong>on</strong> of StandardML. MIT Press, 1990.[22] Olaf Müller, Tobias Nipkow, David v<strong>on</strong> Oheimb, and Oscar Slotosch.<strong>HOL</strong>CF = <strong>HOL</strong> + LCF. Journal of Functi<strong>on</strong>al Programming, 9:191–223, 1999.[23] Wolfgang Naraschewski and Markus Wenzel. Object-oriented verificati<strong>on</strong>based <strong>on</strong> record subtyping in higher-order logic. In Jim Grundyand Malcom Newey, editors, Theorem Proving in Higher Order Logics:TP<strong>HOL</strong>s ’98, volume 1479 of Lecture Notes in Computer Science.Springer-Verlag, 1998.[24] Roger M. Needham and Michael D. Schroeder. Using encrypti<strong>on</strong> forauthenticati<strong>on</strong> in large networks of computers. Communicati<strong>on</strong>s of theACM, 21(12):993–999, December 1978.[25] Tobias Nipkow. Functi<strong>on</strong>al unificati<strong>on</strong> of higher-order patterns. InM. Vardi, editor, Eighth Annual Symposium <strong>on</strong> Logic in Computer Science,pages 64–74. ieee Computer Society Press, 1993.[26] Tobias Nipkow. Structured Proofs in Isar/<strong>HOL</strong>. In H. Geuvers andF. Wiedijk, editors, Types for Proofs and Programs (TYPES 2002),volume 2646 of Lecture Notes in Computer Science, pages 259–278.Springer-Verlag, 2003.[27] Tobias Nipkow, Lawrence C. Pauls<strong>on</strong>, and Markus Wenzel. <strong>Isabelle</strong>’sLogics: <strong>HOL</strong>. http://isabelle.in.tum.de/doc/logics-<strong>HOL</strong>.pdf.[28] Lawrence C. Pauls<strong>on</strong>. The <strong>Isabelle</strong> Reference Manual. http://isabelle.in.tum.de/doc/ref.pdf.


BIBLIOGRAPHY 207[29] Lawrence C. Pauls<strong>on</strong>. Logic and Computati<strong>on</strong>: Interactive proof withCambridge LCF. Cambridge University Press, 1987.[30] Lawrence C. Pauls<strong>on</strong>. <strong>Isabelle</strong>: A Generic Theorem Prover. Springer,1994. LNCS 828.[31] Lawrence C. Pauls<strong>on</strong>. ML for the Working Programmer. CambridgeUniversity Press, 2nd editi<strong>on</strong>, 1996.[32] Lawrence C. Pauls<strong>on</strong>. The inductive approach to verifying cryptographicprotocols. Journal of Computer Security, 6:85–128, 1998.[33] Lawrence C. Pauls<strong>on</strong>. Inductive analysis of the Internet protocol TLS.ACM Transacti<strong>on</strong>s <strong>on</strong> Informati<strong>on</strong> and System Security, 2(3):332–351,August 1999.[34] Lawrence C. Pauls<strong>on</strong>. Relati<strong>on</strong>s between secrets: Two formal analysesof the Yahalom protocol. Journal of Computer Security, 9(3):197–216,2001.[35] F. J. Pelletier. Seventy-five problems for testing automatic theoremprovers. Journal of Automated Reas<strong>on</strong>ing, 2:191–216, 1986. Errata,JAR 4 (1988), 235–236 and JAR 18 (1997), 135.[36] Kenneth H. Rosen. Discrete Mathematics and Its Applicati<strong>on</strong>s. McGraw-Hill, 1998.[37] Sim<strong>on</strong> Thomps<strong>on</strong>. Haskell: The Craft of Functi<strong>on</strong>al Programming.Addis<strong>on</strong>-Wesley, 1999.[38] Makarius Wenzel. The <strong>Isabelle</strong>/Isar Reference Manual. http://isabelle.in.tum.de/doc/isar-ref.pdf.[39] Markus Wenzel. <strong>Isabelle</strong>/Isar — a versatile envir<strong>on</strong>ment for humanreadableformal proof documents. PhD thesis, Institut für Informatik,Technische Universität München, 2002. http://tumb1.biblio.tu-muenchen.de/publ/diss/in/2002/wenzel.html.[40] Markus Wenzel and Stefan Berghofer. The <strong>Isabelle</strong> System Manual.http://isabelle.in.tum.de/doc/system.pdf.


Index!, 203?, 203∃! , 203?!, 203&, 203~, 203~=, 203|, 203*, 22+, 22-, 22


Index 209bij_def (theorem), 112bijecti<strong>on</strong>s, 112binary trees, 18binomial coefficients, 111bisimulati<strong>on</strong>s, 118blast (method), 89–92bool (type), 5boolean expressi<strong>on</strong>s example, 19–22bspec (theorem), 110by (command), 73card (c<strong>on</strong>stant), 111card_Pow (theorem), 111card_Un_Int (theorem), 111cardinality, 111case (symbol), 31, 32case expressi<strong>on</strong>s, 5, 6, 18case distincti<strong>on</strong>s, 19case splits, 31case_tac (method), 19, 102, 153cases (method), 158chapter (command), 59clarify (method), 91, 92clarsimp (method), 91, 92classical (theorem), 73coinducti<strong>on</strong>, 118Collect (c<strong>on</strong>stant), 111compiling expressi<strong>on</strong>s example, 37–39Compl_iff (theorem), 108complement– of a set, 107complex (type), 170–171complex numbers, 170–171Complex_Main (theory), 170compositi<strong>on</strong>– of functi<strong>on</strong>s, 112– of relati<strong>on</strong>s, 114c<strong>on</strong>clusi<strong>on</strong>– of subgoal, 13c<strong>on</strong>diti<strong>on</strong>al expressi<strong>on</strong>s, see ifexpressi<strong>on</strong>sc<strong>on</strong>diti<strong>on</strong>al simplificati<strong>on</strong> rules, 31c<strong>on</strong>g (attribute), 178c<strong>on</strong>gruence rules, 177c<strong>on</strong>jE (theorem), 71c<strong>on</strong>jI (theorem), 68C<strong>on</strong>s (c<strong>on</strong>stant), 9c<strong>on</strong>trapositives, 73c<strong>on</strong>verse– of a relati<strong>on</strong>, 114c<strong>on</strong>verse_iff (theorem), 114CTL, 123–127, 184–187datatype (command), 9, 39–44datatypes, 16–22– and nested recursi<strong>on</strong>, 41, 45– mutually recursive, 39defer (command), 16, 101definiti<strong>on</strong> (command), 25Definiti<strong>on</strong>al Approach, 25definiti<strong>on</strong>s, 25– unfolding, 30del (modifier), 29descripti<strong>on</strong> operators, 85–87descripti<strong>on</strong>s– definite, 86– indefinite, 86dest (attribute), 103destructi<strong>on</strong> rules, 71diff_mult_distrib (theorem), 168difference– of sets, 108disjCI (theorem), 74disjE (theorem), 70div (symbol), 22, 23divides relati<strong>on</strong>, 85, 96, 102–105, 168divisi<strong>on</strong>– by negative numbers, 169– by zero, 168– for type nat, 168divisi<strong>on</strong>_by_zero (type class), 171documents, 57domain– of a relati<strong>on</strong>, 114Domain_iff (theorem), 114d<strong>on</strong>e (command), 14drule_tac (method), 76, 97dvd (symbol), 23dvd_add (theorem), 168dvd_anti_sym (theorem), 168dvd_def (theorem), 168elim! (attribute), 133eliminati<strong>on</strong> rules, 69–70end (command), 15Eps (c<strong>on</strong>stant), 111equality, 5– of functi<strong>on</strong>s, 111– of records, 157– of sets, 108equalityE (theorem), 108equalityI (theorem), 108erule (method), 70erule_tac (method), 76Euclid’s algorithm, 102–105evaluati<strong>on</strong>, 11even numbers


210 Index– defining inductively, 129–133EX, 203Ex (c<strong>on</strong>stant), 111exE (theorem), 83exI (theorem), 82ext (theorem), 111extend (c<strong>on</strong>stant), 158extensi<strong>on</strong>ality– for functi<strong>on</strong>s, 111, 112– for records, 157– for sets, 108EX!, 203False (c<strong>on</strong>stant), 5fast (method), 92, 125Fib<strong>on</strong>acci functi<strong>on</strong>, 47field (type class), 171fields (c<strong>on</strong>stant), 158finding theorems, 33, 93finite (symbol), 111fixed points, 117–118force (method), 91, 92formal comments, 60formal proof documents, 57formulae, 5–6forward proof, 93–99frule (method), 83–84frule_tac (method), 76fst (c<strong>on</strong>stant), 23fun (command), 47–51functi<strong>on</strong> types, 5functi<strong>on</strong>s, 111–113– total, 11, 47–51gcd (c<strong>on</strong>stant), 94–95, 102–105generalizing for inducti<strong>on</strong>, 131generalizing inducti<strong>on</strong> formulae, 36Girard, Jean-Yves, 71nGord<strong>on</strong>, Mike, 3grammars– defining inductively, 143–147ground terms example, 138–142hd (c<strong>on</strong>stant), 17, 38header (command), 59Hilbert’s ε-operator, 86<strong>HOL</strong>CF, 44Hopcroft, J. E., 147hypreal (type), 170Id_def (theorem), 114id_def (theorem), 112identifiers, 6– qualified, 4identity functi<strong>on</strong>, 112identity relati<strong>on</strong>, 114if expressi<strong>on</strong>s, 5, 6– simplificati<strong>on</strong> of, 32– splitting of, 31, 49if-and-<strong>on</strong>ly-if, 6iff (attribute), 90, 91, 103, 132iffD1 (theorem), 95iffD2 (theorem), 95ignored material, 63image– under a functi<strong>on</strong>, 113– under a relati<strong>on</strong>, 114image_def (theorem), 113Image_iff (theorem), 114impI (theorem), 72implicati<strong>on</strong>, 72–73imports (command), 4ind_cases (method), 133induct_tac (method), 12, 19, 51, 183inducti<strong>on</strong>, 180–187– complete, 182– deriving new schemas, 184– <strong>on</strong> a term, 181– recursi<strong>on</strong>, 50–51– structural, 19– well-founded, 117inducti<strong>on</strong> heuristics, 35–37inductive (command), 134inductive definiti<strong>on</strong>– simultaneous, 143inductive definiti<strong>on</strong>s, 129–147inductive predicates, 134inductive cases (command), 133, 142inductive set (command), 129infinitely branching trees, 43infix annotati<strong>on</strong>s, 53infixr (annotati<strong>on</strong>), 10inj_<strong>on</strong>_def (theorem), 112injecti<strong>on</strong>s, 112insert (c<strong>on</strong>stant), 109insert (method), 98–99instance, 161INT, 203Int, 203int (type), 169–170INT_iff (theorem), 110IntD1 (theorem), 107IntD2 (theorem), 107integers, 169–170INTER (c<strong>on</strong>stant), 111Inter, 203Inter_iff (theorem), 110


Index 211intersecti<strong>on</strong>, 107– indexed, 110IntI (theorem), 107intro (method), 74intro! (attribute), 130intro_classes (method), 161introducti<strong>on</strong> rules, 68–69inv (c<strong>on</strong>stant), 86inv_image_def (theorem), 117inverse– of a functi<strong>on</strong>, 112– of a relati<strong>on</strong>, 114inverse (c<strong>on</strong>stant), 171inverse image– of a functi<strong>on</strong>, 113– of a relati<strong>on</strong>, 116itrev (c<strong>on</strong>stant), 35λ expressi<strong>on</strong>s, 5LCF, 44LEAST (symbol), 22, 86least number operator, see LEASTLeibniz, Gottfried Wilhelm, 53lemma (command), 13lemmas (command), 94, 103length (symbol), 17length_induct, 183less_than (c<strong>on</strong>stant), 116less_than_iff (theorem), 116let expressi<strong>on</strong>s, 5, 6, 30Let_def (theorem), 30lex_prod_def (theorem), 117lexicographic product, 117lfp– applicati<strong>on</strong>s of, see CTLlinear arithmetic, 22–23, 166List (theory), 17list (type), 5, 9, 17list.split (theorem), 31Lowe, Gavin, 190–191Main (theory), 4major premise, 75make (c<strong>on</strong>stant), 158marginal comments, 60markup commands, 59max (c<strong>on</strong>stant), 22, 23measure functi<strong>on</strong>s, 116measure_def (theorem), 117meta-logic, 80methods, 16min (c<strong>on</strong>stant), 22, 23mixfix annotati<strong>on</strong>s, 53mod (symbol), 22, 23mod_div_equality (theorem), 168mod_mult_distrib (theorem), 168model checking example, 118–127modus p<strong>on</strong>ens, 67, 72m<strong>on</strong>o_def (theorem), 118m<strong>on</strong>ot<strong>on</strong>e functi<strong>on</strong>s, 118, 141– and inductive definiti<strong>on</strong>s, 139–140more (c<strong>on</strong>stant), 154, 155mp (theorem), 72mult_ac (theorems), 172multiple inheritance, 164multiset ordering, 117nat (type), 5, 22, 167–169nat_less_induct (theorem), 182natural deducti<strong>on</strong>, 67–68natural numbers, 22, 167–169Needham-Schroeder protocol, 189–191negati<strong>on</strong>, 73–75Nil (c<strong>on</strong>stant), 9no_asm (modifier), 29no_asm_simp (modifier), 29no_asm_use (modifier), 30no_vars (attribute), 62n<strong>on</strong>-standard reals, 170N<strong>on</strong>e (c<strong>on</strong>stant), 24normal form (command), 11notati<strong>on</strong> (command), 55notE (theorem), 73notI (theorem), 73numbers, 166–173numeric literals, 166–167– for type nat, 167– for type real, 170O (symbol), 114o, 203o_def (theorem), 112OF (attribute), 96–97of (attribute), 94, 97<strong>on</strong>ly (modifier), 29oops (command), 13opti<strong>on</strong> (type), 24ordered rewriting, 178ordered_field (type class), 171ordered_ring (type class), 171ordered_semiring (type class), 171overloading, 22, 160–162– and arithmetic, 167pairs and tuples, 23, 151–154parent theories, 4pattern matching


212 Index– and fun, 48patterns– higher-order, 179PDL, 120–122Power (theory), 173pr (command), 101prefer (command), 16, 101prefix annotati<strong>on</strong>, 55primitive recursi<strong>on</strong>, see recursi<strong>on</strong>,primitiveprimrec (command), 10, 39–44print mode, 55product type, see pairs and tuplesProof General, 7proof state, 12proofs– aband<strong>on</strong>ing, 13– examples of failing, 88–89protocols– security, 189–199quantifiers, 6– and inductive definiti<strong>on</strong>s, 138–139– existential, 82–83– for sets, 110– instantiating, 84– universal, 80–82r_into_rtrancl (theorem), 114r_into_trancl (theorem), 115range– of a functi<strong>on</strong>, 113– of a relati<strong>on</strong>, 114range (symbol), 113Range_iff (theorem), 114rat (type), 170–171rati<strong>on</strong>al numbers, 170–171real (type), 170–171real numbers, 170–171recdef (command)– and numeric literals, 167record (command), 154records, 154–159– extensible, 155–157recursi<strong>on</strong>– primitive, 18recursi<strong>on</strong> inducti<strong>on</strong>, 50–51reflexive and transitive closure, 114–116reflexive transitive closure– defining inductively, 135–137rel_comp_def (theorem), 114relati<strong>on</strong>s, 113–116– well-founded, 116–117rename_tac (method), 83rev (c<strong>on</strong>stant), 10–15, 35rewrite rules, 27– permutative, 178rewriting, 27ring (type class), 171ring_no_zero_divisors (type class),171ringppower (type class), 173rtrancl_refl (theorem), 114rtrancl_trans (theorem), 114rule inducti<strong>on</strong>, 130–132rule inversi<strong>on</strong>, 132–133, 142rule_format (attribute), 181rule_tac (method), 76– and renaming, 83safe (method), 91, 92safe rules, 90searching theorems, 33, 93sect (command), 59secti<strong>on</strong> (command), 59selector– record, 155semiring (type class), 171sessi<strong>on</strong>, 58set (type), 5, 107set comprehensi<strong>on</strong>s, 109–110set_ext (theorem), 108sets, 107–111– finite, 111– notati<strong>on</strong> for finite, 109Show Types (Proof General), 7show_main_goal (flag), 12simp (attribute), 12, 28simp (method), 28simp del (attribute), 28simp_all (method), 29, 39simplificati<strong>on</strong>, 27–35, 177–180– of let-expressi<strong>on</strong>s, 30– with definiti<strong>on</strong>s, 30– with/of assumpti<strong>on</strong>s, 29simplificati<strong>on</strong> rule, 179–180simplificati<strong>on</strong> rules, 28– adding and deleting, 29simplified (attribute), 94, 97size (c<strong>on</strong>stant), 17snd (c<strong>on</strong>stant), 23SOME (symbol), 86SOME, 203Some (c<strong>on</strong>stant), 24some_equality (theorem), 87someI (theorem), 87


Index 213someI2 (theorem), 87someI_ex (theorem), 87sorts, 165source comments, 60spec (theorem), 81split (attribute), 32split (c<strong>on</strong>stant), 152split (method), 31, 152split (modifier), 32split rule, 32split_if (theorem), 31split_if_asm (theorem), 32ssubst (theorem), 77structural inducti<strong>on</strong>, see inducti<strong>on</strong>,structuralsubclasses, 160, 164subgoal numbering, 46subgoal_tac (method), 99subgoals, 12subsect (command), 59subsecti<strong>on</strong> (command), 59subset relati<strong>on</strong>, 108subsetD (theorem), 108subsetI (theorem), 108subst (method), 78substituti<strong>on</strong>, 77–80subsubsect (command), 59subsubsecti<strong>on</strong> (command), 59Suc (c<strong>on</strong>stant), 22surj_def (theorem), 112surjecti<strong>on</strong>s, 112sym (theorem), 95symbols, 54syntax, 6, 11tacticals, 100tactics, 12tagged command regi<strong>on</strong>s, 63term (command), 16term rewriting, 27terminati<strong>on</strong>, see functi<strong>on</strong>s, totalterms, 5text, 61text blocks, 60THE (symbol), 86the_equality (theorem), 86THEN (attribute), 95, 97, 103theorem (command), 12, 13theories, 4theory (command), 4theory files, 4thm (command), 16tl (c<strong>on</strong>stant), 17ToyList example, 9–15tracing the simplifier, 32trancl_trans (theorem), 115transiti<strong>on</strong> systems, 119tries, 44–47True (c<strong>on</strong>stant), 5truncate (c<strong>on</strong>stant), 158tuples, see pairs and tuplestxt, 61typ (command), 16type c<strong>on</strong>straints, 6type c<strong>on</strong>structors, 5type inference, 5type syn<strong>on</strong>yms, 24type variables, 5typedecl (command), 119, 173typedef (command), 174–176types, 4–5– declaring, 173– defining, 174–176types (command), 24Ullman, J. D., 147UN, 203Un, 203UN_E (theorem), 110UN_I (theorem), 110UN_iff (theorem), 110Un_subset_iff (theorem), 108unfold (method), 30unificati<strong>on</strong>, 76–79UNION (c<strong>on</strong>stant), 111Uni<strong>on</strong>, 203uni<strong>on</strong>– indexed, 110Uni<strong>on</strong>_iff (theorem), 110unit (type), 24unknowns, 7, 68unsafe rules, 90update– record, 155updating a functi<strong>on</strong>, 111value (command), 11variables, 7– schematic, 7– type, 5vimage_def (theorem), 113wf_induct (theorem), 117wf_inv_image (theorem), 117wf_less_than (theorem), 116wf_lex_prod (theorem), 117wf_measure (theorem), 117

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!