<<

Miscellaneous HOL Examples

December 12, 2016

Contents

1 Some Isar command definitions 15 1.1 Diagnostic command: no state change...... 16 1.2 Old-style global theory declaration...... 16 1.3 Local theory specification...... 16

2 Infinite Sets and Related Concepts 17 2.1 Infinitely Many and Almost All...... 18 2.2 Enumeration of an Infinite Set...... 21

3 Ad Hoc Overloading 24 3.1 Plain Ad Hoc Overloading...... 24 3.2 Adhoc Overloading inside Locales...... 25

4 Permutation Types 27

5 Example of Declaring an Oracle 29 5.1 Oracle declaration...... 29 5.2 Oracle as low-level rule...... 29 5.3 Oracle as proof method...... 30

6 Abstract Natural Numbers primitive recursion 34

7 Proof by guessing 37

8 Examples of function definitions 38 8.1 Very basic...... 38 8.2 Currying...... 38 8.3 Nested recursion...... 38 8.3.1 Here comes McCarthy’s 91-function...... 39 8.4 More general patterns...... 39 8.4.1 Overlapping patterns...... 39 8.4.2 Guards...... 40

1 8.5 Mutual Recursion...... 41 8.6 Definitions in local contexts...... 41 8.7 fun-cases ...... 42 8.7.1 Predecessor...... 42 8.7.2 List to option...... 42 8.7.3 Boolean Functions...... 43 8.7.4 Many parameters...... 43 8.8 Partial Function Definitions...... 43 8.9 Regression tests...... 43 8.9.1 Context recursion...... 44 8.9.2 A combination of context and nested recursion.... 44 8.9.3 Context, but no recursive call...... 44 8.9.4 Tupled nested recursion...... 44 8.9.5 Let...... 44 8.9.6 Abbreviations...... 45 8.9.7 Simple Higher-Order Recursion...... 45 8.9.8 Pattern matching on records...... 45 8.9.9 The diagonal function...... 45 8.9.10 Many equations (quadratic blowup)...... 46 8.9.11 Automatic pattern splitting...... 46 8.9.12 Polymorphic partial-function...... 46

9 Examples of automatically derived induction rules 47 9.1 Some simple induction principles on nat...... 47

10 Test of Locale Interpretation 48

11 Interpretation of Defined Concepts 48 11.1 Lattices...... 48 11.1.1 Definitions...... 48 11.1.2 Total order <= on int ...... 57 11.1.3 Total order <= on nat ...... 58 11.1.4 Lattice dvd on nat ...... 59 11.2 Group example with defined operations inv and unit ..... 61 11.2.1 Locale declarations and lemmas...... 61 11.2.2 Interpretation of Functions...... 65

12 Using extensible records in HOL – points and coloured points 66 12.1 Points...... 67 12.1.1 Introducing concrete records and record schemes... 67 12.1.2 Record selection and record update...... 67 12.1.3 Some lemmas about records...... 67 12.2 Coloured points: record extension...... 69 12.2.1 Non-coercive structural subtyping...... 70

2 12.3 Other features...... 70 12.4 A more complex record expression...... 72 12.5 Some code generation...... 72

13 A general “while” combinator 72 13.1 Partial version...... 72 13.2 Total version...... 76

14 An application of the While combinator 82 14.1 Example...... 82

15 Monoids and Groups as predicates over record schemes 83

16 Binary arithmetic examples 83 16.1 Regression Testing for Cancellation Simprocs...... 83 16.2 Arithmetic Method Tests...... 85 16.3 The ...... 86 16.4 The Natural Numbers...... 89 16.5 Real Arithmetic...... 91 16.5.1 Addition...... 91 16.5.2 Negation...... 91 16.5.3 Multiplication...... 91 16.5.4 Inequalities...... 91 16.5.5 Powers...... 92 16.5.6 Tests...... 92 16.6 Complex Arithmetic...... 98

17 Examples for hexadecimal and binary numerals 99

18 Antiquotations 99

19 Multiple nested quotations and anti-quotations 100

20 Partial equivalence relations 101 20.1 Partial equivalence...... 101 20.2 Equivalence on function spaces...... 102 20.3 Total equivalence...... 103 20.4 Quotient types...... 103 20.5 Equality on quotients...... 104 20.6 Picking representing elements...... 105

21 Summing natural numbers 106

3 22 Three Divides Theorem 108 22.1 Abstract...... 108 22.2 Formal proof...... 108 22.2.1 Miscellaneous summation lemmas...... 108 22.2.2 Generalised Three Divides...... 109 22.2.3 Three Divides Natural...... 110

23 The Cubic and Quartic Root Formulas 112

24 The Cubic Formula 112

25 The Quartic Formula 115

26 The Pythagorean Theorem 115

27 Higher-Order Logic: Intuitionistic predicate calculus prob- lems 116

28 CTL formulae 122 28.1 Basic fixed point properties...... 123 28.2 The tree induction principle...... 125 28.3 An application of tree induction...... 127

29 Arithmetic 127 29.1 Splitting of Operators: max, min, abs, op −, nat, op mod, op div ...... 128 29.2 Meta-Logic...... 130 29.3 Various Other Examples...... 130

30 2-3 Trees 132

31 (Finite) multisets 141 31.1 The type of multisets...... 141 31.2 Representing multisets...... 142 31.3 Basic operations...... 144 31.3.1 Conversion to set and membership...... 144 31.3.2 Union...... 146 31.3.3 Difference...... 147 31.3.4 Equality of multisets...... 149 31.3.5 Pointwise ordering induced by count...... 151 31.3.6 Intersection and bounded union...... 155 31.3.7 Additional intersection facts...... 156 31.3.8 Additional bounded union facts...... 159 31.3.9 Subset is an order...... 160 31.4 Replicate and repeat operations...... 160

4 31.4.1 Simprocs...... 161 31.4.2 Conditionally complete lattice...... 162 31.4.3 Filter (with comprehension syntax)...... 167 31.4.4 Size...... 169 31.5 Induction and case splits...... 171 31.5.1 Strong induction and subset induction for multisets. 172 31.6 The fold combinator...... 173 31.7 Image...... 175 31.8 Further conversions...... 177 31.9 More properties of the replicate and repeat operations.... 183 31.10Big operators...... 184 31.11Alternative representations...... 191 31.11.1 Lists...... 191 31.12The multiset order...... 195 31.12.1 Well-foundedness...... 195 31.12.2 Closure-free presentation...... 198 31.13The multiset extension is cancellative for multiset union... 199 31.14Quasi-executable version of the multiset extension...... 200 31.14.1 Partial-order properties...... 201 31.14.2 Monotonicity of multiset union...... 203 31.14.3 Termination proofs with multiset orders...... 203 31.15Legacy theorem bindings...... 206 31.16Naive implementation using lists...... 208 31.17BNF setup...... 212 31.18Size setup...... 219

32 Bubblesort 219

33 Merge Sort 221

34 A lemma for Lagrange’s theorem 222

35 Groebner Basis Examples 223 35.1 Basic examples...... 223 35.2 Lemmas for Lagrange’s theorem...... 224 35.3 Colinearity is invariant by rotation...... 225

36 Substitution and Unification 225 36.1 Terms...... 226 36.2 Substitutions...... 226 36.3 Unifiers and Most General Unifiers...... 228 36.4 The unification algorithm...... 229 36.5 Properties used in termination proof...... 229 36.6 Termination proof...... 233

5 36.7 Unification returns a Most General Unifier...... 233 36.8 Unification returns Idempotent Substitution...... 234

37 Primitive Recursive Functions 236 37.1 Ackermann’s Function...... 236 37.2 Primitive Recursive Functions...... 238

38 The Full Theorem of Tarski 241 38.1 Partial Order...... 244 38.2 sublattice...... 248 38.3 lub...... 248 38.4 glb...... 250 38.5 fixed points...... 251 38.6 lemmas for Tarski, lub...... 251 38.7 Tarski fixpoint theorem 1, first part...... 252 38.8 interval...... 253 38.9 Top and Bottom...... 256 38.10fixed points form a partial order...... 257

39 Classical Predicate Calculus Problems 260 39.1 Traditional Classical Reasoner...... 260 39.1.1 Pelletier’s examples...... 260 39.1.2 Classical Logic: examples with quantifiers...... 262 39.1.3 Problems requiring quantifier duplication...... 262 39.1.4 Hard examples with quantifiers...... 263 39.1.5 Problems (mainly) involving equality or functions.. 266 39.2 Model Elimination Prover...... 268 39.2.1 Pelletier’s examples...... 269 39.2.2 Classical Logic: examples with quantifiers...... 270 39.2.3 Hard examples with quantifiers...... 271

40 Set Theory examples: Cantor’s Theorem, Schr¨oder-Bernstein Theorem, etc. 277 40.1 Examples for the blast paper...... 277 40.2 Cantor’s Theorem: There is no surjection from a set to its powerset...... 278 40.3 The Schr¨oder-BernsteinTheorem...... 278 40.4 A simple party theorem...... 279

41 Examples and regression tests for automated termination proofs 281 41.1 Manually giving termination relations using relation and mea- sure ...... 281 41.2 lexicographic-order: Trivial examples...... 282

6 41.3 Examples on natural numbers...... 282 41.4 Simple examples with other datatypes than nat, e.g. trees and lists...... 283 41.5 Examples with mutual recursion...... 284 41.6 Refined analysis: The size-change method...... 284

42 Coherent Logic Problems 286 42.1 Equivalence of two versions of Pappus’ Axiom...... 286 42.2 Preservation of the Diamond Property under reflexive closure 287

43 Some examples for Presburger Arithmetic 288

44 Generic reflection and reification 290

45 Examples for generic reflection and reification 291

46 (semi)rings 301 46.1 Irreducible and prime elements...... 301 46.2 Generalized primes: normalized prime elements...... 308 46.3 In a semiring with GCD, each irreducible element is a prime elements...... 313 46.4 Factorial semirings: algebraic structures with factorizations...... 314 46.5 GCD and LCM computation with unique factorizations... 331

47 Abstract euclidean algorithm 339 47.1 Typical instances...... 354

48 Primes 354 48.0.1 Make prime naively executable...... 358 48.1 Infinitely many primes...... 359 48.2 Powers of Primes...... 360 48.3 Chinese Remainder Theorem Variants...... 361 48.4 Multiplicity and primality for natural numbers and integers. 363

49 Square roots of primes are irrational 367 49.1 Variations...... 368

50 Square roots of primes are irrational (script version) 369 50.1 Preliminaries...... 369 50.2 Main theorem...... 370

51 Type of finite sets defined as a subtype of sets 370 51.1 Definition of the type...... 370 51.2 Basic operations and type class instantiations...... 370

7 51.3 Other operations...... 373 51.4 Transferred lemmas from Set.thy...... 375 51.5 Additional lemmas...... 380 51.5.1 fsingleton ...... 380 51.5.2 femepty ...... 380 51.5.3 fset ...... 380 51.5.4 ffilter ...... 380 51.5.5 fset-of-list ...... 381 51.5.6 finsert ...... 381 51.5.7 fimage ...... 381 51.5.8 bounded quantification...... 381 51.5.9 fcard ...... 382 51.5.10 ffold ...... 383 51.6 Choice in fsets...... 385 51.7 Induction and Cases rules for fsets...... 385 51.8 Setup for Lifting/Transfer...... 386 51.8.1 Relator and predicator properties...... 386 51.8.2 Transfer rules for the Transfer package...... 387 51.9 BNF setup...... 389 51.10Size setup...... 391 51.11Advanced relator customization...... 391 51.12Quickcheck setup...... 392 51.131. A missing transfer rule...... 394 51.142. Unwanted instantiation of a transfer relation variable... 395

52 Using the transfer method between nat and int 396 52.1 Correspondence relation...... 396 52.2 Transfer domain rules...... 396 52.3 Transfer rules...... 396 52.4 Transfer examples...... 398

53 Various examples for transfer procedure 400

54 Simple example for table-based implementation of the re- flexive transitive closure 401

55 Divergence of the Harmonic Series 402 55.1 Abstract...... 402 55.2 Formal Proof...... 402

56 Examples for the ’refute’ command 407 56.1 Examples and Test Cases...... 408 56.1.1 Propositional logic...... 408 56.1.2 Predicate logic...... 409

8 56.1.3 Equality...... 409 56.1.4 First-Order Logic...... 409 56.1.5 Higher-Order Logic...... 411 56.1.6 Meta-logic...... 413 56.1.7 Schematic variables...... 413 56.1.8 Abstractions...... 414 56.1.9 Sets...... 414 56.1.10 undefined...... 415 56.1.11 The...... 415 56.1.12 Eps...... 416 56.1.13 Subtypes (typedef), typedecl...... 416 56.1.14 Inductive datatypes...... 416 56.1.15 Examples involving special functions...... 422 56.1.16 Type classes and overloading...... 423

57 Implementation of Association Lists 425 57.1 update and updates ...... 425 57.2 delete ...... 428 57.3 update-with-aux and delete-aux ...... 429 57.4 restrict ...... 431 57.5 clearjunk ...... 433 57.6 map-ran ...... 435 57.7 merge ...... 435 57.8 compose ...... 437 57.9 map-entry ...... 440 57.10map-default ...... 440

58 An abstract view on maps for code generation. 441 58.1 Parametricity transfer rules...... 441 58.2 Type definition and primitive operations...... 443 58.3 Functorial structure...... 444 58.4 Derived operations...... 445 58.5 Properties...... 446 58.6 Code generator setup...... 455

59 Implementation of mappings with Association Lists 455

60 A simple cookbook example how to eliminate choice in pro- grams. 458

61 Theory of Integration on real intervals 460 61.1 Gauges...... 460 61.2 Gauge-fine divisions...... 460 61.3 Riemann sum...... 464

9 61.4 Gauge integrability (definite)...... 465

62 Positive real numbers 473 62.1 Properties of Ordering...... 476 62.2 Properties of Addition...... 477 62.3 Properties of Multiplication...... 479 62.4 Distribution of Multiplication across Addition...... 483 62.5 Existence of Inverse, a Positive Real...... 484 62.6 Gleason’s Lemma 9-3.4, page 122...... 486 62.7 Gleason’s Lemma 9-3.6...... 488 62.8 Existence of Inverse: Part 2...... 488 62.9 Subtraction for Positive Reals...... 491 62.10proving that S ≤ R + D — trickier...... 493 62.11Completeness of type preal ...... 495

63 Defining the Reals from the Positive Reals 496 63.1 Equivalence relation over positive reals...... 497 63.2 Addition and Subtraction...... 498 63.3 Multiplication...... 499 63.4 Inverse and Division...... 501 63.5 The Real Numbers form a Field...... 501 63.6 The ≤ Ordering...... 501 63.7 The Reals Form an Ordered Field...... 504 63.8 Theorems About the Ordering...... 505 63.9 Completeness of Positive Reals...... 506 63.10The Archimedean Property of the Reals...... 510

64 Quicksort with function package 511

65 A Formulation of the Birthday Paradox 512

66 Cardinality 512

67 Birthday paradox 514

68 Examples for the list comprehension to set comprehension simproc 514 68.1 Some own examples for set (case ..) simpproc...... 515 68.2 Existing examples from the List theory...... 515

69 Finite sequences 516

10 70 Testing of arithmetic simprocs 517 70.1 ML bindings...... 517 70.2 Cancellation simprocs from Nat.thy ...... 517 70.3 Abelian group cancellation simprocs...... 518 70.4 int-combine-numerals ...... 518 70.5 inteq-cancel-numerals ...... 519 70.6 intless-cancel-numerals ...... 520 70.7 ring-eq-cancel-numeral-factor ...... 520 70.8 int-div-cancel-numeral-factors ...... 521 70.9 ring-less-cancel-numeral-factor ...... 521 70.10ring-le-cancel-numeral-factor ...... 522 70.11divide-cancel-numeral-factor ...... 522 70.12ring-eq-cancel-factor ...... 523 70.13int-div-cancel-factor ...... 523 70.14divide-cancel-factor ...... 524 70.15linordered-ring-less-cancel-factor ...... 524 70.16linordered-ring-le-cancel-factor ...... 525 70.17field-combine-numerals ...... 525 70.18nat-combine-numerals ...... 526 70.19nateq-cancel-numerals ...... 526 70.20natless-cancel-numerals ...... 527 70.21natle-cancel-numerals ...... 528 70.22natdiff-cancel-numerals ...... 528 70.23Factor-cancellation simprocs for type nat ...... 530 70.24Numeral-cancellation simprocs for type nat ...... 531 70.25Integer numeral div/mod simprocs...... 531 70.26A dedicated type for relations...... 532 70.26.1 Definition of the dedicated type for relations..... 532 70.26.2 Constant definitions on relations...... 533 70.26.3 Code generation...... 533

71 A generic phantom type 534

72 Cardinality of types 534 72.1 Preliminary lemmas...... 535 72.2 Cardinalities of types...... 535 72.3 Classes with at least 1 and 2...... 538 72.4 A type class for deciding finiteness of types...... 538 72.5 A type class for computing the cardinality of types...... 538 72.6 Instantiations for card-UNIV ...... 539 72.7 Code setup for sets...... 543

11 73 Almost everywhere constant functions 546 73.1 The map-default operation...... 546 73.2 The finfun type...... 547 73.3 Kernel functions for type 0a ⇒f 0b ...... 551 73.4 Code generator setup...... 552 73.5 Setup for quickcheck...... 552 73.6 finfun-update as instance of comp-fun-commute ...... 552 73.7 Default value for FinFuns...... 553 73.8 Recursion combinator and well-formedness conditions.... 555 73.9 Weak induction rule and case analysis for FinFuns...... 563 73.10Function application...... 564 73.11Function composition...... 565 73.12Universal quantification...... 567 73.13A diagonal operator for FinFuns...... 568 73.14Currying for FinFuns...... 571 73.15Executable equality for FinFuns...... 573 73.16An operator that explicitly removes all redundant updates in the generated representations...... 573 73.17The domain of a FinFun as a FinFun...... 574 73.18The domain of a FinFun as a sorted list...... 575 73.18.1 Bundles for concrete syntax...... 579

74 Predicates modelled as FinFuns 580

75 Examples for the set comprehension to pointfree simproc 586

76 Testing simproc in code generation 588

77 Futures and parallel lists for code generated towards Is- abelle/ML 589 77.1 Futures...... 589 77.2 Parallel lists...... 589

78 Debugging facilities for code generated towards Isabelle/ML590

79 A simple example demonstrating parallelism for code gen- erated towards Isabelle/ML 591 79.1 Compute-intensive examples...... 591 79.1.1 Fragments of the harmonic series...... 591 79.1.2 The sieve of Erathostenes...... 591 79.1.3 Naive factorisation...... 592 79.2 Concurrent computation via futures...... 593

80 Immutable Arrays with Code Generation 593 80.1 Code Generation...... 594

12 81 Implementation of numbers by target-language in- tegers 596

82 Implementation of natural numbers by target-language in- tegers 599 82.1 Implementation for nat ...... 599

83 Implementation of natural and integer numbers by target- language integers 602

84 Tests for the Simps¡-¿Case conversion tools 603

85 Isabelle/ML basics 606

86 ML expressions 606

87 Antiquotations 606

88 Recursive ML evaluation 607

89 IDE support 607

90 Example: factorial and ackermann function in Isabelle/ML607

91 Parallel Isabelle/ML 608

92 Function specifications in Isabelle/HOL 608

93 The rewrite Proof Method by Example 609

94 Regression tests 615

95 Examples for proof methods ”sat” and ”satx” 615

96 A decision procedure for universal multivariate real arith- metic with addition, multiplication and ordering using semidef- inite programming 626

97 Bertrand’s Ballot Theorem 633 97.1 Preliminaries...... 633 97.2 Formalization of Problem Statement...... 633 97.2.1 Basic Definitions...... 633 97.2.2 Equivalence with Set Cardinality...... 634 97.3 Facts About valid-countings ...... 636 97.3.1 Non-Recursive Cases...... 636 97.4 Relation Between valid-countings and all-countings ...... 639 97.4.1 Executable Definition...... 640

13 97.4.2 Executable Definition...... 640

98 The Erdoes-Szekeres Theorem 640 98.1 Addition to Lattices-Big Theory...... 640 98.2 Additions to Finite-Set Theory...... 640 98.3 Definition of Monotonicity over a Carrier Set...... 641 98.4 The Erdoes-Szekeres Theorem following Seidenberg’s (1959) argument...... 642

99 Sum of Powers 644 99.1 Additions to Binomial Theory...... 644 99.2 Preliminaries...... 645 99.3 Bernoulli Numbers and Bernoulli Polynomials...... 645 99.4 Basic Observations on Bernoulli Polynomials...... 645 99.5 Sum of Powers with Bernoulli Polynomials...... 646 99.6 Instances for Square And Cubic Numbers...... 647

100A SAT-based Sudoku Solver 648

101The sieve of Eratosthenes 655 101.1Preliminary: strict divisibility...... 655 101.2Main corpus...... 655 101.3Application: smallest prime beyond a certain number.... 661

102Examples for code generation timing measures 663

103Permutations as abstract type 664 103.1Abstract type of permutations...... 664 103.2Identity, composition and inversion...... 666 103.3Orbit and order of elements...... 668 103.4Swaps...... 679 103.5Permutations specified by cycles...... 680 103.6Syntax...... 680

104Listswith elements distinct as canonical example for datatype invariants 680 104.1The type of distinct lists...... 680 104.2Executable version obeying invariant...... 682 104.3Induction principle and case distinction...... 683 104.4Functorial structure...... 684 104.5Quickcheck generators...... 684 104.6BNF instance...... 684

105Fragments on permuations 687

14 106Argo 693 106.1Propositional logic...... 693 106.2Equality, congruence and predicates...... 696 106.3Linear real arithmetic...... 699 106.3.1 Negation and subtraction...... 699 106.3.2 Multiplication...... 699 106.3.3 Division...... 700 106.3.4 Addition...... 700 106.3.5 Minimum and maximum...... 701 106.3.6 Absolute value...... 701 106.3.7 Equality...... 702 106.3.8 Less-equal...... 702 106.3.9 Less...... 703 106.3.10Otherexamples...... 703 106.4Larger examples...... 705

107Numeral Syntax for Types 720 107.1Numeral Types...... 720 107.2Locales for for modular arithmetic subtypes...... 721 107.3Ring class instances...... 723 107.4Order instances...... 726 107.5Code setup and type classes for code generation...... 726 107.6Syntax...... 729 107.7Examples...... 731

108Assigning lengths to types by type classes 731

109Proof of concept for algebraically founded bit word types 732 109.1Truncating bit representations of numeric types...... 732 109.2Bit strings as quotient type...... 735 109.2.1 Basic properties...... 735 109.2.2 Conversions...... 736 109.2.3 Properties...... 738 109.2.4 Division...... 738 109.2.5 Orderings...... 738

110Meson test cases 739 110.1Interactive examples...... 739

1 Some Isar command definitions theory Commands imports Main keywords print-test :: diag and

15 global-test :: thy-decl and local-test :: thy-decl begin

1.1 Diagnostic command: no state change

ML h Outer-Syntax.command @{command-keyword print-test} print term test (Parse.term >> (fn s => Toplevel.keep (fn st => let val ctxt = Toplevel.context-of st; val t = Syntax.read-term ctxt s; in Pretty.writeln (Syntax.pretty-term ctxt t) end))); i print-test x print-test λx. x = a

1.2 Old-style global theory declaration

ML h Outer-Syntax.command @{command-keyword global-test} test constant declaration (Parse.binding >> (fn b => Toplevel.theory (fn thy => let val thy 0 = Sign.add-consts [(b, @{typ 0a}, NoSyn)] thy; in thy 0 end))); i global-test a global-test b print-test a

1.3 Local theory specification

ML h Outer-Syntax.local-theory @{command-keyword local-test} test local definition (Parse.binding −− (@{keyword =} |−− Parse.term) >> (fn (b, s) => fn lthy => let val t = Syntax.read-term lthy s; val (def , lthy 0) = Local-Theory.define ((b, NoSyn), ((Thm.def-binding b, []), t)) lthy; in lthy 0 end)); i local-test true = True print-test true thm true-def local-test identity = λx. x

16 print-test identity x thm identity-def context fixes x y :: nat begin local-test test = x + y print-test test thm test-def end print-test test 0 1 thm test-def end

2 Infinite Sets and Related Concepts theory Infinite-Set imports Main begin

The set of natural numbers is infinite. lemma infinite-nat-iff-unbounded-le: infinite (S::nat set) ←→ (∀ m. ∃ n≥m. n ∈ S) using frequently-cofinite[of λx. x ∈ S] by (simp add: cofinite-eq-sequentially frequently-def eventually-sequentially) lemma infinite-nat-iff-unbounded: infinite (S::nat set) ←→ (∀ m. ∃ n>m. n ∈ S) using frequently-cofinite[of λx. x ∈ S] by (simp add: cofinite-eq-sequentially frequently-def eventually-at-top-dense) lemma finite-nat-iff-bounded: finite (S::nat set) ←→ (∃ k. S ⊆ {..

For a set of natural numbers to be infinite, it is enough to know that for any number larger than some k, there is some larger number that is an element of the set. lemma unbounded-k-infinite: ∀ m>k. ∃ n>m. n ∈ S =⇒ infinite (S::nat set) apply (clarsimp simp add: finite-nat-set-iff-bounded) apply (drule-tac x=Suc (max m k) in spec)

17 using less-Suc-eq by fastforce lemma nat-not-finite: finite (UNIV ::nat set) =⇒ R by simp lemma range-inj-infinite: inj (f ::nat ⇒ 0a) =⇒ infinite (range f ) proof assume finite (range f ) and inj f then have finite (UNIV ::nat set) by (rule finite-imageD) then show False by simp qed

The set of integers is also infinite. lemma infinite-int-iff-infinite-nat-abs: infinite (S::int set) ←→ infinite ((nat o abs) ‘S) by (auto simp: transfer-nat-int-set-relations o-def image-comp dest: finite-image-absD) proposition infinite-int-iff-unbounded-le: infinite (S::int set) ←→ (∀ m. ∃ n. |n| ≥ m ∧ n ∈ S) apply (simp add: infinite-int-iff-infinite-nat-abs infinite-nat-iff-unbounded-le o-def image-def ) apply (metis abs-ge-zero nat-le-eq-zle le-nat-iff ) done proposition infinite-int-iff-unbounded: infinite (S::int set) ←→ (∀ m. ∃ n. |n| > m ∧ n ∈ S) apply (simp add: infinite-int-iff-infinite-nat-abs infinite-nat-iff-unbounded o-def image-def ) apply (metis (full-types) nat-le-iff nat-mono not-le) done proposition finite-int-iff-bounded: finite (S::int set) ←→ (∃ k. abs ‘ S ⊆ {..

2.1 Infinitely Many and Almost All

We often need to reason about the existence of infinitely many (resp., all but finitely many) objects satisfying some predicate, so we introduce corre- sponding binders and their proof rules. lemma not-INFM [simp]: ¬ (INFM x. P x) ←→ (MOST x. ¬ P x) by (fact not-frequently) lemma not-MOST [simp]: ¬ (MOST x. P x) ←→ (INFM x. ¬ P x) by (fact not-eventually)

18 lemma INFM-const [simp]: (INFM x:: 0a. P) ←→ P ∧ infinite (UNIV :: 0a set) by (simp add: frequently-const-iff ) lemma MOST-const [simp]: (MOST x:: 0a. P) ←→ P ∨ finite (UNIV :: 0a set) by (simp add: eventually-const-iff ) lemma INFM-imp-distrib:(INFM x. P x −→ Q x) ←→ ((MOST x. P x) −→ (INFM x. Q x)) by (simp only: imp-conv-disj frequently-disj-iff not-eventually) lemma MOST-imp-iff : MOST x. P x =⇒ (MOST x. P x −→ Q x) ←→ (MOST x. Q x) by (auto intro: eventually-rev-mp eventually-mono) lemma INFM-conjI : INFM x. P x =⇒ MOST x. Q x =⇒ INFM x. P x ∧ Q x by (rule frequently-rev-mp[of P]) (auto elim: eventually-mono)

Properties of quantifiers with injective functions. lemma INFM-inj : INFM x. P (f x) =⇒ inj f =⇒ INFM x. P x using finite-vimageI [of {x. P x} f ] by (auto simp: frequently-cofinite) lemma MOST-inj : MOST x. P x =⇒ inj f =⇒ MOST x. P (f x) using finite-vimageI [of {x. ¬ P x} f ] by (auto simp: eventually-cofinite)

Properties of quantifiers with singletons. lemma not-INFM-eq [simp]: ¬ (INFM x. x = a) ¬ (INFM x. a = x) unfolding frequently-cofinite by simp-all lemma MOST-neq [simp]: MOST x. x 6= a MOST x. a 6= x unfolding eventually-cofinite by simp-all lemma INFM-neq [simp]: (INFM x:: 0a. x 6= a) ←→ infinite (UNIV :: 0a set) (INFM x:: 0a. a 6= x) ←→ infinite (UNIV :: 0a set) unfolding frequently-cofinite by simp-all lemma MOST-eq [simp]: (MOST x:: 0a. x = a) ←→ finite (UNIV :: 0a set) (MOST x:: 0a. a = x) ←→ finite (UNIV :: 0a set) unfolding eventually-cofinite by simp-all lemma MOST-eq-imp: MOST x. x = a −→ P x MOST x. a = x −→ P x

19 unfolding eventually-cofinite by simp-all

Properties of quantifiers over the naturals. lemma MOST-nat:(∀ ∞n. P (n::nat)) ←→ (∃ m. ∀ n>m. P n) by (auto simp add: eventually-cofinite finite-nat-iff-bounded-le subset-eq not-le[symmetric]) lemma MOST-nat-le:(∀ ∞n. P (n::nat)) ←→ (∃ m. ∀ n≥m. P n) by (auto simp add: eventually-cofinite finite-nat-iff-bounded subset-eq not-le[symmetric]) lemma INFM-nat:(∃ ∞n. P (n::nat)) ←→ (∀ m. ∃ n>m. P n) by (simp add: frequently-cofinite infinite-nat-iff-unbounded) lemma INFM-nat-le:(∃ ∞n. P (n::nat)) ←→ (∀ m. ∃ n≥m. P n) by (simp add: frequently-cofinite infinite-nat-iff-unbounded-le) lemma MOST-INFM : infinite (UNIV :: 0a set) =⇒ MOST x:: 0a. P x =⇒ INFM x:: 0a. P x by (simp add: eventually-frequently) lemma MOST-Suc-iff :(MOST n. P (Suc n)) ←→ (MOST n. P n) by (simp add: cofinite-eq-sequentially eventually-sequentially-Suc) lemma shows MOST-SucI : MOST n. P n =⇒ MOST n. P (Suc n) and MOST-SucD: MOST n. P (Suc n) =⇒ MOST n. P n by (simp-all add: MOST-Suc-iff ) lemma MOST-ge-nat: MOST n::nat. m ≤ n by (simp add: cofinite-eq-sequentially eventually-ge-at-top) lemma Inf-many-def : Inf-many P ←→ infinite {x. P x} by (fact frequently-cofinite) lemma Alm-all-def : Alm-all P ←→ ¬ (INFM x. ¬ P x) by simp lemma INFM-iff-infinite:(INFM x. P x) ←→ infinite {x. P x} by (fact frequently-cofinite) lemma MOST-iff-cofinite:(MOST x. P x) ←→ finite {x. ¬ P x} by (fact eventually-cofinite) lemma INFM-EX :(∃ ∞x. P x) =⇒ (∃ x. P x) by (fact frequently-ex) lemma ALL-MOST : ∀ x. P x =⇒ ∀ ∞x. P x by (fact always-eventually) V lemma INFM-mono: ∃ ∞x. P x =⇒ ( x. P x =⇒ Q x) =⇒ ∃ ∞x. Q x by (fact frequently-elim1 ) V lemma MOST-mono: ∀ ∞x. P x =⇒ ( x. P x =⇒ Q x) =⇒ ∀ ∞x. Q x by (fact eventually-mono) lemma INFM-disj-distrib:(∃ ∞x. P x ∨ Q x) ←→ (∃ ∞x. P x) ∨ (∃ ∞x. Q x) by (fact frequently-disj-iff ) lemma MOST-rev-mp: ∀ ∞x. P x =⇒ ∀ ∞x. P x −→ Q x =⇒ ∀ ∞x. Q x by (fact eventually-rev-mp) lemma MOST-conj-distrib:(∀ ∞x. P x ∧ Q x) ←→ (∀ ∞x. P x) ∧ (∀ ∞x. Q x) by (fact eventually-conj-iff ) lemma MOST-conjI : MOST x. P x =⇒ MOST x. Q x =⇒ MOST x. P x ∧ Q x by (fact eventually-conj )

20 lemma INFM-finite-Bex-distrib: finite A =⇒ (INFM y. ∃ x∈A. P x y) ←→ (∃ x∈A. INFM y. P x y) by (fact frequently-bex-finite-distrib) lemma MOST-finite-Ball-distrib: finite A =⇒ (MOST y. ∀ x∈A. P x y) ←→ (∀ x∈A. MOST y. P x y) by (fact eventually-ball-finite-distrib) lemma INFM-E: INFM x. P x =⇒ (Vx. P x =⇒ thesis) =⇒ thesis by (fact frequentlyE) lemma MOST-I :(Vx. P x) =⇒ MOST x. P x by (rule eventuallyI ) lemmas MOST-iff-finiteNeg = MOST-iff-cofinite

2.2 Enumeration of an Infinite Set

The set’s element type must be wellordered (e.g. the natural numbers).

Could be generalized to enumerate 0 S n = (SOME t. t ∈ s ∧ finite {s ∈ S. s < t} ∧ card {s ∈ S. s < t} = n). primrec (in wellorder) enumerate :: 0a set ⇒ nat ⇒ 0a where enumerate-0 : enumerate S 0 = (LEAST n. n ∈ S) | enumerate-Suc: enumerate S (Suc n) = enumerate (S − {LEAST n. n ∈ S}) n lemma enumerate-Suc 0: enumerate S (Suc n) = enumerate (S − {enumerate S 0 }) n by simp lemma enumerate-in-set: infinite S =⇒ enumerate S n ∈ S apply (induct n arbitrary: S) apply (fastforce intro: LeastI dest!: infinite-imp-nonempty) apply simp apply (metis DiffE infinite-remove) done declare enumerate-0 [simp del] enumerate-Suc [simp del] lemma enumerate-step: infinite S =⇒ enumerate S n < enumerate S (Suc n) apply (induct n arbitrary: S) apply (rule order-le-neq-trans) apply (simp add: enumerate-0 Least-le enumerate-in-set) apply (simp only: enumerate-Suc 0) apply (subgoal-tac enumerate (S − {enumerate S 0 }) 0 ∈ S − {enumerate S 0 }) apply (blast intro: sym) apply (simp add: enumerate-in-set del: Diff-iff ) apply (simp add: enumerate-Suc 0) done lemma enumerate-mono: m < n =⇒ infinite S =⇒ enumerate S m < enumerate S n apply (erule less-Suc-induct) apply (auto intro: enumerate-step)

21 done lemma le-enumerate: assumes S: infinite S shows n ≤ enumerate S n using S proof (induct n) case 0 then show ?case by simp next case (Suc n) then have n ≤ enumerate S n by simp also note enumerate-mono[of n Suc n, OF - hinfinite S i] finally show ?case by simp qed lemma enumerate-Suc 00: fixes S :: 0a::wellorder set assumes infinite S shows enumerate S (Suc n) = (LEAST s. s ∈ S ∧ enumerate S n < s) using assms proof (induct n arbitrary: S) case 0 then have ∀ s ∈ S. enumerate S 0 ≤ s by (auto simp: enumerate.simps intro: Least-le) then show ?case unfolding enumerate-Suc 0 enumerate-0 [of S − {enumerate S 0 }] by (intro arg-cong[where f = Least] ext) auto next case (Suc n S) show ?case using enumerate-mono[OF zero-less-Suc hinfinite S i, of n] hinfinite S i apply (subst (1 2 ) enumerate-Suc 0) apply (subst Suc) using hinfinite S i apply simp apply (intro arg-cong[where f = Least] ext) apply (auto simp: enumerate-Suc 0[symmetric]) done qed lemma enumerate-Ex: assumes S: infinite (S::nat set) shows s ∈ S =⇒ ∃ n. enumerate S n = s proof (induct s rule: less-induct) case (less s) show ?case proof cases

22 let ?y = Max {s 0∈S. s 0 < s} assume ∃ y∈S. y < s then have y: Vx. ?y < x ←→ (∀ s 0∈S. s 0 < s −→ s 0 < x) by (subst Max-less-iff ) auto then have y-in: ?y ∈ {s 0∈S. s 0 < s} by (intro Max-in) auto with less.hyps[of ?y] obtain n where enumerate S n = ?y by auto with S have enumerate S (Suc n) = s by (auto simp: y less enumerate-Suc 00 intro!: Least-equality) then show ?case by auto next assume ∗: ¬ (∃ y∈S. y < s) then have ∀ t∈S. s ≤ t by auto with hs ∈ S i show ?thesis by (auto intro!: exI [of - 0 ] Least-equality simp: enumerate-0 ) qed qed lemma bij-enumerate: fixes S :: nat set assumes S: infinite S shows bij-betw (enumerate S) UNIV S proof − have Vn m. n 6= m =⇒ enumerate S n 6= enumerate S m using enumerate-mono[OF - hinfinite S i] by (auto simp: neq-iff ) then have inj (enumerate S) by (auto simp: inj-on-def ) moreover have ∀ s ∈ S. ∃ i. enumerate S i = s using enumerate-Ex[OF S] by auto moreover note hinfinite S i ultimately show ?thesis unfolding bij-betw-def by (auto intro: enumerate-in-set) qed

A pair of weird and wonderful lemmas from HOL Light lemma finite-transitivity-chain: assumes finite A and R: Vx. ∼ R x x Vx y z. [[R x y; R y z]] =⇒ R x z and A: Vx. x ∈ A =⇒ ∃ y. y ∈ A ∧ R x y shows A = {} using hfinite Ai A proof (induction A) case (insert a A) with R show ?case by (metis empty-iff insert-iff ) qed simp corollary Union-maximal-sets:

23 assumes finite F shows S {T ∈ F. ∀ U ∈F. ¬ T ⊂ U } = S F (is ?lhs = ?rhs) proof show ?rhs ⊆ ?lhs proof (rule Union-subsetI ) fix S assume S ∈ F have {T ∈ F. S ⊆ T } = {} if ∼ (∃ y. y ∈ {T ∈ F. ∀ U ∈F. ¬ T ⊂ U } ∧ S ⊆ y) apply (rule finite-transitivity-chain [of - λTU . S ⊆ T ∧ T ⊂ U ]) using assms that apply auto by (blast intro: dual-order.trans psubset-imp-subset) then show ∃ y. y ∈ {T ∈ F. ∀ U ∈F. ¬ T ⊂ U } ∧ S ⊆ y using hS ∈ F i by blast qed qed force end

3 Ad Hoc Overloading theory Adhoc-Overloading-Examples imports Main ∼∼/src/HOL/Library/Infinite-Set ∼∼/src/Tools/Adhoc-Overloading begin Adhoc overloading allows to overload a constant depending on its type. Typ- ically this involves to introduce an uninterpreted constant (used for input and output) and then add some variants (used internally).

3.1 Plain Ad Hoc Overloading

Consider the type of first-order terms. datatype ( 0a, 0b) term = Var 0b | Fun 0a ( 0a, 0b) term list The set of variables of a term might be computed as follows. fun term-vars :: ( 0a, 0b) term ⇒ 0b set where term-vars (Var x) = {x} | term-vars (Fun f ts) = S set (map term-vars ts) However, also for rules (i.e., pairs of terms) and term rewrite systems (i.e., sets of rules), the set of variables makes sense. Thus we introduce an un- specified constant vars.

24 consts vars :: 0a ⇒ 0b set

Which is then overloaded with variants for terms, rules, and TRSs. adhoc-overloading vars term-vars value vars (Fun 00f 00 [Var 0 , Var 1 ]) fun rule-vars :: ( 0a, 0b) term × ( 0a, 0b) term ⇒ 0b set where rule-vars (l, r) = vars l ∪ vars r adhoc-overloading vars rule-vars value vars (Var 1 , Var 0 ) definition trs-vars :: (( 0a, 0b) term × ( 0a, 0b) term) set ⇒ 0b set where trs-vars R = S (rule-vars ‘ R) adhoc-overloading vars trs-vars value vars {(Var 1 , Var 0 )}

Sometimes it is necessary to add explicit type constraints before a variant can be determined. value vars (R :: (( 0a, 0b) term × ( 0a, 0b) term) set)

It is also possible to remove variants. no-adhoc-overloading vars term-vars rule-vars

As stated earlier, the overloaded constant is only used for input and output. Internally, always a variant is used, as can be observed by the configuration option show-variants. adhoc-overloading vars term-vars declare [[show-variants]] term vars (Var 1 )

3.2 Adhoc Overloading inside Locales

As example we use permutations that are parametrized over an atom type 0a. definition perms :: ( 0a ⇒ 0a) set where

25 perms = {f . bij f ∧ finite {x. f x 6= x}} typedef 0a perm = perms :: ( 0a ⇒ 0a) set by standard (auto simp: perms-def )

First we need some auxiliary lemmas. lemma permsI [Pure.intro]: assumes bij f and MOST x. f x = x shows f ∈ perms using assms by (auto simp: perms-def )(metis MOST-iff-finiteNeg) lemma perms-imp-bij : f ∈ perms =⇒ bij f by (simp add: perms-def ) lemma perms-imp-MOST-eq: f ∈ perms =⇒ MOST x. f x = x by (simp add: perms-def )(metis MOST-iff-finiteNeg) lemma id-perms [simp]: id ∈ perms (λx. x) ∈ perms by (auto simp: perms-def bij-def ) lemma perms-comp [simp]: assumes f : f ∈ perms and g: g ∈ perms shows (f ◦ g) ∈ perms apply (intro permsI bij-comp) apply (rule perms-imp-bij [OF g]) apply (rule perms-imp-bij [OF f ]) apply (rule MOST-rev-mp [OF perms-imp-MOST-eq [OF g]]) apply (rule MOST-rev-mp [OF perms-imp-MOST-eq [OF f ]]) by simp lemma perms-inv: assumes f : f ∈ perms shows inv f ∈ perms apply (rule permsI ) apply (rule bij-imp-bij-inv) apply (rule perms-imp-bij [OF f ]) apply (rule MOST-mono [OF perms-imp-MOST-eq [OF f ]]) apply (erule subst, rule inv-f-f ) apply (rule bij-is-inj [OF perms-imp-bij [OF f ]]) done lemma bij-Rep-perm: bij (Rep-perm p) using Rep-perm [of p] unfolding perms-def by simp instantiation perm :: (type) group-add

26 begin definition 0 = Abs-perm id definition − p = Abs-perm (inv (Rep-perm p)) definition p + q = Abs-perm (Rep-perm p ◦ Rep-perm q) definition (p1 :: 0a perm) − p2 = p1 + − p2 lemma Rep-perm-0 : Rep-perm 0 = id unfolding zero-perm-def by (simp add: Abs-perm-inverse) lemma Rep-perm-add: Rep-perm (p1 + p2 ) = Rep-perm p1 ◦ Rep-perm p2 unfolding plus-perm-def by (simp add: Abs-perm-inverse Rep-perm) lemma Rep-perm-uminus: Rep-perm (− p) = inv (Rep-perm p) unfolding uminus-perm-def by (simp add: Abs-perm-inverse perms-inv Rep-perm) instance apply standard unfolding Rep-perm-inject [symmetric] unfolding minus-perm-def unfolding Rep-perm-add unfolding Rep-perm-uminus unfolding Rep-perm-0 apply (simp-all add: o-assoc inv-o-cancel [OF bij-is-inj [OF bij-Rep-perm]]) done end lemmas Rep-perm-simps = Rep-perm-0 Rep-perm-add Rep-perm-uminus

4 Permutation Types

We want to be able to apply permutations to arbitrary types. To this end we introduce a constant PERMUTE together with convenient infix syntax. consts PERMUTE :: 0a perm ⇒ 0b ⇒ 0b (infixr · 75 ) Then we add a locale for types 0b that support appliciation of permutations. locale permute = fixes permute :: 0a perm ⇒ 0b ⇒ 0b assumes permute-zero [simp]: permute 0 x = x and permute-plus [simp]: permute (p + q) x = permute p (permute q x) begin

27 adhoc-overloading PERMUTE permute end Permuting atoms. definition permute-atom :: 0a perm ⇒ 0a ⇒ 0a where permute-atom p a = (Rep-perm p) a adhoc-overloading PERMUTE permute-atom interpretation atom-permute: permute permute-atom by standard (simp-all add: permute-atom-def Rep-perm-simps) Permuting permutations. definition permute-perm :: 0a perm ⇒ 0a perm ⇒ 0a perm where permute-perm p q = p + q − p adhoc-overloading PERMUTE permute-perm interpretation perm-permute: permute permute-perm apply standard unfolding permute-perm-def apply simp apply (simp only: diff-conv-add-uminus minus-add add.assoc) done Permuting functions. locale fun-permute = dom: permute perm1 + ran: permute perm2 for perm1 :: 0a perm ⇒ 0b ⇒ 0b and perm2 :: 0a perm ⇒ 0c ⇒ 0c begin adhoc-overloading PERMUTE perm1 perm2 definition permute-fun :: 0a perm ⇒ ( 0b ⇒ 0c) ⇒ ( 0b ⇒ 0c) where permute-fun p f = (λx. p · (f (−p · x))) adhoc-overloading PERMUTE permute-fun end sublocale fun-permute ⊆ permute permute-fun by (unfold-locales, auto simp: permute-fun-def )

28 (metis dom.permute-plus minus-add) lemma (Abs-perm id :: nat perm) · Suc 0 = Suc 0 unfolding permute-atom-def by (metis Rep-perm-0 id-apply zero-perm-def ) interpretation atom-fun-permute: fun-permute permute-atom permute-atom by (unfold-locales) adhoc-overloading PERMUTE atom-fun-permute.permute-fun lemma (Abs-perm id :: 0a perm) · id = id unfolding atom-fun-permute.permute-fun-def unfolding permute-atom-def by (metis Rep-perm-0 id-def inj-imp-inv-eq inj-on-id uminus-perm-def zero-perm-def ) end

5 Example of Declaring an Oracle theory Iff-Oracle imports Main begin

5.1 Oracle declaration

This oracle makes tautologies of the form P = (P = (P = P)). The length is specified by an integer, which is checked to be even and positive. oracle iff-oracle = h let fun mk-iff 1 = Var ((P, 0 ), @{typ bool}) | mk-iff n = HOLogic.mk-eq (Var ((P, 0 ), @{typ bool}), mk-iff (n − 1 )); in fn (thy, n) => if n > 0 andalso n mod 2 = 0 then Thm.global-cterm-of thy (HOLogic.mk-Trueprop (mk-iff n)) else raise Fail (iff-oracle: ˆ string-of-int n) end i

5.2 Oracle as low-level rule

ML hiff-oracle (@{theory}, 2 )i ML hiff-oracle (@{theory}, 10 )i

ML h Thm.peek-status (iff-oracle (@{theory}, 10 ));

29 @{assert} (#oracle it); i

These oracle calls had better fail.

ML h (iff-oracle (@{theory}, 5 ); error Bad oracle) handle Fail - => writeln Oracle failed, as expected i

ML h (iff-oracle (@{theory}, 1 ); error Bad oracle) handle Fail - => writeln Oracle failed, as expected i

5.3 Oracle as proof method method-setup iff = hScan.lift Parse.nat >> (fn n => fn ctxt => SIMPLE-METHOD (HEADGOAL (resolve-tac ctxt [iff-oracle (Proof-Context.theory-of ctxt, n)]) handle Fail - => no-tac))i lemma A ←→ A by (iff 2 ) lemma A ←→ A ←→ A ←→ A ←→ A ←→ A ←→ A ←→ A ←→ A ←→ A by (iff 10 ) lemma A ←→ A ←→ A ←→ A ←→ A apply (iff 5 )? oops lemma A apply (iff 1 )? oops end theory Coercion-Examples imports Main begin declare[[coercion-enabled]]

consts func :: (nat ⇒ int) ⇒ nat

30 consts arg :: int ⇒ nat consts func 0 :: int ⇒ int consts arg 0 :: nat

abbreviation nat-of-bool :: bool ⇒ nat where nat-of-bool ≡ of-bool declare [[coercion nat-of-bool]] declare [[coercion int]] declare [[coercion-map map]] definition map-fun :: ( 0a ⇒ 0b) ⇒ ( 0c ⇒ 0d) ⇒ ( 0b ⇒ 0c) ⇒ ( 0a ⇒ 0d) where map-fun f g h = g o h o f declare [[coercion-map λ f g h . g o h o f ]] primrec map-prod :: ( 0a ⇒ 0c) ⇒ ( 0b ⇒ 0d) ⇒ ( 0a ∗ 0b) ⇒ ( 0c ∗ 0d) where map-prod f g (x,y) = (f x, g y) declare [[coercion-map map-prod]]

term (1 ::nat) = True term True = (1 ::nat) term (1 ::nat) = (True = (1 ::nat)) term op = (True = (1 ::nat)) term [1 ::nat,True] term [True,1 ::nat] term [1 ::nat] = [True] term [True] = [1 ::nat]

31 term [[True]] = [[1 ::nat]] term [[[[[[[[[[True]]]]]]]]]] = [[[[[[[[[[1 ::nat]]]]]]]]]] term [[True],[42 ::nat]] = rev [[True]] term rev [10000 ::nat] = [False, 420000 ::nat, True] term λ x . x = (3 ::nat) term (λ x . x = (3 ::nat)) True term map (λ x . x = (3 ::nat)) term map (λ x . x = (3 ::nat)) [True,1 ::nat] consts bnn :: (bool ⇒ nat) ⇒ nat consts nb :: nat ⇒ bool consts ab :: 0a ⇒ bool term bnn nb term bnn ab term λ x . x = (3 ::int) term map (λ x . x = (3 ::int)) [True] term map (λ x . x = (3 ::int)) [True,1 ::nat] term map (λ x . x = (3 ::int)) [True,1 ::nat,1 ::int] term [1 ::nat,True,1 ::int,False] term map (map (λ x . x = (3 ::int))) [[True],[1 ::nat],[True,1 ::int]] consts cbool :: 0a ⇒ bool consts cnat :: 0a ⇒ nat consts cint :: 0a ⇒ int term [id, cbool, cnat, cint] consts funfun :: ( 0a ⇒ 0b) ⇒ 0a ⇒ 0b consts flip :: ( 0a ⇒ 0b ⇒ 0c) ⇒ 0b ⇒ 0a ⇒ 0c term flip funfun term map funfun [id,cnat,cint,cbool]

32 term map (flip funfun True) term map (flip funfun True)[id,cnat,cint,cbool] consts ii :: int ⇒ int consts aaa :: 0a ⇒ 0a ⇒ 0a consts nlist :: nat list consts ilil :: int list ⇒ int list term ii (aaa (1 ::nat) True) term map ii nlist term ilil nlist

definition xs :: bool list where xs = [True] term (xs::nat list) term (1 ::nat) = True term True = (1 ::nat) term int (1 ::nat) term ((True::nat)::int) term 1 ::nat term nat 1 definition C :: nat where C = 123 consts g :: int ⇒ int consts h :: nat ⇒ nat term (g (1 ::nat)) + (h 2 ) term g 1 term 1 +(1 ::nat) term ((1 ::int) + (1 ::nat),(1 ::int))

33 definition ys :: bool list list list list list where ys=[[[[[True]]]]] term ys=[[[[[1 ::nat]]]]] typedecl ( 0a, 0b, 0c) F consts Fmap :: ( 0a ⇒ 0d) ⇒ ( 0a, 0b, 0c) F ⇒ ( 0d, 0b, 0c) F consts z :: (bool, nat, bool) F declare [[coercion-map Fmap :: ( 0a ⇒ 0d) ⇒ ( 0a, 0b, 0c) F ⇒ ( 0d, 0b, 0c) F ]] term z :: (nat, nat, bool) F consts case-nil :: 0a ⇒ 0b case-cons :: ( 0a ⇒ 0b) ⇒ ( 0a ⇒ 0b) ⇒ 0a ⇒ 0b case-abs :: ( 0c ⇒ 0b) ⇒ 0b case-elem :: 0a ⇒ 0b ⇒ 0a ⇒ 0b declare [[coercion-args case-cons − −]] declare [[coercion-args case-abs −]] declare [[coercion-args case-elem − +]] term case-cons (case-abs (λn. case-abs (λis. case-elem (((n::nat),(is::int list))) (n#is)))) case-nil consts n :: nat m :: nat term − (n + m) declare [[coercion-args uminus −]] declare [[coercion-args plus + +]] term − (n + m) end

6 Abstract Natural Numbers primitive recursion theory Abstract-NAT imports Main begin Axiomatic Natural Numbers (Peano) – a monomorphic theory. locale NAT = fixes zero :: 0n and succ :: 0n ⇒ 0n assumes succ-inject [simp]: succ m = succ n ←→ m = n and succ-neq-zero [simp]: succ m 6= zero and induct [case-names zero succ, induct type: 0n]: P zero =⇒ (Vn. P n =⇒ P (succ n)) =⇒ P n begin lemma zero-neq-succ [simp]: zero 6= succ m

34 by (rule succ-neq-zero [symmetric])

Primitive recursion as a (functional) relation – polymorphic! inductive Rec :: 0a ⇒ ( 0n ⇒ 0a ⇒ 0a) ⇒ 0n ⇒ 0a ⇒ bool for e :: 0a and r :: 0n ⇒ 0a ⇒ 0a where Rec-zero: Rec e r zero e | Rec-succ: Rec e r m n =⇒ Rec e r (succ m)(r m n) lemma Rec-functional: fixes x :: 0n shows ∃ !y:: 0a. Rec e r x y proof − let ?R = Rec e r show ?thesis proof (induct x) case zero show ∃ !y. ?R zero y proof show ?R zero e .. show y = e if ?R zero y for y using that by cases simp-all qed next case (succ m) from h∃ !y. ?R m y i obtain y where y: ?R m y and yy 0: Vy 0. ?R m y 0 =⇒ y = y 0 by blast show ∃ !z. ?R (succ m) z proof from y show ?R (succ m)(r m y) .. next fix z assume ?R (succ m) z then obtain u where z = r m u and ?R m u by cases simp-all with yy 0 show z = r m y by (simp only:) qed qed qed

The recursion operator – polymorphic! definition rec :: 0a ⇒ ( 0n ⇒ 0a ⇒ 0a) ⇒ 0n ⇒ 0a where rec e r x = (THE y. Rec e r x y) lemma rec-eval: assumes Rec: Rec e r x y

35 shows rec e r x = y unfolding rec-def using Rec-functional and Rec by (rule the1-equality) lemma rec-zero [simp]: rec e r zero = e proof (rule rec-eval) show Rec e r zero e .. qed lemma rec-succ [simp]: rec e r (succ m) = r m (rec e r m) proof (rule rec-eval) let ?R = Rec e r have ?R m (rec e r m) unfolding rec-def using Rec-functional by (rule theI 0) then show ?R (succ m)(r m (rec e r m)) .. qed

Example: addition (monomorphic) definition add :: 0n ⇒ 0n ⇒ 0n where add m n = rec n (λ- k. succ k) m lemma add-zero [simp]: add zero n = n and add-succ [simp]: add (succ m) n = succ (add m n) unfolding add-def by simp-all lemma add-assoc: add (add k m) n = add k (add m n) by (induct k) simp-all lemma add-zero-right: add m zero = m by (induct m) simp-all lemma add-succ-right: add m (succ n) = succ (add m n) by (induct m) simp-all lemma add (succ (succ (succ zero))) (succ (succ zero)) = succ (succ (succ (succ (succ zero)))) by simp

Example: replication (polymorphic) definition repl :: 0n ⇒ 0a ⇒ 0a list where repl n x = rec [] (λ- xs. x # xs) n lemma repl-zero [simp]: repl zero x = [] and repl-succ [simp]: repl (succ n) x = x # repl n x unfolding repl-def by simp-all lemma repl (succ (succ (succ zero))) True = [True, True, True] by simp

36 end

Just see that our abstract specification makes sense . . . interpretation NAT 0 Suc proof (rule NAT .intro) fix m n show Suc m = Suc n ←→ m = n by simp show Suc m 6= 0 by simp show P n if zero: P 0 and succ: Vn. P n =⇒ P (Suc n) for P proof (induct n) case 0 show ?case by (rule zero) next case Suc then show ?case by (rule succ) qed qed end

7 Proof by guessing theory Guess imports Main begin notepad begin have 1 : ∃ x. x = x by simp

from 1 guess .. from 1 guess x .. from 1 guess x :: 0a .. from 1 guess x :: nat ..

have 2 : ∃ x y. x = x ∧ y = y by simp from 2 guess apply − apply (erule exE conjE)+ done from 2 guess x apply − apply (erule exE conjE)+ done from 2 guess x y apply − apply (erule exE conjE)+ done from 2 guess x :: 0a and y :: 0b apply − apply (erule exE conjE)+ done from 2 guess x y :: nat apply − apply (erule exE conjE)+ done end end

37 8 Examples of function definitions theory Functions imports Main ∼∼/src/HOL/Library/Monad-Syntax begin

8.1 Very basic fun fib :: nat ⇒ nat where fib 0 = 1 | fib (Suc 0 ) = 1 | fib (Suc (Suc n)) = fib n + fib (Suc n)

Partial simp and induction rules: thm fib.psimps thm fib.pinduct

There is also a cases rule to distinguish cases along the definition: thm fib.cases

Total simp and induction rules: thm fib.simps thm fib.induct

Elimination rules: thm fib.elims

8.2 Currying fun add where add 0 y = y | add (Suc x) y = Suc (add x y) thm add.simps thm add.induct — Note the curried induction predicate

8.3 Nested recursion function nz where nz 0 = 0 | nz (Suc x) = nz (nz x) by pat-completeness auto lemma nz-is-zero: — A lemma we need to prove termination assumes trm: nz-dom x shows nz x = 0

38 using trm by induct (auto simp: nz.psimps) termination nz by (relation less-than)(auto simp:nz-is-zero) thm nz.simps thm nz.induct

8.3.1 Here comes McCarthy’s 91-function function f91 :: nat ⇒ nat where f91 n = (if 100 < n then n − 10 else f91 (f91 (n + 11 ))) by pat-completeness auto

Prove a lemma before attempting a termination proof: lemma f91-estimate: assumes trm: f91-dom n shows n < f91 n + 11 using trm by induct (auto simp: f91 .psimps) termination proof let ?R = measure (λx. 101 − x) show wf ?R ..

fix n :: nat assume ¬ 100 < n — Inner call then show (n + 11 , n) ∈ ?R by simp

assume inner-trm: f91-dom (n + 11 ) — Outer call with f91-estimate have n + 11 < f91 (n + 11 ) + 11 . with h¬ 100 < n i show (f91 (n + 11 ), n) ∈ ?R by simp qed

Now trivial (even though it does not belong here): lemma f91 n = (if 100 < n then n − 10 else 91 ) by (induct n rule: f91 .induct) auto

8.4 More general patterns 8.4.1 Overlapping patterns

Currently, patterns must always be compatible with each other, since no automatic splitting takes place. But the following definition of GCD is OK, although patterns overlap: fun gcd2 :: nat ⇒ nat ⇒ nat

39 where gcd2 x 0 = x | gcd2 0 y = y | gcd2 (Suc x)(Suc y) = (if x < y then gcd2 (Suc x)(y − x) else gcd2 (x − y)(Suc y)) thm gcd2 .simps thm gcd2 .induct

8.4.2 Guards

We can reformulate the above example using guarded patterns: function gcd3 :: nat ⇒ nat ⇒ nat where gcd3 x 0 = x | gcd3 0 y = y | gcd3 (Suc x)(Suc y) = gcd3 (Suc x)(y − x) if x < y | gcd3 (Suc x)(Suc y) = gcd3 (x − y)(Suc y) if ¬ x < y apply (case-tac x, case-tac a, auto) apply (case-tac ba, auto) done termination by lexicographic-order thm gcd3 .simps thm gcd3 .induct General patterns allow even strange definitions: function ev :: nat ⇒ bool where ev (2 ∗ n) = True | ev (2 ∗ n + 1 ) = False proof − — completeness is more difficult here . . . fix P :: bool fix x :: nat assume c1 : Vn. x = 2 ∗ n =⇒ P and c2 : Vn. x = 2 ∗ n + 1 =⇒ P have divmod: x = 2 ∗ (x div 2 ) + (x mod 2 ) by auto show P proof (cases x mod 2 = 0 ) case True with divmod have x = 2 ∗ (x div 2 ) by simp with c1 show P . next case False then have x mod 2 = 1 by simp with divmod have x = 2 ∗ (x div 2 ) + 1 by simp with c2 show P . qed qed presburger+ — solve compatibility with presburger

40 termination by lexicographic-order thm ev.simps thm ev.induct thm ev.cases

8.5 Mutual Recursion fun evn od :: nat ⇒ bool where evn 0 = True | od 0 = False | evn (Suc n) = od n | od (Suc n) = evn n thm evn.simps thm od.simps thm evn-od.induct thm evn-od.termination thm evn.elims thm od.elims

8.6 Definitions in local contexts locale my-monoid = fixes opr :: 0a ⇒ 0a ⇒ 0a and un :: 0a assumes assoc: opr (opr x y) z = opr x (opr y z) and lunit: opr un x = x and runit: opr x un = x begin fun foldR :: 0a list ⇒ 0a where foldR [] = un | foldR (x # xs) = opr x (foldR xs) fun foldL :: 0a list ⇒ 0a where foldL [] = un | foldL [x] = x | foldL (x # y # ys) = foldL (opr x y # ys) thm foldL.simps lemma foldR-foldL: foldR xs = foldL xs by (induct xs rule: foldL.induct)(auto simp:lunit runit assoc)

41 thm foldR-foldL end thm my-monoid.foldL.simps thm my-monoid.foldR-foldL

8.7 fun-cases 8.7.1 Predecessor fun pred :: nat ⇒ nat where pred 0 = 0 | pred (Suc n) = n thm pred.elims lemma assumes pred x = y obtains x = 0 y = 0 | n where x = Suc n y = n by (fact pred.elims[OF assms])

If the predecessor of a number is 0, that number must be 0 or 1. fun-cases pred0E[elim]: pred n = 0 lemma pred n = 0 =⇒ n = 0 ∨ n = Suc 0 by (erule pred0E) metis+

Other expressions on the right-hand side also work, but whether the gener- ated rule is useful depends on how well the simplifier can simplify it. This example works well: fun-cases pred42E[elim]: pred n = 42 lemma pred n = 42 =⇒ n = 43 by (erule pred42E)

8.7.2 List to option fun list-to-option :: 0a list ⇒ 0a option where list-to-option [x] = Some x | list-to-option - = None fun-cases list-to-option-NoneE: list-to-option xs = None and list-to-option-SomeE: list-to-option xs = Some x lemma list-to-option xs = Some y =⇒ xs = [y] by (erule list-to-option-SomeE)

42 8.7.3 Boolean Functions fun xor :: bool ⇒ bool ⇒ bool where xor False False = False | xor True True = False | xor - - = True thm xor.elims fun-cases does not only recognise function equations, but also works with functions that return a boolean, e.g.: fun-cases xor-TrueE: xor a b and xor-FalseE: ¬xor a b print-theorems

8.7.4 Many parameters fun sum4 :: nat ⇒ nat ⇒ nat ⇒ nat ⇒ nat where sum4 a b c d = a + b + c + d fun-cases sum40E: sum4 a b c d = 0 lemma sum4 a b c d = 0 =⇒ a = 0 by (erule sum40E)

8.8 Partial Function Definitions

Partial functions in the option monad: partial-function (option) collatz :: nat ⇒ nat list option where collatz n = (if n ≤ 1 then Some [n] else if even n then do { ns ← collatz (n div 2 ); Some (n # ns) } else do { ns ← collatz (3 ∗ n + 1 ); Some (n # ns)}) declare collatz.simps[code] value collatz 23

Tail-recursive functions: partial-function (tailrec) fixpoint :: ( 0a ⇒ 0a) ⇒ 0a ⇒ 0a where fixpoint f x = (if f x = x then x else fixpoint f (f x))

8.9 Regression tests

The following examples mainly serve as tests for the function package.

43 fun listlen :: 0a list ⇒ nat where listlen [] = 0 | listlen (x#xs) = Suc (listlen xs)

8.9.1 Context recursion fun f :: nat ⇒ nat where zero: f 0 = 0 | succ: f (Suc n) = (if f n = 0 then 0 else f n)

8.9.2 A combination of context and nested recursion function h :: nat ⇒ nat where h 0 = 0 | h (Suc n) = (if h n = 0 then h (h n) else h n) by pat-completeness auto

8.9.3 Context, but no recursive call fun i :: nat ⇒ nat where i 0 = 0 | i (Suc n) = (if n = 0 then 0 else i n)

8.9.4 Tupled nested recursion fun fa :: nat ⇒ nat ⇒ nat where fa 0 y = 0 | fa (Suc n) y = (if fa n y = 0 then 0 else fa n y)

8.9.5 Let fun j :: nat ⇒ nat where j 0 = 0 | j (Suc n) = (let u = n in Suc (j u))

There were some problems with fresh names . . . function k :: nat ⇒ nat where k x = (let a = x; b = x in k x) by pat-completeness auto function f2 :: (nat × nat) ⇒ (nat × nat) where

44 f2 p = (let (x,y) = p in f2 (y,x)) by pat-completeness auto

8.9.6 Abbreviations fun f3 :: 0a set ⇒ bool where f3 x = finite x

8.9.7 Simple Higher-Order Recursion datatype 0a tree = Leaf 0a | Branch 0a tree list fun treemap :: ( 0a ⇒ 0a) ⇒ 0a tree ⇒ 0a tree where treemap fn (Leaf n) = (Leaf (fn n)) | treemap fn (Branch l) = (Branch (map (treemap fn) l)) fun tinc :: nat tree ⇒ nat tree where tinc (Leaf n) = Leaf (Suc n) | tinc (Branch l) = Branch (map tinc l) fun testcase :: 0a tree ⇒ 0a list where testcase (Leaf a) = [a] | testcase (Branch x) = (let xs = concat (map testcase x); ys = concat (map testcase x) in xs @ ys)

8.9.8 Pattern matching on records record point = Xcoord :: int Ycoord :: int function swp :: point ⇒ point where swp (| Xcoord = x, Ycoord = y |) = (| Xcoord = y, Ycoord = x |) proof − fix P x assume Vxa y. x = (|Xcoord = xa, Ycoord = y|) =⇒ P then show P by (cases x) qed auto termination by rule auto

8.9.9 The diagonal function fun diag :: bool ⇒ bool ⇒ bool ⇒ nat

45 where diag x True False = 1 | diag False y True = 2 | diag True False z = 3 | diag True True True = 4 | diag False False False = 5

8.9.10 Many equations (quadratic blowup) datatype DT = A | B | C | D | E | F | G | H | I | J | K | L | M | N | P | Q | R | S | T | U | V fun big :: DT ⇒ nat where big A = 0 | big B = 0 | big C = 0 | big D = 0 | big E = 0 | big F = 0 | big G = 0 | big H = 0 | big I = 0 | big J = 0 | big K = 0 | big L = 0 | big M = 0 | big N = 0 | big P = 0 | big Q = 0 | big R = 0 | big S = 0 | big T = 0 | big U = 0 | big V = 0

8.9.11 Automatic pattern splitting fun f4 :: nat ⇒ nat ⇒ bool where f4 0 0 = True | f4 - - = False

8.9.12 Polymorphic partial-function partial-function (option) f5 :: 0a list ⇒ 0a option where f5 x = f5 x

46 end

9 Examples of automatically derived induction rules theory Induction-Schema imports Main begin

9.1 Some simple induction principles on nat lemma nat-standard-induct: [[P 0 ; Vn. P n =⇒ P (Suc n)]] =⇒ P x by induction-schema (pat-completeness, lexicographic-order) lemma nat-induct2 : [[ P 0 ; P (Suc 0 ); Vk. P k ==> P (Suc k) ==> P (Suc (Suc k)) ]] =⇒ P n by induction-schema (pat-completeness, lexicographic-order) lemma minus-one-induct: [[Vn::nat. (n 6= 0 =⇒ P (n − 1 )) =⇒ P n]] =⇒ P x by induction-schema (pat-completeness, lexicographic-order) theorem diff-induct: (!!x. P x 0 ) ==> (!!y. P 0 (Suc y)) ==> (!!x y. P x y ==> P (Suc x)(Suc y)) ==> P m n by induction-schema (pat-completeness, lexicographic-order) lemma list-induct2 0: [[ P [] []; Vx xs. P (x#xs) []; Vy ys. P [] (y#ys); Vx xs y ys. P xs ys =⇒ P (x#xs)(y#ys) ]] =⇒ P xs ys by induction-schema (pat-completeness, lexicographic-order) theorem even-odd-induct: assumes R 0 assumes Q 0 assumes Vn. Q n =⇒ R (Suc n) assumes Vn. R n =⇒ Q (Suc n) shows R n Q n using assms by induction-schema (pat-completeness+, lexicographic-order) end

47 10 Test of Locale Interpretation theory LocaleTest2 imports Main GCD begin

11 Interpretation of Defined Concepts

Naming convention for global objects: prefixes D and d

11.1 Lattices

Much of the lattice proofs are from HOL/Lattice.

11.1.1 Definitions locale dpo = fixes le :: [ 0a, 0a] => bool (infixl v 50 ) assumes refl [intro, simp]: x v x and antisym [intro]: [| x v y; y v x |] ==> x = y and trans [trans]: [| x v y; y v z |] ==> x v z begin theorem circular: [| x v y; y v z; z v x |] ==> x = y & y = z by (blast intro: trans) definition less :: [ 0a, 0a] => bool (infixl 50 ) ∼ where (x y) = (x v y & x < = y) < theorem abs-test: op = (%x y. x y) by bool where is-inf x y i = (i v x ∧ i v y ∧ (∀ z. z v x ∧ z v y −→ z v i)) definition is-sup :: [ 0a, 0a, 0a] => bool where is-sup x y s = (x v s ∧ y v s ∧ (∀ z. x v z ∧ y v z −→ s v z)) end locale dlat = dpo + assumes ex-inf : EX inf . dpo.is-inf le x y inf

48 and ex-sup: EX sup. dpo.is-sup le x y sup begin definition meet :: [ 0a, 0a] => 0a (infixl u 70 ) where x u y = (THE inf . is-inf x y inf ) definition join :: [ 0a, 0a] => 0a (infixl t 65 ) where x t y = (THE sup. is-sup x y sup) lemma is-infI [intro?]: i v x =⇒ i v y =⇒ (Vz. z v x =⇒ z v y =⇒ z v i) =⇒ is-inf x y i by (unfold is-inf-def ) blast lemma is-inf-lower [elim?]: is-inf x y i =⇒ (i v x =⇒ i v y =⇒ C ) =⇒ C by (unfold is-inf-def ) blast lemma is-inf-greatest [elim?]: is-inf x y i =⇒ z v x =⇒ z v y =⇒ z v i by (unfold is-inf-def ) blast theorem is-inf-uniq: is-inf x y i =⇒ is-inf x y i 0 =⇒ i = i 0 proof − assume inf : is-inf x y i assume inf 0: is-inf x y i 0 show ?thesis proof (rule antisym) from inf 0 show i v i 0 proof (rule is-inf-greatest) from inf show i v x .. from inf show i v y .. qed from inf show i 0 v i proof (rule is-inf-greatest) from inf 0 show i 0 v x .. from inf 0 show i 0 v y .. qed qed qed theorem is-inf-related [elim?]: x v y =⇒ is-inf x y x proof − assume x v y show ?thesis proof show x v x ..

49 show x v y by fact fix z assume z v x and z v y show z v x by fact qed qed lemma meet-equality [elim?]: is-inf x y i =⇒ x u y = i proof (unfold meet-def ) assume is-inf x y i then show (THE i. is-inf x y i) = i by (rule the-equality)(rule is-inf-uniq [OF - his-inf x y i i]) qed lemma meetI [intro?]: i v x =⇒ i v y =⇒ (Vz. z v x =⇒ z v y =⇒ z v i) =⇒ x u y = i by (rule meet-equality, rule is-infI ) blast+ lemma is-inf-meet [intro?]: is-inf x y (x u y) proof (unfold meet-def ) from ex-inf obtain i where is-inf x y i .. then show is-inf x y (THE i. is-inf x y i) by (rule theI )(rule is-inf-uniq [OF - his-inf x y i i]) qed lemma meet-left [intro?]: x u y v x by (rule is-inf-lower)(rule is-inf-meet) lemma meet-right [intro?]: x u y v y by (rule is-inf-lower)(rule is-inf-meet) lemma meet-le [intro?]: [| z v x; z v y |] ==> z v x u y by (rule is-inf-greatest)(rule is-inf-meet) lemma is-supI [intro?]: x v s =⇒ y v s =⇒ (Vz. x v z =⇒ y v z =⇒ s v z) =⇒ is-sup x y s by (unfold is-sup-def ) blast lemma is-sup-least [elim?]: is-sup x y s =⇒ x v z =⇒ y v z =⇒ s v z by (unfold is-sup-def ) blast lemma is-sup-upper [elim?]: is-sup x y s =⇒ (x v s =⇒ y v s =⇒ C ) =⇒ C by (unfold is-sup-def ) blast theorem is-sup-uniq: is-sup x y s =⇒ is-sup x y s 0 =⇒ s = s 0 proof −

50 assume sup: is-sup x y s assume sup 0: is-sup x y s 0 show ?thesis proof (rule antisym) from sup show s v s 0 proof (rule is-sup-least) from sup 0 show x v s 0 .. from sup 0 show y v s 0 .. qed from sup 0 show s 0 v s proof (rule is-sup-least) from sup show x v s .. from sup show y v s .. qed qed qed theorem is-sup-related [elim?]: x v y =⇒ is-sup x y y proof − assume x v y show ?thesis proof show x v y by fact show y v y .. fix z assume x v z and y v z show y v z by fact qed qed lemma join-equality [elim?]: is-sup x y s =⇒ x t y = s proof (unfold join-def ) assume is-sup x y s then show (THE s. is-sup x y s) = s by (rule the-equality)(rule is-sup-uniq [OF - his-sup x y s i]) qed lemma joinI [intro?]: x v s =⇒ y v s =⇒ (Vz. x v z =⇒ y v z =⇒ s v z) =⇒ x t y = s by (rule join-equality, rule is-supI ) blast+ lemma is-sup-join [intro?]: is-sup x y (x t y) proof (unfold join-def ) from ex-sup obtain s where is-sup x y s .. then show is-sup x y (THE s. is-sup x y s) by (rule theI )(rule is-sup-uniq [OF - his-sup x y s i]) qed lemma join-left [intro?]: x v x t y

51 by (rule is-sup-upper)(rule is-sup-join) lemma join-right [intro?]: y v x t y by (rule is-sup-upper)(rule is-sup-join) lemma join-le [intro?]: [| x v z; y v z |] ==> x t y v z by (rule is-sup-least)(rule is-sup-join) theorem meet-assoc:(x u y) u z = x u (y u z) proof (rule meetI ) show x u (y u z) v x u y proof show x u (y u z) v x .. show x u (y u z) v y proof − have x u (y u z) v y u z .. also have ... v y .. finally show ?thesis . qed qed show x u (y u z) v z proof − have x u (y u z) v y u z .. also have ... v z .. finally show ?thesis . qed fix w assume w v x u y and w v z show w v x u (y u z) proof show w v x proof − have w v x u y by fact also have ... v x .. finally show ?thesis . qed show w v y u z proof show w v y proof − have w v x u y by fact also have ... v y .. finally show ?thesis . qed show w v z by fact qed qed qed

52 theorem meet-commute: x u y = y u x proof (rule meetI ) show y u x v x .. show y u x v y .. fix z assume z v y and z v x then show z v y u x .. qed theorem meet-join-absorb: x u (x t y) = x proof (rule meetI ) show x v x .. show x v x t y .. fix z assume z v x and z v x t y show z v x by fact qed theorem join-assoc:(x t y) t z = x t (y t z) proof (rule joinI ) show x t y v x t (y t z) proof show x v x t (y t z) .. show y v x t (y t z) proof − have y v y t z .. also have ... v x t (y t z) .. finally show ?thesis . qed qed show z v x t (y t z) proof − have z v y t z .. also have ... v x t (y t z) .. finally show ?thesis . qed fix w assume x t y v w and z v w show x t (y t z) v w proof show x v w proof − have x v x t y .. also have ... v w by fact finally show ?thesis . qed show y t z v w proof show y v w proof − have y v x t y ..

53 also have ... v w by fact finally show ?thesis . qed show z v w by fact qed qed qed theorem join-commute: x t y = y t x proof (rule joinI ) show x v y t x .. show y v y t x .. fix z assume y v z and x v z then show y t x v z .. qed theorem join-meet-absorb: x t (x u y) = x proof (rule joinI ) show x v x .. show x u y v x .. fix z assume x v z and x u y v z show x v z by fact qed theorem meet-idem: x u x = x proof − have x u (x t (x u x)) = x by (rule meet-join-absorb) also have x t (x u x) = x by (rule join-meet-absorb) finally show ?thesis . qed theorem meet-related [elim?]: x v y =⇒ x u y = x proof (rule meetI ) assume x v y show x v x .. show x v y by fact fix z assume z v x and z v y show z v x by fact qed theorem meet-related2 [elim?]: y v x =⇒ x u y = y by (drule meet-related)(simp add: meet-commute) theorem join-related [elim?]: x v y =⇒ x t y = y proof (rule joinI ) assume x v y show y v y .. show x v y by fact fix z assume x v z and y v z

54 show y v z by fact qed theorem join-related2 [elim?]: y v x =⇒ x t y = x by (drule join-related)(simp add: join-commute)

Additional theorems theorem meet-connection:(x v y) = (x u y = x) proof assume x v y then have is-inf x y x .. then show x u y = x .. next have x u y v y .. also assume x u y = x finally show x v y . qed theorem meet-connection2 :(x v y) = (y u x = x) using meet-commute meet-connection by simp theorem join-connection:(x v y) = (x t y = y) proof assume x v y then have is-sup x y y .. then show x t y = y .. next have x v x t y .. also assume x t y = y finally show x v y . qed theorem join-connection2 :(x v y) = (x t y = y) using join-commute join-connection by simp

Naming according to Jacobson I, p. 459. lemmas L1 = join-commute meet-commute lemmas L2 = join-assoc meet-assoc lemmas L4 = join-meet-absorb meet-join-absorb end locale ddlat = dlat + assumes meet-distr: dlat.meet le x (dlat.join le y z) = dlat.join le (dlat.meet le x y)(dlat.meet le x z) begin

55 lemma join-distr: x t (y u z) = (x t y) u (x t z) Jacobson I, p. 462 proof − have x t (y u z) = (x t (x u z)) t (y u z) by (simp add: L4 ) also have ... = x t ((x u z) t (y u z)) by (simp add: L2 ) also have ... = x t ((x t y) u z) by (simp add: L1 meet-distr) also have ... = ((x t y) u x) t ((x t y) u z) by (simp add: L1 L4 ) also have ... = (x t y) u (x t z) by (simp add: meet-distr) finally show ?thesis . qed end locale dlo = dpo + assumes total: x v y | y v x begin lemma less-total: x y | x = y | y x using total < < by (unfold less-def ) blast end sublocale dlo < dlat proof fix x y from total have is-inf x y (if x v y then x else y) by (auto simp: is-inf-def ) then show EX inf . is-inf x y inf by blast next fix x y from total have is-sup x y (if x v y then y else x) by (auto simp: is-sup-def ) then show EX sup. is-sup x y sup by blast qed sublocale dlo < ddlat proof fix x y z show x u (y t z) = x u y t x u z (is ?l = ?r) Jacobson I, p. 462 proof − { assume c: y v x z v x from c have ?l = y t z by (metis c join-connection2 join-related2 meet-connection meet-related2 total)

56 also from c have ... = ?r by (metis meet-related2 ) finally have ?l = ?r . } moreover { assume c: x v y | x v z from c have ?l = x by (metis join-connection2 join-related2 meet-connection total trans) also from c have ... = ?r by (metis join-commute join-related2 meet-connection meet-related2 total) finally have ?l = ?r . } moreover note total ultimately show ?thesis by blast qed qed

11.1.2 Total order <= on int interpretation int: dpo op <= :: [int, int] => bool rewrites (dpo.less (op <=) (x::int) y) = (x < y)

We give interpretation for less, but not is-inf and is-sub. proof − show dpo (op <= :: [int, int] => bool) proof qed auto then interpret int: dpo op <= :: [int, int] => bool .

Gives interpreted version of less-def (without condition). show (dpo.less (op <=) (x::int) y) = (x < y) by (unfold int.less-def ) auto qed thm int.circular lemma [[ (x::int) ≤ y; y ≤ z; z ≤ x]] =⇒ x = y ∧ y = z apply (rule int.circular) apply assumption apply assumption apply assumption done thm int.abs-test lemma (op < :: [int, int] => bool) = op < apply (rule int.abs-test) done interpretation int: dlat op <= :: [int, int] => bool rewrites meet-eq: dlat.meet (op <=) (x::int) y = min x y and join-eq: dlat.join (op <=) (x::int) y = max x y proof − show dlat (op <= :: [int, int] => bool) apply unfold-locales apply (unfold int.is-inf-def int.is-sup-def ) apply arith+ done then interpret int: dlat op <= :: [int, int] => bool .

57 Interpretation to ease use of definitions, which are conditional in general but un- conditional after interpretation. show dlat.meet (op <=) (x::int) y = min x y apply (unfold int.meet-def ) apply (rule the-equality) apply (unfold int.is-inf-def ) by auto show dlat.join (op <=) (x::int) y = max x y apply (unfold int.join-def ) apply (rule the-equality) apply (unfold int.is-sup-def ) by auto qed interpretation int: dlo op <= :: [int, int] => bool proof qed arith

Interpreted theorems from the locales, involving defined terms. thm int.less-def from dpo thm int.meet-left from dlat thm int.meet-distr from ddlat thm int.less-total from dlo

11.1.3 Total order <= on nat interpretation nat: dpo op <= :: [nat, nat] => bool rewrites dpo.less (op <=) (x::nat) y = (x < y)

We give interpretation for less, but not is-inf and is-sub. proof − show dpo (op <= :: [nat, nat] => bool) proof qed auto then interpret nat: dpo op <= :: [nat, nat] => bool .

Gives interpreted version of less-def (without condition). show dpo.less (op <=) (x::nat) y = (x < y) apply (unfold nat.less-def ) apply auto done

58 qed interpretation nat: dlat op <= :: [nat, nat] => bool rewrites dlat.meet (op <=) (x::nat) y = min x y and dlat.join (op <=) (x::nat) y = max x y proof − show dlat (op <= :: [nat, nat] => bool) apply unfold-locales apply (unfold nat.is-inf-def nat.is-sup-def ) apply arith+ done then interpret nat: dlat op <= :: [nat, nat] => bool .

Interpretation to ease use of definitions, which are conditional in general but un- conditional after interpretation. show dlat.meet (op <=) (x::nat) y = min x y apply (unfold nat.meet-def ) apply (rule the-equality) apply (unfold nat.is-inf-def ) by auto show dlat.join (op <=) (x::nat) y = max x y apply (unfold nat.join-def ) apply (rule the-equality) apply (unfold nat.is-sup-def ) by auto qed interpretation nat: dlo op <= :: [nat, nat] => bool proof qed arith

Interpreted theorems from the locales, involving defined terms. thm nat.less-def from dpo thm nat.meet-left from dlat thm nat.meet-distr from ddlat thm nat.less-total from ldo

11.1.4 Lattice dvd on nat interpretation nat-dvd: dpo op dvd :: [nat, nat] => bool rewrites dpo.less (op dvd)(x::nat) y = (x dvd y & x ∼= y)

59 We give interpretation for less, but not is-inf and is-sub. proof − show dpo (op dvd :: [nat, nat] => bool) proof qed (auto simp: dvd-def ) then interpret nat-dvd: dpo op dvd :: [nat, nat] => bool .

Gives interpreted version of less-def (without condition). show dpo.less (op dvd)(x::nat) y = (x dvd y & x ∼= y) apply (unfold nat-dvd.less-def ) apply auto done qed interpretation nat-dvd: dlat op dvd :: [nat, nat] => bool rewrites dlat.meet (op dvd)(x::nat) y = gcd x y and dlat.join (op dvd)(x::nat) y = lcm x y proof − show dlat (op dvd :: [nat, nat] => bool) apply unfold-locales apply (unfold nat-dvd.is-inf-def nat-dvd.is-sup-def ) apply (rule-tac x = gcd x y in exI ) apply auto [1 ] apply (rule-tac x = lcm x y in exI ) apply (auto intro: dvd-lcm1 dvd-lcm2 lcm-least) done then interpret nat-dvd: dlat op dvd :: [nat, nat] => bool .

Interpretation to ease use of definitions, which are conditional in general but un- conditional after interpretation. show dlat.meet (op dvd)(x::nat) y = gcd x y apply (unfold nat-dvd.meet-def ) apply (rule the-equality) apply (unfold nat-dvd.is-inf-def ) by auto show dlat.join (op dvd)(x::nat) y = lcm x y apply (unfold nat-dvd.join-def ) apply (rule the-equality) apply (unfold nat-dvd.is-sup-def ) by (auto intro: dvd-lcm1 dvd-lcm2 lcm-least) qed

Interpreted theorems from the locales, involving defined terms. thm nat-dvd.less-def from dpo lemma ((x::nat) dvd y & x ∼= y) = (x dvd y & x ∼= y) apply (rule nat-dvd.less-def ) done thm nat-dvd.meet-left

60 from dlat lemma gcd x y dvd (x::nat) apply (rule nat-dvd.meet-left) done

11.2 Group example with defined operations inv and unit 11.2.1 Locale declarations and lemmas locale Dsemi = fixes prod (infixl ∗∗ 65 ) assumes assoc:(x ∗∗ y) ∗∗ z = x ∗∗ (y ∗∗ z) locale Dmonoid = Dsemi + fixes one assumes l-one [simp]: one ∗∗ x = x and r-one [simp]: x ∗∗ one = x begin definition inv where inv x = (THE y. x ∗∗ y = one & y ∗∗ x = one) definition unit where unit x = (EX y. x ∗∗ y = one & y ∗∗ x = one) lemma inv-unique: assumes eq: y ∗∗ x = one x ∗∗ y 0 = one shows y = y 0 proof − from eq have y = y ∗∗ (x ∗∗ y 0) by (simp add: r-one) also have ... = (y ∗∗ x) ∗∗ y 0 by (simp add: assoc) also from eq have ... = y 0 by (simp add: l-one) finally show ?thesis . qed lemma unit-one [intro, simp]: unit one by (unfold unit-def ) auto lemma unit-l-inv-ex: unit x ==> ∃ y. y ∗∗ x = one by (unfold unit-def ) auto lemma unit-r-inv-ex: unit x ==> ∃ y. x ∗∗ y = one by (unfold unit-def ) auto lemma unit-l-inv: unit x ==> inv x ∗∗ x = one apply (simp add: unit-def inv-def ) apply (erule exE)

61 apply (rule theI2 , fast) apply (rule inv-unique) apply fast+ done lemma unit-r-inv: unit x ==> x ∗∗ inv x = one apply (simp add: unit-def inv-def ) apply (erule exE) apply (rule theI2 , fast) apply (rule inv-unique) apply fast+ done lemma unit-inv-unit [intro, simp]: unit x ==> unit (inv x) proof − assume x: unit x show unit (inv x) by (auto simp add: unit-def intro: unit-l-inv unit-r-inv x) qed lemma unit-l-cancel [simp]: unit x ==> (x ∗∗ y = x ∗∗ z) = (y = z) proof assume eq: x ∗∗ y = x ∗∗ z and G: unit x then have (inv x ∗∗ x) ∗∗ y = (inv x ∗∗ x) ∗∗ z by (simp add: assoc) with G show y = z by (simp add: unit-l-inv) next assume eq: y = z and G: unit x then show x ∗∗ y = x ∗∗ z by simp qed lemma unit-inv-inv [simp]: unit x ==> inv (inv x) = x proof − assume x: unit x then have inv x ∗∗ inv (inv x) = inv x ∗∗ x by (simp add: unit-l-inv unit-r-inv) with x show ?thesis by simp qed lemma inv-inj-on-unit: inj-on inv {x. unit x} proof (rule inj-onI , simp) fix x y

62 assume G: unit x unit y and eq: inv x = inv y then have inv (inv x) = inv (inv y) by simp with G show x = y by simp qed lemma unit-inv-comm: assumes inv: x ∗∗ y = one and G: unit x unit y shows y ∗∗ x = one proof − from G have x ∗∗ y ∗∗ x = x ∗∗ one by (auto simp add: inv) with G show ?thesis by (simp del: r-one add: assoc) qed end locale Dgrp = Dmonoid + assumes unit [intro, simp]: Dmonoid.unit (op ∗∗) one x begin lemma l-inv-ex [simp]: ∃ y. y ∗∗ x = one using unit-l-inv-ex by simp lemma r-inv-ex [simp]: ∃ y. x ∗∗ y = one using unit-r-inv-ex by simp lemma l-inv [simp]: inv x ∗∗ x = one using unit-l-inv by simp lemma l-cancel [simp]: (x ∗∗ y = x ∗∗ z) = (y = z) using unit-l-inv by simp lemma r-inv [simp]: x ∗∗ inv x = one proof − have inv x ∗∗ (x ∗∗ inv x) = inv x ∗∗ one by (simp add: assoc [symmetric] l-inv) then show ?thesis by (simp del: r-one) qed lemma r-cancel [simp]: (y ∗∗ x = z ∗∗ x) = (y = z) proof

63 assume eq: y ∗∗ x = z ∗∗ x then have y ∗∗ (x ∗∗ inv x) = z ∗∗ (x ∗∗ inv x) by (simp add: assoc [symmetric] del: r-inv) then show y = z by simp qed simp lemma inv-one [simp]: inv one = one proof − have inv one = one ∗∗ (inv one) by (simp del: r-inv) moreover have ... = one by simp finally show ?thesis . qed lemma inv-inv [simp]: inv (inv x) = x using unit-inv-inv by simp lemma inv-inj : inj-on inv UNIV using inv-inj-on-unit by simp lemma inv-mult-group: inv (x ∗∗ y) = inv y ∗∗ inv x proof − have inv (x ∗∗ y) ∗∗ (x ∗∗ y) = (inv y ∗∗ inv x) ∗∗ (x ∗∗ y) by (simp add: assoc l-inv)(simp add: assoc [symmetric]) then show ?thesis by (simp del: l-inv) qed lemma inv-comm: x ∗∗ y = one ==> y ∗∗ x = one by (rule unit-inv-comm) auto lemma inv-equality: y ∗∗ x = one ==> inv x = y apply (simp add: inv-def ) apply (rule the-equality) apply (simp add: inv-comm [of y x]) apply (rule r-cancel [THEN iffD1 ], auto) done end locale Dhom = prod: Dgrp prod one + sum: Dgrp sum zero for prod (infixl ∗∗ 65 ) and one and sum (infixl +++ 60 ) and zero + fixes hom assumes hom-mult [simp]: hom (x ∗∗ y) = hom x +++ hom y

64 begin lemma hom-one [simp]: hom one = zero proof − have hom one +++ zero = hom one +++ hom one by (simp add: hom-mult [symmetric] del: hom-mult) then show ?thesis by (simp del: sum.r-one) qed end

11.2.2 Interpretation of Functions interpretation Dfun: Dmonoid op o id :: 0a => 0a rewrites Dmonoid.unit (op o) id f = bij (f :: 0a => 0a) proof − show Dmonoid op o (id :: 0a => 0a) proof qed (simp-all add: o-assoc) note Dmonoid = this

show Dmonoid.unit (op o)(id :: 0a => 0a) f = bij f apply (unfold Dmonoid.unit-def [OF Dmonoid]) apply rule apply clarify proof − fix f g assume id1 : f o g = id and id2 : g o f = id show bij f proof (rule bijI ) show inj f proof (rule inj-onI ) fix x y assume f x = f y then have (g o f ) x = (g o f ) y by simp with id2 show x = y by simp qed next show surj f proof (rule surjI ) fix x from id1 have (f o g) x = x by simp then show f (g x) = x by simp qed qed next fix f assume bij : bij f then

65 have inv: f o Hilbert-Choice.inv f = id & Hilbert-Choice.inv f o f = id by (simp add: bij-def surj-iff inj-iff ) show EX g. f o g = id & g o f = id by rule (rule inv) qed qed thm Dmonoid.unit-def Dfun.unit-def thm Dmonoid.inv-inj-on-unit Dfun.inv-inj-on-unit lemma unit-id: (f :: unit => unit) = id by rule simp interpretation Dfun: Dgrp op o id :: unit => unit rewrites Dmonoid.inv (op o) id f = inv (f :: unit => unit) proof − have Dmonoid op o (id :: 0a => 0a) .. note Dmonoid = this

show Dgrp (op o)(id :: unit => unit) apply unfold-locales apply (unfold Dmonoid.unit-def [OF Dmonoid]) apply (insert unit-id) apply simp done show Dmonoid.inv (op o) id f = inv (f :: unit => unit) apply (unfold Dmonoid.inv-def [OF Dmonoid]) apply (insert unit-id) apply simp apply (rule the-equality) apply rule apply rule apply simp done qed thm Dfun.unit-l-inv Dfun.l-inv thm Dfun.inv-equality thm Dfun.inv-equality end

12 Using extensible records in HOL – points and coloured points theory Records

66 imports Main begin

12.1 Points record point = xpos :: nat ypos :: nat

Apart many other things, above record declaration produces the following theorems: thm point.simps thm point.iffs thm point.defs

The set of theorems point.simps is added automatically to the standard simpset, point.iffs is added to the Classical Reasoner and Simplifier context.

Record declarations define new types and type abbreviations: point = (|xpos :: nat, ypos :: nat|) = () point-ext-type 0a point-scheme = (|xpos :: nat, ypos :: nat, ... :: 0a|) = 0a point-ext-type consts foo2 :: (| xpos :: nat, ypos :: nat |) consts foo4 :: 0a => (| xpos :: nat, ypos :: nat, ... :: 0a |)

12.1.1 Introducing concrete records and record schemes definition foo1 :: point where foo1 = (| xpos = 1 , ypos = 0 |) definition foo3 :: 0a => 0a point-scheme where foo3 ext = (| xpos = 1 , ypos = 0 , ... = ext |)

12.1.2 Record selection and record update definition getX :: 0a point-scheme => nat where getX r = xpos r definition setX :: 0a point-scheme => nat => 0a point-scheme where setX r n = r (| xpos := n |)

12.1.3 Some lemmas about records

Basic simplifications. lemma point.make n p = (| xpos = n, ypos = p |) by (simp only: point.make-def ) lemma xpos (| xpos = m, ypos = n, ... = p |) = m

67 by simp lemma (| xpos = m, ypos = n, ... = p |)(| xpos:= 0 |) = (| xpos = 0 , ypos = n, ... = p |) by simp

Equality of records. lemma n = n 0 ==> p = p 0 ==> (| xpos = n, ypos = p |) = (| xpos = n 0, ypos = p 0 |) — introduction of concrete record equality by simp lemma (| xpos = n, ypos = p |) = (| xpos = n 0, ypos = p 0 |) ==> n = n 0 — elimination of concrete record equality by simp lemma r (| xpos := n |)(| ypos := m |) = r (| ypos := m |)(| xpos := n |) — introduction of abstract record equality by simp lemma r (| xpos := n |) = r (| xpos := n 0 |) ==> n = n 0 — elimination of abstract record equality (manual proof) proof − assume r (| xpos := n |) = r (| xpos := n 0 |)(is ?lhs = ?rhs) then have xpos ?lhs = xpos ?rhs by simp then show ?thesis by simp qed

Surjective pairing lemma r = (| xpos = xpos r, ypos = ypos r |) by simp lemma r = (| xpos = xpos r, ypos = ypos r, ... = point.more r |) by simp

Representation of records by cases or (degenerate) induction. lemma r(| xpos := n |)(| ypos := m |) = r (| ypos := m |)(| xpos := n |) proof (cases r) fix xpos ypos more assume r = (| xpos = xpos, ypos = ypos, ... = more |) then show ?thesis by simp qed lemma r (| xpos := n |)(| ypos := m |) = r (| ypos := m |)(| xpos := n |) proof (induct r) fix xpos ypos more show (| xpos = xpos, ypos = ypos, ... = more |)(| xpos := n, ypos := m |) =

68 (| xpos = xpos, ypos = ypos, ... = more |)(| ypos := m, xpos := n |) by simp qed lemma r (| xpos := n |)(| xpos := m |) = r (| xpos := m |) proof (cases r) fix xpos ypos more assume r = (|xpos = xpos, ypos = ypos,... = more|) then show ?thesis by simp qed lemma r (| xpos := n |)(| xpos := m |) = r (| xpos := m |) proof (cases r) case fields then show ?thesis by simp qed lemma r (| xpos := n |)(| xpos := m |) = r (| xpos := m |) by (cases r) simp

Concrete records are type instances of record schemes. definition foo5 :: nat where foo5 = getX (| xpos = 1 , ypos = 0 |)

Manipulating the “...” (more) part. definition incX :: 0a point-scheme => 0a point-scheme where incX r = (| xpos = xpos r + 1 , ypos = ypos r, ... = point.more r |) lemma incX r = setX r (Suc (getX r)) by (simp add: getX-def setX-def incX-def )

An alternative definition. definition incX 0 :: 0a point-scheme => 0a point-scheme where incX 0 r = r (| xpos := xpos r + 1 |)

12.2 Coloured points: record extension datatype colour = Red | Green | Blue record cpoint = point + colour :: colour

The record declaration defines a new type constructor and abbreviations: cpoint = (| xpos :: nat, ypos :: nat, colour :: colour |) = () cpoint-ext-type point-ext-type 0a cpoint-scheme = (| xpos :: nat, ypos :: nat, colour :: colour, ... :: 0a |) = 0a cpoint-ext-type point-ext-type

69 consts foo6 :: cpoint consts foo7 :: (| xpos :: nat, ypos :: nat, colour :: colour |) consts foo8 :: 0a cpoint-scheme consts foo9 :: (| xpos :: nat, ypos :: nat, colour :: colour, ... :: 0a |)

Functions on point schemes work for cpoints as well. definition foo10 :: nat where foo10 = getX (| xpos = 2 , ypos = 0 , colour = Blue |)

12.2.1 Non-coercive structural subtyping

Term foo11 has type cpoint, not type point — Great! definition foo11 :: cpoint where foo11 = setX (| xpos = 2 , ypos = 0 , colour = Blue |) 0

12.3 Other features

Field names contribute to record identity. record point 0 = xpos 0 :: nat ypos 0 :: nat

May not apply getX to (| xpos 0 = 2 , ypos 0 = 0 |) – type error.

Polymorphic records. record 0a point 00 = point + content :: 0a type-synonym cpoint 00 = colour point 00

Updating a record field with an identical value is simplified. lemma r (| xpos := xpos r |) = r by simp

Only the most recent update to a component survives simplification. lemma r (| xpos := x, ypos := y, xpos := x 0 |) = r (| ypos := y, xpos := x 0 |) by simp

In some cases its convenient to automatically split (quantified) records. For this purpose there is the simproc Record.split_simproc and the tac- tic Record.split_simp_tac. The simplification procedure only splits the records, whereas the tactic also simplifies the resulting goal with the stan- dard record simplification rules. A (generalized) predicate on the record is passed as parameter that decides whether or how ‘deep’ to split the record. It can peek on the subterm starting at the quantified occurrence of the record (including the quantifier). The value 0 indicates no split, a value greater 0

70 splits up to the given bound of record extension and finally the value ~1 completely splits the record. Record.split_simp_tac additionally takes a list of equations for simplification and can also split fixed record variables. lemma (∀ r. P (xpos r)) −→ (∀ x. P x) apply (tactic hsimp-tac (put-simpset HOL-basic-ss @{context} ∼ addsimprocs [Record.split-simproc (K 1 )]) 1 i) apply simp done lemma (∀ r. P (xpos r)) −→ (∀ x. P x) ∼ apply (tactic hRecord.split-simp-tac @{context} [] (K 1 ) 1 i) apply simp done lemma (∃ r. P (xpos r)) −→ (∃ x. P x) apply (tactic hsimp-tac (put-simpset HOL-basic-ss @{context} ∼ addsimprocs [Record.split-simproc (K 1 )]) 1 i) apply simp done lemma (∃ r. P (xpos r)) −→ (∃ x. P x) ∼ apply (tactic hRecord.split-simp-tac @{context} [] (K 1 ) 1 i) apply simp done lemma Vr. P (xpos r) =⇒ (∃ x. P x) apply (tactic hsimp-tac (put-simpset HOL-basic-ss @{context} ∼ addsimprocs [Record.split-simproc (K 1 )]) 1 i) apply auto done lemma Vr. P (xpos r) =⇒ (∃ x. P x) ∼ apply (tactic hRecord.split-simp-tac @{context} [] (K 1 ) 1 i) apply auto done lemma P (xpos r) =⇒ (∃ x. P x) ∼ apply (tactic hRecord.split-simp-tac @{context} [] (K 1 ) 1 i) apply auto done lemma True proof − { fix P r assume pre: P (xpos r) then have ∃ x. P x apply − ∼ apply (tactic hRecord.split-simp-tac @{context} [] (K 1 ) 1 i)

71 apply auto done } show ?thesis .. qed

The effect of simproc Record.ex_sel_eq_simproc is illustrated by the fol- lowing lemma. lemma ∃ r. xpos r = x apply (tactic hsimp-tac (put-simpset HOL-basic-ss @{context} addsimprocs [Record.ex-sel-eq-simproc]) 1 i) done

12.4 A more complex record expression record ( 0a, 0b, 0c) bar = bar1 :: 0a bar2 :: 0b bar3 :: 0c bar21 :: 0b × 0a bar32 :: 0c × 0b bar31 :: 0c × 0a print-record ( 0a, 0b, 0c) bar

12.5 Some code generation export-code foo1 foo3 foo5 foo10 checking SML Code generation can also be switched off, for instance for very large records declare [[record-codegen = false]] record not-so-large-record = bar520 :: nat bar521 :: nat ∗ nat declare [[record-codegen = true]] end

13 A general “while” combinator theory While-Combinator imports Main begin

13.1 Partial version definition while-option :: ( 0a ⇒ bool) ⇒ ( 0a ⇒ 0a) ⇒ 0a ⇒ 0a option where while-option b c s = (if (∃ k. ∼ b ((c ˆˆ k) s))

72 then Some ((c ˆˆ (LEAST k. ∼ b ((c ˆˆ k) s))) s) else None) theorem while-option-unfold[code]: while-option b c s = (if b s then while-option b c (c s) else Some s) proof cases assume b s show ?thesis proof (cases ∃ k. ∼ b ((c ˆˆ k) s)) case True then obtain k where 1 : ∼ b ((c ˆˆ k) s) .. with hb s i obtain l where k = Suc l by (cases k) auto with 1 have ∼ b ((c ˆˆ l)(c s)) by (auto simp: funpow-swap1 ) then have 2 : ∃ l. ∼ b ((c ˆˆ l)(c s)) .. from 1 have (LEAST k. ∼ b ((c ˆˆ k) s)) = Suc (LEAST l. ∼ b ((c ˆˆ Suc l) s)) by (rule Least-Suc)(simp add: hb s i) also have ... = Suc (LEAST l. ∼ b ((c ˆˆ l)(c s))) by (simp add: funpow-swap1 ) finally show ?thesis using True 2 hb s i by (simp add: funpow-swap1 while-option-def ) next case False then have ∼ (∃ l. ∼ b ((c ˆˆ Suc l) s)) by blast then have ∼ (∃ l. ∼ b ((c ˆˆ l)(c s))) by (simp add: funpow-swap1 ) with False hb s i show ?thesis by (simp add: while-option-def ) qed next assume [simp]: ∼ b s have least:(LEAST k. ∼ b ((c ˆˆ k) s)) = 0 by (rule Least-equality) auto moreover have ∃ k. ∼ b ((c ˆˆ k) s) by (rule exI [of - 0 ::nat]) auto ultimately show ?thesis unfolding while-option-def by auto qed lemma while-option-stop2 : while-option b c s = Some t =⇒ EX k. t = (cˆˆk) s ∧ ¬ b t apply(simp add: while-option-def split: if-splits) by (metis (lifting) LeastI-ex) lemma while-option-stop: while-option b c s = Some t =⇒ ∼ b t by(metis while-option-stop2 ) theorem while-option-rule: assumes step: !!s. P s ==> b s ==> P (c s) and result: while-option b c s = Some t

73 and init: P s shows P t proof − define k where k = (LEAST k. ∼ b ((c ˆˆ k) s)) from assms have t: t = (c ˆˆ k) s by (simp add: while-option-def k-def split: if-splits) have 1 : ALL i

{ fix i assume i <= k then have P ((c ˆˆ i) s) by (induct i)(auto simp: init step 1 ) } thus P t by (auto simp: t) qed lemma funpow-commute: [[∀ k 0 < k. f (c ((cˆˆk 0) s)) = c 0 (f ((cˆˆk 0) s))]] =⇒ f ((cˆˆk) s) = (c 0ˆˆk)(f s) by (induct k arbitrary: s) auto lemma while-option-commute-invariant: assumes Invariant: Vs. P s =⇒ b s =⇒ P (c s) assumes TestCommute: Vs. P s =⇒ b s = b 0 (f s) assumes BodyCommute: Vs. P s =⇒ b s =⇒ f (c s) = c 0 (f s) assumes Initial: P s shows map-option f (while-option b c s) = while-option b 0 c 0 (f s) unfolding while-option-def proof (rule trans[OF if-distrib if-cong], safe, unfold option.inject) fix k assume ¬ b ((c ˆˆ k) s) with Initial show ∃ k. ¬ b 0 ((c 0 ˆˆ k)(f s)) proof (induction k arbitrary: s) case 0 thus ?case by (auto simp: TestCommute intro: exI [of - 0 ]) next case (Suc k) thus ?case proof (cases b s) assume b s with Suc.IH [of c s] Suc.prems show ?thesis by (metis BodyCommute Invariant comp-apply funpow.simps(2 ) funpow-swap1 ) next assume ¬ b s with Suc show ?thesis by (auto simp: TestCommute intro: exI [of - 0 ]) qed qed next fix k assume ¬ b 0 ((c 0 ˆˆ k)(f s)) with Initial show ∃ k. ¬ b ((c ˆˆ k) s) proof (induction k arbitrary: s) case 0 thus ?case by (auto simp: TestCommute intro: exI [of - 0 ]) next

74 case (Suc k) thus ?case proof (cases b s) assume b s with Suc.IH [of c s] Suc.prems show ?thesis by (metis BodyCommute Invariant comp-apply funpow.simps(2 ) funpow-swap1 ) next assume ¬ b s with Suc show ?thesis by (auto simp: TestCommute intro: exI [of - 0 ]) qed qed next fix k assume k: ¬ b 0 ((c 0 ˆˆ k)(f s)) have ∗:(LEAST k. ¬ b 0 ((c 0 ˆˆ k)(f s))) = (LEAST k. ¬ b ((c ˆˆ k) s)) (is ?k 0 = ?k) proof (cases ?k 0) case 0 have ¬ b 0 ((c 0 ˆˆ 0 )(f s)) unfolding 0 [symmetric] by (rule LeastI [of - k]) (rule k) hence ¬ b s by (auto simp: TestCommute Initial) hence ?k = 0 by (intro Least-equality) auto with 0 show ?thesis by auto next case (Suc k 0) have ¬ b 0 ((c 0 ˆˆ Suc k 0)(f s)) unfolding Suc[symmetric] by (rule LeastI )(rule k) moreover { fix k assume k ≤ k 0 hence k < ?k 0 unfolding Suc by simp hence b 0 ((c 0 ˆˆ k)(f s)) by (rule iffD1 [OF not-not, OF not-less-Least]) } note b 0 = this { fix k assume k ≤ k 0 hence f ((c ˆˆ k) s) = (c 0 ˆˆ k)(f s) and b ((c ˆˆ k) s) = b 0 ((c 0 ˆˆ k)(f s)) and P ((c ˆˆ k) s) by (induct k)(auto simp: b 0 assms) 0 with hk ≤ k i have b ((c ˆˆ k) s) and f ((c ˆˆ k) s) = (c 0 ˆˆ k)(f s) and P ((c ˆˆ k) s) by (auto simp: b 0) } note b = this(1 ) and body = this(2 ) and inv = this(3 ) hence k 0: f ((c ˆˆ k 0) s) = (c 0 ˆˆ k 0)(f s) by auto ultimately show ?thesis unfolding Suc using b proof (intro Least-equality[symmetric], goal-cases) case 1 hence Test: ¬ b 0 (f ((c ˆˆ Suc k 0) s))

75 by (auto simp: BodyCommute inv b) have P ((c ˆˆ Suc k 0) s) by (auto simp: Invariant inv b) with Test show ?case by (auto simp: TestCommute) next case 2 thus ?case by (metis not-less-eq-eq) qed qed have f ((c ˆˆ ?k) s) = (c 0 ˆˆ ?k 0)(f s) unfolding ∗ proof (rule funpow-commute, clarify) fix k assume k < ?k hence TestTrue: b ((c ˆˆ k) s) by (auto dest: not-less-Least) from hk < ?k i have P ((c ˆˆ k) s) proof (induct k) case 0 thus ?case by (auto simp: assms) next case (Suc h) hence P ((c ˆˆ h) s) by auto with Suc show ?case by (auto, metis (lifting, no-types) Invariant Suc-lessD not-less-Least) qed with TestTrue show f (c ((c ˆˆ k) s)) = c 0 (f ((c ˆˆ k) s)) by (metis BodyCommute) qed thus ∃ z. (c ˆˆ ?k) s = z ∧ f z = (c 0 ˆˆ ?k 0)(f s) by blast qed lemma while-option-commute: assumes Vs. b s = b 0 (f s) Vs. [[b s]] =⇒ f (c s) = c 0 (f s) shows map-option f (while-option b c s) = while-option b 0 c 0 (f s) by(rule while-option-commute-invariant[where P = λ-. True]) (auto simp add: assms)

13.2 Total version definition while :: ( 0a ⇒ bool) ⇒ ( 0a ⇒ 0a) ⇒ 0a ⇒ 0a where while b c s = the (while-option b c s) lemma while-unfold [code]: while b c s = (if b s then while b c (c s) else s) unfolding while-def by (subst while-option-unfold) simp lemma def-while-unfold: assumes fdef : f == while test do shows f x = (if test x then f (do x) else x) unfolding fdef by (fact while-unfold)

The proof rule for while, where P is the invariant. theorem while-rule-lemma:

76 assumes invariant: !!s. P s ==> b s ==> P (c s) and terminate: !!s. P s ==> ¬ b s ==> Q s and wf : wf {(t, s). P s ∧ b s ∧ t = c s} shows P s =⇒ Q (while b c s) using wf apply (induct s) apply simp apply (subst while-unfold) apply (simp add: invariant terminate) done theorem while-rule: [| P s; !!s. [| P s; b s |] ==> P (c s); !!s. [| P s; ¬ b s |] ==> Q s; wf r; !!s. [| P s; b s |] ==> (c s, s) ∈ r |] ==> Q (while b c s) apply (rule while-rule-lemma) prefer 4 apply assumption apply blast apply blast apply (erule wf-subset) apply blast done

Proving termination: theorem wf-while-option-Some: assumes wf {(t, s). (P s ∧ b s) ∧ t = c s} and !!s. P s =⇒ b s =⇒ P(c s) and P s shows EX t. while-option b c s = Some t using assms(1 ,3 ) proof (induction s) case less thus ?case using assms(2 ) by (subst while-option-unfold) simp qed lemma wf-rel-while-option-Some: assumes wf : wf R assumes smaller: Vs. P s ∧ b s =⇒ (c s, s) ∈ R assumes inv: Vs. P s ∧ b s =⇒ P(c s) assumes init: P s shows ∃ t. while-option b c s = Some t proof − from smaller have {(t,s). P s ∧ b s ∧ t = c s} ⊆ R by auto with wf have wf {(t,s). P s ∧ b s ∧ t = c s} by (auto simp: wf-subset) with inv init show ?thesis by (auto simp: wf-while-option-Some) qed

77 theorem measure-while-option-Some: fixes f :: 0s ⇒ nat shows (!!s. P s =⇒ b s =⇒ P(c s) ∧ f (c s) < f s) =⇒ P s =⇒ EX t. while-option b c s = Some t by(blast intro: wf-while-option-Some[OF wf-if-measure, of P b f ])

Kleene iteration starting from the empty set and assuming some finite bounding set: lemma while-option-finite-subset-Some: fixes C :: 0a set assumes mono f and !!X . X ⊆ C =⇒ f X ⊆ C and finite C shows ∃ P. while-option (λA. f A 6= A) f {} = Some P proof(rule measure-while-option-Some[where f = %A:: 0a set. card C − card A and P= %A. A ⊆ C ∧ A ⊆ f A and s= {}]) fix A assume A: A ⊆ C ∧ A ⊆ f A f A 6= A show (f A ⊆ C ∧ f A ⊆ f (f A)) ∧ card C − card (f A) < card C − card A (is ?L ∧ ?R) proof show ?L by(metis A(1 ) assms(2 ) monoD[OF hmono f i]) show ?R by (metis A assms(2 ,3 ) card-seteq diff-less-mono2 equalityI linorder-le-less-linear rev-finite-subset) qed qed simp lemma lfp-the-while-option: assumes mono f and !!X . X ⊆ C =⇒ f X ⊆ C and finite C shows lfp f = the(while-option (λA. f A 6= A) f {}) proof− obtain P where while-option (λA. f A 6= A) f {} = Some P using while-option-finite-subset-Some[OF assms] by blast with while-option-stop2 [OF this] lfp-Kleene-iter[OF assms(1 )] show ?thesis by auto qed lemma lfp-while: assumes mono f and !!X . X ⊆ C =⇒ f X ⊆ C and finite C shows lfp f = while (λA. f A 6= A) f {} unfolding while-def using assms by (rule lfp-the-while-option) blast lemma wf-finite-less: assumes finite (C :: 0a::order set) shows wf {(x, y). {x, y} ⊆ C ∧ x < y} by (rule wf-measure[where f =λb. card {a. a ∈ C ∧ a < b}, THEN wf-subset]) (fastforce simp: less-eq assms intro: psubset-card-mono) lemma wf-finite-greater: assumes finite (C :: 0a::order set) shows wf {(x, y). {x, y} ⊆ C ∧ y < x} by (rule wf-measure[where f =λb. card {a. a ∈ C ∧ b < a}, THEN wf-subset]) (fastforce simp: less-eq assms intro: psubset-card-mono)

78 lemma while-option-finite-increasing-Some: fixes f :: 0a::order ⇒ 0a assumes mono f and finite (UNIV :: 0a set) and s ≤ f s shows ∃ P. while-option (λA. f A 6= A) f s = Some P by (rule wf-rel-while-option-Some[where R={(x, y). y < x} and P=λA. A ≤ f A and s=s]) (auto simp: assms monoD intro: wf-finite-greater[where C =UNIV :: 0a set, sim- plified]) lemma lfp-the-while-option-lattice: fixes f :: 0a::complete-lattice ⇒ 0a assumes mono f and finite (UNIV :: 0a set) shows lfp f = the (while-option (λA. f A 6= A) f bot) proof − obtain P where while-option (λA. f A 6= A) f bot = Some P using while-option-finite-increasing-Some[OF assms, where s=bot] by simp blast with while-option-stop2 [OF this] lfp-Kleene-iter[OF assms(1 )] show ?thesis by auto qed lemma lfp-while-lattice: fixes f :: 0a::complete-lattice ⇒ 0a assumes mono f and finite (UNIV :: 0a set) shows lfp f = while (λA. f A 6= A) f bot unfolding while-def using assms by (rule lfp-the-while-option-lattice) lemma while-option-finite-decreasing-Some: fixes f :: 0a::order ⇒ 0a assumes mono f and finite (UNIV :: 0a set) and f s ≤ s shows ∃ P. while-option (λA. f A 6= A) f s = Some P by (rule wf-rel-while-option-Some[where R={(x, y). x < y} and P=λA. f A ≤ A and s=s]) (auto simp add: assms monoD intro: wf-finite-less[where C =UNIV :: 0a set, simplified]) lemma gfp-the-while-option-lattice: fixes f :: 0a::complete-lattice ⇒ 0a assumes mono f and finite (UNIV :: 0a set) shows gfp f = the(while-option (λA. f A 6= A) f top) proof − obtain P where while-option (λA. f A 6= A) f top = Some P using while-option-finite-decreasing-Some[OF assms, where s=top] by simp blast with while-option-stop2 [OF this] gfp-Kleene-iter[OF assms(1 )] show ?thesis by auto qed lemma gfp-while-lattice:

79 fixes f :: 0a::complete-lattice ⇒ 0a assumes mono f and finite (UNIV :: 0a set) shows gfp f = while (λA. f A 6= A) f top unfolding while-def using assms by (rule gfp-the-while-option-lattice) Computing the reflexive, transitive closure by iterating a successor function. Stops when an element is found that dos not satisfy the test. More refined (and hence more efficient) versions can be found in ITP 2011 paper by Nipkow (the theories are in the AFP entry Flyspeck by Nipkow) and the AFP article Executable Transitive Closures by Ren´eThiemann. context fixes p :: 0a ⇒ bool and f :: 0a ⇒ 0a list and x :: 0a begin qualified fun rtrancl-while-test :: 0a list × 0a set ⇒ bool where rtrancl-while-test (ws,-) = (ws 6= [] ∧ p(hd ws)) qualified fun rtrancl-while-step :: 0a list × 0a set ⇒ 0a list × 0a set where rtrancl-while-step (ws, Z ) = (let x = hd ws; new = remdups (filter (λy. y ∈/ Z )(f x)) in (new @ tl ws, set new ∪ Z )) definition rtrancl-while :: ( 0a list ∗ 0a set) option where rtrancl-while = while-option rtrancl-while-test rtrancl-while-step ([x],{x}) qualified fun rtrancl-while-invariant :: 0a list × 0a set ⇒ bool where rtrancl-while-invariant (ws, Z ) = (x ∈ Z ∧ set ws ⊆ Z ∧ distinct ws ∧ {(x,y). y ∈ set(f x)} ‘‘ (Z − set ws) ⊆ Z ∧ Z ⊆ {(x,y). y ∈ set(f x)}ˆ∗ ‘‘ {x} ∧ (∀ z∈Z − set ws. p z)) qualified lemma rtrancl-while-invariant: assumes inv: rtrancl-while-invariant st and test: rtrancl-while-test st shows rtrancl-while-invariant (rtrancl-while-step st) proof (cases st) fix ws Z assume st: st = (ws, Z ) with test obtain h t where ws = h # t p h by (cases ws) auto with inv st show ?thesis by (auto intro: rtrancl.rtrancl-into-rtrancl) qed lemma rtrancl-while-Some: assumes rtrancl-while = Some(ws,Z ) shows if ws = [] then Z = {(x,y). y ∈ set(f x)}ˆ∗ ‘‘ {x} ∧ (∀ z∈Z . p z) else ¬p(hd ws) ∧ hd ws ∈ {(x,y). y ∈ set(f x)}ˆ∗ ‘‘ {x} proof − have rtrancl-while-invariant ([x],{x}) by simp with rtrancl-while-invariant have I : rtrancl-while-invariant (ws,Z )

80 by (rule while-option-rule[OF - assms[unfolded rtrancl-while-def ]]) { assume ws = [] hence ?thesis using I by (auto simp del:Image-Collect-case-prod dest: Image-closed-trancl) } moreover { assume ws 6= [] hence ?thesis using I while-option-stop[OF assms[unfolded rtrancl-while-def ]] by (simp add: subset-iff ) } ultimately show ?thesis by simp qed lemma rtrancl-while-finite-Some: assumes finite ({(x, y). y ∈ set (f x)}∗ ‘‘ {x})(is finite ?Cl) shows ∃ y. rtrancl-while = Some y proof − let ?R = (λ(-, Z ). card (?Cl − Z )) <∗mlex∗> (λ(ws, -). length ws) <∗mlex∗> {} have wf ?R by (blast intro: wf-mlex) then show ?thesis unfolding rtrancl-while-def proof (rule wf-rel-while-option-Some[of ?R rtrancl-while-invariant]) fix st assume ∗: rtrancl-while-invariant st ∧ rtrancl-while-test st hence I : rtrancl-while-invariant (rtrancl-while-step st) by (blast intro: rtrancl-while-invariant) show (rtrancl-while-step st, st) ∈ ?R proof (cases st) fix ws Z let ?ws = fst (rtrancl-while-step st) and ?Z = snd (rtrancl-while-step st) assume st: st = (ws, Z ) with ∗ obtain h t where ws: ws = h # t p h by (cases ws) auto { assume remdups (filter (λy. y ∈/ Z )(f h)) 6= [] then obtain z where z ∈ set (remdups (filter (λy. y ∈/ Z )(f h))) by fastforce with st ws I have Z ⊂ ?Z Z ⊆ ?Cl ?Z ⊆ ?Cl by auto with assms have card (?Cl − ?Z ) < card (?Cl − Z ) by (blast intro: psubset-card-mono) with st ws have ?thesis unfolding mlex-prod-def by simp } moreover { assume remdups (filter (λy. y ∈/ Z )(f h)) = [] with st ws have ?Z = Z ?ws = t by (auto simp: filter-empty-conv) with st ws have ?thesis unfolding mlex-prod-def by simp } ultimately show ?thesis by blast qed qed (simp-all add: rtrancl-while-invariant) qed end

81 end

14 An application of the While combinator theory While-Combinator-Example imports ∼∼/src/HOL/Library/While-Combinator begin

Computation of the lfp on finite sets via iteration. theorem lfp-conv-while: [| mono f ; finite U ; f U = U |] ==> lfp f = fst (while (λ(A, fA). A 6= fA)(λ(A, fA). (fA, f fA)) ({}, f {})) apply (rule-tac P = λ(A, B). (A ⊆ U ∧ B = f A ∧ A ⊆ B ∧ B ⊆ lfp f ) and r = ((Pow U × UNIV ) × (Pow U × UNIV )) ∩ inv-image finite-psubset (op − U o fst) in while-rule) apply (subst lfp-unfold) apply assumption apply (simp add: monoD) apply (subst lfp-unfold) apply assumption apply clarsimp apply (blast dest: monoD) apply (fastforce intro!: lfp-lowerbound) apply (blast intro: wf-finite-psubset Int-lower2 [THEN [2 ] wf-subset]) apply (clarsimp simp add: finite-psubset-def order-less-le) apply (blast dest: monoD) done

14.1 Example

Cannot use set-eq-subset because it leads to looping because the antisym- metry simproc turns the subset relationship back into equality. theorem P (lfp (λN ::int set. {0 } ∪ {(n + 2 ) mod 6 | n. n ∈ N })) = P {0 , 4 , 2 } proof − have seteq: !!AB. (A = B) = ((!a : A. a:B) & (!b:B. b:A)) by blast have aux: !!f A B. {f n | n. A n ∨ B n} = {f n | n. A n} ∪ {f n | n. B n} apply blast done show ?thesis apply (subst lfp-conv-while [where ?U = {0 , 1 , 2 , 3 , 4 , 5 }]) apply (rule monoI ) apply blast apply simp apply (simp add: aux set-eq-subset)

82 The fixpoint computation is performed purely by rewriting: apply (simp add: while-unfold aux seteq del: subset-empty) done qed end

15 Monoids and Groups as predicates over record schemes theory MonoidGroup imports Main begin record 0a monoid-sig = times :: 0a => 0a => 0a one :: 0a record 0a group-sig = 0a monoid-sig + inv :: 0a => 0a definition monoid :: (| times :: 0a => 0a => 0a, one :: 0a, ... :: 0b |) => bool where monoid M = (∀ x y z. times M (times M x y) z = times M x (times M y z) ∧ times M (one M ) x = x ∧ times M x (one M ) = x) definition group :: (| times :: 0a => 0a => 0a, one :: 0a, inv :: 0a => 0a, ... :: 0b |) => bool where group G = (monoid G ∧ (∀ x. times G (inv G x) x = one G)) definition reverse :: (| times :: 0a => 0a => 0a, one :: 0a, ... :: 0b |) => (| times :: 0a => 0a => 0a, one :: 0a, ... :: 0b |) where reverse M = M (| times := λx y. times M y x |) end

16 Binary arithmetic examples theory BinEx imports Complex-Main begin

16.1 Regression Testing for Cancellation Simprocs lemma l + 2 + 2 + 2 + (l + 2 ) + (oo + 2 ) = (uu::int) apply simp oops

83 lemma 2 ∗u = (u::int) apply simp oops lemma (i + j + 12 + (k::int)) − 15 = y apply simp oops lemma (i + j + 12 + (k::int)) − 5 = y apply simp oops lemma y − b < (b::int) apply simp oops lemma y − (3 ∗b + c) < (b::int) − 2 ∗c apply simp oops lemma (2 ∗x − (u∗v) + y) − v∗3 ∗u = (w::int) apply simp oops lemma (2 ∗x∗u∗v + (u∗v)∗4 + y) − v∗u∗4 = (w::int) apply simp oops lemma (2 ∗x∗u∗v + (u∗v)∗4 + y) − v∗u = (w::int) apply simp oops lemma u∗v − (x∗u∗v + (u∗v)∗4 + y) = (w::int) apply simp oops lemma (i + j + 12 + (k::int)) = u + 15 + y apply simp oops lemma (i + j ∗2 + 12 + (k::int)) = j + 5 + y apply simp oops lemma 2 ∗y + 3 ∗z + 6 ∗w + 2 ∗y + 3 ∗z + 2 ∗u = 2 ∗y 0 + 3 ∗z 0 + 6 ∗w 0 + 2 ∗y 0 + 3 ∗z 0 + u + (vv::int) apply simp oops lemma a + −(b+c) + b = (d::int) apply simp oops lemma a + −(b+c) − b = (d::int) apply simp oops lemma (i + j + −2 + (k::int)) − (u + 5 + y) = zz apply simp oops lemma (i + j + −3 + (k::int)) < u + 5 + y

84 apply simp oops lemma (i + j + 3 + (k::int)) < u + −6 + y apply simp oops lemma (i + j + −12 + (k::int)) − 15 = y apply simp oops lemma (i + j + 12 + (k::int)) − −15 = y apply simp oops lemma (i + j + −12 + (k::int)) − −15 = y apply simp oops lemma − (2 ∗i) + 3 + (2 ∗i + 4 ) = (0 ::int) apply simp oops lemma (pi ∗ (real u ∗ 2 ) = pi ∗ (real (xa v) ∗ − 2 )) apply simp oops

16.2 Arithmetic Method Tests lemma !!a::int. [| a <= b; c <= d; x+y a+c <= b+d by arith lemma !!a::int. [| a < b; c < d |] ==> a−d+ 2 <= b+(−c) by arith lemma !!a::int. [| a < b; c < d |] ==> a+c+ 1 < b+d by arith lemma !!a::int. [| a <= b; b+b <= c |] ==> a+a <= c by arith lemma !!a::int. [| a+b <= i+j ; a<=b; i<=j |] ==> a+a <= j +j by arith lemma !!a::int. [| a+b < i+j ; a a+a − − (− 1 ) < j +j − 3 by arith lemma !!a::int. a+b+c <= i+j +k & a<=b & b<=c & i<=j & j <=k −−> a+a+a <= k+k+k by arith lemma !!a::int. [| a+b+c+d <= i+j +k+l; a<=b; b<=c; c<=d; i<=j ; j <=k; k<=l |] ==> a <= l by arith

85 lemma !!a::int. [| a+b+c+d <= i+j +k+l; a<=b; b<=c; c<=d; i<=j ; j <=k; k<=l |] ==> a+a+a+a <= l+l+l+l by arith lemma !!a::int. [| a+b+c+d <= i+j +k+l; a<=b; b<=c; c<=d; i<=j ; j <=k; k<=l |] ==> a+a+a+a+a <= l+l+l+l+i by arith lemma !!a::int. [| a+b+c+d <= i+j +k+l; a<=b; b<=c; c<=d; i<=j ; j <=k; k<=l |] ==> a+a+a+a+a+a <= l+l+l+l+i+l by arith lemma !!a::int. [| a+b+c+d <= i+j +k+l; a<=b; b<=c; c<=d; i<=j ; j <=k; k<=l |] ==> 6 ∗a <= 5 ∗l+i by arith

16.3 The Integers

Addition lemma (13 ::int) + 19 = 32 by simp lemma (1234 ::int) + 5678 = 6912 by simp lemma (1359 ::int) + −2468 = −1109 by simp lemma (93746 ::int) + −46375 = 47371 by simp

Negation lemma − (65745 ::int) = −65745 by simp lemma − (−54321 ::int) = 54321 by simp

Multiplication lemma (13 ::int) ∗ 19 = 247 by simp

86 lemma (−84 ::int) ∗ 51 = −4284 by simp lemma (255 ::int) ∗ 255 = 65025 by simp lemma (1359 ::int) ∗ −2468 = −3354012 by simp lemma (89 ::int) ∗ 10 6= 889 by simp lemma (13 ::int) < 18 − 4 by simp lemma (−345 ::int) < −242 + −100 by simp lemma (13557456 ::int) < 18678654 by simp lemma (999999 ::int) ≤ (1000001 + 1 ) − 2 by simp lemma (1234567 ::int) ≤ 1234567 by simp

No integer overflow! lemma 1234567 ∗ (1234567 ::int) < 1234567 ∗1234567 ∗1234567 by simp

Quotient and Remainder lemma (10 ::int) div 3 = 3 by simp lemma (10 ::int) mod 3 = 1 by simp

A negative lemma (10 ::int) div −3 = −4 by simp lemma (10 ::int) mod −3 = −2 by simp

A negative dividend1

1The definition agrees with mathematical convention and with ML, but not with the hardware of most computers

87 lemma (−10 ::int) div 3 = −4 by simp lemma (−10 ::int) mod 3 = 2 by simp

A negative dividend and divisor lemma (−10 ::int) div −3 = 3 by simp lemma (−10 ::int) mod −3 = −1 by simp

A few bigger examples lemma (8452 ::int) mod 3 = 1 by simp lemma (59485 ::int) div 434 = 137 by simp lemma (1000006 ::int) mod 10 = 6 by simp

Division by shifting lemma 10000000 div 2 = (5000000 ::int) by simp lemma 10000001 mod 2 = (1 ::int) by simp lemma 10000055 div 32 = (312501 ::int) by simp lemma 10000055 mod 32 = (23 ::int) by simp lemma 100094 div 144 = (695 ::int) by simp lemma 100094 mod 144 = (14 ::int) by simp

Powers lemma 2 ˆ 10 = (1024 ::int) by simp lemma (− 3 ) ˆ 7 = (−2187 ::int)

88 by simp lemma 13 ˆ 7 = (62748517 ::int) by simp lemma 3 ˆ 15 = (14348907 ::int) by simp lemma (− 5 ) ˆ 11 = (−48828125 ::int) by simp

16.4 The Natural Numbers

Successor lemma Suc 99999 = 100000 by simp

Addition lemma (13 ::nat) + 19 = 32 by simp lemma (1234 ::nat) + 5678 = 6912 by simp lemma (973646 ::nat) + 6475 = 980121 by simp

Subtraction lemma (32 ::nat) − 14 = 18 by simp lemma (14 ::nat) − 15 = 0 by simp lemma (14 ::nat) − 1576644 = 0 by simp lemma (48273776 ::nat) − 3873737 = 44400039 by simp

Multiplication lemma (12 ::nat) ∗ 11 = 132 by simp lemma (647 ::nat) ∗ 3643 = 2357021 by simp

89 Quotient and Remainder lemma (10 ::nat) div 3 = 3 by simp lemma (10 ::nat) mod 3 = 1 by simp lemma (10000 ::nat) div 9 = 1111 by simp lemma (10000 ::nat) mod 9 = 1 by simp lemma (10000 ::nat) div 16 = 625 by simp lemma (10000 ::nat) mod 16 = 0 by simp

Powers lemma 2 ˆ 12 = (4096 ::nat) by simp lemma 3 ˆ 10 = (59049 ::nat) by simp lemma 12 ˆ 7 = (35831808 ::nat) by simp lemma 3 ˆ 14 = (4782969 ::nat) by simp lemma 5 ˆ 11 = (48828125 ::nat) by simp

Testing the cancellation of complementary terms lemma y + (x + −x) = (0 ::int) + y by simp lemma y + (−x + (− y + x)) = (0 ::int) by simp lemma −x + (y + (− y + x)) = (0 ::int) by simp lemma x + (x + (− x + (− x + (− y + − z)))) = (0 ::int) − y − z by simp

90 lemma x + x − x − x − y − z = (0 ::int) − y − z by simp lemma x + y + z − (x + z) = y − (0 ::int) by simp lemma x + (y + (y + (y + (−x + −x)))) = (0 ::int) + y − x + y + y by simp lemma x + (y + (y + (y + (−y + −x)))) = y + (0 ::int) + y by simp lemma x + y − x + z − x − y − z + x < (1 ::int) by simp

16.5 Real Arithmetic 16.5.1 Addition lemma (1359 ::real) + −2468 = −1109 by simp lemma (93746 ::real) + −46375 = 47371 by simp

16.5.2 Negation lemma − (65745 ::real) = −65745 by simp lemma − (−54321 ::real) = 54321 by simp

16.5.3 Multiplication lemma (−84 ::real) ∗ 51 = −4284 by simp lemma (255 ::real) ∗ 255 = 65025 by simp lemma (1359 ::real) ∗ −2468 = −3354012 by simp

16.5.4 Inequalities lemma (89 ::real) ∗ 10 6= 889 by simp lemma (13 ::real) < 18 − 4

91 by simp lemma (−345 ::real) < −242 + −100 by simp lemma (13557456 ::real) < 18678654 by simp lemma (999999 ::real) ≤ (1000001 + 1 ) − 2 by simp lemma (1234567 ::real) ≤ 1234567 by simp

16.5.5 Powers lemma 2 ˆ 15 = (32768 ::real) by simp lemma (− 3 ) ˆ 7 = (−2187 ::real) by simp lemma 13 ˆ 7 = (62748517 ::real) by simp lemma 3 ˆ 15 = (14348907 ::real) by simp lemma (− 5 ) ˆ 11 = (−48828125 ::real) by simp

16.5.6 Tests lemma (x + y = x) = (y = (0 ::real)) by arith lemma (x + y = y) = (x = (0 ::real)) by arith lemma (x + y = (0 ::real)) = (x = −y) by arith lemma (x + y = (0 ::real)) = (y = −x) by arith lemma ((x + y) < (x + z)) = (y < (z::real)) by arith lemma ((x + z) < (y + z)) = (x < (y::real)) by arith

92 lemma (¬ x < y) = (y ≤ (x::real)) by arith lemma ¬ (x < y ∧ y < (x::real)) by arith lemma (x::real) < y ==> ¬ y < x by arith lemma ((x::real) 6= y) = (x < y ∨ y < x) by arith lemma (¬ x ≤ y) = (y < (x::real)) by arith lemma x ≤ y ∨ y ≤ (x::real) by arith lemma x ≤ y ∨ y < (x::real) by arith lemma x < y ∨ y ≤ (x::real) by arith lemma x ≤ (x::real) by arith lemma ((x::real) ≤ y) = (x < y ∨ x = y) by arith lemma ((x::real) ≤ y ∧ y ≤ x) = (x = y) by arith lemma ¬(x < y ∧ y ≤ (x::real)) by arith lemma ¬(x ≤ y ∧ y < (x::real)) by arith lemma (−x < (0 ::real)) = (0 < x) by arith lemma ((0 ::real) < −x) = (x < 0 ) by arith lemma (−x ≤ (0 ::real)) = (0 ≤ x) by arith

93 lemma ((0 ::real) ≤ −x) = (x ≤ 0 ) by arith lemma (x::real) = y ∨ x < y ∨ y < x by arith lemma (x::real) = 0 ∨ 0 < x ∨ 0 < −x by arith lemma (0 ::real) ≤ x ∨ 0 ≤ −x by arith lemma ((x::real) + y ≤ x + z) = (y ≤ z) by arith lemma ((x::real) + z ≤ y + z) = (x ≤ y) by arith lemma (w::real) < x ∧ y < z ==> w + y < x + z by arith lemma (w::real) ≤ x ∧ y ≤ z ==> w + y ≤ x + z by arith lemma (0 ::real) ≤ x ∧ 0 ≤ y ==> 0 ≤ x + y by arith lemma (0 ::real) < x ∧ 0 < y ==> 0 < x + y by arith lemma (−x < y) = (0 < x + (y::real)) by arith lemma (x < −y) = (x + y < (0 ::real)) by arith lemma (y < x + −z) = (y + z < (x::real)) by arith lemma (x + −y < z) = (x < z + (y::real)) by arith lemma x ≤ y ==> x < y + (1 ::real) by arith lemma (x − y) + y = (x::real) by arith lemma y + (x − y) = (x::real)

94 by arith lemma x − x = (0 ::real) by arith lemma (x − y = 0 ) = (x = (y::real)) by arith lemma ((0 ::real) ≤ x + x) = (0 ≤ x) by arith lemma (−x ≤ x) = ((0 ::real) ≤ x) by arith lemma (x ≤ −x) = (x ≤ (0 ::real)) by arith lemma (−x = (0 ::real)) = (x = 0 ) by arith lemma −(x − y) = y − (x::real) by arith lemma ((0 ::real) < x − y) = (y < x) by arith lemma ((0 ::real) ≤ x − y) = (y ≤ x) by arith lemma (x + y) − x = (y::real) by arith lemma (−x = y) = (x = (−y::real)) by arith lemma x < (y::real) ==> ¬(x = y) by arith lemma (x ≤ x + y) = ((0 ::real) ≤ y) by arith lemma (y ≤ x + y) = ((0 ::real) ≤ x) by arith lemma (x < x + y) = ((0 ::real) < y) by arith lemma (y < x + y) = ((0 ::real) < x) by arith

95 lemma (x − y) − x = (−y::real) by arith lemma (x + y < z) = (x < z − (y::real)) by arith lemma (x − y < z) = (x < z + (y::real)) by arith lemma (x < y − z) = (x + z < (y::real)) by arith lemma (x ≤ y − z) = (x + z ≤ (y::real)) by arith lemma (x − y ≤ z) = (x ≤ z + (y::real)) by arith lemma (−x < −y) = (y < (x::real)) by arith lemma (−x ≤ −y) = (y ≤ (x::real)) by arith lemma (a + b) − (c + d) = (a − c) + (b − (d::real)) by arith lemma (0 ::real) − x = −x by arith lemma x − (0 ::real) = x by arith lemma w ≤ x ∧ y < z ==> w + y < x + (z::real) by arith lemma w < x ∧ y ≤ z ==> w + y < x + (z::real) by arith lemma (0 ::real) ≤ x ∧ 0 < y ==> 0 < x + (y::real) by arith lemma (0 ::real) < x ∧ 0 ≤ y ==> 0 < x + y by arith lemma −x − y = −(x + (y::real)) by arith

96 lemma x − (−y) = x + (y::real) by arith lemma −x − −y = y − (x::real) by arith lemma (a − b) + (b − c) = a − (c::real) by arith lemma (x = y − z) = (x + z = (y::real)) by arith lemma (x − y = z) = (x = z + (y::real)) by arith lemma x − (x − y) = (y::real) by arith lemma x − (x + y) = −(y::real) by arith lemma x = y ==> x ≤ (y::real) by arith lemma (0 ::real) < x ==> ¬(x = 0 ) by arith lemma (x + y) ∗ (x − y) = (x ∗ x) − (y ∗ y) oops lemma (−x = −y) = (x = (y::real)) by arith lemma (−x < −y) = (y < (x::real)) by arith lemma !!a::real. a ≤ b ==> c ≤ d ==> x + y < z ==> a + c ≤ b + d by linarith lemma !!a::real. a < b ==> c < d ==> a − d ≤ b + (−c) by linarith lemma !!a::real. a ≤ b ==> b + b ≤ c ==> a + a ≤ c by linarith lemma !!a::real. a + b ≤ i + j ==> a ≤ b ==> i ≤ j ==> a + a ≤ j + j by linarith lemma !!a::real. a + b < i + j ==> a < b ==> i < j ==> a + a < j + j

97 by linarith lemma !!a::real. a + b + c ≤ i + j + k ∧ a ≤ b ∧ b ≤ c ∧ i ≤ j ∧ j ≤ k −−> a + a + a ≤ k + k + k by arith lemma !!a::real. a + b + c + d ≤ i + j + k + l ==> a ≤ b ==> b ≤ c ==> c ≤ d ==> i ≤ j ==> j ≤ k ==> k ≤ l ==> a ≤ l by linarith lemma !!a::real. a + b + c + d ≤ i + j + k + l ==> a ≤ b ==> b ≤ c ==> c ≤ d ==> i ≤ j ==> j ≤ k ==> k ≤ l ==> a + a + a + a ≤ l + l + l + l by linarith lemma !!a::real. a + b + c + d ≤ i + j + k + l ==> a ≤ b ==> b ≤ c ==> c ≤ d ==> i ≤ j ==> j ≤ k ==> k ≤ l ==> a + a + a + a + a ≤ l + l + l + l + i by linarith lemma !!a::real. a + b + c + d ≤ i + j + k + l ==> a ≤ b ==> b ≤ c ==> c ≤ d ==> i ≤ j ==> j ≤ k ==> k ≤ l ==> a + a + a + a + a + a ≤ l + l + l + l + i + l by linarith

16.6 Complex Arithmetic lemma (1359 + 93746 ∗i) − (2468 + 46375 ∗i) = −1109 + 47371 ∗i by simp lemma − (65745 + −47371 ∗i) = −65745 + 47371 ∗i by simp

Multiplication requires distributive laws. Perhaps versions instantiated to literal constants should be added to the simpset. lemma (1 + i) ∗ (1 − i) = 2 by (simp add: ring-distribs) lemma (1 + 2 ∗i) ∗ (1 + 3 ∗i) = −5 + 5 ∗i by (simp add: ring-distribs) lemma (−84 + 255 ∗i) + (51 ∗ 255 ∗i) = −84 + 13260 ∗ i by (simp add: ring-distribs)

No inequalities or linear arithmetic: the complex numbers are unordered!

No powers (not supported yet) end

98 17 Examples for hexadecimal and binary numerals theory Hex-Bin-Examples imports Main begin

Hex and bin numerals can be used like normal decimal numerals in input lemma 0xFF = 255 by (rule refl) lemma 0xF = 0b1111 by (rule refl)

Just like decimal numeral they are polymorphic, for arithmetic they need to be constrained lemma 0x0A + 0x10 = (0x1A :: nat) by simp

The number of leading zeros is irrelevant lemma 0b00010000 = 0x10 by (rule refl)

Unary minus works as for decimal numerals lemma − 0x0A = − 10 by (rule refl)

Hex and bin numerals are printed as decimal: 2 :: 0a term 0b10 term 0x0A

The numerals 0 and 1 are syntactically different from the constants 0 and 1. For the usual numeric types, their values are the same, though. lemma 0x01 = 1 oops lemma 0x00 = 0 oops lemma 0x01 = (1 ::nat) by simp lemma 0b0000 = (0 ::int) by simp end

18 Antiquotations theory Antiquote imports Main begin

A simple example on quote / antiquote in higher-order abstract syntax. definition var :: 0a ⇒ ( 0a ⇒ nat) ⇒ nat (VAR - [1000 ] 999 ) where var x env = env x definition Expr :: (( 0a ⇒ nat) ⇒ nat) ⇒ ( 0a ⇒ nat) ⇒ nat where Expr exp env = exp env

99 syntax -Expr :: 0a ⇒ 0a (EXPR - [1000 ] 999 ) parse-translation h[Syntax-Trans.quote-antiquote-tr @{syntax-const -Expr} @{const-syntax var} @{const-syntax Expr}]i print-translation 0 h[Syntax-Trans.quote-antiquote-tr @{syntax-const -Expr} @{const-syntax var} @{const-syntax Expr}]i term EXPR (a + b + c) term EXPR (a + b + c + VAR x + VAR y + 1 ) term EXPR (VAR (f w) + VAR x) term Expr (λenv. env x) — improper term Expr (λenv. f env) term Expr (λenv. f env + env x) — improper term Expr (λenv. f env y z) term Expr (λenv. f env + g y env) term Expr (λenv. f env + g env y + h a env z) end

19 Multiple nested quotations and anti-quotations theory Multiquote imports Main begin Multiple nested quotations and anti-quotations – basically a generalized version of de-Bruijn representation. syntax 0 0 0 -quote :: b ⇒ ( a ⇒ b)(- [0 ] 1000 ) -antiquote :: ( 0a ⇒ 0b) ⇒ 0b (´- [1000 ] 1000 ) parse-translation h let fun antiquote-tr i (Const (@{syntax-const -antiquote}, -) $ (t as Const (@{syntax-const -antiquote}, -) $ -)) = skip-antiquote-tr i t | antiquote-tr i (Const (@{syntax-const -antiquote}, -) $ t) = antiquote-tr i t $ Bound i | antiquote-tr i (t $ u) = antiquote-tr i t $ antiquote-tr i u | antiquote-tr i (Abs (x, T , t)) = Abs (x, T , antiquote-tr (i + 1 ) t) | antiquote-tr - a = a and skip-antiquote-tr i ((c as Const (@{syntax-const -antiquote}, -)) $ t) = c $ skip-antiquote-tr i t | skip-antiquote-tr i t = antiquote-tr i t;

100 fun quote-tr [t] = Abs (s, dummyT , antiquote-tr 0 (Term.incr-boundvars 1 t)) | quote-tr ts = raise TERM (quote-tr, ts); in [(@{syntax-const -quote}, K quote-tr)] end i basic examples term a + b + c term a + b + c + ´x + ´y + 1  term ´(f w) + ´x  term f ´x ´y z  advanced examples term ´´x + ´y  term ´´x + ´y  ◦ ´f  term ´(f ◦ ´g) term ´´(f ◦ ´g) end

20 Partial equivalence relations theory PER imports Main begin Higher-order quotients are defined over partial equivalence relations (PERs) instead of total ones. We provide axiomatic type classes equiv < partial-equiv and a type constructor 0a quot with basic operations. This development is based on: Oscar Slotosch: Higher Order Quotients and their Implementation in Isabelle HOL. Elsa L. Gunter and Amy Felty, editors, Theorem Proving in Higher Order Logics: TPHOLs ’97, Springer LNCS 1275, 1997.

20.1 Partial equivalence

Type class partial-equiv models partial equivalence relations (PERs) using the polymorphic ∼ :: 0a ⇒ 0a ⇒ bool relation, which is required to be symmetric and transitive, but not necessarily reflexive. class partial-equiv = fixes eqv :: 0a ⇒ 0a ⇒ bool (infixl ∼ 50 ) assumes partial-equiv-sym [elim?]: x ∼ y =⇒ y ∼ x assumes partial-equiv-trans [trans]: x ∼ y =⇒ y ∼ z =⇒ x ∼ z

The domain of a partial equivalence relation is the set of reflexive elements. Due to symmetry and transitivity this characterizes exactly those elements that are connected with any other one.

101 definition domain :: 0a::partial-equiv set where domain = {x. x ∼ x} lemma domainI [intro]: x ∼ x =⇒ x ∈ domain unfolding domain-def by blast lemma domainD [dest]: x ∈ domain =⇒ x ∼ x unfolding domain-def by blast theorem domainI 0 [elim?]: x ∼ y =⇒ x ∈ domain proof assume xy: x ∼ y also from xy have y ∼ x .. finally show x ∼ x . qed

20.2 Equivalence on function spaces

The ∼ relation is lifted to function spaces. It is important to note that this is not the direct product, but a structural one corresponding to the congruence property. instantiation fun :: (partial-equiv, partial-equiv) partial-equiv begin definition f ∼ g ←→ (∀ x ∈ domain. ∀ y ∈ domain. x ∼ y −→ f x ∼ g y) lemma partial-equiv-funI [intro?]: (Vx y. x ∈ domain =⇒ y ∈ domain =⇒ x ∼ y =⇒ f x ∼ g y) =⇒ f ∼ g unfolding eqv-fun-def by blast lemma partial-equiv-funD [dest?]: f ∼ g =⇒ x ∈ domain =⇒ y ∈ domain =⇒ x ∼ y =⇒ f x ∼ g y unfolding eqv-fun-def by blast

The class of partial equivalence relations is closed under function spaces (in both argument positions). instance proof fix f g h :: 0a::partial-equiv ⇒ 0b::partial-equiv assume fg: f ∼ g show g ∼ f proof fix x y :: 0a assume x: x ∈ domain and y: y ∈ domain assume x ∼ y then have y ∼ x .. with fg y x have f y ∼ g x .. then show g x ∼ f y .. qed

102 assume gh: g ∼ h show f ∼ h proof fix x y :: 0a assume x: x ∈ domain and y: y ∈ domain and x ∼ y with fg have f x ∼ g y .. also from y have y ∼ y .. with gh y y have g y ∼ h y .. finally show f x ∼ h y . qed qed end

20.3 Total equivalence

The class of total equivalence relations on top of PERs. It coincides with the standard notion of equivalence, i.e. ∼ :: 0a ⇒ 0a ⇒ bool is required to be reflexive, transitive and symmetric. class equiv = assumes eqv-refl [intro]: x ∼ x

On total equivalences all elements are reflexive, and congruence holds un- conditionally. theorem equiv-domain [intro]: (x:: 0a::equiv) ∈ domain proof show x ∼ x .. qed theorem equiv-cong [dest?]: f ∼ g =⇒ x ∼ y =⇒ f x ∼ g (y:: 0a::equiv) proof − assume f ∼ g moreover have x ∈ domain .. moreover have y ∈ domain .. moreover assume x ∼ y ultimately show ?thesis .. qed

20.4 Quotient types

The quotient type 0a quot consists of all equivalence classes over elements of the base type 0a. definition quot = {{x. a ∼ x}| a:: 0a::partial-equiv. True} typedef (overloaded) 0a quot = quot :: 0a::partial-equiv set set unfolding quot-def by blast

103 lemma quotI [intro]: {x. a ∼ x} ∈ quot unfolding quot-def by blast lemma quotE [elim]: R ∈ quot =⇒ (Va. R = {x. a ∼ x} =⇒ C ) =⇒ C unfolding quot-def by blast

Abstracted equivalence classes are the canonical representation of elements of a quotient type. definition eqv-class :: ( 0a::partial-equiv) ⇒ 0a quot (b-c) where bac = Abs-quot {x. a ∼ x} theorem quot-rep: ∃ a. A = bac proof (cases A) fix R assume R: A = Abs-quot R assume R ∈ quot then have ∃ a. R = {x. a ∼ x} by blast with R have ∃ a. A = Abs-quot {x. a ∼ x} by blast then show ?thesis by (unfold eqv-class-def ) qed lemma quot-cases [cases type: quot]: obtains (rep) a where A = bac using quot-rep by blast

20.5 Equality on quotients

Equality of canonical quotient elements corresponds to the original relation as follows. theorem eqv-class-eqI [intro]: a ∼ b =⇒ bac = bbc proof − assume ab: a ∼ b have {x. a ∼ x} = {x. b ∼ x} proof (rule Collect-cong) fix x show a ∼ x ←→ b ∼ x proof from ab have b ∼ a .. also assume a ∼ x finally show b ∼ x . next note ab also assume b ∼ x finally show a ∼ x . qed qed then show ?thesis by (simp only: eqv-class-def ) qed theorem eqv-class-eqD 0 [dest?]: bac = bbc =⇒ a ∈ domain =⇒ a ∼ b proof (unfold eqv-class-def )

104 assume Abs-quot {x. a ∼ x} = Abs-quot {x. b ∼ x} then have {x. a ∼ x} = {x. b ∼ x} by (simp only: Abs-quot-inject quotI ) moreover assume a ∈ domain then have a ∼ a .. ultimately have a ∈ {x. b ∼ x} by blast then have b ∼ a by blast then show a ∼ b .. qed theorem eqv-class-eqD [dest?]: bac = bbc =⇒ a ∼ (b:: 0a::equiv) proof (rule eqv-class-eqD 0) show a ∈ domain .. qed lemma eqv-class-eq 0 [simp]: a ∈ domain =⇒ bac = bbc ←→ a ∼ b using eqv-class-eqI eqv-class-eqD 0 by (blast del: eqv-refl) lemma eqv-class-eq [simp]: bac = bbc ←→ a ∼ (b:: 0a::equiv) using eqv-class-eqI eqv-class-eqD by blast

20.6 Picking representing elements definition pick :: 0a::partial-equiv quot ⇒ 0a where pick A = (SOME a. A = bac) theorem pick-eqv 0 [intro?, simp]: a ∈ domain =⇒ pick bac ∼ a proof (unfold pick-def ) assume a: a ∈ domain show (SOME x. bac = bxc) ∼ a proof (rule someI2 ) show bac = bac .. fix x assume bac = bxc from this and a have a ∼ x .. then show x ∼ a .. qed qed theorem pick-eqv [intro, simp]: pick bac ∼ (a:: 0a::equiv) proof (rule pick-eqv 0) show a ∈ domain .. qed theorem pick-inverse: bpick Ac = (A:: 0a::equiv quot) proof (cases A) fix a assume a: A = bac then have pick A ∼ a by simp then have bpick Ac = bac by simp with a show ?thesis by simp qed

105 end

21 Summing natural numbers theory NatSum imports Main begin

Summing natural numbers, squares, cubes, etc. Thanks to Sloane’s On-Line Encyclopedia of Integer Sequences, http:// www.research.att.com/∼njas/sequences. lemmas [simp] = ring-distribs diff-mult-distrib diff-mult-distrib2 — for type nat

The sum of the first n odd numbers equals n squared. lemma sum-of-odds:(P i=0 ..

The sum of the first n odd squares. lemma sum-of-odd-squares: 3 ∗ (P i=0 ..

The sum of the first n odd cubes lemma sum-of-odd-cubes: (P i=0 ..

The sum of the first n positive integers equals n (n + 1 ) / 2. lemma sum-of-naturals: 2 ∗ (P i=0 ..n. i) = n ∗ Suc n by (induct n) auto lemma sum-of-squares: 6 ∗ (P i=0 ..n. i ∗ i) = n ∗ Suc n ∗ Suc (2 ∗ n) by (induct n) auto lemma sum-of-cubes: 4 ∗ (P i=0 ..n. i ∗ i ∗ i) = n ∗ n ∗ Suc n ∗ Suc n by (induct n) auto

A cute identity: lemma sum-squared:(P i=0 ..n. i)ˆ2 = (P i=0 ..n::nat. iˆ3 ) proof(induct n)

106 case 0 show ?case by simp next case (Suc n) have (P i = 0 ..Suc n. i)ˆ2 = (P i = 0 ..n. iˆ3 ) + (2 ∗(P i = 0 ..n. i)∗(n+1 ) + (n+1 )ˆ2 ) (is - = ?A + ?B) using Suc by(simp add:eval-nat-numeral) also have ?B = (n+1 )ˆ3 using sum-of-naturals by(simp add:eval-nat-numeral) also have ?A + (n+1 )ˆ3 = (P i=0 ..Suc n. iˆ3 ) by simp finally show ?case . qed

Sum of fourth powers: three versions. lemma sum-of-fourth-powers: 30 ∗ (P i=0 ..n. i ∗ i ∗ i ∗ i) = n ∗ Suc n ∗ Suc (2 ∗ n) ∗ (3 ∗ n ∗ n + 3 ∗ n − 1 ) apply (induct n) apply simp-all apply (case-tac n) — eliminates the subtraction apply (simp-all (no-asm-simp)) done Two alternative proofs, with a change of variables and much more subtrac- tion, performed using the integers. lemma int-sum-of-fourth-powers: 30 ∗ int (P i=0 ..

Sums of geometric series: 2, 3 and the general case. lemma sum-of-2-powers:(P i=0 .. (k − 1 ) ∗ (P i=0 ..

107 22 Three Divides Theorem theory ThreeDivides imports Main ∼∼/src/HOL/Library/LaTeXsugar begin

22.1 Abstract

The following document presents a proof of the Three Divides N theorem formalised in the Isabelle/Isar theorem proving system. Theorem: 3 divides n if and only if 3 divides the sum of all digits in n. P j Informal Proof: Take n = nj ∗ 10 where nj is the j’th least significant digit of the decimal denotation of the number n and the sum ranges over all digits. Then X X j (n − nj) = nj ∗ (10 − 1) We know ∀j 3|(10j − 1) and hence 3|LHS, therefore X ∀n 3|n ⇐⇒ 3| nj

2 22.2 Formal proof 22.2.1 Miscellaneous summation lemmas

If a divides A x for all x then a divides any sum over terms of the form (A x)∗(P x) for arbitrary P . lemma div-sum: fixes a::nat and n::nat shows ∀ x. a dvd A x =⇒ a dvd (P x

108 22.2.2 Generalised Three Divides

This section solves a generalised form of the three divides problem. Here we show that for any sequence of numbers the theorem holds. In the next section we specialise this theorem to apply directly to the decimal expansion of the natural numbers. Here we show that the first statement in the informal proof is true for all natural numbers. Note we are using D i to denote the i’th element in a sequence of numbers. lemma digit-diff-split: fixes n::nat and nd::nat and x::nat shows n = (P x∈{..

109 qed We now present the final theorem of this section. For any sequence of numbers (defined by a function D), we show that 3 divides the expansive sum P (D x) ∗ 10x over x if and only if 3 divides the sum of the individual numbers P D x. lemma three-div-general: fixes D :: nat ⇒ nat shows (3 dvd (P x

This lets us form the term (P x

22.2.3 Three Divides Natural

This section shows that for all natural numbers we can generate a sequence of digits less than ten that represent the decimal expansion of the number. We then use the lemma three-div-general to prove our final theorem.

Definitions of length and digit sum. This section introduces some functions to calculate the required properties of natural numbers. We then proceed to prove some properties of these functions. The function nlen returns the number of digits in a natural number n. fun nlen :: nat ⇒ nat where nlen 0 = 0 | nlen x = 1 + nlen (x div 10 ) The function sumdig returns the sum of all digits in some number n. definition

110 sumdig :: nat ⇒ nat where sumdig n = (P x < nlen n. n div 10ˆx mod 10 ) Some properties of these functions follow. lemma nlen-zero: 0 = nlen x =⇒ x = 0 by (induct x rule: nlen.induct) auto lemma nlen-suc: Suc m = nlen n =⇒ m = nlen (n div 10 ) by (induct n rule: nlen.induct) simp-all The following lemma is the principle lemma required to prove our theorem. It states that an expansion of some natural number n into a sequence of its individual digits is always possible. lemma exp-exists: m = (P x

111 Final theorem. We now combine the general theorem three-div-general and existence result of exp-exists to prove our final theorem. theorem three-divides-nat: shows (3 dvd n) = (3 dvd sumdig n) proof (unfold sumdig-def ) have n = (P x

23 The Cubic and Quartic Root Formulas theory Cubic-Quartic imports Complex-Main begin

24 The Cubic Formula definition ccbrt z = (SOME (w::complex). wˆ3 = z) lemma ccbrt:(ccbrt z) ˆ 3 = z proof − from rcis-Ex obtain r a where ra: z = rcis r a by blast let ?r 0 = if r < 0 then − root 3 (−r) else root 3 r let ?a 0 = a/3 have rcis ?r 0 ?a 0 ˆ 3 = rcis r a by (cases r < 0 )(simp-all add: DeMoivre2 ) then have ∗: ∃ w. wˆ3 = z unfolding ra by blast from someI-ex [OF ∗] show ?thesis unfolding ccbrt-def by blast qed The reduction to a simpler form: lemma cubic-reduction: fixes a :: complex assumes a 6= 0 ∧ x = y − b / (3 ∗ a) ∧ p = (3 ∗ a ∗ c − bˆ2 ) / (9 ∗ aˆ2 ) ∧

112 q = (9 ∗ a ∗ b ∗ c − 2 ∗ bˆ3 − 27 ∗ aˆ2 ∗ d) / (54 ∗ aˆ3 ) shows a ∗ xˆ3 + b ∗ xˆ2 + c ∗ x + d = 0 ←→ yˆ3 + 3 ∗ p ∗ y − 2 ∗ q = 0 proof − from assms have 3 ∗ a 6= 0 9 ∗ aˆ2 6= 0 54 ∗ aˆ3 6= 0 by auto then have ∗: x = y − b / (3 ∗ a) ←→ (3 ∗a) ∗ x = (3 ∗a) ∗ y − b p = (3 ∗ a ∗ c − bˆ2 ) / (9 ∗ aˆ2 ) ←→ (9 ∗ aˆ2 ) ∗ p = (3 ∗ a ∗ c − bˆ2 ) q = (9 ∗ a ∗ b ∗ c − 2 ∗ bˆ3 − 27 ∗ aˆ2 ∗ d) / (54 ∗ aˆ3 ) ←→ (54 ∗ aˆ3 ) ∗ q = (9 ∗ a ∗ b ∗ c − 2 ∗ bˆ3 − 27 ∗ aˆ2 ∗ d) by (simp-all add: field-simps) from assms [unfolded ∗] show ?thesis by algebra qed

The solutions of the special form: lemma cubic-basic: fixes s :: complex assumes sˆ2 = qˆ2 + pˆ3 ∧ s1ˆ3 = (if p = 0 then 2 ∗ q else q + s) ∧ s2 = −s1 ∗ (1 + i ∗ t) / 2 ∧ s3 = −s1 ∗ (1 − i ∗ t) / 2 ∧ iˆ2 + 1 = 0 ∧ tˆ2 = 3 shows if p = 0 then yˆ3 + 3 ∗ p ∗ y − 2 ∗ q = 0 ←→ y = s1 ∨ y = s2 ∨ y = s3 else s1 6= 0 ∧ (yˆ3 + 3 ∗ p ∗ y − 2 ∗ q = 0 ←→ (y = s1 − p / s1 ∨ y = s2 − p / s2 ∨ y = s3 − p / s3 )) proof (cases p = 0 ) case True with assms show ?thesis by (simp add: field-simps) algebra next case False with assms have ∗: s1 6= 0 by (simp add: field-simps) algebra with assms False have s2 6= 0 s3 6= 0 by (simp-all add: field-simps) algebra+ with ∗ have ∗∗: y = s1 − p / s1 ←→ s1 ∗ y = s1ˆ2 − p y = s2 − p / s2 ←→ s2 ∗ y = s2ˆ2 − p y = s3 − p / s3 ←→ s3 ∗ y = s3ˆ2 − p by (simp-all add: field-simps power2-eq-square) from assms False show ?thesis unfolding ∗∗ by (simp add: field-simps) algebra qed

Explicit formula for the roots:

113 lemma cubic: assumes a0 : a 6= 0 shows let p = (3 ∗ a ∗ c − bˆ2 ) / (9 ∗ aˆ2 ); q = (9 ∗ a ∗ b ∗ c − 2 ∗ bˆ3 − 27 ∗ aˆ2 ∗ d) / (54 ∗ aˆ3 ); s = csqrt(qˆ2 + pˆ3 ); s1 = (if p = 0 then ccbrt(2 ∗ q) else ccbrt(q + s)); s2 = −s1 ∗ (1 + i ∗ csqrt 3 ) / 2 ; s3 = −s1 ∗ (1 − i ∗ csqrt 3 ) / 2 in if p = 0 then a ∗ xˆ3 + b ∗ xˆ2 + c ∗ x + d = 0 ←→ x = s1 − b / (3 ∗ a) ∨ x = s2 − b / (3 ∗ a) ∨ x = s3 − b / (3 ∗ a) else s1 6= 0 ∧ (a ∗ xˆ3 + b ∗ xˆ2 + c ∗ x + d = 0 ←→ x = s1 − p / s1 − b / (3 ∗ a) ∨ x = s2 − p / s2 − b / (3 ∗ a) ∨ x = s3 − p / s3 − b / (3 ∗ a)) proof − let ?p = (3 ∗ a ∗ c − bˆ2 ) / (9 ∗ aˆ2 ) let ?q = (9 ∗ a ∗ b ∗ c − 2 ∗ bˆ3 − 27 ∗ aˆ2 ∗ d) / (54 ∗ aˆ3 ) let ?s = csqrt (?qˆ2 + ?pˆ3 ) let ?s1 = if ?p = 0 then ccbrt(2 ∗ ?q) else ccbrt(?q + ?s) let ?s2 = − ?s1 ∗ (1 + i ∗ csqrt 3 ) / 2 let ?s3 = − ?s1 ∗ (1 − i ∗ csqrt 3 ) / 2 let ?y = x + b / (3 ∗ a) from a0 have zero: 9 ∗ aˆ2 6= 0 aˆ3 ∗ 54 6= 0 (a ∗ 3 ) 6= 0 by auto have eq: a ∗ xˆ3 + b ∗ xˆ2 + c ∗ x + d = 0 ←→ ?yˆ3 + 3 ∗ ?p ∗ ?y − 2 ∗ ?q = 0 by (rule cubic-reduction)(auto simp add: field-simps zero a0 ) have csqrt 3ˆ2 = 3 by (rule power2-csqrt) then have th0 : ?sˆ2 = ?qˆ2 + ?p ˆ 3 ∧ ?s1ˆ 3 = (if ?p = 0 then 2 ∗ ?q else ?q + ?s) ∧ ?s2 = − ?s1 ∗ (1 + i ∗ csqrt 3 ) / 2 ∧ ?s3 = − ?s1 ∗ (1 − i ∗ csqrt 3 ) / 2 ∧ iˆ2 + 1 = 0 ∧ csqrt 3ˆ2 = 3 using zero by (simp add: field-simps ccbrt) from cubic-basic[OF th0 , of ?y] show ?thesis apply (simp only: Let-def eq) using zero apply (simp add: field-simps ccbrt) using zero apply (cases a ∗ (c ∗ 3 ) = bˆ2 ) apply (simp-all add: field-simps)

114 done qed

25 The Quartic Formula lemma quartic: (y::real)ˆ3 − b ∗ yˆ2 + (a ∗ c − 4 ∗ d) ∗ y − aˆ2 ∗ d + 4 ∗ b ∗ d − cˆ2 = 0 ∧ Rˆ2 = aˆ2 / 4 − b + y ∧ sˆ2 = yˆ2 − 4 ∗ d ∧ (Dˆ2 = (if R = 0 then 3 ∗ aˆ2 / 4 − 2 ∗ b + 2 ∗ s else 3 ∗ aˆ2 / 4 − Rˆ2 − 2 ∗ b + (4 ∗ a ∗ b − 8 ∗ c − aˆ3 ) / (4 ∗ R))) ∧ (Eˆ2 = (if R = 0 then 3 ∗ aˆ2 / 4 − 2 ∗ b − 2 ∗ s else 3 ∗ aˆ2 / 4 − Rˆ2 − 2 ∗ b − (4 ∗ a ∗ b − 8 ∗ c − aˆ3 ) / (4 ∗ R))) =⇒ xˆ4 + a ∗ xˆ3 + b ∗ xˆ2 + c ∗ x + d = 0 ←→ x = −a / 4 + R / 2 + D / 2 ∨ x = −a / 4 + R / 2 − D / 2 ∨ x = −a / 4 − R / 2 + E / 2 ∨ x = −a / 4 − R / 2 − E / 2 apply (cases R = 0 ) apply (simp-all add: field-simps divide-minus-left[symmetric] del: divide-minus-left) apply algebra apply algebra done end

26 The Pythagorean Theorem theory Pythagoras imports Complex-Main begin

Expressed in real numbers: lemma pythagoras-verbose: ((A1 ::real) − B1 ) ∗ (C1 − B1 ) + (A2 − B2 ) ∗ (C2 − B2 ) = 0 =⇒ (C1 − A1 ) ∗ (C1 − A1 ) + (C2 − A2 ) ∗ (C2 − A2 ) = ((B1 − A1 ) ∗ (B1 − A1 ) + (B2 − A2 ) ∗ (B2 − A2 )) + (C1 − B1 ) ∗ (C1 − B1 ) + (C2 − B2 ) ∗ (C2 − B2 ) by algebra

Expressed in vectors: type-synonym point = real × real lemma pythagoras: defines ort:orthogonal ≡ (λ(A::point) B. fst A ∗ fst B + snd A ∗ snd B = 0 )

115 and vc:vector ≡ (λ(A::point) B. (fst A − fst B, snd A − snd B)) and vcn:vecsqnorm ≡ (λA::point. fst A ˆ 2 + snd A ˆ2 ) assumes o: orthogonal (vector A B)(vector C B) shows vecsqnorm(vector C A) = vecsqnorm(vector B A) + vecsqnorm(vector C B) using o unfolding ort vc vcn by (algebra add: fst-conv snd-conv)

end

27 Higher-Order Logic: Intuitionistic predicate cal- culus problems theory Intuitionistic imports Main begin

lemma (∼∼(P&Q)) = ((∼∼P)&(∼∼Q)) by iprover lemma ∼∼ ((∼P −−> Q) −−> (∼P −−> ∼Q) −−> P) by iprover

lemma (∼∼(P−−>Q)) = (∼∼P −−> ∼∼Q) by iprover lemma (∼∼∼P) = (∼P) by iprover lemma ∼∼((P −−> Q | R) −−> (P−−>Q) | (P−−>R)) by iprover lemma (P=Q) = (Q=P) by iprover lemma ((P −−> (Q | (Q−−>R))) −−> R) −−> R by iprover lemma (((G−−>A) −−> J ) −−> D −−> E) −−> (((H −−>B)−−>I )−−>C −−>J ) −−> (A−−>H ) −−> F −−> G −−> (((C −−>B)−−>I )−−>D)−−>(A−−>C ) −−> (((F −−>A)−−>B) −−> I ) −−> E by iprover

116 lemma P −−> ∼∼P by iprover lemma ∼∼(∼∼P −−> P) by iprover lemma ∼∼P & ∼∼(P −−> Q) −−> ∼∼Q by iprover

lemma ((P=Q) −−> P&Q&R)& ((Q=R) −−> P&Q&R)& ((R=P) −−> P&Q&R) −−> P&Q&R by iprover lemma ((P=Q) −−> P&Q&R&S&T )& ((Q=R) −−> P&Q&R&S&T )& ((R=S) −−> P&Q&R&S&T )& ((S=T ) −−> P&Q&R&S&T )& ((T =P) −−> P&Q&R&S&T ) −−> P&Q&R&S&T by iprover

lemma (ALL x. EX y. ALL z. p(x)& q(y)& r(z)) = (ALL z. EX y. ALL x. p(x)& q(y)& r(z)) by (iprover del: allE elim 2 : allE 0) lemma ∼ (EX x. ALL y. p y x = (∼ p x x)) by iprover

lemma ∼∼((P−−>Q) = (∼Q −−> ∼P)) by iprover lemma ∼∼(∼∼P = P) by iprover

117 lemma ∼(P−−>Q) −−> (Q−−>P) by iprover lemma ∼∼((∼P−−>Q) = (∼Q −−> P)) by iprover lemma ∼∼((P|Q−−>P|R) −−> P|(Q−−>R)) by iprover lemma ∼∼(P | ∼P) by iprover lemma ∼∼(P | ∼∼∼P) by iprover lemma ∼∼(((P−−>Q) −−> P) −−> P) by iprover lemma ((P|Q)&(∼P|Q)&(P| ∼Q)) −−> ∼ (∼P | ∼Q) by iprover lemma (Q−−>R) −−> (R−−>P&Q) −−> (P−−>(Q|R)) −−> (P=Q) by iprover lemma P=P by iprover lemma ∼∼(((P = Q) = R) = (P = (Q = R))) by iprover lemma ((P = Q) = R) −−> ∼∼(P = (Q = R)) by iprover lemma (P | (Q & R)) = ((P | Q)&(P | R)) by iprover lemma ∼∼((P = Q) = ((Q | ∼P)&(∼Q|P)))

118 by iprover lemma ∼∼((P −−> Q) = (∼P | Q)) by iprover lemma ∼∼((P−−>Q) | (Q−−>P)) by iprover lemma ∼∼(((P &(Q−−>R))−−>S) = ((∼P | Q | S)&(∼P | ∼R | S))) oops lemma (P&Q) = (P = (Q = (P|Q))) by iprover

lemma (EX x. P(x)−−>Q) −−> (ALL x. P(x)) −−> Q by iprover lemma ((ALL x. P(x))−−>Q) −−> ∼ (ALL x. P(x)& ∼Q) by iprover lemma ((ALL x. ∼P(x))−−>Q) −−> ∼ (ALL x. ∼ (P(x)|Q)) by iprover lemma (ALL x. P(x)) | Q −−> (ALL x. P(x) | Q) by iprover lemma (EX x. P −−> Q(x)) −−> (P −−> (EX x. Q(x))) by iprover

lemma ∼∼(EX x. ALL y z. (P(y)−−>Q(z)) −−> (P(x)−−>Q(x))) by iprover lemma (ALL x y. EX z. ALL w. (P(x)&Q(y)−−>R(z)&S(w)))

119 −−> (EX x y. P(x)& Q(y)) −−> (EX z. R(z)) by iprover lemma (EX x. P−−>Q(x)) & (EX x. Q(x)−−>P) −−> ∼∼(EX x. P=Q(x)) by iprover lemma (ALL x. P = Q(x)) −−> (P = (ALL x. Q(x))) by iprover lemma ∼∼ ((ALL x. P | Q(x)) = (P | (ALL x. Q(x)))) by iprover lemma (EX x. P(x)) & (ALL x. L(x) −−> ∼ (M (x)& R(x))) & (ALL x. P(x) −−> (M (x)& L(x))) & ((ALL x. P(x)−−>Q(x)) | (EX x. P(x)&R(x))) −−> (EX x. Q(x)&P(x)) by iprover lemma (EX x. P(x)& ∼Q(x)) & (ALL x. P(x) −−> R(x)) & (ALL x. M (x)& L(x) −−> P(x)) & ((EX x. R(x)& ∼ Q(x)) −−> (ALL x. L(x) −−> ∼ R(x))) −−> (ALL x. M (x) −−> ∼L(x)) by iprover lemma (ALL x. P(x) −−> (ALL x. Q(x))) & (∼∼(ALL x. Q(x)|R(x)) −−> (EX x. Q(x)&S(x))) & (∼∼(EX x. S(x)) −−> (ALL x. L(x) −−> M (x))) −−> (ALL x. P(x)& L(x) −−> M (x)) by iprover lemma (((EX x. P(x)) & (EX y. Q(y))) −−> (((ALL x. (P(x) −−> R(x))) & (ALL y. (Q(y) −−> S(y)))) = (ALL x y. ((P(x)& Q(y)) −−> (R(x)& S(y)))))) by iprover lemma (ALL x. (P(x) | Q(x)) −−> ∼ R(x)) & (ALL x. (Q(x) −−> ∼ S(x)) −−> P(x)& R(x)) −−> (ALL x. ∼∼S(x)) by iprover

120 lemma ∼(EX x. P(x)&(Q(x) | R(x))) & (EX x. L(x)& P(x)) & (ALL x. ∼ R(x) −−> M (x)) −−> (EX x. L(x)& M (x)) by iprover lemma (ALL x. P(x)&(Q(x)|R(x))−−>S(x)) & (ALL x. S(x)& R(x) −−> L(x)) & (ALL x. M (x) −−> R(x)) −−> (ALL x. P(x)& M (x) −−> L(x)) by iprover lemma (ALL x. ∼∼(P(a)&(P(x)−−>P(b))−−>P(c))) = (ALL x. ∼∼((∼P(a) | P(x) | P(c)) & (∼P(a) | ∼P(b) | P(c)))) oops lemma (ALL x. EX y. J x y)& (ALL x. EX y. G x y)& (ALL x y. J x y | G x y −−> (ALL z. J y z | G y z −−> H x z)) −−> (ALL x. EX y. H x y) by iprover lemma ∼ (EX x. ALL y. F y x = (∼F y y)) by iprover lemma (EX y. ALL x. F x y = F x x) −−> ∼(ALL x. EX y. ALL z. F z y = (∼ F z x)) by iprover lemma (ALL x. f (x) −−> (EX y. g(y)& h x y &(EX y. g(y)& ∼ h x y))) & (EX x. j (x)&(ALL y. g(y) −−> h x y)) −−> (EX x. j (x)& ∼f (x)) by iprover lemma (a=b | c=d)&(a=c | b=d) −−> a=d | b=c by iprover

121 lemma ((EX z w. (ALL x y. (P x y = ((x = z)&(y = w))))) −−> (EX z. (ALL x. (EX w. ((ALL y. (P x y = (y = w))) = (x = z)))))) by iprover

lemma ((EX z w. (ALL x y. (P x y = ((x = z)&(y = w))))) −−> (EX w. (ALL y. (EX z. ((ALL x. (P x y = (x = z))) = (y = w)))))) by iprover lemma (ALL x. (EX y. P(y)& x=f (y)) −−> P(x)) = (ALL x. P(x) −−> P(f (x))) by iprover lemma P (f a b)(f b c)& P (f b c)(f a c)& (ALL x y z. P x y & P y z −−> P x z) −−> P (f a b)(f a c) by iprover lemma ALL x. P x (f x) = (EX y. (ALL z. P z y −−> P z (f x)) & P x y) by iprover end

28 CTL formulae theory CTL imports Main begin We formalize basic concepts of Computational Tree Logic (CTL) [2,1] within the simply-typed set theory of HOL. By using the common technique of “shallow embedding”, a CTL formula is identified with the corresponding set of states where it holds. Consequently, CTL operations such as negation, conjunction, disjunction simply become complement, intersection, union of sets. We only require a separate oper- ation for implication, as point-wise inclusion is usually not encountered in plain set-theory. lemmas [intro!] = Int-greatest Un-upper2 Un-upper1 Int-lower1 Int-lower2 type-synonym 0a ctl = 0a set definition imp :: 0a ctl ⇒ 0a ctl ⇒ 0a ctl (infixr → 75 ) where p → q = − p ∪ q lemma [intro!]: p ∩ p → q ⊆ q unfolding imp-def by auto

122 lemma [intro!]: p ⊆ (q → p) unfolding imp-def by rule

The CTL path operators are more interesting; they are based on an arbitrary, but fixed model M, which is simply a transition relation over states 0a. axiomatization M :: ( 0a × 0a) set The operators EX, EF, EG are taken as primitives, while AX, AF, AG are defined as derived ones. The formula EX p holds in a state s, iff there is a successor state s 0 (with respect to the model M), such that p holds in s 0. The formula EF p holds in a state s, iff there is a path in M, starting from s, such that there exists a state s 0 on the path, such that p holds in s 0. The formula EG p holds in a state s, iff there is a path, starting from s, such that for all states s 0 on the path, p holds in s 0. It is easy to see that EF p and EG p may be expressed using least and greatest fixed points [2]. definition EX (EX - [80 ] 90 ) where [simp]: EX p = {s. ∃ s 0. (s, s 0) ∈ M ∧ s 0 ∈ p} definition EF (EF - [80 ] 90 ) where [simp]: EF p = lfp (λs. p ∪ EX s) definition EG (EG - [80 ] 90 ) where [simp]: EG p = gfp (λs. p ∩ EX s) AX, AF and AG are now defined dually in terms of EX, EF and EG. definition AX (AX - [80 ] 90 ) where [simp]: AX p = − EX − p definition AF (AF - [80 ] 90 ) where [simp]: AF p = − EG − p definition AG (AG - [80 ] 90 ) where [simp]: AG p = − EF − p

28.1 Basic fixed point properties

First of all, we use the de-Morgan property of fixed points. lemma lfp-gfp: lfp f = − gfp (λs:: 0a set. − (f (− s))) proof show lfp f ⊆ − gfp (λs. − f (− s)) proof show x ∈ − gfp (λs. − f (− s)) if l: x ∈ lfp f for x proof assume x ∈ gfp (λs. − f (− s)) then obtain u where x ∈ u and u ⊆ − f (− u) by (auto simp add: gfp-def ) then have f (− u) ⊆ − u by auto then have lfp f ⊆ − u by (rule lfp-lowerbound) from l and this have x ∈/ u by auto with hx ∈ u i show False by contradiction

123 qed qed show − gfp (λs. − f (− s)) ⊆ lfp f proof (rule lfp-greatest) fix u assume f u ⊆ u then have − u ⊆ − f u by auto then have − u ⊆ − f (− (− u)) by simp then have − u ⊆ gfp (λs. − f (− s)) by (rule gfp-upperbound) then show − gfp (λs. − f (− s)) ⊆ u by auto qed qed lemma lfp-gfp 0: − lfp f = gfp (λs:: 0a set. − (f (− s))) by (simp add: lfp-gfp) lemma gfp-lfp 0: − gfp f = lfp (λs:: 0a set. − (f (− s))) by (simp add: lfp-gfp) In order to give dual fixed point representations of AF p and AG p: lemma AF-lfp: AF p = lfp (λs. p ∪ AX s) by (simp add: lfp-gfp) lemma AG-gfp: AG p = gfp (λs. p ∩ AX s) by (simp add: lfp-gfp) lemma EF-fp: EF p = p ∪ EX EF p proof − have mono (λs. p ∪ EX s) by rule auto then show ?thesis by (simp only: EF-def )(rule lfp-unfold) qed lemma AF-fp: AF p = p ∪ AX AF p proof − have mono (λs. p ∪ AX s) by rule auto then show ?thesis by (simp only: AF-lfp)(rule lfp-unfold) qed lemma EG-fp: EG p = p ∩ EX EG p proof − have mono (λs. p ∩ EX s) by rule auto then show ?thesis by (simp only: EG-def )(rule gfp-unfold) qed From the greatest fixed point definition of AG p, we derive as a consequence of the Knaster-Tarski theorem on the one hand that AG p is a fixed point of the monotonic function λs. p ∩ AX s. lemma AG-fp: AG p = p ∩ AX AG p proof −

124 have mono (λs. p ∩ AX s) by rule auto then show ?thesis by (simp only: AG-gfp)(rule gfp-unfold) qed

This fact may be split up into two inequalities (merely using transitivity of ⊆, which is an instance of the overloaded ≤ in Isabelle/HOL). lemma AG-fp-1 : AG p ⊆ p proof − note AG-fp also have p ∩ AX AG p ⊆ p by auto finally show ?thesis . qed lemma AG-fp-2 : AG p ⊆ AX AG p proof − note AG-fp also have p ∩ AX AG p ⊆ AX AG p by auto finally show ?thesis . qed

On the other hand, we have from the Knaster-Tarski fixed point theorem that any other post-fixed point of λs. p ∩ AX s is smaller than AG p.A post-fixed point is a set of states q such that q ⊆ p ∩ AX q. This leads to the following co-induction principle for AG p. lemma AG-I : q ⊆ p ∩ AX q =⇒ q ⊆ AG p by (simp only: AG-gfp)(rule gfp-upperbound)

28.2 The tree induction principle

With the most basic facts available, we are now able to establish a few more interesting results, leading to the tree induction principle for AG (see below). We will use some elementary monotonicity and distributivity rules. lemma AX-int: AX (p ∩ q) = AX p ∩ AX q by auto lemma AX-mono: p ⊆ q =⇒ AX p ⊆ AX q by auto lemma AG-mono: p ⊆ q =⇒ AG p ⊆ AG q by (simp only: AG-gfp, rule gfp-mono) auto

The formula AG p implies AX p (we use substitution of ⊆ with mono- tonicity). lemma AG-AX : AG p ⊆ AX p proof − have AG p ⊆ AX AG p by (rule AG-fp-2 ) also have AG p ⊆ p by (rule AG-fp-1 ) moreover note AX-mono finally show ?thesis . qed

Furthermore we show idempotency of the AG operator. The proof is a good example of how accumulated facts may get used to feed a single rule step.

125 lemma AG-AG: AG AG p = AG p proof show AG AG p ⊆ AG p by (rule AG-fp-1 ) next show AG p ⊆ AG AG p proof (rule AG-I ) have AG p ⊆ AG p .. moreover have AG p ⊆ AX AG p by (rule AG-fp-2 ) ultimately show AG p ⊆ AG p ∩ AX AG p .. qed qed

We now give an alternative characterization of the AG operator, which describes the AG operator in an “operational” way by tree induction: In a state holds AG p iff in that state holds p, and in all reachable states s follows from the fact that p holds in s, that p also holds in all successor states of s. We use the co-induction principle AG-I to establish this in a purely algebraic manner. theorem AG-induct: p ∩ AG (p → AX p) = AG p proof show p ∩ AG (p → AX p) ⊆ AG p (is ?lhs ⊆ -) proof (rule AG-I ) show ?lhs ⊆ p ∩ AX ?lhs proof show ?lhs ⊆ p .. show ?lhs ⊆ AX ?lhs proof − { have AG (p → AX p) ⊆ p → AX p by (rule AG-fp-1 ) also have p ∩ p → AX p ⊆ AX p .. finally have ?lhs ⊆ AX p by auto } moreover { have p ∩ AG (p → AX p) ⊆ AG (p → AX p) .. also have ... ⊆ AX ... by (rule AG-fp-2 ) finally have ?lhs ⊆ AX AG (p → AX p) . } ultimately have ?lhs ⊆ AX p ∩ AX AG (p → AX p) .. also have ... = AX ?lhs by (simp only: AX-int) finally show ?thesis . qed qed qed next show AG p ⊆ p ∩ AG (p → AX p) proof show AG p ⊆ p by (rule AG-fp-1 )

126 show AG p ⊆ AG (p → AX p) proof − have AG p = AG AG p by (simp only: AG-AG) also have AG p ⊆ AX p by (rule AG-AX ) moreover note AG-mono also have AX p ⊆ (p → AX p) .. moreover note AG-mono finally show ?thesis . qed qed qed

28.3 An application of tree induction

Further interesting properties of CTL expressions may be demonstrated with the help of tree induction; here we show that AX and AG commute. theorem AG-AX-commute: AG AX p = AX AG p proof − have AG AX p = AX p ∩ AX AG AX p by (rule AG-fp) also have ... = AX (p ∩ AG AX p) by (simp only: AX-int) also have p ∩ AG AX p = AG p (is ?lhs = -) proof have AX p ⊆ p → AX p .. also have p ∩ AG (p → AX p) = AG p by (rule AG-induct) also note Int-mono AG-mono ultimately show ?lhs ⊆ AG p by fast next have AG p ⊆ p by (rule AG-fp-1 ) moreover { have AG p = AG AG p by (simp only: AG-AG) also have AG p ⊆ AX p by (rule AG-AX ) also note AG-mono ultimately have AG p ⊆ AG AX p . } ultimately show AG p ⊆ ?lhs .. qed finally show ?thesis . qed end

29 Arithmetic theory Arith-Examples imports Main begin

The arith method is used frequently throughout the Isabelle distribution. This file merely contains some additional tests and special corner cases.

127 Some rather technical remarks: Lin_Arith.simple_tac is a very basic version of the tactic. It performs no meta-to-object-logic conversion, and only some splitting of operators. Lin_Arith.tac performs meta-to-object-logic conversion, full splitting of operators, and NNF normalization of the goal. The arith method combines them both, and tries other methods (e.g. presburger) as well. This is the one that you should use in your proofs! An arith-based simproc is available as well (see Lin_Arith.simproc), which— for performance reasons—however does even less splitting than Lin_Arith.simple_tac at the moment (namely inequalities only). (On the other hand, it does take apart conjunctions, which Lin_Arith.simple_tac currently does not do.)

29.1 Splitting of Operators: max, min, abs, op −, nat, op mod, op div lemma (i::nat) <= max i j by linarith lemma (i::int) <= max i j by linarith lemma min i j <= (i::nat) by linarith lemma min i j <= (i::int) by linarith lemma min (i::nat) j <= max i j by linarith lemma min (i::int) j <= max i j by linarith lemma min (i::nat) j + max i j = i + j by linarith lemma min (i::int) j + max i j = i + j by linarith lemma (i::nat) < j ==> min i j < max i j by linarith lemma (i::int) < j ==> min i j < max i j by linarith lemma (0 ::int) <= |i| by linarith

128 lemma (i::int) <= |i| by linarith lemma ||i::int|| = |i| by linarith

Also testing subgoals with bound variables. lemma !!x. (x::nat) <= y ==> x − y = 0 by linarith lemma !!x. (x::nat) − y = 0 ==> x <= y by linarith lemma !!x. ((x::nat) <= y) = (x − y = 0 ) by linarith lemma [| (x::nat) < y; d < 1 |] ==> x − y = d by linarith lemma [| (x::nat) < y; d < 1 |] ==> x − y − x = d − x by linarith lemma (x::int) < y ==> x − y < 0 by linarith lemma nat (i + j ) <= nat i + nat j by linarith lemma i < j ==> nat (i − j ) = 0 by linarith lemma (i::nat) mod 0 = i

using split-mod [of - - 0 , arith-split] by linarith lemma (i::nat) mod 1 = 0

using split-mod [of - - 1 , arith-split] by linarith lemma (i::nat) mod 42 <= 41 by linarith lemma (i::int) mod 0 = i

using split-zmod [of - - 0 , arith-split] by linarith

129 lemma (i::int) mod 1 = 0

using split-zmod [of - - 1 , arith-split] by linarith lemma (i::int) mod 42 <= 41 by linarith lemma −(i::int) ∗ 1 = 0 ==> i = 0 by linarith lemma [| (0 ::int) < |i|; |i| ∗ 1 < |i| ∗ j |] ==> 1 < |i| ∗ j by linarith

29.2 Meta-Logic lemma x < Suc y == x <= y by linarith lemma ((x::nat) == z ==> x ∼= y) ==> x ∼= y | z ∼= y by linarith

29.3 Various Other Examples lemma (x < Suc y) = (x <= y) by linarith lemma [| (x::nat) < y; y < z |] ==> x < z by linarith lemma (x::nat) < y & y < z ==> x < z by linarith

This example involves no arithmetic at all, but is solved by preprocessing (i.e. NNF normalization) alone. lemma (P::bool) = Q ==> Q = P by linarith lemma [| P = (x = 0 ); (∼P) = (y = 0 ) |] ==> min (x::nat) y = 0 by linarith lemma [| P = (x = 0 ); (∼P) = (y = 0 ) |] ==> max (x::nat) y = x + y by linarith lemma [| (x::nat) ∼= y; a + 2 = b; a < y; y < b; a < x; x < b |] ==> False by linarith lemma [| (x::nat) > y; y > z; z > x |] ==> False

130 by linarith lemma (x::nat) − 5 > y ==> y < x by linarith lemma (x::nat) ∼= 0 ==> 0 < x by linarith lemma [| (x::nat) ∼= y; x <= y |] ==> x < y by linarith lemma [| (x::nat) < y; P (x − y) |] ==> P 0 by linarith lemma (x − y) − (x::nat) = (x − x) − y by linarith lemma [| (a::nat) < b; c < d |] ==> (a − b) = (c − d) by linarith lemma ((a::nat) − (b − (c − (d − e)))) = (a − (b − (c − (d − e)))) by linarith lemma (n < m & m < n 0) | (n < m & m = n 0) | (n < n 0 & n 0 < m) | (n = n 0 & n 0 < m) | (n = m & m < n 0) | (n 0 < m & m < n) | (n 0 < m & m = n) | (n 0 < n & n < m) | (n 0 = n & n < m) | (n 0 = m & m < n) | (m < n & n < n 0) | (m < n & n 0 = n) | (m < n 0 & n 0 < n) | (m = n & n < n 0) | (m = n 0 & n 0 < n) | (n 0 = m & m = (n::nat))

oops lemma 2 ∗ (x::nat) ∼= 1

oops

Constants. lemma (0 ::nat) < 1 by linarith lemma (0 ::int) < 1 by linarith

131 lemma (47 ::nat) + 11 < 8 ∗ 15 by linarith lemma (47 ::int) + 11 < 8 ∗ 15 by linarith Splitting of inequalities of different type. lemma [| (a::nat) ∼= b;(i::int) ∼= j ; a < 2 ; b < 2 |] ==> a + b <= nat (max |i| |j |) by linarith Again, but different order. lemma [| (i::int) ∼= j ;(a::nat) ∼= b; a < 2 ; b < 2 |] ==> a + b <= nat (max |i| |j |) by linarith end

30 2-3 Trees theory Tree23 imports Main begin This is a very direct translation of some of the functions in table.ML in the Isabelle source code. That source is due to Makarius Wenzel and Stefan Berghofer. So far this file contains only data types and functions, but no proofs. Feel free to have a go at the latter! Note that because of complicated patterns and mutual recursion, these func- tion definitions take a few minutes and can also be seen as stress tests for the function definition facility. type-synonym key = int — for simplicity, should be a type class datatype ord = LESS | EQUAL | GREATER definition ord i j = (if i

132 fun add :: key ⇒ 0a ⇒ 0a tree23 ⇒ 0a growth where add key y Empty = Sprout Empty (key,y) Empty | add key y (Branch2 left (k,x) right) = (case ord key k of LESS => (case add key y left of Stay left 0 => Stay (Branch2 left 0 (k,x) right) | Sprout left1 q left2 => Stay (Branch3 left1 q left2 (k,x) right)) | EQUAL => Stay (Branch2 left (k,y) right) | GREATER => (case add key y right of Stay right 0 => Stay (Branch2 left (k,x) right 0) | Sprout right1 q right2 => Stay (Branch3 left (k,x) right1 q right2 ))) | add key y (Branch3 left (k1 ,x1 ) mid (k2 ,x2 ) right) = (case ord key k1 of LESS => (case add key y left of Stay left 0 => Stay (Branch3 left 0 (k1 ,x1 ) mid (k2 ,x2 ) right) | Sprout left1 q left2 => Sprout (Branch2 left1 q left2 )(k1 ,x1 )(Branch2 mid (k2 ,x2 ) right)) | EQUAL => Stay (Branch3 left (k1 ,y) mid (k2 ,x2 ) right) | GREATER => (case ord key k2 of LESS => (case add key y mid of Stay mid 0 => Stay (Branch3 left (k1 ,x1 ) mid 0 (k2 ,x2 ) right) | Sprout mid1 q mid2 => Sprout (Branch2 left (k1 ,x1 ) mid1 ) q (Branch2 mid2 (k2 ,x2 ) right)) | EQUAL => Stay (Branch3 left (k1 ,x1 ) mid (k2 ,y) right) | GREATER => (case add key y right of Stay right 0 => Stay (Branch3 left (k1 ,x1 ) mid (k2 ,x2 ) right 0) | Sprout right1 q right2 => Sprout (Branch2 left (k1 ,x1 ) mid)(k2 ,x2 )(Branch2 right1 q right2 )))) definition add0 :: key ⇒ 0a ⇒ 0a tree23 ⇒ 0a tree23 where add0 k y t = (case add k y t of Stay t 0 => t 0 | Sprout l p r => Branch2 l p r) value add0 5 e (add0 4 d (add0 3 c (add0 2 b (add0 1 a Empty)))) fun compare where compare None (k2 , -) = LESS | compare (Some k1 )(k2 , -) = ord k1 k2

133 fun if-eq where if-eq EQUAL x y = x | if-eq - x y = y fun del :: key option ⇒ 0a tree23 ⇒ ((key ∗ 0a) ∗ bool ∗ 0a tree23 )option where del (Some k) Empty = None | del None (Branch2 Empty p Empty) = Some(p, (True, Empty)) | del None (Branch3 Empty p Empty q Empty) = Some(p, (False, Branch2 Empty q Empty)) | del k (Branch2 Empty p Empty) = (case compare k p of EQUAL => Some(p, (True, Empty)) | - => None) | del k (Branch3 Empty p Empty q Empty) = (case compare k p of EQUAL => Some(p, (False, Branch2 Empty q Empty)) | - => (case compare k q of EQUAL => Some(q, (False, Branch2 Empty p Empty)) | - => None)) | del k (Branch2 l p r) = (case compare k p of LESS => (case del k l of None ⇒ None | Some(p 0, (False, l 0)) => Some(p 0, (False, Branch2 l 0 p r)) | Some(p 0, (True, l 0)) => Some(p 0, case r of Branch2 rl rp rr => (True, Branch3 l 0 p rl rp rr) | Branch3 rl rp rm rq rr => (False, Branch2 (Branch2 l 0 p rl) rp (Branch2 rm rq rr)))) | or => (case del (if-eq or None k) r of None ⇒ None | Some(p 0, (False, r 0)) => Some(p 0, (False, Branch2 l (if-eq or p 0 p) r 0)) | Some(p 0, (True, r 0)) => Some(p 0, case l of Branch2 ll lp lr => (True, Branch3 ll lp lr (if-eq or p 0 p) r 0) | Branch3 ll lp lm lq lr => (False, Branch2 (Branch2 ll lp lm) lq (Branch2 lr (if-eq or p 0 p) r 0))))) | del k (Branch3 l p m q r) = (case compare k q of LESS => (case compare k p of LESS => (case del k l of None ⇒ None | Some(p 0, (False, l 0)) => Some(p 0, (False, Branch3 l 0 p m q r)) | Some(p 0, (True, l 0)) => Some(p 0, (False, case (m, r) of (Branch2 ml mp mr, Branch2 - - -) => Branch2 (Branch3 l 0 p ml mp mr) q r | (Branch3 ml mp mm mq mr, -) => Branch3 (Branch2 l 0 p ml) mp (Branch2 mm mq mr) q r | (Branch2 ml mp mr, Branch3 rl rp rm rq rr) => Branch3 (Branch2 l 0 p ml) mp (Branch2 mr q rl) rp (Branch2 rm rq rr)))) | or => (case del (if-eq or None k) m of None ⇒ None | Some(p 0, (False, m 0)) => Some(p 0, (False, Branch3 l (if-eq or p 0 p) m 0 q r)) | Some(p 0, (True, m 0)) => Some(p 0, (False, case (l, r) of (Branch2 ll lp lr, Branch2 - - -) => Branch2 (Branch3 ll lp lr (if-eq or p 0 p) m 0) q r

134 | (Branch3 ll lp lm lq lr, -) => Branch3 (Branch2 ll lp lm) lq (Branch2 lr (if-eq or p 0 p) m 0) q r | (-, Branch3 rl rp rm rq rr) => Branch3 l (if-eq or p 0 p)(Branch2 m 0 q rl) rp (Branch2 rm rq rr))))) | or => (case del (if-eq or None k) r of None ⇒ None | Some(q 0, (False, r 0)) => Some(q 0, (False, Branch3 l p m (if-eq or q 0 q) r 0)) | Some(q 0, (True, r 0)) => Some(q 0, (False, case (l, m) of (Branch2 - - -, Branch2 ml mp mr) => Branch2 l p (Branch3 ml mp mr (if-eq or q 0 q) r 0) | (-, Branch3 ml mp mm mq mr) => Branch3 l p (Branch2 ml mp mm) mq (Branch2 mr (if-eq or q 0 q) r 0) | (Branch3 ll lp lm lq lr, Branch2 ml mp mr) => Branch3 (Branch2 ll lp lm) lq (Branch2 lr p ml) mp (Branch2 mr (if-eq or q 0 q) r 0))))) definition del0 :: key ⇒ 0a tree23 ⇒ 0a tree23 where del0 k t = (case del (Some k) t of None ⇒ t | Some(-,(-,t 0)) ⇒ t 0)

Ordered trees definition opt-less :: key option ⇒ key option ⇒ bool where opt-less x y = (case x of None ⇒ True | Some a ⇒ (case y of None ⇒ True | Some b ⇒ a < b)) lemma opt-less-simps [simp]: opt-less None y = True opt-less x None = True opt-less (Some a)(Some b) = (a < b) unfolding opt-less-def by (auto simp add: ord-def split: option.split) primrec ord 0 :: key option ⇒ 0a tree23 ⇒ key option ⇒ bool where ord 0 x Empty y = opt-less x y | ord 0 x (Branch2 l p r) y = (ord 0 x l (Some (fst p)) & ord 0 (Some (fst p)) r y) | ord 0 x (Branch3 l p m q r) y = (ord 0 x l (Some (fst p)) & ord 0 (Some (fst p)) m (Some (fst q)) & ord 0 (Some (fst q)) r y) definition ord0 :: 0a tree23 ⇒ bool where ord0 t = ord 0 None t None

Balanced trees inductive full :: nat ⇒ 0a tree23 ⇒ bool where full 0 Empty | [[full n l; full n r]] =⇒ full (Suc n)(Branch2 l p r) | [[full n l; full n m; full n r]] =⇒ full (Suc n)(Branch3 l p m q r) inductive-cases full-elims: full n Empty full n (Branch2 l p r) full n (Branch3 l p m q r)

135 inductive-cases full-0-elim: full 0 t inductive-cases full-Suc-elim: full (Suc n) t lemma full-0-iff [simp]: full 0 t ←→ t = Empty by (auto elim: full-0-elim intro: full.intros) lemma full-Empty-iff [simp]: full n Empty ←→ n = 0 by (auto elim: full-elims intro: full.intros) lemma full-Suc-Branch2-iff [simp]: full (Suc n)(Branch2 l p r) ←→ full n l ∧ full n r by (auto elim: full-elims intro: full.intros) lemma full-Suc-Branch3-iff [simp]: full (Suc n)(Branch3 l p m q r) ←→ full n l ∧ full n m ∧ full n r by (auto elim: full-elims intro: full.intros) fun height :: 0a tree23 ⇒ nat where height Empty = 0 | height (Branch2 l - r) = Suc(max (height l)(height r)) | height (Branch3 l - m - r) = Suc(max (height l)(max (height m)(height r))) Is a tree balanced? fun bal :: 0a tree23 ⇒ bool where bal Empty = True | bal (Branch2 l - r) = (bal l & bal r & height l = height r) | bal (Branch3 l - m - r) = (bal l & bal m & bal r & height l = height m & height m = height r) lemma full-imp-height: full n t =⇒ height t = n by (induct set: full, simp-all) lemma full-imp-bal: full n t =⇒ bal t by (induct set: full, auto dest: full-imp-height) lemma bal-imp-full: bal t =⇒ full (height t) t by (induct t, simp-all) lemma bal-iff-full: bal t ←→ (∃ n. full n t) by (auto elim!: bal-imp-full full-imp-bal) The add0 function either preserves the height of the tree, or increases it by one. The constructor returned by the add function determines which: A return value of the form Stay t indicates that the height will be the same. A value of the form Sprout l p r indicates an increase in height. primrec gfull :: nat ⇒ 0a growth ⇒ bool where gfull n (Stay t) ←→ full n t | gfull n (Sprout l p r) ←→ full n l ∧ full n r

136 lemma gfull-add: full n t =⇒ gfull n (add k y t) by (induct set: full, auto split: ord.split growth.split)

The add0 operation preserves balance. lemma bal-add0 : bal t =⇒ bal (add0 k y t) unfolding bal-iff-full add0-def apply (erule exE) apply (drule gfull-add [of - - k y]) apply (cases add k y t) apply (auto intro: full.intros) done

The add0 operation preserves order. lemma ord-cases: fixes a b :: int obtains ord a b = LESS and a < b | ord a b = EQUAL and a = b | ord a b = GREATER and a > b unfolding ord-def by (rule linorder-cases [of a b]) auto definition gtree :: 0a growth ⇒ 0a tree23 where gtree g = (case g of Stay t ⇒ t | Sprout l p r ⇒ Branch2 l p r) lemma gtree-simps [simp]: gtree (Stay t) = t gtree (Sprout l p r) = Branch2 l p r unfolding gtree-def by simp-all lemma add0 : add0 k y t = gtree (add k y t) unfolding add0-def by (simp split: growth.split) lemma ord 0-add0 : [[ord 0 k1 t k2 ; opt-less k1 (Some k); opt-less (Some k) k2 ]] =⇒ ord 0 k1 (add0 k y t) k2 unfolding add0 apply (induct t arbitrary: k1 k2 ) apply simp apply clarsimp apply (rule-tac a=k and b=a in ord-cases) apply simp apply (case-tac add k y t1 , simp, simp) apply simp apply simp apply (case-tac add k y t2 , simp, simp) apply clarsimp apply (rule-tac a=k and b=a in ord-cases) apply simp apply (case-tac add k y t1 , simp, simp) apply simp

137 apply simp apply (rule-tac a=k and b=aa in ord-cases) apply simp apply (case-tac add k y t2 , simp, simp) apply simp apply simp apply (case-tac add k y t3 , simp, simp) done lemma ord0-add0 : ord0 t =⇒ ord0 (add0 k y t) by (simp add: ord0-def ord 0-add0 )

The del function preserves balance. lemma del-extra-simps: l 6= Empty ∨ r 6= Empty =⇒ del k (Branch2 l p r) = (case compare k p of LESS => (case del k l of None ⇒ None | Some(p 0, (False, l 0)) => Some(p 0, (False, Branch2 l 0 p r)) | Some(p 0, (True, l 0)) => Some(p 0, case r of Branch2 rl rp rr => (True, Branch3 l 0 p rl rp rr) | Branch3 rl rp rm rq rr => (False, Branch2 (Branch2 l 0 p rl) rp (Branch2 rm rq rr)))) | or => (case del (if-eq or None k) r of None ⇒ None | Some(p 0, (False, r 0)) => Some(p 0, (False, Branch2 l (if-eq or p 0 p) r 0)) | Some(p 0, (True, r 0)) => Some(p 0, case l of Branch2 ll lp lr => (True, Branch3 ll lp lr (if-eq or p 0 p) r 0) | Branch3 ll lp lm lq lr => (False, Branch2 (Branch2 ll lp lm) lq (Branch2 lr (if-eq or p 0 p) r 0))))) l 6= Empty ∨ m 6= Empty ∨ r 6= Empty =⇒ del k (Branch3 l p m q r) = (case compare k q of LESS => (case compare k p of LESS => (case del k l of None ⇒ None | Some(p 0, (False, l 0)) => Some(p 0, (False, Branch3 l 0 p m q r)) | Some(p 0, (True, l 0)) => Some(p 0, (False, case (m, r) of (Branch2 ml mp mr, Branch2 - - -) => Branch2 (Branch3 l 0 p ml mp mr) q r | (Branch3 ml mp mm mq mr, -) => Branch3 (Branch2 l 0 p ml) mp (Branch2 mm mq mr) q r | (Branch2 ml mp mr, Branch3 rl rp rm rq rr) => Branch3 (Branch2 l 0 p ml) mp (Branch2 mr q rl) rp (Branch2 rm rq rr)))) | or => (case del (if-eq or None k) m of None ⇒ None | Some(p 0, (False, m 0)) => Some(p 0, (False, Branch3 l (if-eq or p 0 p) m 0 q r)) | Some(p 0, (True, m 0)) => Some(p 0, (False, case (l, r) of (Branch2 ll lp lr, Branch2 - - -) => Branch2 (Branch3 ll lp lr (if-eq or p 0 p) m 0) q r | (Branch3 ll lp lm lq lr, -) => Branch3 (Branch2 ll lp lm) lq (Branch2 lr (if-eq or p 0 p) m 0) q r

138 | (-, Branch3 rl rp rm rq rr) => Branch3 l (if-eq or p 0 p)(Branch2 m 0 q rl) rp (Branch2 rm rq rr))))) | or => (case del (if-eq or None k) r of None ⇒ None | Some(q 0, (False, r 0)) => Some(q 0, (False, Branch3 l p m (if-eq or q 0 q) r 0)) | Some(q 0, (True, r 0)) => Some(q 0, (False, case (l, m) of (Branch2 - - -, Branch2 ml mp mr) => Branch2 l p (Branch3 ml mp mr (if-eq or q 0 q) r 0) | (-, Branch3 ml mp mm mq mr) => Branch3 l p (Branch2 ml mp mm) mq (Branch2 mr (if-eq or q 0 q) r 0) | (Branch3 ll lp lm lq lr, Branch2 ml mp mr) => Branch3 (Branch2 ll lp lm) lq (Branch2 lr p ml) mp (Branch2 mr (if-eq or q 0 q) r 0))))) apply − apply (cases l, cases r, simp-all only: del.simps, simp) apply (cases l, cases m, cases r, simp-all only: del.simps, simp) done fun dfull where dfull n None ←→ True | dfull n (Some (p, (True, t 0))) ←→ full n t 0 | dfull n (Some (p, (False, t 0))) ←→ full (Suc n) t 0 lemmas dfull-case-intros = ord.exhaust [of y dfull a (case-ord b c d y)] option.exhaust [of y dfull a (case-option b c y)] prod.exhaust [of y dfull a (case-prod b y)] bool.exhaust [of y dfull a (case-bool b c y)] tree23 .exhaust [of y dfull a (Some (b, case-tree23 c d e y))] tree23 .exhaust [of y full a (case-tree23 b c d y)] for a b c d e y lemma dfull-del: full (Suc n) t =⇒ dfull n (del k t) proof − { fix n :: nat and p :: key × 0a and l r :: 0a tree23 and k assume Vn. [[compare k p = LESS; full (Suc n) l]] =⇒ dfull n (del k l) and Vn. [[compare k p = EQUAL; full (Suc n) r]] =⇒ dfull n (del (if-eq EQUAL None k) r) and Vn. [[compare k p = GREATER; full (Suc n) r]] =⇒ dfull n (del (if-eq GREATER None k) r) and full (Suc n)(Branch2 l p r) hence dfull n (del k (Branch2 l p r)) apply clarsimp apply (cases n) apply (cases k) apply simp apply (simp split: ord.split) apply simp apply (subst del-extra-simps, force)

139 apply (simp | rule dfull-case-intros)+ done } note A = this { fix n :: nat and p q :: key × 0a and l m r :: 0a tree23 and k assume Vn. [[compare k q = LESS; compare k p = LESS; full (Suc n) l]] =⇒ dfull n (del k l) and Vn. [[compare k q = LESS; compare k p = EQUAL; full (Suc n) m]] =⇒ dfull n (del (if-eq EQUAL None k) m) and Vn. [[compare k q = LESS; compare k p = GREATER; full (Suc n) m]] =⇒ dfull n (del (if-eq GREATER None k) m) and Vn. [[compare k q = EQUAL; full (Suc n) r]] =⇒ dfull n (del (if-eq EQUAL None k) r) and Vn. [[compare k q = GREATER; full (Suc n) r]] =⇒ dfull n (del (if-eq GREATER None k) r) and full (Suc n)(Branch3 l p m q r) hence dfull n (del k (Branch3 l p m q r)) apply clarsimp apply (cases n) apply (cases k) apply simp apply (simp split: ord.split) apply simp apply (subst del-extra-simps, force) apply (simp | rule dfull-case-intros)+ done } note B = this show full (Suc n) t =⇒ dfull n (del k t) proof (induct k t arbitrary: n rule: del.induct, goal-cases) case (1 k n) thus dfull n (del (Some k) Empty) by simp next case (2 p n) thus dfull n (del None (Branch2 Empty p Empty)) by simp next case (3 p q n) thus dfull n (del None (Branch3 Empty p Empty q Empty)) by simp next case (4 v p n) thus dfull n (del (Some v)(Branch2 Empty p Empty)) by (simp split: ord.split) next case (5 v p q n) thus dfull n (del (Some v)(Branch3 Empty p Empty q Empty)) by (simp split: ord.split) next case (26 n) thus ?case by simp qed (fact A | fact B)+ qed

140 lemma bal-del0 : bal t =⇒ bal (del0 k t) unfolding bal-iff-full del0-def apply (erule exE) apply (case-tac n, simp, simp) apply (frule dfull-del [where k=Some k]) apply (cases del (Some k) t, force) apply (rename-tac a, case-tac a, rename-tac b t 0, case-tac b, auto) done

This is a little test harness and should be commented out once the above functions have been proved correct. datatype 0a act = Add int 0a | Del int fun exec where exec [] t = t | exec (Add k x # as) t = exec as (add0 k x t) | exec (Del k # as) t = exec as (del0 k t)

Some quick checks: lemma bal-exec: bal t =⇒ bal (exec as t) by (induct as t arbitrary: t rule: exec.induct, simp-all add: bal-add0 bal-del0 ) lemma bal(exec as Empty) by (simp add: bal-exec) lemma ord0 (exec as Empty) quickcheck oops end

31 (Finite) multisets theory Multiset imports Main begin

31.1 The type of multisets definition multiset = {f :: 0a ⇒ nat. finite {x. f x > 0 }} typedef 0a multiset = multiset :: ( 0a ⇒ nat) set morphisms count Abs-multiset unfolding multiset-def proof show (λx. 0 ::nat) ∈ {f . finite {x. f x > 0 }} by simp

141 qed setup-lifting type-definition-multiset lemma multiset-eq-iff : M = N ←→ (∀ a. count M a = count N a) by (simp only: count-inject [symmetric] fun-eq-iff ) lemma multiset-eqI :(Vx. count A x = count B x) =⇒ A = B using multiset-eq-iff by auto Preservation of the representing set multiset. lemma const0-in-multiset:(λa. 0 ) ∈ multiset by (simp add: multiset-def ) lemma only1-in-multiset:(λb. if b = a then n else 0 ) ∈ multiset by (simp add: multiset-def ) lemma union-preserves-multiset: M ∈ multiset =⇒ N ∈ multiset =⇒ (λa. M a + N a) ∈ multiset by (simp add: multiset-def ) lemma diff-preserves-multiset: assumes M ∈ multiset shows (λa. M a − N a) ∈ multiset proof − have {x. N x < M x} ⊆ {x. 0 < M x} by auto with assms show ?thesis by (auto simp add: multiset-def intro: finite-subset) qed lemma filter-preserves-multiset: assumes M ∈ multiset shows (λx. if P x then M x else 0 ) ∈ multiset proof − have {x. (P x −→ 0 < M x) ∧ P x} ⊆ {x. 0 < M x} by auto with assms show ?thesis by (auto simp add: multiset-def intro: finite-subset) qed lemmas in-multiset = const0-in-multiset only1-in-multiset union-preserves-multiset diff-preserves-multiset filter-preserves-multiset

31.2 Representing multisets

Multiset enumeration instantiation multiset :: (type) cancel-comm-monoid-add begin

142 lift-definition zero-multiset :: 0a multiset is λa. 0 by (rule const0-in-multiset) abbreviation Mempty :: 0a multiset ({#}) where Mempty ≡ 0 lift-definition plus-multiset :: 0a multiset ⇒ 0a multiset ⇒ 0a multiset is λMN . (λa. M a + N a) by (rule union-preserves-multiset) lift-definition minus-multiset :: 0a multiset ⇒ 0a multiset ⇒ 0a multiset is λ M N . λa. M a − N a by (rule diff-preserves-multiset) instance by (standard; transfer; simp add: fun-eq-iff ) end context begin qualified definition is-empty :: 0a multiset ⇒ bool where [code-abbrev]: is-empty A ←→ A = {#} end lemma add-mset-in-multiset: assumes M : hM ∈ multiset i shows h(λb. if b = a then Suc (M b) else M b) ∈ multiset i using assms by (simp add: multiset-def insert-Collect[symmetric]) lift-definition add-mset :: 0a ⇒ 0a multiset ⇒ 0a multiset is λa M b. if b = a then Suc (M b) else M b by (rule add-mset-in-multiset) syntax -multiset :: args ⇒ 0a multiset ({#(-)#}) translations {#x, xs#} == CONST add-mset x {#xs#} {#x#} == CONST add-mset x {#} lemma count-empty [simp]: count {#} a = 0 by (simp add: zero-multiset.rep-eq) lemma count-add-mset [simp]: count (add-mset b A) a = (if b = a then Suc (count A a) else count A a) by (simp add: add-mset.rep-eq)

143 lemma count-single: count {#b#} a = (if b = a then 1 else 0 ) by simp lemma add-mset-not-empty [simp]: hadd-mset a A 6= {#}i and empty-not-add-mset [simp]: {#}= 6 add-mset a A by (auto simp: multiset-eq-iff ) lemma add-mset-add-mset-same-iff [simp]: add-mset a A = add-mset a B ←→ A = B by (auto simp: multiset-eq-iff ) lemma add-mset-commute: add-mset x (add-mset y M ) = add-mset y (add-mset x M ) by (auto simp: multiset-eq-iff )

31.3 Basic operations 31.3.1 Conversion to set and membership definition set-mset :: 0a multiset ⇒ 0a set where set-mset M = {x. count M x > 0 } abbreviation Melem :: 0a ⇒ 0a multiset ⇒ bool where Melem a M ≡ a ∈ set-mset M notation Melem (op ∈#) and Melem ((-/ ∈# -)[51 , 51 ] 50 ) notation (ASCII ) Melem (op :#) and Melem ((-/ :# -)[51 , 51 ] 50 ) abbreviation not-Melem :: 0a ⇒ 0a multiset ⇒ bool where not-Melem a M ≡ a ∈/ set-mset M notation not-Melem (op ∈/#) and not-Melem ((-//∈# -)[51 , 51 ] 50 ) notation (ASCII ) not-Melem (op ∼:#) and not-Melem ((-/ ∼:# -)[51 , 51 ] 50 ) context begin qualified abbreviation Ball :: 0a multiset ⇒ ( 0a ⇒ bool) ⇒ bool

144 where Ball M ≡ Set.Ball (set-mset M ) qualified abbreviation Bex :: 0a multiset ⇒ ( 0a ⇒ bool) ⇒ bool where Bex M ≡ Set.Bex (set-mset M ) end syntax -MBall :: pttrn ⇒ 0a set ⇒ bool ⇒ bool ((3 ∀ -∈#-./ -)[0 , 0 , 10 ] 10 ) -MBex :: pttrn ⇒ 0a set ⇒ bool ⇒ bool ((3 ∃ -∈#-./ -)[0 , 0 , 10 ] 10 ) syntax (ASCII ) -MBall :: pttrn ⇒ 0a set ⇒ bool ⇒ bool ((3 ∀ -:#-./ -)[0 , 0 , 10 ] 10 ) -MBex :: pttrn ⇒ 0a set ⇒ bool ⇒ bool ((3 ∃ -:#-./ -)[0 , 0 , 10 ] 10 ) translations ∀ x∈#A. P CONST Multiset.Ball A (λx. P) ∃ x∈#A. P CONST Multiset.Bex A (λx. P) lemma count-eq-zero-iff : count M x = 0 ←→ x ∈/# M by (auto simp add: set-mset-def ) lemma not-in-iff : x ∈/# M ←→ count M x = 0 by (auto simp add: count-eq-zero-iff ) lemma count-greater-zero-iff [simp]: count M x > 0 ←→ x ∈# M by (auto simp add: set-mset-def ) lemma count-inI : assumes count M x = 0 =⇒ False shows x ∈# M proof (rule ccontr) assume x ∈/# M with assms show False by (simp add: not-in-iff ) qed lemma in-countE: assumes x ∈# M obtains n where count M x = Suc n proof − from assms have count M x > 0 by simp then obtain n where count M x = Suc n using gr0-conv-Suc by blast with that show thesis . qed

145 lemma count-greater-eq-Suc-zero-iff [simp]: count M x ≥ Suc 0 ←→ x ∈# M by (simp add: Suc-le-eq) lemma count-greater-eq-one-iff [simp]: count M x ≥ 1 ←→ x ∈# M by simp lemma set-mset-empty [simp]: set-mset {#} = {} by (simp add: set-mset-def ) lemma set-mset-single: set-mset {#b#} = {b} by (simp add: set-mset-def ) lemma set-mset-eq-empty-iff [simp]: set-mset M = {} ←→ M = {#} by (auto simp add: multiset-eq-iff count-eq-zero-iff ) lemma finite-set-mset [iff ]: finite (set-mset M ) using count [of M ] by (simp add: multiset-def ) lemma set-mset-add-mset-insert [simp]: hset-mset (add-mset a A) = insert a (set-mset A)i by (auto simp del: count-greater-eq-Suc-zero-iff simp: count-greater-eq-Suc-zero-iff [symmetric] split: if-splits) lemma multiset-nonemptyE [elim]: assumes A 6= {#} obtains x where x ∈# A proof − have ∃ x. x ∈# A by (rule ccontr)(insert assms, auto) with that show ?thesis by blast qed

31.3.2 Union lemma count-union [simp]: count (M + N ) a = count M a + count N a by (simp add: plus-multiset.rep-eq) lemma set-mset-union [simp]: set-mset (M + N ) = set-mset M ∪ set-mset N by (simp only: set-eq-iff count-greater-zero-iff [symmetric] count-union) simp lemma union-mset-add-mset-left [simp]: add-mset a A + B = add-mset a (A + B)

146 by (auto simp: multiset-eq-iff ) lemma union-mset-add-mset-right [simp]: A + add-mset a B = add-mset a (A + B) by (auto simp: multiset-eq-iff ) lemma add-mset-add-single: hadd-mset a A = A + {#a#}i by (subst union-mset-add-mset-right, subst add.comm-neutral) standard

31.3.3 Difference instance multiset :: (type) comm-monoid-diff by standard (transfer; simp add: fun-eq-iff ) lemma count-diff [simp]: count (M − N ) a = count M a − count N a by (simp add: minus-multiset.rep-eq) lemma add-mset-diff-bothsides: hadd-mset a M − add-mset a A = M − Ai by (auto simp: multiset-eq-iff ) lemma in-diff-count: a ∈# M − N ←→ count N a < count M a by (simp add: set-mset-def ) lemma count-in-diffI : assumes Vn. count N x = n + count M x =⇒ False shows x ∈# M − N proof (rule ccontr) assume x ∈/# M − N then have count N x = (count N x − count M x) + count M x by (simp add: in-diff-count not-less) with assms show False by auto qed lemma in-diff-countE: assumes x ∈# M − N obtains n where count M x = Suc n + count N x proof − from assms have count M x − count N x > 0 by (simp add: in-diff-count) then have count M x > count N x by simp then obtain n where count M x = Suc n + count N x using less-iff-Suc-add by auto with that show thesis . qed lemma in-diffD: assumes a ∈# M − N

147 shows a ∈# M proof − have 0 ≤ count N a by simp also from assms have count N a < count M a by (simp add: in-diff-count) finally show ?thesis by simp qed lemma set-mset-diff : set-mset (M − N ) = {a. count N a < count M a} by (simp add: set-mset-def ) lemma diff-empty [simp]: M − {#} = M ∧ {#} − M = {#} by rule (fact Groups.diff-zero, fact Groups.zero-diff ) lemma diff-cancel: A − A = {#} by (fact Groups.diff-cancel) lemma diff-union-cancelR: M + N − N = (M :: 0a multiset) by (fact add-diff-cancel-right 0) lemma diff-union-cancelL: N + M − N = (M :: 0a multiset) by (fact add-diff-cancel-left 0) lemma diff-right-commute: fixes MNQ :: 0a multiset shows M − N − Q = M − Q − N by (fact diff-right-commute) lemma diff-add: fixes MNQ :: 0a multiset shows M − (N + Q) = M − N − Q by (rule sym)(fact diff-diff-add) lemma insert-DiffM [simp]: x ∈# M =⇒ add-mset x (M − {#x#}) = M by (clarsimp simp: multiset-eq-iff ) lemma insert-DiffM2 : x ∈# M =⇒ (M − {#x#}) + {#x#} = M by simp lemma diff-union-swap: a 6= b =⇒ add-mset b (M − {#a#}) = add-mset b M − {#a#} by (auto simp add: multiset-eq-iff ) lemma diff-add-mset-swap [simp]: b ∈/# A =⇒ add-mset b M − A = add-mset b (M − A) by (auto simp add: multiset-eq-iff simp: not-in-iff ) lemma diff-union-swap2 [simp]: y ∈# M =⇒ add-mset x M − {#y#} = add-mset

148 x (M − {#y#}) by (metis add-mset-diff-bothsides diff-union-swap diff-zero insert-DiffM ) lemma diff-diff-add-mset [simp]: (M :: 0a multiset) − N − P = M − (N + P) by (rule diff-diff-add) lemma diff-union-single-conv: a ∈# J =⇒ I + J − {#a#} = I + (J − {#a#}) by (simp add: multiset-eq-iff Suc-le-eq) lemma mset-add [elim?]: assumes a ∈# A obtains B where A = add-mset a B proof − from assms have A = add-mset a (A − {#a#}) by simp with that show thesis . qed lemma union-iff : a ∈# A + B ←→ a ∈# A ∨ a ∈# B by auto

31.3.4 Equality of multisets lemma single-eq-single [simp]: {#a#} = {#b#} ←→ a = b by (auto simp add: multiset-eq-iff ) lemma union-eq-empty [iff ]: M + N = {#} ←→ M = {#} ∧ N = {#} by (auto simp add: multiset-eq-iff ) lemma empty-eq-union [iff ]: {#} = M + N ←→ M = {#} ∧ N = {#} by (auto simp add: multiset-eq-iff ) lemma multi-self-add-other-not-self [simp]: M = add-mset x M ←→ False by (auto simp add: multiset-eq-iff ) lemma add-mset-remove-trivial [simp]: hadd-mset x M − {#x#} = M i by (auto simp: multiset-eq-iff ) lemma diff-single-trivial: ¬ x ∈# M =⇒ M − {#x#} = M by (auto simp add: multiset-eq-iff not-in-iff ) lemma diff-single-eq-union: x ∈# M =⇒ M − {#x#} = N ←→ M = add-mset x N by auto lemma union-single-eq-diff : add-mset x M = N =⇒ M = N − {#x#} unfolding add-mset-add-single[of - M ] by (fact add-implies-diff )

149 lemma union-single-eq-member: add-mset x M = N =⇒ x ∈# N by auto lemma add-mset-remove-trivial-If : add-mset a (N − {#a#}) = (if a ∈# N then N else add-mset a N ) by (simp add: diff-single-trivial) lemma add-mset-remove-trivial-eq: hN = add-mset a (N − {#a#}) ←→ a ∈# N i by (auto simp: add-mset-remove-trivial-If ) lemma union-is-single: M + N = {#a#} ←→ M = {#a#} ∧ N = {#} ∨ M = {#} ∧ N = {#a#} (is ?lhs = ?rhs) proof show ?lhs if ?rhs using that by auto show ?rhs if ?lhs by (metis Multiset.diff-cancel add.commute add-diff-cancel-left 0 diff-add-zero diff-single-trivial insert-DiffM that) qed lemma single-is-union: {#a#} = M + N ←→ {#a#} = M ∧ N = {#} ∨ M = {#} ∧ {#a#} = N by (auto simp add: eq-commute [of {#a#} M + N ] union-is-single) lemma add-eq-conv-diff : add-mset a M = add-mset b N ←→ M = N ∧ a = b ∨ M = add-mset b (N − {#a#}) ∧ N = add-mset a (M − {#b#}) (is ?lhs ←→ ?rhs) proof show ?lhs if ?rhs using that by (auto simp add: add-mset-commute[of a b]) show ?rhs if ?lhs proof (cases a = b) case True with h?lhs i show ?thesis by simp next case False from h?lhs i have a ∈# add-mset b N by (rule union-single-eq-member) with False have a ∈# N by auto moreover from h?lhs i have M = add-mset b N − {#a#} by (rule union-single-eq-diff ) moreover note False ultimately show ?thesis by (auto simp add: diff-right-commute [of - {#a#}]) qed qed lemma add-mset-eq-single [iff ]: add-mset b M = {#a#} ←→ b = a ∧ M = {#}

150 by (auto simp: add-eq-conv-diff ) lemma single-eq-add-mset [iff ]: {#a#} = add-mset b M ←→ b = a ∧ M = {#} by (auto simp: add-eq-conv-diff ) lemma insert-noteq-member: assumes BC : add-mset b B = add-mset c C and bnotc: b 6= c shows c ∈# B proof − have c ∈# add-mset c C by simp have nc: ¬ c ∈# {#b#} using bnotc by simp then have c ∈# add-mset b B using BC by simp then show c ∈# B using nc by simp qed lemma add-eq-conv-ex: (add-mset a M = add-mset b N ) = (M = N ∧ a = b ∨ (∃ K . M = add-mset b K ∧ N = add-mset a K )) by (auto simp add: add-eq-conv-diff ) lemma multi-member-split: x ∈# M =⇒ ∃ A. M = add-mset x A by (rule exI [where x = M − {#x#}]) simp lemma multiset-add-sub-el-shuffle: assumes c ∈# B and b 6= c shows add-mset b (B − {#c#}) = add-mset b B − {#c#} proof − from hc ∈# B i obtain A where B: B = add-mset c A by (blast dest: multi-member-split) have add-mset b A = add-mset c (add-mset b A) − {#c#} by simp then have add-mset b A = add-mset b (add-mset c A) − {#c#} by (simp add: hb 6= ci) then show ?thesis using B by simp qed lemma add-mset-eq-singleton-iff [iff ]: add-mset x M = {#y#} ←→ M = {#} ∧ x = y by auto

31.3.5 Pointwise ordering induced by count definition subseteq-mset :: 0a multiset ⇒ 0a multiset ⇒ bool (infix ⊆# 50 ) where A ⊆# B = (∀ a. count A a ≤ count B a) definition subset-mset :: 0a multiset ⇒ 0a multiset ⇒ bool (infix ⊂# 50 ) where A ⊂# B = (A ⊆# B ∧ A 6= B)

151 abbreviation (input) supseteq-mset :: 0a multiset ⇒ 0a multiset ⇒ bool (infix ⊇# 50 ) where supseteq-mset A B ≡ B ⊆# A abbreviation (input) supset-mset :: 0a multiset ⇒ 0a multiset ⇒ bool (infix ⊃# 50 ) where supset-mset A B ≡ B ⊂# A notation (input) subseteq-mset (infix ≤# 50 ) and supseteq-mset (infix ≥# 50 ) notation (ASCII ) subseteq-mset (infix <=# 50 ) and subset-mset (infix <# 50 ) and supseteq-mset (infix >=# 50 ) and supset-mset (infix ># 50 ) interpretation subset-mset: ordered-ab-semigroup-add-imp-le op + op − op ⊆# op ⊂# by standard (auto simp add: subset-mset-def subseteq-mset-def multiset-eq-iff in- tro: order-trans antisym) interpretation subset-mset: ordered-ab-semigroup-monoid-add-imp-le op + 0 op − op ≤# op <# by standard lemma mset-subset-eqI : (Va. count A a ≤ count B a) =⇒ A ⊆# B by (simp add: subseteq-mset-def ) lemma mset-subset-eq-count: A ⊆# B =⇒ count A a ≤ count B a by (simp add: subseteq-mset-def ) lemma mset-subset-eq-exists-conv:(A:: 0a multiset) ⊆# B ←→ (∃ C . B = A + C ) unfolding subseteq-mset-def apply (rule iffI ) apply (rule exI [where x = B − A]) apply (auto intro: multiset-eq-iff [THEN iffD2 ]) done interpretation subset-mset: ordered-cancel-comm-monoid-diff op + 0 op ≤# op <# op − by standard (simp, fact mset-subset-eq-exists-conv) declare subset-mset.add-diff-assoc[simp] subset-mset.add-diff-assoc2 [simp] lemma mset-subset-eq-mono-add-right-cancel:(A:: 0a multiset) + C ⊆# B + C

152 ←→ A ⊆# B by (fact subset-mset.add-le-cancel-right) lemma mset-subset-eq-mono-add-left-cancel: C + (A:: 0a multiset) ⊆# C + B ←→ A ⊆# B by (fact subset-mset.add-le-cancel-left) lemma mset-subset-eq-mono-add:(A:: 0a multiset) ⊆# B =⇒ C ⊆# D =⇒ A + C ⊆# B + D by (fact subset-mset.add-mono) lemma mset-subset-eq-add-left:(A:: 0a multiset) ⊆# A + B by simp lemma mset-subset-eq-add-right: B ⊆#(A:: 0a multiset) + B by simp lemma single-subset-iff [simp]: {#a#} ⊆# M ←→ a ∈# M by (auto simp add: subseteq-mset-def Suc-le-eq) lemma mset-subset-eq-single: a ∈# B =⇒ {#a#} ⊆# B by simp lemma mset-subset-eq-add-mset-cancel: hadd-mset a A ⊆# add-mset a B ←→ A ⊆# B i unfolding add-mset-add-single[of - A] add-mset-add-single[of - B] by (rule mset-subset-eq-mono-add-right-cancel) lemma multiset-diff-union-assoc: fixes ABCD :: 0a multiset shows C ⊆# B =⇒ A + B − C = A + (B − C ) by (fact subset-mset.diff-add-assoc) lemma mset-subset-eq-multiset-union-diff-commute: fixes ABCD :: 0a multiset shows B ⊆# A =⇒ A − B + C = A + C − B by (fact subset-mset.add-diff-assoc2 ) lemma diff-subset-eq-self [simp]: (M :: 0a multiset) − N ⊆# M by (simp add: subseteq-mset-def ) lemma mset-subset-eqD: assumes A ⊆# B and x ∈# A shows x ∈# B proof − from hx ∈# Ai have count A x > 0 by simp also from hA ⊆# B i have count A x ≤ count B x

153 by (simp add: subseteq-mset-def ) finally show ?thesis by simp qed lemma mset-subsetD: A ⊂# B =⇒ x ∈# A =⇒ x ∈# B by (auto intro: mset-subset-eqD [of A]) lemma set-mset-mono: A ⊆# B =⇒ set-mset A ⊆ set-mset B by (metis mset-subset-eqD subsetI ) lemma mset-subset-eq-insertD: add-mset x A ⊆# B =⇒ x ∈# B ∧ A ⊂# B apply (rule conjI ) apply (simp add: mset-subset-eqD) apply (clarsimp simp: subset-mset-def subseteq-mset-def ) apply safe apply (erule-tac x = a in allE) apply (auto split: if-split-asm) done lemma mset-subset-insertD: add-mset x A ⊂# B =⇒ x ∈# B ∧ A ⊂# B by (rule mset-subset-eq-insertD) simp lemma mset-subset-of-empty[simp]: A ⊂# {#} ←→ False by (simp only: subset-mset.not-less-zero) lemma empty-subset-add-mset[simp]: {#} <# add-mset x M by(auto intro: subset-mset.gr-zeroI ) lemma empty-le: {#} ⊆# A by (fact subset-mset.zero-le) lemma insert-subset-eq-iff : add-mset a A ⊆# B ←→ a ∈# B ∧ A ⊆# B − {#a#} using le-diff-conv2 [of Suc 0 count B a count A a] apply (auto simp add: subseteq-mset-def not-in-iff Suc-le-eq) apply (rule ccontr) apply (auto simp add: not-in-iff ) done lemma insert-union-subset-iff : add-mset a A ⊂# B ←→ a ∈# B ∧ A ⊂# B − {#a#} by (auto simp add: insert-subset-eq-iff subset-mset-def ) lemma subset-eq-diff-conv: A − C ⊆# B ←→ A ⊆# B + C

154 by (simp add: subseteq-mset-def le-diff-conv) lemma multi-psub-of-add-self [simp]: A ⊂# add-mset x A by (auto simp: subset-mset-def subseteq-mset-def ) lemma multi-psub-self : A ⊂# A = False by simp lemma mset-subset-add-mset [simp]: add-mset x N ⊂# add-mset x M ←→ N ⊂# M unfolding add-mset-add-single[of - N ] add-mset-add-single[of - M ] by (fact subset-mset.add-less-cancel-right) lemma mset-subset-diff-self : c ∈# B =⇒ B − {#c#} ⊂# B by (auto simp: subset-mset-def elim: mset-add) lemma Diff-eq-empty-iff-mset: A − B = {#} ←→ A ⊆# B by (auto simp: multiset-eq-iff subseteq-mset-def ) lemma add-mset-subseteq-single-iff [iff ]: add-mset a M ⊆# {#b#} ←→ M = {#} ∧ a = b proof assume A: add-mset a M ⊆# {#b#} then have ha = bi by (auto dest: mset-subset-eq-insertD) then show M ={#} ∧ a=b using A by (simp add: mset-subset-eq-add-mset-cancel) qed simp

31.3.6 Intersection and bounded union definition inf-subset-mset :: 0a multiset ⇒ 0a multiset ⇒ 0a multiset (infixl ∩# 70 ) where multiset-inter-def : inf-subset-mset A B = A − (A − B) interpretation subset-mset: semilattice-inf inf-subset-mset op ⊆# op ⊂# proof − have [simp]: m ≤ n =⇒ m ≤ q =⇒ m ≤ n − (n − q) for m n q :: nat by arith show class.semilattice-inf op ∩# op ⊆# op ⊂# by standard (auto simp add: multiset-inter-def subseteq-mset-def ) qed — FIXME: avoid junk stemming from type class interpretation definition sup-subset-mset :: 0a multiset ⇒ 0a multiset ⇒ 0a multiset(infixl ∪# 70 ) where sup-subset-mset A B = A + (B − A) — FIXME irregular fact name interpretation subset-mset: semilattice-sup sup-subset-mset op ⊆# op ⊂#

155 proof − have [simp]: m ≤ n =⇒ q ≤ n =⇒ m + (q − m) ≤ n for m n q :: nat by arith show class.semilattice-sup op ∪# op ⊆# op ⊂# by standard (auto simp add: sup-subset-mset-def subseteq-mset-def ) qed — FIXME: avoid junk stemming from type class interpretation interpretation subset-mset: bounded-lattice-bot op ∩# op ⊆# op ⊂# op ∪# {#} by standard auto

31.3.7 Additional intersection facts lemma multiset-inter-count [simp]: fixes AB :: 0a multiset shows count (A ∩# B) x = min (count A x)(count B x) by (simp add: multiset-inter-def ) lemma set-mset-inter [simp]: set-mset (A ∩# B) = set-mset A ∩ set-mset B by (simp only: set-eq-iff count-greater-zero-iff [symmetric] multiset-inter-count) simp lemma diff-intersect-left-idem [simp]: M − M ∩# N = M − N by (simp add: multiset-eq-iff min-def ) lemma diff-intersect-right-idem [simp]: M − N ∩# M = M − N by (simp add: multiset-eq-iff min-def ) lemma multiset-inter-single[simp]: a 6= b =⇒ {#a#} ∩# {#b#} = {#} by (rule multiset-eqI ) auto lemma multiset-union-diff-commute: assumes B ∩# C = {#} shows A + B − C = A − C + B proof (rule multiset-eqI ) fix x from assms have min (count B x)(count C x) = 0 by (auto simp add: multiset-eq-iff ) then have count B x = 0 ∨ count C x = 0 unfolding min-def by (auto split: if-splits) then show count (A + B − C ) x = count (A − C + B) x by auto qed lemma disjunct-not-in:

156 A ∩# B = {#} ←→ (∀ a. a ∈/# A ∨ a ∈/# B)(is ?P ←→ ?Q) proof assume ?P show ?Q proof fix a from h?P i have min (count A a)(count B a) = 0 by (simp add: multiset-eq-iff ) then have count A a = 0 ∨ count B a = 0 by (cases count A a ≤ count B a)(simp-all add: min-def ) then show a ∈/# A ∨ a ∈/# B by (simp add: not-in-iff ) qed next assume ?Q show ?P proof (rule multiset-eqI ) fix a from h?Q i have count A a = 0 ∨ count B a = 0 by (auto simp add: not-in-iff ) then show count (A ∩# B) a = count {#} a by auto qed qed lemma inter-mset-empty-distrib-right: A ∩#(B + C ) = {#} ←→ A ∩# B = {#} ∧ A ∩# C = {#} by (meson disjunct-not-in union-iff ) lemma inter-mset-empty-distrib-left:(A + B) ∩# C = {#} ←→ A ∩# C = {#} ∧ B ∩# C = {#} by (meson disjunct-not-in union-iff ) lemma add-mset-inter-add-mset[simp]: add-mset a A ∩# add-mset a B = add-mset a (A ∩# B) by (metis add-mset-add-single add-mset-diff-bothsides diff-subset-eq-self multiset-inter-def subset-mset.diff-add-assoc2 ) lemma add-mset-disjoint [simp]: add-mset a A ∩# B = {#} ←→ a ∈/# B ∧ A ∩# B = {#} {#} = add-mset a A ∩# B ←→ a ∈/# B ∧ {#} = A ∩# B by (auto simp: disjunct-not-in) lemma disjoint-add-mset [simp]: B ∩# add-mset a A = {#} ←→ a ∈/# B ∧ B ∩# A = {#} {#} = A ∩# add-mset b B ←→ b ∈/# A ∧ {#} = A ∩# B by (auto simp: disjunct-not-in) lemma inter-add-left1 : ¬ x ∈# N =⇒ (add-mset x M ) ∩# N = M ∩# N

157 by (simp add: multiset-eq-iff not-in-iff ) lemma inter-add-left2 : x ∈# N =⇒ (add-mset x M ) ∩# N = add-mset x (M ∩# (N − {#x#})) by (auto simp add: multiset-eq-iff elim: mset-add) lemma inter-add-right1 : ¬ x ∈# N =⇒ N ∩#(add-mset x M ) = N ∩# M by (simp add: multiset-eq-iff not-in-iff ) lemma inter-add-right2 : x ∈# N =⇒ N ∩#(add-mset x M ) = add-mset x ((N − {#x#}) ∩# M ) by (auto simp add: multiset-eq-iff elim: mset-add) lemma disjunct-set-mset-diff : assumes M ∩# N = {#} shows set-mset (M − N ) = set-mset M proof (rule set-eqI ) fix a from assms have a ∈/# M ∨ a ∈/# N by (simp add: disjunct-not-in) then show a ∈# M − N ←→ a ∈# M by (auto dest: in-diffD)(simp add: in-diff-count not-in-iff ) qed lemma at-most-one-mset-mset-diff : assumes a ∈/# M − {#a#} shows set-mset (M − {#a#}) = set-mset M − {a} using assms by (auto simp add: not-in-iff in-diff-count set-eq-iff ) lemma more-than-one-mset-mset-diff : assumes a ∈# M − {#a#} shows set-mset (M − {#a#}) = set-mset M proof (rule set-eqI ) fix b have Suc 0 < count M b =⇒ count M b > 0 by arith then show b ∈# M − {#a#} ←→ b ∈# M using assms by (auto simp add: in-diff-count) qed lemma inter-iff : a ∈# A ∩# B ←→ a ∈# A ∧ a ∈# B by simp lemma inter-union-distrib-left: A ∩# B + C = (A + C ) ∩#(B + C ) by (simp add: multiset-eq-iff min-add-distrib-left) lemma inter-union-distrib-right: C + A ∩# B = (C + A) ∩#(C + B)

158 using inter-union-distrib-left [of A B C ] by (simp add: ac-simps) lemma inter-subset-eq-union: A ∩# B ⊆# A + B by (auto simp add: subseteq-mset-def )

31.3.8 Additional bounded union facts lemma sup-subset-mset-count [simp]: — FIXME irregular fact name count (A ∪# B) x = max (count A x)(count B x) by (simp add: sup-subset-mset-def ) lemma set-mset-sup [simp]: set-mset (A ∪# B) = set-mset A ∪ set-mset B by (simp only: set-eq-iff count-greater-zero-iff [symmetric] sup-subset-mset-count) (auto simp add: not-in-iff elim: mset-add) lemma sup-union-left1 [simp]: ¬ x ∈# N =⇒ (add-mset x M ) ∪# N = add-mset x (M ∪# N ) by (simp add: multiset-eq-iff not-in-iff ) lemma sup-union-left2 : x ∈# N =⇒ (add-mset x M ) ∪# N = add-mset x (M ∪#(N − {#x#})) by (simp add: multiset-eq-iff ) lemma sup-union-right1 [simp]: ¬ x ∈# N =⇒ N ∪#(add-mset x M ) = add-mset x (N ∪# M ) by (simp add: multiset-eq-iff not-in-iff ) lemma sup-union-right2 : x ∈# N =⇒ N ∪#(add-mset x M ) = add-mset x ((N − {#x#}) ∪# M ) by (simp add: multiset-eq-iff ) lemma sup-union-distrib-left: A ∪# B + C = (A + C ) ∪#(B + C ) by (simp add: multiset-eq-iff max-add-distrib-left) lemma union-sup-distrib-right: C + A ∪# B = (C + A) ∪#(C + B) using sup-union-distrib-left [of A B C ] by (simp add: ac-simps) lemma union-diff-inter-eq-sup: A + B − A ∩# B = A ∪# B by (auto simp add: multiset-eq-iff ) lemma union-diff-sup-eq-inter: A + B − A ∪# B = A ∩# B by (auto simp add: multiset-eq-iff )

159 lemma add-mset-union: hadd-mset a A ∪# add-mset a B = add-mset a (A ∪# B)i by (auto simp: multiset-eq-iff max-def )

31.3.9 Subset is an order interpretation subset-mset: order op ⊆# op ⊂# by unfold-locales

31.4 Replicate and repeat operations definition replicate-mset :: nat ⇒ 0a ⇒ 0a multiset where replicate-mset n x = (add-mset x ˆˆ n) {#} lemma replicate-mset-0 [simp]: replicate-mset 0 x = {#} unfolding replicate-mset-def by simp lemma replicate-mset-Suc [simp]: replicate-mset (Suc n) x = add-mset x (replicate-mset n x) unfolding replicate-mset-def by (induct n)(auto intro: add.commute) lemma count-replicate-mset[simp]: count (replicate-mset n x) y = (if y = x then n else 0 ) unfolding replicate-mset-def by (induct n) auto fun repeat-mset :: nat ⇒ 0a multiset ⇒ 0a multiset where repeat-mset 0 - = {#} | repeat-mset (Suc n) A = A + repeat-mset n A lemma count-repeat-mset [simp]: count (repeat-mset i A) a = i ∗ count A a by (induction i) auto lemma repeat-mset-right [simp]: repeat-mset a (repeat-mset b A) = repeat-mset (a ∗ b) A by (auto simp: multiset-eq-iff left-diff-distrib 0)

0 lemma left-diff-repeat-mset-distrib : hrepeat-mset (i − j ) u = repeat-mset i u − repeat-mset j u i by (auto simp: multiset-eq-iff left-diff-distrib 0) lemma left-add-mult-distrib-mset: repeat-mset i u + (repeat-mset j u + k) = repeat-mset (i+j ) u + k by (auto simp: multiset-eq-iff add-mult-distrib) lemma repeat-mset-distrib: repeat-mset (m + n) A = repeat-mset m A + repeat-mset n A by (auto simp: multiset-eq-iff Nat.add-mult-distrib) lemma repeat-mset-distrib2 [simp]: repeat-mset n (A + B) = repeat-mset n A + repeat-mset n B by (auto simp: multiset-eq-iff add-mult-distrib2 )

160 lemma repeat-mset-replicate-mset[simp]: repeat-mset n {#a#} = replicate-mset n a by (auto simp: multiset-eq-iff ) lemma repeat-mset-distrib-add-mset[simp]: repeat-mset n (add-mset a A) = replicate-mset n a + repeat-mset n A by (auto simp: multiset-eq-iff ) lemma repeat-mset-empty[simp]: repeat-mset n {#} = {#} by (induction n) simp-all

31.4.1 Simprocs lemma mset-diff-add-eq1 : j ≤ (i::nat) =⇒ ((repeat-mset i u + m) − (repeat-mset j u + n)) = ((repeat-mset (i−j ) u + m) − n) by (auto simp: multiset-eq-iff nat-diff-add-eq1 ) lemma mset-diff-add-eq2 : i ≤ (j ::nat) =⇒ ((repeat-mset i u + m) − (repeat-mset j u + n)) = (m − (repeat-mset (j −i) u + n)) by (auto simp: multiset-eq-iff nat-diff-add-eq2 ) lemma mset-eq-add-iff1 : j ≤ (i::nat) =⇒ (repeat-mset i u + m = repeat-mset j u + n) = (repeat-mset (i−j ) u + m = n) by (auto simp: multiset-eq-iff nat-eq-add-iff1 ) lemma mset-eq-add-iff2 : i ≤ (j ::nat) =⇒ (repeat-mset i u + m = repeat-mset j u + n) = (m = repeat-mset (j −i) u + n) by (auto simp: multiset-eq-iff nat-eq-add-iff2 ) lemma mset-subseteq-add-iff1 : j ≤ (i::nat) =⇒ (repeat-mset i u + m ⊆# repeat-mset j u + n) = (repeat-mset (i−j ) u + m ⊆# n) by (auto simp add: subseteq-mset-def nat-le-add-iff1 ) lemma mset-subseteq-add-iff2 : i ≤ (j ::nat) =⇒ (repeat-mset i u + m ⊆# repeat-mset j u + n) = (m ⊆# repeat-mset (j −i) u + n) by (auto simp add: subseteq-mset-def nat-le-add-iff2 ) lemma mset-subset-add-iff1 : j ≤ (i::nat) =⇒ (repeat-mset i u + m ⊂# repeat-mset j u + n) = (repeat-mset (i−j ) u + m ⊂# n) unfolding subset-mset-def by (simp add: mset-eq-add-iff1 mset-subseteq-add-iff1 )

161 lemma mset-subset-add-iff2 : i ≤ (j ::nat) =⇒ (repeat-mset i u + m ⊂# repeat-mset j u + n) = (m ⊂# repeat-mset (j −i) u + n) unfolding subset-mset-def by (simp add: mset-eq-add-iff2 mset-subseteq-add-iff2 )

ML-file multiset-simprocs-util.ML ML-file multiset-simprocs.ML simproc-setup mseteq-cancel-numerals ((l:: 0a multiset) + m = n | (l:: 0a multiset) = m + n | add-mset a m = n | m = add-mset a n | replicate-mset p a = n | m = replicate-mset p a | repeat-mset p m = n | m = repeat-mset p m) = hfn phi => Multiset-Simprocs.eq-cancel-msets i simproc-setup msetless-cancel-numerals ((l:: 0a multiset) + m ⊂# n | (l:: 0a multiset) ⊂# m + n | add-mset a m ⊂# n | m ⊂# add-mset a n | replicate-mset p r ⊂# n | m ⊂# replicate-mset p r | repeat-mset p m ⊂# n | m ⊂# repeat-mset p m) = hfn phi => Multiset-Simprocs.subset-cancel-msets i simproc-setup msetle-cancel-numerals ((l:: 0a multiset) + m ⊆# n | (l:: 0a multiset) ⊆# m + n | add-mset a m ⊆# n | m ⊆# add-mset a n | replicate-mset p r ⊆# n | m ⊆# replicate-mset p r | repeat-mset p m ⊆# n | m ⊆# repeat-mset p m) = hfn phi => Multiset-Simprocs.subseteq-cancel-msets i simproc-setup msetdiff-cancel-numerals (((l:: 0a multiset) + m) − n | (l:: 0a multiset) − (m + n) | add-mset a m − n | m − add-mset a n | replicate-mset p r − n | m − replicate-mset p r | repeat-mset p m − n | m − repeat-mset p m) = hfn phi => Multiset-Simprocs.diff-cancel-msets i

31.4.2 Conditionally complete lattice instantiation multiset :: (type) Inf begin lift-definition Inf-multiset :: 0a multiset set ⇒ 0a multiset is λA i. if A = {} then 0 else Inf ((λf . f i) ‘A) proof − fix A :: ( 0a ⇒ nat) set assume ∗: Vx. x ∈ A =⇒ x ∈ multiset have finite {i. (if A = {} then 0 else Inf ((λf . f i) ‘A)) > 0 } unfolding multiset-def proof (cases A = {}) case False

162 then obtain f where f ∈ A by blast hence {i. Inf ((λf . f i) ‘A) > 0 } ⊆ {i. f i > 0 } by (auto intro: less-le-trans[OF - cInf-lower]) moreover from hf ∈ Ai ∗ have finite ... by (simp add: multiset-def ) ultimately have finite {i. Inf ((λf . f i) ‘A) > 0 } by (rule finite-subset) with False show ?thesis by simp qed simp-all thus (λi. if A = {} then 0 else INF f :A. f i) ∈ multiset by (simp add: multiset-def ) qed instance .. end lemma Inf-multiset-empty: Inf {} = {#} by transfer simp-all lemma count-Inf-multiset-nonempty: A 6= {} =⇒ count (Inf A) x = Inf ((λX . count X x) ‘A) by transfer simp-all instantiation multiset :: (type) Sup begin definition Sup-multiset :: 0a multiset set ⇒ 0a multiset where Sup-multiset A = (if A 6= {} ∧ subset-mset.bdd-above A then Abs-multiset (λi. Sup ((λX . count X i) ‘A)) else {#}) lemma Sup-multiset-empty: Sup {} = {#} by (simp add: Sup-multiset-def ) lemma Sup-multiset-unbounded: ¬subset-mset.bdd-above A =⇒ Sup A = {#} by (simp add: Sup-multiset-def ) instance .. end lemma bdd-above-multiset-imp-bdd-above-count: assumes subset-mset.bdd-above (A :: 0a multiset set) shows bdd-above ((λX . count X x) ‘A) proof − from assms obtain Y where Y : ∀ X ∈A. X ⊆# Y by (auto simp: subset-mset.bdd-above-def ) hence count X x ≤ count Y x if X ∈ A for X using that by (auto intro: mset-subset-eq-count) thus ?thesis by (intro bdd-aboveI [of - count Y x]) auto

163 qed lemma bdd-above-multiset-imp-finite-support: assumes A 6= {} subset-mset.bdd-above (A :: 0a multiset set) shows finite (S X ∈A. {x. count X x > 0 }) proof − from assms obtain Y where Y : ∀ X ∈A. X ⊆# Y by (auto simp: subset-mset.bdd-above-def ) hence count X x ≤ count Y x if X ∈ A for X x using that by (auto intro: mset-subset-eq-count) hence (S X ∈A. {x. count X x > 0 }) ⊆ {x. count Y x > 0 } by safe (erule less-le-trans) moreover have finite ... by simp ultimately show ?thesis by (rule finite-subset) qed lemma Sup-multiset-in-multiset: assumes A 6= {} subset-mset.bdd-above A shows (λi. SUP X :A. count X i) ∈ multiset unfolding multiset-def proof have {i. Sup ((λX . count X i) ‘A) > 0 } ⊆ (S X ∈A. {i. 0 < count X i}) proof safe fix i assume pos:(SUP X :A. count X i) > 0 show i ∈ (S X ∈A. {i. 0 < count X i}) proof (rule ccontr) assume i ∈/ (S X ∈A. {i. 0 < count X i}) hence ∀ X ∈A. count X i ≤ 0 by (auto simp: count-eq-zero-iff ) with assms have (SUP X :A. count X i) ≤ 0 by (intro cSup-least bdd-above-multiset-imp-bdd-above-count) auto with pos show False by simp qed qed moreover from assms have finite ... by (rule bdd-above-multiset-imp-finite-support) ultimately show finite {i. Sup ((λX . count X i) ‘A) > 0 } by (rule finite-subset) qed lemma count-Sup-multiset-nonempty: assumes A 6= {} subset-mset.bdd-above A shows count (Sup A) x = (SUP X :A. count X x) using assms by (simp add: Sup-multiset-def Abs-multiset-inverse Sup-multiset-in-multiset) interpretation subset-mset: conditionally-complete-lattice Inf Sup op ∩# op ⊆# op ⊂# op ∪# proof fix X :: 0a multiset and A assume X ∈ A show Inf A ⊆# X

164 proof (rule mset-subset-eqI ) fix x from hX ∈ Ai have A 6= {} by auto hence count (Inf A) x = (INF X :A. count X x) by (simp add: count-Inf-multiset-nonempty) also from hX ∈ Ai have ... ≤ count X x by (intro cInf-lower) simp-all finally show count (Inf A) x ≤ count X x . qed next fix X :: 0a multiset and A assume nonempty: A 6= {} and le: VY . Y ∈ A =⇒ X ⊆# Y show X ⊆# Inf A proof (rule mset-subset-eqI ) fix x from nonempty have count X x ≤ (INF X :A. count X x) by (intro cInf-greatest)(auto intro: mset-subset-eq-count le) also from nonempty have ... = count (Inf A) x by (simp add: count-Inf-multiset-nonempty) finally show count X x ≤ count (Inf A) x . qed next fix X :: 0a multiset and A assume X : X ∈ A and bdd: subset-mset.bdd-above A show X ⊆# Sup A proof (rule mset-subset-eqI ) fix x from X have A 6= {} by auto have count X x ≤ (SUP X :A. count X x) by (intro cSUP-upper X bdd-above-multiset-imp-bdd-above-count bdd) also from count-Sup-multiset-nonempty[OF hA 6= {}i bdd] have (SUP X :A. count X x) = count (Sup A) x by simp finally show count X x ≤ count (Sup A) x . qed next fix X :: 0a multiset and A assume nonempty: A 6= {} and ge: VY . Y ∈ A =⇒ Y ⊆# X from ge have bdd: subset-mset.bdd-above A by (rule subset-mset.bdd-aboveI [of -X ]) show Sup A ⊆# X proof (rule mset-subset-eqI ) fix x from count-Sup-multiset-nonempty[OF hA 6= {}i bdd] have count (Sup A) x = (SUP X :A. count X x) . also from nonempty have ... ≤ count X x by (intro cSup-least)(auto intro: mset-subset-eq-count ge) finally show count (Sup A) x ≤ count X x . qed qed

165 lemma set-mset-Inf : assumes A 6= {} shows set-mset (Inf A) = (T X ∈A. set-mset X ) proof safe fix x X assume x ∈# Inf A X ∈ A hence nonempty: A 6= {} by (auto simp: Inf-multiset-empty) from hx ∈# Inf Ai have {#x#} ⊆# Inf A by auto also from hX ∈ Ai have ... ⊆# X by (rule subset-mset.cInf-lower) simp-all finally show x ∈# X by simp next fix x assume x: x ∈ (T X ∈A. set-mset X ) hence {#x#} ⊆# X if X ∈ A for X using that by auto from assms and this have {#x#} ⊆# Inf A by (rule subset-mset.cInf-greatest) thus x ∈# Inf A by simp qed lemma in-Inf-multiset-iff : assumes A 6= {} shows x ∈# Inf A ←→ (∀ X ∈A. x ∈# X ) proof − from assms have set-mset (Inf A) = (T X ∈A. set-mset X ) by (rule set-mset-Inf ) also have x ∈ ... ←→ (∀ X ∈A. x ∈# X ) by simp finally show ?thesis . qed lemma in-Inf-multisetD: x ∈# Inf A =⇒ X ∈ A =⇒ x ∈# X by (subst (asm) in-Inf-multiset-iff ) auto lemma set-mset-Sup: assumes subset-mset.bdd-above A shows set-mset (Sup A) = (S X ∈A. set-mset X ) proof safe fix x assume x ∈# Sup A hence nonempty: A 6= {} by (auto simp: Sup-multiset-empty) show x ∈ (S X ∈A. set-mset X ) proof (rule ccontr) assume x: x ∈/ (S X ∈A. set-mset X ) have count X x ≤ count (Sup A) x if X ∈ A for X x using that by (intro mset-subset-eq-count subset-mset.cSup-upper assms) with x have X ⊆# Sup A − {#x#} if X ∈ A for X using that by (auto simp: subseteq-mset-def algebra-simps not-in-iff ) hence Sup A ⊆# Sup A − {#x#} by (intro subset-mset.cSup-least nonempty) with hx ∈# Sup Ai show False by (auto simp: subseteq-mset-def count-greater-zero-iff [symmetric] simp del: count-greater-zero-iff dest!: spec[of - x]) qed next fix x X assume x ∈ set-mset X X ∈ A hence {#x#} ⊆# X by auto

166 also have X ⊆# Sup A by (intro subset-mset.cSup-upper hX ∈ Ai assms) finally show x ∈ set-mset (Sup A) by simp qed lemma in-Sup-multiset-iff : assumes subset-mset.bdd-above A shows x ∈# Sup A ←→ (∃ X ∈A. x ∈# X ) proof − from assms have set-mset (Sup A) = (S X ∈A. set-mset X ) by (rule set-mset-Sup) also have x ∈ ... ←→ (∃ X ∈A. x ∈# X ) by simp finally show ?thesis . qed lemma in-Sup-multisetD: assumes x ∈# Sup A shows ∃ X ∈A. x ∈# X proof − have subset-mset.bdd-above A by (rule ccontr)(insert assms, simp-all add: Sup-multiset-unbounded) with assms show ?thesis by (simp add: in-Sup-multiset-iff ) qed interpretation subset-mset: distrib-lattice op ∩# op ⊆# op ⊂# op ∪# proof fix ABC :: 0a multiset show A ∪#(B ∩# C ) = A ∪# B ∩#(A ∪# C ) by (intro multiset-eqI ) simp-all qed

31.4.3 Filter (with comprehension syntax)

Multiset comprehension lift-definition filter-mset :: ( 0a ⇒ bool) ⇒ 0a multiset ⇒ 0a multiset is λPM . λx. if P x then M x else 0 by (rule filter-preserves-multiset) syntax (ASCII ) -MCollect :: pttrn ⇒ 0a multiset ⇒ bool ⇒ 0a multiset ((1 {#- :# -./ -#})) syntax -MCollect :: pttrn ⇒ 0a multiset ⇒ bool ⇒ 0a multiset ((1 {#- ∈# -./ -#})) translations {#x ∈# M . P#} == CONST filter-mset (λx. P) M lemma count-filter-mset [simp]: count (filter-mset P M ) a = (if P a then count M a else 0 ) by (simp add: filter-mset.rep-eq) lemma set-mset-filter [simp]: set-mset (filter-mset P M ) = {a ∈ set-mset M . P a}

167 by (simp only: set-eq-iff count-greater-zero-iff [symmetric] count-filter-mset) simp lemma filter-empty-mset [simp]: filter-mset P {#} = {#} by (rule multiset-eqI ) simp lemma filter-single-mset: filter-mset P {#x#} = (if P x then {#x#} else {#}) by (rule multiset-eqI ) simp lemma filter-union-mset [simp]: filter-mset P (M + N ) = filter-mset P M + filter-mset P N by (rule multiset-eqI ) simp lemma filter-diff-mset [simp]: filter-mset P (M − N ) = filter-mset P M − filter-mset PN by (rule multiset-eqI ) simp lemma filter-inter-mset [simp]: filter-mset P (M ∩# N ) = filter-mset P M ∩# filter-mset P N by (rule multiset-eqI ) simp lemma filter-sup-mset[simp]: filter-mset P (A ∪# B) = filter-mset P A ∪# filter-mset PB by (rule multiset-eqI ) simp lemma filter-mset-add-mset [simp]: filter-mset P (add-mset x A) = (if P x then add-mset x (filter-mset P A) else filter-mset P A) by (auto simp: multiset-eq-iff ) lemma multiset-filter-subset[simp]: filter-mset f M ⊆# M by (simp add: mset-subset-eqI ) lemma multiset-filter-mono: assumes A ⊆# B shows filter-mset f A ⊆# filter-mset f B proof − from assms[unfolded mset-subset-eq-exists-conv] obtain C where B: B = A + C by auto show ?thesis unfolding B by auto qed lemma filter-mset-eq-conv: filter-mset P M = N ←→ N ⊆# M ∧ (∀ b∈#N . P b) ∧ (∀ a∈#M − N . ¬ P a) (is ?P ←→ ?Q) proof assume ?P then show ?Q by auto (simp add: multiset-eq-iff in-diff-count) next assume ?Q then obtain Q where M : M = N + Q

168 by (auto simp add: mset-subset-eq-exists-conv) then have MN : M − N = Q by simp show ?P proof (rule multiset-eqI ) fix a from h?Q i MN have ∗: ¬ P a =⇒ a ∈/# N P a =⇒ a ∈/# Q by auto show count (filter-mset P M ) a = count N a proof (cases a ∈# M ) case True with ∗ show ?thesis by (simp add: not-in-iff M ) next case False then have count M a = 0 by (simp add: not-in-iff ) with M show ?thesis by simp qed qed qed lemma filter-filter-mset: filter-mset P (filter-mset Q M ) = {#x ∈# M . Q x ∧ P x#} by (auto simp: multiset-eq-iff ) lemma filter-mset-True[simp]: {#y ∈# M . True#} = M and filter-mset-False[simp]: {#y ∈# M . False#} = {#} by (auto simp: multiset-eq-iff )

31.4.4 Size definition wcount where wcount f M = (λx. count M x ∗ Suc (f x)) lemma wcount-union: wcount f (M + N ) a = wcount f M a + wcount f N a by (auto simp: wcount-def add-mult-distrib) lemma wcount-add-mset: wcount f (add-mset x M ) a = (if x = a then Suc (f a) else 0 ) + wcount f M a unfolding add-mset-add-single[of - M ] wcount-union by (auto simp: wcount-def ) definition size-multiset :: ( 0a ⇒ nat) ⇒ 0a multiset ⇒ nat where size-multiset f M = sum (wcount f M )(set-mset M ) lemmas size-multiset-eq = size-multiset-def [unfolded wcount-def ] instantiation multiset :: (type) size begin definition size-multiset where

169 size-multiset-overloaded-def : size-multiset = Multiset.size-multiset (λ-. 0 ) instance .. end lemmas size-multiset-overloaded-eq = size-multiset-overloaded-def [THEN fun-cong, unfolded size-multiset-eq, simplified] lemma size-multiset-empty [simp]: size-multiset f {#} = 0 by (simp add: size-multiset-def ) lemma size-empty [simp]: size {#} = 0 by (simp add: size-multiset-overloaded-def ) lemma size-multiset-single : size-multiset f {#b#} = Suc (f b) by (simp add: size-multiset-eq) lemma size-single: size {#b#} = 1 by (simp add: size-multiset-overloaded-def size-multiset-single) lemma sum-wcount-Int: finite A =⇒ sum (wcount f N )(A ∩ set-mset N ) = sum (wcount f N ) A by (induct rule: finite-induct) (simp-all add: Int-insert-left wcount-def count-eq-zero-iff ) lemma size-multiset-union [simp]: size-multiset f (M + N :: 0a multiset) = size-multiset f M + size-multiset f N apply (simp add: size-multiset-def sum-Un-nat sum.distrib sum-wcount-Int wcount-union) apply (subst Int-commute) apply (simp add: sum-wcount-Int) done lemma size-multiset-add-mset [simp]: size-multiset f (add-mset a M ) = Suc (f a) + size-multiset f M unfolding add-mset-add-single[of - M ] size-multiset-union by (auto simp: size-multiset-single) lemma size-add-mset [simp]: size (add-mset a A) = Suc (size A) by (simp add: size-multiset-overloaded-def wcount-add-mset) lemma size-union [simp]: size (M + N :: 0a multiset) = size M + size N by (auto simp add: size-multiset-overloaded-def ) lemma size-multiset-eq-0-iff-empty [iff ]: size-multiset f M = 0 ←→ M = {#} by (auto simp add: size-multiset-eq count-eq-zero-iff ) lemma size-eq-0-iff-empty [iff ]: (size M = 0 ) = (M = {#}) by (auto simp add: size-multiset-overloaded-def )

170 lemma nonempty-has-size:(S 6= {#}) = (0 < size S) by (metis gr0I gr-implies-not0 size-empty size-eq-0-iff-empty) lemma size-eq-Suc-imp-elem: size M = Suc n =⇒ ∃ a. a ∈# M apply (unfold size-multiset-overloaded-eq) apply (drule sum-SucD) apply auto done lemma size-eq-Suc-imp-eq-union: assumes size M = Suc n shows ∃ a N . M = add-mset a N proof − from assms obtain a where a ∈# M by (erule size-eq-Suc-imp-elem [THEN exE]) then have M = add-mset a (M − {#a#}) by simp then show ?thesis by blast qed lemma size-mset-mono: fixes AB :: 0a multiset assumes A ⊆# B shows size A ≤ size B proof − from assms[unfolded mset-subset-eq-exists-conv] obtain C where B: B = A + C by auto show ?thesis unfolding B by (induct C ) auto qed lemma size-filter-mset-lesseq[simp]: size (filter-mset f M ) ≤ size M by (rule size-mset-mono[OF multiset-filter-subset]) lemma size-Diff-submset: M ⊆# M 0 =⇒ size (M 0 − M ) = size M 0 − size(M :: 0a multiset) by (metis add-diff-cancel-left 0 size-union mset-subset-eq-exists-conv)

31.5 Induction and case splits theorem multiset-induct [case-names empty add, induct type: multiset]: assumes empty: P {#} assumes add: Vx M . PM =⇒ P (add-mset x M ) shows PM proof (induct n ≡ size M arbitrary: M ) case 0 thus PM by (simp add: empty) next case (Suc k) obtain N x where M = add-mset x N using hSuc k = size M i [symmetric] using size-eq-Suc-imp-eq-union by fast

171 with Suc add show PM by simp qed lemma multi-nonempty-split: M 6= {#} =⇒ ∃ A a. M = add-mset a A by (induct M ) auto lemma multiset-cases [cases type]: obtains (empty) M = {#} | (add) x N where M = add-mset x N by (induct M ) simp-all lemma multi-drop-mem-not-eq: c ∈# B =⇒ B − {#c#}= 6 B by (cases B = {#})(auto dest: multi-member-split) lemma multiset-partition: M = {# x∈#M . P x #} + {# x∈#M . ¬ P x #} apply (subst multiset-eq-iff ) apply auto done lemma mset-subset-size:(A:: 0a multiset) ⊂# B =⇒ size A < size B proof (induct A arbitrary: B) case (empty M ) then have M 6= {#} by (simp add: subset-mset.zero-less-iff-neq-zero) then obtain M 0 x where M = add-mset x M 0 by (blast dest: multi-nonempty-split) then show ?case by simp next case (add x S T ) have IH : VB. S ⊂# B =⇒ size S < size B by fact have SxsubT : add-mset x S ⊂# T by fact then have x ∈# T and S ⊂# T by (auto dest: mset-subset-insertD) then obtain T 0 where T : T = add-mset x T 0 by (blast dest: multi-member-split) then have S ⊂# T 0 using SxsubT by simp then have size S < size T 0 using IH by simp then show ?case using T by simp qed lemma size-1-singleton-mset: size M = 1 =⇒ ∃ a. M = {#a#} by (cases M ) auto

31.5.1 Strong induction and subset induction for multisets

Well-foundedness of strict subset relation lemma wf-subset-mset-rel: wf {(M , N :: 0a multiset). M ⊂# N } apply (rule wf-measure [THEN wf-subset, where f1 =size]) apply (clarsimp simp: measure-def inv-image-def mset-subset-size)

172 done lemma full-multiset-induct [case-names less]: assumes ih: VB. ∀ (A:: 0a multiset). A ⊂# B −→ PA =⇒ PB shows PB apply (rule wf-subset-mset-rel [THEN wf-induct]) apply (rule ih, auto) done lemma multi-subset-induct [consumes 2 , case-names empty add]: assumes F ⊆# A and empty: P {#} and insert: Va F . a ∈# A =⇒ PF =⇒ P (add-mset a F ) shows PF proof − from hF ⊆# Ai show ?thesis proof (induct F ) show P {#} by fact next fix x F assume P: F ⊆# A =⇒ PF and i: add-mset x F ⊆# A show P (add-mset x F ) proof (rule insert) from i show x ∈# A by (auto dest: mset-subset-eq-insertD) from i have F ⊆# A by (auto dest: mset-subset-eq-insertD) with P show PF . qed qed qed

31.6 The fold combinator definition fold-mset :: ( 0a ⇒ 0b ⇒ 0b) ⇒ 0b ⇒ 0a multiset ⇒ 0b where fold-mset f s M = Finite-Set.fold (λx. f x ˆˆ count M x) s (set-mset M ) lemma fold-mset-empty [simp]: fold-mset f s {#} = s by (simp add: fold-mset-def ) context comp-fun-commute begin lemma fold-mset-add-mset [simp]: fold-mset f s (add-mset x M ) = f x (fold-mset f s M ) proof − interpret mset: comp-fun-commute λy. f y ˆˆ count M y by (fact comp-fun-commute-funpow) interpret mset-union: comp-fun-commute λy. f y ˆˆ count (add-mset x M ) y

173 by (fact comp-fun-commute-funpow) show ?thesis proof (cases x ∈ set-mset M ) case False then have ∗: count (add-mset x M ) x = 1 by (simp add: not-in-iff ) from False have Finite-Set.fold (λy. f y ˆˆ count (add-mset x M ) y) s (set-mset M ) = Finite-Set.fold (λy. f y ˆˆ count M y) s (set-mset M ) by (auto intro!: Finite-Set.fold-cong comp-fun-commute-funpow) with False ∗ show ?thesis by (simp add: fold-mset-def del: count-add-mset) next case True define N where N = set-mset M − {x} from N-def True have ∗: set-mset M = insert x N x ∈/ N finite N by auto then have Finite-Set.fold (λy. f y ˆˆ count (add-mset x M ) y) s N = Finite-Set.fold (λy. f y ˆˆ count M y) s N by (auto intro!: Finite-Set.fold-cong comp-fun-commute-funpow) with ∗ show ?thesis by (simp add: fold-mset-def del: count-add-mset) simp qed qed corollary fold-mset-single: fold-mset f s {#x#} = f x s by simp lemma fold-mset-fun-left-comm: f x (fold-mset f s M ) = fold-mset f (f x s) M by (induct M )(simp-all add: fun-left-comm) lemma fold-mset-union [simp]: fold-mset f s (M + N ) = fold-mset f (fold-mset f s M ) N by (induct M )(simp-all add: fold-mset-fun-left-comm) lemma fold-mset-fusion: assumes comp-fun-commute g and ∗: Vx y. h (g x y) = f x (h y) shows h (fold-mset g w A) = fold-mset f (h w) A proof − interpret comp-fun-commute g by (fact assms) from ∗ show ?thesis by (induct A) auto qed end lemma union-fold-mset-add-mset: A + B = fold-mset add-mset A B proof − interpret comp-fun-commute add-mset by standard auto show ?thesis

174 by (induction B) auto qed A note on code generation: When defining some function containing a sub- term fold-mset F, code generation is not automatic. When interpreting locale left-commutative with F, the would be code thms for fold-mset be- come thms like fold-mset F z {#} = z where F is not a pattern but contains defined symbols, i.e. is not a code thm. Hence a separate constant with its own code thms needs to be introduced for F. See the image operator below.

31.7 Image definition image-mset :: ( 0a ⇒ 0b) ⇒ 0a multiset ⇒ 0b multiset where image-mset f = fold-mset (add-mset ◦ f ) {#} lemma comp-fun-commute-mset-image: comp-fun-commute (add-mset ◦ f ) proof qed (simp add: fun-eq-iff ) lemma image-mset-empty [simp]: image-mset f {#} = {#} by (simp add: image-mset-def ) lemma image-mset-single: image-mset f {#x#} = {#f x#} proof − interpret comp-fun-commute add-mset ◦ f by (fact comp-fun-commute-mset-image) show ?thesis by (simp add: image-mset-def ) qed lemma image-mset-union [simp]: image-mset f (M + N ) = image-mset f M + image-mset f N proof − interpret comp-fun-commute add-mset ◦ f by (fact comp-fun-commute-mset-image) show ?thesis by (induct N )(simp-all add: image-mset-def ) qed corollary image-mset-add-mset [simp]: image-mset f (add-mset a M ) = add-mset (f a)(image-mset f M ) unfolding image-mset-union add-mset-add-single[of a M ] by (simp add: image-mset-single) lemma set-image-mset [simp]: set-mset (image-mset f M ) = image f (set-mset M ) by (induct M ) simp-all lemma size-image-mset [simp]: size (image-mset f M ) = size M by (induct M ) simp-all lemma image-mset-is-empty-iff [simp]: image-mset f M = {#} ←→ M = {#}

175 by (cases M ) auto lemma image-mset-If : image-mset (λx. if P x then f x else g x) A = image-mset f (filter-mset P A) + image-mset g (filter-mset (λx. ¬P x) A) by (induction A) auto lemma image-mset-Diff : assumes B ⊆# A shows image-mset f (A − B) = image-mset f A − image-mset f B proof − have image-mset f (A − B + B) = image-mset f (A − B) + image-mset f B by simp also from assms have A − B + B = A by (simp add: subset-mset.diff-add) finally show ?thesis by simp qed lemma count-image-mset: count (image-mset f A) x = (P y∈f −‘ {x} ∩ set-mset A. count A y) proof (induction A) case empty then show ?case by simp next case (add x A) moreover have ∗:(if x = y then Suc n else n) = n + (if x = y then 1 else 0 ) for n y by simp ultimately show ?case by (auto simp: sum.distrib sum.delta 0 intro!: sum.mono-neutral-left) qed lemma image-mset-subseteq-mono: A ⊆# B =⇒ image-mset f A ⊆# image-mset f B by (metis image-mset-union subset-mset.le-iff-add) syntax (ASCII ) -comprehension-mset :: 0a ⇒ 0b ⇒ 0b multiset ⇒ 0a multiset (({#-/. - :# -#})) syntax -comprehension-mset :: 0a ⇒ 0b ⇒ 0b multiset ⇒ 0a multiset (({#-/. - ∈# -#})) translations {#e. x ∈# M #} CONST image-mset (λx. e) M syntax (ASCII ) -comprehension-mset 0 :: 0a ⇒ 0b ⇒ 0b multiset ⇒ bool ⇒ 0a multiset (({#-/ | - :# -./ -#})) syntax -comprehension-mset 0 :: 0a ⇒ 0b ⇒ 0b multiset ⇒ bool ⇒ 0a multiset (({#-/ | - ∈# -./ -#}))

176 translations {#e | x∈#M . P#} * {#e. x ∈# {# x∈#M . P#}#}

This allows to write not just filters like {#x ∈# M . x < c#} but also images like {#x + x. x ∈# M #} and {#x+x|x∈#M . x

31.8 Further conversions primrec mset :: 0a list ⇒ 0a multiset where mset [] = {#} | mset (a # x) = add-mset a (mset x) lemma in-multiset-in-set: x ∈# mset xs ←→ x ∈ set xs

177 by (induct xs) simp-all lemma count-mset: count (mset xs) x = length (filter (λy. x = y) xs) by (induct xs) simp-all lemma mset-zero-iff [simp]: (mset x = {#}) = (x = []) by (induct x) auto lemma mset-zero-iff-right[simp]: ({#} = mset x) = (x = []) by (induct x) auto lemma mset-single-iff [iff ]: mset xs = {#x#} ←→ xs = [x] by (cases xs) auto lemma mset-single-iff-right[iff ]: {#x#} = mset xs ←→ xs = [x] by (cases xs) auto lemma set-mset-mset[simp]: set-mset (mset xs) = set xs by (induct xs) auto lemma set-mset-comp-mset [simp]: set-mset ◦ mset = set by (simp add: fun-eq-iff ) lemma size-mset [simp]: size (mset xs) = length xs by (induct xs) simp-all lemma mset-append [simp]: mset (xs @ ys) = mset xs + mset ys by (induct xs arbitrary: ys) auto lemma mset-filter: mset (filter P xs) = {#x ∈# mset xs. P x #} by (induct xs) simp-all lemma mset-rev [simp]: mset (rev xs) = mset xs by (induct xs) simp-all lemma surj-mset: surj mset apply (unfold surj-def ) apply (rule allI ) apply (rule-tac M = y in multiset-induct) apply auto apply (rule-tac x = x # xa in exI ) apply auto done lemma distinct-count-atmost-1 : distinct x = (∀ a. count (mset x) a = (if a ∈ set x then 1 else 0 )) proof (induct x)

178 case Nil then show ?case by simp next case (Cons x xs) show ?case (is ?lhs ←→ ?rhs) proof assume ?lhs then show ?rhs using Cons by simp next assume ?rhs then have x ∈/ set xs by (simp split: if-splits) moreover from h?rhs i have (∀ a. count (mset xs) a = (if a ∈ set xs then 1 else 0 )) by (auto split: if-splits simp add: count-eq-zero-iff ) ultimately show ?lhs using Cons by simp qed qed lemma mset-eq-setD: assumes mset xs = mset ys shows set xs = set ys proof − from assms have set-mset (mset xs) = set-mset (mset ys) by simp then show ?thesis by simp qed lemma set-eq-iff-mset-eq-distinct: distinct x =⇒ distinct y =⇒ (set x = set y) = (mset x = mset y) by (auto simp: multiset-eq-iff distinct-count-atmost-1 ) lemma set-eq-iff-mset-remdups-eq: (set x = set y) = (mset (remdups x) = mset (remdups y)) apply (rule iffI ) apply (simp add: set-eq-iff-mset-eq-distinct[THEN iffD1 ]) apply (drule distinct-remdups [THEN distinct-remdups [THEN set-eq-iff-mset-eq-distinct [THEN iffD2 ]]]) apply simp done lemma mset-compl-union [simp]: mset [x←xs. P x] + mset [x←xs. ¬P x] = mset xs by (induct xs) auto lemma nth-mem-mset: i < length ls =⇒ (ls ! i) ∈# mset ls proof (induct ls arbitrary: i) case Nil then show ?case by simp next case Cons then show ?case by (cases i) auto

179 qed lemma mset-remove1 [simp]: mset (remove1 a xs) = mset xs − {#a#} by (induct xs)(auto simp add: multiset-eq-iff ) lemma mset-eq-length: assumes mset xs = mset ys shows length xs = length ys using assms by (metis size-mset) lemma mset-eq-length-filter: assumes mset xs = mset ys shows length (filter (λx. z = x) xs) = length (filter (λy. z = y) ys) using assms by (metis count-mset) lemma fold-multiset-equiv: assumes f : Vx y. x ∈ set xs =⇒ y ∈ set xs =⇒ f x ◦ f y = f y ◦ f x and equiv: mset xs = mset ys shows List.fold f xs = List.fold f ys using f equiv [symmetric] proof (induct xs arbitrary: ys) case Nil then show ?case by simp next case (Cons x xs) then have ∗: set ys = set (x # xs) by (blast dest: mset-eq-setD) have Vx y. x ∈ set ys =⇒ y ∈ set ys =⇒ f x ◦ f y = f y ◦ f x by (rule Cons.prems(1 )) (simp-all add: ∗) moreover from ∗ have x ∈ set ys by simp ultimately have List.fold f ys = List.fold f (remove1 x ys) ◦ f x by (fact fold-remove1-split) moreover from Cons.prems have List.fold f xs = List.fold f (remove1 x ys) by (auto intro: Cons.hyps) ultimately show ?case by simp qed lemma mset-insort [simp]: mset (insort x xs) = add-mset x (mset xs) by (induct xs) simp-all lemma mset-map[simp]: mset (map f xs) = image-mset f (mset xs) by (induct xs) simp-all global-interpretation mset-set: folding add-mset {#} defines mset-set = folding.F add-mset {#} by standard (simp add: fun-eq-iff ) lemma count-mset-set [simp]:

180 finite A =⇒ x ∈ A =⇒ count (mset-set A) x = 1 (is PROP ?P) ¬ finite A =⇒ count (mset-set A) x = 0 (is PROP ?Q) x ∈/ A =⇒ count (mset-set A) x = 0 (is PROP ?R) proof − have ∗: count (mset-set A) x = 0 if x ∈/ A for A proof (cases finite A) case False then show ?thesis by simp next case True from True hx ∈/ Ai show ?thesis by (induct A) auto qed then show PROP ?P PROP ?Q PROP ?R by (auto elim!: Set.set-insert) qed — TODO: maybe define mset-set also in terms of Abs-multiset lemma elem-mset-set[simp, intro]: finite A =⇒ x ∈# mset-set A ←→ x ∈ A by (induct A rule: finite-induct) simp-all lemma mset-set-Union: finite A =⇒ finite B =⇒ A ∩ B = {} =⇒ mset-set (A ∪ B) = mset-set A + mset-set B by (induction A rule: finite-induct) auto lemma filter-mset-mset-set [simp]: finite A =⇒ filter-mset P (mset-set A) = mset-set {x∈A. P x} proof (induction A rule: finite-induct) case (insert x A) from insert.hyps have filter-mset P (mset-set (insert x A)) = filter-mset P (mset-set A) + mset-set (if P x then {x} else {}) by simp also have filter-mset P (mset-set A) = mset-set {x∈A. P x} by (rule insert.IH ) also from insert.hyps have ... + mset-set (if P x then {x} else {}) = mset-set ({x ∈ A. P x} ∪ (if P x then {x} else {})) (is - = mset-set ?A) by (intro mset-set-Union [symmetric]) simp-all also from insert.hyps have ?A = {y∈insert x A. P y} by auto finally show ?case . qed simp-all lemma mset-set-Diff : assumes finite A B ⊆ A shows mset-set (A − B) = mset-set A − mset-set B proof − from assms have mset-set ((A − B) ∪ B) = mset-set (A − B) + mset-set B by (intro mset-set-Union)(auto dest: finite-subset) also from assms have A − B ∪ B = A by blast finally show ?thesis by simp qed

181 lemma mset-set-set: distinct xs =⇒ mset-set (set xs) = mset xs by (induction xs) simp-all context linorder begin definition sorted-list-of-multiset :: 0a multiset ⇒ 0a list where sorted-list-of-multiset M = fold-mset insort [] M lemma sorted-list-of-multiset-empty [simp]: sorted-list-of-multiset {#} = [] by (simp add: sorted-list-of-multiset-def ) lemma sorted-list-of-multiset-singleton [simp]: sorted-list-of-multiset {#x#} = [x] proof − interpret comp-fun-commute insort by (fact comp-fun-commute-insort) show ?thesis by (simp add: sorted-list-of-multiset-def ) qed lemma sorted-list-of-multiset-insert [simp]: sorted-list-of-multiset (add-mset x M ) = List.insort x (sorted-list-of-multiset M ) proof − interpret comp-fun-commute insort by (fact comp-fun-commute-insort) show ?thesis by (simp add: sorted-list-of-multiset-def ) qed end lemma mset-sorted-list-of-multiset [simp]: mset (sorted-list-of-multiset M ) = M by (induct M ) simp-all lemma sorted-list-of-multiset-mset [simp]: sorted-list-of-multiset (mset xs) = sort xs by (induct xs) simp-all lemma finite-set-mset-mset-set[simp]: finite A =⇒ set-mset (mset-set A) = A by (induct A rule: finite-induct) simp-all lemma mset-set-empty-iff : mset-set A = {#} ←→ A = {} ∨ infinite A using finite-set-mset-mset-set by fastforce lemma infinite-set-mset-mset-set: ¬ finite A =⇒ set-mset (mset-set A) = {} by simp

182 lemma set-sorted-list-of-multiset [simp]: set (sorted-list-of-multiset M ) = set-mset M by (induct M )(simp-all add: set-insort) lemma sorted-list-of-mset-set [simp]: sorted-list-of-multiset (mset-set A) = sorted-list-of-set A by (cases finite A)(induct A rule: finite-induct, simp-all) lemma mset-upt [simp]: mset [m..

31.9 More properties of the replicate and repeat operations lemma in-replicate-mset[simp]: x ∈# replicate-mset n y ←→ n > 0 ∧ x = y unfolding replicate-mset-def by (induct n) auto lemma set-mset-replicate-mset-subset[simp]: set-mset (replicate-mset n x) = (if n = 0 then {} else {x})

183 by (auto split: if-splits) lemma size-replicate-mset[simp]: size (replicate-mset n M ) = n by (induct n, simp-all) lemma count-le-replicate-mset-subset-eq: n ≤ count M x ←→ replicate-mset n x ⊆# M by (auto simp add: mset-subset-eqI )(metis count-replicate-mset subseteq-mset-def ) lemma filter-eq-replicate-mset: {#y ∈# D. y = x#} = replicate-mset (count D x) x by (induct D) simp-all lemma replicate-count-mset-eq-filter-eq: replicate (count (mset xs) k) k = filter (HOL.eq k) xs by (induct xs) auto lemma replicate-mset-eq-empty-iff [simp]: replicate-mset n a = {#} ←→ n = 0 by (induct n) simp-all lemma replicate-mset-eq-iff : replicate-mset m a = replicate-mset n b ←→ m = 0 ∧ n = 0 ∨ m = n ∧ a = b by (auto simp add: multiset-eq-iff ) lemma repeat-mset-cancel1 : repeat-mset a A = repeat-mset a B ←→ A = B ∨ a = 0 by (auto simp: multiset-eq-iff ) lemma repeat-mset-cancel2 : repeat-mset a A = repeat-mset b A ←→ a = b ∨ A = {#} by (auto simp: multiset-eq-iff ) lemma repeat-mset-eq-empty-iff : repeat-mset n A = {#} ←→ n = 0 ∨ A = {#} by (cases n) auto lemma image-replicate-mset [simp]: image-mset f (replicate-mset n a) = replicate-mset n (f a) by (induct n) simp-all

31.10 Big operators locale comm-monoid-mset = comm-monoid begin interpretation comp-fun-commute f by standard (simp add: fun-eq-iff left-commute)

184 interpretation comp?: comp-fun-commute f ◦ g by (fact comp-comp-fun-commute) context begin definition F :: 0a multiset ⇒ 0a where eq-fold: FM = fold-mset f 1 M lemma empty [simp]: F {#} = 1 by (simp add: eq-fold) lemma singleton [simp]: F {#x#} = x proof − interpret comp-fun-commute by standard (simp add: fun-eq-iff left-commute) show ?thesis by (simp add: eq-fold) qed lemma union [simp]: F (M + N ) = FM ∗ FN proof − interpret comp-fun-commute f by standard (simp add: fun-eq-iff left-commute) show ?thesis by (induct N )(simp-all add: left-commute eq-fold) qed lemma add-mset [simp]: F (add-mset x N ) = x ∗ FN unfolding add-mset-add-single[of x N ] union by (simp add: ac-simps) lemma insert [simp]: shows F (image-mset g (add-mset x A)) = g x ∗ F (image-mset g A) by (simp add: eq-fold) lemma remove: assumes x ∈# A shows FA = x ∗ F (A − {#x#}) using multi-member-split[OF assms] by auto lemma neutral: ∀ x∈#A. x = 1 =⇒ FA = 1 by (induct A) simp-all lemma neutral-const [simp]: F (image-mset (λ-. 1) A) = 1 by (simp add: neutral) private lemma F-image-mset-product: F {#g x j ∗ F {#g i j . i ∈# A#}. j ∈# B#} =

185 F (image-mset (g x) B) ∗ F {#F {#g i j . i ∈# A#}. j ∈# B#} by (induction B)(simp-all add: left-commute semigroup.assoc semigroup-axioms) lemma commute: F (image-mset (λi. F (image-mset (g i) B)) A) = F (image-mset (λj . F (image-mset (λi. g i j ) A)) B) apply (induction A, simp) apply (induction B, auto simp add: F-image-mset-product ac-simps) done lemma distrib: F (image-mset (λx. g x ∗ h x) A) = F (image-mset g A) ∗ F (image-mset h A) by (induction A)(auto simp: ac-simps) lemma union-disjoint: A ∩# B = {#} =⇒ F (image-mset g (A ∪# B)) = F (image-mset g A) ∗ F (image-mset g B) by (induction A)(auto simp: ac-simps) end end lemma comp-fun-commute-plus-mset[simp]: comp-fun-commute (op + :: 0a multi- set ⇒ - ⇒ -) by standard (simp add: add-ac comp-def ) declare comp-fun-commute.fold-mset-add-mset[OF comp-fun-commute-plus-mset, simp] lemma in-mset-fold-plus-iff [iff ]: x ∈# fold-mset (op +) M NN ←→ x ∈# M ∨ (∃ N . N ∈# NN ∧ x ∈# N ) by (induct NN ) auto context comm-monoid-add begin sublocale sum-mset: comm-monoid-mset plus 0 defines sum-mset = sum-mset.F .. lemma (in semiring-1 ) sum-mset-replicate-mset [simp]: sum-mset (replicate-mset n a) = of-nat n ∗ a by (induct n)(simp-all add: algebra-simps) lemma sum-unfold-sum-mset: sum f A = sum-mset (image-mset f (mset-set A)) by (cases finite A)(induct A rule: finite-induct, simp-all) lemma sum-mset-delta: sum-mset (image-mset (λx. if x = y then c else 0 ) A) = c ∗ count A y

186 by (induction A) simp-all lemma sum-mset-delta 0: sum-mset (image-mset (λx. if y = x then c else 0 ) A) = c ∗ count A y by (induction A) simp-all end lemma of-nat-sum-mset [simp]: of-nat (sum-mset M ) = sum-mset (image-mset of-nat M ) by (induction M ) auto lemma sum-mset-0-iff [simp]: sum-mset M = (0 :: 0a::canonically-ordered-monoid-add) ←→ (∀ x ∈ set-mset M . x = 0 ) by(induction M ) auto lemma sum-mset-diff : fixes MN :: ( 0a :: ordered-cancel-comm-monoid-diff ) multiset shows N ⊆# M =⇒ sum-mset (M − N ) = sum-mset M − sum-mset N by (metis add-diff-cancel-right 0 sum-mset.union subset-mset.diff-add) lemma size-eq-sum-mset: size M = sum-mset (image-mset (λ-. 1 ) M ) proof (induct M ) case empty then show ?case by simp next case (add x M ) then show ?case by (cases x ∈ set-mset M ) (simp-all add: size-multiset-overloaded-eq not-in-iff sum.If-cases Diff-eq[symmetric] sum.remove) qed lemma size-mset-set [simp]: size (mset-set A) = card A by (simp only: size-eq-sum-mset card-eq-sum sum-unfold-sum-mset) lemma sum-mset-sum-list: sum-mset (mset xs) = sum-list xs by (induction xs) auto syntax (ASCII ) -sum-mset-image :: pttrn ⇒ 0b set ⇒ 0a ⇒ 0a::comm-monoid-add ((3SUM -:#-. -)[0 , 51 , 10 ] 10 ) syntax -sum-mset-image :: pttrn ⇒ 0b set ⇒ 0a ⇒ 0a::comm-monoid-add ((3 P -∈#-. -)[0 , 51 , 10 ] 10 ) translations P i ∈# A. b CONST sum-mset (CONST image-mset (λi. b) A) lemma sum-mset-distrib-left: fixes f :: 0a ⇒ 0b::semiring-0

187 shows c ∗ (P x ∈# M . f x) = (P x ∈# M . c ∗ f (x)) by (induction M )(simp-all add: distrib-left) lemma sum-mset-distrib-right: fixes f :: 0a ⇒ 0b::semiring-0 shows (P b ∈# B. f b) ∗ a = (P b ∈# B. f b ∗ a) by (induction B)(auto simp: distrib-right) lemma sum-mset-constant [simp]: fixes y :: 0b::semiring-1 shows h(P x∈#A. y) = of-nat (size A) ∗ y i by (induction A)(auto simp: algebra-simps) lemma (in ordered-comm-monoid-add) sum-mset-mono: assumes Vi. i ∈# K =⇒ f i ≤ g i shows sum-mset (image-mset f K ) ≤ sum-mset (image-mset g K ) using assms by (induction K )(simp-all add: local.add-mono) lemma sum-mset-product: fixes f :: 0a::{comm-monoid-add,times} ⇒ 0b::semiring-0 shows (P i ∈# A. f i) ∗ (P i ∈# B. g i) = (P i∈#A. P j ∈#B. f i ∗ g j ) by (subst sum-mset.commute)(simp add: sum-mset-distrib-left sum-mset-distrib-right) abbreviation Union-mset :: 0a multiset multiset ⇒ 0a multiset (S #- [900 ] 900 ) where S # MM ≡ sum-mset MM — FIXME ambiguous notation – could likewise refer to F # lemma set-mset-Union-mset[simp]: set-mset (S # MM ) = (S M ∈ set-mset MM . set-mset M ) by (induct MM ) auto lemma in-Union-mset-iff [iff ]: x ∈# S # MM ←→ (∃ M . M ∈# MM ∧ x ∈# M ) by (induct MM ) auto lemma count-sum: count (sum f A) x = sum (λa. count (f a) x) A by (induct A rule: infinite-finite-induct) simp-all lemma sum-eq-empty-iff : assumes finite A shows sum f A = {#} ←→ (∀ a∈A. f a = {#}) using assms by induct simp-all lemma Union-mset-empty-conv[simp]: S # M = {#} ←→ (∀ i∈#M . i = {#}) by (induction M ) auto context comm-monoid-mult begin

188 sublocale prod-mset: comm-monoid-mset times 1 defines prod-mset = prod-mset.F .. lemma prod-mset-empty: prod-mset {#} = 1 by (fact prod-mset.empty) lemma prod-mset-singleton: prod-mset {#x#} = x by (fact prod-mset.singleton) lemma prod-mset-Un: prod-mset (A + B) = prod-mset A ∗ prod-mset B by (fact prod-mset.union) lemma prod-mset-replicate-mset [simp]: prod-mset (replicate-mset n a) = a ˆ n by (induct n) simp-all lemma prod-unfold-prod-mset: prod f A = prod-mset (image-mset f (mset-set A)) by (cases finite A)(induct A rule: finite-induct, simp-all) lemma prod-mset-multiplicity: prod-mset M = prod (λx. x ˆ count M x)(set-mset M ) by (simp add: fold-mset-def prod.eq-fold prod-mset.eq-fold funpow-times-power comp-def ) lemma prod-mset-delta: prod-mset (image-mset (λx. if x = y then c else 1 ) A) = c ˆ count A y by (induction A) simp-all lemma prod-mset-delta 0: prod-mset (image-mset (λx. if y = x then c else 1 ) A) = c ˆ count A y by (induction A) simp-all end syntax (ASCII ) -prod-mset-image :: pttrn ⇒ 0b set ⇒ 0a ⇒ 0a::comm-monoid-mult ((3PROD -:#-. -)[0 , 51 , 10 ] 10 ) syntax -prod-mset-image :: pttrn ⇒ 0b set ⇒ 0a ⇒ 0a::comm-monoid-mult ((3 Q -∈#-. -)[0 , 51 , 10 ] 10 ) translations Q i ∈# A. b CONST prod-mset (CONST image-mset (λi. b) A) lemma (in comm-monoid-mult) prod-mset-subset-imp-dvd:

189 assumes A ⊆# B shows prod-mset A dvd prod-mset B proof − from assms have B = (B − A) + A by (simp add: subset-mset.diff-add) also have prod-mset ... = prod-mset (B − A) ∗ prod-mset A by simp also have prod-mset A dvd ... by simp finally show ?thesis . qed lemma (in comm-monoid-mult) dvd-prod-mset: assumes x ∈# A shows x dvd prod-mset A using assms prod-mset-subset-imp-dvd [of {#x#} A] by simp lemma (in semidom) prod-mset-zero-iff [iff ]: prod-mset A = 0 ←→ 0 ∈# A by (induct A) auto lemma (in semidom-divide) prod-mset-diff : assumes B ⊆# A and 0 ∈/# B shows prod-mset (A − B) = prod-mset A div prod-mset B proof − from assms obtain C where A = B + C by (metis subset-mset.add-diff-inverse) with assms show ?thesis by simp qed lemma (in semidom-divide) prod-mset-minus: assumes a ∈# A and a 6= 0 shows prod-mset (A − {#a#}) = prod-mset A div a using assms prod-mset-diff [of {#a#} A] by auto lemma (in algebraic-semidom) is-unit-prod-mset-iff : is-unit (prod-mset A) ←→ (∀ x ∈# A. is-unit x) by (induct A)(auto simp: is-unit-mult-iff ) lemma (in normalization-semidom) normalize-prod-mset: normalize (prod-mset A) = prod-mset (image-mset normalize A) by (induct A)(simp-all add: normalize-mult) lemma (in normalization-semidom) normalized-prod-msetI : assumes Va. a ∈# A =⇒ normalize a = a shows normalize (prod-mset A) = prod-mset A proof − from assms have image-mset normalize A = A by (induct A) simp-all then show ?thesis by (simp add: normalize-prod-mset) qed

190 lemma prod-mset-prod-list: prod-mset (mset xs) = prod-list xs by (induct xs) auto

31.11 Alternative representations 31.11.1 Lists context linorder begin lemma mset-insort [simp]: mset (insort-key k x xs) = add-mset x (mset xs) by (induct xs) simp-all lemma mset-sort [simp]: mset (sort-key k xs) = mset xs by (induct xs) simp-all

This lemma shows which properties suffice to show that a function f with f xs = ys behaves like sort. lemma properties-for-sort-key: assumes mset ys = mset xs and Vk. k ∈ set ys =⇒ filter (λx. f k = f x) ys = filter (λx. f k = f x) xs and sorted (map f ys) shows sort-key f xs = ys using assms proof (induct xs arbitrary: ys) case Nil then show ?case by simp next case (Cons x xs) from Cons.prems(2 ) have ∀ k ∈ set ys. filter (λx. f k = f x)(remove1 x ys) = filter (λx. f k = f x) xs by (simp add: filter-remove1 ) with Cons.prems have sort-key f xs = remove1 x ys by (auto intro!: Cons.hyps simp add: sorted-map-remove1 ) moreover from Cons.prems have x ∈# mset ys by auto then have x ∈ set ys by simp ultimately show ?case using Cons.prems by (simp add: insort-key-remove1 ) qed lemma properties-for-sort: assumes multiset: mset ys = mset xs and sorted ys shows sort xs = ys proof (rule properties-for-sort-key) from multiset show mset ys = mset xs . from hsorted ys i show sorted (map (λx. x) ys) by simp

191 from multiset have length (filter (λy. k = y) ys) = length (filter (λx. k = x) xs) for k by (rule mset-eq-length-filter) then have replicate (length (filter (λy. k = y) ys)) k = replicate (length (filter (λx. k = x) xs)) k for k by simp then show k ∈ set ys =⇒ filter (λy. k = y) ys = filter (λx. k = x) xs for k by (simp add: replicate-length-filter) qed lemma sort-key-inj-key-eq: assumes mset-equal: mset xs = mset ys and inj-on f (set xs) and sorted (map f ys) shows sort-key f xs = ys proof (rule properties-for-sort-key) from mset-equal show mset ys = mset xs by simp from hsorted (map f ys)i show sorted (map f ys) . show [x←ys . f k = f x] = [x←xs . f k = f x] if k ∈ set ys for k proof − from mset-equal have set-equal: set xs = set ys by (rule mset-eq-setD) with that have insert k (set ys) = set ys by auto with hinj-on f (set xs)i have inj : inj-on f (insert k (set ys)) by (simp add: set-equal) from inj have [x←ys . f k = f x] = filter (HOL.eq k) ys by (auto intro!: inj-on-filter-key-eq) also have ... = replicate (count (mset ys) k) k by (simp add: replicate-count-mset-eq-filter-eq) also have ... = replicate (count (mset xs) k) k using mset-equal by simp also have ... = filter (HOL.eq k) xs by (simp add: replicate-count-mset-eq-filter-eq) also have ... = [x←xs . f k = f x] using inj by (auto intro!: inj-on-filter-key-eq [symmetric] simp add: set-equal) finally show ?thesis . qed qed lemma sort-key-eq-sort-key: assumes mset xs = mset ys and inj-on f (set xs) shows sort-key f xs = sort-key f ys by (rule sort-key-inj-key-eq)(simp-all add: assms) lemma sort-key-by-quicksort: sort-key f xs = sort-key f [x←xs. f x < f (xs !(length xs div 2 ))]

192 @[x←xs. f x = f (xs !(length xs div 2 ))] @ sort-key f [x←xs. f x > f (xs !(length xs div 2 ))] (is sort-key f ?lhs = ?rhs) proof (rule properties-for-sort-key) show mset ?rhs = mset ?lhs by (rule multiset-eqI )(auto simp add: mset-filter) show sorted (map f ?rhs) by (auto simp add: sorted-append intro: sorted-map-same) next fix l assume l ∈ set ?rhs let ?pivot = f (xs !(length xs div 2 )) have ∗: Vx. f l = f x ←→ f x = f l by auto have [x ← sort-key f xs . f x = f l] = [x ← xs. f x = f l] unfolding filter-sort by (rule properties-for-sort-key)(auto intro: sorted-map-same) with ∗ have ∗∗:[x ← sort-key f xs . f l = f x] = [x ← xs. f l = f x] by simp have Vx P. P (f x) ?pivot ∧ f l = f x ←→ P (f l) ?pivot ∧ f l = f x by auto then have VP. [x ← sort-key f xs . P (f x) ?pivot ∧ f l = f x] = [x ← sort-key f xs. P (f l) ?pivot ∧ f l = f x] by simp note ∗∗∗ = this [of op <] this [of op >] this [of op =] show [x ← ?rhs. f l = f x] = [x ← ?lhs. f l = f x] proof (cases f l ?pivot rule: linorder-cases) case less then have f l 6= ?pivot and ¬ f l > ?pivot by auto with less show ?thesis by (simp add: filter-sort [symmetric] ∗∗ ∗∗∗) next case equal then show ?thesis by (simp add: ∗ less-le) next case greater then have f l 6= ?pivot and ¬ f l < ?pivot by auto with greater show ?thesis by (simp add: filter-sort [symmetric] ∗∗ ∗∗∗) qed qed lemma sort-by-quicksort: sort xs = sort [x←xs. x < xs !(length xs div 2 )] @[x←xs. x = xs !(length xs div 2 )] @ sort [x←xs. x > xs !(length xs div 2 )] (is sort ?lhs = ?rhs) using sort-key-by-quicksort [of λx. x, symmetric] by simp

A stable parametrized quicksort definition part :: ( 0b ⇒ 0a) ⇒ 0a ⇒ 0b list ⇒ 0b list × 0b list × 0b list where part f pivot xs = ([x ← xs. f x < pivot], [x ← xs. f x = pivot], [x ← xs. pivot < f x]) lemma part-code [code]: part f pivot [] = ([], [], [])

193 part f pivot (x # xs) = (let (lts, eqs, gts) = part f pivot xs; x 0 = f x in if x 0 < pivot then (x # lts, eqs, gts) else if x 0 > pivot then (lts, eqs, x # gts) else (lts, x # eqs, gts)) by (auto simp add: part-def Let-def split-def ) lemma sort-key-by-quicksort-code [code]: sort-key f xs = (case xs of [] ⇒ [] | [x] ⇒ xs | [x, y] ⇒ (if f x ≤ f y then xs else [y, x]) | - ⇒ let (lts, eqs, gts) = part f (f (xs !(length xs div 2 ))) xs in sort-key f lts @ eqs @ sort-key f gts) proof (cases xs) case Nil then show ?thesis by simp next case (Cons - ys) note hyps = Cons show ?thesis proof (cases ys) case Nil with hyps show ?thesis by simp next case (Cons - zs) note hyps = hyps Cons show ?thesis proof (cases zs) case Nil with hyps show ?thesis by auto next case Cons from sort-key-by-quicksort [of f xs] have sort-key f xs = (let (lts, eqs, gts) = part f (f (xs !(length xs div 2 ))) xs in sort-key f lts @ eqs @ sort-key f gts) by (simp only: split-def Let-def part-def fst-conv snd-conv) with hyps Cons show ?thesis by (simp only: list.cases) qed qed qed end hide-const (open) part lemma mset-remdups-subset-eq: mset (remdups xs) ⊆# mset xs by (induct xs)(auto intro: subset-mset.order-trans) lemma mset-update: i < length ls =⇒ mset (ls[i := v]) = add-mset v (mset ls − {#ls ! i#}) proof (induct ls arbitrary: i) case Nil then show ?case by simp next case (Cons x xs)

194 show ?case proof (cases i) case 0 then show ?thesis by simp next case (Suc i 0) with Cons show ?thesis 0 by (cases hx = xs ! i i) auto qed qed lemma mset-swap: i < length ls =⇒ j < length ls =⇒ mset (ls[j := ls ! i, i := ls ! j ]) = mset ls by (cases i = j )(simp-all add: mset-update nth-mem-mset)

31.12 The multiset order 31.12.1 Well-foundedness definition mult1 :: ( 0a × 0a) set ⇒ ( 0a multiset × 0a multiset) set where mult1 r = {(N , M ). ∃ a M0 K . M = add-mset a M0 ∧ N = M0 + K ∧ (∀ b. b ∈# K −→ (b, a) ∈ r)} definition mult :: ( 0a × 0a) set ⇒ ( 0a multiset × 0a multiset) set where mult r = (mult1 r)+ lemma mult1I : assumes M = add-mset a M0 and N = M0 + K and Vb. b ∈# K =⇒ (b, a) ∈ r shows (N , M ) ∈ mult1 r using assms unfolding mult1-def by blast lemma mult1E: assumes (N , M ) ∈ mult1 r obtains a M0 K where M = add-mset a M0 N = M0 + K Vb. b ∈# K =⇒ (b, a) ∈ r using assms unfolding mult1-def by blast lemma mono-mult1 : assumes r ⊆ r 0 shows mult1 r ⊆ mult1 r 0 unfolding mult1-def using assms by blast lemma mono-mult: assumes r ⊆ r 0 shows mult r ⊆ mult r 0 unfolding mult-def using mono-mult1 [OF assms] trancl-mono by blast lemma not-less-empty [iff ]: (M , {#}) ∈/ mult1 r by (simp add: mult1-def ) lemma less-add:

195 assumes mult1 :(N , add-mset a M0 ) ∈ mult1 r shows (∃ M . (M , M0 ) ∈ mult1 r ∧ N = add-mset a M ) ∨ (∃ K . (∀ b. b ∈# K −→ (b, a) ∈ r) ∧ N = M0 + K ) proof − let ?r = λK a. ∀ b. b ∈# K −→ (b, a) ∈ r let ?R = λNM . ∃ a M0 K . M = add-mset a M0 ∧ N = M0 + K ∧ ?r K a obtain a 0 M0 0 K where M0 : add-mset a M0 = add-mset a 0 M0 0 and N : N = M0 0 + K and r: ?r K a 0 using mult1 unfolding mult1-def by auto show ?thesis (is ?case1 ∨ ?case2 ) proof − from M0 consider M0 = M0 0 a = a 0 | K 0 where M0 = add-mset a 0 K 0 M0 0 = add-mset a K 0 by atomize-elim (simp only: add-eq-conv-ex) then show ?thesis proof cases case 1 with N r have ?r K a ∧ N = M0 + K by simp then have ?case2 .. then show ?thesis .. next case 2 from N 2 (2 ) have n: N = add-mset a (K 0 + K ) by simp with r 2 (1 ) have ?R (K 0 + K ) M0 by blast with n have ?case1 by (simp add: mult1-def ) then show ?thesis .. qed qed qed lemma all-accessible: assumes wf r shows ∀ M . M ∈ Wellfounded.acc (mult1 r) proof let ?R = mult1 r let ?W = Wellfounded.acc ?R { fix M M0 a assume M0 : M0 ∈ ?W and wf-hyp: Vb. (b, a) ∈ r =⇒ (∀ M ∈ ?W . add-mset b M ∈ ?W ) and acc-hyp: ∀ M . (M , M0 ) ∈ ?R −→ add-mset a M ∈ ?W have add-mset a M0 ∈ ?W proof (rule accI [of add-mset a M0 ]) fix N assume (N , add-mset a M0 ) ∈ ?R then consider M where (M , M0 ) ∈ ?R N = add-mset a M | K where ∀ b. b ∈# K −→ (b, a) ∈ r N = M0 + K

196 by atomize-elim (rule less-add) then show N ∈ ?W proof cases case 1 from acc-hyp have (M , M0 ) ∈ ?R −→ add-mset a M ∈ ?W .. from this and h(M , M0 ) ∈ ?Ri have add-mset a M ∈ ?W .. then show N ∈ ?W by (simp only: hN = add-mset a M i) next case 2 from this(1 ) have M0 + K ∈ ?W proof (induct K ) case empty from M0 show M0 + {#} ∈ ?W by simp next case (add x K ) from add.prems have (x, a) ∈ r by simp with wf-hyp have ∀ M ∈ ?W . add-mset x M ∈ ?W by blast moreover from add have M0 + K ∈ ?W by simp ultimately have add-mset x (M0 + K ) ∈ ?W .. then show M0 + (add-mset x K ) ∈ ?W by simp qed then show N ∈ ?W by (simp only: 2 (2 )) qed qed } note tedious-reasoning = this

show M ∈ ?W for M proof (induct M ) show {#} ∈ ?W proof (rule accI ) fix b assume (b, {#}) ∈ ?R with not-less-empty show b ∈ ?W by contradiction qed

fix M a assume M ∈ ?W from hwf r i have ∀ M ∈ ?W . add-mset a M ∈ ?W proof induct fix a assume r: Vb. (b, a) ∈ r =⇒ (∀ M ∈ ?W . add-mset b M ∈ ?W ) show ∀ M ∈ ?W . add-mset a M ∈ ?W proof fix M assume M ∈ ?W then show add-mset a M ∈ ?W by (rule acc-induct)(rule tedious-reasoning [OF - r]) qed qed from this and hM ∈ ?W i show add-mset a M ∈ ?W .. qed qed

197 theorem wf-mult1 : wf r =⇒ wf (mult1 r) by (rule acc-wfI )(rule all-accessible) theorem wf-mult: wf r =⇒ wf (mult r) unfolding mult-def by (rule wf-trancl)(rule wf-mult1 )

31.12.2 Closure-free presentation

One direction. lemma mult-implies-one-step: assumes trans: trans r and MN :(M , N ) ∈ mult r shows ∃ IJK . N = I + J ∧ M = I + K ∧ J 6= {#} ∧ (∀ k ∈ set-mset K . ∃ j ∈ set-mset J . (k, j ) ∈ r) using MN unfolding mult-def mult1-def proof (induction rule: converse-trancl-induct) case (base y) then show ?case by force next case (step y z) note yz = this(1 ) and zN = this(2 ) and N-decomp = this(3 ) obtain IJK where N : N = I + J z = I + KJ 6= {#} ∀ k∈#K . ∃ j ∈#J . (k, j ) ∈ r using N-decomp by blast obtain a M0 K 0 where z: z = add-mset a M0 and y: y = M0 + K 0 and K : ∀ b. b ∈# K 0 −→ (b, a) ∈ r using yz by blast show ?case proof (cases a ∈# K ) case True moreover have ∃ j ∈#J . (k, j ) ∈ r if k ∈# K 0 for k using K N trans True by (meson that transE) ultimately show ?thesis by (rule-tac x = I in exI , rule-tac x = J in exI , rule-tac x = (K − {#a#}) + K 0 in exI ) (use z y N in hauto simp del: subset-mset.add-diff-assoc2 dest: in-diffD i) next case False then have a ∈# I by (metis N (2 ) union-iff union-single-eq-member z) moreover have M0 = I + K − {#a#} using N (2 ) z by force ultimately show ?thesis by (rule-tac x = I − {#a#} in exI , rule-tac x = add-mset a J in exI , rule-tac x = K + K 0 in exI ) (use z y N False K in hauto simp: add.associ) qed qed

198 lemma one-step-implies-mult: assumes J 6= {#} and ∀ k ∈ set-mset K . ∃ j ∈ set-mset J . (k, j ) ∈ r shows (I + K , I + J ) ∈ mult r using assms proof (induction size J arbitrary: IJK ) case 0 then show ?case by auto next case (Suc n) note IH = this(1 ) and size-J = this(2 )[THEN sym] obtain J 0 a where J : J = add-mset a J 0 using size-J by (blast dest: size-eq-Suc-imp-eq-union) show ?case proof (cases J 0 = {#}) case True then show ?thesis using J Suc by (fastforce simp add: mult-def mult1-def ) next case [simp]: False have K : K = {#x ∈# K . (x, a) ∈ r#} + {#x ∈# K . (x, a) ∈/ r#} by (rule multiset-partition) have (I + K , (I + {# x ∈# K . (x, a) ∈ r #}) + J 0) ∈ mult r using IH [of J 0 {# x ∈# K . (x, a) ∈/ r#} I + {# x ∈# K . (x, a) ∈ r#}] J Suc.prems K size-J by (auto simp: ac-simps) moreover have (I + {#x ∈# K . (x, a) ∈ r#} + J 0, I + J ) ∈ mult r by (fastforce simp: J mult1-def mult-def ) ultimately show ?thesis unfolding mult-def by simp qed qed

31.13 The multiset extension is cancellative for multiset union lemma mult-cancel: assumes trans s and irrefl s shows (X + Z , Y + Z ) ∈ mult s ←→ (X , Y ) ∈ mult s (is ?L ←→ ?R) proof assume ?L thus ?R proof (induct Z ) case (add z Z ) obtain X 0 Y 0 Z 0 where ∗: add-mset z X + Z = Z 0 + X 0 add-mset z Y + Z = Z 0 + Y 0 Y 0 6= {#} ∀ x ∈ set-mset X 0. ∃ y ∈ set-mset Y 0. (x, y) ∈ s using mult-implies-one-step[OF htrans s i add(2 )] by auto consider Z2 where Z 0 = add-mset z Z2 | X2 Y2 where X 0 = add-mset z X2 Y 0 = add-mset z Y2 using ∗(1 ,2 ) by (metis add-mset-remove-trivial-If insert-iff set-mset-add-mset-insert

199 union-iff ) thus ?case proof (cases) case 1 thus ?thesis using ∗ one-step-implies-mult[of Y 0 X 0 s Z2 ] by (auto simp: add.commute[of - {#-#}] add.assoc intro: add(1 )) next case 2 then obtain y where y ∈ set-mset Y2 (z, y) ∈ s using ∗(4 ) hirrefl s i by (auto simp: irrefl-def ) moreover from this transD[OF htrans s i - this(2 )] have x 0 ∈ set-mset X2 =⇒ ∃ y ∈ set-mset Y2 . (x 0, y) ∈ s for x 0 using 2 ∗(4 )[rule-format, of x 0] by auto ultimately show ?thesis using ∗ one-step-implies-mult[of Y2 X2 s Z 0] 2 by (force simp: add.commute[of {#-#}] add.assoc[symmetric] intro: add(1 )) qed qed auto next assume ?R then obtain IJK where Y = I + JX = I + KJ 6= {#} ∀ k ∈ set-mset K . ∃ j ∈ set-mset J . (k, j ) ∈ s using mult-implies-one-step[OF htrans s i] by blast thus ?L using one-step-implies-mult[of J K s I + Z ] by (auto simp: ac-simps) qed lemma mult-cancel-max: assumes trans s and irrefl s shows (X , Y ) ∈ mult s ←→ (X − X ∩# Y , Y − X ∩# Y ) ∈ mult s (is ?L ←→ ?R) proof − have X − X ∩# Y + X ∩# Y = XY − X ∩# Y + X ∩# Y = Y by (auto simp: count-inject[symmetric]) thus ?thesis using mult-cancel[OF assms, of X − X ∩# YX ∩# YY − X ∩# Y ] by auto qed

31.14 Quasi-executable version of the multiset extension

Predicate variants of mult and the reflexive closure of mult, which are exe- cutable whenever the given predicate P is. Together with the standard code equations for op ∩# and op − this should yield quadratic (with respect to calls to P) implementations of multp and multeqp. definition multp :: ( 0a ⇒ 0a ⇒ bool) ⇒ 0a multiset ⇒ 0a multiset ⇒ bool where multp P N M = (let Z = M ∩# N ; X = M − Z in X 6= {#} ∧ (let Y = N − Z in (∀ y ∈ set-mset Y . ∃ x ∈ set-mset X . P y x))) definition multeqp :: ( 0a ⇒ 0a ⇒ bool) ⇒ 0a multiset ⇒ 0a multiset ⇒ bool where multeqp P N M =

200 (let Z = M ∩# N ; X = M − Z ; Y = N − Z in (∀ y ∈ set-mset Y . ∃ x ∈ set-mset X . P y x)) lemma multp-iff : assumes irrefl R and trans R and [simp]: Vx y. P x y ←→ (x, y) ∈ R shows multp P N M ←→ (N , M ) ∈ mult R (is ?L ←→ ?R) proof − have ∗: M ∩# N + (N − M ∩# N ) = NM ∩# N + (M − M ∩# N ) = M (M − M ∩# N ) ∩#(N − M ∩# N ) = {#} by (auto simp: count-inject[symmetric]) show ?thesis proof assume ?L thus ?R using one-step-implies-mult[of M − M ∩# NN − M ∩# NRM ∩# N ] ∗ by (auto simp: multp-def Let-def ) next { fix IJK :: 0a multiset assume (I + J ) ∩#(I + K ) = {#} then have I = {#} by (metis inter-union-distrib-right union-eq-empty) } note [dest!] = this assume ?R thus ?L using mult-implies-one-step[OF assms(2 ), of N − M ∩# NM − M ∩# N ] mult-cancel-max[OF assms(2 ,1 ), of N M ] ∗ by (auto simp: multp-def ) qed qed lemma multeqp-iff : assumes irrefl R and trans R and Vx y. P x y ←→ (x, y) ∈ R shows multeqp P N M ←→ (N , M ) ∈ (mult R)= proof − { assume N 6= MM − M ∩# N = {#} then obtain y where count N y 6= count M y by (auto simp: count-inject[symmetric]) then have ∃ y. count M y < count N y using hM − M ∩# N = {#}i by (auto simp: count-inject[symmetric] dest!: le-neq-implies-less fun-cong[of - - y]) } then have multeqp P N M ←→ multp P N M ∨ N = M by (auto simp: multeqp-def multp-def Let-def in-diff-count) thus ?thesis using multp-iff [OF assms] by simp qed

31.14.1 Partial-order properties lemma (in preorder) mult1-lessE: assumes (N , M ) ∈ mult1 {(a, b). a < b} obtains a M0 K where M = add-mset a M0 N = M0 + K a ∈/# K Vb. b ∈# K =⇒ b < a proof − from assms obtain a M0 K where M = add-mset a M0 N = M0 + K and ∗: b ∈# K =⇒ b < a for b by (blast elim: mult1E) moreover from ∗ [of a] have a ∈/# K by auto

201 ultimately show thesis by (auto intro: that) qed instantiation multiset :: (preorder) order begin definition less-multiset :: 0a multiset ⇒ 0a multiset ⇒ bool where M 0 < M ←→ (M 0, M ) ∈ mult {(x 0, x). x 0 < x} definition less-eq-multiset :: 0a multiset ⇒ 0a multiset ⇒ bool where less-eq-multiset M 0 M ←→ M 0 < M ∨ M 0 = M instance proof − have irrefl: ¬ M < M for M :: 0a multiset proof assume M < M then have MM :(M , M ) ∈ mult {(x, y). x < y} by (simp add: less-multiset-def ) have trans {(x 0:: 0a, x). x 0 < x} by (metis (mono-tags, lifting) case-prodD case-prodI less-trans mem-Collect-eq transI ) moreover note MM ultimately have ∃ IJK . M = I + J ∧ M = I + K ∧ J 6= {#} ∧ (∀ k∈set-mset K . ∃ j ∈set-mset J . (k, j ) ∈ {(x, y). x < y}) by (rule mult-implies-one-step) then obtain IJK where M = I + J and M = I + K and J 6= {#} and (∀ k∈set-mset K . ∃ j ∈set-mset J . (k, j ) ∈ {(x, y). x < y}) by blast then have ∗: K 6= {#} and ∗∗: ∀ k∈set-mset K . ∃ j ∈set-mset K . k < j by auto have finite (set-mset K ) by simp moreover note ∗∗ ultimately have set-mset K = {} by (induct rule: finite-induct)(auto intro: order-less-trans) with ∗ show False by simp qed have trans: K < M =⇒ M < N =⇒ K < N for KMN :: 0a multiset unfolding less-multiset-def mult-def by (blast intro: trancl-trans) show OFCLASS( 0a multiset, order-class) by standard (auto simp add: less-eq-multiset-def irrefl dest: trans) qed end — FIXME avoid junk stemming from type class interpretation lemma mset-le-irrefl [elim!]: fixes M :: 0a::preorder multiset shows M < M =⇒ R by simp

202 31.14.2 Monotonicity of multiset union lemma mult1-union:(B, D) ∈ mult1 r =⇒ (C + B, C + D) ∈ mult1 r by (force simp: mult1-def ) lemma union-le-mono2 : B < D =⇒ C + B < C + (D:: 0a::preorder multiset) apply (unfold less-multiset-def mult-def ) apply (erule trancl-induct) apply (blast intro: mult1-union) apply (blast intro: mult1-union trancl-trans) done lemma union-le-mono1 : B < D =⇒ B + C < D + (C :: 0a::preorder multiset) apply (subst add.commute [of B C ]) apply (subst add.commute [of D C ]) apply (erule union-le-mono2 ) done lemma union-less-mono: fixes ABCD :: 0a::preorder multiset shows A < C =⇒ B < D =⇒ A + B < C + D by (blast intro!: union-le-mono1 union-le-mono2 less-trans) instantiation multiset :: (preorder) ordered-ab-semigroup-add begin instance by standard (auto simp add: less-eq-multiset-def intro: union-le-mono2 ) end

31.14.3 Termination proofs with multiset orders lemma multi-member-skip: x ∈# XS =⇒ x ∈# {# y #} + XS and multi-member-this: x ∈# {# x #} + XS and multi-member-last: x ∈# {# x #} by auto definition ms-strict = mult pair-less definition ms-weak = ms-strict ∪ Id lemma ms-reduction-pair: reduction-pair (ms-strict, ms-weak) unfolding reduction-pair-def ms-strict-def ms-weak-def pair-less-def by (auto intro: wf-mult1 wf-trancl simp: mult-def ) lemma smsI : (set-mset A, set-mset B) ∈ max-strict =⇒ (Z + A, Z + B) ∈ ms-strict unfolding ms-strict-def by (rule one-step-implies-mult)(auto simp add: max-strict-def pair-less-def elim!:max-ext.cases) lemma wmsI : (set-mset A, set-mset B) ∈ max-strict ∨ A = {#} ∧ B = {#}

203 =⇒ (Z + A, Z + B) ∈ ms-weak unfolding ms-weak-def ms-strict-def by (auto simp add: pair-less-def max-strict-def elim!:max-ext.cases intro: one-step-implies-mult) inductive pw-leq where pw-leq-empty: pw-leq {#}{#} | pw-leq-step: [[(x,y) ∈ pair-leq; pw-leq X Y ]] =⇒ pw-leq ({#x#} + X )({#y#} + Y ) lemma pw-leq-lstep: (x, y) ∈ pair-leq =⇒ pw-leq {#x#}{#y#} by (drule pw-leq-step)(rule pw-leq-empty, simp) lemma pw-leq-split: assumes pw-leq X Y shows ∃ ABZ . X = A + Z ∧ Y = B + Z ∧ ((set-mset A, set-mset B) ∈ max-strict ∨ (B = {#} ∧ A = {#})) using assms proof induct case pw-leq-empty thus ?case by auto next case (pw-leq-step x y X Y ) then obtain ABZ where [simp]: X = A + ZY = B + Z and 1 [simp]: (set-mset A, set-mset B) ∈ max-strict ∨ (B = {#} ∧ A = {#}) by auto from pw-leq-step consider x = y | (x, y) ∈ pair-less unfolding pair-leq-def by auto thus ?case proof cases case [simp]: 1 have {#x#} + X = A + ({#y#}+Z ) ∧ {#y#} + Y = B + ({#y#}+Z ) ∧ ((set-mset A, set-mset B) ∈ max-strict ∨ (B = {#} ∧ A = {#})) by auto thus ?thesis by blast next case 2 let ?A 0 = {#x#} + A and ?B 0 = {#y#} + B have {#x#} + X = ?A 0 + Z {#y#} + Y = ?B 0 + Z by auto moreover have (set-mset ?A 0, set-mset ?B 0) ∈ max-strict using 1 2 unfolding max-strict-def by (auto elim!: max-ext.cases) ultimately show ?thesis by blast qed qed

204 lemma assumes pwleq: pw-leq Z Z 0 shows ms-strictI :(set-mset A, set-mset B) ∈ max-strict =⇒ (Z + A, Z 0 + B) ∈ ms-strict and ms-weakI1 :(set-mset A, set-mset B) ∈ max-strict =⇒ (Z + A, Z 0 + B) ∈ ms-weak and ms-weakI2 :(Z + {#}, Z 0 + {#}) ∈ ms-weak proof − from pw-leq-split[OF pwleq] obtain A 0 B 0 Z 00 where [simp]: Z = A 0 + Z 00 Z 0 = B 0 + Z 00 and mx-or-empty:(set-mset A 0, set-mset B 0) ∈ max-strict ∨ (A 0 = {#} ∧ B 0 = {#}) by blast { assume max:(set-mset A, set-mset B) ∈ max-strict from mx-or-empty have (Z 00 + (A + A 0), Z 00 + (B + B 0)) ∈ ms-strict proof assume max 0:(set-mset A 0, set-mset B 0) ∈ max-strict with max have (set-mset (A + A 0), set-mset (B + B 0)) ∈ max-strict by (auto simp: max-strict-def intro: max-ext-additive) thus ?thesis by (rule smsI ) next assume [simp]: A 0 = {#} ∧ B 0 = {#} show ?thesis by (rule smsI )(auto intro: max) qed thus (Z + A, Z 0 + B) ∈ ms-strict by (simp add: ac-simps) thus (Z + A, Z 0 + B) ∈ ms-weak by (simp add: ms-weak-def ) } from mx-or-empty have (Z 00 + A 0, Z 00 + B 0) ∈ ms-weak by (rule wmsI ) thus (Z + {#}, Z 0 + {#}) ∈ ms-weak by (simp add: ac-simps) qed lemma empty-neutral: {#} + x = x x + {#} = x and nonempty-plus: {# x #} + rs 6= {#} and nonempty-single: {# x #}= 6 {#} by auto setup h let fun msetT T = Type (@{type-name multiset}, [T ]);

fun mk-mset T [] = Const (@{const-abbrev Mempty}, msetT T ) | mk-mset T [x] = Const (@{const-name add-mset}, T −−> msetT T −−> msetT T ) $ x $ Const (@{const-abbrev Mempty}, msetT T )

205 | mk-mset T (x :: xs) = Const (@{const-name plus}, msetT T −−> msetT T −−> msetT T ) $ mk-mset T [x] $ mk-mset T xs

fun mset-member-tac ctxt m i = if m <= 0 then resolve-tac ctxt @{thms multi-member-this} i ORELSE resolve-tac ctxt @{thms multi-member-last} i else resolve-tac ctxt @{thms multi-member-skip} i THEN mset-member-tac ctxt (m − 1 ) i

fun mset-nonempty-tac ctxt = resolve-tac ctxt @{thms nonempty-plus} ORELSE 0 resolve-tac ctxt @{thms nonempty-single}

fun regroup-munion-conv ctxt = Function-Lib.regroup-conv ctxt @{const-abbrev Mempty} @{const-name plus} (map (fn t => t RS eq-reflection) (@{thms ac-simps} @@{thms empty-neutral}))

fun unfold-pwleq-tac ctxt i = (resolve-tac ctxt @{thms pw-leq-step} i THEN (fn st => unfold-pwleq-tac ctxt (i + 1 ) st)) ORELSE (resolve-tac ctxt @{thms pw-leq-lstep} i) ORELSE (resolve-tac ctxt @{thms pw-leq-empty} i)

val set-mset-simps = [@{thm set-mset-empty}, @{thm set-mset-single}, @{thm set-mset-union}, @{thm Un-insert-left}, @{thm Un-empty-left}] in ScnpReconstruct.multiset-setup (ScnpReconstruct.Multiset { msetT =msetT , mk-mset=mk-mset, mset-regroup-conv=regroup-munion-conv, mset-member-tac=mset-member-tac, mset-nonempty-tac=mset-nonempty-tac, mset-pwleq-tac=unfold-pwleq-tac, set-of-simps=set-mset-simps, smsI 0= @{thm ms-strictI }, wmsI2 00= @{thm ms-weakI2 }, wmsI1 = @{thm ms-weakI1 }, reduction-pair = @{thm ms-reduction-pair} }) end i

31.15 Legacy theorem bindings lemmas multi-count-eq = multiset-eq-iff [symmetric] lemma union-commute: M + N = N + (M :: 0a multiset) by (fact add.commute)

206 lemma union-assoc:(M + N ) + K = M + (N + (K :: 0a multiset)) by (fact add.assoc) lemma union-lcomm: M + (N + K ) = N + (M + (K :: 0a multiset)) by (fact add.left-commute) lemmas union-ac = union-assoc union-commute union-lcomm add-mset-commute lemma union-right-cancel: M + K = N + K ←→ M = (N :: 0a multiset) by (fact add-right-cancel) lemma union-left-cancel: K + M = K + N ←→ M = (N :: 0a multiset) by (fact add-left-cancel) lemma multi-union-self-other-eq:(A:: 0a multiset) + X = A + Y =⇒ X = Y by (fact add-left-imp-eq) lemma mset-subset-trans:(M :: 0a multiset) ⊂# K =⇒ K ⊂# N =⇒ M ⊂# N by (fact subset-mset.less-trans) lemma multiset-inter-commute: A ∩# B = B ∩# A by (fact subset-mset.inf .commute) lemma multiset-inter-assoc: A ∩#(B ∩# C ) = A ∩# B ∩# C by (fact subset-mset.inf .assoc [symmetric]) lemma multiset-inter-left-commute: A ∩#(B ∩# C ) = B ∩#(A ∩# C ) by (fact subset-mset.inf .left-commute) lemmas multiset-inter-ac = multiset-inter-commute multiset-inter-assoc multiset-inter-left-commute lemma mset-le-not-refl: ¬ M < (M :: 0a::preorder multiset) by (fact less-irrefl) lemma mset-le-trans: K < M =⇒ M < N =⇒ K < (N :: 0a::preorder multiset) by (fact less-trans) lemma mset-le-not-sym: M < N =⇒ ¬ N < (M :: 0a::preorder multiset) by (fact less-not-sym) lemma mset-le-asym: M < N =⇒ (¬ P =⇒ N < (M :: 0a::preorder multiset)) =⇒ P by (fact less-asym) declaration h let

207 fun multiset-postproc - maybe-name all-values (T as Type (-, [elem-T ])) (Const - $ t 0) = let val (maybe-opt, ps) = Nitpick-Model.dest-plain-fun t 0 ||> op ∼∼ ||> map (apsnd (snd o HOLogic.dest-number)) fun elems-for t = (case AList.lookup (op =) ps t of SOME n => replicate n t | NONE => [Const (maybe-name, elem-T −−> elem-T ) $ t]) in (case maps elems-for (all-values elem-T )@ (if maybe-opt then [Const (Nitpick-Model.unrep-mixfix (), elem-T )] else []) of [] => Const (@{const-name zero-class.zero}, T ) | ts => foldl1 (fn (s, t) => Const (@{const-name add-mset}, elem-T −−> T −−> T ) $ s $ t) ts) end | multiset-postproc - - - - t = t in Nitpick-Model.register-term-postprocessor @{typ 0a multiset} multiset-postproc end i

31.16 Naive implementation using lists code-datatype mset lemma [code]: {#} = mset [] by simp lemma [code]: add-mset x (mset xs) = mset (x # xs) by simp lemma [code]: Multiset.is-empty (mset xs) ←→ List.null xs by (simp add: Multiset.is-empty-def List.null-def ) lemma union-code [code]: mset xs + mset ys = mset (xs @ ys) by simp lemma [code]: image-mset f (mset xs) = mset (map f xs) by simp lemma [code]: filter-mset f (mset xs) = mset (filter f xs) by (simp add: mset-filter) lemma [code]: mset xs − mset ys = mset (fold remove1 ys xs)

208 by (rule sym, induct ys arbitrary: xs)(simp-all add: diff-add diff-right-commute diff-diff-add) lemma [code]: mset xs ∩# mset ys = mset (snd (fold (λx (ys, zs). if x ∈ set ys then (remove1 x ys, x # zs) else (ys, zs)) xs (ys, []))) proof − have Vzs. mset (snd (fold (λx (ys, zs). if x ∈ set ys then (remove1 x ys, x # zs) else (ys, zs)) xs (ys, zs))) = (mset xs ∩# mset ys) + mset zs by (induct xs arbitrary: ys) (auto simp add: inter-add-right1 inter-add-right2 ac-simps) then show ?thesis by simp qed lemma [code]: mset xs ∪# mset ys = mset (case-prod append (fold (λx (ys, zs). (remove1 x ys, x # zs)) xs (ys, []))) proof − have Vzs. mset (case-prod append (fold (λx (ys, zs). (remove1 x ys, x # zs)) xs (ys, zs))) = (mset xs ∪# mset ys) + mset zs by (induct xs arbitrary: ys)(simp-all add: multiset-eq-iff ) then show ?thesis by simp qed declare in-multiset-in-set [code-unfold] lemma [code]: count (mset xs) x = fold (λy. if x = y then Suc else id) xs 0 proof − have Vn. fold (λy. if x = y then Suc else id) xs n = count (mset xs) x + n by (induct xs) simp-all then show ?thesis by simp qed declare set-mset-mset [code] declare sorted-list-of-multiset-mset [code] lemma [code]: — not very efficient, but representation-ignorant! mset-set A = mset (sorted-list-of-set A) apply (cases finite A) apply simp-all apply (induct A rule: finite-induct) apply simp-all done declare size-mset [code]

209 fun subset-eq-mset-impl :: 0a list ⇒ 0a list ⇒ bool option where subset-eq-mset-impl [] ys = Some (ys 6= []) | subset-eq-mset-impl (Cons x xs) ys = (case List.extract (op = x) ys of None ⇒ None | Some (ys1 ,-,ys2 ) ⇒ subset-eq-mset-impl xs (ys1 @ ys2 )) lemma subset-eq-mset-impl:(subset-eq-mset-impl xs ys = None ←→ ¬ mset xs ⊆# mset ys) ∧ (subset-eq-mset-impl xs ys = Some True ←→ mset xs ⊂# mset ys) ∧ (subset-eq-mset-impl xs ys = Some False −→ mset xs = mset ys) proof (induct xs arbitrary: ys) case (Nil ys) show ?case by (auto simp: subset-mset.zero-less-iff-neq-zero) next case (Cons x xs ys) show ?case proof (cases List.extract (op = x) ys) case None hence x: x ∈/ set ys by (simp add: extract-None-iff ) { assume mset (x # xs) ⊆# mset ys from set-mset-mono[OF this] x have False by simp } note nle = this moreover { assume mset (x # xs) ⊂# mset ys hence mset (x # xs) ⊆# mset ys by auto from nle[OF this] have False . } ultimately show ?thesis using None by auto next case (Some res) obtain ys1 y ys2 where res: res = (ys1 ,y,ys2 ) by (cases res, auto) note Some = Some[unfolded res] from extract-SomeE[OF Some] have ys = ys1 @ x # ys2 by simp hence id: mset ys = add-mset x (mset (ys1 @ ys2 )) by auto show ?thesis unfolding subset-eq-mset-impl.simps unfolding Some option.simps split unfolding id using Cons[of ys1 @ ys2 ] unfolding subset-mset-def subseteq-mset-def by auto qed qed lemma [code]: mset xs ⊆# mset ys ←→ subset-eq-mset-impl xs ys 6= None using subset-eq-mset-impl[of xs ys] by (cases subset-eq-mset-impl xs ys, auto)

210 lemma [code]: mset xs ⊂# mset ys ←→ subset-eq-mset-impl xs ys = Some True using subset-eq-mset-impl[of xs ys] by (cases subset-eq-mset-impl xs ys, auto) instantiation multiset :: (equal) equal begin definition [code del]: HOL.equal A (B :: 0a multiset) ←→ A = B lemma [code]: HOL.equal (mset xs)(mset ys) ←→ subset-eq-mset-impl xs ys = Some False unfolding equal-multiset-def using subset-eq-mset-impl[of xs ys] by (cases subset-eq-mset-impl xs ys, auto) instance by standard (simp add: equal-multiset-def ) end lemma [code]: sum-mset (mset xs) = sum-list xs by (induct xs) simp-all lemma [code]: prod-mset (mset xs) = fold times xs 1 proof − have Vx. fold times xs x = prod-mset (mset xs) ∗ x by (induct xs)(simp-all add: ac-simps) then show ?thesis by simp qed

Exercise for the casual reader: add implementations for op ≤ and op < (multiset order).

Quickcheck generators definition (in term-syntax) msetify :: 0a::typerep list × (unit ⇒ Code-Evaluation.term) ⇒ 0a multiset × (unit ⇒ Code-Evaluation.term) where [code-unfold]: msetify xs = Code-Evaluation.valtermify mset {·} xs notation fcomp (infixl ◦> 60 ) notation scomp (infixl ◦→ 60 ) instantiation multiset :: (random) random begin definition Quickcheck-Random.random i = Quickcheck-Random.random i ◦→ (λxs. Pair (msetify xs)) instance ..

211 end no-notation fcomp (infixl ◦> 60 ) no-notation scomp (infixl ◦→ 60 ) instantiation multiset :: (full-exhaustive) full-exhaustive begin definition full-exhaustive-multiset :: ( 0a multiset × (unit ⇒ term) ⇒ (bool × term list) option) ⇒ natural ⇒ (bool × term list) option where full-exhaustive-multiset f i = Quickcheck-Exhaustive.full-exhaustive (λxs. f (msetify xs)) i instance .. end hide-const (open) msetify

31.17 BNF setup definition rel-mset where rel-mset R X Y ←→ (∃ xs ys. mset xs = X ∧ mset ys = Y ∧ list-all2 R xs ys) lemma mset-zip-take-Cons-drop-twice: assumes length xs = length ys j ≤ length xs shows mset (zip (take j xs @ x # drop j xs)(take j ys @ y # drop j ys)) = add-mset (x,y)(mset (zip xs ys)) using assms proof (induct xs ys arbitrary: x y j rule: list-induct2 ) case Nil thus ?case by simp next case (Cons x xs y ys) thus ?case proof (cases j = 0 ) case True thus ?thesis by simp next case False then obtain k where k: j = Suc k by (cases j ) simp hence k ≤ length xs using Cons.prems by auto hence mset (zip (take k xs @ x # drop k xs)(take k ys @ y # drop k ys)) = add-mset (x,y)(mset (zip xs ys))

212 by (rule Cons.hyps(2 )) thus ?thesis unfolding k by auto qed qed lemma ex-mset-zip-left: assumes length xs = length ys mset xs 0 = mset xs shows ∃ ys 0. length ys 0 = length xs 0 ∧ mset (zip xs 0 ys 0) = mset (zip xs ys) using assms proof (induct xs ys arbitrary: xs 0 rule: list-induct2 ) case Nil thus ?case by auto next case (Cons x xs y ys xs 0) obtain j where j-len: j < length xs 0 and nth-j : xs 0 ! j = x by (metis Cons.prems in-set-conv-nth list.set-intros(1 ) mset-eq-setD)

define xsa where xsa = take j xs 0 @ drop (Suc j ) xs 0 have mset xs 0 = {#x#} + mset xsa unfolding xsa-def using j-len nth-j by (metis Cons-nth-drop-Suc union-mset-add-mset-right add-mset-remove-trivial add-diff-cancel-left 0 append-take-drop-id mset.simps(2 ) mset-append) hence ms-x: mset xsa = mset xs by (simp add: Cons.prems) then obtain ysa where len-a: length ysa = length xsa and ms-a: mset (zip xsa ysa) = mset (zip xs ys) using Cons.hyps(2 ) by blast

define ys 0 where ys 0 = take j ysa @ y # drop j ysa have xs 0: xs 0 = take j xsa @ x # drop j xsa using ms-x j-len nth-j Cons.prems xsa-def by (metis append-eq-append-conv append-take-drop-id diff-Suc-Suc Cons-nth-drop-Suc length-Cons length-drop size-mset) have j-len 0: j ≤ length xsa using j-len xs 0 xsa-def by (metis add-Suc-right append-take-drop-id length-Cons length-append less-eq-Suc-le not-less) have length ys 0 = length xs 0 unfolding ys 0-def using Cons.prems len-a ms-x by (metis add-Suc-right append-take-drop-id length-Cons length-append mset-eq-length) moreover have mset (zip xs 0 ys 0) = mset (zip (x # xs)(y # ys)) unfolding xs 0 ys 0-def by (rule trans[OF mset-zip-take-Cons-drop-twice]) (auto simp: len-a ms-a j-len 0) ultimately show ?case

213 by blast qed lemma list-all2-reorder-left-invariance: assumes rel: list-all2 R xs ys and ms-x: mset xs 0 = mset xs shows ∃ ys 0. list-all2 R xs 0 ys 0 ∧ mset ys 0 = mset ys proof − have len: length xs = length ys using rel list-all2-conv-all-nth by auto obtain ys 0 where len 0: length xs 0 = length ys 0 and ms-xy: mset (zip xs 0 ys 0) = mset (zip xs ys) using len ms-x by (metis ex-mset-zip-left) have list-all2 R xs 0 ys 0 using assms(1 ) len 0 ms-xy unfolding list-all2-iff by (blast dest: mset-eq-setD) moreover have mset ys 0 = mset ys using len len 0 ms-xy map-snd-zip mset-map by metis ultimately show ?thesis by blast qed lemma ex-mset: ∃ xs. mset xs = X by (induct X )(simp, metis mset.simps(2 )) inductive pred-mset :: ( 0a ⇒ bool) ⇒ 0a multiset ⇒ bool where pred-mset P {#} | [[P a; pred-mset P M ]] =⇒ pred-mset P (add-mset a M ) bnf 0a multiset map: image-mset sets: set-mset bd: natLeq wits: {#} rel: rel-mset pred: pred-mset proof − show image-mset id = id by (rule image-mset.id) show image-mset (g ◦ f ) = image-mset g ◦ image-mset f for f g unfolding comp-def by (rule ext)(simp add: comp-def image-mset.compositionality) show (Vz. z ∈ set-mset X =⇒ f z = g z) =⇒ image-mset f X = image-mset g X for f g X by (induct X ) simp-all show set-mset ◦ image-mset f = op ‘ f ◦ set-mset for f by auto show card-order natLeq by (rule natLeq-card-order) show BNF-Cardinal-Arithmetic.cinfinite natLeq by (rule natLeq-cinfinite)

214 show ordLeq3 (card-of (set-mset X )) natLeq for X by transfer (auto intro!: ordLess-imp-ordLeq simp: finite-iff-ordLess-natLeq[symmetric] multiset-def ) show rel-mset R OO rel-mset S ≤ rel-mset (R OO S) for RS unfolding rel-mset-def [abs-def ] OO-def apply clarify subgoal for X Z Y xs ys 0 ys zs apply (drule list-all2-reorder-left-invariance [where xs = ys 0 and ys = zs and xs 0 = ys]) apply (auto intro: list-all2-trans) done done show rel-mset R = (λx y. ∃ z. set-mset z ⊆ {(x, y). R x y} ∧ image-mset fst z = x ∧ image-mset snd z = y) for R unfolding rel-mset-def [abs-def ] apply (rule ext)+ apply safe apply (rule-tac x = mset (zip xs ys) in exI ; auto simp: in-set-zip list-all2-iff mset-map[symmetric]) apply (rename-tac XY ) apply (cut-tac X = XY in ex-mset) apply (erule exE) apply (rename-tac xys) apply (rule-tac x = map fst xys in exI ) apply (auto simp: mset-map) apply (rule-tac x = map snd xys in exI ) apply (auto simp: mset-map list-all2I subset-eq zip-map-fst-snd) done show z ∈ set-mset {#} =⇒ False for z by auto show pred-mset P = (λx. Ball (set-mset x) P) for P proof (intro ext iffI ) fix x assume pred-mset P x then show Ball (set-mset x) P by (induct pred: pred-mset; simp) next fix x assume Ball (set-mset x) P then show pred-mset P x by (induct x; auto intro: pred-mset.intros) qed qed inductive rel-mset 0 where Zero[intro]: rel-mset 0 R {#}{#} | Plus[intro]: [[R a b; rel-mset 0 RMN ]] =⇒ rel-mset 0 R (add-mset a M )(add-mset b N )

215 lemma rel-mset-Zero: rel-mset R {#}{#} unfolding rel-mset-def Grp-def by auto declare multiset.count[simp] declare Abs-multiset-inverse[simp] declare multiset.count-inverse[simp] declare union-preserves-multiset[simp] lemma rel-mset-Plus: assumes ab: R a b and MN : rel-mset R M N shows rel-mset R (add-mset a M )(add-mset b N ) proof − have ∃ ya. add-mset a (image-mset fst y) = image-mset fst ya ∧ add-mset b (image-mset snd y) = image-mset snd ya ∧ set-mset ya ⊆ {(x, y). R x y} if R a b and set-mset y ⊆ {(x, y). R x y} for y using that by (intro exI [of - add-mset (a,b) y]) auto thus ?thesis using assms unfolding multiset.rel-compp-Grp Grp-def by blast qed lemma rel-mset 0-imp-rel-mset: rel-mset 0 RMN =⇒ rel-mset R M N by (induct rule: rel-mset 0.induct)(auto simp: rel-mset-Zero rel-mset-Plus) lemma rel-mset-size: rel-mset R M N =⇒ size M = size N unfolding multiset.rel-compp-Grp Grp-def by auto lemma multiset-induct2 [case-names empty addL addR]: assumes empty: P {#}{#} and addL: Va M N . PMN =⇒ P (add-mset a M ) N and addR: Va M N . PMN =⇒ PM (add-mset a N ) shows PMN apply(induct N rule: multiset-induct) apply(induct M rule: multiset-induct, rule empty, erule addL) apply(induct M rule: multiset-induct, erule addR, erule addR) done lemma multiset-induct2-size[consumes 1 , case-names empty add]: assumes c: size M = size N and empty: P {#}{#} and add: Va b M N a b. PMN =⇒ P (add-mset a M )(add-mset b N ) shows PMN using c proof (induct M arbitrary: N rule: measure-induct-rule[of size]) case (less M ) show ?case

216 proof(cases M = {#}) case True hence N = {#} using less.prems by auto thus ?thesis using True empty by auto next case False then obtain M1 a where M : M = add-mset a M1 by (metis multi-nonempty-split) have N 6= {#} using False less.prems by auto then obtain N1 b where N : N = add-mset b N1 by (metis multi-nonempty-split) have size M1 = size N1 using less.prems unfolding MN by auto thus ?thesis using M N less.hyps add by auto qed qed lemma msed-map-invL: assumes image-mset f (add-mset a M ) = N shows ∃ N1 . N = add-mset (f a) N1 ∧ image-mset f M = N1 proof − have f a ∈# N using assms multiset.set-map[of f add-mset a M ] by auto then obtain N1 where N : N = add-mset (f a) N1 using multi-member-split by metis have image-mset f M = N1 using assms unfolding N by simp thus ?thesis using N by blast qed lemma msed-map-invR: assumes image-mset f M = add-mset b N shows ∃ M1 a. M = add-mset a M1 ∧ f a = b ∧ image-mset f M1 = N proof − obtain a where a: a ∈# M and fa: f a = b using multiset.set-map[of f M ] unfolding assms by (metis image-iff union-single-eq-member) then obtain M1 where M : M = add-mset a M1 using multi-member-split by metis have image-mset f M1 = N using assms unfolding M fa[symmetric] by simp thus ?thesis using M fa by blast qed lemma msed-rel-invL: assumes rel-mset R (add-mset a M ) N shows ∃ N1 b. N = add-mset b N1 ∧ R a b ∧ rel-mset R M N1 proof − obtain K where KM : image-mset fst K = add-mset a M and KN : image-mset snd K = N and sK : set-mset K ⊆ {(a, b). R a b} using assms unfolding multiset.rel-compp-Grp Grp-def by auto obtain K1 ab where K : K = add-mset ab K1 and a: fst ab = a and K1M : image-mset fst K1 = M using msed-map-invR[OF KM ] by auto obtain N1 where N : N = add-mset (snd ab) N1 and K1N1 : image-mset snd

217 K1 = N1 using msed-map-invL[OF KN [unfolded K ]] by auto have Rab: R a (snd ab) using sK a unfolding K by auto have rel-mset R M N1 using sK K1M K1N1 unfolding K multiset.rel-compp-Grp Grp-def by auto thus ?thesis using N Rab by auto qed lemma msed-rel-invR: assumes rel-mset R M (add-mset b N ) shows ∃ M1 a. M = add-mset a M1 ∧ R a b ∧ rel-mset R M1 N proof − obtain K where KN : image-mset snd K = add-mset b N and KM : image-mset fst K = M and sK : set-mset K ⊆ {(a, b). R a b} using assms unfolding multiset.rel-compp-Grp Grp-def by auto obtain K1 ab where K : K = add-mset ab K1 and b: snd ab = b and K1N : image-mset snd K1 = N using msed-map-invR[OF KN ] by auto obtain M1 where M : M = add-mset (fst ab) M1 and K1M1 : image-mset fst K1 = M1 using msed-map-invL[OF KM [unfolded K ]] by auto have Rab: R (fst ab) b using sK b unfolding K by auto have rel-mset R M1 N using sK K1N K1M1 unfolding K multiset.rel-compp-Grp Grp-def by auto thus ?thesis using M Rab by auto qed lemma rel-mset-imp-rel-mset 0: assumes rel-mset R M N shows rel-mset 0 RMN using assms proof(induct M arbitrary: N rule: measure-induct-rule[of size]) case (less M ) have c: size M = size N using rel-mset-size[OF less.prems] . show ?case proof(cases M = {#}) case True hence N = {#} using c by simp thus ?thesis using True rel-mset 0.Zero by auto next case False then obtain M1 a where M : M = add-mset a M1 by (metis multi-nonempty-split) obtain N1 b where N : N = add-mset b N1 and R: R a b and ms: rel-mset R M1 N1 using msed-rel-invL[OF less.prems[unfolded M ]] by auto have rel-mset 0 R M1 N1 using less.hyps[of M1 N1 ] ms unfolding M by simp thus ?thesis using rel-mset 0.Plus[of R a b, OF R] unfolding MN by simp qed qed lemma rel-mset-rel-mset 0: rel-mset R M N = rel-mset 0 RMN

218 using rel-mset-imp-rel-mset 0 rel-mset 0-imp-rel-mset by auto

The main end product for rel-mset: inductive characterization: lemmas rel-mset-induct[case-names empty add, induct pred: rel-mset] = rel-mset 0.induct[unfolded rel-mset-rel-mset 0[symmetric]]

31.18 Size setup lemma multiset-size-o-map: size-multiset g ◦ image-mset f = size-multiset (g ◦ f ) apply (rule ext) subgoal for x by (induct x) auto done setup h BNF-LFP-Size.register-size-global @{type-name multiset} @{const-name size-multiset} @{thm size-multiset-overloaded-def } @{thms size-multiset-empty size-multiset-single size-multiset-union size-empty size-single size-union} @{thms multiset-size-o-map} i hide-const (open) wcount end

32 Bubblesort theory Bubblesort imports ∼∼/src/HOL/Library/Multiset begin

This is a version of bubblesort. context linorder begin fun bubble-min where bubble-min [] = [] | bubble-min [x] = [x] | bubble-min (x#xs) = (case bubble-min xs of y#ys ⇒ if x>y then y#x#ys else x#y#ys) lemma size-bubble-min: size(bubble-min xs) = size xs by(induction xs rule: bubble-min.induct)(auto split: list.split) lemma bubble-min-eq-Nil-iff [simp]: bubble-min xs = [] ←→ xs = [] by (metis length-0-conv size-bubble-min)

219 lemma bubble-minD-size: bubble-min (xs) = ys =⇒ size xs = size ys by(auto simp: size-bubble-min) function (sequential) bubblesort where bubblesort [] = [] | bubblesort [x] = [x] | bubblesort xs = (case bubble-min xs of y#ys ⇒ y # bubblesort ys) by pat-completeness auto termination proof show wf (measure size) by simp next fix x1 x2 y :: 0a fix xs ys :: 0a list show bubble-min(x1 #x2 #xs) = y#ys =⇒ (ys, x1 #x2 #xs) ∈ measure size by(auto simp: size-bubble-min dest!: bubble-minD-size split: list.splits if-splits) qed lemma mset-bubble-min: mset (bubble-min xs) = mset xs apply(induction xs rule: bubble-min.induct) apply simp apply simp apply (auto simp: add-eq-conv-ex split: list.split) done lemma bubble-minD-mset: bubble-min (xs) = ys =⇒ mset xs = mset ys by(auto simp: mset-bubble-min) lemma mset-bubblesort: mset (bubblesort xs) = mset xs apply(induction xs rule: bubblesort.induct) apply simp apply simp by(auto split: list.splits if-splits dest: bubble-minD-mset) lemma set-bubblesort: set (bubblesort xs) = set xs by(rule mset-bubblesort[THEN mset-eq-setD]) lemma bubble-min-min: bubble-min xs = y#ys =⇒ z ∈ set ys =⇒ y ≤ z apply(induction xs arbitrary: y ys z rule: bubble-min.induct) apply simp apply simp apply (fastforce split: list.splits if-splits dest!: sym[of a#b for a b]) done lemma sorted-bubblesort: sorted(bubblesort xs) apply(induction xs rule: bubblesort.induct)

220 apply simp apply simp apply (fastforce simp: set-bubblesort split: list.split if-splits intro!: sorted.Cons dest: bubble-min-min) done end end

33 Merge Sort theory MergeSort imports ∼∼/src/HOL/Library/Multiset begin context linorder begin fun merge :: 0a list ⇒ 0a list ⇒ 0a list where merge (x#xs)(y#ys) = (if x ≤ y then x # merge xs (y#ys) else y # merge (x#xs) ys) | merge xs [] = xs | merge [] ys = ys lemma mset-merge [simp]: mset (merge xs ys) = mset xs + mset ys by (induct xs ys rule: merge.induct)(simp-all add: ac-simps) lemma set-merge [simp]: set (merge xs ys) = set xs ∪ set ys by (induct xs ys rule: merge.induct) auto lemma sorted-merge [simp]: sorted (merge xs ys) ←→ sorted xs ∧ sorted ys by (induct xs ys rule: merge.induct)(auto simp add: ball-Un not-le less-le sorted-Cons) fun msort :: 0a list ⇒ 0a list where msort [] = [] | msort [x] = [x] | msort xs = merge (msort (take (size xs div 2 ) xs)) (msort (drop (size xs div 2 ) xs)) lemma sorted-msort: sorted (msort xs) by (induct xs rule: msort.induct) simp-all

221 lemma mset-msort: mset (msort xs) = mset xs by (induct xs rule: msort.induct) (simp-all, metis append-take-drop-id drop-Suc-Cons mset.simps(2 ) mset-append take-Suc-Cons) theorem msort-sort: sort = msort by (rule ext, rule properties-for-sort)(fact mset-msort sorted-msort)+ end end

34 A lemma for Lagrange’s theorem theory Lagrange imports Main begin

This theory only contains a single theorem, which is a lemma in Lagrange’s proof that every natural number is the sum of 4 squares. Its sole purpose is to demonstrate ordered rewriting for commutative rings. The enterprising reader might consider proving all of Lagrange’s theorem. definition sq :: 0a::times => 0a where sq x == x∗x

The following lemma essentially shows that every natural number is the sum of four squares, provided all prime numbers are. However, this is an abstract theorem about commutative rings. It has, a priori, nothing to do with nat. lemma Lagrange-lemma: fixes x1 :: 0a::comm-ring shows (sq x1 + sq x2 + sq x3 + sq x4 ) ∗ (sq y1 + sq y2 + sq y3 + sq y4 ) = sq (x1 ∗y1 − x2 ∗y2 − x3 ∗y3 − x4 ∗y4 ) + sq (x1 ∗y2 + x2 ∗y1 + x3 ∗y4 − x4 ∗y3 ) + sq (x1 ∗y3 − x2 ∗y4 + x3 ∗y1 + x4 ∗y2 ) + sq (x1 ∗y4 + x2 ∗y3 − x3 ∗y2 + x4 ∗y1 ) by (simp only: sq-def algebra-simps)

A challenge by John Harrison. Takes about 12s on a 1.6GHz machine. lemma fixes p1 :: 0a::comm-ring shows (sq p1 + sq q1 + sq r1 + sq s1 + sq t1 + sq u1 + sq v1 + sq w1 ) ∗ (sq p2 + sq q2 + sq r2 + sq s2 + sq t2 + sq u2 + sq v2 + sq w2 ) = sq (p1 ∗p2 − q1 ∗q2 − r1 ∗r2 − s1 ∗s2 − t1 ∗t2 − u1 ∗u2 − v1 ∗v2 − w1 ∗w2 ) + sq (p1 ∗q2 + q1 ∗p2 + r1 ∗s2 − s1 ∗r2 + t1 ∗u2 − u1 ∗t2 − v1 ∗w2 + w1 ∗v2 ) + sq (p1 ∗r2 − q1 ∗s2 + r1 ∗p2 + s1 ∗q2 + t1 ∗v2 + u1 ∗w2 − v1 ∗t2 − w1 ∗u2 ) + sq (p1 ∗s2 + q1 ∗r2 − r1 ∗q2 + s1 ∗p2 + t1 ∗w2 − u1 ∗v2 + v1 ∗u2 − w1 ∗t2 ) +

222 sq (p1 ∗t2 − q1 ∗u2 − r1 ∗v2 − s1 ∗w2 + t1 ∗p2 + u1 ∗q2 + v1 ∗r2 + w1 ∗s2 ) + sq (p1 ∗u2 + q1 ∗t2 − r1 ∗w2 + s1 ∗v2 − t1 ∗q2 + u1 ∗p2 − v1 ∗s2 + w1 ∗r2 ) + sq (p1 ∗v2 + q1 ∗w2 + r1 ∗t2 − s1 ∗u2 − t1 ∗r2 + u1 ∗s2 + v1 ∗p2 − w1 ∗q2 ) + sq (p1 ∗w2 − q1 ∗v2 + r1 ∗u2 + s1 ∗t2 − t1 ∗s2 − u1 ∗r2 + v1 ∗q2 + w1 ∗p2 ) by (simp only: sq-def algebra-simps) end

35 Groebner Basis Examples theory Groebner-Examples imports ∼∼/src/HOL/Groebner-Basis begin

35.1 Basic examples lemma fixes x :: int shows x ˆ 3 = x ˆ 3 apply (tactic hALLGOALS (CONVERSION (Conv.arg-conv (Conv.arg1-conv (Semiring-Normalizer.semiring-normalize-conv @{context}))))i) by (rule refl) lemma fixes x :: int shows (x − (−2 ))ˆ5 = x ˆ 5 + (10 ∗ x ˆ 4 + (40 ∗ x ˆ 3 + (80 ∗ x 2 + (80 ∗ x + 32 )))) apply (tactic hALLGOALS (CONVERSION (Conv.arg-conv (Conv.arg1-conv (Semiring-Normalizer.semiring-normalize-conv @{context}))))i) by (rule refl) schematic-goal fixes x :: int shows (x − (−2 ))ˆ5 ∗ (y − 78 ) ˆ 8 = ?X apply (tactic hALLGOALS (CONVERSION (Conv.arg-conv (Conv.arg1-conv (Semiring-Normalizer.semiring-normalize-conv @{context}))))i) by (rule refl) lemma ((−3 ) ˆ (Suc (Suc (Suc 0 )))) == (X :: 0a::{comm-ring-1 }) apply (simp only: power-Suc power-0 ) apply (simp only: semiring-norm) oops

223 lemma ((x::int) + y)ˆ3 − 1 = (x − z)ˆ2 − 10 =⇒ x = z + 3 =⇒ x = − y by algebra lemma (4 ::nat) + 4 = 3 + 5 by algebra lemma (4 ::int) + 0 = 4 apply algebra? by simp lemma assumes a ∗ x 2 + b ∗ x + c = (0 ::int) and d ∗ x 2 + e ∗ x + f = 0 shows d 2 ∗ c2 − 2 ∗ d ∗ c ∗ a ∗ f + a2 ∗ f 2 − e ∗ d ∗ b ∗ c − e ∗ b ∗ a ∗ f + a ∗ e2 ∗ c + f ∗ d ∗ b2 = 0 using assms by algebra lemma (x::int)ˆ3 − xˆ2 − 5 ∗x − 3 = 0 ←→ (x = 3 ∨ x = −1 ) by algebra theorem x∗ (x 2 − x − 5 ) − 3 = (0 ::int) ←→ (x = 3 ∨ x = −1 ) by algebra lemma fixes x:: 0a::idom shows x 2∗y = x 2 & x∗y2 = y2 ←→ x = 1 & y = 1 | x = 0 & y = 0 by algebra

35.2 Lemmas for Lagrange’s theorem definition sq :: 0a::times => 0a where sq x == x∗x lemma fixes x1 :: 0a::{idom} shows (sq x1 + sq x2 + sq x3 + sq x4 ) ∗ (sq y1 + sq y2 + sq y3 + sq y4 ) = sq (x1 ∗y1 − x2 ∗y2 − x3 ∗y3 − x4 ∗y4 ) + sq (x1 ∗y2 + x2 ∗y1 + x3 ∗y4 − x4 ∗y3 ) + sq (x1 ∗y3 − x2 ∗y4 + x3 ∗y1 + x4 ∗y2 ) + sq (x1 ∗y4 + x2 ∗y3 − x3 ∗y2 + x4 ∗y1 ) by (algebra add: sq-def ) lemma fixes p1 :: 0a::{idom} shows (sq p1 + sq q1 + sq r1 + sq s1 + sq t1 + sq u1 + sq v1 + sq w1 ) ∗ (sq p2 + sq q2 + sq r2 + sq s2 + sq t2 + sq u2 + sq v2 + sq w2 ) = sq (p1 ∗p2 − q1 ∗q2 − r1 ∗r2 − s1 ∗s2 − t1 ∗t2 − u1 ∗u2 − v1 ∗v2 − w1 ∗w2 )

224 + sq (p1 ∗q2 + q1 ∗p2 + r1 ∗s2 − s1 ∗r2 + t1 ∗u2 − u1 ∗t2 − v1 ∗w2 + w1 ∗v2 ) + sq (p1 ∗r2 − q1 ∗s2 + r1 ∗p2 + s1 ∗q2 + t1 ∗v2 + u1 ∗w2 − v1 ∗t2 − w1 ∗u2 ) + sq (p1 ∗s2 + q1 ∗r2 − r1 ∗q2 + s1 ∗p2 + t1 ∗w2 − u1 ∗v2 + v1 ∗u2 − w1 ∗t2 ) + sq (p1 ∗t2 − q1 ∗u2 − r1 ∗v2 − s1 ∗w2 + t1 ∗p2 + u1 ∗q2 + v1 ∗r2 + w1 ∗s2 ) + sq (p1 ∗u2 + q1 ∗t2 − r1 ∗w2 + s1 ∗v2 − t1 ∗q2 + u1 ∗p2 − v1 ∗s2 + w1 ∗r2 ) + sq (p1 ∗v2 + q1 ∗w2 + r1 ∗t2 − s1 ∗u2 − t1 ∗r2 + u1 ∗s2 + v1 ∗p2 − w1 ∗q2 ) + sq (p1 ∗w2 − q1 ∗v2 + r1 ∗u2 + s1 ∗t2 − t1 ∗s2 − u1 ∗r2 + v1 ∗q2 + w1 ∗p2 ) by (algebra add: sq-def )

35.3 Colinearity is invariant by rotation type-synonym point = int × int definition collinear ::point ⇒ point ⇒ point ⇒ bool where collinear ≡ λ(Ax,Ay)(Bx,By)(Cx,Cy). ((Ax − Bx) ∗ (By − Cy) = (Ay − By) ∗ (Bx − Cx)) lemma collinear-inv-rotation: assumes collinear (Ax, Ay)(Bx, By)(Cx, Cy) and c2 + s2 = 1 shows collinear (Ax ∗ c − Ay ∗ s, Ay ∗ c + Ax ∗ s) (Bx ∗ c − By ∗ s, By ∗ c + Bx ∗ s)(Cx ∗ c − Cy ∗ s, Cy ∗ c + Cx ∗ s) using assms by (algebra add: collinear-def split-def fst-conv snd-conv) lemma EX (d::int). a∗y − a∗x = n∗d =⇒ EX u v. a∗u + n∗v = 1 =⇒ EX e. y − x = n∗e by algebra end

36 Substitution and Unification theory Unification imports Main begin

Implements Manna & Waldinger’s formalization, with Paulson’s simplifica- tions, and some new simplifications by Slind and Krauss. Z Manna & R Waldinger, Deductive Synthesis of the Unification Algorithm. SCP 1 (1981), 5-48 L C Paulson, Verifying the Unification Algorithm in LCF. SCP 5 (1985),

225 143-170 K Slind, Reasoning about Terminating Functional Programs, Ph.D. thesis, TUM, 1999, Sect. 5.8 A Krauss, Partial and Nested Recursive Function Definitions in Higher- Order Logic, JAR 44(4):303-336, 2010. Sect. 6.3

36.1 Terms

Binary trees with leaves that are constants or variables. datatype 0a trm = Var 0a | Const 0a | Comb 0a trm 0a trm (infix · 60 ) primrec vars-of :: 0a trm ⇒ 0a set where vars-of (Var v) = {v} | vars-of (Const c) = {} | vars-of (M · N ) = vars-of M ∪ vars-of N fun occs :: 0a trm ⇒ 0a trm ⇒ bool (infixl ≺ 54 ) where u ≺ Var v ←→ False | u ≺ Const c ←→ False | u ≺ M · N ←→ u = M ∨ u = N ∨ u ≺ M ∨ u ≺ N lemma finite-vars-of [intro]: finite (vars-of t) by (induct t) simp-all lemma vars-iff-occseq: x ∈ vars-of t ←→ Var x ≺ t ∨ Var x = t by (induct t) auto lemma occs-vars-subset: M ≺ N =⇒ vars-of M ⊆ vars-of N by (induct N ) auto

36.2 Substitutions type-synonym 0a subst = ( 0a × 0a trm) list fun assoc :: 0a ⇒ 0b ⇒ ( 0a × 0b) list ⇒ 0b where assoc x d [] = d | assoc x d ((p,q)#t) = (if x = p then q else assoc x d t) primrec subst :: 0a trm ⇒ 0a subst ⇒ 0a trm (infixl 55 ) where  (Var v) s = assoc v (Var v) s  226 | (Const c) s = (Const c) | (M · N ) s = (M s) · (N s)   .  definition subst-eq (infixr = 52 ) where . s1 = s2 ←→ (∀ t. t s1 = t s2 )   0 0 0 fun comp :: a subst ⇒ a subst ⇒ a subst (infixl ♦ 56 ) where [] ♦ bl = bl | ((a,b)# al) ♦ bl = (a, b bl)#(al ♦ bl)  lemma subst-Nil[simp]: t [] = t by (induct t) auto  lemma subst-mono: t ≺ u =⇒ t s ≺ u s by (induct u) auto   lemma agreement:(t r = t s) ←→ (∀ v ∈ vars-of t. Var v r = Var v s)     by (induct t) auto lemma repl-invariance: v ∈/ vars-of t =⇒ t (v,u)# s = t s by (simp add: agreement)   lemma remove-var: v ∈/ vars-of s =⇒ v ∈/ vars-of (t [(v, s)]) by (induct t) simp-all  . lemma subst-refl[iff ]: s = s by (auto simp:subst-eq-def ) . . lemma subst-sym[sym]: [[s1 = s2 ]] =⇒ s2 = s1 by (auto simp:subst-eq-def ) . . . lemma subst-trans[trans]: [[s1 = s2 ; s2 = s3 ]] =⇒ s1 = s3 by (auto simp:subst-eq-def ) lemma subst-no-occs: ¬ Var v ≺ t =⇒ Var v 6= t =⇒ t [(v,s)] = t by (induct t) auto lemma comp-Nil[simp]: σ ♦ [] = σ by (induct σ) auto lemma subst-comp[simp]: t (r ♦ s) = t r s proof (induct t)    case (Var v) thus ?case by (induct r) auto qed auto

227 . lemma subst-eq-intro[intro]: (Vt. t σ = t ϑ) =⇒ σ = ϑ by (auto simp:subst-eq-def )   . lemma subst-eq-dest[dest]: s1 = s2 =⇒ t s1 = t s2 by (auto simp:subst-eq-def )   . lemma comp-assoc:(a ♦ b) ♦ c = a ♦ (b ♦ c) by auto

. 0 . 0 . 0 0 lemma subst-cong: [[σ = σ ; ϑ = ϑ ]] =⇒ (σ ♦ ϑ) = (σ ♦ ϑ ) by (auto simp: subst-eq-def ) . lemma var-self : [(v, Var v)] = [] proof fix t show t [(v, Var v)] = t [] by (induct t) simp-all  qed . lemma var-same[simp]: [(v, t)] = [] ←→ t = Var v by (metis assoc.simps(2 ) subst.simps(1 ) subst-eq-def var-self )

36.3 Unifiers and Most General Unifiers definition Unifier :: 0a subst ⇒ 0a trm ⇒ 0a trm ⇒ bool where Unifier σ t u ←→ (t σ = u σ)   definition MGU :: 0a subst ⇒ 0a trm ⇒ 0a trm ⇒ bool where MGU σ t u ←→ . Unifier σ t u ∧ (∀ ϑ. Unifier ϑ t u −→ (∃ γ. ϑ = σ ♦ γ)) lemma MGUI [intro]: V . [[t σ = u σ; ϑ. t ϑ = u ϑ =⇒ ∃ γ. ϑ = σ ♦ γ]] =⇒MGU σt u   by (simp only:Unifier-def MGU-def , auto) lemma MGU-sym[sym]: MGU σ s t =⇒ MGU σ t s by (auto simp:MGU-def Unifier-def ) lemma MGU-is-Unifier: MGU σ t u =⇒ Unifier σ t u unfolding MGU-def by (rule conjunct1 ) lemma MGU-Var: assumes ¬ Var v ≺ t shows MGU [(v,t)] (Var v) t proof (intro MGUI exI ) show Var v [(v,t)] = t [(v,t)] using assms by (metis assoc .simps(2 ) repl-invariance subst.simps(1 ) subst-Nil vars-iff-occseq)

228 next fix ϑ assume th: Var v ϑ = t ϑ . show ϑ = [(v,t)] ♦ ϑ   proof fix s show s ϑ = s [(v,t)] ♦ ϑ using th by (induct s) auto  qed qed lemma MGU-Const: MGU [] (Const c)(Const d) ←→ c = d by (auto simp: MGU-def Unifier-def )

36.4 The unification algorithm function unify :: 0a trm ⇒ 0a trm ⇒ 0a subst option where unify (Const c)(M · N ) = None | unify (M · N )(Const c) = None | unify (Const c)(Var v) = Some [(v, Const c)] | unify (M · N )(Var v) = (if Var v ≺ M · N then None else Some [(v, M · N )]) | unify (Var v) M = (if Var v ≺ M then None else Some [(v, M )]) | unify (Const c)(Const d) = (if c=d then Some [] else None) | unify (M · N )(M 0 · N 0) = (case unify M M 0 of None ⇒ None | Some ϑ ⇒ (case unify (N ϑ)(N 0 ϑ) of None ⇒ None |   Some σ ⇒ Some (ϑ ♦ σ))) by pat-completeness auto

36.5 Properties used in termination proof

Elimination of variables by a substitution: definition elim σ v ≡ ∀ t. v ∈/ vars-of (t σ)  lemma elim-intro[intro]: (Vt. v ∈/ vars-of (t σ)) =⇒ elim σ v by (auto simp:elim-def )  lemma elim-dest[dest]: elim σ v =⇒ v ∈/ vars-of (t σ) by (auto simp:elim-def )  . lemma elim-eq: σ = ϑ =⇒ elim σ x = elim ϑ x by (auto simp:elim-def subst-eq-def ) lemma occs-elim: ¬ Var v ≺ t

229 . =⇒ elim [(v,t)] v ∨ [(v,t)] = [] by (metis elim-intro remove-var var-same vars-iff-occseq)

The result of a unification never introduces new variables: declare unify.psimps[simp] lemma unify-vars: assumes unify-dom (M , N ) assumes unify M N = Some σ shows vars-of (t σ) ⊆ vars-of M ∪ vars-of N ∪ vars-of t (is ?P M N σ t)  using assms proof (induct M N arbitrary:σ t) case (3 c v) hence σ = [(v, Const c)] by simp thus ?case by (induct t) auto next case (4 M N v) hence ¬ Var v ≺ M · N by auto with 4 have σ = [(v, M ·N )] by simp thus ?case by (induct t) auto next case (5 v M ) hence ¬ Var v ≺ M by auto with 5 have σ = [(v, M )] by simp thus ?case by (induct t) auto next case (7 M N M 0 N 0 σ) then obtain ϑ1 ϑ2 where unify M M 0 = Some ϑ1 and unify (N ϑ1 )(N 0 ϑ1 ) = Some ϑ2 and σ: σ = ϑ1♦ ϑ2  and ih1 : Vt. ?P M M 0 ϑ1 t and ih2 : Vt. ?P (N ϑ1 )(N 0 ϑ1 ) ϑ2 t by (auto split:option.split-asm)

show ?case proof fix v assume a: v ∈ vars-of (t σ)  show v ∈ vars-of (M · N ) ∪ vars-of (M 0 · N 0) ∪ vars-of t proof (cases v ∈/ vars-of M ∧ v ∈/ vars-of M 0 ∧ v ∈/ vars-of N ∧ v ∈/ vars-of N 0) case True with ih1 have l:Vt. v ∈ vars-of (t ϑ1 ) =⇒ v ∈ vars-of t by auto 

from a and ih2 [where t=t ϑ1 ] 0 have v ∈ vars-of (N ϑ1 ) ∪ vars-of (N ϑ1 )   230 ∨ v ∈ vars-of (t ϑ1 ) unfolding σ by auto  hence v ∈ vars-of t proof assume v ∈ vars-of (N ϑ1 ) ∪ vars-of (N 0 ϑ1 ) with True show ?thesis by (auto dest:l)  next assume v ∈ vars-of (t ϑ1 ) thus ?thesis by (rule l) qed

thus ?thesis by auto qed auto qed qed (auto split: if-split-asm)

The result of a unification is either the identity substitution or it eliminates a variable from one of the terms: lemma unify-eliminates: assumes unify-dom (M , N ) assumes unify M N = Some σ . shows (∃ v∈vars-of M ∪ vars-of N . elim σ v) ∨ σ = [] (is ?P M N σ) using assms proof (induct M N arbitrary:σ) case 1 thus ?case by simp next case 2 thus ?case by simp next case (3 c v) have no-occs: ¬ Var v ≺ Const c by simp with 3 have σ = [(v, Const c)] by simp with occs-elim[OF no-occs] show ?case by auto next case (4 M N v) hence no-occs: ¬ Var v ≺ M · N by auto with 4 have σ = [(v, M ·N )] by simp with occs-elim[OF no-occs] show ?case by auto next case (5 v M ) hence no-occs: ¬ Var v ≺ M by auto with 5 have σ = [(v, M )] by simp with occs-elim[OF no-occs] show ?case by auto next case (6 c d) thus ?case by (cases c = d) auto

231 next case (7 M N M 0 N 0 σ) then obtain ϑ1 ϑ2 where unify M M 0 = Some ϑ1 and unify (N ϑ1 )(N 0 ϑ1 ) = Some ϑ2 and σ: σ = ϑ1♦ ϑ2  and ih1 : ?P M M 0 ϑ1 and ih2 : ?P (N ϑ1 )(N 0 ϑ1 ) ϑ2 by (auto split:option .split-asm )

0 0 from hunify-dom (M · N , M · N )i have unify-dom (M , M 0) by (rule accp-downward)(rule unify-rel.intros) hence no-new-vars: Vt. vars-of (t ϑ1 ) ⊆ vars-of M ∪ vars-of M 0 ∪ vars-of t 0 by (rule unify-vars )(rule hunify M M = Some ϑ1 i)

from ih2 show ?case proof assume ∃ v∈vars-of (N ϑ1 ) ∪ vars-of (N 0 ϑ1 ). elim ϑ2 v then obtain v   where v∈vars-of (N ϑ1 ) ∪ vars-of (N 0 ϑ1 ) and el: elim ϑ2 v by auto  with no-new-vars show ?thesis unfolding σ by (auto simp:elim-def ) next . assume empty[simp]: ϑ2 = [] . have σ = (ϑ1 ♦ []) unfolding σ by (rule subst-cong) auto . also have ... = ϑ1 by auto . finally have σ = ϑ1 .

from ih1 show ?thesis proof assume ∃ v∈vars-of M ∪ vars-of M 0. elim ϑ1 v . with elim-eq[OF hσ = ϑ1 i] show ?thesis by auto next . note hσ = ϑ1 i . also assume ϑ1 = [] finally show ?thesis .. qed qed qed declare unify.psimps[simp del]

232 36.6 Termination proof termination unify proof let ?R = measures [λ(M ,N ). card (vars-of M ∪ vars-of N ), λ(M , N ). size M ] show wf ?R by simp

fix MNM 0 N 0 :: 0a trm show ((M , M 0), (M · N , M 0 · N 0)) ∈ ?R — Inner call by (rule measures-lesseq)(auto intro: card-mono)

fix ϑ — Outer call assume inner: unify-dom (M , M 0) unify M M 0 = Some ϑ

from unify-eliminates[OF inner] show ((N ϑ, N 0 ϑ), (M · N , M 0 · N 0)) ∈?R proof   — Either a variable is eliminated . . . assume (∃ v∈vars-of M ∪ vars-of M 0. elim ϑ v) then obtain v where elim ϑ v and v∈vars-of M ∪ vars-of M 0 by auto with unify-vars[OF inner] have vars-of (N ϑ) ∪ vars-of (N 0 ϑ) 0 0 ⊂ vars-of (M ·N) ∪ vars-of (M ·N) by auto

thus ?thesis by (auto intro!: measures-less intro: psubset-card-mono) next — Or the substitution is empty . assume ϑ = [] hence N ϑ = N 0 0 and N  ϑ = N by auto thus ?thesis by (auto intro!: measures-less intro: psubset-card-mono) qed qed

36.7 Unification returns a Most General Unifier lemma unify-computes-MGU : unify M N = Some σ =⇒ MGU σ MN proof (induct M N arbitrary: σ rule: unify.induct) case (7 M N M 0 N 0 σ) — The interesting case

then obtain ϑ1 ϑ2 where unify M M 0 = Some ϑ1

233 and unify (N ϑ1 )(N 0 ϑ1 ) = Some ϑ2 and σ: σ = ϑ1♦ ϑ2  and MGU-inner: MGU ϑ1 M M 0 and MGU-outer: MGU ϑ2 (N ϑ1 )(N 0 ϑ1 ) by (auto split:option.split-asm)  

show ?case proof from MGU-inner and MGU-outer have M ϑ1 = M 0 ϑ1 0 and N  ϑ1 ϑ2 = N ϑ1 ϑ2 unfolding MGU-def Unifier-def  by auto thus M · N σ = M 0 · N 0 σ unfolding σ by simp   next fix σ 0 assume M · N σ 0 = M 0 · N 0 σ 0 0 0 0 hence M σ = M σ  0 0 0 and Ns: N σ = N σ by auto   with MGU-inner obtain δ 0 . where eqv: σ = ϑ1 ♦ δ unfolding MGU-def Unifier-def by auto

from Ns have N ϑ1 δ = N 0 ϑ1 δ by (simp add:subst-eq-dest  [OF eqv]) 

with MGU-outer obtain % . where eqv2 : δ = ϑ2 ♦ % unfolding MGU-def Unifier-def by auto

0 . have σ = σ ♦ % unfolding σ by (rule subst-eq-intro, auto simp:subst-eq-dest[OF eqv] subst-eq-dest[OF eqv2 ]) 0 . thus ∃ γ. σ = σ ♦ γ .. qed qed (auto simp: MGU-Const intro: MGU-Var MGU-Var[symmetric] split: if-split-asm)

36.8 Unification returns Idempotent Substitution definition Idem :: 0a subst ⇒ bool . where Idem s ←→ (s ♦ s) = s lemma Idem-Nil [iff ]: Idem [] by (simp add: Idem-def ) lemma Var-Idem: assumes ∼ (Var v ≺ t) shows Idem [(v,t)]

234 unfolding Idem-def proof from assms have [simp]: t [(v, t)] = t by (metis assoc.simps(2 ) subst .simps(1 ) subst-no-occs)

fix s show s [(v, t)] ♦ [(v, t)] = s [(v, t)] by (induct s) auto  qed lemma Unifier-Idem-subst: Idem(r) =⇒ Unifier s (t r)(u r) =⇒ Unifier (r ♦ s)(t r)(u r)  by (simp add: Idem-def Unifier-def subst-eq-def ) lemma Idem-comp: Idem r =⇒ Unifier s (t r)(u r) =⇒ . (!!q. Unifier q (t r)( u r) =⇒ s ♦ q = q) =⇒ Idem (r ♦ s)   apply (frule Unifier-Idem-subst, blast) apply (force simp add: Idem-def subst-eq-def ) done theorem unify-gives-Idem: unify M N = Some σ =⇒ Idem σ proof (induct M N arbitrary: σ rule: unify.induct) case (7 M M 0 NN 0 σ)

then obtain ϑ1 ϑ2 where unify M N = Some ϑ1 and ϑ2 : unify (M 0 ϑ1 )(N 0 ϑ1 ) = Some ϑ2 and σ: σ = ϑ1 ♦ ϑ2  and Idem ϑ1 and Idem ϑ2 by (auto split: option.split-asm)

from ϑ2 have Unifier ϑ2 (M 0 ϑ1 )(N 0 ϑ1 ) by (rule unify-computes-MGU[THEN MGU-is-Unifier ])

with hIdem ϑ1 i show Idem σ unfolding σ proof (rule Idem-comp) fix σ assume Unifier σ (M 0 ϑ1 )(N 0 ϑ1 ) . with ϑ2 obtain γ where σ: σ = ϑ2 ♦ γ using unify-computes-MGU MGU-def by blast . have ϑ2 σ = ϑ2 (ϑ2 γ) by (rule subst-cong)(auto simp: σ) ♦ . ♦ ♦ also have ... = (ϑ2 ϑ2 ) γ by (rule comp-assoc[symmetric]) . ♦ ♦ also have ... = ϑ2 ♦ γ by (rule subst-cong)(auto simp: hIdem ϑ2 i[unfolded Idem-def ])

235 . also have ... = σ by (rule σ[symmetric]) . finally show ϑ2 ♦ σ = σ . qed qed (auto intro!: Var-Idem split: option.splits if-splits) end

37 Primitive Recursive Functions theory Primrec imports Main begin

Proof adopted from Nora Szasz, A Machine Checked Proof that Ackermann’s Function is not Primitive Recursive, In: Huet & Plotkin, eds., Logical Environments (CUP, 1993), 317-338. See also E. Mendelson, Introduction to Mathematical Logic. (Van Nostrand, 1964), page 250, exercise 11.

37.1 Ackermann’s Function fun ack :: nat => nat => nat where ack 0 n = Suc n | ack (Suc m) 0 = ack m 1 | ack (Suc m)(Suc n) = ack m (ack (Suc m) n)

PROPERTY A 4 lemma less-ack2 [iff ]: j < ack i j by (induct i j rule: ack.induct) simp-all

PROPERTY A 5-, the single-step lemma lemma ack-less-ack-Suc2 [iff ]: ack i j < ack i (Suc j ) by (induct i j rule: ack.induct) simp-all

PROPERTY A 5, monotonicity for < lemma ack-less-mono2 : j < k ==> ack i j < ack i k using lift-Suc-mono-less[where f = ack i] by (metis ack-less-ack-Suc2 )

PROPERTY A 5’, monotonicity for ≤ lemma ack-le-mono2 : j ≤ k ==> ack i j ≤ ack i k apply (simp add: order-le-less) apply (blast intro: ack-less-mono2 ) done

PROPERTY A 6 lemma ack2-le-ack1 [iff ]: ack i (Suc j ) ≤ ack (Suc i) j

236 proof (induct j ) case 0 show ?case by simp next case (Suc j ) show ?case by (auto intro!: ack-le-mono2 ) (metis Suc Suc-leI Suc-lessI less-ack2 linorder-not-less) qed PROPERTY A 7-, the single-step lemma lemma ack-less-ack-Suc1 [iff ]: ack i j < ack (Suc i) j by (blast intro: ack-less-mono2 less-le-trans) PROPERTY A 4’? Extra lemma needed for CONSTANT case, constant functions lemma less-ack1 [iff ]: i < ack i j apply (induct i) apply simp-all apply (blast intro: Suc-leI le-less-trans) done PROPERTY A 8 lemma ack-1 [simp]: ack (Suc 0 ) j = j + 2 by (induct j ) simp-all PROPERTY A 9. The unary 1 and 2 in ack is essential for the rewriting. lemma ack-2 [simp]: ack (Suc (Suc 0 )) j = 2 ∗ j + 3 by (induct j ) simp-all PROPERTY A 7, monotonicity for < [not clear why ack-1 is now needed first!] lemma ack-less-mono1-aux: ack i k < ack (Suc (i +i 0)) k proof (induct i k rule: ack.induct) case (1 n) show ?case by (simp, metis ack-less-ack-Suc1 less-ack2 less-trans-Suc) next case (2 m) thus ?case by simp next case (3 m n) thus ?case by (simp, blast intro: less-trans ack-less-mono2 ) qed lemma ack-less-mono1 : i < j ==> ack i k < ack j k apply (drule less-imp-Suc-add) apply (blast intro!: ack-less-mono1-aux) done PROPERTY A 7’, monotonicity for ≤ lemma ack-le-mono1 : i ≤ j ==> ack i k ≤ ack j k

237 apply (simp add: order-le-less) apply (blast intro: ack-less-mono1 ) done

PROPERTY A 10 lemma ack-nest-bound: ack i1 (ack i2 j ) < ack (2 + (i1 + i2 )) j apply simp apply (rule ack2-le-ack1 [THEN [2 ] less-le-trans]) apply simp apply (rule le-add1 [THEN ack-le-mono1 , THEN le-less-trans]) apply (rule ack-less-mono1 [THEN ack-less-mono2 ]) apply (simp add: le-imp-less-Suc le-add2 ) done

PROPERTY A 11 lemma ack-add-bound: ack i1 j + ack i2 j < ack (4 + (i1 + i2 )) j apply (rule less-trans [of - ack (Suc (Suc 0 )) (ack (i1 + i2 ) j )]) prefer 2 apply (rule ack-nest-bound [THEN less-le-trans]) apply (simp add: Suc3-eq-add-3 ) apply simp apply (cut-tac i = i1 and m1 = i2 and k = j in le-add1 [THEN ack-le-mono1 ]) apply (cut-tac i = i2 and m1 = i1 and k = j in le-add2 [THEN ack-le-mono1 ]) apply auto done

PROPERTY A 12. Article uses existential quantifier but the ALF proof used k + 4. Quantified version must be nested ∃ k 0. ∀ i j . ... lemma ack-add-bound2 : i < ack k j ==> i + j < ack (4 + k) j apply (rule less-trans [of - ack k j + ack 0 j ]) apply (blast intro: add-less-mono) apply (rule ack-add-bound [THEN less-le-trans]) apply simp done

37.2 Primitive Recursive Functions primrec hd0 :: nat list => nat where hd0 [] = 0 | hd0 (m # ms) = m

Inductive definition of the set of primitive recursive functions of type nat list ⇒ nat. definition SC :: nat list => nat where SC l = Suc (hd0 l) definition CONSTANT :: nat => nat list => nat where CONSTANT k l = k

238 definition PROJ :: nat => nat list => nat where PROJ i l = hd0 (drop i l) definition COMP :: (nat list => nat) => (nat list => nat) list => nat list => nat where COMP g fs l = g (map (λf . f l) fs) definition PREC :: (nat list => nat) => (nat list => nat) => nat list => nat where PREC f g l = (case l of [] => 0 | x # l 0 => rec-nat (f l 0)(λy r. g (r # y # l 0)) x) — Note that g is applied first to PREC f g y and then to y! inductive PRIMREC :: (nat list => nat) => bool where SC : PRIMREC SC | CONSTANT : PRIMREC (CONSTANT k) | PROJ : PRIMREC (PROJ i) | COMP: PRIMREC g ==> ∀ f ∈ set fs. PRIMREC f ==> PRIMREC (COMP g fs) | PREC : PRIMREC f ==> PRIMREC g ==> PRIMREC (PREC f g)

Useful special cases of evaluation lemma SC [simp]: SC (x # l) = Suc x by (simp add: SC-def ) lemma CONSTANT [simp]: CONSTANT k l = k by (simp add: CONSTANT-def ) lemma PROJ-0 [simp]: PROJ 0 (x # l) = x by (simp add: PROJ-def ) lemma COMP-1 [simp]: COMP g [f ] l = g [f l] by (simp add: COMP-def ) lemma PREC-0 [simp]: PREC f g (0 # l) = f l by (simp add: PREC-def ) lemma PREC-Suc [simp]: PREC f g (Suc x # l) = g (PREC f g (x # l)# x # l) by (simp add: PREC-def )

MAIN RESULT lemma SC-case: SC l < ack 1 (sum-list l) apply (unfold SC-def ) apply (induct l) apply (simp-all add: le-add1 le-imp-less-Suc)

239 done lemma CONSTANT-case: CONSTANT k l < ack k (sum-list l) by simp lemma PROJ-case: PROJ i l < ack 0 (sum-list l) apply (simp add: PROJ-def ) apply (induct l arbitrary:i) apply (auto simp add: drop-Cons split: nat.split) apply (blast intro: less-le-trans le-add2 ) done

COMP case lemma COMP-map-aux: ∀ f ∈ set fs. PRIMREC f ∧ (∃ kf . ∀ l. f l < ack kf (sum-list l)) ==> ∃ k. ∀ l. sum-list (map (λf . f l) fs) < ack k (sum-list l) apply (induct fs) apply (rule-tac x = 0 in exI ) apply simp apply simp apply (blast intro: add-less-mono ack-add-bound less-trans) done lemma COMP-case: ∀ l. g l < ack kg (sum-list l) ==> ∀ f ∈ set fs. PRIMREC f ∧ (∃ kf . ∀ l. f l < ack kf (sum-list l)) ==> ∃ k. ∀ l. COMP g fs l < ack k (sum-list l) apply (unfold COMP-def ) apply (drule COMP-map-aux) apply (meson ack-less-mono2 ack-nest-bound less-trans) done

PREC case lemma PREC-case-aux: ∀ l. f l + sum-list l < ack kf (sum-list l) ==> ∀ l. g l + sum-list l < ack kg (sum-list l) ==> PREC f g l + sum-list l < ack (Suc (kf + kg)) (sum-list l) apply (unfold PREC-def ) apply (case-tac l) apply simp-all apply (blast intro: less-trans) apply (erule ssubst) — get rid of the needless assumption apply (induct-tac a) apply simp-all base case apply (blast intro: le-add1 [THEN le-imp-less-Suc, THEN ack-less-mono1 ] less-trans) induction step

240 apply (rule Suc-leI [THEN le-less-trans]) apply (rule le-refl [THEN add-le-mono, THEN le-less-trans]) prefer 2 apply (erule spec) apply (simp add: le-add2 )

final part of the simplification apply simp apply (rule le-add2 [THEN ack-le-mono1 , THEN le-less-trans]) apply (erule ack-less-mono2 ) done lemma PREC-case: ∀ l. f l < ack kf (sum-list l) ==> ∀ l. g l < ack kg (sum-list l) ==> ∃ k. ∀ l. PREC f g l < ack k (sum-list l) by (metis le-less-trans [OF le-add1 PREC-case-aux] ack-add-bound2 ) lemma ack-bounds-PRIMREC : PRIMREC f ==> ∃ k. ∀ l. f l < ack k (sum-list l) apply (erule PRIMREC .induct) apply (blast intro: SC-case CONSTANT-case PROJ-case COMP-case PREC-case)+ done theorem ack-not-PRIMREC : ¬ PRIMREC (λl. case l of [] => 0 | x # l 0 => ack x x) apply (rule notI ) apply (erule ack-bounds-PRIMREC [THEN exE]) apply (rule less-irrefl [THEN notE]) apply (drule-tac x = [x] in spec) apply simp done end

38 The Full Theorem of Tarski theory Tarski imports Main ∼∼/src/HOL/Library/FuncSet begin

Minimal version of lattice theory plus the full theorem of Tarski: The fixed- points of a complete lattice themselves form a complete lattice. Illustrates first-class theories, using the Sigma representation of structures. Tidied and converted to Isar by lcp. record 0a potype = pset :: 0a set order :: ( 0a ∗ 0a) set

241 definition monotone :: [ 0a => 0a, 0a set, ( 0a ∗ 0a)set] => bool where monotone f A r = (∀ x∈A. ∀ y∈A. (x, y): r −−> ((f x), (f y)) : r) definition least :: [ 0a => bool, 0a potype] => 0a where least P po = (SOME x. x: pset po & P x & (∀ y ∈ pset po. P y −−> (x,y): order po)) definition greatest :: [ 0a => bool, 0a potype] => 0a where greatest P po = (SOME x. x: pset po & P x & (∀ y ∈ pset po. P y −−> (y,x): order po)) definition lub :: [ 0a set, 0a potype] => 0a where lub S po = least (%x. ∀ y∈S. (y,x): order po) po definition glb :: [ 0a set, 0a potype] => 0a where glb S po = greatest (%x. ∀ y∈S. (x,y): order po) po definition isLub :: [ 0a set, 0a potype, 0a] => bool where isLub S po = (%L. (L: pset po &(∀ y∈S. (y,L): order po)& (∀ z∈pset po. (∀ y∈S. (y,z): order po) −−> (L,z): order po))) definition isGlb :: [ 0a set, 0a potype, 0a] => bool where isGlb S po = (%G. (G: pset po &(∀ y∈S. (G,y): order po)& (∀ z ∈ pset po. (∀ y∈S. (z,y): order po) −−> (z,G): order po))) definition fix :: [( 0a => 0a), 0a set] => 0a set where fix f A = {x. x: A & f x = x} definition interval :: [( 0a∗ 0a) set, 0a, 0a ] => 0a set where interval r a b = {x. (a,x): r &(x,b): r} definition Bot :: 0a potype => 0a where Bot po = least (%x. True) po definition Top :: 0a potype => 0a where Top po = greatest (%x. True) po

242 definition PartialOrder :: ( 0a potype) set where PartialOrder = {P. refl-on (pset P)(order P)& antisym (order P)& trans (order P)} definition CompleteLattice :: ( 0a potype) set where CompleteLattice = {cl. cl: PartialOrder & (∀ S. S ⊆ pset cl −−> (∃ L. isLub S cl L)) & (∀ S. S ⊆ pset cl −−> (∃ G. isGlb S cl G))} definition CLF-set :: ( 0a potype ∗ ( 0a => 0a)) set where CLF-set = (SIGMA cl: CompleteLattice. {f . f : pset cl → pset cl & monotone f (pset cl)(order cl)}) definition induced :: [ 0a set, ( 0a ∗ 0a) set] => ( 0a ∗ 0a)set where induced A r = {(a,b). a : A & b: A &(a,b): r} definition sublattice :: ( 0a potype ∗ 0a set)set where sublattice = (SIGMA cl: CompleteLattice. {S. S ⊆ pset cl & (| pset = S, order = induced S (order cl) |): CompleteLattice}) abbreviation sublat :: [ 0a set, 0a potype] => bool (- <<= - [51 ,50 ]50 ) where S <<= cl == S : sublattice ‘‘ {cl} definition dual :: 0a potype => 0a potype where dual po = (| pset = pset po, order = converse (order po) |) locale S = fixes cl :: 0a potype and A :: 0a set and r :: ( 0a ∗ 0a) set defines A-def : A == pset cl and r-def : r == order cl locale PO = S + assumes cl-po: cl : PartialOrder locale CL = S + assumes cl-co: cl : CompleteLattice

243 sublocale CL < po?: PO apply (simp-all add: A-def r-def ) apply unfold-locales using cl-co unfolding CompleteLattice-def by auto locale CLF = S + fixes f :: 0a => 0a and P :: 0a set assumes f-cl:(cl,f ): CLF-set defines P-def : P == fix f A sublocale CLF < cl?: CL apply (simp-all add: A-def r-def ) apply unfold-locales using f-cl unfolding CLF-set-def by auto locale Tarski = CLF + fixes Y :: 0a set and intY1 :: 0a set and v :: 0a assumes Y-ss: Y ⊆ P defines intY1-def : intY1 == interval r (lub Y cl)(Top cl) and v-def : v == glb {x. ((%x: intY1 . f x) x, x): induced intY1 r & x: intY1 } (| pset=intY1 , order=induced intY1 r|)

38.1 Partial Order lemma (in PO) dual: PO (dual cl) apply unfold-locales using cl-po unfolding PartialOrder-def dual-def by auto lemma (in PO) PO-imp-refl-on [simp]: refl-on A r apply (insert cl-po) apply (simp add: PartialOrder-def A-def r-def ) done lemma (in PO) PO-imp-sym [simp]: antisym r apply (insert cl-po) apply (simp add: PartialOrder-def r-def ) done lemma (in PO) PO-imp-trans [simp]: trans r

244 apply (insert cl-po) apply (simp add: PartialOrder-def r-def ) done lemma (in PO) reflE: x ∈ A ==> (x, x) ∈ r apply (insert cl-po) apply (simp add: PartialOrder-def refl-on-def A-def r-def ) done lemma (in PO) antisymE:[| (a, b) ∈ r;(b, a) ∈ r |] ==> a = b apply (insert cl-po) apply (simp add: PartialOrder-def antisym-def r-def ) done lemma (in PO) transE:[| (a, b) ∈ r;(b, c) ∈ r|] ==> (a,c) ∈ r apply (insert cl-po) apply (simp add: PartialOrder-def r-def ) apply (unfold trans-def , fast) done lemma (in PO) monotoneE: [| monotone f A r; x ∈ A; y ∈ A;(x, y) ∈ r |] ==> (f x, f y) ∈ r by (simp add: monotone-def ) lemma (in PO) po-subset-po: S ⊆ A ==> (| pset = S, order = induced S r |) ∈ PartialOrder apply (simp (no-asm) add: PartialOrder-def ) apply auto — refl apply (simp add: refl-on-def induced-def ) apply (blast intro: reflE) — antisym apply (simp add: antisym-def induced-def ) apply (blast intro: antisymE) — trans apply (simp add: trans-def induced-def ) apply (blast intro: transE) done lemma (in PO) indE:[| (x, y) ∈ induced S r; S ⊆ A |] ==> (x, y) ∈ r by (simp add: add: induced-def ) lemma (in PO) indI :[| (x, y) ∈ r; x ∈ S; y ∈ S |] ==> (x, y) ∈ induced S r by (simp add: add: induced-def ) lemma (in CL) CL-imp-ex-isLub: S ⊆ A ==> ∃ L. isLub S cl L apply (insert cl-co) apply (simp add: CompleteLattice-def A-def ) done

245 declare (in CL) cl-co [simp] lemma isLub-lub:(∃ L. isLub S cl L) = isLub S cl (lub S cl) by (simp add: lub-def least-def isLub-def some-eq-ex [symmetric]) lemma isGlb-glb:(∃ G. isGlb S cl G) = isGlb S cl (glb S cl) by (simp add: glb-def greatest-def isGlb-def some-eq-ex [symmetric]) lemma isGlb-dual-isLub: isGlb S cl = isLub S (dual cl) by (simp add: isLub-def isGlb-def dual-def converse-unfold) lemma isLub-dual-isGlb: isLub S cl = isGlb S (dual cl) by (simp add: isLub-def isGlb-def dual-def converse-unfold) lemma (in PO) dualPO: dual cl ∈ PartialOrder apply (insert cl-po) apply (simp add: PartialOrder-def dual-def refl-on-converse trans-converse antisym-converse) done lemma Rdual: ∀ S. (S ⊆ A −−>( ∃ L. isLub S (| pset = A, order = r|) L)) ==> ∀ S. (S ⊆ A −−> (∃ G. isGlb S (| pset = A, order = r|) G)) apply safe apply (rule-tac x = lub {y. y ∈ A &(∀ k ∈ S. (y, k) ∈ r)} (|pset = A, order = r|) in exI ) apply (drule-tac x = {y. y ∈ A &(∀ k ∈ S. (y,k) ∈ r) } in spec) apply (drule mp, fast) apply (simp add: isLub-lub isGlb-def ) apply (simp add: isLub-def , blast) done lemma lub-dual-glb: lub S cl = glb S (dual cl) by (simp add: lub-def glb-def least-def greatest-def dual-def converse-unfold) lemma glb-dual-lub: glb S cl = lub S (dual cl) by (simp add: lub-def glb-def least-def greatest-def dual-def converse-unfold) lemma CL-subset-PO: CompleteLattice ⊆ PartialOrder by (simp add: PartialOrder-def CompleteLattice-def , fast) lemmas CL-imp-PO = CL-subset-PO [THEN subsetD]

lemma (in CL) CO-refl-on: refl-on A r by (rule PO-imp-refl-on)

246 lemma (in CL) CO-antisym: antisym r by (rule PO-imp-sym) lemma (in CL) CO-trans: trans r by (rule PO-imp-trans) lemma CompleteLatticeI : [| po ∈ PartialOrder;(∀ S. S ⊆ pset po −−> (∃ L. isLub S po L)); (∀ S. S ⊆ pset po −−> (∃ G. isGlb S po G))|] ==> po ∈ CompleteLattice apply (unfold CompleteLattice-def , blast) done lemma (in CL) CL-dualCL: dual cl ∈ CompleteLattice apply (insert cl-co) apply (simp add: CompleteLattice-def dual-def ) apply (fold dual-def ) apply (simp add: isLub-dual-isGlb [symmetric] isGlb-dual-isLub [symmetric] dualPO) done lemma (in PO) dualA-iff : pset (dual cl) = pset cl by (simp add: dual-def ) lemma (in PO) dualr-iff : ((x, y) ∈ (order(dual cl))) = ((y, x) ∈ order cl) by (simp add: dual-def ) lemma (in PO) monotone-dual: monotone f (pset cl)(order cl) ==> monotone f (pset (dual cl)) (order(dual cl)) by (simp add: monotone-def dualA-iff dualr-iff ) lemma (in PO) interval-dual: [| x ∈ A; y ∈ A|] ==> interval r x y = interval (order(dual cl)) y x apply (simp add: interval-def dualr-iff ) apply (fold r-def , fast) done lemma (in PO) trans: (x, y) ∈ r =⇒ (y, z) ∈ r =⇒ (x, z) ∈ r using cl-po apply (auto simp add: PartialOrder-def r-def ) unfolding trans-def by blast lemma (in PO) interval-not-empty: interval r a b 6= {} ==> (a, b) ∈ r apply (simp add: interval-def ) using trans by blast lemma (in PO) interval-imp-mem: x ∈ interval r a b ==> (a, x) ∈ r

247 by (simp add: interval-def ) lemma (in PO) left-in-interval: [| a ∈ A; b ∈ A; interval r a b 6= {} |] ==> a ∈ interval r a b apply (simp (no-asm-simp) add: interval-def ) apply (simp add: PO-imp-trans interval-not-empty) apply (simp add: reflE) done lemma (in PO) right-in-interval: [| a ∈ A; b ∈ A; interval r a b 6= {} |] ==> b ∈ interval r a b apply (simp (no-asm-simp) add: interval-def ) apply (simp add: PO-imp-trans interval-not-empty) apply (simp add: reflE) done

38.2 sublattice lemma (in PO) sublattice-imp-CL: S <<= cl ==> (| pset = S, order = induced S r |) ∈ CompleteLattice by (simp add: sublattice-def CompleteLattice-def r-def ) lemma (in CL) sublatticeI : [| S ⊆ A;(| pset = S, order = induced S r |) ∈ CompleteLattice |] ==> S <<= cl by (simp add: sublattice-def A-def r-def ) lemma (in CL) dual: CL (dual cl) apply unfold-locales using cl-co unfolding CompleteLattice-def apply (simp add: dualPO isGlb-dual-isLub [symmetric] isLub-dual-isGlb [symmetric] dualA-iff ) done

38.3 lub lemma (in CL) lub-unique:[| S ⊆ A; isLub S cl x; isLub S cl L|] ==> x = L apply (rule antisymE) apply (auto simp add: isLub-def r-def ) done lemma (in CL) lub-upper:[|S ⊆ A; x ∈ S|] ==> (x, lub S cl) ∈ r apply (rule CL-imp-ex-isLub [THEN exE], assumption) apply (unfold lub-def least-def ) apply (rule some-equality [THEN ssubst]) apply (simp add: isLub-def ) apply (simp add: lub-unique A-def isLub-def ) apply (simp add: isLub-def r-def ) done

248 lemma (in CL) lub-least: [| S ⊆ A; L ∈ A; ∀ x ∈ S. (x,L) ∈ r |] ==> (lub S cl, L) ∈ r apply (rule CL-imp-ex-isLub [THEN exE], assumption) apply (unfold lub-def least-def ) apply (rule-tac s=x in some-equality [THEN ssubst]) apply (simp add: isLub-def ) apply (simp add: lub-unique A-def isLub-def ) apply (simp add: isLub-def r-def A-def ) done lemma (in CL) lub-in-lattice: S ⊆ A ==> lub S cl ∈ A apply (rule CL-imp-ex-isLub [THEN exE], assumption) apply (unfold lub-def least-def ) apply (subst some-equality) apply (simp add: isLub-def ) prefer 2 apply (simp add: isLub-def A-def ) apply (simp add: lub-unique A-def isLub-def ) done lemma (in CL) lubI : [| S ⊆ A; L ∈ A; ∀ x ∈ S. (x,L) ∈ r; ∀ z ∈ A. (∀ y ∈ S. (y,z) ∈ r) −−> (L,z) ∈ r |] ==> L = lub S cl apply (rule lub-unique, assumption) apply (simp add: isLub-def A-def r-def ) apply (unfold isLub-def ) apply (rule conjI ) apply (fold A-def r-def ) apply (rule lub-in-lattice, assumption) apply (simp add: lub-upper lub-least) done lemma (in CL) lubIa:[| S ⊆ A; isLub S cl L |] ==> L = lub S cl by (simp add: lubI isLub-def A-def r-def ) lemma (in CL) isLub-in-lattice: isLub S cl L ==> L ∈ A by (simp add: isLub-def A-def ) lemma (in CL) isLub-upper:[|isLub S cl L; y ∈ S|] ==> (y, L) ∈ r by (simp add: isLub-def r-def ) lemma (in CL) isLub-least: [| isLub S cl L; z ∈ A; ∀ y ∈ S. (y, z) ∈ r|] ==> (L, z) ∈ r by (simp add: isLub-def A-def r-def ) lemma (in CL) isLubI : [| L ∈ A; ∀ y ∈ S. (y, L) ∈ r; (∀ z ∈ A. (∀ y ∈ S. (y, z):r) −−> (L, z) ∈ r)|] ==> isLub S cl L by (simp add: isLub-def A-def r-def )

249 38.4 glb lemma (in CL) glb-in-lattice: S ⊆ A ==> glb S cl ∈ A apply (subst glb-dual-lub) apply (simp add: A-def ) apply (rule dualA-iff [THEN subst]) apply (rule CL.lub-in-lattice) apply (rule dual) apply (simp add: dualA-iff ) done lemma (in CL) glb-lower:[|S ⊆ A; x ∈ S|] ==> (glb S cl, x) ∈ r apply (subst glb-dual-lub) apply (simp add: r-def ) apply (rule dualr-iff [THEN subst]) apply (rule CL.lub-upper) apply (rule dual) apply (simp add: dualA-iff A-def , assumption) done

Reduce the sublattice property by using substructural properties; abandoned see Tarski-4 .ML. lemma (in CLF )[simp]: f : pset cl → pset cl & monotone f (pset cl)(order cl) apply (insert f-cl) apply (simp add: CLF-set-def ) done declare (in CLF ) f-cl [simp] lemma (in CLF ) f-in-funcset: f ∈ A → A by (simp add: A-def ) lemma (in CLF ) monotone-f : monotone f A r by (simp add: A-def r-def ) lemma (in CLF ) CLF-dual:(dual cl, f ) ∈ CLF-set apply (simp add: CLF-set-def CL-dualCL monotone-dual) apply (simp add: dualA-iff ) done lemma (in CLF ) dual: CLF (dual cl) f apply (rule CLF .intro) apply (rule CLF-dual) done

250 38.5 fixed points lemma fix-subset: fix f A ⊆ A by (simp add: fix-def , fast) lemma fix-imp-eq: x ∈ fix f A ==> f x = x by (simp add: fix-def ) lemma fixf-subset: [| A ⊆ B; x ∈ fix (%y: A. f y) A |] ==> x ∈ fix f B by (simp add: fix-def , auto)

38.6 lemmas for Tarski, lub lemma (in CLF ) lubH-le-flubH : H = {x. (x, f x) ∈ r & x ∈ A} ==> (lub H cl, f (lub H cl)) ∈ r apply (rule lub-least, fast) apply (rule f-in-funcset [THEN funcset-mem]) apply (rule lub-in-lattice, fast) — ∀ x:H . (x, f (lub H r)) ∈ r apply (rule ballI ) apply (rule transE) — instantiates (x, ???z) ∈ order cl to (x, f x), — because of the def of H apply fast — so it remains to show (f x, f (lub H cl)) ∈ r apply (rule-tac f = f in monotoneE) apply (rule monotone-f , fast) apply (rule lub-in-lattice, fast) apply (rule lub-upper, fast) apply assumption done lemma (in CLF ) flubH-le-lubH : [| H = {x. (x, f x) ∈ r & x ∈ A} |] ==> (f (lub H cl), lub H cl) ∈ r apply (rule lub-upper, fast) apply (rule-tac t = H in ssubst, assumption) apply (rule CollectI ) apply (rule conjI ) apply (rule-tac [2 ] f-in-funcset [THEN funcset-mem]) apply (rule-tac [2 ] lub-in-lattice) prefer 2 apply fast apply (rule-tac f = f in monotoneE) apply (rule monotone-f ) apply (blast intro: lub-in-lattice) apply (blast intro: lub-in-lattice f-in-funcset [THEN funcset-mem]) apply (simp add: lubH-le-flubH ) done lemma (in CLF ) lubH-is-fixp:

251 H = {x. (x, f x) ∈ r & x ∈ A} ==> lub H cl ∈ fix f A apply (simp add: fix-def ) apply (rule conjI ) apply (rule lub-in-lattice, fast) apply (rule antisymE) apply (simp add: flubH-le-lubH ) apply (simp add: lubH-le-flubH ) done lemma (in CLF ) fix-in-H : [| H = {x. (x, f x) ∈ r & x ∈ A}; x ∈ P |] ==> x ∈ H by (simp add: P-def fix-imp-eq [of - f A] reflE CO-refl-on fix-subset [of f A, THEN subsetD]) lemma (in CLF ) fixf-le-lubH : H = {x. (x, f x) ∈ r & x ∈ A} ==> ∀ x ∈ fix f A. (x, lub H cl) ∈ r apply (rule ballI ) apply (rule lub-upper, fast) apply (rule fix-in-H ) apply (simp-all add: P-def ) done lemma (in CLF ) lubH-least-fixf : H = {x. (x, f x) ∈ r & x ∈ A} ==> ∀ L. (∀ y ∈ fix f A. (y,L) ∈ r) −−> (lub H cl, L) ∈ r apply (rule allI ) apply (rule impI ) apply (erule bspec) apply (rule lubH-is-fixp, assumption) done

38.7 Tarski fixpoint theorem 1, first part lemma (in CLF ) T-thm-1-lub: lub P cl = lub {x. (x, f x) ∈ r & x ∈ A} cl apply (rule sym) apply (simp add: P-def ) apply (rule lubI ) apply (rule fix-subset) apply (rule lub-in-lattice, fast) apply (simp add: fixf-le-lubH ) apply (simp add: lubH-least-fixf ) done lemma (in CLF ) glbH-is-fixp: H = {x. (f x, x) ∈ r & x ∈ A} ==> glb H cl ∈ P — Tarski for glb apply (simp add: glb-dual-lub P-def A-def r-def ) apply (rule dualA-iff [THEN subst]) apply (rule CLF .lubH-is-fixp) apply (rule dual)

252 apply (simp add: dualr-iff dualA-iff ) done lemma (in CLF ) T-thm-1-glb: glb P cl = glb {x. (f x, x) ∈ r & x ∈ A} cl apply (simp add: glb-dual-lub P-def A-def r-def ) apply (rule dualA-iff [THEN subst]) apply (simp add: CLF .T-thm-1-lub [of - f , OF dual] dualPO CL-dualCL CLF-dual dualr-iff ) done

38.8 interval lemma (in CLF ) rel-imp-elem:(x, y) ∈ r ==> x ∈ A apply (insert CO-refl-on) apply (simp add: refl-on-def , blast) done lemma (in CLF ) interval-subset:[| a ∈ A; b ∈ A |] ==> interval r a b ⊆ A apply (simp add: interval-def ) apply (blast intro: rel-imp-elem) done lemma (in CLF ) intervalI : [| (a, x) ∈ r;(x, b) ∈ r |] ==> x ∈ interval r a b by (simp add: interval-def ) lemma (in CLF ) interval-lemma1 : [| S ⊆ interval r a b; x ∈ S |] ==> (a, x) ∈ r by (unfold interval-def , fast) lemma (in CLF ) interval-lemma2 : [| S ⊆ interval r a b; x ∈ S |] ==> (x, b) ∈ r by (unfold interval-def , fast) lemma (in CLF ) a-less-lub: [| S ⊆ A; S 6= {}; ∀ x ∈ S. (a,x) ∈ r; ∀ y ∈ S. (y, L) ∈ r |] ==> (a,L) ∈ r by (blast intro: transE) lemma (in CLF ) glb-less-b: [| S ⊆ A; S 6= {}; ∀ x ∈ S. (x,b) ∈ r; ∀ y ∈ S. (G, y) ∈ r |] ==> (G,b) ∈ r by (blast intro: transE) lemma (in CLF ) S-intv-cl: [| a ∈ A; b ∈ A; S ⊆ interval r a b |]==> S ⊆ A by (simp add: subset-trans [OF - interval-subset]) lemma (in CLF ) L-in-interval:

253 [| a ∈ A; b ∈ A; S ⊆ interval r a b; S 6= {}; isLub S cl L; interval r a b 6= {} |] ==> L ∈ interval r a b apply (rule intervalI ) apply (rule a-less-lub) prefer 2 apply assumption apply (simp add: S-intv-cl) apply (rule ballI ) apply (simp add: interval-lemma1 ) apply (simp add: isLub-upper) —(L, b) ∈ r apply (simp add: isLub-least interval-lemma2 ) done lemma (in CLF ) G-in-interval: [| a ∈ A; b ∈ A; interval r a b 6= {}; S ⊆ interval r a b; isGlb S cl G; S 6= {} |] ==> G ∈ interval r a b apply (simp add: interval-dual) apply (simp add: CLF .L-in-interval [of - f , OF dual] dualA-iff A-def isGlb-dual-isLub) done lemma (in CLF ) intervalPO: [| a ∈ A; b ∈ A; interval r a b 6= {} |] ==> (| pset = interval r a b, order = induced (interval r a b) r |) ∈ PartialOrder apply (rule po-subset-po) apply (simp add: interval-subset) done lemma (in CLF ) intv-CL-lub: [| a ∈ A; b ∈ A; interval r a b 6= {} |] ==> ∀ S. S ⊆ interval r a b −−> (∃ L. isLub S (| pset = interval r a b, order = induced (interval r a b) r |) L) apply (intro strip) apply (frule S-intv-cl [THEN CL-imp-ex-isLub]) prefer 2 apply assumption apply assumption apply (erule exE) — define the lub for the interval as apply (rule-tac x = if S = {} then a else L in exI ) apply (simp (no-asm-simp) add: isLub-def split del: if-split) apply (intro impI conjI ) —(if S = {} then a else L) ∈ interval r a b apply (simp add: CL-imp-PO L-in-interval) apply (simp add: left-in-interval) — lub prop 1 apply (case-tac S = {}) — S = {}, y ∈ S = False => everything

254 apply fast — S 6= {} apply simp — ∀ y:S. (y, L) ∈ induced (interval r a b) r apply (rule ballI ) apply (simp add: induced-def L-in-interval) apply (rule conjI ) apply (rule subsetD) apply (simp add: S-intv-cl, assumption) apply (simp add: isLub-upper) — ∀ z:interval r a b. (∀ y:S. (y, z) ∈ induced (interval r a b) r −→ (if S = {} then a else L, z) ∈ induced (interval r a b) r apply (rule ballI ) apply (rule impI ) apply (case-tac S = {}) — S = {} apply simp apply (simp add: induced-def interval-def ) apply (rule conjI ) apply (rule reflE, assumption) apply (rule interval-not-empty) apply (simp add: interval-def ) — S 6= {} apply simp apply (simp add: induced-def L-in-interval) apply (rule isLub-least, assumption) apply (rule subsetD) prefer 2 apply assumption apply (simp add: S-intv-cl, fast) done lemmas (in CLF ) intv-CL-glb = intv-CL-lub [THEN Rdual] lemma (in CLF ) interval-is-sublattice: [| a ∈ A; b ∈ A; interval r a b 6= {} |] ==> interval r a b <<= cl apply (rule sublatticeI ) apply (simp add: interval-subset) apply (rule CompleteLatticeI ) apply (simp add: intervalPO) apply (simp add: intv-CL-lub) apply (simp add: intv-CL-glb) done lemmas (in CLF ) interv-is-compl-latt = interval-is-sublattice [THEN sublattice-imp-CL]

255 38.9 Top and Bottom lemma (in CLF ) Top-dual-Bot: Top cl = Bot (dual cl) by (simp add: Top-def Bot-def least-def greatest-def dualA-iff dualr-iff ) lemma (in CLF ) Bot-dual-Top: Bot cl = Top (dual cl) by (simp add: Top-def Bot-def least-def greatest-def dualA-iff dualr-iff ) lemma (in CLF ) Bot-in-lattice: Bot cl ∈ A apply (simp add: Bot-def least-def ) apply (rule-tac a=glb A cl in someI2 ) apply (simp-all add: glb-in-lattice glb-lower r-def [symmetric] A-def [symmetric]) done lemma (in CLF ) Top-in-lattice: Top cl ∈ A apply (simp add: Top-dual-Bot A-def ) apply (rule dualA-iff [THEN subst]) apply (rule CLF .Bot-in-lattice [OF dual]) done lemma (in CLF ) Top-prop: x ∈ A ==> (x, Top cl) ∈ r apply (simp add: Top-def greatest-def ) apply (rule-tac a=lub A cl in someI2 ) apply (rule someI2 ) apply (simp-all add: lub-in-lattice lub-upper r-def [symmetric] A-def [symmetric]) done lemma (in CLF ) Bot-prop: x ∈ A ==> (Bot cl, x) ∈ r apply (simp add: Bot-dual-Top r-def ) apply (rule dualr-iff [THEN subst]) apply (rule CLF .Top-prop [OF dual]) apply (simp add: dualA-iff A-def ) done lemma (in CLF ) Top-intv-not-empty: x ∈ A ==> interval r x (Top cl) 6= {} apply (rule notI ) apply (drule-tac a = Top cl in equals0D) apply (simp add: interval-def ) apply (simp add: refl-on-def Top-in-lattice Top-prop) done lemma (in CLF ) Bot-intv-not-empty: x ∈ A ==> interval r (Bot cl) x 6= {} apply (simp add: Bot-dual-Top) apply (subst interval-dual) prefer 2 apply assumption apply (simp add: A-def ) apply (rule dualA-iff [THEN subst]) apply (rule CLF .Top-in-lattice [OF dual])

256 apply (rule CLF .Top-intv-not-empty [OF dual]) apply (simp add: dualA-iff A-def ) done

38.10 fixed points form a partial order lemma (in CLF ) fixf-po:(| pset = P, order = induced P r|) ∈ PartialOrder by (simp add: P-def fix-subset po-subset-po) lemma (in Tarski) Y-subset-A: Y ⊆ A apply (rule subset-trans [OF - fix-subset]) apply (rule Y-ss [simplified P-def ]) done lemma (in Tarski) lubY-in-A: lub Y cl ∈ A by (rule Y-subset-A [THEN lub-in-lattice]) lemma (in Tarski) lubY-le-flubY :(lub Y cl, f (lub Y cl)) ∈ r apply (rule lub-least) apply (rule Y-subset-A) apply (rule f-in-funcset [THEN funcset-mem]) apply (rule lubY-in-A) — Y ⊆ P ==> f x = x apply (rule ballI ) apply (rule-tac t = x in fix-imp-eq [THEN subst]) apply (erule Y-ss [simplified P-def , THEN subsetD]) — reduce (f x, f (lub Y cl)) ∈ r to (x, lub Y cl) ∈ r by monotonicity apply (rule-tac f = f in monotoneE) apply (rule monotone-f ) apply (simp add: Y-subset-A [THEN subsetD]) apply (rule lubY-in-A) apply (simp add: lub-upper Y-subset-A) done lemma (in Tarski) intY1-subset: intY1 ⊆ A apply (unfold intY1-def ) apply (rule interval-subset) apply (rule lubY-in-A) apply (rule Top-in-lattice) done lemmas (in Tarski) intY1-elem = intY1-subset [THEN subsetD] lemma (in Tarski) intY1-f-closed: x ∈ intY1 =⇒ f x ∈ intY1 apply (simp add: intY1-def interval-def ) apply (rule conjI ) apply (rule transE) apply (rule lubY-le-flubY ) —(f (lub Y cl), f x) ∈ r

257 apply (rule-tac f =f in monotoneE) apply (rule monotone-f ) apply (rule lubY-in-A) apply (simp add: intY1-def interval-def intY1-elem) apply (simp add: intY1-def interval-def ) —(f x, Top cl) ∈ r apply (rule Top-prop) apply (rule f-in-funcset [THEN funcset-mem]) apply (simp add: intY1-def interval-def intY1-elem) done lemma (in Tarski) intY1-mono: monotone (%x: intY1 . f x) intY1 (induced intY1 r) apply (auto simp add: monotone-def induced-def intY1-f-closed) apply (blast intro: intY1-elem monotone-f [THEN monotoneE]) done lemma (in Tarski) intY1-is-cl: (| pset = intY1 , order = induced intY1 r |) ∈ CompleteLattice apply (unfold intY1-def ) apply (rule interv-is-compl-latt) apply (rule lubY-in-A) apply (rule Top-in-lattice) apply (rule Top-intv-not-empty) apply (rule lubY-in-A) done lemma (in Tarski) v-in-P: v ∈ P apply (unfold P-def ) apply (rule-tac A = intY1 in fixf-subset) apply (rule intY1-subset) unfolding v-def apply (rule CLF .glbH-is-fixp [OF CLF .intro, unfolded CLF-set-def , of (|pset = intY1 , order = induced intY1 r|), simplified]) apply auto apply (rule intY1-is-cl) apply (erule intY1-f-closed) apply (rule intY1-mono) done lemma (in Tarski) z-in-interval: [| z ∈ P; ∀ y∈Y . (y, z) ∈ induced P r |] ==> z ∈ intY1 apply (unfold intY1-def P-def ) apply (rule intervalI ) prefer 2 apply (erule fix-subset [THEN subsetD, THEN Top-prop]) apply (rule lub-least) apply (rule Y-subset-A) apply (fast elim!: fix-subset [THEN subsetD])

258 apply (simp add: induced-def ) done lemma (in Tarski) f 0z-in-int-rel:[| z ∈ P; ∀ y∈Y . (y, z) ∈ induced P r |] ==> ((%x: intY1 . f x) z, z) ∈ induced intY1 r apply (simp add: induced-def intY1-f-closed z-in-interval P-def ) apply (simp add: fix-imp-eq [of - f A] fix-subset [of f A, THEN subsetD] reflE) done lemma (in Tarski) tarski-full-lemma: ∃ L. isLub Y (| pset = P, order = induced P r |) L apply (rule-tac x = v in exI ) apply (simp add: isLub-def ) — v ∈ P apply (simp add: v-in-P) apply (rule conjI ) — v is lub — 1 . ∀ y:Y . (y, v) ∈ induced P r apply (rule ballI ) apply (simp add: induced-def subsetD v-in-P) apply (rule conjI ) apply (erule Y-ss [THEN subsetD]) apply (rule-tac b = lub Y cl in transE) apply (rule lub-upper) apply (rule Y-subset-A, assumption) apply (rule-tac b = Top cl in interval-imp-mem) apply (simp add: v-def ) apply (fold intY1-def ) apply (rule CL.glb-in-lattice [OF CL.intro [OF intY1-is-cl], simplified]) apply auto apply (rule indI ) prefer 3 apply assumption prefer 2 apply (simp add: v-in-P) apply (unfold v-def ) apply (rule indE) apply (rule-tac [2 ] intY1-subset) apply (rule CL.glb-lower [OF CL.intro [OF intY1-is-cl], simplified]) apply (simp add: CL-imp-PO intY1-is-cl) apply force apply (simp add: induced-def intY1-f-closed z-in-interval) apply (simp add: P-def fix-imp-eq [of - f A] reflE fix-subset [of f A, THEN subsetD]) done lemma CompleteLatticeI-simp: [| (| pset = A, order = r |) ∈ PartialOrder; ∀ S. S ⊆ A −−> (∃ L. isLub S (| pset = A, order = r |) L) |] ==> (| pset = A, order = r |) ∈ CompleteLattice

259 by (simp add: CompleteLatticeI Rdual) theorem (in CLF ) Tarski-full: (| pset = P, order = induced P r|) ∈ CompleteLattice apply (rule CompleteLatticeI-simp) apply (rule fixf-po, clarify) apply (simp add: P-def A-def r-def ) apply (rule Tarski.tarski-full-lemma [OF Tarski.intro [OF - Tarski-axioms.intro]]) proof − show CLF cl f .. qed end

39 Classical Predicate Calculus Problems theory Classical imports Main begin

39.1 Traditional Classical Reasoner

The machine ”griffon” mentioned below is a 2.5GHz Power Mac G5.

Taken from FOL/Classical.thy. When porting examples from first-order logic, beware of the precedence of = versus ↔. lemma (P −−> Q | R) −−> (P−−>Q) | (P−−>R) by blast

If and only if lemma (P=Q) = (Q = (P::bool)) by blast lemma ∼ (P = (∼P)) by blast

Sample problems from F. J. Pelletier, Seventy-Five Problems for Testing Automatic Theorem Provers, J. Automated Reasoning 2 (1986), 191-216. Errata, JAR 4 (1988), 236-236. The hardest problems – judging by experience with several theorem provers, including matrix ones – are 34 and 43.

39.1.1 Pelletier’s examples

1 lemma (P−−>Q) = (∼Q −−> ∼P) by blast

2 lemma (∼ ∼ P) = P

260 by blast 3 lemma ∼(P−−>Q) −−> (Q−−>P) by blast 4 lemma (∼P−−>Q) = (∼Q −−> P) by blast 5 lemma ((P|Q)−−>(P|R)) −−> (P|(Q−−>R)) by blast 6 lemma P | ∼ P by blast 7 lemma P | ∼ ∼ ∼ P by blast 8. Peirce’s law lemma ((P−−>Q) −−> P) −−> P by blast 9 lemma ((P|Q)&(∼P|Q)&(P| ∼Q)) −−> ∼ (∼P | ∼Q) by blast 10 lemma (Q−−>R)&(R−−>P&Q)&(P−−>Q|R) −−> (P=Q) by blast 11. Proved in each direction (incorrectly, says Pelletier!!) lemma P=(P::bool) by blast 12. ”Dijkstra’s law” lemma ((P = Q) = R) = (P = (Q = R)) by blast 13. Distributive law lemma (P | (Q & R)) = ((P | Q)&(P | R)) by blast 14

261 lemma (P = Q) = ((Q | ∼P)&(∼Q|P)) by blast

15 lemma (P −−> Q) = (∼P | Q) by blast

16 lemma (P−−>Q) | (Q−−>P) by blast

17 lemma ((P &(Q−−>R))−−>S) = ((∼P | Q | S)&(∼P | ∼R | S)) by blast

39.1.2 Classical Logic: examples with quantifiers lemma (∀ x. P(x)& Q(x)) = ((∀ x. P(x)) & (∀ x. Q(x))) by blast lemma (∃ x. P−−>Q(x)) = (P −−> (∃ x. Q(x))) by blast lemma (∃ x. P(x)−−>Q) = ((∀ x. P(x)) −−> Q) by blast lemma ((∀ x. P(x)) | Q) = (∀ x. P(x) | Q) by blast

From Wishnu Prasetya lemma (∀ s. q(s) −−> r(s)) & ∼r(s)&(∀ s. ∼r(s)& ∼q(s) −−> p(t) | q(t)) −−> p(t) | r(t) by blast

39.1.3 Problems requiring quantifier duplication

Theorem B of Peter Andrews, Theorem Proving via General Matings, JACM 28 (1981). lemma (∃ x. ∀ y. P(x) = P(y)) −−> ((∃ x. P(x)) = (∀ y. P(y))) by blast

Needs multiple instantiation of the quantifier. lemma (∀ x. P(x)−−>P(f (x))) & P(d)−−>P(f (f (f (d)))) by blast

Needs double instantiation of the quantifier lemma ∃ x. P(x) −−> P(a)& P(b)

262 by blast lemma ∃ z. P(z) −−> (∀ x. P(x)) by blast lemma ∃ x. (∃ y. P(y)) −−> P(x) by blast

39.1.4 Hard examples with quantifiers

Problem 18 lemma ∃ y. ∀ x. P(y)−−>P(x) by blast

Problem 19 lemma ∃ x. ∀ y z. (P(y)−−>Q(z)) −−> (P(x)−−>Q(x)) by blast

Problem 20 lemma (∀ x y. ∃ z. ∀ w. (P(x)&Q(y)−−>R(z)&S(w))) −−> (∃ x y. P(x)& Q(y)) −−> (∃ z. R(z)) by blast

Problem 21 lemma (∃ x. P−−>Q(x)) & (∃ x. Q(x)−−>P) −−> (∃ x. P=Q(x)) by blast

Problem 22 lemma (∀ x. P = Q(x)) −−> (P = (∀ x. Q(x))) by blast

Problem 23 lemma (∀ x. P | Q(x)) = (P | (∀ x. Q(x))) by blast

Problem 24 lemma ∼(∃ x. S(x)&Q(x)) & (∀ x. P(x) −−> Q(x)|R(x)) & (∼(∃ x. P(x)) −−> (∃ x. Q(x))) & (∀ x. Q(x)|R(x) −−> S(x)) −−> (∃ x. P(x)&R(x)) by blast

Problem 25 lemma (∃ x. P(x)) & (∀ x. L(x) −−> ∼ (M (x)& R(x))) & (∀ x. P(x) −−> (M (x)& L(x))) & ((∀ x. P(x)−−>Q(x)) | (∃ x. P(x)&R(x))) −−> (∃ x. Q(x)&P(x))

263 by blast Problem 26 lemma ((∃ x. p(x)) = (∃ x. q(x))) & (∀ x. ∀ y. p(x)& q(y) −−> (r(x) = s(y))) −−> ((∀ x. p(x)−−>r(x)) = (∀ x. q(x)−−>s(x))) by blast Problem 27 lemma (∃ x. P(x)& ∼Q(x)) & (∀ x. P(x) −−> R(x)) & (∀ x. M (x)& L(x) −−> P(x)) & ((∃ x. R(x)& ∼ Q(x)) −−> (∀ x. L(x) −−> ∼ R(x))) −−> (∀ x. M (x) −−> ∼L(x)) by blast Problem 28. AMENDED lemma (∀ x. P(x) −−> (∀ x. Q(x))) & ((∀ x. Q(x)|R(x)) −−> (∃ x. Q(x)&S(x))) & ((∃ x. S(x)) −−> (∀ x. L(x) −−> M (x))) −−> (∀ x. P(x)& L(x) −−> M (x)) by blast Problem 29. Essentially the same as Principia Mathematica *11.71 lemma (∃ x. F (x)) & (∃ y. G(y)) −−> ( ((∀ x. F (x)−−>H (x)) & (∀ y. G(y)−−>J (y))) = (∀ x y. F (x)& G(y) −−> H (x)& J (y))) by blast Problem 30 lemma (∀ x. P(x) | Q(x) −−> ∼ R(x)) & (∀ x. (Q(x) −−> ∼ S(x)) −−> P(x)& R(x)) −−> (∀ x. S(x)) by blast Problem 31 lemma ∼(∃ x. P(x)&(Q(x) | R(x))) & (∃ x. L(x)& P(x)) & (∀ x. ∼ R(x) −−> M (x)) −−> (∃ x. L(x)& M (x)) by blast Problem 32 lemma (∀ x. P(x)&(Q(x)|R(x))−−>S(x)) & (∀ x. S(x)& R(x) −−> L(x)) & (∀ x. M (x) −−> R(x)) −−> (∀ x. P(x)& M (x) −−> L(x)) by blast

264 Problem 33 lemma (∀ x. P(a)&(P(x)−−>P(b))−−>P(c)) = (∀ x. (∼P(a) | P(x) | P(c)) & (∼P(a) | ∼P(b) | P(c))) by blast

Problem 34 AMENDED (TWICE!!)

Andrews’s challenge 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

Problem 35 lemma ∃ x y. P x y −−> (∀ u v. P u v) by blast

Problem 36 lemma (∀ x. ∃ y. J x y)& (∀ x. ∃ y. G x y)& (∀ x y. J x y | G x y −−> (∀ z. J y z | G y z −−> H x z)) −−> (∀ x. ∃ y. H x y) by blast

Problem 37 lemma (∀ z. ∃ w. ∀ x. ∃ y. (P x z −−>P y w)& P y z &(P y w −−> (∃ u. Q u w))) & (∀ x z. ∼(P x z) −−> (∃ y. Q y z)) & ((∃ x y. Q x y) −−> (∀ x. R x x)) −−> (∀ x. ∃ y. R x y) by blast

Problem 38 lemma (∀ x. p(a)&(p(x) −−> (∃ y. p(y)& r x y)) −−> (∃ z. ∃ w. p(z)& r x w & r w z)) = (∀ x. (∼p(a) | p(x) | (∃ z. ∃ w. p(z)& r x w & r w z)) & (∼p(a) | ∼(∃ y. p(y)& r x y) | (∃ z. ∃ w. p(z)& r x w & r w z))) by blast

Problem 39 lemma ∼ (∃ x. ∀ y. F y x = (∼ F y y)) by blast

Problem 40. AMENDED

265 lemma (∃ y. ∀ x. F x y = F x x) −−> ∼ (∀ x. ∃ y. ∀ z. F z y = (∼ F z x)) by blast

Problem 41 lemma (∀ z. ∃ y. ∀ x. f x y = (f x z & ∼ f x x)) −−> ∼ (∃ z. ∀ x. f x z) by blast

Problem 42 lemma ∼ (∃ y. ∀ x. p x y = (∼ (∃ z. p x z & p z x))) by blast

Problem 43!! lemma (∀ x:: 0a. ∀ y:: 0a. q x y = (∀ z. p z x = (p z y::bool))) −−> (∀ x. (∀ y. q x y = (q y x::bool))) by blast

Problem 44 lemma (∀ x. f (x) −−> (∃ y. g(y)& h x y &(∃ y. g(y)& ∼ h x y))) & (∃ x. j (x)&(∀ y. g(y) −−> h x y)) −−> (∃ x. j (x)& ∼f (x)) by blast

Problem 45 lemma (∀ x. f (x)&(∀ y. g(y)& h x y −−> j x y) −−> (∀ y. g(y)& h x y −−> k(y))) & ∼ (∃ y. l(y)& k(y)) & (∃ x. f (x)&(∀ y. h x y −−> l(y)) &(∀ y. g(y)& h x y −−> j x y)) −−> (∃ x. f (x)& ∼ (∃ y. g(y)& h x y)) by blast

39.1.5 Problems (mainly) involving equality or functions

Problem 48 lemma (a=b | c=d)&(a=c | b=d) −−> a=d | b=c by blast

Problem 49 NOT PROVED AUTOMATICALLY. Hard because it involves substitution for Vars the type constraint ensures that x,y,z have the same type as a,b,u. lemma (∃ x y:: 0a. ∀ z. z=x | z=y)& P(a)& P(b)&(∼a=b) −−> (∀ u:: 0a. P(u)) by metis

266 Problem 50. (What has this to do with equality?) lemma (∀ x. P a x | (∀ y. P x y)) −−> (∃ x. ∀ y. P x y) by blast

Problem 51 lemma (∃ z w. ∀ x y. P x y = (x=z & y=w)) −−> (∃ z. ∀ x. ∃ w. (∀ y. P x y = (y=w)) = (x=z)) by blast

Problem 52. Almost the same as 51. lemma (∃ z w. ∀ x y. P x y = (x=z & y=w)) −−> (∃ w. ∀ y. ∃ z. (∀ x. P x y = (x=z)) = (y=w)) by blast

Problem 55

Non-equational version, from Manthey and Bry, CADE-9 (Springer, 1988). fast DISCOVERS who killed Agatha. schematic-goal lives(agatha)& lives(butler)& lives(charles)& (killed agatha agatha | killed butler agatha | killed charles agatha)& (∀ x y. killed x y −−> hates x y & ∼richer x y)& (∀ x. hates agatha x −−> ∼hates charles x)& (hates agatha agatha & hates agatha charles)& (∀ x. lives(x)& ∼richer x agatha −−> hates butler x)& (∀ x. hates agatha x −−> hates butler x)& (∀ x. ∼hates x agatha | ∼hates x butler | ∼hates x charles) −−> killed ?who agatha by fast

Problem 56 lemma (∀ x. (∃ y. P(y)& x=f (y)) −−> P(x)) = (∀ x. P(x) −−> P(f (x))) by blast

Problem 57 lemma P (f a b)(f b c)& P (f b c)(f a c)& (∀ x y z. P x y & P y z −−> P x z) −−> P (f a b)(f a c) by blast

Problem 58 NOT PROVED AUTOMATICALLY lemma (∀ x y. f (x)=g(y)) −−> (∀ x y. f (f (x))=f (g(y))) by (fast intro: arg-cong [of concl: f ])

Problem 59 lemma (∀ x. P(x) = (∼P(f (x)))) −−> (∃ x. P(x)& ∼P(f (x))) by blast

Problem 60

267 lemma ∀ x. P x (f x) = (∃ y. (∀ z. P z y −−> P z (f x)) & P x y) by blast

Problem 62 as corrected in JAR 18 (1997), page 135 lemma (∀ x. p a &(p x −−> p(f x)) −−> p(f (f x))) = (∀ x. (∼ p a | p x | p(f (f x))) & (∼ p a | ∼ p(f x) | p(f (f x)))) by blast

From Davis, Obvious Logical Inferences, IJCAI-81, 530-531 fast indeed copes! lemma (∀ x. F (x)& ∼G(x) −−> (∃ y. H (x,y)& J (y))) & (∃ x. K (x)& F (x)&(∀ y. H (x,y) −−> K (y))) & (∀ x. K (x) −−> ∼G(x)) −−> (∃ x. K (x)& J (x)) by fast

From Rudnicki, Obvious Inferences, JAR 3 (1987), 383-393. It does seem obvious! lemma (∀ x. F (x)& ∼G(x) −−> (∃ y. H (x,y)& J (y))) & (∃ x. K (x)& F (x)&(∀ y. H (x,y) −−> K (y))) & (∀ x. K (x) −−> ∼G(x)) −−> (∃ x. K (x) −−> ∼G(x)) by fast

Attributed to Lewis Carroll by S. G. Pulman. The first or last assumption can be deleted. lemma (∀ x. honest(x)& industrious(x) −−> healthy(x)) & ∼ (∃ x. grocer(x)& healthy(x)) & (∀ x. industrious(x)& grocer(x) −−> honest(x)) & (∀ x. cyclist(x) −−> industrious(x)) & (∀ x. ∼healthy(x)& cyclist(x) −−> ∼honest(x)) −−> (∀ x. grocer(x) −−> ∼cyclist(x)) by blast lemma (∀ x y. R(x,y) | R(y,x)) & (∀ x y. S(x,y)& S(y,x) −−> x=y)& (∀ x y. R(x,y) −−> S(x,y)) −−> (∀ x y. S(x,y) −−> R(x,y)) by blast

39.2 Model Elimination Prover

Trying out meson with arguments lemma x < y & y < z −−> ∼ (z < (x::nat)) by (meson order-less-irrefl order-less-trans)

The ”small example” from Bezem, Hendriks and de Nivelle, Automatic Proof Construction in Type Theory Using Resolution, JAR 29: 3-4 (2002), pages 253-275 lemma (∀ x y z. R(x,y)& R(y,z) −−> R(x,z)) &

268 (∀ x. ∃ y. R(x,y)) −−> ∼ (∀ x. P x = (∀ y. R(x,y) −−> ∼ P y)) by (tactichMeson.safe-best-meson-tac @{context} 1 i) — In contrast, meson is SLOW: 7.6s on griffon

39.2.1 Pelletier’s examples

1 lemma (P −−> Q) = (∼Q −−> ∼P) by blast

2 lemma (∼ ∼ P) = P by blast

3 lemma ∼(P−−>Q) −−> (Q−−>P) by blast

4 lemma (∼P−−>Q) = (∼Q −−> P) by blast

5 lemma ((P|Q)−−>(P|R)) −−> (P|(Q−−>R)) by blast

6 lemma P | ∼ P by blast

7 lemma P | ∼ ∼ ∼ P by blast

8. Peirce’s law lemma ((P−−>Q) −−> P) −−> P by blast

9 lemma ((P|Q)&(∼P|Q)&(P| ∼Q)) −−> ∼ (∼P | ∼Q) by blast

10 lemma (Q−−>R)&(R−−>P&Q)&(P−−>Q|R) −−> (P=Q) by blast

269 11. Proved in each direction (incorrectly, says Pelletier!!) lemma P=(P::bool) by blast

12. ”Dijkstra’s law” lemma ((P = Q) = R) = (P = (Q = R)) by blast

13. Distributive law lemma (P | (Q & R)) = ((P | Q)&(P | R)) by blast

14 lemma (P = Q) = ((Q | ∼P)&(∼Q|P)) by blast

15 lemma (P −−> Q) = (∼P | Q) by blast

16 lemma (P−−>Q) | (Q−−>P) by blast

17 lemma ((P &(Q−−>R))−−>S) = ((∼P | Q | S)&(∼P | ∼R | S)) by blast

39.2.2 Classical Logic: examples with quantifiers lemma (∀ x. P x & Q x) = ((∀ x. P x)&(∀ x. Q x)) by blast lemma (∃ x. P −−> Q x) = (P −−> (∃ x. Q x)) by blast lemma (∃ x. P x −−> Q) = ((∀ x. P x) −−> Q) by blast lemma ((∀ x. P x) | Q) = (∀ x. P x | Q) by blast lemma (∀ x. P x −−> P(f x)) & P d −−> P(f (f (f d))) by blast

Needs double instantiation of EXISTS lemma ∃ x. P x −−> P a & P b

270 by blast lemma ∃ z. P z −−> (∀ x. P x) by blast

From a paper by Claire Quigley lemma ∃ y. ((P c & Q y) | (∃ z. ∼ Q z)) | (∃ x. ∼ P x & Q d) by fast

39.2.3 Hard examples with quantifiers

Problem 18 lemma ∃ y. ∀ x. P y −−> P x by blast

Problem 19 lemma ∃ x. ∀ y z. (P y −−> Q z) −−> (P x −−> Q x) by blast

Problem 20 lemma (∀ x y. ∃ z. ∀ w. (P x & Q y −−> R z & S w)) −−> (∃ x y. P x & Q y) −−> (∃ z. R z) by blast

Problem 21 lemma (∃ x. P −−> Q x)&(∃ x. Q x −−> P) −−> (∃ x. P=Q x) by blast

Problem 22 lemma (∀ x. P = Q x) −−> (P = (∀ x. Q x)) by blast

Problem 23 lemma (∀ x. P | Q x) = (P | (∀ x. Q x)) by blast

Problem 24 lemma ∼(∃ x. S x & Q x)&(∀ x. P x −−> Q x | R x)& (∼(∃ x. P x) −−> (∃ x. Q x)) & (∀ x. Q x | R x −−> S x) −−> (∃ x. P x & R x) by blast

Problem 25 lemma (∃ x. P x)& (∀ x. L x −−> ∼ (M x & R x)) & (∀ x. P x −−> (M x & L x)) &

271 ((∀ x. P x −−> Q x) | (∃ x. P x & R x)) −−> (∃ x. Q x & P x) by blast

Problem 26; has 24 Horn clauses lemma ((∃ x. p x) = (∃ x. q x)) & (∀ x. ∀ y. p x & q y −−> (r x = s y)) −−> ((∀ x. p x −−> r x) = (∀ x. q x −−> s x)) by blast

Problem 27; has 13 Horn clauses lemma (∃ x. P x & ∼Q x)& (∀ x. P x −−> R x)& (∀ x. M x & L x −−> P x)& ((∃ x. R x & ∼ Q x) −−> (∀ x. L x −−> ∼ R x)) −−> (∀ x. M x −−> ∼L x) by blast

Problem 28. AMENDED; has 14 Horn clauses lemma (∀ x. P x −−> (∀ x. Q x)) & ((∀ x. Q x | R x) −−> (∃ x. Q x & S x)) & ((∃ x. S x) −−> (∀ x. L x −−> M x)) −−> (∀ x. P x & L x −−> M x) by blast

Problem 29. Essentially the same as Principia Mathematica *11.71. 62 Horn clauses lemma (∃ x. F x)&(∃ y. G y) −−> ( ((∀ x. F x −−> H x)&(∀ y. G y −−> J y)) = (∀ x y. F x & G y −−> H x & J y)) by blast

Problem 30 lemma (∀ x. P x | Q x −−> ∼ R x)&(∀ x. (Q x −−> ∼ S x) −−> P x & R x) −−> (∀ x. S x) by blast

Problem 31; has 10 Horn clauses; first negative clauses is useless lemma ∼(∃ x. P x &(Q x | R x)) & (∃ x. L x & P x)& (∀ x. ∼ R x −−> M x) −−> (∃ x. L x & M x) by blast

Problem 32 lemma (∀ x. P x &(Q x | R x)−−>S x)& (∀ x. S x & R x −−> L x)&

272 (∀ x. M x −−> R x) −−> (∀ x. P x & M x −−> L x) by blast Problem 33; has 55 Horn clauses lemma (∀ x. P a &(P x −−> P b)−−>P c) = (∀ x. (∼P a | P x | P c)&(∼P a | ∼P b | P c)) by blast Problem 34: Andrews’s challenge has 924 Horn clauses 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 Problem 35 lemma ∃ x y. P x y −−> (∀ u v. P u v) by blast Problem 36; has 15 Horn clauses lemma (∀ x. ∃ y. J x y)&(∀ x. ∃ y. G x y)& (∀ x y. J x y | G x y −−> (∀ z. J y z | G y z −−> H x z)) −−> (∀ x. ∃ y. H x y) by blast Problem 37; has 10 Horn clauses lemma (∀ z. ∃ w. ∀ x. ∃ y. (P x z −−> P y w)& P y z &(P y w −−> (∃ u. Q u w))) & (∀ x z. ∼P x z −−> (∃ y. Q y z)) & ((∃ x y. Q x y) −−> (∀ x. R x x)) −−> (∀ x. ∃ y. R x y) by blast — causes unification tracing messages Problem 38 Quite hard: 422 Horn clauses!! lemma (∀ x. p a &(p x −−> (∃ y. p y & r x y)) −−> (∃ z. ∃ w. p z & r x w & r w z)) = (∀ x. (∼p a | p x | (∃ z. ∃ w. p z & r x w & r w z)) & (∼p a | ∼(∃ y. p y & r x y) | (∃ z. ∃ w. p z & r x w & r w z))) by blast Problem 39 lemma ∼ (∃ x. ∀ y. F y x = (∼F y y)) by blast Problem 40. AMENDED lemma (∃ y. ∀ x. F x y = F x x)

273 −−> ∼ (∀ x. ∃ y. ∀ z. F z y = (∼F z x)) by blast

Problem 41 lemma (∀ z. (∃ y. (∀ x. f x y = (f x z & ∼ f x x)))) −−> ∼ (∃ z. ∀ x. f x z) by blast

Problem 42 lemma ∼ (∃ y. ∀ x. p x y = (∼ (∃ z. p x z & p z x))) by blast

Problem 43 NOW PROVED AUTOMATICALLY!! lemma (∀ x. ∀ y. q x y = (∀ z. p z x = (p z y::bool))) −−> (∀ x. (∀ y. q x y = (q y x::bool))) by blast

Problem 44: 13 Horn clauses; 7-step proof lemma (∀ x. f x −−> (∃ y. g y & h x y &(∃ y. g y & ∼ h x y))) & (∃ x. j x &(∀ y. g y −−> h x y)) −−> (∃ x. j x & ∼f x) by blast

Problem 45; has 27 Horn clauses; 54-step proof lemma (∀ x. f x &(∀ y. g y & h x y −−> j x y) −−> (∀ y. g y & h x y −−> k y)) & ∼ (∃ y. l y & k y)& (∃ x. f x &(∀ y. h x y −−> l y) &(∀ y. g y & h x y −−> j x y)) −−> (∃ x. f x & ∼ (∃ y. g y & h x y)) by blast

Problem 46; has 26 Horn clauses; 21-step proof lemma (∀ x. f x &(∀ y. f y & h y x −−> g y) −−> g x)& ((∃ x. f x & ∼g x) −−> (∃ x. f x & ∼g x &(∀ y. f y & ∼g y −−> j x y))) & (∀ x y. f x & f y & h x y −−> ∼j y x) −−> (∀ x. f x −−> g x) by blast

Problem 47. Schubert’s Steamroller. 26 clauses; 63 Horn clauses. 87094 inferences so far. Searching to depth 36 lemma (∀ x. wolf x −→ animal x)&(∃ x. wolf x)& (∀ x. fox x −→ animal x)&(∃ x. fox x)& (∀ x. bird x −→ animal x)&(∃ x. bird x)& (∀ x. caterpillar x −→ animal x)&(∃ x. caterpillar x)& (∀ x. snail x −→ animal x)&(∃ x. snail x)&

274 (∀ x. grain x −→ plant x)&(∃ x. grain x)& (∀ x. animal x −→ ((∀ y. plant y −→ eats x y) ∨ (∀ y. animal y & smaller-than y x & (∃ z. plant z & eats y z) −→ eats x y))) & (∀ x y. bird y &(snail x ∨ caterpillar x) −→ smaller-than x y)& (∀ x y. bird x & fox y −→ smaller-than x y)& (∀ x y. fox x & wolf y −→ smaller-than x y)& (∀ x y. wolf x &(fox y ∨ grain y) −→ ∼eats x y)& (∀ x y. bird x & caterpillar y −→ eats x y)& (∀ x y. bird x & snail y −→ ∼eats x y)& (∀ x. (caterpillar x ∨ snail x) −→ (∃ y. plant y & eats x y)) −→ (∃ x y. animal x & animal y &(∃ z. grain z & eats y z & eats x y)) by (tactichMeson.safe-best-meson-tac @{context} 1 i) — Nearly twice as fast as meson, which performs iterative deepening rather than best-first search

The Los problem. Circulated by John Harrison lemma (∀ x y z. P x y & P y z −−> P x z)& (∀ x y z. Q x y & Q y z −−> Q x z)& (∀ x y. P x y −−> P y x)& (∀ x y. P x y | Q x y) −−> (∀ x y. P x y) | (∀ x y. Q x y) by meson

A similar example, suggested by Johannes Schumann and credited to Pel- letier lemma (∀ x y z. P x y −−> P y z −−> P x z) −−> (∀ x y z. Q x y −−> Q y z −−> Q x z) −−> (∀ x y. Q x y −−> Q y x) −−> (∀ x y. P x y | Q x y) −−> (∀ x y. P x y) | (∀ x y. Q x y) by meson

Problem 50. What has this to do with equality? lemma (∀ x. P a x | (∀ y. P x y)) −−> (∃ x. ∀ y. P x y) by blast

Problem 54: NOT PROVED lemma (∀ y:: 0a. ∃ z. ∀ x. F x z = (x=y)) −−> ∼ (∃ w. ∀ x. F x w = (∀ u. F x u −−> (∃ y. F y u & ∼ (∃ z. F z u & F z y)))) oops

Problem 55

Non-equational version, from Manthey and Bry, CADE-9 (Springer, 1988). meson cannot report who killed Agatha. lemma lives agatha & lives butler & lives charles & (killed agatha agatha | killed butler agatha | killed charles agatha)&

275 (∀ x y. killed x y −−> hates x y & ∼richer x y)& (∀ x. hates agatha x −−> ∼hates charles x)& (hates agatha agatha & hates agatha charles)& (∀ x. lives x & ∼richer x agatha −−> hates butler x)& (∀ x. hates agatha x −−> hates butler x)& (∀ x. ∼hates x agatha | ∼hates x butler | ∼hates x charles) −−> (∃ x. killed x agatha) by meson Problem 57 lemma P (f a b)(f b c)& P (f b c)(f a c)& (∀ x y z. P x y & P y z −−> P x z) −−> P (f a b)(f a c) by blast Problem 58: Challenge found on info-hol lemma ∀ P Q R x. ∃ v w. ∀ y z. P x & Q y −−> (P v | R w)&(R z −−> Q v) by blast Problem 59 lemma (∀ x. P x = (∼P(f x))) −−> (∃ x. P x & ∼P(f x)) by blast Problem 60 lemma ∀ x. P x (f x) = (∃ y. (∀ z. P z y −−> P z (f x)) & P x y) by blast Problem 62 as corrected in JAR 18 (1997), page 135 lemma (∀ x. p a &(p x −−> p(f x)) −−> p(f (f x))) = (∀ x. (∼ p a | p x | p(f (f x))) & (∼ p a | ∼ p(f x) | p(f (f x)))) by blast * Charles Morgan’s problems * lemma assumes a: ∀ x y. T (i x(i y x)) and b: ∀ x y z. T (i (i x (i y z)) (i (i x y)(i x z))) and c: ∀ x y. T (i (i (n x)(n y)) (i y x)) and c 0: ∀ x y. T (i (i y x)(i (n x)(n y))) and d: ∀ x y. T (i x y)& T x −−> T y shows True proof − from a b d have ∀ x. T (i x x) by blast from a b c d have ∀ x. T (i x (n(n x))) — Problem 66 by metis from a b c d have ∀ x. T (i (n(n x)) x) — Problem 67 by meson — 4.9s on griffon. 51061 inferences, depth 21 from a b c 0 d have ∀ x. T (i x (n(n x)))

276 — Problem 68: not proved. Listed as satisfiable in TPTP (LCL078-1) oops Problem 71, as found in TPTP (SYN007+1.005) lemma p1 = (p2 = (p3 = (p4 = (p5 = (p1 = (p2 = (p3 = (p4 = p5 )))))))) by blast end

40 Set Theory examples: Cantor’s Theorem, Schr¨oder- Bernstein Theorem, etc. theory Set-Theory imports Main begin These two are cited in Benzmueller and Kohlhase’s system description of LEO, CADE-15, 1998 (pages 139-143) as theorems LEO could not prove. lemma (X = Y ∪ Z ) = (Y ⊆ X ∧ Z ⊆ X ∧ (∀ V . Y ⊆ V ∧ Z ⊆ V −→ X ⊆ V )) by blast lemma (X = Y ∩ Z ) = (X ⊆ Y ∧ X ⊆ Z ∧ (∀ V . V ⊆ Y ∧ V ⊆ Z −→ V ⊆ X )) by blast Trivial example of term synthesis: apparently hard for some provers! schematic-goal a 6= b =⇒ a ∈ ?X ∧ b ∈/ ?X by blast

40.1 Examples for the blast paper lemma (S x ∈ C . f x ∪ g x) = S (f ‘ C ) ∪ S (g ‘ C ) — Union-image, called Un-Union-image in Main HOL by blast lemma (T x ∈ C . f x ∩ g x) = T (f ‘ C ) ∩ T (g ‘ C ) — Inter-image, called Int-Inter-image in Main HOL by blast lemma singleton-example-1 : VS:: 0a set set. ∀ x ∈ S. ∀ y ∈ S. x ⊆ y =⇒ ∃ z. S ⊆ {z} by blast lemma singleton-example-2 : ∀ x ∈ S. S S ⊆ x =⇒ ∃ z. S ⊆ {z} — Variant of the problem above. by blast

277 lemma ∃ !x. f (g x) = x =⇒ ∃ !y. g (f y) = y — A unique fixpoint theorem — fast/best/meson all fail. by metis

40.2 Cantor’s Theorem: There is no surjection from a set to its powerset lemma cantor1 : ¬ (∃ f :: 0a ⇒ 0a set. ∀ S. ∃ x. f x = S) — Requires best-first search because it is undirectional. by best schematic-goal ∀ f :: 0a ⇒ 0a set. ∀ x. f x 6= ?S f — This form displays the diagonal term. by best schematic-goal ?S ∈/ range (f :: 0a ⇒ 0a set) — This form exploits the set constructs. by (rule notI , erule rangeE, best) schematic-goal ?S ∈/ range (f :: 0a ⇒ 0a set) — Or just this! by best

40.3 The Schr¨oder-BernsteinTheorem lemma disj-lemma: − (f ‘ X ) = g 0 ‘ (−X ) =⇒ f a = g 0 b =⇒ a ∈ X =⇒ b ∈ X by blast lemma surj-if-then-else: −(f ‘ X ) = g 0 ‘ (−X ) =⇒ surj (λz. if z ∈ X then f z else g 0 z) by (simp add: surj-def ) blast lemma bij-if-then-else: inj-on f X =⇒ inj-on g 0 (−X ) =⇒ −(f ‘ X ) = g 0 ‘ (−X ) =⇒ h = (λz. if z ∈ X then f z else g 0 z) =⇒ inj h ∧ surj h apply (unfold inj-on-def ) apply (simp add: surj-if-then-else) apply (blast dest: disj-lemma sym) done lemma decomposition: ∃ X . X = − (g ‘ (− (f ‘ X ))) apply (rule exI ) apply (rule lfp-unfold) apply (rule monoI , blast) done theorem Schroeder-Bernstein: inj (f :: 0a ⇒ 0b) =⇒ inj (g :: 0b ⇒ 0a)

278 =⇒ ∃ h:: 0a ⇒ 0b. inj h ∧ surj h apply (rule decomposition [where f =f and g=g, THEN exE]) apply (rule-tac x = (λz. if z ∈ x then f z else inv g z) in exI ) — The term above can be synthesized by a sufficiently detailed proof. apply (rule bij-if-then-else) apply (rule-tac [4 ] refl) apply (rule-tac [2 ] inj-on-inv-into) apply (erule subset-inj-on [OF - subset-UNIV ]) apply blast apply (erule ssubst, subst double-complement, erule image-inv-f-f [symmetric]) done

40.4 A simple party theorem

At any party there are two people who know the same number of people. Provided the party consists of at least two people and the knows relation is symmetric. Knowing yourself does not count — otherwise knows needs to be reflexive. (From Freek Wiedijk’s talk at TPHOLs 2007.) lemma equal-number-of-acquaintances: assumes Domain R <= A and sym R and card A ≥ 2 shows ¬ inj-on (%a. card(R ‘‘ {a} − {a})) A proof − let ?N = %a. card(R ‘‘ {a} − {a}) let ?n = card A have finite A using hcard A ≥ 2 i by(auto intro:ccontr) have 0 : R ‘‘ A <= A using hsym Ri hDomain R <= Ai unfolding Domain-unfold sym-def by blast have h: ALL a:A. R ‘‘ {a} <= A using 0 by blast hence 1 : ALL a:A. finite(R ‘‘ {a}) using hfinite Ai by(blast intro: finite-subset) have sub: ?N ‘ A <= {0 ..

279 hence a ∈/ R ‘‘ {b} by (metis Image-singleton-iff assms(2 ) sym-def ) hence 3 : R ‘‘ {b} − {b} <= A − {a,b} using 0 ab by blast have 4 : finite (A − {a,b}) using hfinite Ai by simp have ?N b <= ?n − 2 using ab ha6=bi hfinite Ai card-mono[OF 4 3 ] by simp then show False using Nb hcard A ≥ 2 i by arith qed qed

From W. W. Bledsoe and Guohui Feng, SET-VAR. JAR 11 (3), 1993, pages 293-314. Isabelle can prove the easy examples without any special mechanisms, but it can’t prove the hard ones. lemma ∃ A. (∀ x ∈ A. x ≤ (0 ::int)) — Example 1, page 295. by force lemma D ∈ F =⇒ ∃ G. ∀ A ∈ G. ∃ B ∈ F . A ⊆ B — Example 2. by force lemma P a =⇒ ∃ A. (∀ x ∈ A. P x) ∧ (∃ y. y ∈ A) — Example 3. by force lemma a < b ∧ b < (c::int) =⇒ ∃ A. a ∈/ A ∧ b ∈ A ∧ c ∈/ A — Example 4. by auto — slow lemma P (f b) =⇒ ∃ s A. (∀ x ∈ A. P x) ∧ f s ∈ A — Example 5, page 298. by force lemma P (f b) =⇒ ∃ s A. (∀ x ∈ A. P x) ∧ f s ∈ A — Example 6. by force lemma ∃ A. a ∈/ A — Example 7. by force lemma (∀ u v. u < (0 ::int) −→ u 6= |v|) −→ (∃ A::int set. −2 ∈ A &(∀ y. |y| ∈/ A)) — Example 8 needs a small hint. by force — not blast, which can’t simplify −2 < 0

Example 9 omitted (requires the reals).

The paper has no Example 10!

280 lemma (∀ A. 0 ∈ A ∧ (∀ x ∈ A. Suc x ∈ A) −→ n ∈ A) ∧ P 0 ∧ (∀ x. P x −→ P (Suc x)) −→ P n — Example 11: needs a hint. by(metis nat.induct) lemma (∀ A. (0 , 0 ) ∈ A ∧ (∀ x y. (x, y) ∈ A −→ (Suc x, Suc y) ∈ A) −→ (n, m) ∈ A) ∧ P n −→ P m — Example 12. by auto lemma (∀ x. (∃ u. x = 2 ∗ u) = (¬ (∃ v. Suc x = 2 ∗ v))) −→ (∃ A. ∀ x. (x ∈ A) = (Suc x ∈/ A)) — Example EO1: typo in article, and with the obvious fix it seems to require arithmetic reasoning. apply clarify apply (rule-tac x = {x. ∃ u. x = 2 ∗ u} in exI , auto) apply metis+ done end

41 Examples and regression tests for automated termination proofs theory Termination imports Main ∼∼/src/HOL/Library/Multiset begin

41.1 Manually giving termination relations using relation and measure function sum :: nat ⇒ nat ⇒ nat where sum i N = (if i > N then 0 else i + sum (Suc i) N ) by pat-completeness auto termination by (relation measure (λ(i,N ). N + 1 − i)) auto function foo :: nat ⇒ nat ⇒ nat where foo i N = (if i > N then (if N = 0 then 0 else foo 0 (N − 1 )) else i + foo (Suc i) N ) by pat-completeness auto termination by (relation measures [λ(i, N ). N , λ(i,N ). N + 1 − i]) auto

281 41.2 lexicographic-order: Trivial examples

The fun command uses the method lexicographic-order by default, so it is not explicitly invoked. fun identity :: nat ⇒ nat where identity n = n fun yaSuc :: nat ⇒ nat where yaSuc 0 = 0 | yaSuc (Suc n) = Suc (yaSuc n)

41.3 Examples on natural numbers fun bin :: (nat ∗ nat) ⇒ nat where bin (0 , 0 ) = 1 | bin (Suc n, 0 ) = 0 | bin (0 , Suc m) = 0 | bin (Suc n, Suc m) = bin (n, m) + bin (Suc n, m) fun t :: (nat ∗ nat) ⇒ nat where t (0 ,n) = 0 | t (n,0 ) = 0 | t (Suc n, Suc m) = (if (n mod 2 = 0 ) then (t (Suc n, m)) else (t (n, Suc m))) fun k :: (nat ∗ nat) ∗ (nat ∗ nat) ⇒ nat where k ((0 ,0 ),(0 ,0 )) = 0 | k ((Suc z, y), (u,v)) = k((z, y), (u, v)) | k ((0 , Suc y), (u,v)) = k((1 , y), (u, v)) | k ((0 ,0 ), (Suc u, v)) = k((1 , 1 ), (u, v)) | k ((0 ,0 ), (0 , Suc v)) = k((1 ,1 ), (1 ,v)) fun gcd2 :: nat ⇒ nat ⇒ nat where gcd2 x 0 = x | gcd2 0 y = y | gcd2 (Suc x)(Suc y) = (if x < y then gcd2 (Suc x)(y − x) else gcd2 (x − y)(Suc y)) fun ack :: (nat ∗ nat) ⇒ nat where ack (0 , m) = Suc m

282 | ack (Suc n, 0 ) = ack(n, 1 ) | ack (Suc n, Suc m) = ack (n, ack (Suc n, m)) fun greedy :: nat ∗ nat ∗ nat ∗ nat ∗ nat => nat where greedy (Suc a, Suc b, Suc c, Suc d, Suc e) = (if (a < 10 ) then greedy (Suc a, Suc b, c, d + 2 , Suc e) else (if (a < 20 ) then greedy (Suc a, b, Suc c, d, Suc e) else (if (a < 30 ) then greedy (Suc a, b, Suc c, d, Suc e) else (if (a < 40 ) then greedy (Suc a, b, Suc c, d, Suc e) else (if (a < 50 ) then greedy (Suc a, b, Suc c, d, Suc e) else (if (a < 60 ) then greedy (a, Suc b, Suc c, d, Suc e) else (if (a < 70 ) then greedy (a, Suc b, Suc c, d, Suc e) else (if (a < 80 ) then greedy (a, Suc b, Suc c, d, Suc e) else (if (a < 90 ) then greedy (Suc a, Suc b, Suc c, d, e) else greedy (Suc a, Suc b, Suc c, d, e)))))))))) | greedy (a, b, c, d, e) = 0 fun blowup :: nat => nat => nat => nat => nat => nat => nat => nat => nat => nat where blowup 0 0 0 0 0 0 0 0 0 = 0 | blowup 0 0 0 0 0 0 0 0 (Suc i) = Suc (blowup i i i i i i i i i) | blowup 0 0 0 0 0 0 0 (Suc h) i = Suc (blowup h h h h h h h h i) | blowup 0 0 0 0 0 0 (Suc g) h i = Suc (blowup g g g g g g g h i) | blowup 0 0 0 0 0 (Suc f ) g h i = Suc (blowup f f f f f f g h i) | blowup 0 0 0 0 (Suc e) f g h i = Suc (blowup e e e e e f g h i) | blowup 0 0 0 (Suc d) e f g h i = Suc (blowup d d d d e f g h i) | blowup 0 0 (Suc c) d e f g h i = Suc (blowup c c c d e f g h i) | blowup 0 (Suc b) c d e f g h i = Suc (blowup b b c d e f g h i) | blowup (Suc a) b c d e f g h i = Suc (blowup a b c d e f g h i)

41.4 Simple examples with other datatypes than nat, e.g. trees and lists datatype tree = Node | Branch tree tree fun g-tree :: tree ∗ tree ⇒ tree where g-tree (Node, Node) = Node | g-tree (Node, Branch a b) = Branch Node (g-tree (a,b)) | g-tree (Branch a b, Node) = Branch (g-tree (a,Node)) b | g-tree (Branch a b, Branch c d) = Branch (g-tree (a,c)) (g-tree (b,d)) fun acklist :: 0a list ∗ 0a list ⇒ 0a list where

283 acklist ([], m) = ((hd m)#m) | acklist (n#ns, []) = acklist (ns, [n]) | acklist ((n#ns), (m#ms)) = acklist (ns, acklist ((n#ns), ms))

41.5 Examples with mutual recursion fun evn od :: nat ⇒ bool where evn 0 = True | od 0 = False | evn (Suc n) = od (Suc n) | od (Suc n) = evn n fun sizechange-f :: 0a list => 0a list => 0a list and sizechange-g :: 0a list => 0a list => 0a list => 0a list where sizechange-f i x = (if i=[] then x else sizechange-g (tl i) x i) | sizechange-g a b c = sizechange-f a (b @ c) fun pedal :: nat => nat => nat => nat and coast :: nat => nat => nat => nat where pedal 0 m c = c | pedal n 0 c = c | pedal n m c = (if n < m then coast (n − 1 )(m − 1 )(c + m) else pedal (n − 1 ) m (c + m))

| coast n m c = (if n < m then coast n (m − 1 )(c + n) else pedal n m (c + n))

41.6 Refined analysis: The size-change method

Unsolvable for lexicographic-order function fun1 :: nat ∗ nat ⇒ nat where fun1 (0 ,0 ) = 1 | fun1 (0 , Suc b) = 0 | fun1 (Suc a, 0 ) = 0 | fun1 (Suc a, Suc b) = fun1 (b, a) by pat-completeness auto termination by size-change lexicographic-order can do the following, but it is much slower. function

284 prod :: nat => nat => nat => nat and eprod :: nat => nat => nat => nat and oprod :: nat => nat => nat => nat where prod x y z = (if y mod 2 = 0 then eprod x y z else oprod x y z) | oprod x y z = eprod x (y − 1 )(z+x) | eprod x y z = (if y=0 then z else prod (2 ∗x)(y div 2 ) z) by pat-completeness auto termination by size-change

Permutations of arguments: function perm :: nat ⇒ nat ⇒ nat ⇒ nat where perm m n r = (if r > 0 then perm m (r − 1 ) n else if n > 0 then perm r (n − 1 ) m else m) by auto termination by size-change

Artificial examples and regression tests: function fun2 :: nat ⇒ nat ⇒ nat ⇒ nat where fun2 x y z = (if x > 1000 ∧ z > 0 then fun2 (min x y) y (z − 1 ) else if y > 0 ∧ x > 100 then fun2 x (y − 1 )(2 ∗ z) else if z > 0 then fun2 (min y (z − 1 )) x x else 0 ) by pat-completeness auto termination by size-change — requires Multiset definition negate :: int ⇒ int where negate i = − i function fun3 :: int => nat where fun3 i = (if i < 0 then fun3 (negate i) else if i = 0 then 0 else fun3 (i − 1 )) by (pat-completeness) auto termination apply size-change apply (simp add: negate-def )

285 apply size-change done end

42 Coherent Logic Problems theory Coherent imports Main begin

42.1 Equivalence of two versions of Pappus’ Axiom no-notation comp (infixl o 55 ) and relcomp (infixr O 75 ) lemma p1p2 : assumes col a b c l ∧ col d e f m and col b f g n ∧ col c e g o and col b d h p ∧ col a e h q and col c d i r ∧ col a f i s and el n o =⇒ goal and el p q =⇒ goal and el s r =⇒ goal and VA. el A A =⇒ pl g A =⇒ pl h A =⇒ pl i A =⇒ goal and VABCD. col A B C D =⇒ pl A D and VABCD. col A B C D =⇒ pl B D and VABCD. col A B C D =⇒ pl C D and VAB. pl A B =⇒ ep A A and VAB. ep A B =⇒ ep B A and VABC . ep A B =⇒ ep B C =⇒ ep A C and VAB. pl A B =⇒ el B B and VAB. el A B =⇒ el B A and VABC . el A B =⇒ el B C =⇒ el A C and VABC . ep A B =⇒ pl B C =⇒ pl A C and VABC . pl A B =⇒ el B C =⇒ pl A C and VABCDEFGHIJKLMNOPQ. col A B C D =⇒ col E F G H =⇒ col B G I J =⇒ col C F I K =⇒ col B E L M =⇒ col A F L N =⇒ col C E O P =⇒ col A G O Q =⇒ (∃ R. col I L O R) ∨ pl A H ∨ pl B H ∨ pl C H ∨ pl E D ∨ pl F D ∨ pl G D and VABCD. pl A B =⇒ pl A C =⇒ pl D B =⇒ pl D C =⇒ ep A D ∨ el BC and VAB. ep A A =⇒ ep B B =⇒ ∃ C . pl A C ∧ pl B C shows goal using assms by coherent

286 lemma p2p1 : assumes col a b c l ∧ col d e f m and col b f g n ∧ col c e g o and col b d h p ∧ col a e h q and col c d i r ∧ col a f i s and pl a m =⇒ goal and pl b m =⇒ goal and pl c m =⇒ goal and pl d l =⇒ goal and pl e l =⇒ goal and pl f l =⇒ goal and VA. pl g A =⇒ pl h A =⇒ pl i A =⇒ goal and VABCD. col A B C D =⇒ pl A D and VABCD. col A B C D =⇒ pl B D and VABCD. col A B C D =⇒ pl C D and VAB. pl A B =⇒ ep A A and VAB. ep A B =⇒ ep B A and VABC . ep A B =⇒ ep B C =⇒ ep A C and VAB. pl A B =⇒ el B B and VAB. el A B =⇒ el B A and VABC . el A B =⇒ el B C =⇒ el A C and VABC . ep A B =⇒ pl B C =⇒ pl A C and VABC . pl A B =⇒ el B C =⇒ pl A C and VABCDEFGHIJKLMNOPQ. col A B C J =⇒ col D E F K =⇒ col B F G L =⇒ col C E G M =⇒ col B D H N =⇒ col A E H O =⇒ col C D I P =⇒ col A F I Q =⇒ (∃ R. col G H I R) ∨ el L M ∨ el N O ∨ el P Q and VABCD. pl C A =⇒ pl C B =⇒ pl D A =⇒ pl D B =⇒ ep C D ∨ el AB and VABC . ep A A =⇒ ep B B =⇒ ∃ C . pl A C ∧ pl B C shows goal using assms by coherent

42.2 Preservation of the Diamond Property under reflexive closure lemma diamond: assumes reflexive-rewrite a b reflexive-rewrite a c and VA. reflexive-rewrite b A =⇒ reflexive-rewrite c A =⇒ goal and VA. equalish A A and VAB. equalish A B =⇒ equalish B A and VABC . equalish A B =⇒ reflexive-rewrite B C =⇒ reflexive-rewrite A C and VAB. equalish A B =⇒ reflexive-rewrite A B and VAB. rewrite A B =⇒ reflexive-rewrite A B and VAB. reflexive-rewrite A B =⇒ equalish A B ∨ rewrite A B and VABC . rewrite A B =⇒ rewrite A C =⇒ ∃ D. rewrite B D ∧ rewrite C D shows goal using assms

287 by coherent end

43 Some examples for Presburger Arithmetic theory PresburgerEx imports Presburger begin lemma Vm n ja ia. [[¬ m ≤ j ; ¬ (n::nat) ≤ i;(e::nat) 6= 0 ; Suc j ≤ ja]] =⇒ ∃ m. ∀ ja ia. m ≤ ja −→ (if j = ja ∧ i = ia then e else 0 ) = 0 by presburger lemma (0 ::nat) < emBits mod 8 =⇒ 8 + emBits div 8 ∗ 8 − emBits = 8 − emBits mod 8 by presburger lemma (0 ::nat) < emBits mod 8 =⇒ 8 + emBits div 8 ∗ 8 − emBits = 8 − emBits mod 8 by presburger theorem (∀ (y::int). 3 dvd y) ==> ∀ (x::int). b < x −−> a ≤ x by presburger theorem !! (y::int)(z::int)(n::int). 3 dvd z ==> 2 dvd (y::int) ==> (∃ (x::int). 2 ∗x = y)&(∃ (k::int). 3 ∗k = z) by presburger theorem !! (y::int)(z::int) n. Suc(n::nat) < 6 ==> 3 dvd z ==> 2 dvd (y::int) ==> (∃ (x::int). 2 ∗x = y)&(∃ (k::int). 3 ∗k = z) by presburger theorem ∀ (x::nat). ∃ (y::nat). (0 ::nat) ≤ 5 −−> y = 5 + x by presburger Slow: about 7 seconds on a 1.6GHz machine. theorem ∀ (x::nat). ∃ (y::nat). y = 5 + x | x div 6 + 1 = 2 by presburger theorem ∃ (x::int). 0 < x by presburger theorem ∀ (x::int) y. x < y −−> 2 ∗ x + 1 < 2 ∗ y by presburger theorem ∀ (x::int) y. 2 ∗ x + 1 6= 2 ∗ y by presburger theorem ∃ (x::int) y. 0 < x & 0 ≤ y & 3 ∗ x − 5 ∗ y = 1 by presburger

288 theorem ∼ (∃ (x::int)(y::int)(z::int). 4 ∗x + (−6 ::int)∗y = 1 ) by presburger theorem ∀ (x::int). b < x −−> a ≤ x apply (presburger elim) oops theorem ∼ (∃ (x::int). False) by presburger theorem ∀ (x::int). (a::int) < 3 ∗ x −−> b < 3 ∗ x apply (presburger elim) oops theorem ∀ (x::int). (2 dvd x) −−> (∃ (y::int). x = 2 ∗y) by presburger theorem ∀ (x::int). (2 dvd x) −−> (∃ (y::int). x = 2 ∗y) by presburger theorem ∀ (x::int). (2 dvd x) = (∃ (y::int). x = 2 ∗y) by presburger theorem ∀ (x::int). ((2 dvd x) = (∀ (y::int). x 6= 2 ∗y + 1 )) by presburger theorem ∼ (∀ (x::int). ((2 dvd x) = (∀ (y::int). x 6= 2 ∗y+1 ) | (∃ (q::int)(u::int) i. 3 ∗i + 2 ∗q − u < 17 ) −−> 0 < x | ((∼ 3 dvd x) &(x + 8 = 0 )))) by presburger theorem ∼ (∀ (i::int). 4 ≤ i −−> (∃ x y. 0 ≤ x & 0 ≤ y & 3 ∗ x + 5 ∗ y = i)) by presburger theorem ∀ (i::int). 8 ≤ i −−> (∃ x y. 0 ≤ x & 0 ≤ y & 3 ∗ x + 5 ∗ y = i) by presburger theorem ∃ (j ::int). ∀ i. j ≤ i −−> (∃ x y. 0 ≤ x & 0 ≤ y & 3 ∗ x + 5 ∗ y = i) by presburger theorem ∼ (∀ j (i::int). j ≤ i −−> (∃ x y. 0 ≤ x & 0 ≤ y & 3 ∗ x + 5 ∗ y = i)) by presburger Slow: about 5 seconds on a 1.6GHz machine. theorem (∃ m::nat. n = 2 ∗ m) −−> (n + 1 ) div 2 = n div 2 by presburger This following theorem proves that all solutions to the recurrence relation

289 xi+2 = |xi+1| − xi are periodic with period 9. The example was brought to our attention by John Harrison. It does does not require Presburger arithmetic but merely quantifier-free linear arithmetic and holds for the rationals as well. Warning: it takes (in 2006) over 4.2 minutes! lemma [[ x3 = |x2 | − x1 ; x4 = |x3 | − x2 ; x5 = |x4 | − x3 ; x6 = |x5 | − x4 ; x7 = |x6 | − x5 ; x8 = |x7 | − x6 ; x9 = |x8 | − x7 ; x10 = |x9 | − x8 ; x11 = |x10 | − x9 ]] =⇒ x1 = x10 & x2 = (x11 ::int) by arith end

44 Generic reflection and reification theory Reflection imports Main begin

ML-file ∼∼/src/HOL/Tools/reflection.ML method-setup reify = h Attrib.thms −− Scan.option (Scan.lift (Args.$$$ () |−− Args.term −−| Scan.lift (Args.$$$ ))) >> (fn (user-eqs, to) => fn ctxt => SIMPLE-METHOD 0 (Reflection.default-reify-tac ctxt user-eqs to)) i partial automatic reification method-setup reflection = h let fun keyword k = Scan.lift (Args.$$$ k −− Args.colon) >> K (); val onlyN = only; val rulesN = rules; val any-keyword = keyword onlyN || keyword rulesN ; val thms = Scan.repeats (Scan.unless any-keyword Attrib.multi-thm); val terms = thms >> map (Thm.term-of o Drule.dest-term); in thms −− Scan.optional (keyword rulesN |−− thms) [] −− Scan.option (keyword onlyN |−− Args.term) >> (fn ((user-eqs, user-thms), to) => fn ctxt => SIMPLE-METHOD 0 (Reflection.default-reflection-tac ctxt user-thms user-eqs to)) end i partial automatic reflection end

290 45 Examples for generic reflection and reification theory Reflection-Examples imports Complex-Main ∼∼/src/HOL/Library/Reflection begin

This theory presents two methods: reify and reflection

Consider an HOL type σ, the structure of which is not recongnisable on the theory level. This is the case of bool, arithmetical terms such as int, real etc . . . In order to implement a simplification on terms of type σ we often need its structure. Traditionnaly such simplifications are written in ML, proofs are synthesized. An other strategy is to declare an HOL datatype τ and an HOL function (the interpretation) that maps elements of τ to elements of σ. The functionality of reify then is, given a term t of type σ, to compute a term s of type τ. For this it needs equations for the interpretation. N.B: All the interpretations supported by reify must have the type 0a list ⇒ τ ⇒ σ. The method reify can also be told which subterm of the current subgoal should be reified. The general call for reify is reify eqs (t), where eqs are the defining equations of the interpretation and (t) is an optional parameter which specifies the subterm to which reification should be applied to. If (t) is abscent, reify tries to reify the whole subgoal. The method reflection uses reify and has a very similar signature: reflection corr-thm eqs (t). Here again eqs and (t) are as described above and corr-thm is a theorem proving I vs (f t) = I vs t. We assume that I is the interpreta- tion and f is some useful and executable simplification of type τ ⇒ τ. The method reflection applies reification and hence the theorem t = I xs s and hence using corr-thm derives t = I xs (f s). It then uses normalization by equational rewriting to prove f s = s 0 which almost finishes the proof of t = t 0 where I xs s 0 = t 0.

Example 1 : Propositional formulae and NNF.

The type fm represents simple propositional formulae: datatype form = TrueF | FalseF | Less nat nat | And form form | Or form form | Neg form | ExQ form primrec interp :: form ⇒ ( 0a::ord) list ⇒ bool where interp TrueF vs ←→ True | interp FalseF vs ←→ False | interp (Less i j ) vs ←→ vs ! i < vs ! j | interp (And f1 f2 ) vs ←→ interp f1 vs ∧ interp f2 vs | interp (Or f1 f2 ) vs ←→ interp f1 vs ∨ interp f2 vs | interp (Neg f ) vs ←→ ¬ interp f vs

291 | interp (ExQ f ) vs ←→ (∃ v. interp f (v # vs)) lemmas interp-reify-eqs = interp.simps declare interp-reify-eqs [reify] lemma ∃ x. x < y ∧ x < z apply reify oops datatype fm = And fm fm | Or fm fm | Imp fm fm | Iff fm fm | NOT fm | At nat primrec Ifm :: fm ⇒ bool list ⇒ bool where Ifm (At n) vs ←→ vs ! n | Ifm (And p q) vs ←→ Ifm p vs ∧ Ifm q vs | Ifm (Or p q) vs ←→ Ifm p vs ∨ Ifm q vs | Ifm (Imp p q) vs ←→ Ifm p vs −→ Ifm q vs | Ifm (Iff p q) vs ←→ Ifm p vs = Ifm q vs | Ifm (NOT p) vs ←→ ¬ Ifm p vs lemma Q −→ (D ∧ F ∧ ((¬ D) ∧ (¬ F ))) apply (reify Ifm.simps) oops

Method reify maps a bool to an fm. For this it needs the semantics of fm, i.e. the rewrite rules in Ifm.simps.

You can also just pick up a subterm to reify. lemma Q −→ (D ∧ F ∧ ((¬ D) ∧ (¬ F ))) apply (reify Ifm.simps (((¬ D) ∧ (¬ F )))) oops

Let’s perform NNF. This is a version that tends to generate disjunctions primrec fmsize :: fm ⇒ nat where fmsize (At n) = 1 | fmsize (NOT p) = 1 + fmsize p | fmsize (And p q) = 1 + fmsize p + fmsize q | fmsize (Or p q) = 1 + fmsize p + fmsize q | fmsize (Imp p q) = 2 + fmsize p + fmsize q | fmsize (Iff p q) = 2 + 2 ∗ fmsize p + 2 ∗ fmsize q lemma [measure-function]: is-measure fmsize .. fun nnf :: fm ⇒ fm where nnf (At n) = At n | nnf (And p q) = And (nnf p)(nnf q)

292 | nnf (Or p q) = Or (nnf p)(nnf q) | nnf (Imp p q) = Or (nnf (NOT p)) (nnf q) | nnf (Iff p q) = Or (And (nnf p)(nnf q)) (And (nnf (NOT p)) (nnf (NOT q))) | nnf (NOT (And p q)) = Or (nnf (NOT p)) (nnf (NOT q)) | nnf (NOT (Or p q)) = And (nnf (NOT p)) (nnf (NOT q)) | nnf (NOT (Imp p q)) = And (nnf p)(nnf (NOT q)) | nnf (NOT (Iff p q)) = Or (And (nnf p)(nnf (NOT q))) (And (nnf (NOT p)) (nnf q)) | nnf (NOT (NOT p)) = nnf p | nnf (NOT p) = NOT p

The correctness theorem of nnf : it preserves the semantics of fm lemma nnf [reflection]: Ifm (nnf p) vs = Ifm p vs by (induct p rule: nnf .induct) auto

Now let’s perform NNF using our nnf function defined above. First to the whole subgoal. lemma A 6= B ∧ (B −→ A 6= (B ∨ C ∧ (B −→ A ∨ D))) −→ A ∨ B ∧ D apply (reflection Ifm.simps) oops

Now we specify on which subterm it should be applied lemma A 6= B ∧ (B −→ A 6= (B ∨ C ∧ (B −→ A ∨ D))) −→ A ∨ B ∧ D apply (reflection Ifm.simps only: B ∨ C ∧ (B −→ A ∨ D)) oops

Example 2: Simple arithmetic formulae The type num reflects linear expressions over natural number datatype num = C nat | Add num num | Mul nat num | Var nat | CN nat nat num

This is just technical to make recursive definitions easier. primrec num-size :: num ⇒ nat where num-size (C c) = 1 | num-size (Var n) = 1 | num-size (Add a b) = 1 + num-size a + num-size b | num-size (Mul c a) = 1 + num-size a | num-size (CN n c a) = 4 + num-size a lemma [measure-function]: is-measure num-size ..

The semantics of num primrec Inum:: num ⇒ nat list ⇒ nat where Inum-C : Inum (C i) vs = i

293 | Inum-Var: Inum (Var n) vs = vs!n | Inum-Add: Inum (Add s t) vs = Inum s vs + Inum t vs | Inum-Mul: Inum (Mul c t) vs = c ∗ Inum t vs | Inum-CN : Inum (CN n c t) vs = c∗(vs!n) + Inum t vs

Let’s reify some nat expressions . . . lemma 4 ∗ (2 ∗ x + (y::nat)) + f a 6= 0 apply (reify Inum.simps (4 ∗ (2 ∗ x + (y::nat)) + f a)) oops

We’re in a bad situation! x, y and f have been recongnized as constants, which is correct but does not correspond to our intuition of the constructor C. It should encapsulate constants, i.e. numbers, i.e. numerals.

So let’s leave the Inum-C equation at the end and see what happens . . . lemma 4 ∗ (2 ∗ x + (y::nat)) 6= 0 apply (reify Inum-Var Inum-Add Inum-Mul Inum-CN Inum-C (4 ∗ (2 ∗ x + (y::nat)))) oops

Hm, let’s specialize Inum-C with numerals. lemma Inum-number: Inum (C (numeral t)) vs = numeral t by simp lemmas Inum-eqs = Inum-Var Inum-Add Inum-Mul Inum-CN Inum-number

Second attempt lemma 1 ∗ (2 ∗ x + (y::nat)) 6= 0 apply (reify Inum-eqs (1 ∗ (2 ∗ x + (y::nat)))) oops

That was fine, so let’s try another one . . . lemma 1 ∗ (2 ∗ x + (y::nat) + 0 + 1 ) 6= 0 apply (reify Inum-eqs (1 ∗ (2 ∗ x + (y::nat) + 0 + 1 ))) oops

Oh!! 0 is not a variable . . . Oh! 0 is not a numeral . . . thing. The same for 1. So let’s add those equations, too. lemma Inum-01 : Inum (C 0 ) vs = 0 Inum (C 1 ) vs = 1 Inum (C (Suc n)) vs = Suc n by simp-all lemmas Inum-eqs 0= Inum-eqs Inum-01

Third attempt: lemma 1 ∗ (2 ∗ x + (y::nat) + 0 + 1 ) 6= 0 apply (reify Inum-eqs 0 (1 ∗ (2 ∗ x + (y::nat) + 0 + 1 ))) oops

294 Okay, let’s try reflection. Some simplifications on Reflection-Examples.num follow. You can skim until the main theorem linum. fun lin-add :: num ⇒ num ⇒ num where lin-add (CN n1 c1 r1 )(CN n2 c2 r2 ) = (if n1 = n2 then (let c = c1 + c2 in (if c = 0 then lin-add r1 r2 else CN n1 c (lin-add r1 r2 ))) else if n1 ≤ n2 then (CN n1 c1 (lin-add r1 (CN n2 c2 r2 ))) else (CN n2 c2 (lin-add (CN n1 c1 r1 ) r2 ))) | lin-add (CN n1 c1 r1 ) t = CN n1 c1 (lin-add r1 t) | lin-add t (CN n2 c2 r2 ) = CN n2 c2 (lin-add t r2 ) | lin-add (C b1 )(C b2 ) = C (b1 + b2 ) | lin-add a b = Add a b lemma lin-add: Inum (lin-add t s) bs = Inum (Add t s) bs apply (induct t s rule: lin-add.induct, simp-all add: Let-def ) apply (case-tac c1 +c2 = 0 ,case-tac n1 ≤ n2 , simp-all) apply (case-tac n1 = n2 , simp-all add: algebra-simps) done fun lin-mul :: num ⇒ nat ⇒ num where lin-mul (C j ) i = C (i ∗ j ) | lin-mul (CN n c a) i = (if i=0 then (C 0 ) else CN n (i ∗ c)(lin-mul a i)) | lin-mul t i = (Mul i t) lemma lin-mul: Inum (lin-mul t i) bs = Inum (Mul i t) bs by (induct t i rule: lin-mul.induct)(auto simp add: algebra-simps) fun linum:: num ⇒ num where linum (C b) = C b | linum (Var n) = CN n 1 (C 0 ) | linum (Add t s) = lin-add (linum t)(linum s) | linum (Mul c t) = lin-mul (linum t) c | linum (CN n c t) = lin-add (linum (Mul c (Var n))) (linum t) lemma linum [reflection]: Inum (linum t) bs = Inum t bs by (induct t rule: linum.induct)(simp-all add: lin-mul lin-add)

Now we can use linum to simplify nat terms using reflection lemma Suc (Suc 1 ) ∗ (x + Suc 1 ∗ y) = 3 ∗ x + 6 ∗ y apply (reflection Inum-eqs 0 only: Suc (Suc 1 ) ∗ (x + Suc 1 ∗ y)) oops

295 Let’s lift this to formulae and see what happens datatype aform = Lt num num | Eq num num | Ge num num | NEq num num | Conj aform aform | Disj aform aform | NEG aform | T | F primrec linaformsize:: aform ⇒ nat where linaformsize T = 1 | linaformsize F = 1 | linaformsize (Lt a b) = 1 | linaformsize (Ge a b) = 1 | linaformsize (Eq a b) = 1 | linaformsize (NEq a b) = 1 | linaformsize (NEG p) = 2 + linaformsize p | linaformsize (Conj p q) = 1 + linaformsize p + linaformsize q | linaformsize (Disj p q) = 1 + linaformsize p + linaformsize q lemma [measure-function]: is-measure linaformsize .. primrec is-aform :: aform => nat list => bool where is-aform T vs = True | is-aform F vs = False | is-aform (Lt a b) vs = (Inum a vs < Inum b vs) | is-aform (Eq a b) vs = (Inum a vs = Inum b vs) | is-aform (Ge a b) vs = (Inum a vs ≥ Inum b vs) | is-aform (NEq a b) vs = (Inum a vs 6= Inum b vs) | is-aform (NEG p) vs = (¬ (is-aform p vs)) | is-aform (Conj p q) vs = (is-aform p vs ∧ is-aform q vs) | is-aform (Disj p q) vs = (is-aform p vs ∨ is-aform q vs)

Let’s reify and do reflection lemma (3 ::nat) ∗ x + t < 0 ∧ (2 ∗ x + y 6= 17 ) apply (reify Inum-eqs 0 is-aform.simps) oops

Note that reification handles several interpretations at the same time lemma (3 ::nat) ∗ x + t < 0 ∧ x ∗ x + t ∗ x + 3 + 1 = z ∗ t ∗ 4 ∗ z ∨ x + x + 1 < 0 apply (reflection Inum-eqs 0 is-aform.simps only: x + x + 1 ) oops

For reflection we now define a simple transformation on aform: NNF + linum on atoms fun linaform:: aform ⇒ aform where linaform (Lt s t) = Lt (linum s)(linum t) | linaform (Eq s t) = Eq (linum s)(linum t)

296 | linaform (Ge s t) = Ge (linum s)(linum t) | linaform (NEq s t) = NEq (linum s)(linum t) | linaform (Conj p q) = Conj (linaform p)(linaform q) | linaform (Disj p q) = Disj (linaform p)(linaform q) | linaform (NEG T ) = F | linaform (NEG F ) = T | linaform (NEG (Lt a b)) = Ge a b | linaform (NEG (Ge a b)) = Lt a b | linaform (NEG (Eq a b)) = NEq a b | linaform (NEG (NEq a b)) = Eq a b | linaform (NEG (NEG p)) = linaform p | linaform (NEG (Conj p q)) = Disj (linaform (NEG p)) (linaform (NEG q)) | linaform (NEG (Disj p q)) = Conj (linaform (NEG p)) (linaform (NEG q)) | linaform p = p lemma linaform: is-aform (linaform p) vs = is-aform p vs by (induct p rule: linaform.induct)(auto simp add: linum) lemma (Suc (Suc (Suc 0 )) ∗ ((x::nat) + Suc (Suc 0 )) + Suc (Suc (Suc 0 )) ∗ (Suc (Suc (Suc 0 ))) ∗ ((x::nat) + Suc (Suc 0 ))) < 0 ∧ Suc 0 + Suc 0 < 0 apply (reflection Inum-eqs 0 is-aform.simps rules: linaform) oops declare linaform [reflection] lemma (Suc (Suc (Suc 0 )) ∗ ((x::nat) + Suc (Suc 0 )) + Suc (Suc (Suc 0 )) ∗ (Suc (Suc (Suc 0 ))) ∗ ((x::nat) + Suc (Suc 0 ))) < 0 ∧ Suc 0 + Suc 0 < 0 apply (reflection Inum-eqs 0 is-aform.simps) oops

We now give an example where interpretaions have zero or more than only one envornement of different types and show that automatic reification also deals with bindings datatype rb = BC bool | BAnd rb rb | BOr rb rb primrec Irb :: rb ⇒ bool where Irb (BC p) ←→ p | Irb (BAnd s t) ←→ Irb s ∧ Irb t | Irb (BOr s t) ←→ Irb s ∨ Irb t lemma A ∧ (B ∨ D ∧ B) ∧ A ∧ (B ∨ D ∧ B) ∨ A ∧ (B ∨ D ∧ B) ∨ A ∧ (B ∨ D ∧ B) apply (reify Irb.simps) oops datatype rint = IC int | IVar nat | IAdd rint rint | IMult rint rint | INeg rint | ISub rint rint

297 primrec Irint :: rint ⇒ int list ⇒ int where Irint-Var: Irint (IVar n) vs = vs ! n | Irint-Neg: Irint (INeg t) vs = − Irint t vs | Irint-Add: Irint (IAdd s t) vs = Irint s vs + Irint t vs | Irint-Sub: Irint (ISub s t) vs = Irint s vs − Irint t vs | Irint-Mult: Irint (IMult s t) vs = Irint s vs ∗ Irint t vs | Irint-C : Irint (IC i) vs = i lemma Irint-C0 : Irint (IC 0 ) vs = 0 by simp lemma Irint-C1 : Irint (IC 1 ) vs = 1 by simp lemma Irint-Cnumeral: Irint (IC (numeral x)) vs = numeral x by simp lemmas Irint-simps = Irint-Var Irint-Neg Irint-Add Irint-Sub Irint-Mult Irint-C0 Irint-C1 Irint-Cnumeral lemma (3 ::int) ∗ x + y ∗ y − 9 + (− z) = 0 apply (reify Irint-simps ((3 ::int) ∗ x + y ∗ y − 9 + (− z))) oops datatype rlist = LVar nat | LEmpty | LCons rint rlist | LAppend rlist rlist primrec Irlist :: rlist ⇒ int list ⇒ int list list ⇒ int list where Irlist (LEmpty) is vs = [] | Irlist (LVar n) is vs = vs ! n | Irlist (LCons i t) is vs = Irint i is # Irlist t is vs | Irlist (LAppend s t) is vs = Irlist s is vs @ Irlist t is vs lemma [(1 ::int)] = [] apply (reify Irlist.simps Irint-simps ([1 ] :: int list)) oops lemma ([(3 ::int) ∗ x + y ∗ y − 9 + (− z)] @ []) @ xs = [y ∗ y − z − 9 + (3 ::int) ∗ x] apply (reify Irlist.simps Irint-simps (([(3 ::int) ∗ x + y ∗ y − 9 + (− z)] @ []) @ xs)) oops datatype rnat = NC nat| NVar nat| NSuc rnat | NAdd rnat rnat | NMult rnat rnat | NNeg rnat | NSub rnat rnat | Nlgth rlist primrec Irnat :: rnat ⇒ int list ⇒ int list list ⇒ nat list ⇒ nat

298 where Irnat-Suc: Irnat (NSuc t) is ls vs = Suc (Irnat t is ls vs) | Irnat-Var: Irnat (NVar n) is ls vs = vs ! n | Irnat-Neg: Irnat (NNeg t) is ls vs = 0 | Irnat-Add: Irnat (NAdd s t) is ls vs = Irnat s is ls vs + Irnat t is ls vs | Irnat-Sub: Irnat (NSub s t) is ls vs = Irnat s is ls vs − Irnat t is ls vs | Irnat-Mult: Irnat (NMult s t) is ls vs = Irnat s is ls vs ∗ Irnat t is ls vs | Irnat-lgth: Irnat (Nlgth rxs) is ls vs = length (Irlist rxs is ls) | Irnat-C : Irnat (NC i) is ls vs = i lemma Irnat-C0 : Irnat (NC 0 ) is ls vs = 0 by simp lemma Irnat-C1 : Irnat (NC 1 ) is ls vs = 1 by simp lemma Irnat-Cnumeral: Irnat (NC (numeral x)) is ls vs = numeral x by simp lemmas Irnat-simps = Irnat-Suc Irnat-Var Irnat-Neg Irnat-Add Irnat-Sub Irnat-Mult Irnat-lgth Irnat-C0 Irnat-C1 Irnat-Cnumeral lemma Suc n ∗ length (([(3 ::int) ∗ x + y ∗ y − 9 + (− z)] @ []) @ xs) = length xs apply (reify Irnat-simps Irlist.simps Irint-simps (Suc n ∗ length (([(3 ::int) ∗ x + y ∗ y − 9 + (− z)] @ []) @ xs))) oops datatype rifm = RT | RF | RVar nat | RNLT rnat rnat | RNILT rnat rint | RNEQ rnat rnat | RAnd rifm rifm | ROr rifm rifm | RImp rifm rifm| RIff rifm rifm | RNEX rifm | RIEX rifm | RLEX rifm | RNALL rifm | RIALL rifm | RLALL rifm | RBEX rifm | RBALL rifm primrec Irifm :: rifm ⇒ bool list ⇒ int list ⇒ (int list) list ⇒ nat list ⇒ bool where Irifm RT ps is ls ns ←→ True | Irifm RF ps is ls ns ←→ False | Irifm (RVar n) ps is ls ns ←→ ps ! n | Irifm (RNLT s t) ps is ls ns ←→ Irnat s is ls ns < Irnat t is ls ns | Irifm (RNILT s t) ps is ls ns ←→ int (Irnat s is ls ns) < Irint t is | Irifm (RNEQ s t) ps is ls ns ←→ Irnat s is ls ns = Irnat t is ls ns | Irifm (RAnd p q) ps is ls ns ←→ Irifm p ps is ls ns ∧ Irifm q ps is ls ns | Irifm (ROr p q) ps is ls ns ←→ Irifm p ps is ls ns ∨ Irifm q ps is ls ns | Irifm (RImp p q) ps is ls ns ←→ Irifm p ps is ls ns −→ Irifm q ps is ls ns | Irifm (RIff p q) ps is ls ns ←→ Irifm p ps is ls ns = Irifm q ps is ls ns | Irifm (RNEX p) ps is ls ns ←→ (∃ x. Irifm p ps is ls (x # ns))

299 | Irifm (RIEX p) ps is ls ns ←→ (∃ x. Irifm p ps (x # is) ls ns) | Irifm (RLEX p) ps is ls ns ←→ (∃ x. Irifm p ps is (x # ls) ns) | Irifm (RBEX p) ps is ls ns ←→ (∃ x. Irifm p (x # ps) is ls ns) | Irifm (RNALL p) ps is ls ns ←→ (∀ x. Irifm p ps is ls (x#ns)) | Irifm (RIALL p) ps is ls ns ←→ (∀ x. Irifm p ps (x # is) ls ns) | Irifm (RLALL p) ps is ls ns ←→ (∀ x. Irifm p ps is (x#ls) ns) | Irifm (RBALL p) ps is ls ns ←→ (∀ x. Irifm p (x # ps) is ls ns) lemma ∀ x. ∃ n. ((Suc n) ∗ length (([(3 ::int) ∗ x + f t ∗ y − 9 + (− z)] @ []) @ xs) = length xs) ∧ m < 5 ∗n − length (xs @[2 ,3 ,4 ,x∗z + 8 − y]) −→ (∃ p. ∀ q. p ∧ q −→ r) apply (reify Irifm.simps Irnat-simps Irlist.simps Irint-simps) oops

An example for equations containing type variables datatype prod = Zero | One | Var nat | Mul prod prod | Pw prod nat | PNM nat nat prod primrec Iprod :: prod ⇒ ( 0a::linordered-idom) list ⇒ 0a where Iprod Zero vs = 0 | Iprod One vs = 1 | Iprod (Var n) vs = vs ! n | Iprod (Mul a b) vs = Iprod a vs ∗ Iprod b vs | Iprod (Pw a n) vs = Iprod a vs ˆ n | Iprod (PNM n k t) vs = (vs ! n) ˆ k ∗ Iprod t vs datatype sgn = Pos prod | Neg prod | ZeroEq prod | NZeroEq prod | Tr | F | Or sgn sgn | And sgn sgn primrec Isgn :: sgn ⇒ ( 0a::linordered-idom) list ⇒ bool where Isgn Tr vs ←→ True | Isgn F vs ←→ False | Isgn (ZeroEq t) vs ←→ Iprod t vs = 0 | Isgn (NZeroEq t) vs ←→ Iprod t vs 6= 0 | Isgn (Pos t) vs ←→ Iprod t vs > 0 | Isgn (Neg t) vs ←→ Iprod t vs < 0 | Isgn (And p q) vs ←→ Isgn p vs ∧ Isgn q vs | Isgn (Or p q) vs ←→ Isgn p vs ∨ Isgn q vs lemmas eqs = Isgn.simps Iprod.simps lemma (x:: 0a::{linordered-idom}) ˆ 4 ∗ y ∗ z ∗ y ˆ 2 ∗ z ˆ 23 > 0 apply (reify eqs) oops end

300 46 Factorial (semi)rings theory Factorial-Ring imports Main ∼∼/src/HOL/GCD ∼∼/src/HOL/Library/Multiset begin

46.1 Irreducible and prime elements context comm-semiring-1 begin definition irreducible :: 0a ⇒ bool where irreducible p ←→ p 6= 0 ∧ ¬p dvd 1 ∧ (∀ a b. p = a ∗ b −→ a dvd 1 ∨ b dvd 1 ) lemma not-irreducible-zero [simp]: ¬irreducible 0 by (simp add: irreducible-def ) lemma irreducible-not-unit: irreducible p =⇒ ¬p dvd 1 by (simp add: irreducible-def ) lemma not-irreducible-one [simp]: ¬irreducible 1 by (simp add: irreducible-def ) lemma irreducibleI : p 6= 0 =⇒ ¬p dvd 1 =⇒ (Va b. p = a ∗ b =⇒ a dvd 1 ∨ b dvd 1 ) =⇒ irreducible p by (simp add: irreducible-def ) lemma irreducibleD: irreducible p =⇒ p = a ∗ b =⇒ a dvd 1 ∨ b dvd 1 by (simp add: irreducible-def ) definition prime-elem :: 0a ⇒ bool where prime-elem p ←→ p 6= 0 ∧ ¬p dvd 1 ∧ (∀ a b. p dvd (a ∗ b) −→ p dvd a ∨ p dvd b) lemma not-prime-elem-zero [simp]: ¬prime-elem 0 by (simp add: prime-elem-def ) lemma prime-elem-not-unit: prime-elem p =⇒ ¬p dvd 1 by (simp add: prime-elem-def ) lemma prime-elemI : p 6= 0 =⇒ ¬p dvd 1 =⇒ (Va b. p dvd (a ∗ b) =⇒ p dvd a ∨ p dvd b) =⇒ prime-elem p by (simp add: prime-elem-def ) lemma prime-elem-dvd-multD:

301 prime-elem p =⇒ p dvd (a ∗ b) =⇒ p dvd a ∨ p dvd b by (simp add: prime-elem-def ) lemma prime-elem-dvd-mult-iff : prime-elem p =⇒ p dvd (a ∗ b) ←→ p dvd a ∨ p dvd b by (auto simp: prime-elem-def ) lemma not-prime-elem-one [simp]: ¬ prime-elem 1 by (auto dest: prime-elem-not-unit) lemma prime-elem-not-zeroI : assumes prime-elem p shows p 6= 0 using assms by (auto intro: ccontr) lemma prime-elem-dvd-power: prime-elem p =⇒ p dvd x ˆ n =⇒ p dvd x by (induction n)(auto dest: prime-elem-dvd-multD intro: dvd-trans[of - 1 ]) lemma prime-elem-dvd-power-iff : prime-elem p =⇒ n > 0 =⇒ p dvd x ˆ n ←→ p dvd x by (auto dest: prime-elem-dvd-power intro: dvd-trans) lemma prime-elem-imp-nonzero [simp]: ASSUMPTION (prime-elem x) =⇒ x 6= 0 unfolding ASSUMPTION-def by (rule prime-elem-not-zeroI ) lemma prime-elem-imp-not-one [simp]: ASSUMPTION (prime-elem x) =⇒ x 6= 1 unfolding ASSUMPTION-def by auto end context algebraic-semidom begin lemma prime-elem-imp-irreducible: assumes prime-elem p shows irreducible p proof (rule irreducibleI ) fix a b assume p-eq: p = a ∗ b with assms have nz: a 6= 0 b 6= 0 by auto from p-eq have p dvd a ∗ b by simp with hprime-elem pi have p dvd a ∨ p dvd b by (rule prime-elem-dvd-multD) with hp = a ∗ bi have a ∗ b dvd 1 ∗ b ∨ a ∗ b dvd a ∗ 1 by auto thus a dvd 1 ∨ b dvd 1 by (simp only: dvd-times-left-cancel-iff [OF nz(1 )] dvd-times-right-cancel-iff [OF

302 nz(2 )]) qed (insert assms, simp-all add: prime-elem-def ) lemma (in algebraic-semidom) unit-imp-no-irreducible-: assumes is-unit x irreducible p shows ¬p dvd x proof (rule notI ) assume p dvd x with his-unit x i have is-unit p by (auto intro: dvd-trans) with hirreducible pi show False by (simp add: irreducible-not-unit) qed lemma unit-imp-no-prime-divisors: assumes is-unit x prime-elem p shows ¬p dvd x using unit-imp-no-irreducible-divisors[OF assms(1 ) prime-elem-imp-irreducible[OF assms(2 )]] . lemma prime-elem-mono: assumes prime-elem p ¬q dvd 1 q dvd p shows prime-elem q proof − from hq dvd pi obtain r where r: p = q ∗ r by (elim dvdE) hence p dvd q ∗ r by simp with hprime-elem pi have p dvd q ∨ p dvd r by (rule prime-elem-dvd-multD) hence p dvd q proof assume p dvd r then obtain s where s: r = p ∗ s by (elim dvdE) from r have p ∗ 1 = p ∗ (q ∗ s) by (subst (asm) s)(simp add: mult-ac) with hprime-elem pi have q dvd 1 by (subst (asm) mult-cancel-left) auto with h¬q dvd 1 i show ?thesis by contradiction qed

show ?thesis proof (rule prime-elemI ) fix a b assume q dvd (a ∗ b) with hp dvd q i have p dvd (a ∗ b) by (rule dvd-trans) with hprime-elem pi have p dvd a ∨ p dvd b by (rule prime-elem-dvd-multD) with hq dvd pi show q dvd a ∨ q dvd b by (blast intro: dvd-trans) qed (insert assms, auto) qed lemma irreducibleD 0: assumes irreducible a b dvd a shows a dvd b ∨ is-unit b

303 proof − from assms obtain c where c: a = b ∗ c by (elim dvdE) from irreducibleD[OF assms(1 ) this] have is-unit b ∨ is-unit c . thus ?thesis by (auto simp: c mult-unit-dvd-iff ) qed lemma irreducibleI 0: assumes a 6= 0 ¬is-unit a Vb. b dvd a =⇒ a dvd b ∨ is-unit b shows irreducible a proof (rule irreducibleI ) fix b c assume a-eq: a = b ∗ c hence a dvd b ∨ is-unit b by (intro assms) simp-all thus is-unit b ∨ is-unit c proof assume a dvd b hence b ∗ c dvd b ∗ 1 by (simp add: a-eq) moreover from ha 6= 0 i a-eq have b 6= 0 by auto ultimately show ?thesis by (subst (asm) dvd-times-left-cancel-iff ) auto qed blast qed (simp-all add: assms(1 ,2 )) lemma irreducible-altdef : irreducible x ←→ x 6= 0 ∧ ¬is-unit x ∧ (∀ b. b dvd x −→ x dvd b ∨ is-unit b) using irreducibleI 0[of x] irreducibleD 0[of x] irreducible-not-unit[of x] by auto lemma prime-elem-multD: assumes prime-elem (a ∗ b) shows is-unit a ∨ is-unit b proof − from assms have a 6= 0 b 6= 0 by (auto dest!: prime-elem-not-zeroI ) moreover from assms prime-elem-dvd-multD [of a ∗ b] have a ∗ b dvd a ∨ a ∗ b dvd b by auto ultimately show ?thesis using dvd-times-left-cancel-iff [of a b 1 ] dvd-times-right-cancel-iff [of b a 1 ] by auto qed lemma prime-elemD2 : assumes prime-elem p and a dvd p and ¬ is-unit a shows p dvd a proof − from ha dvd pi obtain b where p = a ∗ b .. with hprime-elem pi prime-elem-multD h¬ is-unit a i have is-unit b by auto with hp = a ∗ bi show ?thesis by (auto simp add: mult-unit-dvd-iff ) qed

304 lemma prime-elem-dvd-prod-msetE: assumes prime-elem p assumes dvd: p dvd prod-mset A obtains a where a ∈# A and p dvd a proof − from dvd have ∃ a. a ∈# A ∧ p dvd a proof (induct A) case empty then show ?case using hprime-elem pi by (simp add: prime-elem-not-unit) next case (add a A) then have p dvd a ∗ prod-mset A by simp with hprime-elem pi consider (A) p dvd prod-mset A | (B) p dvd a by (blast dest: prime-elem-dvd-multD) then show ?case proof cases case B then show ?thesis by auto next case A with add.hyps obtain b where b ∈# A p dvd b by auto then show ?thesis by auto qed qed with that show thesis by blast qed context begin private lemma prime-elem-powerD: assumes prime-elem (p ˆ n) shows prime-elem p ∧ n = 1 proof (cases n) case (Suc m) note assms also from Suc have p ˆ n = p ∗ pˆm by simp finally have is-unit p ∨ is-unit (pˆm) by (rule prime-elem-multD) moreover from assms have ¬is-unit p by (simp add: prime-elem-def is-unit-power-iff ) ultimately have is-unit (p ˆ m) by simp with h¬is-unit pi have m = 0 by (simp add: is-unit-power-iff ) with Suc assms show ?thesis by simp qed (insert assms, simp-all) lemma prime-elem-power-iff : prime-elem (p ˆ n) ←→ prime-elem p ∧ n = 1 by (auto dest: prime-elem-powerD) end

305 lemma irreducible-mult-unit-left: is-unit a =⇒ irreducible (a ∗ p) ←→ irreducible p by (auto simp: irreducible-altdef mult.commute[of a] is-unit-mult-iff mult-unit-dvd-iff dvd-mult-unit-iff ) lemma prime-elem-mult-unit-left: is-unit a =⇒ prime-elem (a ∗ p) ←→ prime-elem p by (auto simp: prime-elem-def mult.commute[of a] is-unit-mult-iff mult-unit-dvd-iff ) lemma prime-elem-dvd-cases: assumes pk: p∗k dvd m∗n and p: prime-elem p shows (∃ x. k dvd x∗n ∧ m = p∗x) ∨ (∃ y. k dvd m∗y ∧ n = p∗y) proof − have p dvd m∗n using dvd-mult-left pk by blast then consider p dvd m | p dvd n using p prime-elem-dvd-mult-iff by blast then show ?thesis proof cases case 1 then obtain a where m = p ∗ a by (metis dvd-mult-div-cancel) then have ∃ x. k dvd x ∗ n ∧ m = p ∗ x using p pk by (auto simp: mult.assoc) then show ?thesis .. next case 2 then obtain b where n = p ∗ b by (metis dvd-mult-div-cancel) with p pk have ∃ y. k dvd m∗y ∧ n = p∗y by (metis dvd-mult-right dvd-times-left-cancel-iff mult.left-commute mult-zero-left) then show ?thesis .. qed qed lemma prime-elem-power-dvd-prod: assumes pc: pˆc dvd m∗n and p: prime-elem p shows ∃ a b. a+b = c ∧ pˆa dvd m ∧ pˆb dvd n using pc proof (induct c arbitrary: m n) case 0 show ?case by simp next case (Suc c) consider x where pˆc dvd x∗n m = p∗x | y where pˆc dvd m∗y n = p∗y using prime-elem-dvd-cases [of - pˆc, OF - p] Suc.prems by force then show ?case proof cases case (1 x) with Suc.hyps[of x n] obtain a b where a + b = c ∧ p ˆ a dvd x ∧ p ˆ b dvd n by blast with 1 have Suc a + b = Suc c ∧ p ˆ Suc a dvd m ∧ p ˆ b dvd n by (auto intro: mult-dvd-mono) thus ?thesis by blast next

306 case (2 y) with Suc.hyps[of m y] obtain a b where a + b = c ∧ p ˆ a dvd m ∧ p ˆ b dvd y by blast with 2 have a + Suc b = Suc c ∧ p ˆ a dvd m ∧ p ˆ Suc b dvd n by (auto intro: mult-dvd-mono) with Suc.hyps [of m y] show ∃ a b. a + b = Suc c ∧ p ˆ a dvd m ∧ p ˆ b dvd n by force qed qed lemma prime-elem-power-dvd-cases: assumes p ˆ c dvd m ∗ n and a + b = Suc c and prime-elem p shows p ˆ a dvd m ∨ p ˆ b dvd n proof − from assms obtain r s where r + s = c ∧ p ˆ r dvd m ∧ p ˆ s dvd n by (blast dest: prime-elem-power-dvd-prod) moreover with assms have a ≤ r ∨ b ≤ s by arith ultimately show ?thesis by (auto intro: power-le-dvd) qed lemma prime-elem-not-unit 0 [simp]: ASSUMPTION (prime-elem x) =⇒ ¬is-unit x unfolding ASSUMPTION-def by (rule prime-elem-not-unit) lemma prime-elem-dvd-power-iff : assumes prime-elem p shows p dvd a ˆ n ←→ p dvd a ∧ n > 0 using assms by (induct n)(auto dest: prime-elem-not-unit prime-elem-dvd-multD) lemma prime-power-dvd-multD: assumes prime-elem p assumes p ˆ n dvd a ∗ b and n > 0 and ¬ p dvd a shows p ˆ n dvd b using hp ˆ n dvd a ∗ bi and hn > 0 i proof (induct n arbitrary: b) case 0 then show ?case by simp next case (Suc n) show ?case proof (cases n = 0 ) case True with Suc hprime-elem pi h¬ p dvd a i show ?thesis by (simp add: prime-elem-dvd-mult-iff ) next case False then have n > 0 by simp from hprime-elem pi have p 6= 0 by auto from Suc.prems have ∗: p ∗ p ˆ n dvd a ∗ b by simp

307 then have p dvd a ∗ b by (rule dvd-mult-left) with Suc hprime-elem pi h¬ p dvd a i have p dvd b by (simp add: prime-elem-dvd-mult-iff ) moreover define c where c = b div p ultimately have b: b = p ∗ c by simp with ∗ have p ∗ p ˆ n dvd p ∗ (a ∗ c) by (simp add: ac-simps) with hp 6= 0 i have p ˆ n dvd a ∗ c by simp with Suc.hyps hn > 0 i have p ˆ n dvd c by blast with hp 6= 0 i show ?thesis by (simp add: b) qed qed end

46.2 Generalized primes: normalized prime elements context normalization-semidom begin lemma irreducible-normalized-divisors: assumes irreducible x y dvd x normalize y = y shows y = 1 ∨ y = normalize x proof − from assms have is-unit y ∨ x dvd y by (auto simp: irreducible-altdef ) thus ?thesis proof (elim disjE) assume is-unit y hence normalize y = 1 by (simp add: is-unit-normalize) with assms show ?thesis by simp next assume x dvd y with hy dvd x i have normalize y = normalize x by (rule associatedI ) with assms show ?thesis by simp qed qed lemma irreducible-normalize-iff [simp]: irreducible (normalize x) = irreducible x using irreducible-mult-unit-left[of 1 div unit-factor x x] by (cases x = 0 )(simp-all add: unit-div-commute) lemma prime-elem-normalize-iff [simp]: prime-elem (normalize x) = prime-elem x using prime-elem-mult-unit-left[of 1 div unit-factor x x] by (cases x = 0 )(simp-all add: unit-div-commute)

308 lemma prime-elem-associated: assumes prime-elem p and prime-elem q and q dvd p shows normalize q = normalize p using hq dvd pi proof (rule associatedI ) from hprime-elem q i have ¬ is-unit q by (auto simp add: prime-elem-not-unit) with hprime-elem pi hq dvd pi show p dvd q by (blast intro: prime-elemD2 ) qed definition prime :: 0a ⇒ bool where prime p ←→ prime-elem p ∧ normalize p = p lemma not-prime-0 [simp]: ¬prime 0 by (simp add: prime-def ) lemma not-prime-unit: is-unit x =⇒ ¬prime x using prime-elem-not-unit[of x] by (auto simp add: prime-def ) lemma not-prime-1 [simp]: ¬prime 1 by (simp add: not-prime-unit) lemma primeI : prime-elem x =⇒ normalize x = x =⇒ prime x by (simp add: prime-def ) lemma prime-imp-prime-elem [dest]: prime p =⇒ prime-elem p by (simp add: prime-def ) lemma normalize-prime: prime p =⇒ normalize p = p by (simp add: prime-def ) lemma prime-normalize-iff [simp]: prime (normalize p) ←→ prime-elem p by (auto simp add: prime-def ) lemma prime-power-iff : prime (p ˆ n) ←→ prime p ∧ n = 1 by (auto simp: prime-def prime-elem-power-iff ) lemma prime-imp-nonzero [simp]: ASSUMPTION (prime x) =⇒ x 6= 0 unfolding ASSUMPTION-def prime-def by auto lemma prime-imp-not-one [simp]: ASSUMPTION (prime x) =⇒ x 6= 1 unfolding ASSUMPTION-def by auto lemma prime-not-unit 0 [simp]: ASSUMPTION (prime x) =⇒ ¬is-unit x unfolding ASSUMPTION-def prime-def by auto

309 lemma prime-normalize 0 [simp]: ASSUMPTION (prime x) =⇒ normalize x = x unfolding ASSUMPTION-def prime-def by simp lemma unit-factor-prime: prime x =⇒ unit-factor x = 1 using unit-factor-normalize[of x] unfolding prime-def by auto lemma unit-factor-prime 0 [simp]: ASSUMPTION (prime x) =⇒ unit-factor x = 1 unfolding ASSUMPTION-def by (rule unit-factor-prime) lemma prime-imp-prime-elem 0 [simp]: ASSUMPTION (prime x) =⇒ prime-elem x by (simp add: prime-def ASSUMPTION-def ) lemma prime-dvd-multD: prime p =⇒ p dvd a ∗ b =⇒ p dvd a ∨ p dvd b by (intro prime-elem-dvd-multD) simp-all lemma prime-dvd-mult-iff [simp]: prime p =⇒ p dvd a ∗ b ←→ p dvd a ∨ p dvd b by (auto dest: prime-dvd-multD) lemma prime-dvd-power: prime p =⇒ p dvd x ˆ n =⇒ p dvd x by (auto dest!: prime-elem-dvd-power simp: prime-def ) lemma prime-dvd-power-iff : prime p =⇒ n > 0 =⇒ p dvd x ˆ n ←→ p dvd x by (subst prime-elem-dvd-power-iff ) simp-all lemma prime-dvd-prod-mset-iff : prime p =⇒ p dvd prod-mset A ←→ (∃ x. x ∈# A ∧ p dvd x) by (induction A)(simp-all add: prime-elem-dvd-mult-iff prime-imp-prime-elem, blast+) lemma primes-dvd-imp-eq: assumes prime p prime q p dvd q shows p = q proof − from assms have irreducible q by (simp add: prime-elem-imp-irreducible prime-def ) 0 from irreducibleD [OF this hp dvd q i] assms have q dvd p by simp with hp dvd q i have normalize p = normalize q by (rule associatedI ) with assms show p = q by simp qed lemma prime-dvd-prod-mset-primes-iff : assumes prime p Vq. q ∈# A =⇒ prime q shows p dvd prod-mset A ←→ p ∈# A proof − from assms(1 ) have p dvd prod-mset A ←→ (∃ x. x ∈# A ∧ p dvd x) by (rule

310 prime-dvd-prod-mset-iff ) also from assms have ... ←→ p ∈# A by (auto dest: primes-dvd-imp-eq) finally show ?thesis . qed lemma prod-mset-primes-dvd-imp-subset: assumes prod-mset A dvd prod-mset B Vp. p ∈# A =⇒ prime p Vp. p ∈# B =⇒ prime p shows A ⊆# B using assms proof (induction A arbitrary: B) case empty thus ?case by simp next case (add p A B) hence p: prime p by simp define B 0 where B 0 = B − {#p#} from add.prems have p dvd prod-mset B by (simp add: dvd-mult-left) with add.prems have p ∈# B by (subst (asm)(2 ) prime-dvd-prod-mset-primes-iff ) simp-all hence B: B = B 0 + {#p#} by (simp add: B 0-def ) from add.prems p have A ⊆# B 0 by (intro add.IH )(simp-all add: B) thus ?case by (simp add: B) qed lemma normalize-prod-mset-primes: (Vp. p ∈# A =⇒ prime p) =⇒ normalize (prod-mset A) = prod-mset A proof (induction A) case (add p A) hence prime p by simp hence normalize p = p by simp with add show ?case by (simp add: normalize-mult) qed simp-all lemma prod-mset-dvd-prod-mset-primes-iff : assumes Vx. x ∈# A =⇒ prime x Vx. x ∈# B =⇒ prime x shows prod-mset A dvd prod-mset B ←→ A ⊆# B using assms by (auto intro: prod-mset-subset-imp-dvd prod-mset-primes-dvd-imp-subset) lemma is-unit-prod-mset-primes-iff : assumes Vx. x ∈# A =⇒ prime x shows is-unit (prod-mset A) ←→ A = {#} by (auto simp add: is-unit-prod-mset-iff ) (meson all-not-in-conv assms not-prime-unit set-mset-eq-empty-iff ) lemma prod-mset-primes-irreducible-imp-prime: assumes irred: irreducible (prod-mset A) assumes A: Vx. x ∈# A =⇒ prime x assumes B: Vx. x ∈# B =⇒ prime x

311 assumes C : Vx. x ∈# C =⇒ prime x assumes dvd: prod-mset A dvd prod-mset B ∗ prod-mset C shows prod-mset A dvd prod-mset B ∨ prod-mset A dvd prod-mset C proof − from dvd have prod-mset A dvd prod-mset (B + C ) by simp with ABC have subset: A ⊆# B + C by (subst (asm) prod-mset-dvd-prod-mset-primes-iff ) auto define A1 and A2 where A1 = A ∩# B and A2 = A − A1 have A = A1 + A2 unfolding A1-def A2-def by (rule sym, intro subset-mset.add-diff-inverse) simp-all from subset have A1 ⊆# B A2 ⊆# C by (auto simp: A1-def A2-def Multiset.subset-eq-diff-conv Multiset.union-commute) from hA = A1 + A2 i have prod-mset A = prod-mset A1 ∗ prod-mset A2 by simp from irred and this have is-unit (prod-mset A1 ) ∨ is-unit (prod-mset A2 ) by (rule irreducibleD) with A have A1 = {#} ∨ A2 = {#} unfolding A1-def A2-def by (subst (asm)(1 2 ) is-unit-prod-mset-primes-iff )(auto dest: Multiset.in-diffD) with dvd hA = A1 + A2 i hA1 ⊆# B i hA2 ⊆# C i show ?thesis by (auto intro: prod-mset-subset-imp-dvd) qed lemma prod-mset-primes-finite-divisor-powers: assumes A: Vx. x ∈# A =⇒ prime x assumes B: Vx. x ∈# B =⇒ prime x assumes A 6= {#} shows finite {n. prod-mset A ˆ n dvd prod-mset B} proof − from hA 6= {#}i obtain x where x: x ∈# A by blast define m where m = count B x have {n. prod-mset A ˆ n dvd prod-mset B} ⊆ {..m} proof safe fix n assume dvd: prod-mset A ˆ n dvd prod-mset B from x have x ˆ n dvd prod-mset A ˆ n by (intro dvd-power-same dvd-prod-mset) also note dvd also have x ˆ n = prod-mset (replicate-mset n x) by simp finally have replicate-mset n x ⊆# B by (rule prod-mset-primes-dvd-imp-subset)(insert A B x, simp-all split: if-splits) thus n ≤ m by (simp add: count-le-replicate-mset-subset-eq m-def ) qed moreover have finite {..m} by simp ultimately show ?thesis by (rule finite-subset) qed end

312 46.3 In a semiring with GCD, each irreducible element is a prime elements context semiring-gcd begin lemma irreducible-imp-prime-elem-gcd: assumes irreducible x shows prime-elem x proof (rule prime-elemI ) fix a b assume x dvd a ∗ b from dvd-productE[OF this] obtain y z where yz: x = y ∗ z y dvd a z dvd b . from hirreducible x i and hx = y ∗ z i have is-unit y ∨ is-unit z by (rule irre- ducibleD) with yz show x dvd a ∨ x dvd b by (auto simp: mult-unit-dvd-iff mult-unit-dvd-iff 0) qed (insert assms, auto simp: irreducible-not-unit) lemma prime-elem-imp-coprime: assumes prime-elem p ¬p dvd n shows coprime p n proof (rule coprimeI ) fix d assume d dvd p d dvd n show is-unit d proof (rule ccontr) assume ¬is-unit d from hprime-elem pi and hd dvd pi and this have p dvd d by (rule prime-elemD2 ) from this and hd dvd n i have p dvd n by (rule dvd-trans) with h¬p dvd n i show False by contradiction qed qed lemma prime-imp-coprime: assumes prime p ¬p dvd n shows coprime p n using assms by (simp add: prime-elem-imp-coprime) lemma prime-elem-imp-power-coprime: prime-elem p =⇒ ¬p dvd a =⇒ coprime a (p ˆ m) by (auto intro!: coprime-exp dest: prime-elem-imp-coprime simp: gcd.commute) lemma prime-imp-power-coprime: prime p =⇒ ¬p dvd a =⇒ coprime a (p ˆ m) by (simp add: prime-elem-imp-power-coprime) lemma prime-elem-divprod-pow: assumes p: prime-elem p and ab: coprime a b and pab: pˆn dvd a ∗ b shows pˆn dvd a ∨ pˆn dvd b using assms

313 proof − from ab p have ¬p dvd a ∨ ¬p dvd b by (auto simp: coprime prime-elem-def ) with p have coprime (pˆn) a ∨ coprime (pˆn) b by (auto intro: prime-elem-imp-coprime coprime-exp-left) with pab show ?thesis by (auto intro: coprime-dvd-mult simp: mult-ac) qed lemma primes-coprime: prime p =⇒ prime q =⇒ p 6= q =⇒ coprime p q using prime-imp-coprime primes-dvd-imp-eq by blast end

46.4 Factorial semirings: algebraic structures with unique prime factorizations class factorial-semiring = normalization-semidom + assumes prime-factorization-exists: x 6= 0 =⇒ ∃ A. (∀ x. x ∈# A −→ prime-elem x) ∧ prod-mset A = normalize x

Alternative characterization lemma (in normalization-semidom) factorial-semiring-altI-aux: assumes finite-divisors: Vx. x 6= 0 =⇒ finite {y. y dvd x ∧ normalize y = y} assumes irreducible-imp-prime-elem: Vx. irreducible x =⇒ prime-elem x assumes x 6= 0 shows ∃ A. (∀ x. x ∈# A −→ prime-elem x) ∧ prod-mset A = normalize x using hx 6= 0 i proof (induction card {b. b dvd x ∧ normalize b = b} arbitrary: x rule: less-induct) case (less a) let ?fctrs = λa. {b. b dvd a ∧ normalize b = b} show ?case proof (cases is-unit a) case True thus ?thesis by (intro exI [of - {#}]) (auto simp: is-unit-normalize) next case False show ?thesis proof (cases ∃ b. b dvd a ∧ ¬is-unit b ∧ ¬a dvd b) case False with h¬is-unit a i less.prems have irreducible a by (auto simp: irreducible-altdef ) hence prime-elem a by (rule irreducible-imp-prime-elem) thus ?thesis by (intro exI [of - {#normalize a#}]) auto next case True then guess b by (elim exE conjE) note b = this

from b have ?fctrs b ⊆ ?fctrs a by (auto intro: dvd-trans) moreover from b have normalize a ∈/ ?fctrs b normalize a ∈ ?fctrs a by

314 simp-all hence ?fctrs b 6= ?fctrs a by blast ultimately have ?fctrs b ⊂ ?fctrs a by (subst subset-not-subset-eq) blast with finite-divisors[OF ha 6= 0 i] have card (?fctrs b) < card (?fctrs a) by (rule psubset-card-mono) moreover from ha 6= 0 i b have b 6= 0 by auto ultimately have ∃ A. (∀ x. x ∈# A −→ prime-elem x) ∧ prod-mset A = normalize b by (intro less) auto then guess A .. note A = this

define c where c = a div b from b have c: a = b ∗ c by (simp add: c-def ) from less.prems c have c 6= 0 by auto from b c have ?fctrs c ⊆ ?fctrs a by (auto intro: dvd-trans) moreover have normalize a ∈/ ?fctrs c proof safe assume normalize a dvd c hence b ∗ c dvd 1 ∗ c by (simp add: c) hence b dvd 1 by (subst (asm) dvd-times-right-cancel-iff ) fact+ with b show False by simp qed with hnormalize a ∈ ?fctrs a i have ?fctrs a 6= ?fctrs c by blast ultimately have ?fctrs c ⊂ ?fctrs a by (subst subset-not-subset-eq) blast with finite-divisors[OF ha 6= 0 i] have card (?fctrs c) < card (?fctrs a) by (rule psubset-card-mono) with hc 6= 0 i have ∃ A. (∀ x. x ∈# A −→ prime-elem x) ∧ prod-mset A = normalize c by (intro less) auto then guess B .. note B = this

from AB show ?thesis by (intro exI [of - A + B]) (auto simp: c normalize-mult) qed qed qed lemma factorial-semiring-altI : assumes finite-divisors: Vx:: 0a. x 6= 0 =⇒ finite {y. y dvd x ∧ normalize y = y} assumes irreducible-imp-prime: Vx:: 0a. irreducible x =⇒ prime-elem x shows OFCLASS( 0a :: normalization-semidom, factorial-semiring-class) by intro-classes (rule factorial-semiring-altI-aux[OF assms])

Properties context factorial-semiring begin lemma prime-factorization-exists 0: assumes x 6= 0

315 obtains A where Vx. x ∈# A =⇒ prime x prod-mset A = normalize x proof − from prime-factorization-exists[OF assms] obtain A where A: Vx. x ∈# A =⇒ prime-elem x prod-mset A = normalize x by blast define A 0 where A 0 = image-mset normalize A have prod-mset A 0 = normalize (prod-mset A) by (simp add: A 0-def normalize-prod-mset) also note A(2 ) finally have prod-mset A 0 = normalize x by simp moreover from A(1 ) have ∀ x. x ∈# A 0 −→ prime x by (auto simp: prime-def A 0-def ) ultimately show ?thesis by (intro that[of A 0]) blast qed lemma irreducible-imp-prime-elem: assumes irreducible x shows prime-elem x proof (rule prime-elemI ) fix a b assume dvd: x dvd a ∗ b from assms have x 6= 0 by auto show x dvd a ∨ x dvd b proof (cases a = 0 ∨ b = 0 ) case False hence a 6= 0 b 6= 0 by blast+ note nz = hx 6= 0 i this from nz[THEN prime-factorization-exists 0] guess ABC . note ABC = this from assms ABC have irreducible (prod-mset A) by simp from dvd prod-mset-primes-irreducible-imp-prime[of A B C , OF this ABC (1 ,3 ,5 )] ABC (2 ,4 ,6 ) show ?thesis by (simp add: normalize-mult [symmetric]) qed auto qed (insert assms, simp-all add: irreducible-def ) lemma finite-divisor-powers: assumes y 6= 0 ¬is-unit x shows finite {n. x ˆ n dvd y} proof (cases x = 0 ) case True with assms have {n. x ˆ n dvd y} = {0 } by (auto simp: power-0-left) thus ?thesis by simp next case False note nz = this hy 6= 0 i from nz[THEN prime-factorization-exists 0] guess AB . note AB = this from AB assms have A 6= {#} by (auto simp: normalize-1-iff ) from AB(2 ,4 ) prod-mset-primes-finite-divisor-powers [of A B, OF AB(1 ,3 ) this] show ?thesis by (simp add: normalize-power [symmetric]) qed

316 lemma finite-prime-divisors: assumes x 6= 0 shows finite {p. prime p ∧ p dvd x} proof − from prime-factorization-exists 0[OF assms] guess A . note A = this have {p. prime p ∧ p dvd x} ⊆ set-mset A proof safe fix p assume p: prime p and dvd: p dvd x from dvd have p dvd normalize x by simp also from A have normalize x = prod-mset A by simp finally show p ∈# A using p A by (subst (asm) prime-dvd-prod-mset-primes-iff ) qed moreover have finite (set-mset A) by simp ultimately show ?thesis by (rule finite-subset) qed lemma prime-elem-iff-irreducible: prime-elem x ←→ irreducible x by (blast intro: irreducible-imp-prime-elem prime-elem-imp-irreducible) lemma prime-divisor-exists: assumes a 6= 0 ¬is-unit a shows ∃ b. b dvd a ∧ prime b proof − from prime-factorization-exists 0[OF assms(1 )] guess A . note A = this moreover from A and assms have A 6= {#} by auto then obtain x where x ∈# A by blast with A(1 ) have ∗: x dvd prod-mset A prime x by (auto simp: dvd-prod-mset) with A have x dvd a by simp with ∗ show ?thesis by blast qed lemma prime-divisors-induct [case-names zero unit factor]: assumes P 0 Vx. is-unit x =⇒ P x Vp x. prime p =⇒ P x =⇒ P (p ∗ x) shows P x proof (cases x = 0 ) case False from prime-factorization-exists 0[OF this] guess A . note A = this from A(1 ) have P (unit-factor x ∗ prod-mset A) proof (induction A) case (add p A) from add.prems have prime p by simp moreover from add.prems have P (unit-factor x ∗ prod-mset A) by (intro add.IH ) simp-all ultimately have P (p ∗ (unit-factor x ∗ prod-mset A)) by (rule assms(3 )) thus ?case by (simp add: mult-ac) qed (simp-all add: assms False) with A show ?thesis by simp qed (simp-all add: assms(1 ))

317 lemma no-prime-divisors-imp-unit: assumes a 6= 0 Vb. b dvd a =⇒ normalize b = b =⇒ ¬ prime-elem b shows is-unit a proof (rule ccontr) assume ¬is-unit a from prime-divisor-exists[OF assms(1 ) this] guess b by (elim exE conjE) with assms(2 )[of b] show False by (simp add: prime-def ) qed lemma prime-divisorE: assumes a 6= 0 and ¬ is-unit a obtains p where prime p and p dvd a using assms no-prime-divisors-imp-unit unfolding prime-def by blast definition multiplicity :: 0a ⇒ 0a ⇒ nat where multiplicity p x = (if finite {n. p ˆ n dvd x} then Max {n. p ˆ n dvd x} else 0 ) lemma multiplicity-dvd: p ˆ multiplicity p x dvd x proof (cases finite {n. p ˆ n dvd x}) case True hence multiplicity p x = Max {n. p ˆ n dvd x} by (simp add: multiplicity-def ) also have ... ∈ {n. p ˆ n dvd x} by (rule Max-in)(auto intro!: True exI [of - 0 ::nat]) finally show ?thesis by simp qed (simp add: multiplicity-def ) lemma multiplicity-dvd 0: n ≤ multiplicity p x =⇒ p ˆ n dvd x by (rule dvd-trans[OF le-imp-power-dvd multiplicity-dvd]) context fixes x p :: 0a assumes xp: x 6= 0 ¬is-unit p begin lemma multiplicity-eq-Max: multiplicity p x = Max {n. p ˆ n dvd x} using finite-divisor-powers[OF xp] by (simp add: multiplicity-def ) lemma multiplicity-geI : assumes p ˆ n dvd x shows multiplicity p x ≥ n proof − from assms have n ≤ Max {n. p ˆ n dvd x} by (intro Max-ge finite-divisor-powers xp) simp-all thus ?thesis by (subst multiplicity-eq-Max) qed lemma multiplicity-lessI : assumes ¬p ˆ n dvd x

318 shows multiplicity p x < n proof (rule ccontr) assume ¬(n > multiplicity p x) hence p ˆ n dvd x by (intro multiplicity-dvd 0) simp with assms show False by contradiction qed lemma power-dvd-iff-le-multiplicity: p ˆ n dvd x ←→ n ≤ multiplicity p x using multiplicity-geI [of n] multiplicity-lessI [of n] by (cases p ˆ n dvd x) auto lemma multiplicity-eq-zero-iff : shows multiplicity p x = 0 ←→ ¬p dvd x using power-dvd-iff-le-multiplicity[of 1 ] by auto lemma multiplicity-gt-zero-iff : shows multiplicity p x > 0 ←→ p dvd x using power-dvd-iff-le-multiplicity[of 1 ] by auto lemma multiplicity-decompose: ¬p dvd (x div p ˆ multiplicity p x) proof assume ∗: p dvd x div p ˆ multiplicity p x have x = x div p ˆ multiplicity p x ∗ (p ˆ multiplicity p x) using multiplicity-dvd[of p x] by simp also from ∗ have x div p ˆ multiplicity p x = (x div p ˆ multiplicity p x div p) ∗ p by simp also have x div p ˆ multiplicity p x div p ∗ p ∗ p ˆ multiplicity p x = x div p ˆ multiplicity p x div p ∗ p ˆ Suc (multiplicity p x) by (simp add: mult-assoc) also have p ˆ Suc (multiplicity p x) dvd ... by (rule dvd-triv-right) finally show False by (subst (asm) power-dvd-iff-le-multiplicity) simp qed lemma multiplicity-decompose 0: obtains y where x = p ˆ multiplicity p x ∗ y ¬p dvd y using that[of x div p ˆ multiplicity p x] by (simp add: multiplicity-decompose multiplicity-dvd) end lemma multiplicity-zero [simp]: multiplicity p 0 = 0 by (simp add: multiplicity-def ) lemma prime-elem-multiplicity-eq-zero-iff : prime-elem p =⇒ x 6= 0 =⇒ multiplicity p x = 0 ←→ ¬p dvd x by (rule multiplicity-eq-zero-iff ) simp-all lemma prime-multiplicity-other:

319 assumes prime p prime q p 6= q shows multiplicity p q = 0 using assms by (subst prime-elem-multiplicity-eq-zero-iff )(auto dest: primes-dvd-imp-eq) lemma prime-multiplicity-gt-zero-iff : prime-elem p =⇒ x 6= 0 =⇒ multiplicity p x > 0 ←→ p dvd x by (rule multiplicity-gt-zero-iff ) simp-all lemma multiplicity-unit-left: is-unit p =⇒ multiplicity p x = 0 by (simp add: multiplicity-def is-unit-power-iff unit-imp-dvd) lemma multiplicity-unit-right: assumes is-unit x shows multiplicity p x = 0 proof (cases is-unit p ∨ x = 0 ) case False with multiplicity-lessI [of x p 1 ] this assms show ?thesis by (auto dest: dvd-unit-imp-unit) qed (auto simp: multiplicity-unit-left) lemma multiplicity-one [simp]: multiplicity p 1 = 0 by (rule multiplicity-unit-right) simp-all lemma multiplicity-eqI : assumes p ˆ n dvd x ¬p ˆ Suc n dvd x shows multiplicity p x = n proof − consider x = 0 | is-unit p | x 6= 0 ¬is-unit p by blast thus ?thesis proof cases assume xp: x 6= 0 ¬is-unit p from xp assms(1 ) have multiplicity p x ≥ n by (intro multiplicity-geI ) moreover from assms(2 ) xp have multiplicity p x < Suc n by (intro multiplicity-lessI ) ultimately show ?thesis by simp next assume is-unit p hence is-unit (p ˆ Suc n) by (simp add: is-unit-power-iff del: power-Suc) hence p ˆ Suc n dvd x by (rule unit-imp-dvd) with h¬p ˆ Suc n dvd x i show ?thesis by contradiction qed (insert assms, simp-all) qed context fixes x p :: 0a assumes xp: x 6= 0 ¬is-unit p begin

320 lemma multiplicity-times-same: assumes p 6= 0 shows multiplicity p (p ∗ x) = Suc (multiplicity p x) proof (rule multiplicity-eqI ) show p ˆ Suc (multiplicity p x) dvd p ∗ x by (auto intro!: mult-dvd-mono multiplicity-dvd) from xp assms show ¬ p ˆ Suc (Suc (multiplicity p x)) dvd p ∗ x using power-dvd-iff-le-multiplicity[OF xp, of Suc (multiplicity p x)] by simp qed end lemma multiplicity-same-power 0: multiplicity p (p ˆ n) = (if p = 0 ∨ is-unit p then 0 else n) proof − consider p = 0 | is-unit p |p 6= 0 ¬is-unit p by blast thus ?thesis proof cases assume p 6= 0 ¬is-unit p thus ?thesis by (induction n)(simp-all add: multiplicity-times-same) qed (simp-all add: power-0-left multiplicity-unit-left) qed lemma multiplicity-same-power: p 6= 0 =⇒ ¬is-unit p =⇒ multiplicity p (p ˆ n) = n by (simp add: multiplicity-same-power 0) lemma multiplicity-prime-elem-times-other: assumes prime-elem p ¬p dvd q shows multiplicity p (q ∗ x) = multiplicity p x proof (cases x = 0 ) case False show ?thesis proof (rule multiplicity-eqI ) have 1 ∗ p ˆ multiplicity p x dvd q ∗ x by (intro mult-dvd-mono multiplicity-dvd) simp-all thus p ˆ multiplicity p x dvd q ∗ x by simp next define n where n = multiplicity p x from assms have ¬is-unit p by simp from multiplicity-decompose 0[OF False this] guess y . note y = this [folded n-def ] from y have p ˆ Suc n dvd q ∗ x ←→ p ˆ n ∗ p dvd p ˆ n ∗ (q ∗ y) by (simp add: mult-ac) also from assms have ... ←→ p dvd q ∗ y by simp also have ... ←→ p dvd q ∨ p dvd y by (rule prime-elem-dvd-mult-iff ) fact+ also from assms y have ... ←→ False by simp finally show ¬(p ˆ Suc n dvd q ∗ x) by blast qed

321 qed simp-all lemma multiplicity-self : assumes p 6= 0 ¬is-unit p shows multiplicity p p = 1 proof − from assms have multiplicity p p = Max {n. p ˆ n dvd p} by (simp add: multiplicity-eq-Max) also from assms have p ˆ n dvd p ←→ n ≤ 1 for n using dvd-power-iff [of p n 1 ] by auto hence {n. p ˆ n dvd p} = {..1 } by auto also have ... = {0 ,1 } by auto finally show ?thesis by simp qed lemma multiplicity-times-unit-left: assumes is-unit c shows multiplicity (c ∗ p) x = multiplicity p x proof − from assms have {n. (c ∗ p) ˆ n dvd x} = {n. p ˆ n dvd x} by (subst mult.commute)(simp add: mult-unit-dvd-iff power-mult-distrib is-unit-power-iff ) thus ?thesis by (simp add: multiplicity-def ) qed lemma multiplicity-times-unit-right: assumes is-unit c shows multiplicity p (c ∗ x) = multiplicity p x proof − from assms have {n. p ˆ n dvd c ∗ x} = {n. p ˆ n dvd x} by (subst mult.commute)(simp add: dvd-mult-unit-iff ) thus ?thesis by (simp add: multiplicity-def ) qed lemma multiplicity-normalize-left [simp]: multiplicity (normalize p) x = multiplicity p x proof (cases p = 0 ) case [simp]: False have normalize p = (1 div unit-factor p) ∗ p by (simp add: unit-div-commute is-unit-unit-factor) also have multiplicity ... x = multiplicity p x by (rule multiplicity-times-unit-left)(simp add: is-unit-unit-factor) finally show ?thesis . qed simp-all lemma multiplicity-normalize-right [simp]: multiplicity p (normalize x) = multiplicity p x proof (cases x = 0 ) case [simp]: False have normalize x = (1 div unit-factor x) ∗ x

322 by (simp add: unit-div-commute is-unit-unit-factor) also have multiplicity p ... = multiplicity p x by (rule multiplicity-times-unit-right)(simp add: is-unit-unit-factor) finally show ?thesis . qed simp-all lemma multiplicity-prime [simp]: prime-elem p =⇒ multiplicity p p = 1 by (rule multiplicity-self ) auto lemma multiplicity-prime-power [simp]: prime-elem p =⇒ multiplicity p (p ˆ n) = n by (subst multiplicity-same-power 0) auto lift-definition prime-factorization :: 0a ⇒ 0a multiset is λx p. if prime p then multiplicity p x else 0 unfolding multiset-def proof clarify fix x :: 0a show finite {p. 0 < (if prime p then multiplicity p x else 0 )} (is finite ?A) proof (cases x = 0 ) case False from False have ?A ⊆ {p. prime p ∧ p dvd x} by (auto simp: multiplicity-gt-zero-iff ) moreover from False have finite {p. prime p ∧ p dvd x} by (rule finite-prime-divisors) ultimately show ?thesis by (rule finite-subset) qed simp-all qed abbreviation prime-factors :: 0a ⇒ 0a set where prime-factors a ≡ set-mset (prime-factorization a) lemma count-prime-factorization-nonprime: ¬prime p =⇒ count (prime-factorization x) p = 0 by transfer simp lemma count-prime-factorization-prime: prime p =⇒ count (prime-factorization x) p = multiplicity p x by transfer simp lemma count-prime-factorization: count (prime-factorization x) p = (if prime p then multiplicity p x else 0 ) by transfer simp lemma dvd-imp-multiplicity-le: assumes a dvd b b 6= 0 shows multiplicity p a ≤ multiplicity p b proof (cases is-unit p) case False

323 with assms show ?thesis by (intro multiplicity-geI )(auto intro: dvd-trans[OF multiplicity-dvd 0 assms(1 )]) qed (insert assms, auto simp: multiplicity-unit-left) lemma prime-factorization-0 [simp]: prime-factorization 0 = {#} by (simp add: multiset-eq-iff count-prime-factorization) lemma prime-factorization-empty-iff : prime-factorization x = {#} ←→ x = 0 ∨ is-unit x proof assume ∗: prime-factorization x = {#} { assume x: x 6= 0 ¬is-unit x { fix p assume p: prime p have count (prime-factorization x) p = 0 by (simp add: ∗) also from p have count (prime-factorization x) p = multiplicity p x by (rule count-prime-factorization-prime) also from x p have ... = 0 ←→ ¬p dvd x by (simp add: multiplicity-eq-zero-iff ) finally have ¬p dvd x . } with prime-divisor-exists[OF x] have False by blast } thus x = 0 ∨ is-unit x by blast next assume x = 0 ∨ is-unit x thus prime-factorization x = {#} proof assume x: is-unit x { fix p assume p: prime p from p x have multiplicity p x = 0 by (subst multiplicity-eq-zero-iff ) (auto simp: multiplicity-eq-zero-iff dest: unit-imp-no-prime-divisors) } thus ?thesis by (simp add: multiset-eq-iff count-prime-factorization) qed simp-all qed lemma prime-factorization-unit: assumes is-unit x shows prime-factorization x = {#} proof (rule multiset-eqI ) fix p :: 0a show count (prime-factorization x) p = count {#} p proof (cases prime p) case True with assms have multiplicity p x = 0 by (subst multiplicity-eq-zero-iff )

324 (auto simp: multiplicity-eq-zero-iff dest: unit-imp-no-prime-divisors) with True show ?thesis by (simp add: count-prime-factorization-prime) qed (simp-all add: count-prime-factorization-nonprime) qed lemma prime-factorization-1 [simp]: prime-factorization 1 = {#} by (simp add: prime-factorization-unit) lemma prime-factorization-times-prime: assumes x 6= 0 prime p shows prime-factorization (p ∗ x) = {#p#} + prime-factorization x proof (rule multiset-eqI ) fix q :: 0a consider ¬prime q | p = q | prime q p 6= q by blast thus count (prime-factorization (p ∗ x)) q = count ({#p#} + prime-factorization x) q proof cases assume q: prime q p 6= q with assms primes-dvd-imp-eq[of q p] have ¬q dvd p by auto with q assms show ?thesis by (simp add: multiplicity-prime-elem-times-other count-prime-factorization) qed (insert assms, auto simp: count-prime-factorization multiplicity-times-same) qed lemma prod-mset-prime-factorization: assumes x 6= 0 shows prod-mset (prime-factorization x) = normalize x using assms by (induction x rule: prime-divisors-induct) (simp-all add: prime-factorization-unit prime-factorization-times-prime is-unit-normalize normalize-mult) lemma in-prime-factors-iff : p ∈ prime-factors x ←→ x 6= 0 ∧ p dvd x ∧ prime p proof − have p ∈ prime-factors x ←→ count (prime-factorization x) p > 0 by simp also have ... ←→ x 6= 0 ∧ p dvd x ∧ prime p by (subst count-prime-factorization, cases x = 0 ) (auto simp: multiplicity-eq-zero-iff multiplicity-gt-zero-iff ) finally show ?thesis . qed lemma in-prime-factors-imp-prime [intro]: p ∈ prime-factors x =⇒ prime p by (simp add: in-prime-factors-iff ) lemma in-prime-factors-imp-dvd [dest]: p ∈ prime-factors x =⇒ p dvd x by (simp add: in-prime-factors-iff )

325 lemma prime-factorsI : x 6= 0 =⇒ prime p =⇒ p dvd x =⇒ p ∈ prime-factors x by (auto simp: in-prime-factors-iff ) lemma prime-factors-dvd: x 6= 0 =⇒ prime-factors x = {p. prime p ∧ p dvd x} by (auto intro: prime-factorsI ) lemma prime-factors-multiplicity: prime-factors n = {p. prime p ∧ multiplicity p n > 0 } by (cases n = 0 )(auto simp add: prime-factors-dvd prime-multiplicity-gt-zero-iff ) lemma prime-factorization-prime: assumes prime p shows prime-factorization p = {#p#} proof (rule multiset-eqI ) fix q :: 0a consider ¬prime q | q = p | prime q q 6= p by blast thus count (prime-factorization p) q = count {#p#} q by cases (insert assms, auto dest: primes-dvd-imp-eq simp: count-prime-factorization multiplicity-self multiplicity-eq-zero-iff ) qed lemma prime-factorization-prod-mset-primes: assumes Vp. p ∈# A =⇒ prime p shows prime-factorization (prod-mset A) = A using assms proof (induction A) case (add p A) from add.prems[of 0 ] have 0 ∈/# A by auto hence prod-mset A 6= 0 by auto with add show ?case by (simp-all add: mult-ac prime-factorization-times-prime Multiset.union-commute) qed simp-all lemma prime-factorization-cong: normalize x = normalize y =⇒ prime-factorization x = prime-factorization y by (simp add: multiset-eq-iff count-prime-factorization multiplicity-normalize-right [of - x, symmetric] multiplicity-normalize-right [of - y, symmetric] del: multiplicity-normalize-right) lemma prime-factorization-unique: assumes x 6= 0 y 6= 0 shows prime-factorization x = prime-factorization y ←→ normalize x = nor- malize y proof assume prime-factorization x = prime-factorization y

326 hence prod-mset (prime-factorization x) = prod-mset (prime-factorization y) by simp with assms show normalize x = normalize y by (simp add: prod-mset-prime-factorization) qed (rule prime-factorization-cong) lemma prime-factorization-mult: assumes x 6= 0 y 6= 0 shows prime-factorization (x ∗ y) = prime-factorization x + prime-factorization y proof − have prime-factorization (prod-mset (prime-factorization (x ∗ y))) = prime-factorization (prod-mset (prime-factorization x + prime-factorization y)) by (simp add: prod-mset-prime-factorization assms normalize-mult) also have prime-factorization (prod-mset (prime-factorization (x ∗ y))) = prime-factorization (x ∗ y) by (rule prime-factorization-prod-mset-primes)(simp-all add: in-prime-factors-imp-prime) also have prime-factorization (prod-mset (prime-factorization x + prime-factorization y)) = prime-factorization x + prime-factorization y by (rule prime-factorization-prod-mset-primes)(auto simp: in-prime-factors-imp-prime) finally show ?thesis . qed lemma prime-elem-multiplicity-mult-distrib: assumes prime-elem p x 6= 0 y 6= 0 shows multiplicity p (x ∗ y) = multiplicity p x + multiplicity p y proof − have multiplicity p (x ∗ y) = count (prime-factorization (x ∗ y)) (normalize p) by (subst count-prime-factorization-prime)(simp-all add: assms) also from assms have prime-factorization (x ∗ y) = prime-factorization x + prime-factorization y by (intro prime-factorization-mult) also have count ... (normalize p) = count (prime-factorization x)(normalize p) + count (prime-factorization y) (normalize p) by simp also have ... = multiplicity p x + multiplicity p y by (subst (1 2 ) count-prime-factorization-prime)(simp-all add: assms) finally show ?thesis . qed lemma prime-elem-multiplicity-prod-mset-distrib: assumes prime-elem p 0 ∈/# A shows multiplicity p (prod-mset A) = sum-mset (image-mset (multiplicity p) A) using assms by (induction A)(auto simp: prime-elem-multiplicity-mult-distrib)

327 lemma prime-elem-multiplicity-power-distrib: assumes prime-elem p x 6= 0 shows multiplicity p (x ˆ n) = n ∗ multiplicity p x using assms prime-elem-multiplicity-prod-mset-distrib [of p replicate-mset n x] by simp lemma prime-elem-multiplicity-prod-distrib: assumes prime-elem p 0 ∈/ f ‘ A finite A shows multiplicity p (prod f A) = (P x∈A. multiplicity p (f x)) proof − have multiplicity p (prod f A) = (P x∈#mset-set A. multiplicity p (f x)) using assms by (subst prod-unfold-prod-mset) (simp-all add: prime-elem-multiplicity-prod-mset-distrib sum-unfold-sum-mset

multiset.map-comp o-def ) also from hfinite Ai have ... = (P x∈A. multiplicity p (f x)) by (induction A rule: finite-induct) simp-all finally show ?thesis . qed lemma multiplicity-distinct-prime-power: prime p =⇒ prime q =⇒ p 6= q =⇒ multiplicity p (q ˆ n) = 0 by (subst prime-elem-multiplicity-power-distrib)(auto simp: prime-multiplicity-other) lemma prime-factorization-prime-power: prime p =⇒ prime-factorization (p ˆ n) = replicate-mset n p by (induction n) (simp-all add: prime-factorization-mult prime-factorization-prime Multiset.union-commute) lemma prime-decomposition: unit-factor x ∗ prod-mset (prime-factorization x) = x by (cases x = 0 )(simp-all add: prod-mset-prime-factorization) lemma prime-factorization-subset-iff-dvd: assumes [simp]: x 6= 0 y 6= 0 shows prime-factorization x ⊆# prime-factorization y ←→ x dvd y proof − have x dvd y ←→ prod-mset (prime-factorization x) dvd prod-mset (prime-factorization y) by (simp add: prod-mset-prime-factorization) also have ... ←→ prime-factorization x ⊆# prime-factorization y by (auto intro!: prod-mset-primes-dvd-imp-subset prod-mset-subset-imp-dvd) finally show ?thesis .. qed lemma prime-factorization-subset-imp-dvd: x 6= 0 =⇒ (prime-factorization x ⊆# prime-factorization y) =⇒ x dvd y by (cases y = 0 )(simp-all add: prime-factorization-subset-iff-dvd)

328 lemma prime-factorization-divide: assumes b dvd a shows prime-factorization (a div b) = prime-factorization a − prime-factorization b proof (cases a = 0 ) case [simp]: False from assms have [simp]: b 6= 0 by auto have prime-factorization ((a div b) ∗ b) = prime-factorization (a div b) + prime-factorization b by (intro prime-factorization-mult)(insert assms, auto elim!: dvdE) with assms show ?thesis by simp qed simp-all lemma zero-not-in-prime-factors [simp]: 0 ∈/ prime-factors x by (auto dest: in-prime-factors-imp-prime) lemma prime-prime-factors: prime p =⇒ prime-factors p = {p} by (drule prime-factorization-prime) simp lemma prod-prime-factors: assumes x 6= 0 shows (Q p ∈ prime-factors x. p ˆ multiplicity p x) = normalize x proof − have normalize x = prod-mset (prime-factorization x) by (simp add: prod-mset-prime-factorization assms) also have ... = (Q p ∈ prime-factors x. p ˆ count (prime-factorization x) p) by (subst prod-mset-multiplicity) simp-all also have ... = (Q p ∈ prime-factors x. p ˆ multiplicity p x) by (intro prod.cong) (simp-all add: assms count-prime-factorization-prime in-prime-factors-imp-prime) finally show ?thesis .. qed lemma prime-factorization-unique 00: assumes S-eq: S = {p. 0 < f p} and finite S and S: ∀ p∈S. prime p normalize n = (Q p∈S. p ˆ f p) shows S = prime-factors n ∧ (∀ p. prime p −→ f p = multiplicity p n) proof define A where A = Abs-multiset f from hfinite S i S(1 ) have (Q p∈S. p ˆ f p) 6= 0 by auto with S(2 ) have nz: n 6= 0 by auto from S-eq hfinite S i have count-A: count A x = f x for x unfolding A-def by (subst multiset.Abs-multiset-inverse)(simp-all add: multiset-def ) from S-eq count-A have set-mset-A: set-mset A = S by (simp only: set-mset-def ) from S(2 ) have normalize n = (Q p∈S. p ˆ f p) . also have ... = prod-mset A by (simp add: prod-mset-multiplicity S-eq set-mset-A

329 count-A) also from nz have normalize n = prod-mset (prime-factorization n) by (simp add: prod-mset-prime-factorization) finally have prime-factorization (prod-mset A) = prime-factorization (prod-mset (prime-factorization n)) by simp also from S(1 ) have prime-factorization (prod-mset A) = A by (intro prime-factorization-prod-mset-primes)(auto simp: set-mset-A) also have prime-factorization (prod-mset (prime-factorization n)) = prime-factorization n by (intro prime-factorization-prod-mset-primes) auto finally show S = prime-factors n by (simp add: set-mset-A [symmetric])

show (∀ p. prime p −→ f p = multiplicity p n) proof safe fix p :: 0a assume p: prime p have multiplicity p n = multiplicity p (normalize n) by simp also have normalize n = prod-mset A by (simp add: prod-mset-multiplicity S-eq set-mset-A count-A S) also from p set-mset-A S(1 ) have multiplicity p ... = sum-mset (image-mset (multiplicity p) A) by (intro prime-elem-multiplicity-prod-mset-distrib) auto also from S(1 ) p have image-mset (multiplicity p) A = image-mset (λq. if p = q then 1 else 0 ) A by (intro image-mset-cong)(auto simp: set-mset-A multiplicity-self prime-multiplicity-other) also have sum-mset ... = f p by (simp add: sum-mset-delta 0 count-A) finally show f p = multiplicity p n .. qed qed lemma prime-factors-product: x 6= 0 =⇒ y 6= 0 =⇒ prime-factors (x ∗ y) = prime-factors x ∪ prime-factors y by (simp add: prime-factorization-mult) lemma dvd-prime-factors [intro]: y 6= 0 =⇒ x dvd y =⇒ prime-factors x ⊆ prime-factors y by (intro set-mset-mono, subst prime-factorization-subset-iff-dvd) auto lemma multiplicity-le-imp-dvd: assumes x 6= 0 Vp. prime p =⇒ multiplicity p x ≤ multiplicity p y shows x dvd y proof (cases y = 0 ) case False from assms this have prime-factorization x ⊆# prime-factorization y by (intro mset-subset-eqI )(auto simp: count-prime-factorization) with assms False show ?thesis by (subst (asm) prime-factorization-subset-iff-dvd) qed auto

330 lemma dvd-multiplicity-eq: x 6= 0 =⇒ y 6= 0 =⇒ x dvd y ←→ (∀ p. multiplicity p x ≤ multiplicity p y) by (auto intro: dvd-imp-multiplicity-le multiplicity-le-imp-dvd) lemma multiplicity-eq-imp-eq: assumes x 6= 0 y 6= 0 assumes Vp. prime p =⇒ multiplicity p x = multiplicity p y shows normalize x = normalize y using assms by (intro associatedI multiplicity-le-imp-dvd) simp-all lemma prime-factorization-unique 0: assumes ∀ p ∈# M . prime p ∀ p ∈# N . prime p (Q i ∈# M . i) = (Q i ∈# N . i) shows M = N proof − have prime-factorization (Q i ∈# M . i) = prime-factorization (Q i ∈# N . i) by (simp only: assms) also from assms have prime-factorization (Q i ∈# M . i) = M by (subst prime-factorization-prod-mset-primes) simp-all also from assms have prime-factorization (Q i ∈# N . i) = N by (subst prime-factorization-prod-mset-primes) simp-all finally show ?thesis . qed lemma multiplicity-cong: (Vr. p ˆ r dvd a ←→ p ˆ r dvd b) =⇒ multiplicity p a = multiplicity p b by (simp add: multiplicity-def ) lemma not-dvd-imp-multiplicity-0 : assumes ¬p dvd x shows multiplicity p x = 0 proof − from assms have multiplicity p x < 1 by (intro multiplicity-lessI ) auto thus ?thesis by simp qed

46.5 GCD and LCM computation with unique factorizations definition gcd-factorial a b = (if a = 0 then normalize b else if b = 0 then normalize a else prod-mset (prime-factorization a ∩# prime-factorization b)) definition lcm-factorial a b = (if a = 0 ∨ b = 0 then 0 else prod-mset (prime-factorization a ∪# prime-factorization b)) definition Gcd-factorial A = (if A ⊆ {0 } then 0 else prod-mset (Inf (prime-factorization ‘ (A − {0 }))))

331 definition Lcm-factorial A = (if A = {} then 1 else if 0 ∈/ A ∧ subset-mset.bdd-above (prime-factorization ‘ (A − {0 })) then prod-mset (Sup (prime-factorization ‘ A)) else 0 ) lemma prime-factorization-gcd-factorial: assumes [simp]: a 6= 0 b 6= 0 shows prime-factorization (gcd-factorial a b) = prime-factorization a ∩# prime-factorization b proof − have prime-factorization (gcd-factorial a b) = prime-factorization (prod-mset (prime-factorization a ∩# prime-factorization b)) by (simp add: gcd-factorial-def ) also have ... = prime-factorization a ∩# prime-factorization b by (subst prime-factorization-prod-mset-primes) auto finally show ?thesis . qed lemma prime-factorization-lcm-factorial: assumes [simp]: a 6= 0 b 6= 0 shows prime-factorization (lcm-factorial a b) = prime-factorization a ∪# prime-factorization b proof − have prime-factorization (lcm-factorial a b) = prime-factorization (prod-mset (prime-factorization a ∪# prime-factorization b)) by (simp add: lcm-factorial-def ) also have ... = prime-factorization a ∪# prime-factorization b by (subst prime-factorization-prod-mset-primes) auto finally show ?thesis . qed lemma prime-factorization-Gcd-factorial: assumes ¬A ⊆ {0 } shows prime-factorization (Gcd-factorial A) = Inf (prime-factorization ‘ (A − {0 })) proof − from assms obtain x where x: x ∈ A − {0 } by auto hence Inf (prime-factorization ‘ (A − {0 })) ⊆# prime-factorization x by (intro subset-mset.cInf-lower) simp-all hence ∀ y. y ∈# Inf (prime-factorization ‘ (A − {0 })) −→ y ∈ prime-factors x by (auto dest: mset-subset-eqD) with in-prime-factors-imp-prime[of - x] have ∀ p. p ∈# Inf (prime-factorization ‘ (A − {0 })) −→ prime p by blast with assms show ?thesis by (simp add: Gcd-factorial-def prime-factorization-prod-mset-primes)

332 qed lemma prime-factorization-Lcm-factorial: assumes 0 ∈/ A subset-mset.bdd-above (prime-factorization ‘ A) shows prime-factorization (Lcm-factorial A) = Sup (prime-factorization ‘ A) proof (cases A = {}) case True hence prime-factorization ‘ A = {} by auto also have Sup ... = {#} by (simp add: Sup-multiset-empty) finally show ?thesis by (simp add: Lcm-factorial-def ) next case False have ∀ y. y ∈# Sup (prime-factorization ‘ A) −→ prime y by (auto simp: in-Sup-multiset-iff assms) with assms False show ?thesis by (simp add: Lcm-factorial-def prime-factorization-prod-mset-primes) qed lemma gcd-factorial-commute: gcd-factorial a b = gcd-factorial b a by (simp add: gcd-factorial-def multiset-inter-commute) lemma gcd-factorial-dvd1 : gcd-factorial a b dvd a proof (cases a = 0 ∨ b = 0 ) case False hence gcd-factorial a b 6= 0 by (auto simp: gcd-factorial-def ) with False show ?thesis by (subst prime-factorization-subset-iff-dvd [symmetric]) (auto simp: prime-factorization-gcd-factorial) qed (auto simp: gcd-factorial-def ) lemma gcd-factorial-dvd2 : gcd-factorial a b dvd b by (subst gcd-factorial-commute)(rule gcd-factorial-dvd1 ) lemma normalize-gcd-factorial: normalize (gcd-factorial a b) = gcd-factorial a b proof − have normalize (prod-mset (prime-factorization a ∩# prime-factorization b)) = prod-mset (prime-factorization a ∩# prime-factorization b) by (intro normalize-prod-mset-primes) auto thus ?thesis by (simp add: gcd-factorial-def ) qed lemma gcd-factorial-greatest: c dvd gcd-factorial a b if c dvd a c dvd b for a b c proof (cases a = 0 ∨ b = 0 ) case False with that have [simp]: c 6= 0 by auto let ?p = prime-factorization from that False have ?p c ⊆# ?p a ?p c ⊆# ?p b by (simp-all add: prime-factorization-subset-iff-dvd) hence prime-factorization c ⊆#

333 prime-factorization (prod-mset (prime-factorization a ∩# prime-factorization b)) using False by (subst prime-factorization-prod-mset-primes) auto with False show ?thesis by (auto simp: gcd-factorial-def prime-factorization-subset-iff-dvd [symmetric]) qed (auto simp: gcd-factorial-def that) lemma lcm-factorial-gcd-factorial: lcm-factorial a b = normalize (a ∗ b) div gcd-factorial a b for a b proof (cases a = 0 ∨ b = 0 ) case False let ?p = prime-factorization from False have prod-mset (?p (a ∗ b)) div gcd-factorial a b = prod-mset (?p a + ?p b − ?p a ∩# ?p b) by (subst prod-mset-diff )(auto simp: lcm-factorial-def gcd-factorial-def prime-factorization-mult subset-mset.le-infI1 ) also from False have prod-mset (?p (a ∗ b)) = normalize (a ∗ b) by (intro prod-mset-prime-factorization) simp-all also from False have prod-mset (?p a + ?p b − ?p a ∩# ?p b) = lcm-factorial a b by (simp add: union-diff-inter-eq-sup lcm-factorial-def ) finally show ?thesis .. qed (auto simp: lcm-factorial-def ) lemma normalize-Gcd-factorial: normalize (Gcd-factorial A) = Gcd-factorial A proof (cases A ⊆ {0 }) case False then obtain x where x ∈ A x 6= 0 by blast hence Inf (prime-factorization ‘ (A − {0 })) ⊆# prime-factorization x by (intro subset-mset.cInf-lower) auto hence prime p if p ∈# Inf (prime-factorization ‘ (A − {0 })) for p using that by (auto dest: mset-subset-eqD) with False show ?thesis by (auto simp add: Gcd-factorial-def normalize-prod-mset-primes) qed (simp-all add: Gcd-factorial-def ) lemma Gcd-factorial-eq-0-iff : Gcd-factorial A = 0 ←→ A ⊆ {0 } by (auto simp: Gcd-factorial-def in-Inf-multiset-iff split: if-splits) lemma Gcd-factorial-dvd: assumes x ∈ A shows Gcd-factorial A dvd x proof (cases x = 0 ) case False with assms have prime-factorization (Gcd-factorial A) = Inf (prime-factorization ‘ (A − {0 })) by (intro prime-factorization-Gcd-factorial) auto

334 also from False assms have ... ⊆# prime-factorization x by (intro subset-mset.cInf-lower) auto finally show ?thesis by (subst (asm) prime-factorization-subset-iff-dvd) (insert assms False, auto simp: Gcd-factorial-eq-0-iff ) qed simp-all lemma Gcd-factorial-greatest: assumes Vy. y ∈ A =⇒ x dvd y shows x dvd Gcd-factorial A proof (cases A ⊆ {0 }) case False from False obtain y where y ∈ A y 6= 0 by auto with assms[of y] have nz: x 6= 0 by auto from nz assms have prime-factorization x ⊆# prime-factorization y if y ∈ A − {0 } for y using that by (subst prime-factorization-subset-iff-dvd) auto with False have prime-factorization x ⊆# Inf (prime-factorization ‘ (A − {0 })) by (intro subset-mset.cInf-greatest) auto also from False have ... = prime-factorization (Gcd-factorial A) by (rule prime-factorization-Gcd-factorial [symmetric]) finally show ?thesis by (subst (asm) prime-factorization-subset-iff-dvd) (insert nz False, auto simp: Gcd-factorial-eq-0-iff ) qed (simp-all add: Gcd-factorial-def ) lemma normalize-Lcm-factorial: normalize (Lcm-factorial A) = Lcm-factorial A proof (cases subset-mset.bdd-above (prime-factorization ‘ A)) case True hence normalize (prod-mset (Sup (prime-factorization ‘ A))) = prod-mset (Sup (prime-factorization ‘ A)) by (intro normalize-prod-mset-primes) (auto simp: in-Sup-multiset-iff ) with True show ?thesis by (simp add: Lcm-factorial-def ) qed (auto simp: Lcm-factorial-def ) lemma Lcm-factorial-eq-0-iff : Lcm-factorial A = 0 ←→ 0 ∈ A ∨ ¬subset-mset.bdd-above (prime-factorization ‘A) by (auto simp: Lcm-factorial-def in-Sup-multiset-iff ) lemma dvd-Lcm-factorial: assumes x ∈ A shows x dvd Lcm-factorial A proof (cases 0 ∈/ A ∧ subset-mset.bdd-above (prime-factorization ‘ A)) case True with assms have [simp]: 0 ∈/ A x 6= 0 A 6= {} by auto

335 from assms True have prime-factorization x ⊆# Sup (prime-factorization ‘ A) by (intro subset-mset.cSup-upper) auto also have ... = prime-factorization (Lcm-factorial A) by (rule prime-factorization-Lcm-factorial [symmetric]) (insert True, simp-all) finally show ?thesis by (subst (asm) prime-factorization-subset-iff-dvd) (insert True, auto simp: Lcm-factorial-eq-0-iff ) qed (insert assms, auto simp: Lcm-factorial-def ) lemma Lcm-factorial-least: assumes Vy. y ∈ A =⇒ y dvd x shows Lcm-factorial A dvd x proof − consider A = {} | 0 ∈ A | x = 0 | A 6= {} 0 ∈/ A x 6= 0 by blast thus ?thesis proof cases assume ∗: A 6= {} 0 ∈/ A x 6= 0 hence nz: x 6= 0 if x ∈ A for x using that by auto from ∗ have bdd: subset-mset.bdd-above (prime-factorization ‘ A) by (intro subset-mset.bdd-aboveI [of - prime-factorization x]) (auto simp: prime-factorization-subset-iff-dvd nz dest: assms) have prime-factorization (Lcm-factorial A) = Sup (prime-factorization ‘ A) by (rule prime-factorization-Lcm-factorial) fact+ also from ∗ have ... ⊆# prime-factorization x by (intro subset-mset.cSup-least) (auto simp: prime-factorization-subset-iff-dvd nz dest: assms) finally show ?thesis by (subst (asm) prime-factorization-subset-iff-dvd) (insert ∗ bdd, auto simp: Lcm-factorial-eq-0-iff ) qed (auto simp: Lcm-factorial-def dest: assms) qed lemmas gcd-lcm-factorial = gcd-factorial-dvd1 gcd-factorial-dvd2 gcd-factorial-greatest normalize-gcd-factorial lcm-factorial-gcd-factorial normalize-Gcd-factorial Gcd-factorial-dvd Gcd-factorial-greatest normalize-Lcm-factorial dvd-Lcm-factorial Lcm-factorial-least end class factorial-semiring-gcd = factorial-semiring + gcd + Gcd + assumes gcd-eq-gcd-factorial: gcd a b = gcd-factorial a b and lcm-eq-lcm-factorial: lcm a b = lcm-factorial a b and Gcd-eq-Gcd-factorial: Gcd A = Gcd-factorial A and Lcm-eq-Lcm-factorial: Lcm A = Lcm-factorial A begin lemma prime-factorization-gcd: assumes [simp]: a 6= 0 b 6= 0

336 shows prime-factorization (gcd a b) = prime-factorization a ∩# prime-factorization b by (simp add: gcd-eq-gcd-factorial prime-factorization-gcd-factorial) lemma prime-factorization-lcm: assumes [simp]: a 6= 0 b 6= 0 shows prime-factorization (lcm a b) = prime-factorization a ∪# prime-factorization b by (simp add: lcm-eq-lcm-factorial prime-factorization-lcm-factorial) lemma prime-factorization-Gcd: assumes Gcd A 6= 0 shows prime-factorization (Gcd A) = Inf (prime-factorization ‘ (A − {0 })) using assms by (simp add: prime-factorization-Gcd-factorial Gcd-eq-Gcd-factorial Gcd-factorial-eq-0-iff ) lemma prime-factorization-Lcm: assumes Lcm A 6= 0 shows prime-factorization (Lcm A) = Sup (prime-factorization ‘ A) using assms by (simp add: prime-factorization-Lcm-factorial Lcm-eq-Lcm-factorial Lcm-factorial-eq-0-iff ) subclass semiring-gcd by (standard, unfold gcd-eq-gcd-factorial lcm-eq-lcm-factorial) (rule gcd-lcm-factorial; assumption)+ subclass semiring-Gcd by (standard, unfold Gcd-eq-Gcd-factorial Lcm-eq-Lcm-factorial) (rule gcd-lcm-factorial; assumption)+ lemma assumes x 6= 0 y 6= 0 shows gcd-eq-factorial 0: gcd x y = (Q p ∈ prime-factors x ∩ prime-factors y. p ˆ min (multiplicity p x)(multiplicity p y)) (is - = ?rhs1 ) and lcm-eq-factorial 0: lcm x y = (Q p ∈ prime-factors x ∪ prime-factors y. p ˆ max (multiplicity p x)(multiplicity p y)) (is - = ?rhs2 ) proof − have gcd x y = gcd-factorial x y by (rule gcd-eq-gcd-factorial) also have ... = ?rhs1 by (auto simp: gcd-factorial-def assms prod-mset-multiplicity count-prime-factorization-prime dest: in-prime-factors-imp-prime intro!: prod.cong) finally show gcd x y = ?rhs1 . have lcm x y = lcm-factorial x y by (rule lcm-eq-lcm-factorial) also have ... = ?rhs2 by (auto simp: lcm-factorial-def assms prod-mset-multiplicity count-prime-factorization-prime dest: in-prime-factors-imp-prime intro!:

337 prod.cong) finally show lcm x y = ?rhs2 . qed lemma assumes x 6= 0 y 6= 0 prime p shows multiplicity-gcd: multiplicity p (gcd x y) = min (multiplicity p x) (multiplicity p y) and multiplicity-lcm: multiplicity p (lcm x y) = max (multiplicity p x) (multiplicity p y) proof − have gcd x y = gcd-factorial x y by (rule gcd-eq-gcd-factorial) also from assms have multiplicity p ... = min (multiplicity p x)(multiplicity p y) by (simp add: count-prime-factorization-prime [symmetric] prime-factorization-gcd-factorial) finally show multiplicity p (gcd x y) = min (multiplicity p x)(multiplicity p y) . have lcm x y = lcm-factorial x y by (rule lcm-eq-lcm-factorial) also from assms have multiplicity p ... = max (multiplicity p x)(multiplicity p y) by (simp add: count-prime-factorization-prime [symmetric] prime-factorization-lcm-factorial) finally show multiplicity p (lcm x y) = max (multiplicity p x)(multiplicity p y) . qed lemma gcd-lcm-distrib: gcd x (lcm y z) = lcm (gcd x y)(gcd x z) proof (cases x = 0 ∨ y = 0 ∨ z = 0 ) case True thus ?thesis by (auto simp: lcm-proj1-if-dvd lcm-proj2-if-dvd) next case False hence normalize (gcd x (lcm y z)) = normalize (lcm (gcd x y)(gcd x z)) by (intro associatedI prime-factorization-subset-imp-dvd) (auto simp: lcm-eq-0-iff prime-factorization-gcd prime-factorization-lcm subset-mset.inf-sup-distrib1 ) thus ?thesis by simp qed lemma lcm-gcd-distrib: lcm x (gcd y z) = gcd (lcm x y)(lcm x z) proof (cases x = 0 ∨ y = 0 ∨ z = 0 ) case True thus ?thesis by (auto simp: lcm-proj1-if-dvd lcm-proj2-if-dvd) next case False hence normalize (lcm x (gcd y z)) = normalize (gcd (lcm x y)(lcm x z))

338 by (intro associatedI prime-factorization-subset-imp-dvd) (auto simp: lcm-eq-0-iff prime-factorization-gcd prime-factorization-lcm subset-mset.sup-inf-distrib1 ) thus ?thesis by simp qed end class factorial-ring-gcd = factorial-semiring-gcd + idom begin subclass ring-gcd .. subclass idom-divide .. end end

47 Abstract euclidean algorithm theory Euclidean-Algorithm imports ∼∼/src/HOL/GCD Factorial-Ring begin

A Euclidean semiring is a semiring upon which the Euclidean algorithm can be implemented. It must provide:

• division with remainder

• a size function such that size (a mod b) < size b for any b 6= (0 :: 0a)

The existence of these functions makes it possible to derive gcd and lcm functions for any Euclidean semiring. class euclidean-semiring = semiring-modulo + normalization-semidom + fixes euclidean-size :: 0a ⇒ nat assumes size-0 [simp]: euclidean-size 0 = 0 assumes mod-size-less: b 6= 0 =⇒ euclidean-size (a mod b) < euclidean-size b assumes size-mult-mono: b 6= 0 =⇒ euclidean-size a ≤ euclidean-size (a ∗ b) begin lemma mod-0 [simp]: 0 mod a = 0 using div-mult-mod-eq [of 0 a] by simp lemma dvd-mod-iff : assumes k dvd n

339 shows (k dvd m mod n) = (k dvd m) proof − from assms have (k dvd m mod n) ←→ (k dvd ((m div n) ∗ n + m mod n)) by (simp add: dvd-add-right-iff ) also have (m div n) ∗ n + m mod n = m using div-mult-mod-eq [of m n] by simp finally show ?thesis . qed lemma mod-0-imp-dvd: assumes a mod b = 0 shows b dvd a proof − have b dvd ((a div b) ∗ b) by simp also have (a div b) ∗ b = a using div-mult-mod-eq [of a b] by (simp add: assms) finally show ?thesis . qed lemma euclidean-size-normalize [simp]: euclidean-size (normalize a) = euclidean-size a proof (cases a = 0 ) case True then show ?thesis by simp next case [simp]: False have euclidean-size (normalize a) ≤ euclidean-size (normalize a ∗ unit-factor a) by (rule size-mult-mono) simp moreover have euclidean-size a ≤ euclidean-size (a ∗ (1 div unit-factor a)) by (rule size-mult-mono) simp ultimately show ?thesis by simp qed lemma euclidean-division: fixes a :: 0a and b :: 0a assumes b 6= 0 obtains s and t where a = s ∗ b + t and euclidean-size t < euclidean-size b proof − from div-mult-mod-eq [of a b] have a = a div b ∗ b + a mod b by simp with that and assms show ?thesis by (auto simp add: mod-size-less) qed lemma dvd-euclidean-size-eq-imp-dvd: assumes a 6= 0 and b-dvd-a: b dvd a and size-eq: euclidean-size a = euclidean-size b

340 shows a dvd b proof (rule ccontr) assume ¬ a dvd b hence b mod a 6= 0 using mod-0-imp-dvd[of b a] by blast then have b mod a 6= 0 by (simp add: mod-eq-0-iff-dvd) from b-dvd-a have b-dvd-mod: b dvd b mod a by (simp add: dvd-mod-iff ) from b-dvd-mod obtain c where b mod a = b ∗ c unfolding dvd-def by blast with hb mod a 6= 0 i have c 6= 0 by auto with hb mod a = b ∗ ci have euclidean-size (b mod a) ≥ euclidean-size b using size-mult-mono by force moreover from h¬ a dvd bi and ha 6= 0 i have euclidean-size (b mod a) < euclidean-size a using mod-size-less by blast ultimately show False using size-eq by simp qed lemma size-mult-mono 0: b 6= 0 =⇒ euclidean-size a ≤ euclidean-size (b ∗ a) by (subst mult.commute)(rule size-mult-mono) lemma euclidean-size-times-unit: assumes is-unit a shows euclidean-size (a ∗ b) = euclidean-size b proof (rule antisym) from assms have [simp]: a 6= 0 by auto thus euclidean-size (a ∗ b) ≥ euclidean-size b by (rule size-mult-mono 0) from assms have is-unit (1 div a) by simp hence 1 div a 6= 0 by (intro notI ) simp-all hence euclidean-size (a ∗ b) ≤ euclidean-size ((1 div a) ∗ (a ∗ b)) by (rule size-mult-mono 0) also from assms have (1 div a) ∗ (a ∗ b) = b by (simp add: algebra-simps unit-div-mult-swap) finally show euclidean-size (a ∗ b) ≤ euclidean-size b . qed lemma euclidean-size-unit: is-unit a =⇒ euclidean-size a = euclidean-size 1 using euclidean-size-times-unit[of a 1 ] by simp lemma unit-iff-euclidean-size: is-unit a ←→ euclidean-size a = euclidean-size 1 ∧ a 6= 0 proof safe assume A: a 6= 0 and B: euclidean-size a = euclidean-size 1 show is-unit a by (rule dvd-euclidean-size-eq-imp-dvd[OF A - B]) simp-all qed (auto intro: euclidean-size-unit) lemma euclidean-size-times-nonunit: assumes a 6= 0 b 6= 0 ¬is-unit a shows euclidean-size b < euclidean-size (a ∗ b) proof (rule ccontr) assume ¬euclidean-size b < euclidean-size (a ∗ b)

341 with size-mult-mono 0[OF assms(1 ), of b] have eq: euclidean-size (a ∗ b) = euclidean-size b by simp have a ∗ b dvd b by (rule dvd-euclidean-size-eq-imp-dvd[OF - - eq]) (insert assms, simp-all) hence a ∗ b dvd 1 ∗ b by simp with hb 6= 0 i have is-unit a by (subst (asm) dvd-times-right-cancel-iff ) with assms(3 ) show False by contradiction qed lemma dvd-imp-size-le: assumes a dvd b b 6= 0 shows euclidean-size a ≤ euclidean-size b using assms by (auto elim!: dvdE simp: size-mult-mono) lemma dvd-proper-imp-size-less: assumes a dvd b ¬b dvd a b 6= 0 shows euclidean-size a < euclidean-size b proof − from assms(1 ) obtain c where b = a ∗ c by (erule dvdE) hence z: b = c ∗ a by (simp add: mult.commute) from z assms have ¬is-unit c by (auto simp: mult.commute mult-unit-dvd-iff ) with z assms show ?thesis by (auto intro!: euclidean-size-times-nonunit simp:) qed function gcd-eucl :: 0a ⇒ 0a ⇒ 0a where gcd-eucl a b = (if b = 0 then normalize a else gcd-eucl b (a mod b)) by pat-completeness simp termination by (relation measure (euclidean-size ◦ snd)) (simp-all add: mod-size-less) declare gcd-eucl.simps [simp del] lemma gcd-eucl-induct [case-names zero mod]: assumes H1 : Vb. P b 0 and H2 : Va b. b 6= 0 =⇒ P b (a mod b) =⇒ P a b shows P a b proof (induct a b rule: gcd-eucl.induct) case (1 a b) show ?case proof (cases b = 0 ) case True then show P a b by simp (rule H1 ) next case False then have P b (a mod b) by (rule 1 .hyps) with hb 6= 0 i show P a b by (blast intro: H2 )

342 qed qed definition lcm-eucl :: 0a ⇒ 0a ⇒ 0a where lcm-eucl a b = normalize (a ∗ b) div gcd-eucl a b definition Lcm-eucl :: 0a set ⇒ 0a — Somewhat complicated definition of Lcm that has the advantage of working for infinite sets as well where Lcm-eucl A = (if ∃ l. l 6= 0 ∧ (∀ a∈A. a dvd l) then let l = SOME l. l 6= 0 ∧ (∀ a∈A. a dvd l) ∧ euclidean-size l = (LEAST n. ∃ l. l 6= 0 ∧ (∀ a∈A. a dvd l) ∧ euclidean-size l = n) in normalize l else 0 ) definition Gcd-eucl :: 0a set ⇒ 0a where Gcd-eucl A = Lcm-eucl {d. ∀ a∈A. d dvd a} declare Lcm-eucl-def Gcd-eucl-def [code del] lemma gcd-eucl-0 : gcd-eucl a 0 = normalize a by (simp add: gcd-eucl.simps [of a 0 ]) lemma gcd-eucl-0-left: gcd-eucl 0 a = normalize a by (simp-all add: gcd-eucl-0 gcd-eucl.simps [of 0 a]) lemma gcd-eucl-non-0 : b 6= 0 =⇒ gcd-eucl a b = gcd-eucl b (a mod b) by (simp add: gcd-eucl.simps [of a b] gcd-eucl.simps [of b 0 ]) lemma gcd-eucl-dvd1 [iff ]: gcd-eucl a b dvd a and gcd-eucl-dvd2 [iff ]: gcd-eucl a b dvd b by (induct a b rule: gcd-eucl-induct) (simp-all add: gcd-eucl-0 gcd-eucl-non-0 dvd-mod-iff ) lemma normalize-gcd-eucl [simp]: normalize (gcd-eucl a b) = gcd-eucl a b by (induct a b rule: gcd-eucl-induct)(simp-all add: gcd-eucl-0 gcd-eucl-non-0 ) lemma gcd-eucl-greatest: fixes k a b :: 0a shows k dvd a =⇒ k dvd b =⇒ k dvd gcd-eucl a b proof (induct a b rule: gcd-eucl-induct) case (zero a) from zero(1 ) show ?case by (rule dvd-trans)(simp add: gcd-eucl-0 ) next

343 case (mod a b) then show ?case by (simp add: gcd-eucl-non-0 dvd-mod-iff ) qed lemma gcd-euclI : fixes gcd :: 0a ⇒ 0a ⇒ 0a assumes d dvd a d dvd b normalize d = d Vk. k dvd a =⇒ k dvd b =⇒ k dvd d shows gcd-eucl a b = d by (rule associated-eqI )(simp-all add: gcd-eucl-greatest assms) lemma eq-gcd-euclI : fixes gcd :: 0a ⇒ 0a ⇒ 0a assumes Va b. gcd a b dvd a Va b. gcd a b dvd b Va b. normalize (gcd a b) = gcd a b Va b k. k dvd a =⇒ k dvd b =⇒ k dvd gcd a b shows gcd = gcd-eucl by (intro ext, rule associated-eqI )(simp-all add: gcd-eucl-greatest assms) lemma gcd-eucl-zero [simp]: gcd-eucl a b = 0 ←→ a = 0 ∧ b = 0 by (metis dvd-0-left dvd-refl gcd-eucl-dvd1 gcd-eucl-dvd2 gcd-eucl-greatest)+ lemma dvd-Lcm-eucl [simp]: a ∈ A =⇒ a dvd Lcm-eucl A and Lcm-eucl-least:(Va. a ∈ A =⇒ a dvd b) =⇒ Lcm-eucl A dvd b and unit-factor-Lcm-eucl [simp]: unit-factor (Lcm-eucl A) = (if Lcm-eucl A = 0 then 0 else 1 ) proof − have (∀ a∈A. a dvd Lcm-eucl A) ∧ (∀ l 0. (∀ a∈A. a dvd l 0) −→ Lcm-eucl A dvd l 0) ∧ unit-factor (Lcm-eucl A) = (if Lcm-eucl A = 0 then 0 else 1 )(is ?thesis) proof (cases ∃ l. l 6= 0 ∧ (∀ a∈A. a dvd l)) case False hence Lcm-eucl A = 0 by (auto simp: Lcm-eucl-def ) with False show ?thesis by auto next case True then obtain l 0 where l 0-props: l 0 6= 0 ∧ (∀ a∈A. a dvd l 0) by blast define n where n = (LEAST n. ∃ l. l 6= 0 ∧ (∀ a∈A. a dvd l) ∧ euclidean-size l = n) define l where l = (SOME l. l 6= 0 ∧ (∀ a∈A. a dvd l) ∧ euclidean-size l = n) have ∃ l. l 6= 0 ∧ (∀ a∈A. a dvd l) ∧ euclidean-size l = n apply (subst n-def ) apply (rule LeastI [of - euclidean-size l 0]) apply (rule exI [of - l 0]) apply (simp add: l 0-props)

344 done from someI-ex[OF this] have l 6= 0 and ∀ a∈A. a dvd l and euclidean-size l = n unfolding l-def by simp-all { fix l 0 assume ∀ a∈A. a dvd l 0 0 with h∀ a∈A. a dvd l i have ∀ a∈A. a dvd gcd-eucl l l by (auto intro: gcd-eucl-greatest) 0 moreover from hl 6= 0 i have gcd-eucl l l 6= 0 by simp ultimately have ∃ b. b 6= 0 ∧ (∀ a∈A. a dvd b) ∧ euclidean-size b = euclidean-size (gcd-eucl l l 0) by (intro exI [of - gcd-eucl l l 0], auto) hence euclidean-size (gcd-eucl l l 0) ≥ n by (subst n-def )(rule Least-le) moreover have euclidean-size (gcd-eucl l l 0) ≤ n proof − have gcd-eucl l l 0 dvd l by simp then obtain a where l = gcd-eucl l l 0 ∗ a unfolding dvd-def by blast with hl 6= 0 i have a 6= 0 by auto hence euclidean-size (gcd-eucl l l 0) ≤ euclidean-size (gcd-eucl l l 0 ∗ a) by (rule size-mult-mono) 0 0 also have gcd-eucl l l ∗ a = l using hl = gcd-eucl l l ∗ a i .. also note heuclidean-size l = n i finally show euclidean-size (gcd-eucl l l 0) ≤ n . qed ultimately have ∗: euclidean-size l = euclidean-size (gcd-eucl l l 0) by (intro le-antisym, simp-all add: heuclidean-size l = n i) 0 from hl 6= 0 i have l dvd gcd-eucl l l by (rule dvd-euclidean-size-eq-imp-dvd)(auto simp add: ∗) hence l dvd l 0 by (rule dvd-trans[OF - gcd-eucl-dvd2 ]) }

with h(∀ a∈A. a dvd l)i and unit-factor-is-unit[OF hl 6= 0 i] and hl 6= 0 i have (∀ a∈A. a dvd normalize l) ∧ (∀ l 0. (∀ a∈A. a dvd l 0) −→ normalize l dvd l 0) ∧ unit-factor (normalize l) = (if normalize l = 0 then 0 else 1 ) by (auto simp: unit-simps) also from True have normalize l = Lcm-eucl A by (simp add: Lcm-eucl-def Let-def n-def l-def ) finally show ?thesis . qed note A = this

{fix a assume a ∈ A then show a dvd Lcm-eucl A using A by blast} {fix b assume Va. a ∈ A =⇒ a dvd b then show Lcm-eucl A dvd b using A by blast} from A show unit-factor (Lcm-eucl A) = (if Lcm-eucl A = 0 then 0 else 1 ) by blast qed

345 lemma normalize-Lcm-eucl [simp]: normalize (Lcm-eucl A) = Lcm-eucl A proof (cases Lcm-eucl A = 0 ) case True then show ?thesis by simp next case False have unit-factor (Lcm-eucl A) ∗ normalize (Lcm-eucl A) = Lcm-eucl A by (fact unit-factor-mult-normalize) with False show ?thesis by simp qed lemma eq-Lcm-euclI : fixes lcm :: 0a set ⇒ 0a assumes VA a. a ∈ A =⇒ a dvd lcm A and VA c. (Va. a ∈ A =⇒ a dvd c) =⇒ lcm A dvd c VA. normalize (lcm A) = lcm A shows lcm = Lcm-eucl by (intro ext, rule associated-eqI )(auto simp: assms intro: Lcm-eucl-least) lemma Gcd-eucl-dvd: a ∈ A =⇒ Gcd-eucl A dvd a unfolding Gcd-eucl-def by (auto intro: Lcm-eucl-least) lemma Gcd-eucl-greatest:(Vx. x ∈ A =⇒ d dvd x) =⇒ d dvd Gcd-eucl A unfolding Gcd-eucl-def by auto lemma normalize-Gcd-eucl [simp]: normalize (Gcd-eucl A) = Gcd-eucl A by (simp add: Gcd-eucl-def ) lemma Lcm-euclI : assumes Vx. x ∈ A =⇒ x dvd d Vd 0. (Vx. x ∈ A =⇒ x dvd d 0) =⇒ d dvd d 0 normalize d = d shows Lcm-eucl A = d proof − have normalize (Lcm-eucl A) = normalize d by (intro associatedI )(auto intro: dvd-Lcm-eucl Lcm-eucl-least assms) thus ?thesis by (simp add: assms) qed lemma Gcd-euclI : assumes Vx. x ∈ A =⇒ d dvd x Vd 0. (Vx. x ∈ A =⇒ d 0 dvd x) =⇒ d 0 dvd d normalize d = d shows Gcd-eucl A = d proof − have normalize (Gcd-eucl A) = normalize d by (intro associatedI )(auto intro: Gcd-eucl-dvd Gcd-eucl-greatest assms) thus ?thesis by (simp add: assms) qed lemmas lcm-gcd-eucl-facts =

346 gcd-eucl-dvd1 gcd-eucl-dvd2 gcd-eucl-greatest normalize-gcd-eucl lcm-eucl-def Gcd-eucl-def Gcd-eucl-dvd Gcd-eucl-greatest normalize-Gcd-eucl dvd-Lcm-eucl Lcm-eucl-least normalize-Lcm-eucl lemma normalized-factors-product: {p. p dvd a ∗ b ∧ normalize p = p} = (λ(x,y). x ∗ y) ‘ ({p. p dvd a ∧ normalize p = p} × {p. p dvd b ∧ normalize p = p}) proof safe fix p assume p: p dvd a ∗ b normalize p = p interpret semiring-gcd 1 0 op ∗ gcd-eucl lcm-eucl op div op + op − normalize unit-factor by standard (rule lcm-gcd-eucl-facts; assumption)+ from dvd-productE[OF p(1 )] guess x y . note xy = this define x 0 y 0 where x 0 = normalize x and y 0 = normalize y have p = x 0 ∗ y 0 by (subst p(2 )[symmetric]) (simp add: xy x 0-def y 0-def normalize-mult) moreover from xy have normalize x 0 = x 0 normalize y 0 = y 0 x 0 dvd a y 0 dvd b by (simp-all add: x 0-def y 0-def ) ultimately show p ∈ (λ(x, y). x ∗ y) ‘ ({p. p dvd a ∧ normalize p = p} × {p. p dvd b ∧ normalize p = p}) by blast qed (auto simp: normalize-mult mult-dvd-mono) subclass factorial-semiring proof (standard, rule factorial-semiring-altI-aux) fix x assume x 6= 0 thus finite {p. p dvd x ∧ normalize p = p} proof (induction euclidean-size x arbitrary: x rule: less-induct) case (less x) show ?case proof (cases ∃ y. y dvd x ∧ ¬x dvd y ∧ ¬is-unit y) case False have {p. p dvd x ∧ normalize p = p} ⊆ {1 , normalize x} proof fix p assume p: p ∈ {p. p dvd x ∧ normalize p = p} with False have is-unit p ∨ x dvd p by blast thus p ∈ {1 , normalize x} proof (elim disjE) assume is-unit p hence normalize p = 1 by (simp add: is-unit-normalize) with p show ?thesis by simp next assume x dvd p with p have normalize p = normalize x by (intro associatedI ) simp-all with p show ?thesis by simp qed

347 qed moreover have finite ... by simp ultimately show ?thesis by (rule finite-subset)

next case True then obtain y where y: y dvd x ¬x dvd y ¬is-unit y by blast define z where z = x div y let ?fctrs = λx. {p. p dvd x ∧ normalize p = p} from y have x: x = y ∗ z by (simp add: z-def ) with less.prems have y 6= 0 z 6= 0 by auto from x y have ¬is-unit z by (auto simp: mult-unit-dvd-iff ) have ?fctrs x = (λ(p,p 0). p ∗ p 0) ‘ (?fctrs y × ?fctrs z) by (subst x)(rule normalized-factors-product) also have ¬y ∗ z dvd y ∗ 1 ¬y ∗ z dvd 1 ∗ z by (subst dvd-times-left-cancel-iff dvd-times-right-cancel-iff ; fact)+ hence finite ((λ(p,p 0). p ∗ p 0) ‘ (?fctrs y × ?fctrs z)) by (intro finite-imageI finite-cartesian-product less dvd-proper-imp-size-less) (auto simp: x) finally show ?thesis . qed qed next interpret semiring-gcd 1 0 op ∗ gcd-eucl lcm-eucl op div op + op − normalize unit-factor by standard (rule lcm-gcd-eucl-facts; assumption)+ fix p assume p: irreducible p thus prime-elem p by (rule irreducible-imp-prime-elem-gcd) qed lemma gcd-eucl-eq-gcd-factorial: gcd-eucl = gcd-factorial by (intro ext gcd-euclI gcd-lcm-factorial) lemma lcm-eucl-eq-lcm-factorial: lcm-eucl = lcm-factorial by (intro ext)(simp add: lcm-eucl-def lcm-factorial-gcd-factorial gcd-eucl-eq-gcd-factorial) lemma Gcd-eucl-eq-Gcd-factorial: Gcd-eucl = Gcd-factorial by (intro ext Gcd-euclI gcd-lcm-factorial) lemma Lcm-eucl-eq-Lcm-factorial: Lcm-eucl = Lcm-factorial by (intro ext Lcm-euclI gcd-lcm-factorial) lemmas eucl-eq-factorial = gcd-eucl-eq-gcd-factorial lcm-eucl-eq-lcm-factorial Gcd-eucl-eq-Gcd-factorial Lcm-eucl-eq-Lcm-factorial end class euclidean-ring = euclidean-semiring + idom

348 begin function euclid-ext-aux :: 0a ⇒ - where euclid-ext-aux r 0 r s 0 s t 0 t = ( if r = 0 then let c = 1 div unit-factor r 0 in (s 0 ∗ c, t 0 ∗ c, normalize r 0) else let q = r 0 div r in euclid-ext-aux r (r 0 mod r) s (s 0 − q ∗ s) t (t 0 − q ∗ t)) by auto termination by (relation measure (λ(-,b,-,-,-,-). euclidean-size b)) (simp-all add: mod-size-less) declare euclid-ext-aux.simps [simp del] lemma euclid-ext-aux-correct: assumes gcd-eucl r 0 r = gcd-eucl a b assumes s 0 ∗ a + t 0 ∗ b = r 0 assumes s ∗ a + t ∗ b = r shows case euclid-ext-aux r 0 r s 0 s t 0 t of (x,y,c) ⇒ x ∗ a + y ∗ b = c ∧ c = gcd-eucl a b (is ?P (euclid-ext-aux r 0 r s 0 s t 0 t)) using assms proof (induction r 0 r s 0 s t 0 t rule: euclid-ext-aux.induct) case (1 r 0 r s 0 s t 0 t) show ?case proof (cases r = 0 ) case True hence euclid-ext-aux r 0 r s 0 s t 0 t = (s 0 div unit-factor r 0, t 0 div unit-factor r 0, normalize r 0) by (subst euclid-ext-aux.simps)(simp add: Let-def ) also have ?P ... proof safe have s 0 div unit-factor r 0 ∗ a + t 0 div unit-factor r 0 ∗ b = (s 0 ∗ a + t 0 ∗ b) div unit-factor r 0 by (cases r 0 = 0 )(simp-all add: unit-div-commute) also have s 0 ∗ a + t 0 ∗ b = r 0 by fact also have ... div unit-factor r 0 = normalize r 0 by simp finally show s 0 div unit-factor r 0 ∗ a + t 0 div unit-factor r 0 ∗ b = normalize r 0 . next from 1 .prems True show normalize r 0 = gcd-eucl a b by (simp add: gcd-eucl-0 ) qed finally show ?thesis . next case False hence euclid-ext-aux r 0 r s 0 s t 0 t = euclid-ext-aux r (r 0 mod r) s (s 0 − r 0 div r ∗ s) t (t 0 − r 0 div r ∗ t) by (subst euclid-ext-aux.simps)(simp add: Let-def ) also from 1 .prems False have ?P ...

349 proof (intro 1 .IH ) have (s 0 − r 0 div r ∗ s) ∗ a + (t 0 − r 0 div r ∗ t) ∗ b = (s 0 ∗ a + t 0 ∗ b) − r 0 div r ∗ (s ∗ a + t ∗ b) by (simp add: algebra-simps) also have s 0 ∗ a + t 0 ∗ b = r 0 by fact also have s ∗ a + t ∗ b = r by fact also have r 0 − r 0 div r ∗ r = r 0 mod r using div-mult-mod-eq [of r 0 r] by (simp add: algebra-simps) finally show (s 0 − r 0 div r ∗ s) ∗ a + (t 0 − r 0 div r ∗ t) ∗ b = r 0 mod r . qed (auto simp: gcd-eucl-non-0 algebra-simps minus-mod-eq-div-mult [symmetric]) finally show ?thesis . qed qed definition euclid-ext where euclid-ext a b = euclid-ext-aux a b 1 0 0 1 lemma euclid-ext-0 : euclid-ext a 0 = (1 div unit-factor a, 0 , normalize a) by (simp add: euclid-ext-def euclid-ext-aux.simps) lemma euclid-ext-left-0 : euclid-ext 0 a = (0 , 1 div unit-factor a, normalize a) by (simp add: euclid-ext-def euclid-ext-aux.simps) lemma euclid-ext-correct 0: case euclid-ext a b of (x,y,c) ⇒ x ∗ a + y ∗ b = c ∧ c = gcd-eucl a b unfolding euclid-ext-def by (rule euclid-ext-aux-correct) simp-all lemma euclid-ext-gcd-eucl: (case euclid-ext a b of (x,y,c) ⇒ c) = gcd-eucl a b using euclid-ext-correct 0[of a b] by (simp add: case-prod-unfold) definition euclid-ext 0 where euclid-ext 0 a b = (case euclid-ext a b of (x, y, -) ⇒ (x, y)) lemma euclid-ext 0-correct 0: case euclid-ext 0 a b of (x,y) ⇒ x ∗ a + y ∗ b = gcd-eucl a b using euclid-ext-correct 0[of a b] by (simp add: case-prod-unfold euclid-ext 0-def ) lemma euclid-ext 0-0 : euclid-ext 0 a 0 = (1 div unit-factor a, 0 ) by (simp add: euclid-ext 0-def euclid-ext-0 ) lemma euclid-ext 0-left-0 : euclid-ext 0 0 a = (0 , 1 div unit-factor a) by (simp add: euclid-ext 0-def euclid-ext-left-0 ) end class euclidean-semiring-gcd = euclidean-semiring + gcd + Gcd + assumes gcd-gcd-eucl: gcd = gcd-eucl and lcm-lcm-eucl: lcm = lcm-eucl

350 assumes Gcd-Gcd-eucl: Gcd = Gcd-eucl and Lcm-Lcm-eucl: Lcm = Lcm-eucl begin subclass semiring-gcd by standard (simp-all add: gcd-gcd-eucl gcd-eucl-greatest lcm-lcm-eucl lcm-eucl-def ) subclass semiring-Gcd by standard (auto simp: Gcd-Gcd-eucl Lcm-Lcm-eucl Gcd-eucl-def intro: Lcm-eucl-least) subclass factorial-semiring-gcd proof fix a b show gcd a b = gcd-factorial a b by (rule sym, rule gcdI )(rule gcd-lcm-factorial; assumption)+ thus lcm a b = lcm-factorial a b by (simp add: lcm-factorial-gcd-factorial lcm-gcd) next fix A show Gcd A = Gcd-factorial A by (rule sym, rule GcdI )(rule gcd-lcm-factorial; assumption)+ show Lcm A = Lcm-factorial A by (rule sym, rule LcmI )(rule gcd-lcm-factorial; assumption)+ qed lemma gcd-non-0 : b 6= 0 =⇒ gcd a b = gcd b (a mod b) unfolding gcd-gcd-eucl by (fact gcd-eucl-non-0 ) lemmas gcd-0 = gcd-0-right lemmas dvd-gcd-iff = gcd-greatest-iff lemmas gcd-greatest-iff = dvd-gcd-iff lemma gcd-mod1 [simp]: gcd (a mod b) b = gcd a b by (rule gcdI , metis dvd-mod-iff gcd-dvd1 gcd-dvd2 , simp-all add: gcd-greatest dvd-mod-iff ) lemma gcd-mod2 [simp]: gcd a (b mod a) = gcd a b by (rule gcdI , simp, metis dvd-mod-iff gcd-dvd1 gcd-dvd2 , simp-all add: gcd-greatest dvd-mod-iff ) lemma euclidean-size-gcd-le1 [simp]: assumes a 6= 0 shows euclidean-size (gcd a b) ≤ euclidean-size a proof − have gcd a b dvd a by (rule gcd-dvd1 ) then obtain c where A: a = gcd a b ∗ c unfolding dvd-def by blast with ha 6= 0 i show ?thesis by (subst (2 ) A, intro size-mult-mono) auto

351 qed lemma euclidean-size-gcd-le2 [simp]: b 6= 0 =⇒ euclidean-size (gcd a b) ≤ euclidean-size b by (subst gcd.commute, rule euclidean-size-gcd-le1 ) lemma euclidean-size-gcd-less1 : assumes a 6= 0 and ¬a dvd b shows euclidean-size (gcd a b) < euclidean-size a proof (rule ccontr) assume ¬euclidean-size (gcd a b) < euclidean-size a with ha 6= 0 i have A: euclidean-size (gcd a b) = euclidean-size a by (intro le-antisym, simp-all) have a dvd gcd a b by (rule dvd-euclidean-size-eq-imp-dvd)(simp-all add: assms A) hence a dvd b using dvd-gcdD2 by blast with h¬a dvd bi show False by contradiction qed lemma euclidean-size-gcd-less2 : assumes b 6= 0 and ¬b dvd a shows euclidean-size (gcd a b) < euclidean-size b using assms by (subst gcd.commute, rule euclidean-size-gcd-less1 ) lemma euclidean-size-lcm-le1 : assumes a 6= 0 and b 6= 0 shows euclidean-size a ≤ euclidean-size (lcm a b) proof − have a dvd lcm a b by (rule dvd-lcm1 ) then obtain c where A: lcm a b = a ∗ c .. with ha 6= 0 i and hb 6= 0 i have c 6= 0 by (auto simp: lcm-eq-0-iff ) then show ?thesis by (subst A, intro size-mult-mono) qed lemma euclidean-size-lcm-le2 : a 6= 0 =⇒ b 6= 0 =⇒ euclidean-size b ≤ euclidean-size (lcm a b) using euclidean-size-lcm-le1 [of b a] by (simp add: ac-simps) lemma euclidean-size-lcm-less1 : assumes b 6= 0 and ¬b dvd a shows euclidean-size a < euclidean-size (lcm a b) proof (rule ccontr) from assms have a 6= 0 by auto assume ¬euclidean-size a < euclidean-size (lcm a b) with ha 6= 0 i and hb 6= 0 i have euclidean-size (lcm a b) = euclidean-size a by (intro le-antisym, simp, intro euclidean-size-lcm-le1 ) with assms have lcm a b dvd a by (rule-tac dvd-euclidean-size-eq-imp-dvd)(auto simp: lcm-eq-0-iff ) hence b dvd a by (rule lcm-dvdD2 )

352 with h¬b dvd a i show False by contradiction qed lemma euclidean-size-lcm-less2 : assumes a 6= 0 and ¬a dvd b shows euclidean-size b < euclidean-size (lcm a b) using assms euclidean-size-lcm-less1 [of a b] by (simp add: ac-simps) lemma Lcm-eucl-set [code]: Lcm-eucl (set xs) = foldl lcm-eucl 1 xs by (simp add: Lcm-Lcm-eucl [symmetric] lcm-lcm-eucl Lcm-set) lemma Gcd-eucl-set [code]: Gcd-eucl (set xs) = foldl gcd-eucl 0 xs by (simp add: Gcd-Gcd-eucl [symmetric] gcd-gcd-eucl Gcd-set) end

A Euclidean ring is a Euclidean semiring with additive inverses. It provides a few more lemmas; in particular, Bezout’s lemma holds for any Euclidean ring. class euclidean-ring-gcd = euclidean-semiring-gcd + idom begin subclass euclidean-ring .. subclass ring-gcd .. subclass factorial-ring-gcd .. lemma euclid-ext-gcd [simp]: (case euclid-ext a b of (-, - , t) ⇒ t) = gcd a b using euclid-ext-correct 0[of a b] by (simp add: case-prod-unfold Let-def gcd-gcd-eucl) lemma euclid-ext-gcd 0 [simp]: euclid-ext a b = (r, s, t) =⇒ t = gcd a b by (insert euclid-ext-gcd[of a b], drule (1 ) subst, simp) lemma euclid-ext-correct: case euclid-ext a b of (x,y,c) ⇒ x ∗ a + y ∗ b = c ∧ c = gcd a b using euclid-ext-correct 0[of a b] by (simp add: gcd-gcd-eucl case-prod-unfold) lemma euclid-ext 0-correct: fst (euclid-ext 0 a b) ∗ a + snd (euclid-ext 0 a b) ∗ b = gcd a b using euclid-ext-correct 0[of a b] by (simp add: gcd-gcd-eucl case-prod-unfold euclid-ext 0-def ) lemma bezout: ∃ s t. s ∗ a + t ∗ b = gcd a b using euclid-ext 0-correct by blast

353 end

47.1 Typical instances instantiation nat :: euclidean-semiring begin definition [simp]: euclidean-size-nat = (id :: nat ⇒ nat) instance by standard simp-all end instantiation int :: euclidean-ring begin definition [simp]: euclidean-size-int = (nat ◦ abs :: int ⇒ nat) instance by standard (auto simp add: abs-mult nat-mult-distrib split: abs-split) end instance nat :: euclidean-semiring-gcd proof show [simp]: gcd = (gcd-eucl :: nat ⇒ -) Lcm = (Lcm-eucl :: nat set ⇒ -) by (simp-all add: eq-gcd-euclI eq-Lcm-euclI ) show lcm = (lcm-eucl :: nat ⇒ -) Gcd = (Gcd-eucl :: nat set ⇒ -) by (intro ext, simp add: lcm-eucl-def lcm-nat-def Gcd-nat-def Gcd-eucl-def )+ qed instance int :: euclidean-ring-gcd proof show [simp]: gcd = (gcd-eucl :: int ⇒ -) Lcm = (Lcm-eucl :: int set ⇒ -) by (simp-all add: eq-gcd-euclI eq-Lcm-euclI ) show lcm = (lcm-eucl :: int ⇒ -) Gcd = (Gcd-eucl :: int set ⇒ -) by (intro ext, simp add: lcm-eucl-def lcm-altdef-int semiring-Gcd-class.Gcd-Lcm Gcd-eucl-def abs-mult)+ qed end

48 Primes theory Primes imports ∼∼/src/HOL/Binomial Euclidean-Algorithm begin

354 declare [[coercion int]] declare [[coercion-enabled]] lemma prime-elem-nat-iff : prime-elem (n :: nat) ←→ (1 < n ∧ (∀ m. m dvd n −→ m = 1 ∨ m = n)) proof safe assume ∗: prime-elem n from ∗ have n 6= 0 n 6= 1 by (intro notI , simp del: One-nat-def )+ thus n > 1 by (cases n) simp-all fix m assume m: m dvd n m 6= n from ∗ hm dvd n i have n dvd m ∨ is-unit m by (intro irreducibleD 0 prime-elem-imp-irreducible) with m show m = 1 by (auto dest: dvd-antisym) next assume n > 1 ∀ m. m dvd n −→ m = 1 ∨ m = n thus prime-elem n by (auto simp: prime-elem-iff-irreducible irreducible-altdef ) qed lemma prime-nat-iff-prime-elem: prime (n :: nat) ←→ prime-elem n by (simp add: prime-def ) lemma prime-nat-iff : prime (n :: nat) ←→ (1 < n ∧ (∀ m. m dvd n −→ m = 1 ∨ m = n)) by (simp add: prime-nat-iff-prime-elem prime-elem-nat-iff ) lemma prime-elem-int-nat-transfer: prime-elem (n::int) ←→ prime-elem (nat (abs n)) proof assume prime-elem n thus prime-elem (nat (abs n)) by (auto simp: prime-elem-def nat-dvd-iff ) next assume prime-elem (nat (abs n)) thus prime-elem n by (auto simp: dvd-int-unfold-dvd-nat prime-elem-def abs-mult nat-mult-distrib) qed lemma prime-elem-nat-int-transfer [simp]: prime-elem (int n) ←→ prime-elem n by (auto simp: prime-elem-int-nat-transfer) lemma prime-nat-int-transfer [simp]: prime (int n) ←→ prime n by (auto simp: prime-elem-int-nat-transfer prime-def ) lemma prime-int-nat-transfer: prime (n::int) ←→ n ≥ 0 ∧ prime (nat n) by (auto simp: prime-elem-int-nat-transfer prime-def )

355 lemma prime-int-iff : prime (n::int) ←→ (1 < n ∧ (∀ m. m ≥ 0 ∧ m dvd n −→ m = 1 ∨ m = n)) proof (intro iffI conjI allI impI ;(elim conjE)?) assume ∗: prime n hence irred: irreducible n by (simp add: prime-elem-imp-irreducible) from ∗ have n ≥ 0 n 6= 0 n 6= 1 by (auto simp: prime-def zabs-def not-less split: if-splits) thus n > 1 by presburger fix m assume m dvd n hm ≥ 0 i with irred have m dvd 1 ∨ n dvd m by (auto simp: irreducible-altdef ) with hm dvd n i hm ≥ 0 i hn > 1 i show m = 1 ∨ m = n using associated-iff-dvd[of m n] by auto next assume n: 1 < n ∀ m. m ≥ 0 ∧ m dvd n −→ m = 1 ∨ m = n hence nat n > 1 by simp moreover have ∀ m. m dvd nat n −→ m = 1 ∨ m = nat n proof (intro allI impI ) fix m assume m dvd nat n with hn > 1 i have int m dvd n by (auto simp: int-dvd-iff ) with n(2 ) have int m = 1 ∨ int m = n by auto thus m = 1 ∨ m = nat n by auto qed ultimately show prime n unfolding prime-int-nat-transfer prime-nat-iff by auto qed lemma prime-nat-not-dvd: assumes prime p p > n n 6= (1 ::nat) shows ¬n dvd p proof assume n dvd p from assms(1 ) have irreducible p by (simp add: prime-elem-imp-irreducible) 0 from irreducibleD [OF this hn dvd pi] hn dvd pi hp > n i assms show False by (cases n = 0 )(auto dest!: dvd-imp-le) qed lemma prime-int-not-dvd: assumes prime p p > n n > (1 ::int) shows ¬n dvd p proof assume n dvd p from assms(1 ) have irreducible p by (simp add: prime-elem-imp-irreducible) 0 from irreducibleD [OF this hn dvd pi] hn dvd pi hp > n i assms show False by (auto dest!: zdvd-imp-le) qed lemma prime-odd-nat: prime p =⇒ p > (2 ::nat) =⇒ odd p by (intro prime-nat-not-dvd) auto

356 lemma prime-odd-int: prime p =⇒ p > (2 ::int) =⇒ odd p by (intro prime-int-not-dvd) auto lemma prime-ge-0-int: prime p =⇒ p ≥ (0 ::int) unfolding prime-int-iff by auto lemma prime-gt-0-nat: prime p =⇒ p > (0 ::nat) unfolding prime-nat-iff by auto lemma prime-gt-0-int: prime p =⇒ p > (0 ::int) unfolding prime-int-iff by auto lemma prime-ge-1-nat: prime p =⇒ p ≥ (1 ::nat) unfolding prime-nat-iff by auto lemma prime-ge-Suc-0-nat: prime p =⇒ p ≥ Suc 0 unfolding prime-nat-iff by auto lemma prime-ge-1-int: prime p =⇒ p ≥ (1 ::int) unfolding prime-int-iff by auto lemma prime-gt-1-nat: prime p =⇒ p > (1 ::nat) unfolding prime-nat-iff by auto lemma prime-gt-Suc-0-nat: prime p =⇒ p > Suc 0 unfolding prime-nat-iff by auto lemma prime-gt-1-int: prime p =⇒ p > (1 ::int) unfolding prime-int-iff by auto lemma prime-ge-2-nat: prime p =⇒ p ≥ (2 ::nat) unfolding prime-nat-iff by auto lemma prime-ge-2-int: prime p =⇒ p ≥ (2 ::int) unfolding prime-int-iff by auto lemma prime-int-altdef : prime p = (1 < p ∧ (∀ m::int. m ≥ 0 −→ m dvd p −→ m = 1 ∨ m = p)) unfolding prime-int-iff by blast lemma not-prime-eq-prod-nat: assumes m > 1 ¬prime (m::nat) shows ∃ n k. n = m ∗ k ∧ 1 < m ∧ m < n ∧ 1 < k ∧ k < n using assms irreducible-altdef [of m] by (auto simp: prime-elem-iff-irreducible prime-def irreducible-altdef )

357 48.0.1 Make prime naively executable lemma Suc-0-not-prime-nat [simp]: ∼prime (Suc 0 ) unfolding One-nat-def [symmetric] by (rule not-prime-1 ) lemma prime-nat-iff 0: prime (p :: nat) ←→ p > 1 ∧ (∀ n ∈ {1 <.. 1 and ∗: ∀ n∈{1 <.. 1 i have m 6= 0 by (intro notI ) auto hence m ≥ 1 by simp moreover from hm dvd pi and ∗ have m ∈/ {1 <.. 1 i have m ≤ 1 ∨ m = p by (auto dest: dvd-imp-le) ultimately show m = 1 ∨ m = p by simp qed fact+ qed (auto simp: prime-nat-iff ) lemma prime-nat-code [code-unfold]: (prime :: nat ⇒ bool) = (λp. p > 1 ∧ (∀ n ∈ {1 <.. 1 ∧ (∀ n ∈ {1 <.. 1 ∧ (∀ n ∈ {1 <.. 1 ∧ (∀ n ∈ set [2 .. 1 ∧ (∀ n ∈ {2 ..

358 declare prime-int-nat-transfer[of numeral m for m, simp]

A bit of regression testing: lemma prime(97 ::nat) by simp lemma prime(997 ::nat) by eval lemma prime(97 ::int) by simp lemma prime(997 ::int) by eval lemma prime-factor-nat: n 6= (1 ::nat) =⇒ ∃ p. prime p ∧ p dvd n using prime-divisor-exists[of n] by (cases n = 0 )(auto intro: exI [of - 2 ::nat])

48.1 Infinitely many primes lemma next-prime-bound: ∃ p::nat. prime p ∧ n < p ∧ p ≤ fact n + 1 proof− have f1 : fact n + 1 6= (1 ::nat) using fact-ge-1 [of n, where 0a=nat] by arith from prime-factor-nat [OF f1 ] obtain p :: nat where prime p and p dvd fact n + 1 by auto then have p ≤ fact n + 1 apply (intro dvd-imp-le) apply auto done { assume p ≤ n from hprime pi have p ≥ 1 by (cases p, simp-all) with hp <= n i have p dvd fact n by (intro dvd-fact) with hp dvd fact n + 1 i have p dvd fact n + 1 − fact n by (rule dvd-diff-nat) then have p dvd 1 by simp then have p <= 1 by auto moreover from hprime pi have p > 1 using prime-nat-iff by blast ultimately have False by auto} then have n < p by presburger with hprime pi and hp <= fact n + 1 i show ?thesis by auto qed lemma bigger-prime: ∃ p. prime p ∧ p > (n::nat) using next-prime-bound by auto lemma primes-infinite: ¬ (finite {(p::nat). prime p}) proof assume finite {(p::nat). prime p} with Max-ge have (EX b. (ALL x : {(p::nat). prime p}. x <= b)) by auto then obtain b where ALL (x::nat). prime x −→ x <= b by auto with bigger-prime [of b] show False

359 by auto qed

48.2 Powers of Primes

Versions for type nat only lemma prime-product: fixes p::nat assumes prime (p ∗ q) shows p = 1 ∨ q = 1 proof − from assms have 1 < p ∗ q and P: Vm. m dvd p ∗ q =⇒ m = 1 ∨ m = p ∗ q unfolding prime-nat-iff by auto from h1 < p ∗ q i have p 6= 0 by (cases p) auto then have Q: p = p ∗ q ←→ q = 1 by auto have p dvd p ∗ q by simp then have p = 1 ∨ p = p ∗ q by (rule P) then show ?thesis by (simp add: Q) qed lemma prime-power-mult-nat: fixes p::nat assumes p: prime p and xy: x ∗ y = p ˆ k shows ∃ i j . x = p ˆi ∧ y = pˆ j using xy proof(induct k arbitrary: x y) case 0 thus ?case apply simp by (rule exI [where x=0 ], simp) next case (Suc k x y) from Suc.prems have pxy: p dvd x∗y by auto from prime-dvd-multD [OF p pxy] have pxyc: p dvd x ∨ p dvd y . from p have p0 : p 6= 0 by − (rule ccontr, simp) {assume px: p dvd x then obtain d where d: x = p∗d unfolding dvd-def by blast from Suc.prems d have p∗d∗y = pˆSuc k by simp hence th: d∗y = pˆk using p0 by simp from Suc.hyps[OF th] obtain i j where ij : d = pˆi y = pˆj by blast with d have x = pˆSuc i by simp with ij (2 ) have ?case by blast} moreover {assume px: p dvd y then obtain d where d: y = p∗d unfolding dvd-def by blast from Suc.prems d have p∗d∗x = pˆSuc k by (simp add: mult.commute) hence th: d∗x = pˆk using p0 by simp from Suc.hyps[OF th] obtain i j where ij : d = pˆi x = pˆj by blast with d have y = pˆSuc i by simp with ij (2 ) have ?case by blast}

360 ultimately show ?case using pxyc by blast qed lemma prime-power-exp-nat: fixes p::nat assumes p: prime p and n: n 6= 0 and xn: xˆn = pˆk shows ∃ i. x = pˆi using n xn proof(induct n arbitrary: k) case 0 thus ?case by simp next case (Suc n k) hence th: x∗xˆn = pˆk by simp {assume n = 0 with Suc have ?case by simp (rule exI [where x=k], simp)} moreover {assume n: n 6= 0 from prime-power-mult-nat[OF p th] obtain i j where ij : x = pˆi xˆn = pˆj by blast from Suc.hyps[OF n ij (2 )] have ?case .} ultimately show ?case by blast qed lemma divides-primepow-nat: fixes p::nat assumes p: prime p shows d dvd pˆk ←→ (∃ i. i ≤ k ∧ d = p ˆi) proof assume H : d dvd pˆk then obtain e where e: d∗e = pˆk unfolding dvd-def apply (auto simp add: mult.commute) by blast from prime-power-mult-nat[OF p e] obtain i j where ij : d = pˆi e=pˆj by blast from e ij have pˆ(i + j ) = pˆk by (simp add: power-add) hence i + j = k using p prime-gt-1-nat power-inject-exp[of p i+j k] by simp hence i ≤ k by arith with ij (1 ) show ∃ i≤k. d = p ˆ i by blast next {fix i assume H : i ≤ k d = pˆi then obtain j where j : k = i + j by (metis le-add-diff-inverse) hence pˆk = pˆj ∗d using H (2 ) by (simp add: power-add) hence d dvd pˆk unfolding dvd-def by auto} thus ∃ i≤k. d = p ˆ i =⇒ d dvd p ˆ k by blast qed

48.3 Chinese Remainder Theorem Variants lemma bezout-gcd-nat: fixes a::nat shows ∃ x y. a ∗ x − b ∗ y = gcd a b ∨ b ∗ x − a ∗ y = gcd a b using bezout-nat[of a b] by (metis bezout-nat diff-add-inverse gcd-add-mult gcd.commute

361 gcd-nat.right-neutral mult-0 ) lemma gcd-bezout-sum-nat: fixes a::nat assumes a ∗ x + b ∗ y = d shows gcd a b dvd d proof− let ?g = gcd a b have dv: ?g dvd a∗x ?g dvd b ∗ y by simp-all from dvd-add[OF dv] assms show ?thesis by auto qed

A binary form of the Chinese Remainder Theorem. lemma chinese-remainder: fixes a::nat assumes ab: coprime a b and a: a 6= 0 and b: b 6= 0 shows ∃ x q1 q2 . x = u + q1 ∗ a ∧ x = v + q2 ∗ b proof− from bezout-add-strong-nat[OF a, of b] bezout-add-strong-nat[OF b, of a] obtain d1 x1 y1 d2 x2 y2 where dxy1 : d1 dvd a d1 dvd b a ∗ x1 = b ∗ y1 + d1 and dxy2 : d2 dvd b d2 dvd a b ∗ x2 = a ∗ y2 + d2 by blast then have d12 : d1 = 1 d2 =1 by (metis ab coprime-nat)+ let ?x = v ∗ a ∗ x1 + u ∗ b ∗ x2 let ?q1 = v ∗ x1 + u ∗ y2 let ?q2 = v ∗ y1 + u ∗ x2 from dxy2 (3 )[simplified d12 ] dxy1 (3 )[simplified d12 ] have ?x = u + ?q1 ∗ a ?x = v + ?q2 ∗ b by algebra+ thus ?thesis by blast qed

Primality lemma coprime-bezout-strong: fixes a::nat assumes coprime a b b 6= 1 shows ∃ x y. a ∗ x = b ∗ y + 1 by (metis assms bezout-nat gcd-nat.left-neutral) lemma bezout-prime: assumes p: prime p and pa: ¬ p dvd a shows ∃ x y. a∗x = Suc (p∗y) proof − have ap: coprime a p by (metis gcd.commute p pa prime-imp-coprime) moreover from p have p 6= 1 by auto ultimately have ∃ x y. a ∗ x = p ∗ y + 1 by (rule coprime-bezout-strong) then show ?thesis by simp

362 qed

48.4 Multiplicity and primality for natural numbers and in- tegers lemma prime-factors-gt-0-nat: p ∈ prime-factors x =⇒ p > (0 ::nat) by (simp add: in-prime-factors-imp-prime prime-gt-0-nat) lemma prime-factors-gt-0-int: p ∈ prime-factors x =⇒ p > (0 ::int) by (simp add: in-prime-factors-imp-prime prime-gt-0-int) lemma prime-factors-ge-0-int [elim]: fixes n :: int shows p ∈ prime-factors n =⇒ p ≥ 0 by (drule prime-factors-gt-0-int) simp lemma prod-mset-prime-factorization-int: fixes n :: int assumes n > 0 shows prod-mset (prime-factorization n) = n using assms by (simp add: prod-mset-prime-factorization) lemma prime-factorization-exists-nat: n > 0 =⇒ (∃ M . (∀ p::nat ∈ set-mset M . prime p) ∧ n = (Q i ∈# M . i)) using prime-factorization-exists[of n] by (auto simp: prime-def ) lemma prod-mset-prime-factorization-nat [simp]: (n::nat) > 0 =⇒ prod-mset (prime-factorization n) = n by (subst prod-mset-prime-factorization) simp-all lemma prime-factorization-nat: n > (0 ::nat) =⇒ n = (Q p ∈ prime-factors n. p ˆ multiplicity p n) by (simp add: prod-prime-factors) lemma prime-factorization-int: n > (0 ::int) =⇒ n = (Q p ∈ prime-factors n. p ˆ multiplicity p n) by (simp add: prod-prime-factors) lemma prime-factorization-unique-nat: fixes f :: nat ⇒ - assumes S-eq: S = {p. 0 < f p} and finite S and S: ∀ p∈S. prime p n = (Q p∈S. p ˆ f p) shows S = prime-factors n ∧ (∀ p. prime p −→ f p = multiplicity p n) using assms by (intro prime-factorization-unique 00) auto lemma prime-factorization-unique-int:

363 fixes f :: int ⇒ - assumes S-eq: S = {p. 0 < f p} and finite S and S: ∀ p∈S. prime p abs n = (Q p∈S. p ˆ f p) shows S = prime-factors n ∧ (∀ p. prime p −→ f p = multiplicity p n) using assms by (intro prime-factorization-unique 00) auto lemma prime-factors-characterization-nat: S = {p. 0 < f (p::nat)} =⇒ finite S =⇒ ∀ p∈S. prime p =⇒ n = (Q p∈S. p ˆ f p) =⇒ prime-factors n = S by (rule prime-factorization-unique-nat [THEN conjunct1 , symmetric]) lemma prime-factors-characterization 0-nat: finite {p. 0 < f (p::nat)} =⇒ (∀ p. 0 < f p −→ prime p) =⇒ prime-factors (Q p | 0 < f p. p ˆ f p) = {p. 0 < f p} by (rule prime-factors-characterization-nat) auto lemma prime-factors-characterization-int: S = {p. 0 < f (p::int)} =⇒ finite S =⇒ ∀ p∈S. prime p =⇒ abs n = (Q p∈S. p ˆ f p) =⇒ prime-factors n = S by (rule prime-factorization-unique-int [THEN conjunct1 , symmetric]) lemma abs-prod: abs (prod f A :: 0a :: linordered-idom) = prod (λx. abs (f x)) A by (cases finite A, induction A rule: finite-induct)(simp-all add: abs-mult) lemma primes-characterization 0-int [rule-format]: finite {p. p ≥ 0 ∧ 0 < f (p::int)} =⇒ ∀ p. 0 < f p −→ prime p =⇒ prime-factors (Q p | p ≥ 0 ∧ 0 < f p. p ˆ f p) = {p. p ≥ 0 ∧ 0 < f p} by (rule prime-factors-characterization-int)(auto simp: abs-prod prime-ge-0-int) lemma multiplicity-characterization-nat: S = {p. 0 < f (p::nat)} =⇒ finite S =⇒ ∀ p∈S. prime p =⇒ prime p =⇒ n = (Q p∈S. p ˆ f p) =⇒ multiplicity p n = f p by (frule prime-factorization-unique-nat [of S f n, THEN conjunct2 , rule-format, symmetric]) auto lemma multiplicity-characterization 0-nat: finite {p. 0 < f (p::nat)} −→ (∀ p. 0 < f p −→ prime p) −→ prime p −→ multiplicity p (Q p | 0 < f p. p ˆ f p) = f p by (intro impI , rule multiplicity-characterization-nat) auto lemma multiplicity-characterization-int: S = {p. 0 < f (p::int)} =⇒ finite S =⇒ ∀ p∈S. prime p =⇒ prime p =⇒ n = (Q p∈S. p ˆ f p) =⇒ multiplicity p n = f p by (frule prime-factorization-unique-int [of S f n, THEN conjunct2 , rule-format, symmetric])

364 (auto simp: abs-prod power-abs prime-ge-0-int intro!: prod.cong) lemma multiplicity-characterization 0-int [rule-format]: finite {p. p ≥ 0 ∧ 0 < f (p::int)} =⇒ (∀ p. 0 < f p −→ prime p) =⇒ prime p =⇒ multiplicity p (Q p | p ≥ 0 ∧ 0 < f p. p ˆ f p) = f p by (rule multiplicity-characterization-int)(auto simp: prime-ge-0-int) lemma multiplicity-one-nat [simp]: multiplicity p (Suc 0 ) = 0 unfolding One-nat-def [symmetric] by (rule multiplicity-one) lemma multiplicity-eq-nat: fixes x and y::nat assumes x > 0 y > 0 Vp. prime p =⇒ multiplicity p x = multiplicity p y shows x = y using multiplicity-eq-imp-eq[of x y] assms by simp lemma multiplicity-eq-int: fixes x y :: int assumes x > 0 y > 0 Vp. prime p =⇒ multiplicity p x = multiplicity p y shows x = y using multiplicity-eq-imp-eq[of x y] assms by simp lemma multiplicity-prod-prime-powers: assumes finite S Vx. x ∈ S =⇒ prime x prime p shows multiplicity p (Q p ∈ S. p ˆ f p) = (if p ∈ S then f p else 0 ) proof − define g where g = (λx. if x ∈ S then f x else 0 ) define A where A = Abs-multiset g have {x. g x > 0 } ⊆ S by (auto simp: g-def ) from finite-subset[OF this assms(1 )] have [simp]: g : multiset by (simp add: multiset-def ) from assms have count-A: count A x = g x for x unfolding A-def by simp have set-mset-A: set-mset A = {x∈S. f x > 0 } unfolding set-mset-def count-A by (auto simp: g-def ) with assms have prime: prime x if x ∈# A for x using that by auto from set-mset-A assms have (Q p ∈ S. p ˆ f p) = (Q p ∈ S. p ˆ g p) by (intro prod.cong)(auto simp: g-def ) also from set-mset-A assms have ... = (Q p ∈ set-mset A. p ˆ g p) by (intro prod.mono-neutral-right)(auto simp: g-def set-mset-A) also have ... = prod-mset A by (auto simp: prod-mset-multiplicity count-A set-mset-A intro!: prod.cong) also from assms have multiplicity p ... = sum-mset (image-mset (multiplicity p) A) by (subst prime-elem-multiplicity-prod-mset-distrib)(auto dest: prime) also from assms have image-mset (multiplicity p) A = image-mset (λx. if x = p then 1 else 0 ) A by (intro image-mset-cong)(auto simp: prime-multiplicity-other dest: prime)

365 also have sum-mset ... = (if p ∈ S then f p else 0 ) by (simp add: sum-mset-delta count-A g-def ) finally show ?thesis . qed lemma prime-factorization-prod-mset: assumes 0 ∈/# A shows prime-factorization (prod-mset A) = S #(image-mset prime-factorization A) using assms by (induct A)(auto simp add: prime-factorization-mult) lemma prime-factors-prod: assumes finite A and 0 ∈/ f ‘ A shows prime-factors (prod f A) = UNION A (prime-factors ◦ f ) using assms by (simp add: prod-unfold-prod-mset prime-factorization-prod-mset) lemma prime-factors-fact: prime-factors (fact n) = {p ∈ {2 ..n}. prime p} (is ?M = ?N ) proof (rule set-eqI ) fix p { fix m :: nat assume p ∈ prime-factors m then have prime p and p dvd m by auto moreover assume m > 0 ultimately have 2 ≤ p and p ≤ m by (auto intro: prime-ge-2-nat dest: dvd-imp-le) moreover assume m ≤ n ultimately have 2 ≤ p and p ≤ n by (auto intro: order-trans) } note ∗ = this show p ∈ ?M ←→ p ∈ ?N by (auto simp add: fact-prod prime-factors-prod Suc-le-eq dest!: prime-prime-factors intro: ∗) qed lemma prime-dvd-fact-iff : assumes prime p shows p dvd fact n ←→ p ≤ n using assms by (auto simp add: prime-factorization-subset-iff-dvd [symmetric] prime-factorization-prime prime-factors-fact prime-ge-2-nat) lemmas prime-imp-coprime-nat = prime-imp-coprime[where ? 0a = nat] lemmas prime-imp-coprime-int = prime-imp-coprime[where ? 0a = int] lemmas prime-dvd-mult-nat = prime-dvd-mult-iff [where ? 0a = nat] lemmas prime-dvd-mult-int = prime-dvd-mult-iff [where ? 0a = int] lemmas prime-dvd-mult-eq-nat = prime-dvd-mult-iff [where ? 0a = nat] lemmas prime-dvd-mult-eq-int = prime-dvd-mult-iff [where ? 0a = int]

366 lemmas prime-dvd-power-nat = prime-dvd-power[where ? 0a = nat] lemmas prime-dvd-power-int = prime-dvd-power[where ? 0a = int] lemmas prime-dvd-power-nat-iff = prime-dvd-power-iff [where ? 0a = nat] lemmas prime-dvd-power-int-iff = prime-dvd-power-iff [where ? 0a = int] lemmas prime-imp-power-coprime-nat = prime-imp-power-coprime[where ? 0a = nat] lemmas prime-imp-power-coprime-int = prime-imp-power-coprime[where ? 0a = int] lemmas primes-coprime-nat = primes-coprime[where ? 0a = nat] lemmas primes-coprime-int = primes-coprime[where ? 0a = nat] lemmas prime-divprod-pow-nat = prime-elem-divprod-pow[where ? 0a = nat] lemmas prime-exp = prime-elem-power-iff [where ? 0a = nat] end

49 Square roots of primes are irrational theory Sqrt imports Complex-Main ∼∼/src/HOL/Number-Theory/Primes begin The square root of any (including 2) is irrational. theorem sqrt-prime-irrational: assumes prime (p::nat) shows sqrt p ∈/ Q proof from hprime pi have p: 1 < p by (simp add: prime-nat-iff ) assume sqrt p ∈ Q then obtain m n :: nat where n: n 6= 0 and sqrt-rat: |sqrt p| = m / n and coprime m n by (rule Rats-abs-nat-div-natE) have eq: m2 = p ∗ n2 proof − from n and sqrt-rat have m = |sqrt p| ∗ n by simp then have m2 = (sqrt p)2 ∗ n2 by (auto simp add: power2-eq-square) also have (sqrt p)2 = p by simp also have ... ∗ n2 = p ∗ n2 by simp finally show ?thesis using of-nat-eq-iff by blast qed have p dvd m ∧ p dvd n proof from eq have p dvd m2 .. with hprime pi show p dvd m by (rule prime-dvd-power-nat) then obtain k where m = p ∗ k .. with eq have p ∗ n2 = p2 ∗ k 2 by (auto simp add: power2-eq-square ac-simps) with p have n2 = p ∗ k 2 by (simp add: power2-eq-square) then have p dvd n2 .. with hprime pi show p dvd n by (rule prime-dvd-power-nat)

367 qed then have p dvd gcd m n by simp with hcoprime m n i have p = 1 by simp with p show False by simp qed corollary sqrt-2-not-rat: sqrt 2 ∈/ Q using sqrt-prime-irrational[of 2 ] by simp

49.1 Variations

Here is an alternative version of the main proof, using mostly linear forward- reasoning. While this results in less top-down structure, it is probably closer to proofs seen in mathematics. theorem assumes prime (p::nat) shows sqrt p ∈/ Q proof from hprime pi have p: 1 < p by (simp add: prime-nat-iff ) assume sqrt p ∈ Q then obtain m n :: nat where n: n 6= 0 and sqrt-rat: |sqrt p| = m / n and coprime m n by (rule Rats-abs-nat-div-natE) from n and sqrt-rat have m = |sqrt p| ∗ n by simp then have m2 = (sqrt p)2 ∗ n2 by (auto simp add: power2-eq-square) also have (sqrt p)2 = p by simp also have ... ∗ n2 = p ∗ n2 by simp finally have eq: m2 = p ∗ n2 using of-nat-eq-iff by blast then have p dvd m2 .. with hprime pi have dvd-m: p dvd m by (rule prime-dvd-power-nat) then obtain k where m = p ∗ k .. with eq have p ∗ n2 = p2 ∗ k 2 by (auto simp add: power2-eq-square ac-simps) with p have n2 = p ∗ k 2 by (simp add: power2-eq-square) then have p dvd n2 .. with hprime pi have p dvd n by (rule prime-dvd-power-nat) with dvd-m have p dvd gcd m n by (rule gcd-greatest) with hcoprime m n i have p = 1 by simp with p show False by simp qed

Another old chestnut, which is a consequence of the irrationality of 2. lemma ∃ a b::real. a ∈/ Q ∧ b ∈/ Q ∧ a powr b ∈ Q (is ∃ a b. ?P a b) proof cases assume sqrt 2 powr sqrt 2 ∈ Q then have ?P (sqrt 2 )(sqrt 2 ) by (metis sqrt-2-not-rat) then show ?thesis by blast

368 next assume 1 : sqrt 2 powr sqrt 2 ∈/ Q have (sqrt 2 powr sqrt 2 ) powr sqrt 2 = 2 using powr-realpow [of - 2 ] by (simp add: powr-powr power2-eq-square [symmetric]) then have ?P (sqrt 2 powr sqrt 2 )(sqrt 2 ) by (metis 1 Rats-number-of sqrt-2-not-rat) then show ?thesis by blast qed end

50 Square roots of primes are irrational (script version) theory Sqrt-Script imports Complex-Main ∼∼/src/HOL/Number-Theory/Primes begin

Contrast this linear Isabelle/Isar script with Markus Wenzel’s more mathe- matical version.

50.1 Preliminaries lemma prime-nonzero: prime (p::nat) =⇒ p 6= 0 by (force simp add: prime-nat-iff ) lemma prime-dvd-other-side: (n::nat) ∗ n = p ∗ (k ∗ k) =⇒ prime p =⇒ p dvd n apply (subgoal-tac p dvd n ∗ n, blast dest: prime-dvd-mult-nat) apply auto done lemma reduction: prime (p::nat) =⇒ 0 < k =⇒ k ∗ k = p ∗ (j ∗ j ) =⇒ k < p ∗ j ∧ 0 < j apply (rule ccontr) apply (simp add: linorder-not-less) apply (erule disjE) apply (frule mult-le-mono, assumption) apply auto apply (force simp add: prime-nat-iff ) done lemma rearrange:(j ::nat) ∗ (p ∗ j ) = k ∗ k =⇒ k ∗ k = p ∗ (j ∗ j ) by (simp add: ac-simps) lemma prime-not-square: prime (p::nat) =⇒ (Vk. 0 < k =⇒ m ∗ m 6= p ∗ (k ∗ k))

369 apply (induct m rule: nat-less-induct) apply clarify apply (frule prime-dvd-other-side, assumption) apply (erule dvdE) apply (simp add: nat-mult-eq-cancel-disj prime-nonzero) apply (blast dest: rearrange reduction) done

50.2 Main theorem

The square root of any prime number (including 2 ) is irrational. theorem prime-sqrt-irrational: prime (p::nat) =⇒ x ∗ x = real p =⇒ 0 ≤ x =⇒ x ∈/ Q apply (rule notI ) apply (erule Rats-abs-nat-div-natE) apply (simp del: of-nat-mult add: abs-if divide-eq-eq prime-not-square of-nat-mult [symmetric]) done lemmas two-sqrt-irrational = prime-sqrt-irrational [OF two-is-prime-nat] end

51 Type of finite sets defined as a subtype of sets theory FSet imports Main begin

51.1 Definition of the type typedef 0a fset = {A :: 0a set. finite A} morphisms fset Abs-fset by auto setup-lifting type-definition-fset

51.2 Basic operations and type class instantiations instantiation fset :: (finite) finite begin instance by (standard; transfer; simp) end instantiation fset :: (type) {bounded-lattice-bot, distrib-lattice, minus} begin lift-definition bot-fset :: 0a fset is {} parametric empty-transfer by simp

370 lift-definition less-eq-fset :: 0a fset ⇒ 0a fset ⇒ bool is subset-eq parametric subset-transfer . definition less-fset :: 0a fset ⇒ 0a fset ⇒ bool where xs < ys ≡ xs ≤ ys ∧ xs 6= (ys:: 0a fset) lemma less-fset-transfer[transfer-rule]: includes lifting-syntax assumes [transfer-rule]: bi-unique A shows ((pcr-fset A) ===> (pcr-fset A) ===> op =) op ⊂ op < unfolding less-fset-def [abs-def ] psubset-eq[abs-def ] by transfer-prover lift-definition sup-fset :: 0a fset ⇒ 0a fset ⇒ 0a fset is union parametric union-transfer by simp lift-definition inf-fset :: 0a fset ⇒ 0a fset ⇒ 0a fset is inter parametric inter-transfer by simp lift-definition minus-fset :: 0a fset ⇒ 0a fset ⇒ 0a fset is minus parametric Diff-transfer by simp instance by (standard; transfer; auto)+ end abbreviation fempty :: 0a fset ({||}) where {||} ≡ bot abbreviation fsubset-eq :: 0a fset ⇒ 0a fset ⇒ bool (infix |⊆| 50 ) where xs |⊆| ys ≡ xs ≤ ys abbreviation fsubset :: 0a fset ⇒ 0a fset ⇒ bool (infix |⊂| 50 ) where xs |⊂| ys ≡ xs < ys abbreviation funion :: 0a fset ⇒ 0a fset ⇒ 0a fset (infixl |∪| 65 ) where xs |∪| ys ≡ sup xs ys abbreviation finter :: 0a fset ⇒ 0a fset ⇒ 0a fset (infixl |∩| 65 ) where xs |∩| ys ≡ inf xs ys abbreviation fminus :: 0a fset ⇒ 0a fset ⇒ 0a fset (infixl |−| 65 ) where xs |−| ys ≡ minus xs ys instantiation fset :: (equal) equal begin definition HOL.equal A B ←→ A |⊆| B ∧ B |⊆| A instance by intro-classes (auto simp add: equal-fset-def ) end instantiation fset :: (type) conditionally-complete-lattice

371 begin context includes lifting-syntax begin lemma right-total-Inf-fset-transfer: assumes [transfer-rule]: bi-unique A and [transfer-rule]: right-total A shows (rel-set (rel-set A) ===> rel-set A) (λS. if finite (T S ∩ Collect (Domainp A)) then T S ∩ Collect (Domainp A) else {}) (λS. if finite (Inf S) then Inf S else {}) by transfer-prover lemma Inf-fset-transfer: assumes [transfer-rule]: bi-unique A and [transfer-rule]: bi-total A shows (rel-set (rel-set A) ===> rel-set A)(λA. if finite (Inf A) then Inf A else {}) (λA. if finite (Inf A) then Inf A else {}) by transfer-prover lift-definition Inf-fset :: 0a fset set ⇒ 0a fset is λA. if finite (Inf A) then Inf A else {} parametric right-total-Inf-fset-transfer Inf-fset-transfer by simp lemma Sup-fset-transfer: assumes [transfer-rule]: bi-unique A shows (rel-set (rel-set A) ===> rel-set A)(λA. if finite (Sup A) then Sup A else {}) (λA. if finite (Sup A) then Sup A else {}) by transfer-prover lift-definition Sup-fset :: 0a fset set ⇒ 0a fset is λA. if finite (Sup A) then Sup A else {} parametric Sup-fset-transfer by simp lemma finite-Sup: ∃ z. finite z ∧ (∀ a. a ∈ X −→ a ≤ z) =⇒ finite (Sup X ) by (auto intro: finite-subset) lemma transfer-bdd-below[transfer-rule]: (rel-set (pcr-fset op =) ===> op =) bdd-below bdd-below by auto end instance proof fix x z :: 0a fset fix X :: 0a fset set { assume x ∈ X bdd-below X

372 then show Inf X |⊆| x by transfer auto next assume X 6= {} (Vx. x ∈ X =⇒ z |⊆| x) then show z |⊆| Inf X by transfer (clarsimp, blast) next assume x ∈ X bdd-above X then obtain z where x ∈ X (Vx. x ∈ X =⇒ x |⊆| z) by (auto simp: bdd-above-def ) then show x |⊆| Sup X by transfer (auto intro!: finite-Sup) next assume X 6= {} (Vx. x ∈ X =⇒ x |⊆| z) then show Sup X |⊆| z by transfer (clarsimp, blast) } qed end instantiation fset :: (finite) complete-lattice begin lift-definition top-fset :: 0a fset is UNIV parametric right-total-UNIV-transfer UNIV-transfer by simp instance by (standard; transfer; auto) end instantiation fset :: (finite) complete-boolean-algebra begin lift-definition uminus-fset :: 0a fset ⇒ 0a fset is uminus parametric right-total-Compl-transfer Compl-transfer by simp instance by (standard; transfer)(simp-all add: Diff-eq) end abbreviation fUNIV :: 0a::finite fset where fUNIV ≡ top abbreviation fuminus :: 0a::finite fset ⇒ 0a fset (|−| - [81 ] 80 ) where |−| x ≡ uminus x declare top-fset.rep-eq[simp]

51.3 Other operations lift-definition finsert :: 0a ⇒ 0a fset ⇒ 0a fset is insert parametric Lifting-Set.insert-transfer

373 by simp syntax -insert-fset :: args => 0a fset ({|(-)|}) translations {|x, xs|} == CONST finsert x {|xs|} {|x|} == CONST finsert x {||} lift-definition fmember :: 0a ⇒ 0a fset ⇒ bool (infix |∈| 50 ) is Set.member parametric member-transfer . abbreviation notin-fset :: 0a ⇒ 0a fset ⇒ bool (infix |∈|/ 50 ) where x |∈|/ S ≡ ¬ (x |∈| S) context includes lifting-syntax begin lift-definition ffilter :: ( 0a ⇒ bool) ⇒ 0a fset ⇒ 0a fset is Set.filter parametric Lifting-Set.filter-transfer unfolding Set.filter-def by simp lift-definition fPow :: 0a fset ⇒ 0a fset fset is Pow parametric Pow-transfer by (simp add: finite-subset) lift-definition fcard :: 0a fset ⇒ nat is card parametric card-transfer . lift-definition fimage :: ( 0a ⇒ 0b) ⇒ 0a fset ⇒ 0b fset (infixr |‘| 90 ) is image parametric image-transfer by simp lift-definition fthe-elem :: 0a fset ⇒ 0a is the-elem . lift-definition fbind :: 0a fset ⇒ ( 0a ⇒ 0b fset) ⇒ 0b fset is Set.bind parametric bind-transfer by (simp add: Set.bind-def ) lift-definition ffUnion :: 0a fset fset ⇒ 0a fset is Union parametric Union-transfer by simp lift-definition fBall :: 0a fset ⇒ ( 0a ⇒ bool) ⇒ bool is Ball parametric Ball-transfer . lift-definition fBex :: 0a fset ⇒ ( 0a ⇒ bool) ⇒ bool is Bex parametric Bex-transfer . lift-definition ffold :: ( 0a ⇒ 0b ⇒ 0b) ⇒ 0b ⇒ 0a fset ⇒ 0b is Finite-Set.fold . lift-definition fset-of-list :: 0a list ⇒ 0a fset is set by (rule finite-set)

374 51.4 Transferred lemmas from Set.thy lemmas fset-eqI = set-eqI [Transfer.transferred] lemmas fset-eq-iff [no-atp] = set-eq-iff [Transfer.transferred] lemmas fBallI [intro!] = ballI [Transfer.transferred] lemmas fbspec[dest?] = bspec[Transfer.transferred] lemmas fBallE[elim] = ballE[Transfer.transferred] lemmas fBexI [intro] = bexI [Transfer.transferred] lemmas rev-fBexI [intro?] = rev-bexI [Transfer.transferred] lemmas fBexCI = bexCI [Transfer.transferred] lemmas fBexE[elim!] = bexE[Transfer.transferred] lemmas fBall-triv[simp] = ball-triv[Transfer.transferred] lemmas fBex-triv[simp] = bex-triv[Transfer.transferred] lemmas fBex-triv-one-point1 [simp] = bex-triv-one-point1 [Transfer.transferred] lemmas fBex-triv-one-point2 [simp] = bex-triv-one-point2 [Transfer.transferred] lemmas fBex-one-point1 [simp] = bex-one-point1 [Transfer.transferred] lemmas fBex-one-point2 [simp] = bex-one-point2 [Transfer.transferred] lemmas fBall-one-point1 [simp] = ball-one-point1 [Transfer.transferred] lemmas fBall-one-point2 [simp] = ball-one-point2 [Transfer.transferred] lemmas fBall-conj-distrib = ball-conj-distrib[Transfer.transferred] lemmas fBex-disj-distrib = bex-disj-distrib[Transfer.transferred] lemmas fBall-cong = ball-cong[Transfer.transferred] lemmas fBex-cong = bex-cong[Transfer.transferred] lemmas fsubsetI [intro!] = subsetI [Transfer.transferred] lemmas fsubsetD[elim, intro?] = subsetD[Transfer.transferred] lemmas rev-fsubsetD[no-atp,intro?] = rev-subsetD[Transfer.transferred] lemmas fsubsetCE[no-atp,elim] = subsetCE[Transfer.transferred] lemmas fsubset-eq[no-atp] = subset-eq[Transfer.transferred] lemmas contra-fsubsetD[no-atp] = contra-subsetD[Transfer.transferred] lemmas fsubset-refl = subset-refl[Transfer.transferred] lemmas fsubset-trans = subset-trans[Transfer.transferred] lemmas fset-rev-mp = set-rev-mp[Transfer.transferred] lemmas fset-mp = set-mp[Transfer.transferred] lemmas fsubset-not-fsubset-eq[code] = subset-not-subset-eq[Transfer.transferred] lemmas eq-fmem-trans = eq-mem-trans[Transfer.transferred] lemmas fsubset-antisym[intro!] = subset-antisym[Transfer.transferred] lemmas fequalityD1 = equalityD1 [Transfer.transferred] lemmas fequalityD2 = equalityD2 [Transfer.transferred] lemmas fequalityE = equalityE[Transfer.transferred] lemmas fequalityCE[elim] = equalityCE[Transfer.transferred] lemmas eqfset-imp-iff = eqset-imp-iff [Transfer.transferred] lemmas eqfelem-imp-iff = eqelem-imp-iff [Transfer.transferred] lemmas fempty-iff [simp] = empty-iff [Transfer.transferred] lemmas fempty-fsubsetI [iff ] = empty-subsetI [Transfer.transferred] lemmas equalsffemptyI = equals0I [Transfer.transferred] lemmas equalsffemptyD = equals0D[Transfer.transferred] lemmas fBall-fempty[simp] = ball-empty[Transfer.transferred] lemmas fBex-fempty[simp] = bex-empty[Transfer.transferred] lemmas fPow-iff [iff ] = Pow-iff [Transfer.transferred] lemmas fPowI = PowI [Transfer.transferred]

375 lemmas fPowD = PowD[Transfer.transferred] lemmas fPow-bottom = Pow-bottom[Transfer.transferred] lemmas fPow-top = Pow-top[Transfer.transferred] lemmas fPow-not-fempty = Pow-not-empty[Transfer.transferred] lemmas finter-iff [simp] = Int-iff [Transfer.transferred] lemmas finterI [intro!] = IntI [Transfer.transferred] lemmas finterD1 = IntD1 [Transfer.transferred] lemmas finterD2 = IntD2 [Transfer.transferred] lemmas finterE[elim!] = IntE[Transfer.transferred] lemmas funion-iff [simp] = Un-iff [Transfer.transferred] lemmas funionI1 [elim?] = UnI1 [Transfer.transferred] lemmas funionI2 [elim?] = UnI2 [Transfer.transferred] lemmas funionCI [intro!] = UnCI [Transfer.transferred] lemmas funionE[elim!] = UnE[Transfer.transferred] lemmas fminus-iff [simp] = Diff-iff [Transfer.transferred] lemmas fminusI [intro!] = DiffI [Transfer.transferred] lemmas fminusD1 = DiffD1 [Transfer.transferred] lemmas fminusD2 = DiffD2 [Transfer.transferred] lemmas fminusE[elim!] = DiffE[Transfer.transferred] lemmas finsert-iff [simp] = insert-iff [Transfer.transferred] lemmas finsertI1 = insertI1 [Transfer.transferred] lemmas finsertI2 = insertI2 [Transfer.transferred] lemmas finsertE[elim!] = insertE[Transfer.transferred] lemmas finsertCI [intro!] = insertCI [Transfer.transferred] lemmas fsubset-finsert-iff = subset-insert-iff [Transfer.transferred] lemmas finsert-ident = insert-ident[Transfer.transferred] lemmas fsingletonI [intro!,no-atp] = singletonI [Transfer.transferred] lemmas fsingletonD[dest!,no-atp] = singletonD[Transfer.transferred] lemmas fsingleton-iff = singleton-iff [Transfer.transferred] lemmas fsingleton-inject[dest!] = singleton-inject[Transfer.transferred] lemmas fsingleton-finsert-inj-eq[iff ,no-atp] = singleton-insert-inj-eq[Transfer.transferred] lemmas fsingleton-finsert-inj-eq 0[iff ,no-atp] = singleton-insert-inj-eq 0[Transfer.transferred] lemmas fsubset-fsingletonD = subset-singletonD[Transfer.transferred] lemmas fminus-single-finsert = Diff-single-insert[Transfer.transferred] lemmas fdoubleton-eq-iff = doubleton-eq-iff [Transfer.transferred] lemmas funion-fsingleton-iff = Un-singleton-iff [Transfer.transferred] lemmas fsingleton-funion-iff = singleton-Un-iff [Transfer.transferred] lemmas fimage-eqI [simp, intro] = image-eqI [Transfer.transferred] lemmas fimageI = imageI [Transfer.transferred] lemmas rev-fimage-eqI = rev-image-eqI [Transfer.transferred] lemmas fimageE[elim!] = imageE[Transfer.transferred] lemmas Compr-fimage-eq = Compr-image-eq[Transfer.transferred] lemmas fimage-funion = image-Un[Transfer.transferred] lemmas fimage-iff = image-iff [Transfer.transferred] lemmas fimage-fsubset-iff [no-atp] = image-subset-iff [Transfer.transferred] lemmas fimage-fsubsetI = image-subsetI [Transfer.transferred] lemmas fimage-ident[simp] = image-ident[Transfer.transferred] lemmas if-split-fmem1 = if-split-mem1 [Transfer.transferred] lemmas if-split-fmem2 = if-split-mem2 [Transfer.transferred]

376 lemmas pfsubsetI [intro!,no-atp] = psubsetI [Transfer.transferred] lemmas pfsubsetE[elim!,no-atp] = psubsetE[Transfer.transferred] lemmas pfsubset-finsert-iff = psubset-insert-iff [Transfer.transferred] lemmas pfsubset-eq = psubset-eq[Transfer.transferred] lemmas pfsubset-imp-fsubset = psubset-imp-subset[Transfer.transferred] lemmas pfsubset-trans = psubset-trans[Transfer.transferred] lemmas pfsubsetD = psubsetD[Transfer.transferred] lemmas pfsubset-fsubset-trans = psubset-subset-trans[Transfer.transferred] lemmas fsubset-pfsubset-trans = subset-psubset-trans[Transfer.transferred] lemmas pfsubset-imp-ex-fmem = psubset-imp-ex-mem[Transfer.transferred] lemmas fimage-fPow-mono = image-Pow-mono[Transfer.transferred] lemmas fimage-fPow-surj = image-Pow-surj [Transfer.transferred] lemmas fsubset-finsertI = subset-insertI [Transfer.transferred] lemmas fsubset-finsertI2 = subset-insertI2 [Transfer.transferred] lemmas fsubset-finsert = subset-insert[Transfer.transferred] lemmas funion-upper1 = Un-upper1 [Transfer.transferred] lemmas funion-upper2 = Un-upper2 [Transfer.transferred] lemmas funion-least = Un-least[Transfer.transferred] lemmas finter-lower1 = Int-lower1 [Transfer.transferred] lemmas finter-lower2 = Int-lower2 [Transfer.transferred] lemmas finter-greatest = Int-greatest[Transfer.transferred] lemmas fminus-fsubset = Diff-subset[Transfer.transferred] lemmas fminus-fsubset-conv = Diff-subset-conv[Transfer.transferred] lemmas fsubset-fempty[simp] = subset-empty[Transfer.transferred] lemmas not-pfsubset-fempty[iff ] = not-psubset-empty[Transfer.transferred] lemmas finsert-is-funion = insert-is-Un[Transfer.transferred] lemmas finsert-not-fempty[simp] = insert-not-empty[Transfer.transferred] lemmas fempty-not-finsert = empty-not-insert[Transfer.transferred] lemmas finsert-absorb = insert-absorb[Transfer.transferred] lemmas finsert-absorb2 [simp] = insert-absorb2 [Transfer.transferred] lemmas finsert-commute = insert-commute[Transfer.transferred] lemmas finsert-fsubset[simp] = insert-subset[Transfer.transferred] lemmas finsert-inter-finsert[simp] = insert-inter-insert[Transfer.transferred] lemmas finsert-disjoint[simp,no-atp] = insert-disjoint[Transfer.transferred] lemmas disjoint-finsert[simp,no-atp] = disjoint-insert[Transfer.transferred] lemmas fimage-fempty[simp] = image-empty[Transfer.transferred] lemmas fimage-finsert[simp] = image-insert[Transfer.transferred] lemmas fimage-constant = image-constant[Transfer.transferred] lemmas fimage-constant-conv = image-constant-conv[Transfer.transferred] lemmas fimage-fimage = image-image[Transfer.transferred] lemmas finsert-fimage[simp] = insert-image[Transfer.transferred] lemmas fimage-is-fempty[iff ] = image-is-empty[Transfer.transferred] lemmas fempty-is-fimage[iff ] = empty-is-image[Transfer.transferred] lemmas fimage-cong = image-cong[Transfer.transferred] lemmas fimage-finter-fsubset = image-Int-subset[Transfer.transferred] lemmas fimage-fminus-fsubset = image-diff-subset[Transfer.transferred] lemmas finter-absorb = Int-absorb[Transfer.transferred] lemmas finter-left-absorb = Int-left-absorb[Transfer.transferred] lemmas finter-commute = Int-commute[Transfer.transferred]

377 lemmas finter-left-commute = Int-left-commute[Transfer.transferred] lemmas finter-assoc = Int-assoc[Transfer.transferred] lemmas finter-ac = Int-ac[Transfer.transferred] lemmas finter-absorb1 = Int-absorb1 [Transfer.transferred] lemmas finter-absorb2 = Int-absorb2 [Transfer.transferred] lemmas finter-fempty-left = Int-empty-left[Transfer.transferred] lemmas finter-fempty-right = Int-empty-right[Transfer.transferred] lemmas disjoint-iff-fnot-equal = disjoint-iff-not-equal[Transfer.transferred] lemmas finter-funion-distrib = Int-Un-distrib[Transfer.transferred] lemmas finter-funion-distrib2 = Int-Un-distrib2 [Transfer.transferred] lemmas finter-fsubset-iff [no-atp, simp] = Int-subset-iff [Transfer.transferred] lemmas funion-absorb = Un-absorb[Transfer.transferred] lemmas funion-left-absorb = Un-left-absorb[Transfer.transferred] lemmas funion-commute = Un-commute[Transfer.transferred] lemmas funion-left-commute = Un-left-commute[Transfer.transferred] lemmas funion-assoc = Un-assoc[Transfer.transferred] lemmas funion-ac = Un-ac[Transfer.transferred] lemmas funion-absorb1 = Un-absorb1 [Transfer.transferred] lemmas funion-absorb2 = Un-absorb2 [Transfer.transferred] lemmas funion-fempty-left = Un-empty-left[Transfer.transferred] lemmas funion-fempty-right = Un-empty-right[Transfer.transferred] lemmas funion-finsert-left[simp] = Un-insert-left[Transfer.transferred] lemmas funion-finsert-right[simp] = Un-insert-right[Transfer.transferred] lemmas finter-finsert-left = Int-insert-left[Transfer.transferred] lemmas finter-finsert-left-ifffempty[simp] = Int-insert-left-if0 [Transfer.transferred] lemmas finter-finsert-left-if1 [simp] = Int-insert-left-if1 [Transfer.transferred] lemmas finter-finsert-right = Int-insert-right[Transfer.transferred] lemmas finter-finsert-right-ifffempty[simp] = Int-insert-right-if0 [Transfer.transferred] lemmas finter-finsert-right-if1 [simp] = Int-insert-right-if1 [Transfer.transferred] lemmas funion-finter-distrib = Un-Int-distrib[Transfer.transferred] lemmas funion-finter-distrib2 = Un-Int-distrib2 [Transfer.transferred] lemmas funion-finter-crazy = Un-Int-crazy[Transfer.transferred] lemmas fsubset-funion-eq = subset-Un-eq[Transfer.transferred] lemmas funion-fempty[iff ] = Un-empty[Transfer.transferred] lemmas funion-fsubset-iff [no-atp, simp] = Un-subset-iff [Transfer.transferred] lemmas funion-fminus-finter = Un-Diff-Int[Transfer.transferred] lemmas fminus-finter2 = Diff-Int2 [Transfer.transferred] lemmas funion-finter-assoc-eq = Un-Int-assoc-eq[Transfer.transferred] lemmas fBall-funion = ball-Un[Transfer.transferred] lemmas fBex-funion = bex-Un[Transfer.transferred] lemmas fminus-eq-fempty-iff [simp,no-atp] = Diff-eq-empty-iff [Transfer.transferred] lemmas fminus-cancel[simp] = Diff-cancel[Transfer.transferred] lemmas fminus-idemp[simp] = Diff-idemp[Transfer.transferred] lemmas fminus-triv = Diff-triv[Transfer.transferred] lemmas fempty-fminus[simp] = empty-Diff [Transfer.transferred] lemmas fminus-fempty[simp] = Diff-empty[Transfer.transferred] lemmas fminus-finsertffempty[simp,no-atp] = Diff-insert0 [Transfer.transferred] lemmas fminus-finsert = Diff-insert[Transfer.transferred] lemmas fminus-finsert2 = Diff-insert2 [Transfer.transferred]

378 lemmas finsert-fminus-if = insert-Diff-if [Transfer.transferred] lemmas finsert-fminus1 [simp] = insert-Diff1 [Transfer.transferred] lemmas finsert-fminus-single[simp] = insert-Diff-single[Transfer.transferred] lemmas finsert-fminus = insert-Diff [Transfer.transferred] lemmas fminus-finsert-absorb = Diff-insert-absorb[Transfer.transferred] lemmas fminus-disjoint[simp] = Diff-disjoint[Transfer.transferred] lemmas fminus-partition = Diff-partition[Transfer.transferred] lemmas double-fminus = double-diff [Transfer.transferred] lemmas funion-fminus-cancel[simp] = Un-Diff-cancel[Transfer.transferred] lemmas funion-fminus-cancel2 [simp] = Un-Diff-cancel2 [Transfer.transferred] lemmas fminus-funion = Diff-Un[Transfer.transferred] lemmas fminus-finter = Diff-Int[Transfer.transferred] lemmas funion-fminus = Un-Diff [Transfer.transferred] lemmas finter-fminus = Int-Diff [Transfer.transferred] lemmas fminus-finter-distrib = Diff-Int-distrib[Transfer.transferred] lemmas fminus-finter-distrib2 = Diff-Int-distrib2 [Transfer.transferred] lemmas fUNIV-bool[no-atp] = UNIV-bool[Transfer.transferred] lemmas fPow-fempty[simp] = Pow-empty[Transfer.transferred] lemmas fPow-finsert = Pow-insert[Transfer.transferred] lemmas funion-fPow-fsubset = Un-Pow-subset[Transfer.transferred] lemmas fPow-finter-eq[simp] = Pow-Int-eq[Transfer.transferred] lemmas fset-eq-fsubset = set-eq-subset[Transfer.transferred] lemmas fsubset-iff [no-atp] = subset-iff [Transfer.transferred] lemmas fsubset-iff-pfsubset-eq = subset-iff-psubset-eq[Transfer.transferred] lemmas all-not-fin-conv[simp] = all-not-in-conv[Transfer.transferred] lemmas ex-fin-conv = ex-in-conv[Transfer.transferred] lemmas fimage-mono = image-mono[Transfer.transferred] lemmas fPow-mono = Pow-mono[Transfer.transferred] lemmas finsert-mono = insert-mono[Transfer.transferred] lemmas funion-mono = Un-mono[Transfer.transferred] lemmas finter-mono = Int-mono[Transfer.transferred] lemmas fminus-mono = Diff-mono[Transfer.transferred] lemmas fin-mono = in-mono[Transfer.transferred] lemmas fthe-felem-eq[simp] = the-elem-eq[Transfer.transferred] lemmas fLeast-mono = Least-mono[Transfer.transferred] lemmas fbind-fbind = bind-bind[Transfer.transferred] lemmas fempty-fbind[simp] = empty-bind[Transfer.transferred] lemmas nonfempty-fbind-const = nonempty-bind-const[Transfer.transferred] lemmas fbind-const = bind-const[Transfer.transferred] lemmas ffmember-filter[simp] = member-filter[Transfer.transferred] lemmas fequalityI = equalityI [Transfer.transferred] lemmas fset-of-list-simps[simp] = set-simps[Transfer.transferred] lemmas fset-of-list-append[simp] = set-append[Transfer.transferred] lemmas fset-of-list-rev[simp] = set-rev[Transfer.transferred] lemmas fset-of-list-map[simp] = set-map[Transfer.transferred]

379 51.5 Additional lemmas 51.5.1 fsingleton lemmas fsingletonE = fsingletonD [elim-format]

51.5.2 femepty lemma fempty-ffilter[simp]: ffilter (λ-. False) A = {||} by transfer auto lemma femptyE [elim!]: a |∈| {||} =⇒ P by simp

51.5.3 fset lemmas fset-simps[simp] = bot-fset.rep-eq finsert.rep-eq lemma finite-fset [simp]: shows finite (fset S) by transfer simp lemmas fset-cong = fset-inject lemma filter-fset [simp]: shows fset (ffilter P xs) = Collect P ∩ fset xs by transfer auto lemma notin-fset: x |∈|/ S ←→ x ∈/ fset S by (simp add: fmember.rep-eq) lemmas inter-fset[simp] = inf-fset.rep-eq lemmas union-fset[simp] = sup-fset.rep-eq lemmas minus-fset[simp] = minus-fset.rep-eq

51.5.4 ffilter lemma subset-ffilter: ffilter P A |⊆| ffilter Q A = (∀ x. x |∈| A −→ P x −→ Q x) by transfer auto lemma eq-ffilter: (ffilter P A = ffilter Q A) = (∀ x. x |∈| A −→ P x = Q x) by transfer auto lemma pfsubset-ffilter: (Vx. x |∈| A =⇒ P x =⇒ Q x) =⇒ (x |∈| A & ¬ P x & Q x) =⇒ ffilter P A |⊂| ffilter Q A unfolding less-fset-def by (auto simp add: subset-ffilter eq-ffilter)

380 51.5.5 fset-of-list lemma fset-of-list-filter[simp]: fset-of-list (filter P xs) = ffilter P (fset-of-list xs) by transfer (auto simp: Set.filter-def ) lemma fset-of-list-subset[intro]: set xs ⊆ set ys =⇒ fset-of-list xs |⊆| fset-of-list ys by transfer simp lemma fset-of-list-elem:(x |∈| fset-of-list xs) ←→ (x ∈ set xs) by transfer simp

51.5.6 finsert lemma set-finsert: assumes x |∈| A obtains B where A = finsert x B and x |∈|/ B using assms by transfer (metis Set.set-insert finite-insert) lemma mk-disjoint-finsert: a |∈| A =⇒ ∃ B. A = finsert a B ∧ a |∈|/ B by (rule exI [where x = A |−| {|a|}]) blast

51.5.7 fimage lemma subset-fimage-iff :(B |⊆| f |‘|A) = (∃ AA. AA |⊆| A ∧ B = f |‘|AA) by transfer (metis mem-Collect-eq rev-finite-subset subset-image-iff )

51.5.8 bounded quantification lemma bex-simps [simp, no-atp]: VAPQ. fBex A (λx. P x ∧ Q) = (fBex A P ∧ Q) VAPQ. fBex A (λx. P ∧ Q x) = (P ∧ fBex A Q) VP. fBex {||} P = False Va B P. fBex (finsert a B) P = (P a ∨ fBex B P) VA P f . fBex (f |‘| A) P = fBex A (λx. P (f x)) VAP. (¬ fBex A P) = fBall A (λx. ¬ P x) by auto lemma ball-simps [simp, no-atp]: VAPQ. fBall A (λx. P x ∨ Q) = (fBall A P ∨ Q) VAPQ. fBall A (λx. P ∨ Q x) = (P ∨ fBall A Q) VAPQ. fBall A (λx. P −→ Q x) = (P −→ fBall A Q) VAPQ. fBall A (λx. P x −→ Q) = (fBex A P −→ Q) VP. fBall {||} P = True Va B P. fBall (finsert a B) P = (P a ∧ fBall B P) VA P f . fBall (f |‘| A) P = fBall A (λx. P (f x)) VAP. (¬ fBall A P) = fBex A (λx. ¬ P x) by auto

381 lemma atomize-fBall: (Vx. x |∈| A ==> P x) == Trueprop (fBall A (λx. P x)) apply (simp only: atomize-all atomize-imp) apply (rule equal-intr-rule) by (transfer, simp)+ lemma fBall-mono[mono]: P ≤ Q =⇒ fBall S P ≤ fBall S Q by auto end

51.5.9 fcard lemma fcard-fempty: fcard {||} = 0 by transfer (rule card-empty) lemma fcard-finsert-disjoint: x |∈|/ A =⇒ fcard (finsert x A) = Suc (fcard A) by transfer (rule card-insert-disjoint) lemma fcard-finsert-if : fcard (finsert x A) = (if x |∈| A then fcard A else Suc (fcard A)) by transfer (rule card-insert-if ) lemma card-0-eq [simp, no-atp]: fcard A = 0 ←→ A = {||} by transfer (rule card-0-eq) lemma fcard-Suc-fminus1 : x |∈| A =⇒ Suc (fcard (A |−| {|x|})) = fcard A by transfer (rule card-Suc-Diff1 ) lemma fcard-fminus-fsingleton: x |∈| A =⇒ fcard (A |−| {|x|}) = fcard A − 1 by transfer (rule card-Diff-singleton) lemma fcard-fminus-fsingleton-if : fcard (A |−| {|x|}) = (if x |∈| A then fcard A − 1 else fcard A) by transfer (rule card-Diff-singleton-if ) lemma fcard-fminus-finsert[simp]: assumes a |∈| A and a |∈|/ B shows fcard (A |−| finsert a B) = fcard (A |−| B) − 1 using assms by transfer (rule card-Diff-insert) lemma fcard-finsert: fcard (finsert x A) = Suc (fcard (A |−| {|x|})) by transfer (rule card-insert)

382 lemma fcard-finsert-le: fcard A ≤ fcard (finsert x A) by transfer (rule card-insert-le) lemma fcard-mono: A |⊆| B =⇒ fcard A ≤ fcard B by transfer (rule card-mono) lemma fcard-seteq: A |⊆| B =⇒ fcard B ≤ fcard A =⇒ A = B by transfer (rule card-seteq) lemma pfsubset-fcard-mono: A |⊂| B =⇒ fcard A < fcard B by transfer (rule psubset-card-mono) lemma fcard-funion-finter: fcard A + fcard B = fcard (A |∪| B) + fcard (A |∩| B) by transfer (rule card-Un-Int) lemma fcard-funion-disjoint: A |∩| B = {||} =⇒ fcard (A |∪| B) = fcard A + fcard B by transfer (rule card-Un-disjoint) lemma fcard-funion-fsubset: B |⊆| A =⇒ fcard (A |−| B) = fcard A − fcard B by transfer (rule card-Diff-subset) lemma diff-fcard-le-fcard-fminus: fcard A − fcard B ≤ fcard(A |−| B) by transfer (rule diff-card-le-card-Diff ) lemma fcard-fminus1-less: x |∈| A =⇒ fcard (A |−| {|x|}) < fcard A by transfer (rule card-Diff1-less) lemma fcard-fminus2-less: x |∈| A =⇒ y |∈| A =⇒ fcard (A |−| {|x|} |−| {|y|}) < fcard A by transfer (rule card-Diff2-less) lemma fcard-fminus1-le: fcard (A |−| {|x|}) ≤ fcard A by transfer (rule card-Diff1-le) lemma fcard-pfsubset: A |⊆| B =⇒ fcard A < fcard B =⇒ A < B by transfer (rule card-psubset)

51.5.10 ffold context comp-fun-commute begin lemmas ffold-empty[simp] = fold-empty[Transfer.transferred]

383 lemma ffold-finsert [simp]: assumes x |∈|/ A shows ffold f z (finsert x A) = f x (ffold f z A) using assms by (transfer fixing: f )(rule fold-insert)

lemma ffold-fun-left-comm: f x (ffold f z A) = ffold f (f x z) A by (transfer fixing: f )(rule fold-fun-left-comm)

lemma ffold-finsert2 : x |∈|/ A =⇒ ffold f z (finsert x A) = ffold f (f x z) A by (transfer fixing: f )(rule fold-insert2 )

lemma ffold-rec: assumes x |∈| A shows ffold f z A = f x (ffold f z (A |−| {|x|})) using assms by (transfer fixing: f )(rule fold-rec)

lemma ffold-finsert-fremove: ffold f z (finsert x A) = f x (ffold f z (A |−| {|x|})) by (transfer fixing: f )(rule fold-insert-remove) end lemma ffold-fimage: assumes inj-on g (fset A) shows ffold f z (g |‘| A) = ffold (f ◦ g) z A using assms by transfer 0 (rule fold-image) lemma ffold-cong: assumes comp-fun-commute f comp-fun-commute g Vx. x |∈| A =⇒ f x = g x and s = t and A = B shows ffold f s A = ffold g t B using assms by transfer (metis Finite-Set.fold-cong) context comp-fun-idem begin

lemma ffold-finsert-idem: ffold f z (finsert x A) = f x (ffold f z A) by (transfer fixing: f )(rule fold-insert-idem)

declare ffold-finsert [simp del] ffold-finsert-idem [simp]

lemma ffold-finsert-idem2 : ffold f z (finsert x A) = ffold f (f x z) A by (transfer fixing: f )(rule fold-insert-idem2 ) end

384 51.6 Choice in fsets lemma fset-choice: assumes ∀ x. x |∈| A −→ (∃ y. P x y) shows ∃ f . ∀ x. x |∈| A −→ P x (f x) using assms by transfer metis

51.7 Induction and Cases rules for fsets lemma fset-exhaust [case-names empty insert, cases type: fset]: assumes fempty-case: S = {||} =⇒ P and finsert-case: Vx S 0. S = finsert x S 0 =⇒ P shows P using assms by transfer blast lemma fset-induct [case-names empty insert]: assumes fempty-case: P {||} and finsert-case: Vx S. PS =⇒ P (finsert x S) shows PS proof −

note Domainp-forall-transfer[transfer-rule] show ?thesis using assms by transfer (auto intro: finite-induct) qed lemma fset-induct-stronger [case-names empty insert, induct type: fset]: assumes empty-fset-case: P {||} and insert-fset-case: Vx S. [[x |∈|/ S; PS]] =⇒ P (finsert x S) shows PS proof −

note Domainp-forall-transfer[transfer-rule] show ?thesis using assms by transfer (auto intro: finite-induct) qed lemma fset-card-induct: assumes empty-fset-case: P {||} and card-fset-Suc-case: VST . Suc (fcard S) = (fcard T ) =⇒ PS =⇒ PT shows PS proof (induct S) case empty show P {||} by (rule empty-fset-case) next case (insert x S) have h: PS by fact have x |∈|/ S by fact then have Suc (fcard S) = fcard (finsert x S) by transfer auto

385 then show P (finsert x S) using h card-fset-Suc-case by simp qed lemma fset-strong-cases: obtains xs = {||} | ys x where x |∈|/ ys and xs = finsert x ys by transfer blast lemma fset-induct2 : P {||} {||} =⇒ (Vx xs. x |∈|/ xs =⇒ P (finsert x xs) {||}) =⇒ (Vy ys. y |∈|/ ys =⇒ P {||} (finsert y ys)) =⇒ (Vx xs y ys. [[P xs ys; x |∈|/ xs; y |∈|/ ys]] =⇒ P (finsert x xs)(finsert y ys)) =⇒ P xsa ysa apply (induct xsa arbitrary: ysa) apply (induct-tac x rule: fset-induct-stronger) apply simp-all apply (induct-tac xa rule: fset-induct-stronger) apply simp-all done

51.8 Setup for Lifting/Transfer 51.8.1 Relator and predicator properties lift-definition rel-fset :: ( 0a ⇒ 0b ⇒ bool) ⇒ 0a fset ⇒ 0b fset ⇒ bool is rel-set parametric rel-set-transfer . lemma rel-fset-alt-def : rel-fset R = (λAB. (∀ x.∃ y. x|∈|A −→ y|∈|B ∧ R x y) ∧ (∀ y. ∃ x. y|∈|B −→ x|∈|A ∧ R x y)) apply (rule ext)+ apply transfer 0 apply (subst rel-set-def [unfolded fun-eq-iff ]) by blast lemma finite-rel-set: assumes fin: finite X finite Z assumes R-S: rel-set (R OO S) XZ shows ∃ Y . finite Y ∧ rel-set R X Y ∧ rel-set S Y Z proof − obtain f where f : ∀ x∈X . R x (f x) ∧ (∃ z∈Z . S (f x) z) apply atomize-elim apply (subst bchoice-iff [symmetric]) using R-S[unfolded rel-set-def OO-def ] by blast

obtain g where g: ∀ z∈Z . S (g z) z ∧ (∃ x∈X . R x (g z)) apply atomize-elim apply (subst bchoice-iff [symmetric]) using R-S[unfolded rel-set-def OO-def ] by blast

386 let ?Y = f ‘ X ∪ g ‘ Z have finite ?Y by (simp add: fin) moreover have rel-set R X ?Y unfolding rel-set-def using f g by clarsimp blast moreover have rel-set S ?Y Z unfolding rel-set-def using f g by clarsimp blast ultimately show ?thesis by metis qed

51.8.2 Transfer rules for the Transfer package

Unconditional transfer rules context includes lifting-syntax begin lemmas fempty-transfer [transfer-rule] = empty-transfer[Transfer.transferred] lemma finsert-transfer [transfer-rule]: (A ===> rel-fset A ===> rel-fset A) finsert finsert unfolding rel-fun-def rel-fset-alt-def by blast lemma funion-transfer [transfer-rule]: (rel-fset A ===> rel-fset A ===> rel-fset A) funion funion unfolding rel-fun-def rel-fset-alt-def by blast lemma ffUnion-transfer [transfer-rule]: (rel-fset (rel-fset A) ===> rel-fset A) ffUnion ffUnion unfolding rel-fun-def rel-fset-alt-def by transfer (simp, fast) lemma fimage-transfer [transfer-rule]: ((A ===> B) ===> rel-fset A ===> rel-fset B) fimage fimage unfolding rel-fun-def rel-fset-alt-def by simp blast lemma fBall-transfer [transfer-rule]: (rel-fset A ===> (A ===> op =) ===> op =) fBall fBall unfolding rel-fset-alt-def rel-fun-def by blast lemma fBex-transfer [transfer-rule]: (rel-fset A ===> (A ===> op =) ===> op =) fBex fBex unfolding rel-fset-alt-def rel-fun-def by blast lemma fPow-transfer [transfer-rule]: (rel-fset A ===> rel-fset (rel-fset A)) fPow fPow unfolding rel-fun-def using Pow-transfer[unfolded rel-fun-def , rule-format, Transfer.transferred]

387 by blast lemma rel-fset-transfer [transfer-rule]: ((A ===> B ===> op =) ===> rel-fset A ===> rel-fset B ===> op =) rel-fset rel-fset unfolding rel-fun-def using rel-set-transfer[unfolded rel-fun-def ,rule-format, Transfer.transferred, where A = A and B = B] by simp lemma bind-transfer [transfer-rule]: (rel-fset A ===> (A ===> rel-fset B) ===> rel-fset B) fbind fbind unfolding rel-fun-def using bind-transfer[unfolded rel-fun-def , rule-format, Transfer.transferred] by blast

Rules requiring bi-unique, bi-total or right-total relations lemma fmember-transfer [transfer-rule]: assumes bi-unique A shows (A ===> rel-fset A ===> op =) (op |∈|)(op |∈|) using assms unfolding rel-fun-def rel-fset-alt-def bi-unique-def by metis lemma finter-transfer [transfer-rule]: assumes bi-unique A shows (rel-fset A ===> rel-fset A ===> rel-fset A) finter finter using assms unfolding rel-fun-def using inter-transfer[unfolded rel-fun-def , rule-format, Transfer.transferred] by blast lemma fminus-transfer [transfer-rule]: assumes bi-unique A shows (rel-fset A ===> rel-fset A ===> rel-fset A)(op |−|)(op |−|) using assms unfolding rel-fun-def using Diff-transfer[unfolded rel-fun-def , rule-format, Transfer.transferred] by blast lemma fsubset-transfer [transfer-rule]: assumes bi-unique A shows (rel-fset A ===> rel-fset A ===> op =) (op |⊆|)(op |⊆|) using assms unfolding rel-fun-def using subset-transfer[unfolded rel-fun-def , rule-format, Transfer.transferred] by blast lemma fSup-transfer [transfer-rule]: bi-unique A =⇒ (rel-set (rel-fset A) ===> rel-fset A) Sup Sup unfolding rel-fun-def apply clarify apply transfer 0 using Sup-fset-transfer[unfolded rel-fun-def ] by blast

388 lemma fInf-transfer [transfer-rule]: assumes bi-unique A and bi-total A shows (rel-set (rel-fset A) ===> rel-fset A) Inf Inf using assms unfolding rel-fun-def apply clarify apply transfer 0 using Inf-fset-transfer[unfolded rel-fun-def ] by blast lemma ffilter-transfer [transfer-rule]: assumes bi-unique A shows ((A ===> op=) ===> rel-fset A ===> rel-fset A) ffilter ffilter using assms unfolding rel-fun-def using Lifting-Set.filter-transfer[unfolded rel-fun-def , rule-format, Transfer.transferred] by blast lemma card-transfer [transfer-rule]: bi-unique A =⇒ (rel-fset A ===> op =) fcard fcard unfolding rel-fun-def using card-transfer[unfolded rel-fun-def , rule-format, Transfer.transferred] by blast end lifting-update fset.lifting lifting-forget fset.lifting

51.9 BNF setup context includes fset.lifting begin lemma rel-fset-alt: rel-fset R a b ←→ (∀ t ∈ fset a. ∃ u ∈ fset b. R t u) ∧ (∀ t ∈ fset b. ∃ u ∈ fset a. R u t) by transfer (simp add: rel-set-def ) lemma fset-to-fset: finite A =⇒ fset (the-inv fset A) = A apply (rule f-the-inv-into-f [unfolded inj-on-def ]) apply (simp add: fset-inject) apply (rule range-eqI Abs-fset-inverse[symmetric] CollectI )+ . lemma rel-fset-aux: (∀ t ∈ fset a. ∃ u ∈ fset b. R t u) ∧ (∀ u ∈ fset b. ∃ t ∈ fset a. R t u) ←→ ((BNF-Def .Grp {a. fset a ⊆ {(a, b). R a b}} (fimage fst))−1−1 OO

389 BNF-Def .Grp {a. fset a ⊆ {(a, b). R a b}} (fimage snd)) a b (is ?L = ?R) proof assume ?L define R 0 where R 0 = the-inv fset (Collect (case-prod R) ∩ (fset a × fset b)) (is - = the-inv fset ?L 0) have finite ?L 0 by (intro finite-Int[OF disjI2 ] finite-cartesian-product)(transfer, simp)+ hence ∗: fset R 0 = ?L 0 unfolding R 0-def by (intro fset-to-fset) show ?R unfolding Grp-def relcompp.simps conversep.simps proof (intro CollectI case-prodI exI [of - a] exI [of - b] exI [of - R 0] conjI refl) 0 from ∗ show a = fimage fst R using conjunct1 [OF h?Li] by (transfer, auto simp add: image-def Int-def split: prod.splits) 0 from ∗ show b = fimage snd R using conjunct2 [OF h?Li] by (transfer, auto simp add: image-def Int-def split: prod.splits) qed (auto simp add: ∗) next assume ?R thus ?L unfolding Grp-def relcompp.simps conversep.simps apply (simp add: subset-eq Ball-def ) apply (rule conjI ) apply (transfer, clarsimp, metis snd-conv) by (transfer, clarsimp, metis fst-conv) qed bnf 0a fset map: fimage sets: fset bd: natLeq wits: {||} rel: rel-fset apply − apply transfer 0 apply simp apply transfer 0 apply force apply transfer apply force apply transfer 0 apply force apply (rule natLeq-card-order) apply (rule natLeq-cinfinite) apply transfer apply (metis ordLess-imp-ordLeq finite-iff-ordLess-natLeq) apply (fastforce simp: rel-fset-alt) apply (simp add: Grp-def relcompp.simps conversep.simps fun-eq-iff rel-fset-alt rel-fset-aux[unfolded OO-Grp-alt]) apply transfer apply simp done lemma rel-fset-fset: rel-set χ (fset A1 )(fset A2 ) = rel-fset χ A1 A2 by transfer (rule refl) end lemmas [simp] = fset.map-comp fset.map-id fset.set-map

390 51.10 Size setup context includes fset.lifting begin lift-definition size-fset :: ( 0a ⇒ nat) ⇒ 0a fset ⇒ nat is λf . sum (Suc ◦ f ) . end instantiation fset :: (type) size begin definition size-fset where size-fset-overloaded-def : size-fset = FSet.size-fset (λ-. 0 ) instance .. end lemmas size-fset-simps[simp] = size-fset-def [THEN meta-eq-to-obj-eq, THEN fun-cong, THEN fun-cong, unfolded map-fun-def comp-def id-apply] lemmas size-fset-overloaded-simps[simp] = size-fset-simps[of λ-. 0 , unfolded add-0-left add-0-right, folded size-fset-overloaded-def ] lemma fset-size-o-map: inj f =⇒ size-fset g ◦ fimage f = size-fset (g ◦ f ) apply (subst fun-eq-iff ) including fset.lifting by transfer (auto intro: sum.reindex-cong subset-inj-on) setup h BNF-LFP-Size.register-size-global @{type-name fset} @{const-name size-fset} @{thm size-fset-overloaded-def } @{thms size-fset-simps size-fset-overloaded-simps} @{thms fset-size-o-map} i lifting-update fset.lifting lifting-forget fset.lifting

51.11 Advanced relator customization lemma rel-set-rel-sum[simp]: rel-set (rel-sum χ ϕ) A1 A2 ←→ rel-set χ (Inl −‘ A1 )(Inl −‘ A2 ) ∧ rel-set ϕ (Inr −‘ A1 )(Inr −‘ A2 ) (is ?L ←→ ?Rl ∧ ?Rr) proof safe assume L: ?L show ?Rl unfolding rel-set-def Bex-def vimage-eq proof safe fix l1 assume Inl l1 ∈ A1 then obtain a2 where a2 : a2 ∈ A2 and rel-sum χ ϕ (Inl l1 ) a2 using L unfolding rel-set-def by auto then obtain l2 where a2 = Inl l2 ∧ χ l1 l2 by (cases a2 , auto) thus ∃ l2 . Inl l2 ∈ A2 ∧ χ l1 l2 using a2 by auto next fix l2 assume Inl l2 ∈ A2 then obtain a1 where a1 : a1 ∈ A1 and rel-sum χ ϕ a1 (Inl l2 )

391 using L unfolding rel-set-def by auto then obtain l1 where a1 = Inl l1 ∧ χ l1 l2 by (cases a1 , auto) thus ∃ l1 . Inl l1 ∈ A1 ∧ χ l1 l2 using a1 by auto qed show ?Rr unfolding rel-set-def Bex-def vimage-eq proof safe fix r1 assume Inr r1 ∈ A1 then obtain a2 where a2 : a2 ∈ A2 and rel-sum χ ϕ (Inr r1 ) a2 using L unfolding rel-set-def by auto then obtain r2 where a2 = Inr r2 ∧ ϕ r1 r2 by (cases a2 , auto) thus ∃ r2 . Inr r2 ∈ A2 ∧ ϕ r1 r2 using a2 by auto next fix r2 assume Inr r2 ∈ A2 then obtain a1 where a1 : a1 ∈ A1 and rel-sum χ ϕ a1 (Inr r2 ) using L unfolding rel-set-def by auto then obtain r1 where a1 = Inr r1 ∧ ϕ r1 r2 by (cases a1 , auto) thus ∃ r1 . Inr r1 ∈ A1 ∧ ϕ r1 r2 using a1 by auto qed next assume Rl: ?Rl and Rr: ?Rr show ?L unfolding rel-set-def Bex-def vimage-eq proof safe fix a1 assume a1 : a1 ∈ A1 show ∃ a2 . a2 ∈ A2 ∧ rel-sum χ ϕ a1 a2 proof(cases a1 ) case (Inl l1 ) then obtain l2 where Inl l2 ∈ A2 ∧ χ l1 l2 using Rl a1 unfolding rel-set-def by blast thus ?thesis unfolding Inl by auto next case (Inr r1 ) then obtain r2 where Inr r2 ∈ A2 ∧ ϕ r1 r2 using Rr a1 unfolding rel-set-def by blast thus ?thesis unfolding Inr by auto qed next fix a2 assume a2 : a2 ∈ A2 show ∃ a1 . a1 ∈ A1 ∧ rel-sum χ ϕ a1 a2 proof(cases a2 ) case (Inl l2 ) then obtain l1 where Inl l1 ∈ A1 ∧ χ l1 l2 using Rl a2 unfolding rel-set-def by blast thus ?thesis unfolding Inl by auto next case (Inr r2 ) then obtain r1 where Inr r1 ∈ A1 ∧ ϕ r1 r2 using Rr a2 unfolding rel-set-def by blast thus ?thesis unfolding Inr by auto qed qed qed

51.12 Quickcheck setup

Setup adapted from sets.

392 notation Quickcheck-Exhaustive.orelse (infixr orelse 55 ) definition (in term-syntax)[code-unfold]: valterm-femptyset = Code-Evaluation.valtermify ({||} :: ( 0a :: typerep) fset) definition (in term-syntax)[code-unfold]: valtermify-finsert x s = Code-Evaluation.valtermify finsert {·} (x :: ( 0a :: typerep ∗ -)) {·} s instantiation fset :: (exhaustive) exhaustive begin fun exhaustive-fset where exhaustive-fset f i = (if i = 0 then None else (f {||} orelse exhaustive-fset (λA. f A orelse Quickcheck-Exhaustive.exhaustive (λx. if x |∈| A then None else f (finsert x A)) (i − 1 )) (i − 1 ))) instance .. end instantiation fset :: (full-exhaustive) full-exhaustive begin fun full-exhaustive-fset where full-exhaustive-fset f i = (if i = 0 then None else (f valterm-femptyset orelse full-exhaustive-fset (λA. f A orelse Quickcheck-Exhaustive.full-exhaustive (λx. if fst x |∈| fst A then None else f (valtermify-finsert x A)) (i − 1 )) (i − 1 ))) instance .. end no-notation Quickcheck-Exhaustive.orelse (infixr orelse 55 ) notation scomp (infixl ◦→ 60 ) instantiation fset :: (random) random begin fun random-aux-fset :: natural ⇒ natural ⇒ natural × natural ⇒ ( 0a fset × (unit ⇒ term)) × natural × natural where random-aux-fset 0 j = Quickcheck-Random.collapse (Random.select-weight [(1 , Pair valterm-femptyset)]) | random-aux-fset (Code-Numeral.Suc i) j = Quickcheck-Random.collapse (Random.select-weight [(1 , Pair valterm-femptyset), (Code-Numeral.Suc i, Quickcheck-Random.random j ◦→ (λx. random-aux-fset i j ◦→ (λs. Pair

393 (valtermify-finsert x s))))]) lemma [code]: random-aux-fset i j = Quickcheck-Random.collapse (Random.select-weight [(1 , Pair valterm-femptyset), (i, Quickcheck-Random.random j ◦→ (λx. random-aux-fset (i − 1 ) j ◦→ (λs. Pair (valtermify-finsert x s))))]) proof (induct i rule: natural.induct) case zero show ?case by (subst select-weight-drop-zero[symmetric]) (simp add: less-natural-def ) next case (Suc i) show ?case by (simp only: random-aux-fset.simps Suc-natural-minus-one) qed definition random-fset i = random-aux-fset i i instance .. end no-notation scomp (infixl ◦→ 60 ) end theory Transfer-Debug imports Main ∼∼/src/HOL/Library/FSet begin

context includes fset.lifting begin

51.13 1. A missing transfer rule declare fmember.transfer[transfer-rule del] fmember-transfer[transfer-rule del] lemma (A |⊆| B) = fBall A (λx. x |∈| B) apply transfer oops lemma (A |⊆| B) = fBall A (λx. x |∈| B) apply transfer-start

394 apply transfer-step oops lemma [transfer-rule]: bi-unique A =⇒ rel-fun A (rel-fun (pcr-fset A) op =) op ∈ op |∈| by (rule fmember.transfer) lemma (A |⊆| B) = fBall A (λx. x |∈| B) apply transfer-start apply transfer-step apply transfer-step+ apply transfer-end by blast lemma (A |⊆| B) = fBall A (λx. x |∈| B) by transfer blast

51.14 2. Unwanted instantiation of a transfer relation vari- able lemma finite (UNIV :: 0a::finite fset set) apply transfer oops lemma finite (UNIV :: 0a::finite fset set) apply transfer-start apply transfer-step back back apply transfer-step apply transfer-end by auto lemma finite (UNIV :: 0a::finite fset set) proof − note right-total-UNIV-transfer[transfer-rule] show ?thesis by transfer auto qed end lifting-forget fset.lifting

395 declare fmember-transfer[transfer-rule] end

52 Using the transfer method between nat and int theory Transfer-Int-Nat imports GCD begin

52.1 Correspondence relation definition ZN :: int ⇒ nat ⇒ bool where ZN = (λz n. z = of-nat n)

52.2 Transfer domain rules lemma Domainp-ZN [transfer-domain-rule]: Domainp ZN = (λx. x ≥ 0 ) unfolding ZN-def Domainp-iff [abs-def ] by (auto intro: zero-le-imp-eq-int)

52.3 Transfer rules context includes lifting-syntax begin lemma bi-unique-ZN [transfer-rule]: bi-unique ZN unfolding ZN-def bi-unique-def by simp lemma right-total-ZN [transfer-rule]: right-total ZN unfolding ZN-def right-total-def by simp lemma ZN-0 [transfer-rule]: ZN 0 0 unfolding ZN-def by simp lemma ZN-1 [transfer-rule]: ZN 1 1 unfolding ZN-def by simp lemma ZN-add [transfer-rule]: (ZN ===> ZN ===> ZN )(op +) (op +) unfolding rel-fun-def ZN-def by simp lemma ZN-mult [transfer-rule]: (ZN ===> ZN ===> ZN )(op ∗)(op ∗) unfolding rel-fun-def ZN-def by (simp add: of-nat-mult) lemma ZN-diff [transfer-rule]: (ZN ===> ZN ===> ZN ) tsub (op −) unfolding rel-fun-def ZN-def tsub-def by (simp add: of-nat-diff ) lemma ZN-power [transfer-rule]: (ZN ===> op = ===> ZN )(op ˆ)(op ˆ) unfolding rel-fun-def ZN-def by (simp add: of-nat-power)

396 lemma ZN-nat-id [transfer-rule]: (ZN ===> op =) nat id unfolding rel-fun-def ZN-def by simp lemma ZN-id-int [transfer-rule]: (ZN ===> op =) id int unfolding rel-fun-def ZN-def by simp lemma ZN-All [transfer-rule]: ((ZN ===> op =) ===> op =) (Ball {0 ..}) All unfolding rel-fun-def ZN-def by (auto dest: zero-le-imp-eq-int) lemma ZN-transfer-forall [transfer-rule]: ((ZN ===> op =) ===> op =) (transfer-bforall (λx. 0 ≤ x)) transfer-forall unfolding transfer-forall-def transfer-bforall-def unfolding rel-fun-def ZN-def by (auto dest: zero-le-imp-eq-int) lemma ZN-Ex [transfer-rule]: ((ZN ===> op =) ===> op =) (Bex {0 ..}) Ex unfolding rel-fun-def ZN-def Bex-def atLeast-iff by (metis zero-le-imp-eq-int of-nat-0-le-iff ) lemma ZN-le [transfer-rule]: (ZN ===> ZN ===> op =) (op ≤)(op ≤) unfolding rel-fun-def ZN-def by simp lemma ZN-less [transfer-rule]: (ZN ===> ZN ===> op =) (op <)(op <) unfolding rel-fun-def ZN-def by simp lemma ZN-eq [transfer-rule]: (ZN ===> ZN ===> op =) (op =) (op =) unfolding rel-fun-def ZN-def by simp lemma ZN-Suc [transfer-rule]: (ZN ===> ZN )(λx. x + 1 ) Suc unfolding rel-fun-def ZN-def by simp lemma ZN-numeral [transfer-rule]: (op = ===> ZN ) numeral numeral unfolding rel-fun-def ZN-def by simp lemma ZN-dvd [transfer-rule]: (ZN ===> ZN ===> op =) (op dvd)(op dvd) unfolding rel-fun-def ZN-def by (simp add: zdvd-int) lemma ZN-div [transfer-rule]: (ZN ===> ZN ===> ZN )(op div)(op div) unfolding rel-fun-def ZN-def by (simp add: zdiv-int) lemma ZN-mod [transfer-rule]: (ZN ===> ZN ===> ZN )(op mod)(op mod) unfolding rel-fun-def ZN-def by (simp add: zmod-int) lemma ZN-gcd [transfer-rule]: (ZN ===> ZN ===> ZN ) gcd gcd unfolding rel-fun-def ZN-def by (simp add: transfer-int-nat-gcd) lemma ZN-atMost [transfer-rule]: (ZN ===> rel-set ZN )(atLeastAtMost 0 ) atMost

397 unfolding rel-fun-def ZN-def rel-set-def by (clarsimp simp add: Bex-def , arith) lemma ZN-atLeastAtMost [transfer-rule]: (ZN ===> ZN ===> rel-set ZN ) atLeastAtMost atLeastAtMost unfolding rel-fun-def ZN-def rel-set-def by (clarsimp simp add: Bex-def , arith) lemma ZN-sum [transfer-rule]: bi-unique A =⇒ ((A ===> ZN ) ===> rel-set A ===> ZN ) sum sum apply (intro rel-funI ) apply (erule (1 ) bi-unique-rel-set-lemma) apply (simp add: sum.reindex int-sum ZN-def rel-fun-def ) apply (rule sum.cong) apply simp-all done

For derived operations, we can use the transfer-prover method to help gen- erate transfer rules. lemma ZN-sum-list [transfer-rule]: (list-all2 ZN ===> ZN ) sum-list sum-list by transfer-prover end

52.4 Transfer examples lemma assumes Vi::int. 0 ≤ i =⇒ i + 0 = i shows Vi::nat. i + 0 = i apply transfer apply fact done lemma assumes Vi k::int. [[0 ≤ i; 0 ≤ k; i < k]] =⇒ ∃ j ∈{0 ..}. i + j = k shows Vi k::nat. i < k =⇒ ∃ j . i + j = k apply transfer apply fact done lemma assumes ∀ x∈{0 ::int..}. ∀ y∈{0 ..}. x ∗ y div y = x shows ∀ x y :: nat. x ∗ y div y = x apply transfer apply fact done lemma assumes Vm n::int. [[0 ≤ m; 0 ≤ n; m ∗ n = 0 ]] =⇒ m = 0 ∨ n = 0

398 shows m ∗ n = (0 ::nat) =⇒ m = 0 ∨ n = 0 apply transfer apply fact done lemma assumes ∀ x∈{0 ::int..}. ∃ y∈{0 ..}. ∃ z∈{0 ..}. x + 3 ∗ y = 5 ∗ z shows ∀ x::nat. ∃ y z. x + 3 ∗ y = 5 ∗ z apply transfer apply fact done The fixing option prevents generalization over the free variable n, allowing the local transfer rule to be used. lemma assumes [transfer-rule]: ZN x n assumes ∀ i∈{0 ..}. i < x −→ 2 ∗ i < 3 ∗ x shows ∀ i. i < n −→ 2 ∗ i < 3 ∗ n apply (transfer fixing: n) apply fact done lemma assumes gcd (2ˆi)(3ˆj ) = (1 ::int) shows gcd (2ˆi)(3ˆj ) = (1 ::nat) apply (transfer fixing: i j ) apply fact done lemma assumes Vx y z::int. [[0 ≤ x; 0 ≤ y; 0 ≤ z]] =⇒ sum-list [x, y, z] = 0 ←→ list-all (λx. x = 0 )[x, y, z] shows sum-list [x, y, z] = (0 ::nat) ←→ list-all (λx. x = 0 )[x, y, z] apply transfer apply fact done Quantifiers over higher types (e.g. nat list) are transferred to a readable formula thanks to the transfer domain rule Domainp ZN = op ≤ 0 lemma assumes Vxs::int list. list-all (λx. x ≥ 0 ) xs =⇒ (sum-list xs = 0 ) = list-all (λx. x = 0 ) xs shows sum-list xs = (0 ::nat) ←→ list-all (λx. x = 0 ) xs apply transfer apply fact done Equality on a higher type can be transferred if the relations involved are bi-unique.

399 lemma assumes Vxs::int list. [[list-all (λx. x ≥ 0 ) xs; xs 6= []]] =⇒ sum-list xs < sum-list (map (λx. x + 1 ) xs) shows xs 6= [] =⇒ sum-list xs < sum-list (map Suc xs) apply transfer apply fact done end

53 Various examples for transfer procedure theory Transfer-Ex imports Main Transfer-Int-Nat begin lemma ex1 :(x::nat) + y = y + x by auto lemma 0 ≤ (y::int) =⇒ 0 ≤ (x::int) =⇒ x + y = y + x by (fact ex1 [transferred]) lemma 0 ≤ (x::int) =⇒ 0 ≤ (y::int) =⇒ x + y = y + x by (fact ex1 [untransferred]) lemma ex2 :(a::nat) div b ∗ b + a mod b = a by (rule div-mult-mod-eq) lemma 0 ≤ (b::int) =⇒ 0 ≤ (a::int) =⇒ a div b ∗ b + a mod b = a by (fact ex2 [transferred]) lemma 0 ≤ (a::int) =⇒ 0 ≤ (b::int) =⇒ a div b ∗ b + a mod b = a by (fact ex2 [untransferred]) lemma ex3 : ALL (x::nat). ALL y. EX z. z >= x + y by auto lemma ∀ x≥0 ::int. ∀ y≥0 . ∃ z≥0 . x + y ≤ z by (fact ex3 [transferred nat-int]) lemma ∀ x::int∈{0 ..}. ∀ y∈{0 ..}. ∃ z∈{0 ..}. x + y ≤ z by (fact ex3 [untransferred]) lemma ex4 :(x::nat) >= y =⇒ (x − y) + y = x by auto

400 lemma 0 ≤ (x::int) =⇒ 0 ≤ (y::int) =⇒ y ≤ x =⇒ tsub x y + y = x by (fact ex4 [transferred]) lemma 0 ≤ (y::int) =⇒ 0 ≤ (x::int) =⇒ y ≤ x =⇒ tsub x y + y = x by (fact ex4 [untransferred]) lemma ex5 :(2 ::nat) ∗ P {..n} = n ∗ (n + 1 ) by (induct n rule: nat-induct, auto) lemma 0 ≤ (n::int) =⇒ 2 ∗ P {0 ..n} = n ∗ (n + 1 ) by (fact ex5 [transferred]) lemma 0 ≤ (n::int) =⇒ 2 ∗ P {0 ..n} = n ∗ (n + 1 ) by (fact ex5 [untransferred]) lemma 0 ≤ (n::nat) =⇒ 2 ∗ P {0 ..n} = n ∗ (n + 1 ) by (fact ex5 [transferred, transferred]) lemma 0 ≤ (n::nat) =⇒ 2 ∗ P {..n} = n ∗ (n + 1 ) by (fact ex5 [untransferred, Transfer.transferred]) end

54 Simple example for table-based implementa- tion of the reflexive transitive closure theory Transitive-Closure-Table-Ex imports ∼∼/src/HOL/Library/Transitive-Closure-Table begin datatype ty = A | B | C inductive test :: ty ⇒ ty ⇒ bool where test A B | test B A | test B C

Invoking with the predicate compiler and the generic code generator code-pred test . values {x. test ∗∗ AC } values {x. test ∗∗ CA} values {x. test ∗∗ A x} values {x. test ∗∗ x C }

401 value test ∗∗ AC value test ∗∗ CA end

55 Divergence of the Harmonic Series theory HarmonicSeries imports Complex-Main begin

55.1 Abstract

The following document presents a proof of the Divergence of Harmonic Series theorem formalised in the Isabelle/Isar theorem proving system. P∞ 1 Theorem: The series n=1 n does not converge to any number. Informal Proof: The informal proof is based on the following auxillary lem- mas:

P2m 1 1 • aux: n=2m−1 n ≥ 2

P2M 1 PM P2m 1 • aux2: n=1 n = 1 + m=1 n=2m−1 n

P2M 1 M From aux and aux2 we can deduce that n=1 n ≥ 1 + 2 for all M. Now P∞ 1 1 for contradiction, assume that n=1 n = s for some s. Because ∀n. n > 0 all the partial sums in the series must be less than s. However with our P2N 1 deduction above we can choose N > 2 ∗ s − 2 and thus n=1 n > s. This P∞ 1 leads to a contradiction and hence n=1 n is not summable. QED.

55.2 Formal Proof lemma two-pow-sub: 0 < m =⇒ (2 ::nat)ˆm − 2ˆ(m − 1 ) = 2ˆ(m − 1 ) by (induct m) auto We first prove the following auxillary lemma. This lemma simply states that 1 1 1 1 1 1 1 the finite sums: 2 , 3 + 4 , 5 + 6 + 7 + 8 etc. are all greater than or equal 1 to 2 . We do this by observing that each term in the sum is greater than or 1 1 1 1 1 1 1 equal to the last term, e.g. 3 > 4 and thus 3 + 4 > 4 + 4 = 2 . lemma harmonic-aux: ∀ m>0 . (P n∈{(2 ::nat)ˆ(m − 1 )+1 ..2ˆm}. 1 /real n) ≥ 1 /2 (is ∀ m>0 . (P n∈(?S m). 1 /real n) ≥ 1 /2 ) proof fix m::nat obtain tm where tmdef : tm = (2 ::nat)ˆm by simp

402 { assume mgt0 : 0 < m have Vx. x∈(?S m) =⇒ 1 /(real x) ≥ 1 /(real tm) proof − fix x::nat assume xs: x∈(?S m) have xgt0 : x>0 proof − from xs have x ≥ 2ˆ(m − 1 ) + 1 by auto moreover from mgt0 have 2ˆ(m − 1 ) + 1 ≥ (1 ::nat) by auto ultimately have x ≥ 1 by (rule xtrans) thus ?thesis by simp qed moreover from xs have x ≤ 2ˆm by auto ultimately have inverse (real x) ≥ inverse (real ((2 ::nat)ˆm)) by simp moreover from xgt0 have real x 6= 0 by simp then have inverse (real x) = 1 / (real x) by (rule nonzero-inverse-eq-divide) moreover from mgt0 have real tm 6= 0 by (simp add: tmdef ) then have inverse (real tm) = 1 / (real tm) by (rule nonzero-inverse-eq-divide) ultimately show 1 /(real x) ≥ 1 /(real tm) by (auto simp add: tmdef ) qed then have (P n∈(?S m). 1 / real n) ≥ (P n∈(?S m). 1 /(real tm)) by (rule sum-mono) moreover have (P n∈(?S m). 1 /(real tm)) = 1 /2 proof − have (P n∈(?S m). 1 /(real tm)) = (1 /(real tm))∗(P n∈(?S m). 1 ) by simp also have ... = ((1 /(real tm)) ∗ real (card (?S m))) by (simp add: real-of-card) also have ... = ((1 /(real tm)) ∗ real (tm − (2ˆ(m − 1 )))) by (simp add: tmdef ) also from mgt0 have ... = ((1 /(real tm)) ∗ real ((2 ::nat)ˆ(m − 1 ))) by (auto simp: tmdef dest: two-pow-sub)

403 also have ... = (real (2 ::nat))ˆ(m − 1 ) / (real (2 ::nat))ˆm by (simp add: tmdef ) also from mgt0 have ... = (real (2 ::nat))ˆ(m − 1 ) / (real (2 ::nat))ˆ((m − 1 ) + 1 ) by auto also have ... = 1 /2 by simp finally show ?thesis . qed ultimately have (P n∈(?S m). 1 / real n) ≥ 1 /2 by − (erule subst) } thus 0 < m −→ 1 / 2 ≤ (P n∈(?S m). 1 / real n) by simp qed

We then show that the sum of a finite number of terms from the harmonic 1 1 series can be regrouped in increasing powers of 2. For example: 1 + 2 + 3 + 1 1 1 1 1 1 1 1 1 1 1 1 4 + 5 + 6 + 7 + 8 = 1 + ( 2 ) + ( 3 + 4 ) + ( 5 + 6 + 7 + 8 ). lemma harmonic-aux2 [rule-format]: 0

404 moreover { from mz have ?RHS (Suc M ) = ?RHS 1 by simp also have ... = (P n∈{((2 ::nat)ˆ0 )+1 ..2ˆ1 }. 1 /real n) + 1 by simp also have ... = (P n∈{2 ::nat..2 }. 1 /real n) + 1 by (auto simp: atLeastAtMost-singleton 0) also have ... = 1 /2 + 1 by simp finally have ?RHS (Suc M ) = 1 /2 + 1 by simp } ultimately show ?LHS (Suc M ) = ?RHS (Suc M ) by simp next assume mnz: M 6=0 then have mgtz: M >0 by simp with Suc have suc: (?LHS M ) = (?RHS M ) by blast have (?LHS (Suc M )) = ((?LHS M ) + (P n∈{(2 ::nat)ˆM +1 ..2ˆ(Suc M )}. 1 / real n)) proof − have {1 ..(2 ::nat)ˆ(Suc M )} = {1 ..(2 ::nat)ˆM }∪{(2 ::nat)ˆM +1 ..(2 ::nat)ˆ(Suc M )} by auto moreover have {1 ..(2 ::nat)ˆM }∩{(2 ::nat)ˆM +1 ..(2 ::nat)ˆ(Suc M )} = {} by auto moreover have finite {1 ..(2 ::nat)ˆM } and finite {(2 ::nat)ˆM +1 ..(2 ::nat)ˆ(Suc M )} by auto ultimately show ?thesis by (auto intro: sum.union-disjoint) qed moreover { have (?RHS (Suc M )) = (1 + (P m∈{1 ..M }. P n∈{(2 ::nat)ˆ(m − 1 )+1 ..2ˆm}. 1 /real n) + (P n∈{(2 ::nat)ˆ(Suc M − 1 )+1 ..2ˆ(Suc M )}. 1 /real n)) by simp also have ... = (?RHS M ) + (P n∈{(2 ::nat)ˆM +1 ..2ˆ(Suc M )}. 1 /real n) by simp also from suc have

405 ... = (?LHS M ) + (P n∈{(2 ::nat)ˆM +1 ..2ˆ(Suc M )}. 1 /real n) by simp finally have (?RHS (Suc M )) = ... by simp } ultimately show ?LHS (Suc M ) = ?RHS (Suc M ) by simp qed } thus ?case by simp qed

Using harmonic-aux and harmonic-aux2 we now show that each group sum 1 is greater than or equal to 2 and thus the finite sum is bounded below by a value proportional to the number of elements we choose. lemma harmonic-aux3 [rule-format]: shows ∀ (M ::nat). (P n∈{1 ..(2 ::nat)ˆM }. 1 / real n) ≥ 1 + (real M )/2 (is ∀ M . ?P M ≥ -) proof (rule allI , cases) fix M ::nat assume M =0 then show ?P M ≥ 1 + (real M )/2 by simp next fix M ::nat assume M 6=0 then have M > 0 by simp then have (?P M ) = (1 + (P m∈{1 ..M }. P n∈{(2 ::nat)ˆ(m − 1 )+1 ..2ˆm}. 1 /real n)) by (rule harmonic-aux2 ) also have ... ≥ (1 + (P m∈{1 ..M }. 1 /2 )) proof − let ?f = (λx. 1 /2 ) let ?g = (λx. (P n∈{(2 ::nat)ˆ(x − 1 )+1 ..2ˆx}. 1 /real n)) from harmonic-aux have Vx. x∈{1 ..M } =⇒ ?f x ≤ ?g x by simp then have (P m∈{1 ..M }. ?g m) ≥ (P m∈{1 ..M }. ?f m) by (rule sum-mono) thus ?thesis by simp qed finally have (?P M ) ≥ (1 + (P m∈{1 ..M }. 1 /2 )) . moreover { have (P m∈{1 ..M }. (1 ::real)/2 ) = 1 /2 ∗ (P m∈{1 ..M }. 1 ) by auto also have ... = 1 /2 ∗(real (card {1 ..M })) by (simp only: real-of-card[symmetric]) also have ... = 1 /2 ∗(real M ) by simp

406 also have ... = (real M )/2 by simp finally have (P m∈{1 ..M }. (1 ::real)/2 ) = (real M )/2 . } ultimately show (?P M ) ≥ (1 + (real M )/2 ) by simp qed

The final theorem shows that as we take more and more elements (see harmonic-aux3 ) we get an ever increasing sum. By assuming the sum con- verges, the lemma sum-less-suminf ( [[summable ?f ; ∀ m≥?n. (0 ::? 0a) < ?f m]] =⇒ sum ?f {.. ?s by linarith define j where j = (2 ::nat)ˆn have ∀ m≥j . 0 < ?f m by simp with sf have (P i ?s by simp ultimately show False by simp qed end

56 Examples for the ’refute’ command theory Refute-Examples imports ∼∼/src/HOL/Library/Refute begin refute-params [satsolver = cdclite] lemma P ∧ Q

407 apply (rule conjI ) refute [expect = genuine] 1 — refutes P refute [expect = genuine] 2 — refutes Q refute [expect = genuine] — equivalent to ’refute 1’ — here ’refute 3’ would cause an exception, since we only have 2 subgoals refute [maxsize = 5 , expect = genuine] — we can override parameters ... refute [satsolver = cdclite, expect = genuine] 2 — ... and specify a subgoal at the same time oops

56.1 Examples and Test Cases 56.1.1 Propositional logic lemma True refute [expect = none] by auto lemma False refute [expect = genuine] oops lemma P refute [expect = genuine] oops lemma ∼ P refute [expect = genuine] oops lemma P & Q refute [expect = genuine] oops lemma P | Q refute [expect = genuine] oops lemma P −→ Q refute [expect = genuine] oops lemma (P::bool) = Q refute [expect = genuine] oops lemma (P | Q) −→ (P & Q) refute [expect = genuine] oops

408 56.1.2 Predicate logic lemma P x y z refute [expect = genuine] oops lemma P x y −→ P y x refute [expect = genuine] oops lemma P (f (f x)) −→ P x −→ P (f x) refute [expect = genuine] oops

56.1.3 Equality lemma P = True refute [expect = genuine] oops lemma P = False refute [expect = genuine] oops lemma x = y refute [expect = genuine] oops lemma f x = g x refute [expect = genuine] oops lemma (f :: 0a⇒ 0b) = g refute [expect = genuine] oops lemma (f ::( 0d⇒ 0d)⇒( 0c⇒ 0d)) = g refute [expect = genuine] oops lemma distinct [a, b] apply simp refute [expect = genuine] oops

56.1.4 First-Order Logic lemma ∃ x. P x refute [expect = genuine]

409 oops lemma ∀ x. P x refute [expect = genuine] oops lemma ∃ !x. P x refute [expect = genuine] oops lemma Ex P refute [expect = genuine] oops lemma All P refute [expect = genuine] oops lemma Ex1 P refute [expect = genuine] oops lemma (∃ x. P x) −→ (∀ x. P x) refute [expect = genuine] oops lemma (∀ x. ∃ y. P x y) −→ (∃ y. ∀ x. P x y) refute [expect = genuine] oops lemma (∃ x. P x) −→ (∃ !x. P x) refute [expect = genuine] oops

A true statement (also testing names of free and bound variables being identical) lemma (∀ x y. P x y −→ P y x) −→ (∀ x. P x y) −→ P y x refute [maxsize = 4 , expect = none] by fast

”A type has at most 4 elements.” lemma a=b | a=c | a=d | a=e | b=c | b=d | b=e | c=d | c=e | d=e refute [expect = genuine] oops lemma ∀ a b c d e. a=b | a=c | a=d | a=e | b=c | b=d | b=e | c=d | c=e | d=e refute [expect = genuine] oops

410 ”Every reflexive and symmetric relation is transitive.” lemma [[ ∀ x. P x x; ∀ x y. P x y −→ P y x ]] =⇒ P x y −→ P y z −→ P x z refute [expect = genuine] oops The ”Drinker’s theorem” ... lemma ∃ x. f x = g x −→ f = g refute [maxsize = 4 , expect = none] by (auto simp add: ext) ... and an incorrect version of it lemma (∃ x. f x = g x) −→ f = g refute [expect = genuine] oops ”Every function has a fixed point.” lemma ∃ x. f x = x refute [expect = genuine] oops ”Function composition is commutative.” lemma f (g x) = g (f x) refute [expect = genuine] oops ”Two functions that are equivalent wrt. the same predicate ’P’ are equal.” lemma ((P::( 0a⇒ 0b)⇒bool) f = P g) −→ (f x = g x) refute [expect = genuine] oops

56.1.5 Higher-Order Logic lemma ∃ P. P refute [expect = none] by auto lemma ∀ P. P refute [expect = genuine] oops lemma ∃ !P. P refute [expect = none] by auto lemma ∃ !P. P x refute [expect = genuine] oops

411 lemma PQ | Q x refute [expect = genuine] oops lemma x 6= All refute [expect = genuine] oops lemma x 6= Ex refute [expect = genuine] oops lemma x 6= Ex1 refute [expect = genuine] oops

”The transitive closure ’T’ of an arbitrary relation ’P’ is non-empty.” definition trans :: ( 0a ⇒ 0a ⇒ bool) ⇒ bool where trans P == (ALL x y z. P x y −→ P y z −→ P x z) definition subset :: ( 0a ⇒ 0a ⇒ bool) ⇒ ( 0a ⇒ 0a ⇒ bool) ⇒ bool where subset P Q == (ALL x y. P x y −→ Q x y) definition trans-closure :: ( 0a ⇒ 0a ⇒ bool) ⇒ ( 0a ⇒ 0a ⇒ bool) ⇒ bool where trans-closure P Q == (subset Q P)&(trans P)&(ALL R. subset Q R −→ trans R −→ subset P R) lemma trans-closure T P −→ (∃ x y. T x y) refute [expect = genuine] oops

”Every surjective function is invertible.” lemma (∀ y. ∃ x. y = f x) −→ (∃ g. ∀ x. g (f x) = x) refute [expect = genuine] oops

”Every invertible function is surjective.” lemma (∃ g. ∀ x. g (f x) = x) −→ (∀ y. ∃ x. y = f x) refute [expect = genuine] oops

Every point is a fixed point of some function. lemma ∃ f . f x = x refute [maxsize = 4 , expect = none] apply (rule-tac x=λx. x in exI ) by simp

Axiom of Choice: first an incorrect version ...

412 lemma (∀ x. ∃ y. P x y) −→ (∃ !f . ∀ x. P x (f x)) refute [expect = genuine] oops ... and now two correct ones lemma (∀ x. ∃ y. P x y) −→ (∃ f . ∀ x. P x (f x)) refute [maxsize = 4 , expect = none] by (simp add: choice) lemma (∀ x. ∃ !y. P x y) −→ (∃ !f . ∀ x. P x (f x)) refute [maxsize = 2 , expect = none] apply auto apply (simp add: ex1-implies-ex choice) by (fast intro: ext)

56.1.6 Meta-logic lemma !!x. P x refute [expect = genuine] oops lemma f x == g x refute [expect = genuine] oops lemma P =⇒ Q refute [expect = genuine] oops lemma [[ P; Q; R ]] =⇒ S refute [expect = genuine] oops lemma (x == Pure.all) =⇒ False refute [expect = genuine] oops lemma (x == (op ==)) =⇒ False refute [expect = genuine] oops lemma (x == (op =⇒)) =⇒ False refute [expect = genuine] oops

56.1.7 Schematic variables schematic-goal ?P refute [expect = none] by auto

413 schematic-goal x = ?y refute [expect = none] by auto

56.1.8 Abstractions lemma (λx. x) = (λx. y) refute [expect = genuine] oops lemma (λf . f x) = (λf . True) refute [expect = genuine] oops lemma (λx. x) = (λy. y) refute by simp

56.1.9 Sets lemma P (A:: 0a set) refute oops lemma P (A:: 0a set set) refute oops lemma {x. P x} = {y. P y} refute by simp lemma x : {x. P x} refute oops lemma P op: refute oops lemma P (op: x) refute oops lemma P Collect refute oops lemma A Un B = A Int B

414 refute oops lemma (A Int B) Un C = (A Un C ) Int B refute oops lemma Ball A P −→ Bex A P refute oops

56.1.10 undefined lemma undefined refute [expect = genuine] oops lemma P undefined refute [expect = genuine] oops lemma undefined x refute [expect = genuine] oops lemma undefined undefined refute [expect = genuine] oops

56.1.11 The lemma The P refute [expect = genuine] oops lemma P The refute [expect = genuine] oops lemma P (The P) refute [expect = genuine] oops lemma (THE x. x=y) = z refute [expect = genuine] oops lemma Ex P −→ P (The P) refute [expect = genuine] oops

415 56.1.12 Eps lemma Eps P refute [expect = genuine] oops lemma P Eps refute [expect = genuine] oops lemma P (Eps P) refute [expect = genuine] oops lemma (SOME x. x=y) = z refute [expect = genuine] oops lemma Ex P −→ P (Eps P) refute [maxsize = 3 , expect = none] by (auto simp add: someI )

56.1.13 Subtypes (typedef), typedecl

A completely unspecified non-empty subset of 0a: definition myTdef = insert (undefined:: 0a)(undefined:: 0a set) typedef 0a myTdef = myTdef :: 0a set unfolding myTdef-def by auto lemma (x:: 0a myTdef ) = y refute oops typedecl myTdecl definition T-bij = {(f :: 0a⇒ 0a). ∀ y. ∃ !x. f x = y} typedef 0a T-bij = T-bij :: ( 0a ⇒ 0a) set unfolding T-bij-def by auto lemma P (f ::(myTdecl myTdef ) T-bij ) refute oops

56.1.14 Inductive datatypes unit lemma P (x::unit)

416 refute [expect = genuine] oops lemma ∀ x::unit. P x refute [expect = genuine] oops lemma P () refute [expect = genuine] oops lemma P (case x of () ⇒ u) refute [expect = genuine] oops option lemma P (x:: 0a option) refute [expect = genuine] oops lemma ∀ x:: 0a option. P x refute [expect = genuine] oops lemma P None refute [expect = genuine] oops lemma P (Some x) refute [expect = genuine] oops lemma P (case x of None ⇒ n | Some u ⇒ s u) refute [expect = genuine] oops

* lemma P (x:: 0a∗ 0b) refute [expect = genuine] oops lemma ∀ x:: 0a∗ 0b. P x refute [expect = genuine] oops lemma P (x, y) refute [expect = genuine] oops

417 lemma P (fst x) refute [expect = genuine] oops lemma P (snd x) refute [expect = genuine] oops lemma P Pair refute [expect = genuine] oops lemma P (case x of Pair a b ⇒ p a b) refute [expect = genuine] oops

+ lemma P (x:: 0a+ 0b) refute [expect = genuine] oops lemma ∀ x:: 0a+ 0b. P x refute [expect = genuine] oops lemma P (Inl x) refute [expect = genuine] oops lemma P (Inr x) refute [expect = genuine] oops lemma P Inl refute [expect = genuine] oops lemma P (case x of Inl a ⇒ l a | Inr b ⇒ r b) refute [expect = genuine] oops

Non-recursive datatypes datatype T1 = A | B lemma P (x::T1 ) refute [expect = genuine] oops lemma ∀ x::T1 . P x

418 refute [expect = genuine] oops lemma PA refute [expect = genuine] oops lemma PB refute [expect = genuine] oops lemma rec-T1 a b A = a refute [expect = none] by simp lemma rec-T1 a b B = b refute [expect = none] by simp lemma P (rec-T1 a b x) refute [expect = genuine] oops lemma P (case x of A ⇒ a | B ⇒ b) refute [expect = genuine] oops datatype 0a T2 = C T1 | D 0a lemma P (x:: 0a T2 ) refute [expect = genuine] oops lemma ∀ x:: 0a T2 . P x refute [expect = genuine] oops lemma PD refute [expect = genuine] oops lemma rec-T2 c d (C x) = c x refute [maxsize = 4 , expect = none] by simp lemma rec-T2 c d (D x) = d x refute [maxsize = 4 , expect = none] by simp

419 lemma P (rec-T2 c d x) refute [expect = genuine] oops lemma P (case x of C u ⇒ c u | D v ⇒ d v) refute [expect = genuine] oops datatype ( 0a, 0b) T3 = E 0a ⇒ 0b lemma P (x::( 0a, 0b) T3 ) refute [expect = genuine] oops lemma ∀ x::( 0a, 0b) T3 . P x refute [expect = genuine] oops lemma PE refute [expect = genuine] oops lemma rec-T3 e (E x) = e x refute [maxsize = 2 , expect = none] by simp lemma P (rec-T3 e x) refute [expect = genuine] oops lemma P (case x of E f ⇒ e f ) refute [expect = genuine] oops Recursive datatypes nat lemma P (x::nat) refute [expect = potential] oops lemma ∀ x::nat. P x refute [expect = potential] oops lemma P (Suc 0 ) refute [expect = potential] oops lemma P Suc

420 refute [maxsize = 3 , expect = none] — Suc is a partial function (regardless of the size of the model), hence P Suc is undefined and no model will be found oops lemma rec-nat zero suc 0 = zero refute [expect = none] by simp lemma rec-nat zero suc (Suc x) = suc x (rec-nat zero suc x) refute [maxsize = 2 , expect = none] by simp lemma P (rec-nat zero suc x) refute [expect = potential] oops lemma P (case x of 0 ⇒ zero | Suc n ⇒ suc n) refute [expect = potential] oops

’a list lemma P (xs:: 0a list) refute [expect = potential] oops lemma ∀ xs:: 0a list. P xs refute [expect = potential] oops lemma P [x, y] refute [expect = potential] oops lemma rec-list nil cons [] = nil refute [maxsize = 3 , expect = none] by simp lemma rec-list nil cons (x#xs) = cons x xs (rec-list nil cons xs) refute [maxsize = 2 , expect = none] by simp lemma P (rec-list nil cons xs) refute [expect = potential] oops lemma P (case x of Nil ⇒ nil | Cons a b ⇒ cons a b) refute [expect = potential] oops

421 lemma (xs:: 0a list) = ys refute [expect = potential] oops lemma a # xs = b # xs refute [expect = potential] oops datatype BitList = BitListNil | Bit0 BitList | Bit1 BitList lemma P (x::BitList) refute [expect = potential] oops lemma ∀ x::BitList. P x refute [expect = potential] oops lemma P (Bit0 (Bit1 BitListNil)) refute [expect = potential] oops lemma rec-BitList nil bit0 bit1 BitListNil = nil refute [maxsize = 4 , expect = none] by simp lemma rec-BitList nil bit0 bit1 (Bit0 xs) = bit0 xs (rec-BitList nil bit0 bit1 xs) refute [maxsize = 2 , expect = none] by simp lemma rec-BitList nil bit0 bit1 (Bit1 xs) = bit1 xs (rec-BitList nil bit0 bit1 xs) refute [maxsize = 2 , expect = none] by simp lemma P (rec-BitList nil bit0 bit1 x) refute [expect = potential] oops

56.1.15 Examples involving special functions lemma card x = 0 refute [expect = potential] oops lemma finite x refute — no finite countermodel exists oops

422 lemma (x::nat) + y = 0 refute [expect = potential] oops lemma (x::nat) = x + x refute [expect = potential] oops lemma (x::nat) − y + y = x refute [expect = potential] oops lemma (x::nat) = x ∗ x refute [expect = potential] oops lemma (x::nat) < x + y refute [expect = potential] oops lemma xs @ [] = ys @ [] refute [expect = potential] oops lemma xs @ ys = ys @ xs refute [expect = potential] oops

56.1.16 Type classes and overloading

A type class without axioms: class classA lemma P (x:: 0a::classA) refute [expect = genuine] oops

An axiom with a type variable (denoting types which have at least two elements): class classC = assumes classC-ax: ∃ x y. x 6= y lemma P (x:: 0a::classC ) refute [expect = genuine] oops lemma ∃ x y. (x:: 0a::classC ) 6= y

423 oops

A type class for which a constant is defined: class classD = fixes classD-const :: 0a ⇒ 0a assumes classD-ax: classD-const (classD-const x) = classD-const x lemma P (x:: 0a::classD) refute [expect = genuine] oops

A type class with multiple superclasses: class classE = classC + classD lemma P (x:: 0a::classE) refute [expect = genuine] oops

OFCLASS: lemma OFCLASS( 0a::type, type-class) refute [expect = none] by intro-classes lemma OFCLASS( 0a::classC , type-class) refute [expect = none] by intro-classes lemma OFCLASS( 0a::type, classC-class) refute [expect = genuine] oops

Overloading: consts inverse :: 0a ⇒ 0a overloading inverse-bool ≡ inverse :: bool ⇒ bool begin definition inverse (b::bool) ≡ ¬ b end overloading inverse-set ≡ inverse :: 0a set ⇒ 0a set begin definition inverse (S:: 0a set) ≡ −S end overloading inverse-pair ≡ inverse :: 0a × 0b ⇒ 0a × 0b begin definition inverse-pair p ≡ (inverse (fst p), inverse (snd p)) end

424 lemma inverse b refute [expect = genuine] oops lemma P (inverse (S:: 0a set)) refute [expect = genuine] oops lemma P (inverse (p:: 0a× 0b)) refute [expect = genuine] oops

Structured proofs lemma x = y proof cases assume x = y show ?thesis refute [expect = none] refute [no-assms, expect = genuine] refute [no-assms = false, expect = none] oops refute-params [satsolver = auto] end

57 Implementation of Association Lists theory AList imports Main begin context begin

The operations preserve distinctness of keys and function clearjunk dis- tributes over them. Since clearjunk enforces distinctness of keys it can be used to establish the invariant, e.g. for inductive proofs.

57.1 update and updates qualified primrec update :: 0key ⇒ 0val ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where update k v [] = [(k, v)] | update k v (p # ps) = (if fst p = k then (k, v)# ps else p # update k v ps) lemma update-conv 0: map-of (update k v al) = (map-of al)(k7→v)

425 by (induct al)(auto simp add: fun-eq-iff ) corollary update-conv: map-of (update k v al) k 0 = ((map-of al)(k7→v)) k 0 by (simp add: update-conv 0) lemma dom-update: fst ‘ set (update k v al) = {k} ∪ fst ‘ set al by (induct al) auto lemma update-keys: map fst (update k v al) = (if k ∈ set (map fst al) then map fst al else map fst al @[k]) by (induct al) simp-all lemma distinct-update: assumes distinct (map fst al) shows distinct (map fst (update k v al)) using assms by (simp add: update-keys) lemma update-filter: a 6= k =⇒ update k v [q←ps. fst q 6= a] = [q←update k v ps. fst q 6= a] by (induct ps) auto lemma update-triv: map-of al k = Some v =⇒ update k v al = al by (induct al) auto lemma update-nonempty [simp]: update k v al 6= [] by (induct al) auto lemma update-eqD: update k v al = update k v 0 al 0 =⇒ v = v 0 proof (induct al arbitrary: al 0) case Nil then show ?case by (cases al 0)(auto split: if-split-asm) next case Cons then show ?case by (cases al 0)(auto split: if-split-asm) qed lemma update-last [simp]: update k v (update k v 0 al) = update k v al by (induct al) auto

Note that the lists are not necessarily the same: update k v (update k 0 v 0 []) = [(k 0, v 0), (k, v)] and update k 0 v 0 (update k v []) = [(k, v), (k 0, v 0)]. lemma update-swap: k 6= k 0 =⇒ map-of (update k v (update k 0 v 0 al)) = map-of (update k 0 v 0 (update k v al)) by (simp add: update-conv 0 fun-eq-iff )

426 lemma update-Some-unfold: map-of (update k v al) x = Some y ←→ x = k ∧ v = y ∨ x 6= k ∧ map-of al x = Some y by (simp add: update-conv 0 map-upd-Some-unfold) lemma image-update [simp]: x ∈/ A =⇒ map-of (update x y al) ‘A = map-of al ‘A by (simp add: update-conv 0) qualified definition updates :: 0key list ⇒ 0val list ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where updates ks vs = fold (case-prod update)(zip ks vs) lemma updates-simps [simp]: updates [] vs ps = ps updates ks [] ps = ps updates (k#ks)(v#vs) ps = updates ks vs (update k v ps) by (simp-all add: updates-def ) lemma updates-key-simp [simp]: updates (k # ks) vs ps = (case vs of [] ⇒ ps | v # vs ⇒ updates ks vs (update k v ps)) by (cases vs) simp-all lemma updates-conv 0: map-of (updates ks vs al) = (map-of al)(ks[7→]vs) proof − have map-of ◦ fold (case-prod update)(zip ks vs) = fold (λ(k, v) f . f (k 7→ v)) (zip ks vs) ◦ map-of by (rule fold-commute)(auto simp add: fun-eq-iff update-conv 0) then show ?thesis by (auto simp add: updates-def fun-eq-iff map-upds-fold-map-upd foldl-conv-fold split-def ) qed lemma updates-conv: map-of (updates ks vs al) k = ((map-of al)(ks[7→]vs)) k by (simp add: updates-conv 0) lemma distinct-updates: assumes distinct (map fst al) shows distinct (map fst (updates ks vs al)) proof − have distinct (fold (λ(k, v) al. if k ∈ set al then al else al @[k]) (zip ks vs)(map fst al)) by (rule fold-invariant [of zip ks vs λ-. True]) (auto intro: assms) moreover have map fst ◦ fold (case-prod update)(zip ks vs) = fold (λ(k, v) al. if k ∈ set al then al else al @[k]) (zip ks vs) ◦ map fst by (rule fold-commute)(simp add: update-keys split-def case-prod-beta comp-def ) ultimately show ?thesis

427 by (simp add: updates-def fun-eq-iff ) qed lemma updates-append1 [simp]: size ks < size vs =⇒ updates (ks@[k]) vs al = update k (vs!size ks)(updates ks vs al) by (induct ks arbitrary: vs al)(auto split: list.splits) lemma updates-list-update-drop[simp]: size ks ≤ i =⇒ i < size vs =⇒ updates ks (vs[i:=v]) al = updates ks vs al by (induct ks arbitrary: al vs i)(auto split: list.splits nat.splits) lemma update-updates-conv-if : map-of (updates xs ys (update x y al)) = map-of (if x ∈ set (take (length ys) xs) then updates xs ys al else (update x y (updates xs ys al))) by (simp add: updates-conv 0 update-conv 0 map-upd-upds-conv-if ) lemma updates-twist [simp]: k ∈/ set ks =⇒ map-of (updates ks vs (update k v al)) = map-of (update k v (updates ks vs al)) by (simp add: updates-conv 0 update-conv 0) lemma updates-apply-notin [simp]: k ∈/ set ks =⇒ map-of (updates ks vs al) k = map-of al k by (simp add: updates-conv) lemma updates-append-drop [simp]: size xs = size ys =⇒ updates (xs @ zs) ys al = updates xs ys al by (induct xs arbitrary: ys al)(auto split: list.splits) lemma updates-append2-drop [simp]: size xs = size ys =⇒ updates xs (ys @ zs) al = updates xs ys al by (induct xs arbitrary: ys al)(auto split: list.splits)

57.2 delete qualified definition delete :: 0key ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where delete-eq: delete k = filter (λ(k 0, -). k 6= k 0) lemma delete-simps [simp]: delete k [] = [] delete k (p # ps) = (if fst p = k then delete k ps else p # delete k ps) by (auto simp add: delete-eq) lemma delete-conv 0: map-of (delete k al) = (map-of al)(k := None) by (induct al)(auto simp add: fun-eq-iff )

428 corollary delete-conv: map-of (delete k al) k 0 = ((map-of al)(k := None)) k 0 by (simp add: delete-conv 0) lemma delete-keys: map fst (delete k al) = removeAll k (map fst al) by (simp add: delete-eq removeAll-filter-not-eq filter-map split-def comp-def ) lemma distinct-delete: assumes distinct (map fst al) shows distinct (map fst (delete k al)) using assms by (simp add: delete-keys distinct-removeAll) lemma delete-id [simp]: k ∈/ fst ‘ set al =⇒ delete k al = al by (auto simp add: image-iff delete-eq filter-id-conv) lemma delete-idem: delete k (delete k al) = delete k al by (simp add: delete-eq) lemma map-of-delete [simp]: k 0 6= k =⇒ map-of (delete k al) k 0 = map-of al k 0 by (simp add: delete-conv 0) lemma delete-notin-dom: k ∈/ fst ‘ set (delete k al) by (auto simp add: delete-eq) lemma dom-delete-subset: fst ‘ set (delete k al) ⊆ fst ‘ set al by (auto simp add: delete-eq) lemma delete-update-same: delete k (update k v al) = delete k al by (induct al) simp-all lemma delete-update: k 6= l =⇒ delete l (update k v al) = update k v (delete l al) by (induct al) simp-all lemma delete-twist: delete x (delete y al) = delete y (delete x al) by (simp add: delete-eq conj-commute) lemma length-delete-le: length (delete k al) ≤ length al by (simp add: delete-eq)

57.3 update-with-aux and delete-aux qualified primrec update-with-aux :: 0val ⇒ 0key ⇒ ( 0val ⇒ 0val) ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where update-with-aux v k f [] = [(k, f v)] | update-with-aux v k f (p # ps) = (if (fst p = k) then (k, f (snd p)) # ps else p # update-with-aux v k f ps) The above delete traverses all the list even if it has found the key. This one does not have to keep going because is assumes the invariant that keys are

429 distinct. qualified fun delete-aux :: 0key ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where delete-aux k [] = [] | delete-aux k ((k 0, v)# xs) = (if k = k 0 then xs else (k 0, v)# delete-aux k xs) lemma map-of-update-with-aux 0: map-of (update-with-aux v k f ps) k 0 = ((map-of ps)(k 7→ (case map-of ps k of None ⇒ f v | Some v ⇒ f v))) k 0 by (induct ps) auto lemma map-of-update-with-aux: map-of (update-with-aux v k f ps) = (map-of ps)(k 7→ (case map-of ps k of None ⇒ f v | Some v ⇒ f v)) by (simp add: fun-eq-iff map-of-update-with-aux 0) lemma dom-update-with-aux: fst ‘ set (update-with-aux v k f ps) = {k} ∪ fst ‘ set ps by (induct ps) auto lemma distinct-update-with-aux [simp]: distinct (map fst (update-with-aux v k f ps)) = distinct (map fst ps) by (induct ps)(auto simp add: dom-update-with-aux) lemma set-update-with-aux: distinct (map fst xs) =⇒ set (update-with-aux v k f xs) = (set xs − {k} × UNIV ∪ {(k, f (case map-of xs k of None ⇒ v | Some v ⇒ v))}) by (induct xs)(auto intro: rev-image-eqI ) lemma set-delete-aux: distinct (map fst xs) =⇒ set (delete-aux k xs) = set xs − {k} × UNIV apply (induct xs) apply simp-all apply clarsimp apply (fastforce intro: rev-image-eqI ) done lemma dom-delete-aux: distinct (map fst ps) =⇒ fst ‘ set (delete-aux k ps) = fst ‘ set ps − {k} by (auto simp add: set-delete-aux) lemma distinct-delete-aux [simp]: distinct (map fst ps) =⇒ distinct (map fst (delete-aux k ps)) proof (induct ps) case Nil then show ?case by simp next

430 case (Cons a ps) obtain k 0 v where a: a = (k 0, v) by (cases a) show ?case proof (cases k 0 = k) case True with Cons a show ?thesis by simp next case False with Cons a have k 0 ∈/ fst ‘ set ps distinct (map fst ps) by simp-all with False a have k 0 ∈/ fst ‘ set (delete-aux k ps) by (auto dest!: dom-delete-aux[where k=k]) with Cons a show ?thesis by simp qed qed lemma map-of-delete-aux 0: distinct (map fst xs) =⇒ map-of (delete-aux k xs) = (map-of xs)(k := None) apply (induct xs) apply (fastforce simp add: map-of-eq-None-iff fun-upd-twist) apply (auto intro!: ext) apply (simp add: map-of-eq-None-iff ) done lemma map-of-delete-aux: distinct (map fst xs) =⇒ map-of (delete-aux k xs) k 0 = ((map-of xs)(k := None)) k 0 by (simp add: map-of-delete-aux 0) lemma delete-aux-eq-Nil-conv: delete-aux k ts = [] ←→ ts = [] ∨ (∃ v. ts = [(k, v)]) by (cases ts)(auto split: if-split-asm)

57.4 restrict qualified definition restrict :: 0key set ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where restrict-eq: restrict A = filter (λ(k, v). k ∈ A) lemma restr-simps [simp]: restrict A [] = [] restrict A (p#ps) = (if fst p ∈ A then p # restrict A ps else restrict A ps) by (auto simp add: restrict-eq) lemma restr-conv 0: map-of (restrict A al) = ((map-of al)|‘A) proof show map-of (restrict A al) k = ((map-of al)|‘A) k for k apply (induct al)

431 apply simp apply (cases k ∈ A) apply auto done qed corollary restr-conv: map-of (restrict A al) k = ((map-of al)|‘A) k by (simp add: restr-conv 0) lemma distinct-restr: distinct (map fst al) =⇒ distinct (map fst (restrict A al)) by (induct al)(auto simp add: restrict-eq) lemma restr-empty [simp]: restrict {} al = [] restrict A [] = [] by (induct al)(auto simp add: restrict-eq) lemma restr-in [simp]: x ∈ A =⇒ map-of (restrict A al) x = map-of al x by (simp add: restr-conv 0) lemma restr-out [simp]: x ∈/ A =⇒ map-of (restrict A al) x = None by (simp add: restr-conv 0) lemma dom-restr [simp]: fst ‘ set (restrict A al) = fst ‘ set al ∩ A by (induct al)(auto simp add: restrict-eq) lemma restr-upd-same [simp]: restrict (−{x})(update x y al) = restrict (−{x}) al by (induct al)(auto simp add: restrict-eq) lemma restr-restr [simp]: restrict A (restrict B al) = restrict (A∩B) al by (induct al)(auto simp add: restrict-eq) lemma restr-update[simp]: map-of (restrict D (update x y al)) = map-of ((if x ∈ D then (update x y (restrict (D−{x}) al)) else restrict D al)) by (simp add: restr-conv 0 update-conv 0) lemma restr-delete [simp]: delete x (restrict D al) = (if x ∈ D then restrict (D − {x}) al else restrict D al) apply (simp add: delete-eq restrict-eq) apply (auto simp add: split-def ) proof − have y 6= x ←→ x 6= y for y by auto then show [p ← al. fst p ∈ D ∧ x 6= fst p] = [p ← al. fst p ∈ D ∧ fst p 6= x] by simp assume x ∈/ D then have y ∈ D ←→ y ∈ D ∧ x 6= y for y

432 by auto then show [p ← al . fst p ∈ D ∧ x 6= fst p] = [p ← al . fst p ∈ D] by simp qed lemma update-restr: map-of (update x y (restrict D al)) = map-of (update x y (restrict (D − {x}) al)) by (simp add: update-conv 0 restr-conv 0)(rule fun-upd-restrict) lemma update-restr-conv [simp]: x ∈ D =⇒ map-of (update x y (restrict D al)) = map-of (update x y (restrict (D − {x}) al)) by (simp add: update-conv 0 restr-conv 0) lemma restr-updates [simp]: length xs = length ys =⇒ set xs ⊆ D =⇒ map-of (restrict D (updates xs ys al)) = map-of (updates xs ys (restrict (D − set xs) al)) by (simp add: updates-conv 0 restr-conv 0) lemma restr-delete-twist:(restrict A (delete a ps)) = delete a (restrict A ps) by (induct ps) auto

57.5 clearjunk qualified function clearjunk :: ( 0key × 0val) list ⇒ ( 0key × 0val) list where clearjunk [] = [] | clearjunk (p#ps) = p # clearjunk (delete (fst p) ps) by pat-completeness auto termination by (relation measure length)(simp-all add: less-Suc-eq-le length-delete-le) lemma map-of-clearjunk: map-of (clearjunk al) = map-of al by (induct al rule: clearjunk.induct)(simp-all add: fun-eq-iff ) lemma clearjunk-keys-set: set (map fst (clearjunk al)) = set (map fst al) by (induct al rule: clearjunk.induct)(simp-all add: delete-keys) lemma dom-clearjunk: fst ‘ set (clearjunk al) = fst ‘ set al using clearjunk-keys-set by simp lemma distinct-clearjunk [simp]: distinct (map fst (clearjunk al)) by (induct al rule: clearjunk.induct)(simp-all del: set-map add: clearjunk-keys-set delete-keys) lemma ran-clearjunk: ran (map-of (clearjunk al)) = ran (map-of al)

433 by (simp add: map-of-clearjunk) lemma ran-map-of : ran (map-of al) = snd ‘ set (clearjunk al) proof − have ran (map-of al) = ran (map-of (clearjunk al)) by (simp add: ran-clearjunk) also have ... = snd ‘ set (clearjunk al) by (simp add: ran-distinct) finally show ?thesis . qed lemma clearjunk-update: clearjunk (update k v al) = update k v (clearjunk al) by (induct al rule: clearjunk.induct)(simp-all add: delete-update) lemma clearjunk-updates: clearjunk (updates ks vs al) = updates ks vs (clearjunk al) proof − have clearjunk ◦ fold (case-prod update)(zip ks vs) = fold (case-prod update)(zip ks vs) ◦ clearjunk by (rule fold-commute)(simp add: clearjunk-update case-prod-beta o-def ) then show ?thesis by (simp add: updates-def fun-eq-iff ) qed lemma clearjunk-delete: clearjunk (delete x al) = delete x (clearjunk al) by (induct al rule: clearjunk.induct)(auto simp add: delete-idem delete-twist) lemma clearjunk-restrict: clearjunk (restrict A al) = restrict A (clearjunk al) by (induct al rule: clearjunk.induct)(auto simp add: restr-delete-twist) lemma distinct-clearjunk-id [simp]: distinct (map fst al) =⇒ clearjunk al = al by (induct al rule: clearjunk.induct) auto lemma clearjunk-idem: clearjunk (clearjunk al) = clearjunk al by simp lemma length-clearjunk: length (clearjunk al) ≤ length al proof (induct al rule: clearjunk.induct [case-names Nil Cons]) case Nil then show ?case by simp next case (Cons kv al) moreover have length (delete (fst kv) al) ≤ length al by (fact length-delete-le) ultimately have length (clearjunk (delete (fst kv) al)) ≤ length al by (rule order-trans) then show ?case by simp qed

434 lemma delete-map: assumes Vkv. fst (f kv) = fst kv shows delete k (map f ps) = map f (delete k ps) by (simp add: delete-eq filter-map comp-def split-def assms) lemma clearjunk-map: assumes Vkv. fst (f kv) = fst kv shows clearjunk (map f ps) = map f (clearjunk ps) by (induct ps rule: clearjunk.induct [case-names Nil Cons]) (simp-all add: clearjunk-delete delete-map assms)

57.6 map-ran definition map-ran :: ( 0key ⇒ 0val ⇒ 0val) ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where map-ran f = map (λ(k, v). (k, f k v)) lemma map-ran-simps [simp]: map-ran f [] = [] map-ran f ((k, v)# ps) = (k, f k v)# map-ran f ps by (simp-all add: map-ran-def ) lemma dom-map-ran: fst ‘ set (map-ran f al) = fst ‘ set al by (simp add: map-ran-def image-image split-def ) lemma map-ran-conv: map-of (map-ran f al) k = map-option (f k)(map-of al k) by (induct al) auto lemma distinct-map-ran: distinct (map fst al) =⇒ distinct (map fst (map-ran f al)) by (simp add: map-ran-def split-def comp-def ) lemma map-ran-filter: map-ran f [p←ps. fst p 6= a] = [p←map-ran f ps. fst p 6= a] by (simp add: map-ran-def filter-map split-def comp-def ) lemma clearjunk-map-ran: clearjunk (map-ran f al) = map-ran f (clearjunk al) by (simp add: map-ran-def split-def clearjunk-map)

57.7 merge qualified definition merge :: ( 0key × 0val) list ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where merge qs ps = foldr (λ(k, v). update k v) ps qs lemma merge-simps [simp]: merge qs [] = qs merge qs (p#ps) = update (fst p)(snd p)(merge qs ps) by (simp-all add: merge-def split-def )

435 lemma merge-updates: merge qs ps = updates (rev (map fst ps)) (rev (map snd ps)) qs by (simp add: merge-def updates-def foldr-conv-fold zip-rev zip-map-fst-snd) lemma dom-merge: fst ‘ set (merge xs ys) = fst ‘ set xs ∪ fst ‘ set ys by (induct ys arbitrary: xs)(auto simp add: dom-update) lemma distinct-merge: distinct (map fst xs) =⇒ distinct (map fst (merge xs ys)) by (simp add: merge-updates distinct-updates) lemma clearjunk-merge: clearjunk (merge xs ys) = merge (clearjunk xs) ys by (simp add: merge-updates clearjunk-updates) lemma merge-conv 0: map-of (merge xs ys) = map-of xs ++ map-of ys proof − have map-of ◦ fold (case-prod update)(rev ys) = fold (λ(k, v) m. m(k 7→ v)) (rev ys) ◦ map-of by (rule fold-commute)(simp add: update-conv 0 case-prod-beta split-def fun-eq-iff ) then show ?thesis by (simp add: merge-def map-add-map-of-foldr foldr-conv-fold fun-eq-iff ) qed corollary merge-conv: map-of (merge xs ys) k = (map-of xs ++ map-of ys) k by (simp add: merge-conv 0) lemma merge-empty: map-of (merge [] ys) = map-of ys by (simp add: merge-conv 0) lemma merge-assoc [simp]: map-of (merge m1 (merge m2 m3 )) = map-of (merge (merge m1 m2 ) m3 ) by (simp add: merge-conv 0) lemma merge-Some-iff : map-of (merge m n) k = Some x ←→ map-of n k = Some x ∨ map-of n k = None ∧ map-of m k = Some x by (simp add: merge-conv 0 map-add-Some-iff ) lemmas merge-SomeD [dest!] = merge-Some-iff [THEN iffD1 ] lemma merge-find-right [simp]: map-of n k = Some v =⇒ map-of (merge m n) k = Some v by (simp add: merge-conv 0) lemma merge-None [iff ]: (map-of (merge m n) k = None) = (map-of n k = None ∧ map-of m k = None) by (simp add: merge-conv 0) lemma merge-upd [simp]: map-of (merge m (update k v n)) = map-of (update k

436 v (merge m n)) by (simp add: update-conv 0 merge-conv 0) lemma merge-updatess [simp]: map-of (merge m (updates xs ys n)) = map-of (updates xs ys (merge m n)) by (simp add: updates-conv 0 merge-conv 0) lemma merge-append: map-of (xs @ ys) = map-of (merge ys xs) by (simp add: merge-conv 0)

57.8 compose qualified function compose :: ( 0key × 0a) list ⇒ ( 0a × 0b) list ⇒ ( 0key × 0b) list where compose [] ys = [] | compose (x # xs) ys = (case map-of ys (snd x) of None ⇒ compose (delete (fst x) xs) ys | Some v ⇒ (fst x, v)# compose xs ys) by pat-completeness auto termination by (relation measure (length ◦ fst)) (simp-all add: less-Suc-eq-le length-delete-le) lemma compose-first-None [simp]: map-of xs k = None =⇒ map-of (compose xs ys) k = None by (induct xs ys rule: compose.induct)(auto split: option.splits if-split-asm) lemma compose-conv: map-of (compose xs ys) k = (map-of ys ◦m map-of xs) k proof (induct xs ys rule: compose.induct) case 1 then show ?case by simp next case (2 x xs ys) show ?case proof (cases map-of ys (snd x)) case None with 2 have hyp: map-of (compose (delete (fst x) xs) ys) k = (map-of ys ◦m map-of (delete (fst x) xs)) k by simp show ?thesis proof (cases fst x = k) case True from True delete-notin-dom [of k xs] have map-of (delete (fst x) xs) k = None by (simp add: map-of-eq-None-iff ) with hyp show ?thesis using True None by simp next

437 case False from False have map-of (delete (fst x) xs) k = map-of xs k by simp with hyp show ?thesis using False None by (simp add: map-comp-def ) qed next case (Some v) with 2 have map-of (compose xs ys) k = (map-of ys ◦m map-of xs) k by simp with Some show ?thesis by (auto simp add: map-comp-def ) qed qed

0 lemma compose-conv : map-of (compose xs ys) = (map-of ys ◦m map-of xs) by (rule ext)(rule compose-conv) lemma compose-first-Some [simp]: map-of xs k = Some v =⇒ map-of (compose xs ys) k = map-of ys v by (simp add: compose-conv) lemma dom-compose: fst ‘ set (compose xs ys) ⊆ fst ‘ set xs proof (induct xs ys rule: compose.induct) case 1 then show ?case by simp next case (2 x xs ys) show ?case proof (cases map-of ys (snd x)) case None with 2 .hyps have fst ‘ set (compose (delete (fst x) xs) ys) ⊆ fst ‘ set (delete (fst x) xs) by simp also have ... ⊆ fst ‘ set xs by (rule dom-delete-subset) finally show ?thesis using None by auto next case (Some v) with 2 .hyps have fst ‘ set (compose xs ys) ⊆ fst ‘ set xs by simp with Some show ?thesis by auto qed qed lemma distinct-compose:

438 assumes distinct (map fst xs) shows distinct (map fst (compose xs ys)) using assms proof (induct xs ys rule: compose.induct) case 1 then show ?case by simp next case (2 x xs ys) show ?case proof (cases map-of ys (snd x)) case None with 2 show ?thesis by simp next case (Some v) with 2 dom-compose [of xs ys] show ?thesis by auto qed qed lemma compose-delete-twist: compose (delete k xs) ys = delete k (compose xs ys) proof (induct xs ys rule: compose.induct) case 1 then show ?case by simp next case (2 x xs ys) show ?case proof (cases map-of ys (snd x)) case None with 2 have hyp: compose (delete k (delete (fst x) xs)) ys = delete k (compose (delete (fst x) xs) ys) by simp show ?thesis proof (cases fst x = k) case True with None hyp show ?thesis by (simp add: delete-idem) next case False from None False hyp show ?thesis by (simp add: delete-twist) qed next case (Some v) with 2 have hyp: compose (delete k xs) ys = delete k (compose xs ys) by simp with Some show ?thesis by simp qed qed

439 lemma compose-clearjunk: compose xs (clearjunk ys) = compose xs ys by (induct xs ys rule: compose.induct) (auto simp add: map-of-clearjunk split: option.splits) lemma clearjunk-compose: clearjunk (compose xs ys) = compose (clearjunk xs) ys by (induct xs rule: clearjunk.induct) (auto split: option.splits simp add: clearjunk-delete delete-idem compose-delete-twist) lemma compose-empty [simp]: compose xs [] = [] by (induct xs)(auto simp add: compose-delete-twist) lemma compose-Some-iff : (map-of (compose xs ys) k = Some v) ←→ (∃ k 0. map-of xs k = Some k 0 ∧ map-of ys k 0 = Some v) by (simp add: compose-conv map-comp-Some-iff ) lemma map-comp-None-iff : map-of (compose xs ys) k = None ←→ (map-of xs k = None ∨ (∃ k 0. map-of xs k = Some k 0 ∧ map-of ys k 0 = None)) by (simp add: compose-conv map-comp-None-iff )

57.9 map-entry qualified fun map-entry :: 0key ⇒ ( 0val ⇒ 0val) ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where map-entry k f [] = [] | map-entry k f (p # ps) = (if fst p = k then (k, f (snd p)) # ps else p # map-entry k f ps) lemma map-of-map-entry: map-of (map-entry k f xs) = (map-of xs)(k := case map-of xs k of None ⇒ None | Some v 0 ⇒ Some (f v 0)) by (induct xs) auto lemma dom-map-entry: fst ‘ set (map-entry k f xs) = fst ‘ set xs by (induct xs) auto lemma distinct-map-entry: assumes distinct (map fst xs) shows distinct (map fst (map-entry k f xs)) using assms by (induct xs)(auto simp add: dom-map-entry)

57.10 map-default fun map-default :: 0key ⇒ 0val ⇒ ( 0val ⇒ 0val) ⇒ ( 0key × 0val) list ⇒ ( 0key × 0val) list where map-default k v f [] = [(k, v)]

440 | map-default k v f (p # ps) = (if fst p = k then (k, f (snd p)) # ps else p # map-default k v f ps) lemma map-of-map-default: map-of (map-default k v f xs) = (map-of xs)(k := case map-of xs k of None ⇒ Some v | Some v 0 ⇒ Some (f v 0)) by (induct xs) auto lemma dom-map-default: fst ‘ set (map-default k v f xs) = insert k (fst ‘ set xs) by (induct xs) auto lemma distinct-map-default: assumes distinct (map fst xs) shows distinct (map fst (map-default k v f xs)) using assms by (induct xs)(auto simp add: dom-map-default) end end

58 An abstract view on maps for code generation. theory Mapping imports Main begin

58.1 Parametricity transfer rules lemma map-of-foldr: map-of xs = foldr (λ(k, v) m. m(k 7→ v)) xs Map.empty using map-add-map-of-foldr [of Map.empty] by auto context includes lifting-syntax begin lemma empty-parametric:(A ===> rel-option B) Map.empty Map.empty by transfer-prover lemma lookup-parametric: ((A ===> B) ===> A ===> B)(λm k. m k)(λm k. m k) by transfer-prover lemma update-parametric: assumes [transfer-rule]: bi-unique A shows (A ===> B ===> (A ===> rel-option B) ===> A ===> rel-option B) (λk v m. m(k 7→ v)) (λk v m. m(k 7→ v)) by transfer-prover

441 lemma delete-parametric: assumes [transfer-rule]: bi-unique A shows (A ===> (A ===> rel-option B) ===> A ===> rel-option B) (λk m. m(k := None)) (λk m. m(k := None)) by transfer-prover lemma is-none-parametric [transfer-rule]: (rel-option A ===> HOL.eq) Option.is-none Option.is-none by (auto simp add: Option.is-none-def rel-fun-def rel-option-iff split: option.split) lemma dom-parametric: assumes [transfer-rule]: bi-total A shows ((A ===> rel-option B) ===> rel-set A) dom dom unfolding dom-def [abs-def ] Option.is-none-def [symmetric] by transfer-prover lemma map-of-parametric [transfer-rule]: assumes [transfer-rule]: bi-unique R1 shows (list-all2 (rel-prod R1 R2 ) ===> R1 ===> rel-option R2 ) map-of map-of unfolding map-of-def by transfer-prover lemma map-entry-parametric [transfer-rule]: assumes [transfer-rule]: bi-unique A shows (A ===> (B ===> B) ===> (A ===> rel-option B) ===> A ===> rel-option B) (λk f m. (case m k of None ⇒ m | Some v ⇒ m (k 7→ (f v)))) (λk f m. (case m k of None ⇒ m | Some v ⇒ m (k 7→ (f v)))) by transfer-prover lemma tabulate-parametric: assumes [transfer-rule]: bi-unique A shows (list-all2 A ===> (A ===> B) ===> A ===> rel-option B) (λks f . (map-of (map (λk. (k, f k)) ks))) (λks f . (map-of (map (λk. (k, f k)) ks))) by transfer-prover lemma bulkload-parametric: (list-all2 A ===> HOL.eq ===> rel-option A) (λxs k. if k < length xs then Some (xs ! k) else None) (λxs k. if k < length xs then Some (xs ! k) else None) proof fix xs ys assume list-all2 A xs ys then show (HOL.eq ===> rel-option A) (λk. if k < length xs then Some (xs ! k) else None) (λk. if k < length ys then Some (ys ! k) else None) apply induct

442 apply auto unfolding rel-fun-def apply clarsimp apply (case-tac xa) apply (auto dest: list-all2-lengthD list-all2-nthD) done qed lemma map-parametric: ((A ===> B) ===> (C ===> D) ===> (B ===> rel-option C ) ===> A ===> rel-option D) (λf g m. (map-option g ◦ m ◦ f )) (λf g m. (map-option g ◦ m ◦ f )) by transfer-prover lemma combine-with-key-parametric: ((A ===> B ===> B ===> B) ===> (A ===> rel-option B) ===> (A ===> rel-option B) ===> (A ===> rel-option B)) (λf m1 m2 x. combine-options (f x)(m1 x)(m2 x)) (λf m1 m2 x. combine-options (f x)(m1 x)(m2 x)) unfolding combine-options-def by transfer-prover lemma combine-parametric: ((B ===> B ===> B) ===> (A ===> rel-option B) ===> (A ===> rel-option B) ===> (A ===> rel-option B)) (λf m1 m2 x. combine-options f (m1 x)(m2 x)) (λf m1 m2 x. combine-options f (m1 x)(m2 x)) unfolding combine-options-def by transfer-prover end

58.2 Type definition and primitive operations typedef ( 0a, 0b) mapping = UNIV :: ( 0a * 0b) set morphisms rep Mapping .. setup-lifting type-definition-mapping lift-definition empty :: ( 0a, 0b) mapping is Map.empty parametric empty-parametric . lift-definition lookup :: ( 0a, 0b) mapping ⇒ 0a ⇒ 0b option is λm k. m k parametric lookup-parametric . definition lookup-default d m k = (case Mapping.lookup m k of None ⇒ d | Some v ⇒ v) declare [[code drop: Mapping.lookup]] setup hCode.add-eqn (Code.Equation, true)@{thm Mapping.lookup.abs-eq}i

443 lift-definition update :: 0a ⇒ 0b ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping is λk v m. m(k 7→ v) parametric update-parametric . lift-definition delete :: 0a ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping is λk m. m(k := None) parametric delete-parametric . lift-definition filter :: ( 0a ⇒ 0b ⇒ bool) ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping is λP m k. case m k of None ⇒ None | Some v ⇒ if P k v then Some v else None . lift-definition keys :: ( 0a, 0b) mapping ⇒ 0a set is dom parametric dom-parametric . lift-definition tabulate :: 0a list ⇒ ( 0a ⇒ 0b) ⇒ ( 0a, 0b) mapping is λks f . (map-of (List.map (λk. (k, f k)) ks)) parametric tabulate-parametric . lift-definition bulkload :: 0a list ⇒ (nat, 0a) mapping is λxs k. if k < length xs then Some (xs ! k) else None parametric bulkload-parametric . lift-definition map :: ( 0c ⇒ 0a) ⇒ ( 0b ⇒ 0d) ⇒ ( 0a, 0b) mapping ⇒ ( 0c, 0d) mapping is λf g m. (map-option g ◦ m ◦ f ) parametric map-parametric . lift-definition map-values :: ( 0c ⇒ 0a ⇒ 0b) ⇒ ( 0c, 0a) mapping ⇒ ( 0c, 0b) mapping is λf m x. map-option (f x)(m x) . lift-definition combine-with-key :: ( 0a ⇒ 0b ⇒ 0b ⇒ 0b) ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping is λf m1 m2 x. combine-options (f x)(m1 x)(m2 x) parametric combine-with-key-parametric . lift-definition combine :: ( 0b ⇒ 0b ⇒ 0b) ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping is λf m1 m2 x. combine-options f (m1 x)(m2 x) parametric combine-parametric . definition All-mapping m P ←→ (∀ x. case Mapping.lookup m x of None ⇒ True | Some y ⇒ P x y) declare [[code drop: map]]

58.3 Functorial structure functor map: map by (transfer, auto simp add: fun-eq-iff option.map-comp option.map-id)+

444 58.4 Derived operations definition ordered-keys :: ( 0a::linorder, 0b) mapping ⇒ 0a list where ordered-keys m = (if finite (keys m) then sorted-list-of-set (keys m) else []) definition is-empty :: ( 0a, 0b) mapping ⇒ bool where is-empty m ←→ keys m = {} definition size :: ( 0a, 0b) mapping ⇒ nat where size m = (if finite (keys m) then card (keys m) else 0 ) definition replace :: 0a ⇒ 0b ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping where replace k v m = (if k ∈ keys m then update k v m else m) definition default :: 0a ⇒ 0b ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping where default k v m = (if k ∈ keys m then m else update k v m) Manual derivation of transfer rule is non-trivial lift-definition map-entry :: 0a ⇒ ( 0b ⇒ 0b) ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping is λk f m. (case m k of None ⇒ m | Some v ⇒ m (k 7→ (f v))) parametric map-entry-parametric . lemma map-entry-code [code]: map-entry k f m = (case lookup m k of None ⇒ m | Some v ⇒ update k (f v) m) by transfer rule definition map-default :: 0a ⇒ 0b ⇒ ( 0b ⇒ 0b) ⇒ ( 0a, 0b) mapping ⇒ ( 0a, 0b) mapping where map-default k v f m = map-entry k f (default k v m) definition of-alist :: ( 0k × 0v) list ⇒ ( 0k, 0v) mapping where of-alist xs = foldr (λ(k, v) m. update k v m) xs empty instantiation mapping :: (type, type) equal begin definition HOL.equal m1 m2 ←→ (∀ k. lookup m1 k = lookup m2 k) instance apply standard unfolding equal-mapping-def apply transfer apply auto

445 done end context includes lifting-syntax begin lemma [transfer-rule]: assumes [transfer-rule]: bi-total A and [transfer-rule]: bi-unique B shows (pcr-mapping A B ===> pcr-mapping A B ===> op=) HOL.eq HOL.equal unfolding equal by transfer-prover lemma of-alist-transfer [transfer-rule]: assumes [transfer-rule]: bi-unique R1 shows (list-all2 (rel-prod R1 R2 ) ===> pcr-mapping R1 R2 ) map-of of-alist unfolding of-alist-def [abs-def ] map-of-foldr [abs-def ] by transfer-prover end

58.5 Properties lemma mapping-eqI :(Vx. lookup m x = lookup m 0 x) =⇒ m = m 0 by transfer (simp add: fun-eq-iff ) lemma mapping-eqI 0: assumes Vx. x ∈ Mapping.keys m =⇒ Mapping.lookup-default d m x = Map- ping.lookup-default d m 0 x and Mapping.keys m = Mapping.keys m 0 shows m = m 0 proof (intro mapping-eqI ) show Mapping.lookup m x = Mapping.lookup m 0 x for x proof (cases Mapping.lookup m x) case None then have x ∈/ Mapping.keys m by transfer (simp add: dom-def ) then have x ∈/ Mapping.keys m 0 by (simp add: assms) then have Mapping.lookup m 0 x = None by transfer (simp add: dom-def ) with None show ?thesis by simp next case (Some y) then have A: x ∈ Mapping.keys m by transfer (simp add: dom-def ) then have x ∈ Mapping.keys m 0 by (simp add: assms) then have ∃ y 0. Mapping.lookup m 0 x = Some y 0

446 by transfer (simp add: dom-def ) with Some assms(1 )[OF A] show ?thesis by (auto simp add: lookup-default-def ) qed qed lemma lookup-update: lookup (update k v m) k = Some v by transfer simp lemma lookup-update-neq: k 6= k 0 =⇒ lookup (update k v m) k 0 = lookup m k 0 by transfer simp lemma lookup-update 0: Mapping.lookup (update k v m) k 0 = (if k = k 0 then Some v else lookup m k 0) by (auto simp: lookup-update lookup-update-neq) lemma lookup-empty: lookup empty k = None by transfer simp lemma lookup-filter: lookup (filter P m) k = (case lookup m k of None ⇒ None | Some v ⇒ if P k v then Some v else None) by transfer simp-all lemma lookup-map-values: lookup (map-values f m) k = map-option (f k)(lookup m k) by transfer simp-all lemma lookup-default-empty: lookup-default d empty k = d by (simp add: lookup-default-def lookup-empty) lemma lookup-default-update: lookup-default d (update k v m) k = v by (simp add: lookup-default-def lookup-update) lemma lookup-default-update-neq: k 6= k 0 =⇒ lookup-default d (update k v m) k 0 = lookup-default d m k 0 by (simp add: lookup-default-def lookup-update-neq) lemma lookup-default-update 0: lookup-default d (update k v m) k 0 = (if k = k 0 then v else lookup-default d m k 0) by (auto simp: lookup-default-update lookup-default-update-neq) lemma lookup-default-filter: lookup-default d (filter P m) k = (if P k (lookup-default d m k) then lookup-default d m k else d) by (simp add: lookup-default-def lookup-filter split: option.splits)

447 lemma lookup-default-map-values: lookup-default (f k d)(map-values f m) k = f k (lookup-default d m k) by (simp add: lookup-default-def lookup-map-values split: option.splits) lemma lookup-combine-with-key: Mapping.lookup (combine-with-key f m1 m2 ) x = combine-options (f x)(Mapping.lookup m1 x)(Mapping.lookup m2 x) by transfer (auto split: option.splits) lemma combine-altdef : combine f m1 m2 = combine-with-key (λ-. f ) m1 m2 by transfer 0 (rule refl) lemma lookup-combine: Mapping.lookup (combine f m1 m2 ) x = combine-options f (Mapping.lookup m1 x)(Mapping.lookup m2 x) by transfer (auto split: option.splits) lemma lookup-default-neutral-combine-with-key: assumes Vx. f k d x = x Vx. f k x d = x shows Mapping.lookup-default d (combine-with-key f m1 m2 ) k = f k (Mapping.lookup-default d m1 k)(Mapping.lookup-default d m2 k) by (auto simp: lookup-default-def lookup-combine-with-key assms split: option.splits) lemma lookup-default-neutral-combine: assumes Vx. f d x = x Vx. f x d = x shows Mapping.lookup-default d (combine f m1 m2 ) x = f (Mapping.lookup-default d m1 x)(Mapping.lookup-default d m2 x) by (auto simp: lookup-default-def lookup-combine assms split: option.splits) lemma lookup-map-entry: lookup (map-entry x f m) x = map-option f (lookup m x) by transfer (auto split: option.splits) lemma lookup-map-entry-neq: x 6= y =⇒ lookup (map-entry x f m) y = lookup m y by transfer (auto split: option.splits) lemma lookup-map-entry 0: lookup (map-entry x f m) y = (if x = y then map-option f (lookup m y) else lookup m y) by transfer (auto split: option.splits) lemma lookup-default: lookup (default x d m) x = Some (lookup-default d m x) unfolding lookup-default-def default-def by transfer (auto split: option.splits) lemma lookup-default-neq: x 6= y =⇒ lookup (default x d m) y = lookup m y unfolding lookup-default-def default-def by transfer (auto split: option.splits)

448 lemma lookup-default 0: lookup (default x d m) y = (if x = y then Some (lookup-default d m x) else lookup m y) unfolding lookup-default-def default-def by transfer (auto split: option.splits) lemma lookup-map-default: lookup (map-default x d f m) x = Some (f (lookup-default d m x)) unfolding lookup-default-def default-def by (simp add: map-default-def lookup-map-entry lookup-default lookup-default-def ) lemma lookup-map-default-neq: x 6= y =⇒ lookup (map-default x d f m) y = lookup m y unfolding lookup-default-def default-def by (simp add: map-default-def lookup-map-entry-neq lookup-default-neq) lemma lookup-map-default 0: lookup (map-default x d f m) y = (if x = y then Some (f (lookup-default d m x)) else lookup m y) unfolding lookup-default-def default-def by (simp add: map-default-def lookup-map-entry 0 lookup-default 0 lookup-default-def ) lemma lookup-tabulate: assumes distinct xs shows Mapping.lookup (Mapping.tabulate xs f ) x = (if x ∈ set xs then Some (f x) else None) using assms by transfer (auto simp: map-of-eq-None-iff o-def dest!: map-of-SomeD) lemma lookup-of-alist: Mapping.lookup (Mapping.of-alist xs) k = map-of xs k by transfer simp-all lemma keys-is-none-rep [code-unfold]: k ∈ keys m ←→ ¬ (Option.is-none (lookup m k)) by transfer (auto simp add: Option.is-none-def ) lemma update-update: update k v (update k w m) = update k v m k 6= l =⇒ update k v (update l w m) = update l w (update k v m) by (transfer; simp add: fun-upd-twist)+ lemma update-delete [simp]: update k v (delete k m) = update k v m by transfer simp lemma delete-update: delete k (update k v m) = delete k m k 6= l =⇒ delete k (update l v m) = update l v (delete k m) by (transfer; simp add: fun-upd-twist)+

449 lemma delete-empty [simp]: delete k empty = empty by transfer simp lemma replace-update: k ∈/ keys m =⇒ replace k v m = m k ∈ keys m =⇒ replace k v m = update k v m by (transfer; auto simp add: replace-def fun-upd-twist)+ lemma map-values-update: map-values f (update k v m) = update k (f k v)(map-values f m) by transfer (simp-all add: fun-eq-iff ) lemma size-mono: finite (keys m 0) =⇒ keys m ⊆ keys m 0 =⇒ size m ≤ size m 0 unfolding size-def by (auto intro: card-mono) lemma size-empty [simp]: size empty = 0 unfolding size-def by transfer simp lemma size-update: finite (keys m) =⇒ size (update k v m) = (if k ∈ keys m then size m else Suc (size m)) unfolding size-def by transfer (auto simp add: insert-dom) lemma size-delete: size (delete k m) = (if k ∈ keys m then size m − 1 else size m) unfolding size-def by transfer simp lemma size-tabulate [simp]: size (tabulate ks f ) = length (remdups ks) unfolding size-def by transfer (auto simp add: map-of-map-restrict card-set comp-def ) lemma keys-filter: keys (filter P m) ⊆ keys m by transfer (auto split: option.splits) lemma size-filter: finite (keys m) =⇒ size (filter P m) ≤ size m by (intro size-mono keys-filter) lemma bulkload-tabulate: bulkload xs = tabulate [0 ..

450 lemma is-empty-replace [simp]: is-empty (replace k v m) ←→ is-empty m unfolding is-empty-def replace-def by transfer auto lemma is-empty-default [simp]: ¬ is-empty (default k v m) unfolding is-empty-def default-def by transfer auto lemma is-empty-map-entry [simp]: is-empty (map-entry k f m) ←→ is-empty m unfolding is-empty-def by transfer (auto split: option.split) lemma is-empty-map-values [simp]: is-empty (map-values f m) ←→ is-empty m unfolding is-empty-def by transfer (auto simp: fun-eq-iff ) lemma is-empty-map-default [simp]: ¬ is-empty (map-default k v f m) by (simp add: map-default-def ) lemma keys-dom-lookup: keys m = dom (Mapping.lookup m) by transfer rule lemma keys-empty [simp]: keys empty = {} by transfer simp lemma keys-update [simp]: keys (update k v m) = insert k (keys m) by transfer simp lemma keys-delete [simp]: keys (delete k m) = keys m − {k} by transfer simp lemma keys-replace [simp]: keys (replace k v m) = keys m unfolding replace-def by transfer (simp add: insert-absorb) lemma keys-default [simp]: keys (default k v m) = insert k (keys m) unfolding default-def by transfer (simp add: insert-absorb) lemma keys-map-entry [simp]: keys (map-entry k f m) = keys m by transfer (auto split: option.split) lemma keys-map-default [simp]: keys (map-default k v f m) = insert k (keys m) by (simp add: map-default-def ) lemma keys-map-values [simp]: keys (map-values f m) = keys m by transfer (simp-all add: dom-def ) lemma keys-combine-with-key [simp]: Mapping.keys (combine-with-key f m1 m2 ) = Mapping.keys m1 ∪ Mapping.keys m2 by transfer (auto simp: dom-def combine-options-def split: option.splits) lemma keys-combine [simp]: Mapping.keys (combine f m1 m2 ) = Mapping.keys m1 ∪ Mapping.keys m2

451 by (simp add: combine-altdef ) lemma keys-tabulate [simp]: keys (tabulate ks f ) = set ks by transfer (simp add: map-of-map-restrict o-def ) lemma keys-of-alist [simp]: keys (of-alist xs) = set (List.map fst xs) by transfer (simp-all add: dom-map-of-conv-image-fst) lemma keys-bulkload [simp]: keys (bulkload xs) = {0 ..

452 by (simp add: replace-def ) lemma ordered-keys-default [simp]: k ∈ keys m =⇒ ordered-keys (default k v m) = ordered-keys m finite (keys m) =⇒ k ∈/ keys m =⇒ ordered-keys (default k v m) = insort k (ordered-keys m) by (simp-all add: default-def ) lemma ordered-keys-map-entry [simp]: ordered-keys (map-entry k f m) = ordered-keys m by (simp add: ordered-keys-def ) lemma ordered-keys-map-default [simp]: k ∈ keys m =⇒ ordered-keys (map-default k v f m) = ordered-keys m finite (keys m) =⇒ k ∈/ keys m =⇒ ordered-keys (map-default k v f m) = insort k (ordered-keys m) by (simp-all add: map-default-def ) lemma ordered-keys-tabulate [simp]: ordered-keys (tabulate ks f ) = sort (remdups ks) by (simp add: ordered-keys-def sorted-list-of-set-sort-remdups) lemma ordered-keys-bulkload [simp]: ordered-keys (bulkload ks) = [0 ..

453 = k 0 ∨ P k 0 v 0) unfolding All-mapping-def proof safe assume ∀ x. case Mapping.lookup (Mapping.update k v m) x of None ⇒ True | Some y ⇒ P x y then have ∗: case Mapping.lookup (Mapping.update k v m) x of None ⇒ True | Some y ⇒ P x y for x by blast from ∗[of k] show P k v by (simp add: lookup-update) show case Mapping.lookup m x of None ⇒ True | Some v 0 ⇒ k = x ∨ P x v 0 for x using ∗[of x] by (auto simp add: lookup-update 0 split: if-splits option.splits) next assume P k v assume ∀ x. case Mapping.lookup m x of None ⇒ True | Some v 0 ⇒ k = x ∨ P x v 0 then have A: case Mapping.lookup m x of None ⇒ True | Some v 0 ⇒ k = x ∨ P x v 0 for x by blast show case Mapping.lookup (Mapping.update k v m) x of None ⇒ True | Some xa ⇒ P x xa for x 0 using hP k v i A[of x] by (auto simp: lookup-update split: option.splits) qed lemma All-mapping-update: P k v =⇒ All-mapping m (λk 0 v 0. k = k 0 ∨ P k 0 v 0) =⇒ All-mapping (Mapping.update k v m) P by (simp add: All-mapping-update-iff ) lemma All-mapping-filter-iff : All-mapping (filter P m) Q ←→ All-mapping m (λk v. P k v −→ Q k v) by (auto simp: All-mapping-def lookup-filter split: option.splits) lemma All-mapping-filter: All-mapping m Q =⇒ All-mapping (filter P m) Q by (auto simp: All-mapping-filter-iff intro: All-mapping-mono) lemma All-mapping-map-values: All-mapping (map-values f m) P ←→ All-mapping m (λk v. P k (f k v)) by (auto simp: All-mapping-def lookup-map-values split: option.splits) lemma All-mapping-tabulate:(∀ x∈set xs. P x (f x)) =⇒ All-mapping (Mapping.tabulate xs f ) P unfolding All-mapping-def apply (intro allI ) apply transfer apply (auto split: option.split dest!: map-of-SomeD) done

454 lemma All-mapping-alist: (Vk v. (k, v) ∈ set xs =⇒ P k v) =⇒ All-mapping (Mapping.of-alist xs) P by (auto simp: All-mapping-def lookup-of-alist dest!: map-of-SomeD split: op- tion.splits) lemma combine-empty [simp]: combine f Mapping.empty y = y combine f y Map- ping.empty = y by (transfer; force)+ lemma (in abel-semigroup) comm-monoid-set-combine: comm-monoid-set (combine f ) Mapping.empty by standard (transfer fixing: f , simp add: combine-options-ac[of f ] ac-simps)+ locale combine-mapping-abel-semigroup = abel-semigroup begin sublocale combine: comm-monoid-set combine f Mapping.empty by (rule comm-monoid-set-combine) lemma fold-combine-code: combine.F g (set xs) = foldr (λx. combine f (g x)) (remdups xs) Mapping.empty proof − have combine.F g (set xs) = foldr (λx. combine f (g x)) xs Mapping.empty if distinct xs for xs using that by (induction xs) simp-all from this[of remdups xs] show ?thesis by simp qed lemma keys-fold-combine: finite A =⇒ Mapping.keys (combine.F g A) = (S x∈A. Mapping.keys (g x)) by (induct A rule: finite-induct) simp-all end

58.6 Code generator setup hide-const (open) empty is-empty rep lookup lookup-default filter update delete ordered-keys keys size replace default map-entry map-default tabulate bulkload map map-values combine of-alist end

59 Implementation of mappings with Association Lists theory AList-Mapping imports AList Mapping

455 begin lift-definition Mapping :: ( 0a × 0b) list ⇒ ( 0a, 0b) mapping is map-of . code-datatype Mapping lemma lookup-Mapping [simp, code]: Mapping.lookup (Mapping xs) = map-of xs by transfer rule lemma keys-Mapping [simp, code]: Mapping.keys (Mapping xs) = set (map fst xs) by transfer (simp add: dom-map-of-conv-image-fst) lemma empty-Mapping [code]: Mapping.empty = Mapping [] by transfer simp lemma is-empty-Mapping [code]: Mapping.is-empty (Mapping xs) ←→ List.null xs by (cases xs)(simp-all add: is-empty-def null-def ) lemma update-Mapping [code]: Mapping.update k v (Mapping xs) = Mapping (AList.update k v xs) by transfer (simp add: update-conv 0) lemma delete-Mapping [code]: Mapping.delete k (Mapping xs) = Mapping (AList.delete k xs) by transfer (simp add: delete-conv 0) lemma ordered-keys-Mapping [code]: Mapping.ordered-keys (Mapping xs) = sort (remdups (map fst xs)) by (simp only: ordered-keys-def keys-Mapping sorted-list-of-set-sort-remdups) simp lemma size-Mapping [code]: Mapping.size (Mapping xs) = length (remdups (map fst xs)) by (simp add: size-def length-remdups-card-conv dom-map-of-conv-image-fst) lemma tabulate-Mapping [code]: Mapping.tabulate ks f = Mapping (map (λk. (k, f k)) ks) by transfer (simp add: map-of-map-restrict) lemma bulkload-Mapping [code]: Mapping.bulkload vs = Mapping (map (λn. (n, vs ! n)) [0 ..

456 proof − have ∗:(a, b) ∈ set xs =⇒ a ∈ fst ‘ set xs for a b xs by (auto simp add: image-def intro!: bexI ) show ?thesis apply transfer apply (auto intro!: map-of-eqI ) apply (auto dest!: map-of-eq-dom intro: ∗) done qed lemma map-values-Mapping [code]: Mapping.map-values f (Mapping xs) = Mapping (map (λ(x,y). (x, f x y)) xs) for f :: 0c ⇒ 0a ⇒ 0b and xs :: ( 0c × 0a) list apply transfer apply (rule ext) subgoal for f xs x by (induct xs) auto done lemma combine-with-key-code [code]: Mapping.combine-with-key f (Mapping xs)(Mapping ys) = Mapping.tabulate (remdups (map fst xs @ map fst ys)) (λx. the (combine-options (f x)(map-of xs x)(map-of ys x))) apply transfer apply (rule ext) apply (rule sym) subgoal for f xs ys x apply (cases map-of xs x; cases map-of ys x; simp) apply (force simp: map-of-eq-None-iff combine-options-def option.the-def o-def image-iff dest: map-of-SomeD split: option.splits)+ done done lemma combine-code [code]: Mapping.combine f (Mapping xs)(Mapping ys) = Mapping.tabulate (remdups (map fst xs @ map fst ys)) (λx. the (combine-options f (map-of xs x)(map-of ys x))) apply transfer apply (rule ext) apply (rule sym) subgoal for f xs ys x apply (cases map-of xs x; cases map-of ys x; simp) apply (force simp: map-of-eq-None-iff combine-options-def option.the-def o-def image-iff dest: map-of-SomeD split: option.splits)+ done done lemma map-of-filter-distinct:

457 assumes distinct (map fst xs) shows map-of (filter P xs) x = (case map-of xs x of None ⇒ None | Some y ⇒ if P (x,y) then Some y else None) using assms by (auto simp: map-of-eq-None-iff filter-map distinct-map-filter dest: map-of-SomeD simp del: map-of-eq-Some-iff intro!: map-of-is-SomeI split: option.splits) lemma filter-Mapping [code]: Mapping.filter P (Mapping xs) = Mapping (filter (λ(k,v). P k v)(AList.clearjunk xs)) apply transfer apply (rule ext) apply (subst map-of-filter-distinct) apply (simp-all add: map-of-clearjunk split: option.split) done lemma [code nbe]: HOL.equal (x :: ( 0a, 0b) mapping) x ←→ True by (fact equal-refl) end

60 A simple cookbook example how to eliminate choice in programs. theory Execute-Choice imports Main ∼∼/src/HOL/Library/AList-Mapping begin A trivial example: definition valuesum :: ( 0a, 0b :: ab-group-add) mapping ⇒ 0b where valuesum m = (P k ∈ Mapping.keys m. the (Mapping.lookup m k)) Not that instead of defining valuesum with choice, we define it directly and derive a description involving choice afterwards: lemma valuesum-rec: assumes fin: finite (dom (Mapping.lookup m)) shows valuesum m = (if Mapping.is-empty m then 0 else let l = (SOME l. l ∈ Mapping.keys m) in the (Mapping.lookup m l) + valuesum (Mapping.delete l m)) proof (cases Mapping.is-empty m) case True then show ?thesis by (simp add: is-empty-def keys-def valuesum-def ) next case False then have l: ∃ l. l ∈ dom (Mapping.lookup m) unfolding is-empty-def by transfer auto then have (let l = SOME l. l ∈ dom (Mapping.lookup m) in

458 the (Mapping.lookup m l) + (P k ∈ dom (Mapping.lookup m) − {l}. the (Mapping.lookup m k))) = (P k ∈ dom (Mapping.lookup m). the (Mapping.lookup m k)) proof (rule someI2-ex) fix l note fin moreover assume l ∈ dom (Mapping.lookup m) moreover obtain A where A = dom (Mapping.lookup m) − {l} by simp ultimately have dom (Mapping.lookup m) = insert l A and finite A and l ∈/ A by auto then show (let l = l in the (Mapping.lookup m l) + (P k ∈ dom (Mapping.lookup m) − {l}. the (Mapping.lookup m k))) = (P k ∈ dom (Mapping.lookup m). the (Mapping.lookup m k)) by simp qed then show ?thesis unfolding is-empty-def valuesum-def by transfer simp qed

In the context of the else-branch we can show that the exact choice is irrel- vant; in practice, finding this point where choice becomes irrelevant is the most difficult thing! lemma valuesum-choice: finite (Mapping.keys M ) =⇒ x ∈ Mapping.keys M =⇒ y ∈ Mapping.keys M =⇒ the (Mapping.lookup M x) + valuesum (Mapping.delete x M ) = the (Mapping.lookup M y) + valuesum (Mapping.delete y M ) unfolding valuesum-def by transfer (simp add: sum-diff )

Given valuesum-rec as initial description, we stepwise refine it to something executable; first, we formally insert the constructor AList-Mapping.Mapping and split the one equation into two, where the second one provides the necessary context: lemma valuesum-rec-Mapping: shows [code]: valuesum (Mapping []) = 0 and valuesum (Mapping (x # xs)) = (let l = (SOME l. l ∈ Mapping.keys (Mapping (x # xs))) in the (Mapping.lookup (Mapping (x # xs)) l) + valuesum (Mapping.delete l (Mapping (x # xs)))) by (simp-all add: valuesum-rec finite-dom-map-of is-empty-Mapping null-def )

As a side effect the precondition disappears (but note this has nothing to do with choice!). The first equation deals with the uncritical empty case and can already be used for code generation. Using valuesum-choice, we are able to prove an executable version of value- sum: lemma valuesum-rec-exec [code]: valuesum (Mapping (x # xs)) = (let l = fst (hd (x # xs)) in

459 the (Mapping.lookup (Mapping (x # xs)) l) + valuesum (Mapping.delete l (Mapping (x # xs)))) proof − let ?M = Mapping (x # xs) let ?l1 = (SOME l. l ∈ Mapping.keys ?M ) let ?l2 = fst (hd (x # xs)) have finite (Mapping.keys ?M ) by (simp add: keys-Mapping) moreover have ?l1 ∈ Mapping.keys ?M by (rule someI )(auto simp add: keys-Mapping) moreover have ?l2 ∈ Mapping.keys ?M by (simp add: keys-Mapping) ultimately have the (Mapping.lookup ?M ?l1 ) + valuesum (Mapping.delete ?l1 ?M ) = the (Mapping.lookup ?M ?l2 ) + valuesum (Mapping.delete ?l2 ?M ) by (rule valuesum-choice) then show ?thesis by (simp add: valuesum-rec-Mapping) qed

See how it works: value valuesum (Mapping [( 00abc 00, (42 ::int)), ( 00def 00, 1705 )]) end

61 Theory of Integration on real intervals theory Gauge-Integration imports Complex-Main begin

Attention: This theory defines the Integration on real intervals. This is just a example theory for historical / expository interests. A better replacement is found in the Multivariate Analysis library. This defines the gauge integral on real vector spaces and in the Real Integral theory is a specialization to the integral on arbitrary real intervals. The Multivariate Analysis package also provides a better support for analysis on integrals.

We follow John Harrison in formalizing the Gauge integral.

61.1 Gauges definition gauge :: [real set, real => real] => bool where gauge E g = (∀ x∈E. 0 < g(x))

61.2 Gauge-fine divisions inductive fine :: [real ⇒ real, real × real, (real × real × real) list] ⇒ bool

460 for δ :: real ⇒ real where fine-Nil: fine δ (a, a) [] | fine-Cons: [[fine δ (b, c) D; a < b; a ≤ x; x ≤ b; b − a < δ x]] =⇒ fine δ (a, c) ((a, x, b)# D) lemmas fine-induct [induct set: fine] = fine.induct [of δ (a,b) D case-prod P, unfolded split-conv] for δ a b D P lemma fine-single: [[a < b; a ≤ x; x ≤ b; b − a < δ x]] =⇒ fine δ (a, b) [(a, x, b)] by (rule fine-Cons [OF fine-Nil]) lemma fine-append: [[fine δ (a, b) D; fine δ (b, c) D 0]] =⇒ fine δ (a, c)(D @ D 0) by (induct set: fine, simp, simp add: fine-Cons) lemma fine-imp-le: fine δ (a, b) D =⇒ a ≤ b by (induct set: fine, simp-all) lemma nonempty-fine-imp-less: [[fine δ (a, b) D; D 6= []]] =⇒ a < b apply (induct set: fine, simp) apply (drule fine-imp-le, simp) done lemma fine-Nil-iff : fine δ (a, b) [] ←→ a = b by (auto elim: fine.cases intro: fine.intros) lemma fine-same-iff : fine δ (a, a) D ←→ D = [] proof assume fine δ (a, a) D thus D = [] by (metis nonempty-fine-imp-less less-irrefl) next assume D = [] thus fine δ (a, a) D by (simp add: fine-Nil) qed lemma empty-fine-imp-eq: [[fine δ (a, b) D; D = []]] =⇒ a = b by (simp add: fine-Nil-iff ) lemma mem-fine: [[fine δ (a, b) D;(u, x, v) ∈ set D]] =⇒ u < v ∧ u ≤ x ∧ x ≤ v by (induct set: fine, simp, force) lemma mem-fine2 : [[fine δ (a, b) D;(u, z, v) ∈ set D]] =⇒ a ≤ u ∧ v ≤ b apply (induct arbitrary: z u v set: fine, auto)

461 apply (simp add: fine-imp-le) apply (erule order-trans [OF less-imp-le], simp) done lemma mem-fine3 : [[fine δ (a, b) D;(u, z, v) ∈ set D]] =⇒ v − u < δ z by (induct arbitrary: z u v set: fine) auto lemma BOLZANO: fixes P :: real ⇒ real ⇒ bool assumes 1 : a ≤ b assumes 2 : Va b c. [[P a b; P b c; a ≤ b; b ≤ c]] =⇒ P a c assumes 3 : Vx. ∃ d>0 . ∀ a b. a ≤ x & x ≤ b &(b−a) < d −→ P a b shows P a b using 1 2 3 by (rule Bolzano)

We can always find a division that is fine wrt any gauge lemma fine-exists: assumes a ≤ b and gauge {a..b} δ shows ∃ D. fine δ (a, b) D proof − { fix u v :: real assume u ≤ v have a ≤ u =⇒ v ≤ b =⇒ ∃ D. fine δ (u, v) D apply (induct u v rule: BOLZANO, rule hu ≤ v i) apply (simp, fast intro: fine-append) apply (case-tac a ≤ x ∧ x ≤ b) apply (rule-tac x=δ x in exI ) apply (rule conjI ) apply (simp add: hgauge {a..b} δi [unfolded gauge-def ]) apply (clarify, rename-tac u v) apply (case-tac u = v) apply (fast intro: fine-Nil) apply (subgoal-tac u < v, fast intro: fine-single, simp) apply (rule-tac x=1 in exI , clarsimp) done } with ha ≤ bi show ?thesis by auto qed lemma fine-covers-all: assumes fine δ (a, c) D and a < x and x ≤ c shows ∃ N < length D. ∀ d t e. D ! N = (d,t,e) −→ d < x ∧ x ≤ e using assms proof (induct set: fine) case (2 b c D a t) thus ?case proof (cases b < x) case True with 2 obtain N where ∗: N < length D and ∗∗: D ! N = (d,t,e) =⇒ d < x ∧ x ≤ e for d t e by auto

462 hence Suc N < length ((a,t,b)#D) ∧ (∀ d t 0 e. ((a,t,b)#D)! Suc N = (d,t 0,e) −→ d < x ∧ x ≤ e) by auto thus ?thesis by auto next case False with 2 have 0 < length ((a,t,b)#D) ∧ (∀ d t 0 e. ((a,t,b)#D)! 0 = (d,t 0,e) −→ d < x ∧ x ≤ e) by auto thus ?thesis by auto qed qed auto lemma fine-append-split: assumes fine δ (a,b) D and D2 6= [] and D = D1 @ D2 shows fine δ (a,fst (hd D2 )) D1 (is ?fine1 ) and fine δ (fst (hd D2 ), b) D2 (is ?fine2 ) proof − from assms have ?fine1 ∧ ?fine2 proof (induct arbitrary: D1 D2 ) case (2 b c D a 0 x D1 D2 ) note induct = this

thus ?case proof (cases D1 ) case Nil hence fst (hd D2 ) = a 0 using 2 by auto with fine-Cons[OF hfine δ (b,c) D i induct(3 ,4 ,5 )] Nil induct show ?thesis by (auto intro: fine-Nil) next case (Cons d1 D1 0) 0 with induct(2 )[OF hD2 6= []i, of D1 ] induct(8 ) have fine δ (b, fst (hd D2 )) D1 0 and fine δ (fst (hd D2 ), c) D2 and d1 = (a 0, x, b) by auto with fine-Cons[OF this(1 ) induct(3 ,4 ,5 ), OF induct(6 )] Cons show ?thesis by auto qed qed auto thus ?fine1 and ?fine2 by auto qed lemma fine-δ-expand: assumes fine δ (a,b) D and Vx. a ≤ x =⇒ x ≤ b =⇒ δ x ≤ δ 0 x shows fine δ 0 (a,b) D using assms proof induct case 1 show ?case by (rule fine-Nil) next case (2 b c D a x) show ?case

463 proof (rule fine-Cons) show fine δ 0 (b,c) D using 2 by auto from fine-imp-le[OF 2 (1 )] 2 (6 ) hx ≤ bi show b − a < δ 0 x using 2 (7 )[OF ha ≤ x i] by auto qed (auto simp add: 2 ) qed lemma fine-single-boundaries: assumes fine δ (a,b) D and D = [(d, t, e)] shows a = d ∧ b = e using assms proof induct case (2 b c D a x) hence D = [] and a = d and b = e by auto moreover from hfine δ (b,c) D i hD = []i have b = c by (rule empty-fine-imp-eq) ultimately show ?case by simp qed auto lemma fine-sum-list-eq-diff : fixes f :: real ⇒ real shows fine δ (a, b) D =⇒ (P (u, x, v)←D. f v − f u) = f b − f a by (induct set: fine) simp-all

Lemmas about combining gauges lemma gauge-min: [| gauge(E) g1 ; gauge(E) g2 |] ==> gauge(E) (%x. min (g1 (x)) (g2 (x))) by (simp add: gauge-def ) lemma fine-min: fine (%x. min (g1 (x)) (g2 (x))) (a,b) D ==> fine(g1 )(a,b) D & fine(g2 )(a,b) D apply (erule fine.induct) apply (simp add: fine-Nil) apply (simp add: fine-Cons) done

61.3 Riemann sum definition rsum :: [(real × real × real) list, real ⇒ real] ⇒ real where rsum D f = (P (u, x, v)←D. f x ∗ (v − u)) lemma rsum-Nil [simp]: rsum [] f = 0 unfolding rsum-def by simp lemma rsum-Cons [simp]: rsum ((u, x, v)# D) f = f x ∗ (v − u) + rsum D f

464 unfolding rsum-def by simp lemma rsum-zero [simp]: rsum D (λx. 0 ) = 0 by (induct D, auto) lemma rsum-left-distrib: rsum D f ∗ c = rsum D (λx. f x ∗ c) by (induct D, auto simp add: algebra-simps) lemma rsum-right-distrib: c ∗ rsum D f = rsum D (λx. c ∗ f x) by (induct D, auto simp add: algebra-simps) lemma rsum-add: rsum D (λx. f x + g x) = rsum D f + rsum D g by (induct D, auto simp add: algebra-simps) lemma rsum-append: rsum (D1 @ D2 ) f = rsum D1 f + rsum D2 f unfolding rsum-def map-append sum-list-append ..

61.4 Gauge integrability (definite) definition Integral :: [(real∗real),real=>real,real] => bool where Integral = (%(a,b) f k. ∀ e > 0 . (∃ δ. gauge {a .. b} δ & (∀ D. fine δ (a,b) D −−> |rsum D f − k| < e))) lemma Integral-eq: Integral (a, b) f k ←→ (∀ e>0 . ∃ δ. gauge {a..b} δ ∧ (∀ D. fine δ (a,b) D −→ |rsum D f − k| < e)) unfolding Integral-def by simp lemma IntegralI : assumes Ve. 0 < e =⇒ ∃ δ. gauge {a..b} δ ∧ (∀ D. fine δ (a, b) D −→ |rsum D f − k| < e) shows Integral (a, b) f k using assms unfolding Integral-def by auto lemma IntegralE: assumes Integral (a, b) f k and 0 < e obtains δ where gauge {a..b} δ and ∀ D. fine δ (a, b) D −→ |rsum D f − k| < e using assms unfolding Integral-def by auto lemma Integral-def2 : Integral = (%(a,b) f k. ∀ e>0 . (∃ δ. gauge {a..b} δ & (∀ D. fine δ (a,b) D −−> |rsum D f − k| ≤ e))) unfolding Integral-def apply (safe intro!: ext)

465 apply (fast intro: less-imp-le) apply (drule-tac x=e/2 in spec) apply force done

The integral is unique if it exists lemma Integral-unique: assumes le: a ≤ b assumes 1 : Integral (a, b) f k1 assumes 2 : Integral (a, b) f k2 shows k1 = k2 proof (rule ccontr) assume k1 6= k2 hence e: 0 < |k1 − k2 | / 2 by simp obtain d1 where gauge {a..b} d1 and d1 : ∀ D. fine d1 (a, b) D −→ |rsum D f − k1 | < |k1 − k2 | / 2 using 1 e by (rule IntegralE) obtain d2 where gauge {a..b} d2 and d2 : ∀ D. fine d2 (a, b) D −→ |rsum D f − k2 | < |k1 − k2 | / 2 using 2 e by (rule IntegralE) have gauge {a..b} (λx. min (d1 x)(d2 x)) using hgauge {a..b} d1 i and hgauge {a..b} d2 i by (rule gauge-min) then obtain D where fine (λx. min (d1 x)(d2 x)) (a, b) D using fine-exists [OF le] by fast hence fine d1 (a, b) D and fine d2 (a, b) D by (auto dest: fine-min) hence |rsum D f − k1 | < |k1 − k2 | / 2 and |rsum D f − k2 | < |k1 − k2 | / 2 using d1 d2 by simp-all hence |rsum D f − k1 | + |rsum D f − k2 | < |k1 − k2 | / 2 + |k1 − k2 | / 2 by (rule add-strict-mono) thus False by auto qed lemma Integral-zero: Integral(a,a) f 0 apply (rule IntegralI ) apply (rule-tac x = λx. 1 in exI ) apply (simp add: fine-same-iff gauge-def ) done lemma Integral-same-iff [simp]: Integral (a, a) f k ←→ k = 0 by (auto intro: Integral-zero Integral-unique) lemma Integral-zero-fun: Integral (a,b)(λx. 0 ) 0 apply (rule IntegralI ) apply (rule-tac x=λx. 1 in exI , simp add: gauge-def ) done lemma fine-rsum-const: fine δ (a,b) D =⇒ rsum D (λx. c) = (c ∗ (b − a))

466 unfolding rsum-def by (induct set: fine, auto simp add: algebra-simps) lemma Integral-mult-const: a ≤ b =⇒ Integral(a,b)(λx. c)(c ∗ (b − a)) apply (cases a = b, simp) apply (rule IntegralI ) apply (rule-tac x = λx. b − a in exI ) apply (rule conjI , simp add: gauge-def ) apply (clarify) apply (subst fine-rsum-const, assumption, simp) done lemma Integral-eq-diff-bounds: a ≤ b =⇒ Integral(a,b)(λx. 1 )(b − a) using Integral-mult-const [of a b 1 ] by simp lemma Integral-mult: [| a ≤ b; Integral(a,b) f k |] ==> Integral(a,b) (%x. c ∗ f x)(c ∗ k) apply (auto simp add: order-le-less) apply (cases c = 0 , simp add: Integral-zero-fun) apply (rule IntegralI ) apply (erule-tac e=e / |c| in IntegralE, simp) apply (rule-tac x=δ in exI , clarify) apply (drule-tac x=D in spec, clarify) apply (simp add: pos-less-divide-eq abs-mult [symmetric] algebra-simps rsum-right-distrib) done lemma Integral-add: assumes Integral (a, b) f x1 assumes Integral (b, c) f x2 assumes a ≤ b and b ≤ c shows Integral (a, c) f (x1 + x2 ) proof (cases a < b ∧ b < c, rule IntegralI ) fix ε :: real assume 0 < ε hence 0 < ε / 2 by auto

assume a < b ∧ b < c hence a < b and b < c by auto

obtain δ1 where δ1-gauge: gauge {a..b} δ1 and I1 : fine δ1 (a,b) D =⇒ | rsum D f − x1 | < (ε / 2 ) for D using IntegralE [OF hIntegral (a, b) f x1 i h0 < ε/2 i] by auto

obtain δ2 where δ2-gauge: gauge {b..c} δ2 and I2 : fine δ2 (b,c) D =⇒ | rsum D f − x2 | < (ε / 2 ) for D using IntegralE [OF hIntegral (b, c) f x2 i h0 < ε/2 i] by auto

define δ where δ x = (if x < b then min (δ1 x)(b − x)

467 else if x = b then min (δ1 b)(δ2 b) else min (δ2 x)(x − b)) for x have gauge {a..c} δ using δ1-gauge δ2-gauge unfolding δ-def gauge-def by auto moreover { fix D :: (real × real × real) list assume fine: fine δ (a,c) D from fine-covers-all[OF this ha < bi hb ≤ ci] obtain N where N < length D and ∗: ∀ d t e. D ! N = (d, t, e) −→ d < b ∧ b ≤ e by auto obtain d t e where D-eq: D ! N = (d, t, e) by (cases D!N , auto) with ∗ have d < b and b ≤ e by auto have in-D:(d, t, e) ∈ set D using D-eq[symmetric] using hN < length D i by auto

from mem-fine[OF fine in-D] have d < e and d ≤ t and t ≤ e by auto

have t = b proof (rule ccontr) assume t 6= b with mem-fine3 [OF fine in-D] hb ≤ e i hd ≤ t i ht ≤ e i hd < bi δ-def show False by (cases t < b) auto qed

let ?D1 = take N D let ?D2 = drop N D define D1 where D1 = take N D @ [(d, t, b)] define D2 where D2 = (if b = e then [] else [(b, t, e)]) @ drop (Suc N ) D

from hd-drop-conv-nth[OF hN < length D i] have fst (hd ?D2 ) = d using hD ! N = (d, t, e)i by auto with fine-append-split[OF - - append-take-drop-id[symmetric]] have fine1 : fine δ (a,d) ?D1 and fine2 : fine δ (d,c) ?D2 using hN < length D i fine by auto

have fine δ1 (a,b) D1 unfolding D1-def proof (rule fine-append) show fine δ1 (a, d) ?D1 proof (rule fine1 [THEN fine-δ-expand]) fix x assume a ≤ x x ≤ d hence x ≤ b using hd < bi hx ≤ d i by auto thus δ x ≤ δ1 x unfolding δ-def by auto qed

have b − d < δ1 t

468 using mem-fine3 [OF fine in-D] δ-def hb ≤ e i ht = bi by auto from hd < bi hd ≤ t i ht = bi this show fine δ1 (d, b) [(d, t, b)] using fine-single by auto qed note rsum1 = I1 [OF this]

have drop-split: drop N D = [D ! N ]@ drop (Suc N ) D using Cons-nth-drop-Suc[OF hN < length D i] by simp

have fine2 : fine δ2 (e,c)(drop (Suc N ) D) proof (cases drop (Suc N ) D = []) case True note ∗ = fine2 [simplified drop-split True D-eq append-Nil2 ] have e = c using fine-single-boundaries[OF ∗ refl] by auto thus ?thesis unfolding True using fine-Nil by auto next case False note ∗ = fine-append-split[OF fine2 False drop-split] from fine-single-boundaries[OF ∗(1 )] have fst (hd (drop (Suc N ) D)) = e using D-eq by auto with ∗(2 ) have fine δ (e,c)(drop (Suc N ) D) by auto thus ?thesis proof (rule fine-δ-expand) fix x assume e ≤ x and x ≤ c thus δ x ≤ δ2 x using hb ≤ e i unfolding δ-def by auto qed qed

have fine δ2 (b, c) D2 proof (cases e = b) case True thus ?thesis using fine2 by (simp add: D1-def D2-def ) next case False have e − b < δ2 b using mem-fine3 [OF fine in-D] δ-def hd < bi ht = bi by auto with False ht = bi hb ≤ e i show ?thesis using D2-def by (auto intro!: fine-append[OF - fine2 ] fine-single simp del: append-Cons) qed note rsum2 = I2 [OF this]

have rsum D f = rsum (take N D) f + rsum [D ! N ] f + rsum (drop (Suc N ) D) f using rsum-append[symmetric] Cons-nth-drop-Suc[OF hN < length D i] by auto also have ... = rsum D1 f + rsum D2 f by (cases b = e, auto simp add: D1-def D2-def D-eq rsum-append algebra-simps) finally have |rsum D f − (x1 + x2 )| < ε

469 using add-strict-mono[OF rsum1 rsum2 ] by simp } ultimately show ∃ δ. gauge {a .. c} δ ∧ (∀ D. fine δ (a,c) D −→ |rsum D f − (x1 + x2 )| < ε) by blast next case False hence a = b ∨ b = c using ha ≤ bi and hb ≤ ci by auto thus ?thesis proof (rule disjE) assume a = b hence x1 = 0 using hIntegral (a, b) f x1 i by simp thus ?thesis using ha = bi hIntegral (b, c) f x2 i by simp next assume b = c hence x2 = 0 using hIntegral (b, c) f x2 i by simp thus ?thesis using hb = ci hIntegral (a, b) f x1 i by simp qed qed Fundamental theorem of calculus (Part I) ”Straddle Lemma” : Swartz and Thompson: AMM 95(7) 1988 lemma strad1 : fixes z x s e :: real assumes P:(Vz. z 6= x =⇒ |z − x| < s =⇒ |(f z − f x) / (z − x) − f 0 x| < e / 2 ) assumes |z − x| < s shows |f z − f x − f 0 x ∗ (z − x)| ≤ e / 2 ∗ |z − x| proof (cases z = x) case True then show ?thesis by simp next case False then have inverse (z − x) ∗ (f z − f x − f 0 x ∗ (z − x)) = (f z − f x) / (z − x) − f 0 x apply (subst mult.commute) apply (simp add: left-diff-distrib) apply (simp add: mult.assoc divide-inverse) apply (simp add: ring-distribs) done 0 moreover from False h|z − x| < s i have |(f z − f x) / (z − x) − f x| < e / 2 by (rule P) ultimately have |inverse (z − x)| ∗ (|f z − f x − f 0 x ∗ (z − x)| ∗ 2 ) ≤ |inverse (z − x)| ∗ (e ∗ |z − x|) using False by (simp del: abs-inverse add: abs-mult [symmetric] ac-simps) with False have |f z − f x − f 0 x ∗ (z − x)| ∗ 2 ≤ e ∗ |z − x| by simp then show ?thesis by simp qed

470 lemma lemma-straddle: assumes f 0: ∀ x. a ≤ x & x ≤ b −−> DERIV f x :> f 0(x) and 0 < e shows ∃ g. gauge {a..b} g & (∀ x u v. a ≤ u & u ≤ x & x ≤ v & v ≤ b &(v − u) < g(x) −−> |(f (v) − f (u)) − (f 0(x) ∗ (v − u))| ≤ e ∗ (v − u)) proof − have ∀ x∈{a..b}. (∃ d > 0 . ∀ u v. u ≤ x & x ≤ v &(v − u) < d −−> |(f (v) − f (u)) − (f 0(x) ∗ (v − u))| ≤ e ∗ (v − u)) proof (clarsimp) fix x :: real assume a ≤ x and x ≤ b with f 0 have DERIV f x :> f 0(x) by simp then have ∀ r>0 . ∃ s>0 . ∀ z. z 6= x ∧ |z − x| < s −→ |(f z − f x) / (z − x) − f 0 x| < r by (simp add: DERIV-iff2 LIM-eq) with h0 < e i obtain s where z 6= x =⇒ |z − x| < s =⇒ |(f z − f x) / (z − x) − f 0 x| < e/2 and 0 < s for z by (drule-tac x=e/2 in spec, auto) with strad1 [of x s f f 0 e] have strad: Vz. |z − x| < s =⇒ |f z − f x − f 0 x ∗ (z − x)| ≤ e/2 ∗ |z − x| by auto show ∃ d>0 . ∀ u v. u ≤ x ∧ x ≤ v ∧ v − u < d −→ |f v − f u − f 0 x ∗ (v − u)| ≤ e ∗ (v − u) proof (safe intro!: exI ) show 0 < s by fact next fix u v :: real assume u ≤ x and x ≤ v and v − u < s have |f v − f u − f 0 x ∗ (v − u)| = |(f v − f x − f 0 x ∗ (v − x)) + (f x − f u − f 0 x ∗ (x − u))| by (simp add: right-diff-distrib) also have ... ≤ |f v − f x − f 0 x ∗ (v − x)| + |f x − f u − f 0 x ∗ (x − u)| by (rule abs-triangle-ineq) also have ... = |f v − f x − f 0 x ∗ (v − x)| + |f u − f x − f 0 x ∗ (u − x)| by (simp add: right-diff-distrib) also have ... ≤ (e/2 ) ∗ |v − x| + (e/2 ) ∗ |u − x| using hu ≤ x i hx ≤ v i hv − u < s i by (intro add-mono strad, simp-all) also have ... ≤ e ∗ (v − u) / 2 + e ∗ (v − u) / 2 using hu ≤ x i hx ≤ v i h0 < e i by (intro add-mono, simp-all) also have ... = e ∗ (v − u) by simp finally show |f v − f u − f 0 x ∗ (v − u)| ≤ e ∗ (v − u) . qed qed thus ?thesis by (simp add: gauge-def )(drule bchoice, auto) qed lemma fundamental-theorem-of-calculus:

471 assumes a ≤ b assumes f 0: ∀ x. a ≤ x ∧ x ≤ b −→ DERIV f x :> f 0(x) shows Integral (a, b) f 0 (f (b) − f (a)) proof (cases a = b) assume a = b thus ?thesis by simp next assume a 6= b with ha ≤ bi have a < b by simp show ?thesis proof (simp add: Integral-def2 , clarify) fix e :: real assume 0 < e with ha < bi have 0 < e / (b − a) by simp

from lemma-straddle [OF f 0 this] obtain δ where gauge {a..b} δ and δ: [[a ≤ u; u ≤ x; x ≤ v; v ≤ b; v − u < δ x]] =⇒ |f v − f u − f 0 x ∗ (v − u)| ≤ e ∗ (v − u) / (b − a) for x u v by auto

have ∀ D. fine δ (a, b) D −→ |rsum D f 0 − (f b − f a)| ≤ e proof (clarify) fix D assume D: fine δ (a, b) D hence (P (u, x, v)←D. f v − f u) = f b − f a by (rule fine-sum-list-eq-diff ) hence |rsum D f 0 − (f b − f a)| = |rsum D f 0 − (P (u, x, v)←D. f v − f u)| by simp also have ... = |(P (u, x, v)←D. f v − f u) − rsum D f 0| by (rule abs-minus-commute) also have ... = |P (u, x, v)←D. (f v − f u) − f 0 x ∗ (v − u)| by (simp only: rsum-def sum-list-subtractf split-def ) also have ... ≤ (P (u, x, v)←D. |(f v − f u) − f 0 x ∗ (v − u)|) by (rule ord-le-eq-trans [OF sum-list-abs], simp add: o-def split-def ) also have ... ≤ (P (u, x, v)←D. (e / (b − a)) ∗ (v − u)) apply (rule sum-list-mono, clarify, rename-tac u x v) using D apply (simp add: δ mem-fine mem-fine2 mem-fine3 ) done also have ... = e using fine-sum-list-eq-diff [OF D, where f =λx. x] unfolding split-def sum-list-const-mult using ha < bi by simp finally show |rsum D f 0 − (f b − f a)| ≤ e . qed

with hgauge {a..b} δi show ∃ δ. gauge {a..b} δ ∧ (∀ D. fine δ (a, b) D −→ |rsum D f 0 − (f b − f a)| ≤ e) by auto qed qed end

472 theory Dedekind-Real imports Complex-Main begin

62 Positive real numbers

Could be generalized and moved to Groups lemma add-eq-exists: ∃ x. a+x = (b::rat) by (rule-tac x=b−a in exI , simp) definition cut :: rat set => bool where cut A = ({} ⊂ A & A < {r. 0 < r} & (∀ y ∈ A. ((∀ z. 0 z ∈ A)&(∃ u ∈ A. y < u)))) lemma interval-empty-iff : {y. (x:: 0a::unbounded-dense-linorder) < y ∧ y < z} = {} ←→ ¬ x < z by (auto dest: dense) lemma cut-of-rat: assumes q: 0 < q shows cut {r::rat. 0 < r & r < q} (is cut ?A) proof − from q have pos: ?A < {r. 0 < r} by force have nonempty: {} ⊂ ?A proof show {} ⊆ ?A by simp show {}= 6 ?A by (force simp only: q eq-commute [of {}] interval-empty-iff ) qed show ?thesis by (simp add: cut-def pos nonempty, blast dest: dense intro: order-less-trans) qed typedef preal = Collect cut by (blast intro: cut-of-rat [OF zero-less-one]) lemma Abs-preal-induct [induct type: preal]: (Vx. cut x =⇒ P (Abs-preal x)) =⇒ P x using Abs-preal-induct [of P x] by simp lemma Rep-preal: cut (Rep-preal x)

473 using Rep-preal [of x] by simp definition psup :: preal set => preal where psup P = Abs-preal (S X ∈ P. Rep-preal X ) definition add-set :: [rat set,rat set] => rat set where add-set A B = {w. ∃ x ∈ A. ∃ y ∈ B. w = x + y} definition diff-set :: [rat set,rat set] => rat set where diff-set A B = {w. ∃ x. 0 < w & 0 < x & x ∈/ B & x + w ∈ A} definition mult-set :: [rat set,rat set] => rat set where mult-set A B = {w. ∃ x ∈ A. ∃ y ∈ B. w = x ∗ y} definition inverse-set :: rat set => rat set where inverse-set A = {x. ∃ y. 0 < x & x < y & inverse y ∈/ A} instantiation preal :: {ord, plus, minus, times, inverse, one} begin definition preal-less-def : R < S == Rep-preal R < Rep-preal S definition preal-le-def : R ≤ S == Rep-preal R ⊆ Rep-preal S definition preal-add-def : R + S == Abs-preal (add-set (Rep-preal R)(Rep-preal S)) definition preal-diff-def : R − S == Abs-preal (diff-set (Rep-preal R)(Rep-preal S)) definition preal-mult-def : R ∗ S == Abs-preal (mult-set (Rep-preal R)(Rep-preal S)) definition preal-inverse-def : inverse R == Abs-preal (inverse-set (Rep-preal R))

474 definition R div S = R ∗ inverse (S::preal) definition preal-one-def : 1 == Abs-preal {x. 0 < x & x < 1 } instance .. end Reduces equality on abstractions to equality on representatives declare Abs-preal-inject [simp] declare Abs-preal-inverse [simp] lemma rat-mem-preal: 0 < q ==> cut {r::rat. 0 < r & r < q} by (simp add: cut-of-rat) lemma preal-nonempty: cut A ==> ∃ x∈A. 0 < x unfolding cut-def [abs-def ] by blast lemma preal-Ex-mem: cut A =⇒ ∃ x. x ∈ A apply (drule preal-nonempty) apply fast done lemma preal-imp-psubset-positives: cut A ==> A < {r. 0 < r} by (force simp add: cut-def ) lemma preal-exists-bound: cut A ==> ∃ x. 0 < x & x ∈/ A apply (drule preal-imp-psubset-positives) apply auto done lemma preal-exists-greater:[| cut A; y ∈ A |] ==> ∃ u ∈ A. y < u unfolding cut-def [abs-def ] by blast lemma preal-downwards-closed:[| cut A; y ∈ A; 0 < z; z < y |] ==> z ∈ A unfolding cut-def [abs-def ] by blast Relaxing the final premise lemma preal-downwards-closed 0: [| cut A; y ∈ A; 0 < z; z ≤ y |] ==> z ∈ A apply (simp add: order-le-less) apply (blast intro: preal-downwards-closed) done A positive fraction not in a positive real is an upper bound. Gleason p. 122 - Remark (1) lemma not-in-preal-ub:

475 assumes A: cut A and notx: x ∈/ A and y: y ∈ A and pos: 0 < x shows y < x proof (cases rule: linorder-cases) assume x0 . x ∈/ Rep-preal X by (rule preal-exists-bound [OF Rep-preal]) lemmas not-in-Rep-preal-ub = not-in-preal-ub [OF Rep-preal]

62.1 Properties of Ordering instance preal :: order proof fix w :: preal show w ≤ w by (simp add: preal-le-def ) next fix i j k :: preal assume i ≤ j and j ≤ k then show i ≤ k by (simp add: preal-le-def ) next fix z w :: preal assume z ≤ w and w ≤ z then show z = w by (simp add: preal-le-def Rep-preal-inject) next fix z w :: preal show z < w ←→ z ≤ w ∧ ¬ w ≤ z by (auto simp add: preal-le-def preal-less-def Rep-preal-inject) qed lemma preal-imp-pos:[|cut A; r ∈ A|] ==> 0 < r by (insert preal-imp-psubset-positives, blast)

476 instance preal :: linorder proof fix x y :: preal show x <= y | y <= x apply (auto simp add: preal-le-def ) apply (rule ccontr) apply (blast dest: not-in-Rep-preal-ub intro: preal-imp-pos [OF Rep-preal] elim: order-less-asym) done qed instantiation preal :: distrib-lattice begin definition (inf :: preal ⇒ preal ⇒ preal) = min definition (sup :: preal ⇒ preal ⇒ preal) = max instance by intro-classes (auto simp add: inf-preal-def sup-preal-def max-min-distrib2 ) end

62.2 Properties of Addition lemma preal-add-commute:(x::preal) + y = y + x apply (unfold preal-add-def add-set-def ) apply (rule-tac f = Abs-preal in arg-cong) apply (force simp add: add.commute) done

Lemmas for proving that addition of two positive reals gives a positive real

Part 1 of Dedekind sections definition lemma add-set-not-empty: [|cut A; cut B|] ==> {} ⊂ add-set A B apply (drule preal-nonempty)+ apply (auto simp add: add-set-def ) done

Part 2 of Dedekind sections definition. A structured version of this proof is preal-not-mem-mult-set-Ex below. lemma preal-not-mem-add-set-Ex: [|cut A; cut B|] ==> ∃ q>0 . q ∈/ add-set A B apply (insert preal-exists-bound [of A] preal-exists-bound [of B], auto)

477 apply (rule-tac x = x+xa in exI ) apply (simp add: add-set-def , clarify) apply (drule (3 ) not-in-preal-ub)+ apply (force dest: add-strict-mono) done lemma add-set-not-rat-set: assumes A: cut A and B: cut B shows add-set A B < {r. 0 < r} proof from preal-imp-pos [OF A] preal-imp-pos [OF B] show add-set A B ⊆ {r. 0 < r} by (force simp add: add-set-def ) next show add-set A B 6= {r. 0 < r} by (insert preal-not-mem-add-set-Ex [OF A B], blast) qed

Part 3 of Dedekind sections definition lemma add-set-lemma3 : [|cut A; cut B; u ∈ add-set A B; 0 < z; z < u|] ==> z ∈ add-set A B proof (unfold add-set-def , clarify) fix x::rat and y::rat assume A: cut A and B: cut B and [simp]: 0 < z and zless: z < x + y and x: x ∈ A and y: y ∈ B have xpos [simp]: 0

478 next show x ∗ ?f ∈ A proof (rule preal-downwards-closed [OF A x]) show 0 < x ∗ ?f by (simp add: divide-inverse zero-less-mult-iff ) next show x ∗ ?f < x by (insert mult-strict-left-mono [OF fless xpos], simp) qed qed qed

Part 4 of Dedekind sections definition lemma add-set-lemma4 : [|cut A; cut B; y ∈ add-set A B|] ==> ∃ u ∈ add-set A B. y < u apply (auto simp add: add-set-def ) apply (frule preal-exists-greater [of A], auto) apply (rule-tac x=u + ya in exI ) apply (auto intro: add-strict-left-mono) done lemma mem-add-set: [|cut A; cut B|] ==> cut (add-set A B) apply (simp (no-asm-simp) add: cut-def ) apply (blast intro!: add-set-not-empty add-set-not-rat-set add-set-lemma3 add-set-lemma4 ) done lemma preal-add-assoc: ((x::preal) + y) + z = x + (y + z) apply (simp add: preal-add-def mem-add-set Rep-preal) apply (force simp add: add-set-def ac-simps) done instance preal :: ab-semigroup-add proof fix a b c :: preal show (a + b) + c = a + (b + c) by (rule preal-add-assoc) show a + b = b + a by (rule preal-add-commute) qed

62.3 Properties of Multiplication

Proofs essentially same as for addition lemma preal-mult-commute:(x::preal) ∗ y = y ∗ x apply (unfold preal-mult-def mult-set-def ) apply (rule-tac f = Abs-preal in arg-cong) apply (force simp add: mult.commute) done

479 Multiplication of two positive reals gives a positive real.

Lemmas for proving positive reals multiplication set in preal

Part 1 of Dedekind sections definition lemma mult-set-not-empty: [|cut A; cut B|] ==> {} ⊂ mult-set A B apply (insert preal-nonempty [of A] preal-nonempty [of B]) apply (auto simp add: mult-set-def ) done

Part 2 of Dedekind sections definition lemma preal-not-mem-mult-set-Ex: assumes A: cut A and B: cut B shows ∃ q. 0 < q & q ∈/ mult-set A B proof − from preal-exists-bound [OF A] obtain x where 1 [simp]: 0 < x x ∈/ A by blast from preal-exists-bound [OF B] obtain y where 2 [simp]: 0 < y y ∈/ B by blast show ?thesis proof (intro exI conjI ) show 0 < x∗y by simp show x ∗ y ∈/ mult-set A B proof − { fix u::rat and v::rat assume u: u ∈ A and v: v ∈ B and xy: x∗y = u∗v moreover from A B 1 2 u v have u

480 intro: preal-imp-pos [OF A] preal-imp-pos [OF B] mult-pos-pos) show mult-set A B 6= {r. 0 < r} using preal-not-mem-mult-set-Ex [OF A B] by blast qed

Part 3 of Dedekind sections definition lemma mult-set-lemma3 : [|cut A; cut B; u ∈ mult-set A B; 0 < z; z < u|] ==> z ∈ mult-set A B proof (unfold mult-set-def , clarify) fix x::rat and y::rat assume A: cut A and B: cut B and [simp]: 0 < z and zless: z < x ∗ y and x: x ∈ A and y: y ∈ B have [simp]: 0

Part 4 of Dedekind sections definition lemma mult-set-lemma4 : [|cut A; cut B; y ∈ mult-set A B|] ==> ∃ u ∈ mult-set A B. y < u apply (auto simp add: mult-set-def ) apply (frule preal-exists-greater [of A], auto) apply (rule-tac x=u ∗ ya in exI ) apply (auto intro: preal-imp-pos [of A] preal-imp-pos [of B] mult-strict-right-mono) done lemma mem-mult-set:

481 [|cut A; cut B|] ==> cut (mult-set A B) apply (simp (no-asm-simp) add: cut-def ) apply (blast intro!: mult-set-not-empty mult-set-not-rat-set mult-set-lemma3 mult-set-lemma4 ) done lemma preal-mult-assoc: ((x::preal) ∗ y) ∗ z = x ∗ (y ∗ z) apply (simp add: preal-mult-def mem-mult-set Rep-preal) apply (force simp add: mult-set-def ac-simps) done instance preal :: ab-semigroup-mult proof fix a b c :: preal show (a ∗ b) ∗ c = a ∗ (b ∗ c) by (rule preal-mult-assoc) show a ∗ b = b ∗ a by (rule preal-mult-commute) qed

Positive real 1 is the multiplicative identity element lemma preal-mult-1 :(1 ::preal) ∗ z = z proof (induct z) fix A :: rat set assume A: cut A have {w. ∃ u. 0 < u ∧ u < 1 &(∃ v ∈ A. w = u ∗ v)} = A (is ?lhs = A) proof show ?lhs ⊆ A proof clarify fix x::rat and u::rat and v::rat assume upos: 0

482 by (simp add: pos-divide-less-eq vpos xlessv) show ∃ v 0∈A. x = (x / v) ∗ v 0 proof show x = (x/v)∗v by (simp add: divide-inverse mult.assoc vpos order-less-imp-not-eq2 ) show v ∈ A by fact qed qed qed qed thus 1 ∗ Abs-preal A = Abs-preal A by (simp add: preal-one-def preal-mult-def mult-set-def rat-mem-preal A) qed instance preal :: comm-monoid-mult by intro-classes (rule preal-mult-1 )

62.4 Distribution of Multiplication across Addition lemma mem-Rep-preal-add-iff : (z ∈ Rep-preal(R+S)) = (∃ x ∈ Rep-preal R. ∃ y ∈ Rep-preal S. z = x + y) apply (simp add: preal-add-def mem-add-set Rep-preal) apply (simp add: add-set-def ) done lemma mem-Rep-preal-mult-iff : (z ∈ Rep-preal(R∗S)) = (∃ x ∈ Rep-preal R. ∃ y ∈ Rep-preal S. z = x ∗ y) apply (simp add: preal-mult-def mem-mult-set Rep-preal) apply (simp add: mult-set-def ) done lemma distrib-subset1 : Rep-preal (w ∗ (x + y)) ⊆ Rep-preal (w ∗ x + w ∗ y) apply (auto simp add: Bex-def mem-Rep-preal-add-iff mem-Rep-preal-mult-iff ) apply (force simp add: distrib-left) done lemma preal-add-mult-distrib-mean: assumes a: a ∈ Rep-preal w and b: b ∈ Rep-preal w and d: d ∈ Rep-preal x and e: e ∈ Rep-preal y shows ∃ c ∈ Rep-preal w. a ∗ d + b ∗ e = c ∗ (d + e) proof let ?c = (a∗d + b∗e)/(d+e) have [simp]: 0

483 have cpos: 0 < ?c by (simp add: zero-less-divide-iff zero-less-mult-iff pos-add-strict) show a ∗ d + b ∗ e = ?c ∗ (d + e) by (simp add: divide-inverse mult.assoc order-less-imp-not-eq2 ) show ?c ∈ Rep-preal w proof (cases rule: linorder-le-cases) assume a ≤ b hence ?c ≤ b by (simp add: pos-divide-le-eq distrib-left mult-right-mono order-less-imp-le) thus ?thesis by (rule preal-downwards-closed 0 [OF Rep-preal b cpos]) next assume b ≤ a hence ?c ≤ a by (simp add: pos-divide-le-eq distrib-left mult-right-mono order-less-imp-le) thus ?thesis by (rule preal-downwards-closed 0 [OF Rep-preal a cpos]) qed qed lemma distrib-subset2 : Rep-preal (w ∗ x + w ∗ y) ⊆ Rep-preal (w ∗ (x + y)) apply (auto simp add: Bex-def mem-Rep-preal-add-iff mem-Rep-preal-mult-iff ) apply (drule-tac w=w and x=x and y=y in preal-add-mult-distrib-mean, auto) done lemma preal-add-mult-distrib2 :(w ∗ ((x::preal) + y)) = (w ∗ x) + (w ∗ y) apply (rule Rep-preal-inject [THEN iffD1 ]) apply (rule equalityI [OF distrib-subset1 distrib-subset2 ]) done lemma preal-add-mult-distrib: (((x::preal) + y) ∗ w) = (x ∗ w) + (y ∗ w) by (simp add: preal-mult-commute preal-add-mult-distrib2 ) instance preal :: comm-semiring by intro-classes (rule preal-add-mult-distrib)

62.5 Existence of Inverse, a Positive Real lemma mem-inv-set-ex: assumes A: cut A shows ∃ x y. 0 < x & x < y & inverse y ∈/ A proof − from preal-exists-bound [OF A] obtain x where [simp]: 0

484 by (simp add: less-imp-inverse-less less-add-one) show inverse (inverse x) ∈/ A by (simp add: order-less-imp-not-eq2 ) qed qed Part 1 of Dedekind sections definition lemma inverse-set-not-empty: cut A ==> {} ⊂ inverse-set A apply (insert mem-inv-set-ex [of A]) apply (auto simp add: inverse-set-def ) done Part 2 of Dedekind sections definition lemma preal-not-mem-inverse-set-Ex: assumes A: cut A shows ∃ q. 0 < q & q ∈/ inverse-set A proof − from preal-nonempty [OF A] obtain x where x: x ∈ A and xpos [simp]: 0 z ∈ inverse-set A

485 apply (auto simp add: inverse-set-def ) apply (auto intro: order-less-trans) done

Part 4 of Dedekind sections definition lemma inverse-set-lemma4 : [|cut A; y ∈ inverse-set A|] ==> ∃ u ∈ inverse-set A. y < u apply (auto simp add: inverse-set-def ) apply (drule dense [of y]) apply (blast intro: order-less-trans) done lemma mem-inverse-set: cut A ==> cut (inverse-set A) apply (simp (no-asm-simp) add: cut-def ) apply (blast intro!: inverse-set-not-empty inverse-set-not-rat-set inverse-set-lemma3 inverse-set-lemma4 ) done

62.6 Gleason’s Lemma 9-3.4, page 122 lemma Gleason9-34-exists: assumes A: cut A and ∀ x∈A. x + u ∈ A and 0 ≤ z shows ∃ b∈A. b + (of-int z) ∗ u ∈ A proof (cases z rule: int-cases) case (nonneg n) show ?thesis proof (simp add: nonneg, induct n) case 0 from preal-nonempty [OF A] show ?case by force next case (Suc k) then obtain b where b: b ∈ A b + of-nat k ∗ u ∈ A .. hence b + of-int (int k)∗u + u ∈ A by (simp add: assms) thus ?case by (force simp add: algebra-simps b) qed next case (neg n) with assms show ?thesis by simp qed lemma Gleason9-34-contra: assumes A: cut A shows [|∀ x∈A. x + u ∈ A; 0 < u; 0 < y; y ∈/ A|] ==> False proof (induct u, induct y)

486 fix a::int and b::int fix c::int and d::int assume bpos [simp]: 0 < b and dpos [simp]: 0 < d and closed: ∀ x∈A. x + (Fract c d) ∈ A and upos: 0 < Fract c d and ypos: 0 < Fract a b and notin: Fract a b ∈/ A have cpos [simp]: 0 < c by (simp add: zero-less-Fract-iff [OF dpos, symmetric] upos) have apos [simp]: 0 < a by (simp add: zero-less-Fract-iff [OF bpos, symmetric] ypos) let ?k = a∗d have frle: Fract a b ≤ Fract ?k 1 ∗ (Fract c d) proof − have ?thesis = ((a ∗ d ∗ b ∗ d) ≤ c ∗ b ∗ (a ∗ d ∗ b ∗ d)) by (simp add: order-less-imp-not-eq2 ac-simps) moreover have (1 ∗ (a ∗ d ∗ b ∗ d)) ≤ c ∗ b ∗ (a ∗ d ∗ b ∗ d) by (rule mult-mono, simp-all add: int-one-le-iff-zero-less zero-less-mult-iff order-less-imp-le) ultimately show ?thesis by simp qed have k: 0 ≤ ?k by (simp add: order-less-imp-le zero-less-mult-iff ) from Gleason9-34-exists [OF A closed k] obtain z where z: z ∈ A and mem: z + of-int ?k ∗ Fract c d ∈ A .. have less: z + of-int ?k ∗ Fract c d < Fract a b by (rule not-in-preal-ub [OF A notin mem ypos]) have 0

487 62.7 Gleason’s Lemma 9-3.6 lemma lemma-gleason9-36 : assumes A: cut A and x: 1 < x shows ∃ r ∈ A. r∗x ∈/ A proof − from preal-nonempty [OF A] obtain y where y: y ∈ A and ypos: 0

62.8 Existence of Inverse: Part 2 lemma mem-Rep-preal-inverse-iff : (z ∈ Rep-preal(inverse R)) = (0 < z ∧ (∃ y. z < y ∧ inverse y ∈/ Rep-preal R))

488 apply (simp add: preal-inverse-def mem-inverse-set Rep-preal) apply (simp add: inverse-set-def ) done lemma Rep-preal-one: Rep-preal 1 = {x. 0 < x ∧ x < 1 } by (simp add: preal-one-def rat-mem-preal) lemma subset-inverse-mult-lemma: assumes xpos: 0 < x and xless: x < 1 shows ∃ r u y. 0 < r & r < y & inverse y ∈/ Rep-preal R & u ∈ Rep-preal R & x = r ∗ u proof − from xpos and xless have 1 < inverse x by (simp add: one-less-inverse-iff ) from lemma-gleason9-36 [OF Rep-preal this] obtain r where r: r ∈ Rep-preal R and notin: r ∗ (inverse x) ∈/ Rep-preal R .. have rpos: 0

489 have q < inverse y using rpos rless by (simp add: not-in-preal-ub [OF Rep-preal notin] q) hence r ∗ q < r/y using rpos by (simp add: divide-inverse mult-less-cancel-left) also have ... ≤ 1 using rpos rless by (simp add: pos-divide-le-eq) finally show ?thesis . qed lemma inverse-mult-subset: Rep-preal(inverse R ∗ R) ⊆ Rep-preal 1 apply (auto simp add: Bex-def Rep-preal-one mem-Rep-preal-inverse-iff mem-Rep-preal-mult-iff ) apply (simp add: zero-less-mult-iff preal-imp-pos [OF Rep-preal]) apply (blast intro: inverse-mult-subset-lemma) done lemma preal-mult-inverse: inverse R ∗ R = (1 ::preal) apply (rule Rep-preal-inject [THEN iffD1 ]) apply (rule equalityI [OF inverse-mult-subset subset-inverse-mult]) done lemma preal-mult-inverse-right: R ∗ inverse R = (1 ::preal) apply (rule preal-mult-commute [THEN subst]) apply (rule preal-mult-inverse) done

Theorems needing Gleason9-34 lemma Rep-preal-self-subset: Rep-preal (R) ⊆ Rep-preal(R + S) proof fix r assume r: r ∈ Rep-preal R have rpos: 0

490 have r + y ∈ Rep-preal (R + S) using r y by (auto simp add: mem-Rep-preal-add-iff ) thus ?thesis using notin by blast qed lemma Rep-preal-sum-not-eq: Rep-preal (R + S) 6= Rep-preal(R) by (insert Rep-preal-sum-not-subset, blast) at last, Gleason prop. 9-3.5(iii) page 123 lemma preal-self-less-add-left:(R::preal) < R + S apply (unfold preal-less-def less-le) apply (simp add: Rep-preal-self-subset Rep-preal-sum-not-eq [THEN not-sym]) done

62.9 Subtraction for Positive Reals

Gleason prop. 9-3.5(iv), page 123: proving A < B =⇒ ∃ D. A + D = B. We define the claimed D and show that it is a positive real

Part 1 of Dedekind sections definition lemma diff-set-not-empty: R < S ==> {} ⊂ diff-set (Rep-preal S)(Rep-preal R) apply (auto simp add: preal-less-def diff-set-def elim!: equalityE) apply (frule-tac x1 = S in Rep-preal [THEN preal-exists-greater]) apply (drule preal-imp-pos [OF Rep-preal], clarify) apply (cut-tac a=x and b=u in add-eq-exists, force) done

Part 2 of Dedekind sections definition lemma diff-set-nonempty: ∃ q. 0 < q & q ∈/ diff-set (Rep-preal S)(Rep-preal R) apply (cut-tac X = S in Rep-preal-exists-bound) apply (erule exE) apply (rule-tac x = x in exI , auto) apply (simp add: diff-set-def ) apply (auto dest: Rep-preal [THEN preal-downwards-closed]) done lemma diff-set-not-rat-set: diff-set (Rep-preal S)(Rep-preal R) < {r. 0 < r} (is ?lhs < ?rhs) proof show ?lhs ⊆ ?rhs by (auto simp add: diff-set-def ) show ?lhs 6= ?rhs using diff-set-nonempty by blast qed

Part 3 of Dedekind sections definition lemma diff-set-lemma3 : [|R < S; u ∈ diff-set (Rep-preal S)(Rep-preal R); 0 < z; z < u|]

491 ==> z ∈ diff-set (Rep-preal S)(Rep-preal R) apply (auto simp add: diff-set-def ) apply (rule-tac x=x in exI ) apply (drule Rep-preal [THEN preal-downwards-closed], auto) done

Part 4 of Dedekind sections definition lemma diff-set-lemma4 : [|R < S; y ∈ diff-set (Rep-preal S)(Rep-preal R)|] ==> ∃ u ∈ diff-set (Rep-preal S)(Rep-preal R). y < u apply (auto simp add: diff-set-def ) apply (drule Rep-preal [THEN preal-exists-greater], clarify) apply (cut-tac a=x+y and b=u in add-eq-exists, clarify) apply (rule-tac x=y+xa in exI ) apply (auto simp add: ac-simps) done lemma mem-diff-set: R < S ==> cut (diff-set (Rep-preal S)(Rep-preal R)) apply (unfold cut-def ) apply (blast intro!: diff-set-not-empty diff-set-not-rat-set diff-set-lemma3 diff-set-lemma4 ) done lemma mem-Rep-preal-diff-iff : R < S ==> (z ∈ Rep-preal(S−R)) = (∃ x. 0 < x & 0 < z & x ∈/ Rep-preal R & x + z ∈ Rep-preal S) apply (simp add: preal-diff-def mem-diff-set Rep-preal) apply (force simp add: diff-set-def ) done proving that R + D ≤ S lemma less-add-left-lemma: assumes Rless: R < S and a: a ∈ Rep-preal R and cb: c + b ∈ Rep-preal S and c ∈/ Rep-preal R and 0 < b and 0 < c shows a + b ∈ Rep-preal S proof − have 0

492 lemma less-add-left-le1 : R < (S::preal) ==> R + (S−R) ≤ S apply (auto simp add: Bex-def preal-le-def mem-Rep-preal-add-iff mem-Rep-preal-diff-iff ) apply (blast intro: less-add-left-lemma) done

62.10 proving that S ≤ R + D — trickier lemma lemma-sum-mem-Rep-preal-ex: x ∈ Rep-preal S ==> ∃ e. 0 < e & x + e ∈ Rep-preal S apply (drule Rep-preal [THEN preal-exists-greater], clarify) apply (cut-tac a=x and b=u in add-eq-exists, auto) done lemma less-add-left-lemma2 : assumes Rless: R < S and x: x ∈ Rep-preal S and xnot: x ∈/ Rep-preal R shows ∃ u v z. 0 < v & 0 < z & u ∈ Rep-preal R & z ∈/ Rep-preal R & z + v ∈ Rep-preal S & x = u + v proof − have xpos: 0 S ≤ R + (S−R) apply (auto simp add: preal-le-def ) apply (case-tac x ∈ Rep-preal R) apply (cut-tac Rep-preal-self-subset [of R], force) apply (auto simp add: Bex-def mem-Rep-preal-add-iff mem-Rep-preal-diff-iff ) apply (blast dest: less-add-left-lemma2 ) done

493 lemma less-add-left: R < (S::preal) ==> R + (S−R) = S by (blast intro: antisym [OF less-add-left-le1 less-add-left-le2 ]) lemma less-add-left-Ex: R < (S::preal) ==> ∃ D. R + D = S by (fast dest: less-add-left) lemma preal-add-less2-mono1 : R < (S::preal) ==> R + T < S + T apply (auto dest!: less-add-left-Ex simp add: preal-add-assoc) apply (rule-tac y1 = D in preal-add-commute [THEN subst]) apply (auto intro: preal-self-less-add-left simp add: preal-add-assoc [symmetric]) done lemma preal-add-less2-mono2 : R < (S::preal) ==> T + R < T + S by (auto intro: preal-add-less2-mono1 simp add: preal-add-commute [of T ]) lemma preal-add-right-less-cancel: R + T < S + T ==> R < (S::preal) apply (insert linorder-less-linear [of R S], auto) apply (drule-tac R = S and T = T in preal-add-less2-mono1 ) apply (blast dest: order-less-trans) done lemma preal-add-left-less-cancel: T + R < T + S ==> R < (S::preal) by (auto elim: preal-add-right-less-cancel simp add: preal-add-commute [of T ]) lemma preal-add-less-cancel-left [simp]: (T + (R::preal) < T + S) = (R < S) by (blast intro: preal-add-less2-mono2 preal-add-left-less-cancel) lemma preal-add-less-cancel-right [simp]: ((R::preal) + T < S + T ) = (R < S) using preal-add-less-cancel-left [symmetric, of R S T ] by (simp add: ac-simps) lemma preal-add-le-cancel-left [simp]: (T + (R::preal) ≤ T + S) = (R ≤ S) by (simp add: linorder-not-less [symmetric]) lemma preal-add-le-cancel-right [simp]: ((R::preal) + T ≤ S + T ) = (R ≤ S) using preal-add-le-cancel-left [symmetric, of R S T ] by (simp add: ac-simps) lemma preal-add-right-cancel:(R::preal) + T = S + T ==> R = S apply (insert linorder-less-linear [of R S], safe) apply (drule-tac [!] T = T in preal-add-less2-mono1 , auto) done lemma preal-add-left-cancel: C + A = C + B ==> A = (B::preal) by (auto intro: preal-add-right-cancel simp add: preal-add-commute) instance preal :: linordered-ab-semigroup-add proof fix a b c :: preal show a ≤ b =⇒ c + a ≤ c + b by (simp only: preal-add-le-cancel-left)

494 qed

62.11 Completeness of type preal

Prove that supremum is a cut

Part 1 of Dedekind sections definition lemma preal-sup-set-not-empty: P 6= {} ==> {} ⊂ (S X ∈ P. Rep-preal(X )) apply auto apply (cut-tac X = x in mem-Rep-preal-Ex, auto) done

Part 2 of Dedekind sections definition lemma preal-sup-not-exists: ∀ X ∈ P. X ≤ Y ==> ∃ q. 0 < q & q ∈/ (S X ∈ P. Rep-preal(X )) apply (cut-tac X = Y in Rep-preal-exists-bound) apply (auto simp add: preal-le-def ) done lemma preal-sup-set-not-rat-set: ∀ X ∈ P. X ≤ Y ==> (S X ∈ P. Rep-preal(X )) < {r. 0 < r} apply (drule preal-sup-not-exists) apply (blast intro: preal-imp-pos [OF Rep-preal]) done

Part 3 of Dedekind sections definition lemma preal-sup-set-lemma3 : [|P 6= {}; ∀ X ∈ P. X ≤ Y ; u ∈ (S X ∈ P. Rep-preal(X )); 0 < z; z < u|] ==> z ∈ (S X ∈ P. Rep-preal(X )) by (auto elim: Rep-preal [THEN preal-downwards-closed])

Part 4 of Dedekind sections definition lemma preal-sup-set-lemma4 : [|P 6= {}; ∀ X ∈ P. X ≤ Y ; y ∈ (S X ∈ P. Rep-preal(X )) |] ==> ∃ u ∈ (S X ∈ P. Rep-preal(X )). y < u by (blast dest: Rep-preal [THEN preal-exists-greater]) lemma preal-sup: [|P 6= {}; ∀ X ∈ P. X ≤ Y |] ==> cut (S X ∈ P. Rep-preal(X )) apply (unfold cut-def ) apply (blast intro!: preal-sup-set-not-empty preal-sup-set-not-rat-set preal-sup-set-lemma3 preal-sup-set-lemma4 ) done lemma preal-psup-le: [| ∀ X ∈ P. X ≤ Y ; x ∈ P |] ==> x ≤ psup P apply (simp (no-asm-simp) add: preal-le-def )

495 apply (subgoal-tac P 6= {}) apply (auto simp add: psup-def preal-sup) done lemma psup-le-ub:[| P 6= {}; ∀ X ∈ P. X ≤ Y |] ==> psup P ≤ Y apply (simp (no-asm-simp) add: preal-le-def ) apply (simp add: psup-def preal-sup) apply (auto simp add: preal-le-def ) done Supremum property lemma preal-complete: [| P 6= {}; ∀ X ∈ P. X ≤ Y |] ==> (∃ X ∈ P. Z < X ) = (Z < psup P) apply (simp add: preal-less-def psup-def preal-sup) apply (auto simp add: preal-le-def ) apply (rename-tac U ) apply (cut-tac x = U and y = Z in linorder-less-linear) apply (auto simp add: preal-less-def ) done

63 Defining the Reals from the Positive Reals definition realrel :: ((preal ∗ preal) ∗ (preal ∗ preal)) set where realrel = {p. ∃ x1 y1 x2 y2 . p = ((x1 ,y1 ),(x2 ,y2 )) & x1 +y2 = x2 +y1 } definition Real = UNIV //realrel typedef real = Real morphisms Rep-Real Abs-Real unfolding Real-def by (auto simp add: quotient-def ) definition

real-of-preal :: preal => real where real-of-preal m = Abs-Real (realrel ‘‘ {(m + 1 , 1 )}) instantiation real :: {zero, one, plus, minus, uminus, times, inverse, ord, abs, sgn} begin definition real-zero-def : 0 = Abs-Real(realrel‘‘{(1 , 1 )}) definition real-one-def : 1 = Abs-Real(realrel‘‘{(1 + 1 , 1 )}) definition real-add-def : z + w =

496 the-elem (S (x,y) ∈ Rep-Real(z). S (u,v) ∈ Rep-Real(w). { Abs-Real(realrel‘‘{(x+u, y+v)}) }) definition real-minus-def : − r = the-elem (S (x,y) ∈ Rep-Real(r). { Abs-Real(realrel‘‘{(y,x)}) }) definition real-diff-def : r − (s::real) = r + − s definition real-mult-def : z ∗ w = the-elem (S (x,y) ∈ Rep-Real(z). S (u,v) ∈ Rep-Real(w). { Abs-Real(realrel‘‘{(x∗u + y∗v, x∗v + y∗u)}) }) definition real-inverse-def : inverse (R::real) = (THE S. (R = 0 & S = 0 ) | S ∗ R = 1 ) definition real-divide-def : R div (S::real) = R ∗ inverse S definition real-le-def : z ≤ (w::real) ←→ (∃ x y u v. x+v ≤ u+y &(x,y) ∈ Rep-Real z &(u,v) ∈ Rep-Real w) definition real-less-def : x < (y::real) ←→ x ≤ y ∧ x 6= y definition real-abs-def : |r::real| = (if r < 0 then − r else r) definition real-sgn-def : sgn (x::real) = (if x=0 then 0 else if 0

63.1 Equivalence relation over positive reals lemma preal-trans-lemma: assumes x + y1 = x1 + y and x + y2 = x2 + y shows x1 + y2 = x2 + (y1 ::preal) proof − have (x1 + y2 ) + x = (x + y2 ) + x1 by (simp add: ac-simps) also have ... = (x2 + y) + x1 by (simp add: assms) also have ... = x2 + (x1 + y) by (simp add: ac-simps)

497 also have ... = x2 + (x + y1 ) by (simp add: assms) also have ... = (x2 + y1 ) + x by (simp add: ac-simps) finally have (x1 + y2 ) + x = (x2 + y1 ) + x . thus ?thesis by (rule preal-add-right-cancel) qed lemma realrel-iff [simp]: (((x1 ,y1 ),(x2 ,y2 )) ∈ realrel) = (x1 + y2 = x2 + y1 ) by (simp add: realrel-def ) lemma equiv-realrel: equiv UNIV realrel apply (auto simp add: equiv-def refl-on-def sym-def trans-def realrel-def ) apply (blast dest: preal-trans-lemma) done Reduces equality of equivalence classes to the Dedekind-Real.realrel relation: (Dedekind-Real.realrel ‘‘ {x} = Dedekind-Real.realrel ‘‘ {y}) = ((x, y) ∈ Dedekind-Real.realrel) lemmas equiv-realrel-iff = eq-equiv-class-iff [OF equiv-realrel UNIV-I UNIV-I ] declare equiv-realrel-iff [simp] lemma realrel-in-real [simp]: realrel‘‘{(x,y)}: Real by (simp add: Real-def realrel-def quotient-def , blast) declare Abs-Real-inject [simp] declare Abs-Real-inverse [simp] Case analysis on the representation of a real number as an equivalence class of pairs of positive reals. lemma eq-Abs-Real [case-names Abs-Real, cases type: real]: (!!x y. z = Abs-Real(realrel‘‘{(x,y)}) ==> P) ==> P apply (rule Rep-Real [of z, unfolded Real-def , THEN quotientE]) apply (drule arg-cong [where f =Abs-Real]) apply (auto simp add: Rep-Real-inverse) done

63.2 Addition and Subtraction lemma real-add-congruent2-lemma: [|a + ba = aa + b; ab + bc = ac + bb|] ==> a + ab + (ba + bc) = aa + ac + (b + (bb::preal)) apply (simp add: add.assoc) apply (rule add.left-commute [of ab, THEN ssubst]) apply (simp add: add.assoc [symmetric]) apply (simp add: ac-simps) done

498 lemma real-add: Abs-Real (realrel‘‘{(x,y)}) + Abs-Real (realrel‘‘{(u,v)}) = Abs-Real (realrel‘‘{(x+u, y+v)}) proof − have (λz w. (λ(x,y). (λ(u,v). {Abs-Real (realrel ‘‘ {(x+u, y+v)})}) w) z) respects2 realrel by (auto simp add: congruent2-def , blast intro: real-add-congruent2-lemma) thus ?thesis by (simp add: real-add-def UN-UN-split-split-eq UN-equiv-class2 [OF equiv-realrel equiv-realrel]) qed lemma real-minus: − Abs-Real(realrel‘‘{(x,y)}) = Abs-Real(realrel ‘‘ {(y,x)}) proof − have (λ(x,y). {Abs-Real (realrel‘‘{(y,x)})}) respects realrel by (auto simp add: congruent-def add.commute) thus ?thesis by (simp add: real-minus-def UN-equiv-class [OF equiv-realrel]) qed instance real :: ab-group-add proof fix x y z :: real show (x + y) + z = x + (y + z) by (cases x, cases y, cases z, simp add: real-add add.assoc) show x + y = y + x by (cases x, cases y, simp add: real-add add.commute) show 0 + x = x by (cases x, simp add: real-add real-zero-def ac-simps) show − x + x = 0 by (cases x, simp add: real-minus real-add real-zero-def add.commute) show x − y = x + − y by (simp add: real-diff-def ) qed

63.3 Multiplication lemma real-mult-congruent2-lemma: !!(x1 ::preal). [| x1 + y2 = x2 + y1 |] ==> x ∗ x1 + y ∗ y1 + (x ∗ y2 + y ∗ x2 ) = x ∗ x2 + y ∗ y2 + (x ∗ y1 + y ∗ x1 ) apply (simp add: add.left-commute add.assoc [symmetric]) apply (simp add: add.assoc distrib-left [symmetric]) apply (simp add: add.commute) done lemma real-mult-congruent2 : (%p1 p2 .

499 (%(x1 ,y1 ). (%(x2 ,y2 ). { Abs-Real (realrel‘‘{(x1 ∗x2 + y1 ∗y2 , x1 ∗y2 +y1 ∗x2 )}) }) p2 ) p1 ) respects2 realrel apply (rule congruent2-commuteI [OF equiv-realrel], clarify) apply (simp add: mult.commute add.commute) apply (auto simp add: real-mult-congruent2-lemma) done lemma real-mult: Abs-Real((realrel‘‘{(x1 ,y1 )})) ∗ Abs-Real((realrel‘‘{(x2 ,y2 )})) = Abs-Real(realrel ‘‘ {(x1 ∗x2 +y1 ∗y2 ,x1 ∗y2 +y1 ∗x2 )}) by (simp add: real-mult-def UN-UN-split-split-eq UN-equiv-class2 [OF equiv-realrel equiv-realrel real-mult-congruent2 ]) lemma real-mult-commute:(z::real) ∗ w = w ∗ z by (cases z, cases w, simp add: real-mult ac-simps) lemma real-mult-assoc: ((z1 ::real) ∗ z2 ) ∗ z3 = z1 ∗ (z2 ∗ z3 ) apply (cases z1 , cases z2 , cases z3 ) apply (simp add: real-mult algebra-simps) done lemma real-mult-1 :(1 ::real) ∗ z = z apply (cases z) apply (simp add: real-mult real-one-def algebra-simps) done lemma real-add-mult-distrib: ((z1 ::real) + z2 ) ∗ w = (z1 ∗ w) + (z2 ∗ w) apply (cases z1 , cases z2 , cases w) apply (simp add: real-add real-mult algebra-simps) done one and zero are distinct lemma real-zero-not-eq-one: 0 6= (1 ::real) proof − have (1 ::preal) < 1 + 1 by (simp add: preal-self-less-add-left) then show ?thesis by (simp add: real-zero-def real-one-def neq-iff ) qed instance real :: comm-ring-1 proof fix x y z :: real show (x ∗ y) ∗ z = x ∗ (y ∗ z) by (rule real-mult-assoc) show x ∗ y = y ∗ x by (rule real-mult-commute) show 1 ∗ x = x by (rule real-mult-1 ) show (x + y) ∗ z = x ∗ z + y ∗ z by (rule real-add-mult-distrib) show 0 6= (1 ::real) by (rule real-zero-not-eq-one)

500 qed

63.4 Inverse and Division lemma real-zero-iff : Abs-Real (realrel ‘‘ {(x, x)}) = 0 by (simp add: real-zero-def add.commute)

Instead of using an existential quantifier and constructing the inverse within the proof, we could define the inverse explicitly. lemma real-mult-inverse-left-ex: x 6= 0 ==> ∃ y. y∗x = (1 ::real) apply (simp add: real-zero-def real-one-def , cases x) apply (cut-tac x = xa and y = y in linorder-less-linear) apply (auto dest!: less-add-left-Ex simp add: real-zero-iff ) apply (rule-tac x = Abs-Real (realrel‘‘{(1 , inverse (D) + 1 )}) in exI ) apply (rule-tac [2 ] x = Abs-Real (realrel‘‘{(inverse (D) + 1 , 1 )}) in exI ) apply (auto simp add: real-mult preal-mult-inverse-right algebra-simps) done lemma real-mult-inverse-left: x 6= 0 ==> inverse(x)∗x = (1 ::real) apply (simp add: real-inverse-def ) apply (drule real-mult-inverse-left-ex, safe) apply (rule theI , assumption, rename-tac z) apply (subgoal-tac (z ∗ x) ∗ y = z ∗ (x ∗ y)) apply (simp add: mult.commute) apply (rule mult.assoc) done

63.5 The Real Numbers form a Field instance real :: field proof fix x y z :: real show x 6= 0 ==> inverse x ∗ x = 1 by (rule real-mult-inverse-left) show x / y = x ∗ inverse y by (simp add: real-divide-def ) show inverse 0 = (0 ::real) by (simp add: real-inverse-def ) qed

63.6 The ≤ Ordering lemma real-le-refl: w ≤ (w::real) by (cases w, force simp add: real-le-def )

The arithmetic decision procedure is not set up for type preal. This lemma is currently unused, but it could simplify the proofs of the following two lemmas.

501 lemma preal-eq-le-imp-le: assumes eq: a+b = c+d and le: c ≤ a shows b ≤ (d::preal) proof − from le have c+d ≤ a+d by simp hence a+b ≤ a+d by (simp add: eq) thus b ≤ d by simp qed lemma real-le-lemma: assumes l: u1 + v2 ≤ u2 + v1 and x1 + v1 = u1 + y1 and x2 + v2 = u2 + y2 shows x1 + y2 ≤ x2 + (y1 ::preal) proof − have (x1 +v1 ) + (u2 +y2 ) = (u1 +y1 ) + (x2 +v2 ) by (simp add: assms) hence (x1 +y2 ) + (u2 +v1 ) = (x2 +y1 ) + (u1 +v2 ) by (simp add: ac-simps) also have ... ≤ (x2 +y1 ) + (u2 +v1 ) by (simp add: assms) finally show ?thesis by simp qed lemma real-le: (Abs-Real(realrel‘‘{(x1 ,y1 )}) ≤ Abs-Real(realrel‘‘{(x2 ,y2 )})) = (x1 + y2 ≤ x2 + y1 ) apply (simp add: real-le-def ) apply (auto intro: real-le-lemma) done lemma real-le-antisym:[| z ≤ w; w ≤ z |] ==> z = (w::real) by (cases z, cases w, simp add: real-le) lemma real-trans-lemma: assumes x + v ≤ u + y and u + v 0 ≤ u 0 + v and x2 + v2 = u2 + y2 shows x + v 0 ≤ u 0 + (y::preal) proof − have (x+v 0) + (u+v) = (x+v) + (u+v 0) by (simp add: ac-simps) also have ... ≤ (u+y) + (u+v 0) by (simp add: assms) also have ... ≤ (u+y) + (u 0+v) by (simp add: assms) also have ... = (u 0+y) + (u+v) by (simp add: ac-simps) finally show ?thesis by simp qed lemma real-le-trans:[| i ≤ j ; j ≤ k |] ==> i ≤ (k::real) apply (cases i, cases j , cases k) apply (simp add: real-le) apply (blast intro: real-trans-lemma) done

502 instance real :: order proof fix u v :: real show u < v ←→ u ≤ v ∧ ¬ v ≤ u by (auto simp add: real-less-def intro: real-le-antisym) qed (assumption | rule real-le-refl real-le-trans real-le-antisym)+ lemma real-le-linear:(z::real) ≤ w | w ≤ z apply (cases z, cases w) apply (auto simp add: real-le real-zero-def ac-simps) done instance real :: linorder by (intro-classes, rule real-le-linear) lemma real-le-eq-diff :(x ≤ y) = (x−y ≤ (0 ::real)) apply (cases x, cases y) apply (auto simp add: real-le real-zero-def real-diff-def real-add real-minus ac-simps) apply (simp-all add: add.assoc [symmetric]) done lemma real-add-left-mono: assumes le: x ≤ y shows z + x ≤ z + (y::real) proof − have z + x − (z + y) = (z + −z) + (x − y) by (simp add: algebra-simps) with le show ?thesis by (simp add: real-le-eq-diff [of x] real-le-eq-diff [of z+x]) qed lemma real-sum-gt-zero-less:(0 < S + (−W ::real)) ==> (W < S) by (simp add: linorder-not-le [symmetric] real-le-eq-diff [of S]) lemma real-less-sum-gt-zero:(W < S) ==> (0 < S + (−W ::real)) by (simp add: linorder-not-le [symmetric] real-le-eq-diff [of S]) lemma real-mult-order:[| 0 < x; 0 < y |] ==> (0 ::real) < x ∗ y apply (cases x, cases y) apply (simp add: linorder-not-le [where 0a = real, symmetric] linorder-not-le [where 0a = preal] real-zero-def real-le real-mult) — Reduce to the (simpler) ≤ relation apply (auto dest!: less-add-left-Ex simp add: algebra-simps preal-self-less-add-left) done

503 lemma real-mult-less-mono2 :[| (0 ::real) < z; x < y |] ==> z ∗ x < z ∗ y apply (rule real-sum-gt-zero-less) apply (drule real-less-sum-gt-zero [of x y]) apply (drule real-mult-order, assumption) apply (simp add: algebra-simps) done instantiation real :: distrib-lattice begin definition (inf :: real ⇒ real ⇒ real) = min definition (sup :: real ⇒ real ⇒ real) = max instance by standard (auto simp add: inf-real-def sup-real-def max-min-distrib2 ) end

63.7 The Reals Form an Ordered Field instance real :: linordered-field proof fix x y z :: real show x ≤ y ==> z + x ≤ z + y by (rule real-add-left-mono) show x < y ==> 0 < z ==> z ∗ x < z ∗ y by (rule real-mult-less-mono2 ) show |x| = (if x < 0 then −x else x) by (simp only: real-abs-def ) show sgn x = (if x=0 then 0 else if 0

The function real-of-preal requires many proofs, but it seems to be essential for proving completeness of the reals from that of the positive reals. lemma real-of-preal-add: real-of-preal ((x::preal) + y) = real-of-preal x + real-of-preal y by (simp add: real-of-preal-def real-add algebra-simps) lemma real-of-preal-mult: real-of-preal ((x::preal) ∗ y) = real-of-preal x∗ real-of-preal y by (simp add: real-of-preal-def real-mult algebra-simps)

Gleason prop 9-4.4 p 127 lemma real-of-preal-trichotomy: ∃ m. (x::real) = real-of-preal m | x = 0 | x = −(real-of-preal m) apply (simp add: real-of-preal-def real-zero-def , cases x) apply (auto simp add: real-minus ac-simps) apply (cut-tac x = xa and y = y in linorder-less-linear)

504 apply (auto dest!: less-add-left-Ex simp add: add.assoc [symmetric]) done lemma real-of-preal-leD: real-of-preal m1 ≤ real-of-preal m2 ==> m1 ≤ m2 by (simp add: real-of-preal-def real-le) lemma real-of-preal-lessI : m1 < m2 ==> real-of-preal m1 < real-of-preal m2 by (auto simp add: real-of-preal-leD linorder-not-le [symmetric]) lemma real-of-preal-lessD: real-of-preal m1 < real-of-preal m2 ==> m1 < m2 by (simp add: real-of-preal-def real-le linorder-not-le [symmetric]) lemma real-of-preal-less-iff [simp]: (real-of-preal m1 < real-of-preal m2 ) = (m1 < m2 ) by (blast intro: real-of-preal-lessI real-of-preal-lessD) lemma real-of-preal-le-iff : (real-of-preal m1 ≤ real-of-preal m2 ) = (m1 ≤ m2 ) by (simp add: linorder-not-less [symmetric]) lemma real-of-preal-zero-less: 0 < real-of-preal m using preal-self-less-add-left [of 1 m] apply (auto simp add: real-zero-def real-of-preal-def real-less-def real-le-def ac-simps neq-iff ) apply (metis Rep-preal-self-subset add.commute preal-le-def ) done lemma real-of-preal-minus-less-zero: − real-of-preal m < 0 by (simp add: real-of-preal-zero-less) lemma real-of-preal-not-minus-gt-zero: ∼ 0 < − real-of-preal m proof − from real-of-preal-minus-less-zero show ?thesis by (blast dest: order-less-trans) qed

63.8 Theorems About the Ordering lemma real-gt-zero-preal-Ex:(0 < x) = (∃ y. x = real-of-preal y) apply (auto simp add: real-of-preal-zero-less) apply (cut-tac x = x in real-of-preal-trichotomy) apply (blast elim!: real-of-preal-not-minus-gt-zero [THEN notE]) done lemma real-gt-preal-preal-Ex: real-of-preal z < x ==> ∃ y. x = real-of-preal y by (blast dest!: real-of-preal-zero-less [THEN order-less-trans]

505 intro: real-gt-zero-preal-Ex [THEN iffD1 ]) lemma real-ge-preal-preal-Ex: real-of-preal z ≤ x ==> ∃ y. x = real-of-preal y by (blast dest: order-le-imp-less-or-eq real-gt-preal-preal-Ex) lemma real-less-all-preal: y ≤ 0 ==> ∀ x. y < real-of-preal x by (auto elim: order-le-imp-less-or-eq [THEN disjE] intro: real-of-preal-zero-less [THEN [2 ] order-less-trans] simp add: real-of-preal-zero-less) lemma real-less-all-real2 : ∼ 0 < y ==> ∀ x. y < real-of-preal x by (blast intro!: real-less-all-preal linorder-not-less [THEN iffD1 ])

63.9 Completeness of Positive Reals

Supremum property for the set of positive reals Let P be a non-empty set of positive reals, with an upper bound y. Then P has a least upper bound (written S). FIXME: Can the premise be weakened to ∀ x ∈ P. x≤ y? lemma posreal-complete: assumes positive-P: ∀ x ∈ P. (0 ::real) < x and not-empty-P: ∃ x. x ∈ P and upper-bound-Ex: ∃ y. ∀ x ∈ P. x

show (∃ x∈P. y < x) = (y < real-of-preal (psup ?pP)) proof (cases 0 < y) assume neg-y: ¬ 0 < y show ?thesis proof assume ∃ x∈P. y < x have ∀ x. y < real-of-preal x using neg-y by (rule real-less-all-real2 ) thus y < real-of-preal (psup ?pP) .. next assume y < real-of-preal (psup ?pP) obtain x where x-in-P: x ∈ P using not-empty-P .. hence 0 < x using positive-P by simp hence y < x using neg-y by simp thus ∃ x ∈ P. y < x using x-in-P .. qed next assume pos-y: 0 < y

506 then obtain py where y-is-py: y = real-of-preal py by (auto simp add: real-gt-zero-preal-Ex) obtain a where a ∈ P using not-empty-P .. with positive-P have a-pos: 0 < a .. then obtain pa where a = real-of-preal pa by (auto simp add: real-gt-zero-preal-Ex) hence pa ∈ ?pP using ha ∈ P i by auto hence pP-not-empty: ?pP 6= {} by auto obtain sup where sup: ∀ x ∈ P. x < sup using upper-bound-Ex .. from this and ha ∈ P i have a < sup .. hence 0 < sup using a-pos by arith then obtain possup where sup = real-of-preal possup by (auto simp add: real-gt-zero-preal-Ex) hence ∀ X ∈ ?pP. X ≤ possup using sup by (auto simp add: real-of-preal-lessI ) with pP-not-empty have psup: VZ . (∃ X ∈ ?pP. Z < X ) = (Z < psup ?pP) by (rule preal-complete) show ?thesis proof assume ∃ x ∈ P. y < x then obtain x where x-in-P: x ∈ P and y-less-x: y < x .. hence 0 < x using pos-y by arith then obtain px where x-is-px: x = real-of-preal px by (auto simp add: real-gt-zero-preal-Ex)

have py-less-X : ∃ X ∈ ?pP. py < X proof show py < px using y-is-py and x-is-px and y-less-x by (simp add: real-of-preal-lessI ) show px ∈ ?pP using x-in-P and x-is-px by simp qed

have (∃ X ∈ ?pP. py < X ) ==> (py < psup ?pP) using psup by simp hence py < psup ?pP using py-less-X by simp thus y < real-of-preal (psup {w. real-of-preal w ∈ P}) using y-is-py and pos-y by (simp add: real-of-preal-lessI ) next assume y-less-psup: y < real-of-preal (psup ?pP)

hence py < psup ?pP using y-is-py by (simp add: real-of-preal-lessI ) then obtain X where py-less-X : py < X and X-in-pP: X ∈ ?pP using psup by auto then obtain x where x-is-X : x = real-of-preal X

507 by (simp add: real-gt-zero-preal-Ex) hence y < x using py-less-X and y-is-py by (simp add: real-of-preal-lessI )

moreover have x ∈ P using x-is-X and X-in-pP by simp

ultimately show ∃ x ∈ P. y < x .. qed qed qed

Completeness lemma reals-complete: fixes S :: real set assumes notempty-S: ∃ X . X ∈ S and exists-Ub: bdd-above S shows ∃ x. (∀ s∈S. s ≤ x) ∧ (∀ y. (∀ s∈S. s ≤ y) −→ x ≤ y) proof − obtain X where X-in-S: X ∈ S using notempty-S .. obtain Y where Y-isUb: ∀ s∈S. s ≤ Y using exists-Ub by (auto simp: bdd-above-def ) let ?SHIFT = {z. ∃ x ∈S. z = x + (−X ) + 1 } ∩ {x. 0 < x}

{ fix x assume S-le-x: ∀ s∈S. s ≤ x { fix s assume s ∈ {z. ∃ x∈S. z = x + − X + 1 } hence ∃ x ∈ S. s = x + −X + 1 .. then obtain x1 where x1 : x1 ∈ S s = x1 + (−X ) + 1 .. then have x1 ≤ x using S-le-x by simp with x1 have s ≤ x + − X + 1 by arith } then have ∀ s∈?SHIFT . s ≤ x + (−X ) + 1 by auto } note S-Ub-is-SHIFT-Ub = this

have ∗: ∀ s∈?SHIFT . s ≤ Y + (−X ) + 1 using Y-isUb by (rule S-Ub-is-SHIFT-Ub) have ∀ s∈?SHIFT . s < Y + (−X ) + 2 proof fix s assume s∈?SHIFT with ∗ have s ≤ Y + (−X ) + 1 by simp also have . . . < Y + (−X ) + 2 by simp finally show s < Y + (−X ) + 2 . qed moreover have ∀ y ∈ ?SHIFT . 0 < y by auto moreover have shifted-not-empty: ∃ u. u ∈ ?SHIFT using X-in-S and Y-isUb by auto

508 ultimately obtain t where t-is-Lub: ∀ y. (∃ x∈?SHIFT . y < x) = (y < t) using posreal-complete [of ?SHIFT ] unfolding bdd-above-def by blast

show ?thesis proof show (∀ s∈S. s ≤ (t + X + (−1 ))) ∧ (∀ y. (∀ s∈S. s ≤ y) −→ (t + X + (−1 )) ≤ y) proof safe fix x assume ∀ s∈S. s ≤ x hence ∀ s∈?SHIFT . s ≤ x + (−X ) + 1 using S-Ub-is-SHIFT-Ub by simp then have ¬ x + (−X ) + 1 < t by (subst t-is-Lub[rule-format, symmetric]) (simp add: not-less) thus t + X + −1 ≤ x by arith next fix y assume y-in-S: y ∈ S obtain u where u-in-shift: u ∈ ?SHIFT using shifted-not-empty .. hence ∃ x ∈ S. u = x + − X + 1 by simp then obtain x where x-and-u: u = x + − X + 1 .. have u-le-t: u ≤ t proof (rule dense-le) fix x assume x < u then have x < t using u-in-shift t-is-Lub by auto then show x ≤ t by simp qed

show y ≤ t + X + −1 proof cases assume y ≤ x moreover have x = u + X + − 1 using x-and-u by arith moreover have u + X + − 1 ≤ t + X + −1 using u-le-t by arith ultimately show y ≤ t + X + −1 by arith next assume ∼(y ≤ x) hence x-less-y: x < y by arith

have x + (−X ) + 1 ∈ ?SHIFT using x-and-u and u-in-shift by simp hence 0 < x + (−X ) + 1 by simp hence 0 < y + (−X ) + 1 using x-less-y by arith hence ∗: y + (−X ) + 1 ∈ ?SHIFT using y-in-S by simp have y + (−X ) + 1 ≤ t proof (rule dense-le) fix x assume x < y + (−X ) + 1 then have x < t using ∗ t-is-Lub by auto then show x ≤ t by simp qed thus ?thesis by simp

509 qed qed qed qed

63.10 The Archimedean Property of the Reals theorem reals-Archimedean: fixes x :: real assumes x-pos: 0 < x shows ∃ n. inverse (of-nat (Suc n)) < x proof (rule ccontr) assume contr: ¬ ?thesis have ∀ n. x ∗ of-nat (Suc n) <= 1 proof fix n from contr have x ≤ inverse (of-nat (Suc n)) by (simp add: linorder-not-less) hence x ≤ (1 / (of-nat (Suc n))) by (simp add: inverse-eq-divide) moreover have (0 ::real) ≤ of-nat (Suc n) by (rule of-nat-0-le-iff ) ultimately have x ∗ of-nat (Suc n) ≤ (1 / of-nat (Suc n)) ∗ of-nat (Suc n) by (rule mult-right-mono) thus x ∗ of-nat (Suc n) ≤ 1 by (simp del: of-nat-Suc) qed hence 2 : bdd-above {z. ∃ n. z = x ∗ (of-nat (Suc n))} by (auto intro!: bdd-aboveI [of - 1 ]) have 1 : ∃ X . X ∈ {z. ∃ n. z = x∗ (of-nat (Suc n))} by auto obtain t where upper: Vz. z ∈ {z. ∃ n. z = x ∗ of-nat (Suc n)} =⇒ z ≤ t and least: Vy. (Va. a ∈ {z. ∃ n. z = x ∗ of-nat (Suc n)} =⇒ a ≤ y) =⇒ t ≤ y using reals-complete[OF 1 2 ] by auto

have t ≤ t + − x proof (rule least) fix a assume a: a ∈ {z. ∃ n. z = x ∗ (of-nat (Suc n))} have ∀ n::nat. x ∗ of-nat n ≤ t + − x proof fix n have x ∗ of-nat (Suc n) ≤ t by (simp add: upper) hence x ∗ (of-nat n) + x ≤ t by (simp add: distrib-left) thus x ∗ (of-nat n) ≤ t + − x by arith qed hence ∀ m. x ∗ of-nat (Suc m) ≤ t + − x by (simp del: of-nat-Suc) with a show a ≤ t + − x by auto

510 qed thus False using x-pos by arith qed There must be other proofs, e.g. Suc of the largest integer in the cut repre- senting x. lemma reals-Archimedean2 : ∃ n. (x::real) < of-nat (n::nat) proof cases assume x ≤ 0 hence x < of-nat (1 ::nat) by simp thus ?thesis .. next assume ¬ x ≤ 0 hence x-greater-zero: 0 < x by simp hence 0 < inverse x by simp then obtain n where inverse (of-nat (Suc n)) < inverse x using reals-Archimedean by blast hence inverse (of-nat (Suc n)) ∗ x < inverse x ∗ x using x-greater-zero by (rule mult-strict-right-mono) hence inverse (of-nat (Suc n)) ∗ x < 1 using x-greater-zero by simp hence of-nat (Suc n) ∗ (inverse (of-nat (Suc n)) ∗ x) < of-nat (Suc n) ∗ 1 by (rule mult-strict-left-mono)(simp del: of-nat-Suc) hence x < of-nat (Suc n) by (simp add: algebra-simps del: of-nat-Suc) thus ∃ (n::nat). x < of-nat n .. qed instance real :: archimedean-field proof fix r :: real obtain n :: nat where r < of-nat n using reals-Archimedean2 .. then have r ≤ of-int (int n) by simp then show ∃ z. r ≤ of-int z .. qed end

64 Quicksort with function package theory Quicksort imports ∼∼/src/HOL/Library/Multiset begin context linorder begin

511 fun quicksort :: 0a list ⇒ 0a list where quicksort [] = [] | quicksort (x#xs) = quicksort [y←xs. ¬ x≤y]@[x]@ quicksort [y←xs. x≤y] lemma [code]: quicksort [] = [] quicksort (x#xs) = quicksort [y←xs. y

65 A Formulation of the Birthday Paradox theory Birthday-Paradox imports Main ∼∼/src/HOL/Binomial ∼∼/src/HOL/Library/FuncSet begin

66 Cardinality lemma card-product-dependent: assumes finite S assumes ∀ x ∈ S. finite (T x) shows card {(x, y). x ∈ S ∧ y ∈ T x} = (P x ∈ S. card (T x)) using card-SigmaI [OF assms, symmetric] by (auto intro!: arg-cong[where f =card] simp add: Sigma-def ) lemma card-extensional-funcset-inj-on:

512 assumes finite S finite T card S ≤ card T shows card {f ∈ extensional-funcset S T . inj-on f S} = fact (card T ) div (fact (card T − card S)) using assms proof (induct S arbitrary: T rule: finite-induct) case empty from this show ?case by (simp add: Collect-conv-if PiE-empty-domain) next case (insert x S) { fix x from hfinite T i have finite (T − {x}) by auto from hfinite S i this have finite (extensional-funcset S (T − {x})) by (rule finite-PiE) moreover have {f : extensional-funcset S (T − {x}). inj-on f S} ⊆ (extensional-funcset S (T − {x})) by auto ultimately have finite {f : extensional-funcset S (T − {x}). inj-on f S} by (auto intro: finite-subset) } note finite-delete = this from insert have hyps: ∀ y ∈ T . card ({g. g ∈ extensional-funcset S (T − {y}) ∧ inj-on g S}) = fact (card T − 1 ) div fact ((card T − 1 ) − card S)(is ∀ - ∈ T . - = ?k) by auto from extensional-funcset-extend-domain-inj-on-eq[OF hx ∈/ S i] have card {f . f : extensional-funcset (insert x S) T & inj-on f (insert x S)} = card ((%(y, g). g(x := y)) ‘ {(y, g). y : T & g : extensional-funcset S (T − {y})& inj-on g S}) by metis also from extensional-funcset-extend-domain-inj-onI [OF hx ∈/ S i, of T ] have ... = card {(y, g). y : T & g : extensional-funcset S (T − {y})& inj-on g S} by (simp add: card-image) also have card {(y, g). y ∈ T ∧ g ∈ extensional-funcset S (T − {y}) ∧ inj-on g S} = card {(y, g). y ∈ T ∧ g ∈ {f ∈ extensional-funcset S (T − {y}). inj-on f S}} by auto also from hfinite T i finite-delete have ... = (P y ∈ T . card {g. g ∈ extensional-funcset S (T − {y}) ∧ inj-on g S}) by (subst card-product-dependent) auto also from hyps have ... = (card T ) ∗ ?k by auto also have ... = card T ∗ fact (card T − 1 ) div fact (card T − card (insert x S)) using insert unfolding div-mult1-eq[of card T fact (card T − 1 )] by (simp add: fact-mod) also have ... = fact (card T ) div fact (card T − card (insert x S)) using insert by (simp add: fact-reduce[of card T ]) finally show ?case . qed lemma card-extensional-funcset-not-inj-on: assumes finite S finite T card S ≤ card T

513 shows card {f ∈ extensional-funcset S T . ¬ inj-on f S} = (card T ) ˆ (card S) − (fact (card T )) div (fact (card T − card S)) proof − have subset: {f : extensional-funcset S T . inj-on f S} <= extensional-funcset S T by auto from finite-subset[OF subset] assms have finite: finite {f : extensional-funcset ST . inj-on f S} by (auto intro!: finite-PiE) have {f ∈ extensional-funcset S T . ¬ inj-on f S} = extensional-funcset S T − {f ∈ extensional-funcset S T . inj-on f S} by auto from assms this finite subset show ?thesis by (simp add: card-Diff-subset card-PiE card-extensional-funcset-inj-on prod-constant) qed lemma prod-upto-nat-unfold: prod f {m..(n::nat)} = (if n < m then 1 else (if n = 0 then f 0 else f n ∗ prod f {m..(n − 1 )})) by auto (auto simp add: gr0-conv-Suc atLeastAtMostSuc-conv)

67 Birthday paradox lemma birthday-paradox: assumes card S = 23 card T = 365 shows 2 ∗ card {f ∈ extensional-funcset S T . ¬ inj-on f S} ≥ card (extensional-funcset ST ) proof − from hcard S = 23 i hcard T = 365 i have finite S finite T card S <= card T by (auto intro: card-ge-0-finite) from assms show ?thesis using card-PiE[OF hfinite S i, of λi. T ] hfinite S i card-extensional-funcset-not-inj-on[OF hfinite S i hfinite T i hcard S <= card T i] by (simp add: fact-div-fact prod-upto-nat-unfold prod-constant) qed end

68 Examples for the list comprehension to set com- prehension simproc theory List-to-Set-Comprehension-Examples imports Main begin

Examples that show and test the simproc that rewrites list comprehensions applied to List.set to set comprehensions.

514 68.1 Some own examples for set (case ..) simpproc lemma set [(x, xs). x # xs <− as] = {(x, xs). x # xs ∈ set as} by auto lemma set [(x, y, ys). x # y # ys <− as] = {(x, y, ys). x # y # ys ∈ set as} by auto lemma set [(x, y, z, zs). x # y # z # zs <− as] = {(x, y, z, zs). x # y # z # zs ∈ set as} by auto lemma set [(zs, x, z, y). x #(y, z)# zs <− as] = {(zs, x, z, y). x #(y, z)# zs ∈ set as} by auto lemma set [(x, y). x # y <− zs, x = x 0] = {(x, y). x # y ∈ set zs & x = x 0} by auto

68.2 Existing examples from the List theory lemma set [(x,y,z). b] = {(x 0, y 0, z 0). x = x 0 & y = y 0 & z = z 0 & b} by auto lemma set [(x,y,z). x←xs] = {(x, y 0, z 0). x ∈ set xs & y 0 = y & z = z 0} by auto lemma set [e x y. x←xs, y←ys] = {z. ∃ x y. z = e x y & x ∈ set xs & y ∈ set ys} by auto lemma set [(x,y,z). xb] = {(x 0, y 0, z 0). x 0 = x & y 0 = y & z = z 0 & x < a & x>b} by auto lemma set [(x,y,z). x←xs, x>b] = {(x 0, y 0, z 0). y = y 0 & z = z 0 & x 0 ∈ set xs & x 0 > b} by auto lemma set [(x,y,z). x

515 lemma set [(x,y,z). xb, x=d] = {(x 0, y 0, z 0). x = x 0 & y = y 0 & z = z 0 & x < a & x > b & x = d} by auto lemma set [(x,y,z). xb, y←ys] = {(x 0, y, z 0). x = x 0 & y ∈ set ys & z = z 0 & x < a & x > b} by auto lemma set [(x,y,z). xb] = {(x 0,y 0,z 0). x 0 ∈ set xs & y = y 0 & z = z 0 & x < a & y > b} by auto lemma set [(x,y,z). xb, y b & y < a} by auto lemma set [(x,y,z). x←xs, x>b, y←ys] = {(x 0, y 0, z 0). z = z 0 & x 0 ∈ set xs & x 0 > b & y 0 ∈ set ys} by auto lemma set [(x,y,z). x←xs, y←ys,y>x] = {(x 0, y 0, z 0). z = z 0 & x 0 ∈ set xs & y 0 ∈ set ys & y 0 > x 0} by auto lemma set [(x,y,z). x←xs, y←ys,z←zs] = {(x 0, y 0, z 0). x 0 ∈ set xs & y 0 ∈ set ys & z 0 ∈ set zs} by auto end

69 Finite sequences theory Seq imports Main begin datatype 0a seq = Empty | Seq 0a 0a seq fun conc :: 0a seq ⇒ 0a seq ⇒ 0a seq where conc Empty ys = ys | conc (Seq x xs) ys = Seq x (conc xs ys) fun reverse :: 0a seq ⇒ 0a seq where

516 reverse Empty = Empty | reverse (Seq x xs) = conc (reverse xs)(Seq x Empty) lemma conc-empty: conc xs Empty = xs by (induct xs) simp-all lemma conc-assoc: conc (conc xs ys) zs = conc xs (conc ys zs) by (induct xs) simp-all lemma reverse-conc: reverse (conc xs ys) = conc (reverse ys)(reverse xs) by (induct xs)(simp-all add: conc-empty conc-assoc) lemma reverse-reverse: reverse (reverse xs) = xs by (induct xs)(simp-all add: reverse-conc) end

70 Testing of arithmetic simprocs theory Simproc-Tests imports Main begin This theory tests the various simprocs defined in ~~/src/HOL/Nat.thy and ~~/src/HOL/Numeral_Simprocs.thy. Many of the tests are derived from commented-out code originally found in ~~/src/HOL/Tools/numeral_simprocs.ML.

70.1 ML bindings

ML h fun test ctxt ps = CHANGED (asm-simp-tac (put-simpset HOL-basic-ss ctxt addsimprocs ps) 1 ) i

70.2 Cancellation simprocs from Nat.thy notepad begin fix a b c d :: nat { assume b = Suc c have a + b = Suc (c + a) by (tactic htest @{context} [@{simproc nateq-cancel-sums}]i) fact next assume b < Suc c have a + b < Suc (c + a) by (tactic htest @{context} [@{simproc natless-cancel-sums}]i) fact next assume b ≤ Suc c have a + b ≤ Suc (c + a) by (tactic htest @{context} [@{simproc natle-cancel-sums}]i) fact next assume b − Suc c = d have a + b − Suc (c + a) = d

517 by (tactic htest @{context} [@{simproc natdiff-cancel-sums}]i) fact } end schematic-goal V(y::? 0b::size). size (?x::? 0a::size) ≤ size y + size ?x by (tactic htest @{context} [@{simproc natle-cancel-sums}]i)(rule le0 )

70.3 Abelian group cancellation simprocs notepad begin fix a b c u :: 0a::ab-group-add { assume (a + 0 ) − (b + 0 ) = u have (a + c) − (b + c) = u by (tactic htest @{context} [@{simproc group-cancel-diff }]i) fact next assume a + 0 = b + 0 have a + c = b + c by (tactic htest @{context} [@{simproc group-cancel-eq}]i) fact } end

70.4 int-combine-numerals notepad begin fix a b c d oo uu i j k l u v w x y z :: 0a::comm-ring-1 { assume a + − b = u have (a + c) − (b + c) = u by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume 10 + (2 ∗ l + oo) = uu have l + 2 + 2 + 2 + (l + 2 ) + (oo + 2 ) = uu by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume −3 + (i + (j + k)) = y have (i + j + 12 + k) − 15 = y by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume 7 + (i + (j + k)) = y have (i + j + 12 + k) − 5 = y by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume −4 ∗ (u ∗ v) + (2 ∗ x + y) = w have (2 ∗x − (u∗v) + y) − v∗3 ∗u = w by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume 2 ∗ x ∗ u ∗ v + y = w have (2 ∗x∗u∗v + (u∗v)∗4 + y) − v∗u∗4 = w by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume 3 ∗ (u ∗ v) + (2 ∗ x ∗ u ∗ v + y) = w have (2 ∗x∗u∗v + (u∗v)∗4 + y) − v∗u = w

518 by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume −3 ∗ (u ∗ v) + (− (x ∗ u ∗ v) + − y) = w have u∗v − (x∗u∗v + (u∗v)∗4 + y) = w by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume a + − c = d have a + −(b+c) + b = d apply (simp only: minus-add-distrib) by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume −2 ∗ b + (a + − c) = d have a + −(b+c) − b = d apply (simp only: minus-add-distrib) by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume −7 + (i + (j + (k + (− u + − y)))) = z have (i + j + −2 + k) − (u + 5 + y) = z by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume −27 + (i + (j + k)) = y have (i + j + −12 + k) − 15 = y by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume 27 + (i + (j + k)) = y have (i + j + 12 + k) − −15 = y by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact next assume 3 + (i + (j + k)) = y have (i + j + −12 + k) − −15 = y by (tactic htest @{context} [@{simproc int-combine-numerals}]i) fact } end

70.5 inteq-cancel-numerals notepad begin fix i j k u vv w y z w 0 y 0 z 0 :: 0a::comm-ring-1 { assume u = 0 have 2 ∗u = u by (tactic htest @{context} [@{simproc inteq-cancel-numerals}]i) fact

next assume i + (j + k) = 3 + (u + y) have (i + j + 12 + k) = u + 15 + y by (tactic htest @{context} [@{simproc inteq-cancel-numerals}]i) fact next assume 7 + (j + (i + k)) = y have (i + j ∗2 + 12 + k) = j + 5 + y

519 by (tactic htest @{context} [@{simproc inteq-cancel-numerals}]i) fact next assume u + (6 ∗z + (4 ∗y + 6 ∗w)) = 6 ∗z 0 + (4 ∗y 0 + (6 ∗w 0 + vv)) have 2 ∗y + 3 ∗z + 6 ∗w + 2 ∗y + 3 ∗z + 2 ∗u = 2 ∗y 0 + 3 ∗z 0 + 6 ∗w 0 + 2 ∗y 0 + 3 ∗z 0 + u + vv by (tactic htest @{context} [@{simproc int-combine-numerals}, @{simproc inteq-cancel-numerals}]i) fact } end

70.6 intless-cancel-numerals notepad begin fix b c i j k u y :: 0a::linordered-idom { assume y < 2 ∗ b have y − b < b by (tactic htest @{context} [@{simproc intless-cancel-numerals}]i) fact next assume c + y < 4 ∗ b have y − (3 ∗b + c) < b − 2 ∗c by (tactic htest @{context} [@{simproc intless-cancel-numerals}]i) fact next assume i + (j + k) < 8 + (u + y) have (i + j + −3 + k) < u + 5 + y by (tactic htest @{context} [@{simproc intless-cancel-numerals}]i) fact next assume 9 + (i + (j + k)) < u + y have (i + j + 3 + k) < u + −6 + y by (tactic htest @{context} [@{simproc intless-cancel-numerals}]i) fact } end

70.7 ring-eq-cancel-numeral-factor notepad begin fix x y :: 0a::{idom,ring-char-0 } { assume 3 ∗x = 4 ∗y have 9 ∗x = 12 ∗ y by (tactic htest @{context} [@{simproc ring-eq-cancel-numeral-factor}]i) fact next assume −3 ∗x = 4 ∗y have −99 ∗x = 132 ∗ y by (tactic htest @{context} [@{simproc ring-eq-cancel-numeral-factor}]i) fact next assume 111 ∗x = −44 ∗y have 999 ∗x = −396 ∗ y by (tactic htest @{context} [@{simproc ring-eq-cancel-numeral-factor}]i) fact next assume 11 ∗x = 9 ∗y have −99 ∗x = −81 ∗ y by (tactic htest @{context} [@{simproc ring-eq-cancel-numeral-factor}]i) fact next assume 2 ∗x = y have −2 ∗ x = −1 ∗ y by (tactic htest @{context} [@{simproc ring-eq-cancel-numeral-factor}]i) fact

520 next assume 2 ∗x = y have −2 ∗ x = −y by (tactic htest @{context} [@{simproc ring-eq-cancel-numeral-factor}]i) fact } end

70.8 int-div-cancel-numeral-factors notepad begin fix x y z :: 0a::{semiring-div,comm-ring-1 ,ring-char-0 } { assume (3 ∗x) div (4 ∗y) = z have (9 ∗x) div (12 ∗y) = z by (tactic htest @{context} [@{simproc int-div-cancel-numeral-factors}]i) fact next assume (−3 ∗x) div (4 ∗y) = z have (−99 ∗x) div (132 ∗y) = z by (tactic htest @{context} [@{simproc int-div-cancel-numeral-factors}]i) fact next assume (111 ∗x) div (−44 ∗y) = z have (999 ∗x) div (−396 ∗y) = z by (tactic htest @{context} [@{simproc int-div-cancel-numeral-factors}]i) fact next assume (11 ∗x) div (9 ∗y) = z have (−99 ∗x) div (−81 ∗y) = z by (tactic htest @{context} [@{simproc int-div-cancel-numeral-factors}]i) fact next assume (2 ∗x) div y = z have (−2 ∗ x) div (−1 ∗ y) = z by (tactic htest @{context} [@{simproc int-div-cancel-numeral-factors}]i) fact } end

70.9 ring-less-cancel-numeral-factor notepad begin fix x y :: 0a::linordered-idom { assume 3 ∗x < 4 ∗y have 9 ∗x < 12 ∗ y by (tactic htest @{context} [@{simproc ring-less-cancel-numeral-factor}]i) fact next assume −3 ∗x < 4 ∗y have −99 ∗x < 132 ∗ y by (tactic htest @{context} [@{simproc ring-less-cancel-numeral-factor}]i) fact next assume 111 ∗x < −44 ∗y have 999 ∗x < −396 ∗ y by (tactic htest @{context} [@{simproc ring-less-cancel-numeral-factor}]i) fact next assume 9 ∗y < 11 ∗x have −99 ∗x < −81 ∗ y by (tactic htest @{context} [@{simproc ring-less-cancel-numeral-factor}]i) fact next assume y < 2 ∗x have −2 ∗ x < −y by (tactic htest @{context} [@{simproc ring-less-cancel-numeral-factor}]i) fact next assume 23 ∗y < x have −x < −23 ∗ y

521 by (tactic htest @{context} [@{simproc ring-less-cancel-numeral-factor}]i) fact } end

70.10 ring-le-cancel-numeral-factor notepad begin fix x y :: 0a::linordered-idom { assume 3 ∗x ≤ 4 ∗y have 9 ∗x ≤ 12 ∗ y by (tactic htest @{context} [@{simproc ring-le-cancel-numeral-factor}]i) fact next assume −3 ∗x ≤ 4 ∗y have −99 ∗x ≤ 132 ∗ y by (tactic htest @{context} [@{simproc ring-le-cancel-numeral-factor}]i) fact next assume 111 ∗x ≤ −44 ∗y have 999 ∗x ≤ −396 ∗ y by (tactic htest @{context} [@{simproc ring-le-cancel-numeral-factor}]i) fact next assume 9 ∗y ≤ 11 ∗x have −99 ∗x ≤ −81 ∗ y by (tactic htest @{context} [@{simproc ring-le-cancel-numeral-factor}]i) fact next assume y ≤ 2 ∗x have −2 ∗ x ≤ −1 ∗ y by (tactic htest @{context} [@{simproc ring-le-cancel-numeral-factor}]i) fact next assume 23 ∗y ≤ x have −x ≤ −23 ∗ y by (tactic htest @{context} [@{simproc ring-le-cancel-numeral-factor}]i) fact next assume y ≤ 0 have 0 ≤ y ∗ −2 by (tactic htest @{context} [@{simproc ring-le-cancel-numeral-factor}]i) fact next assume − x ≤ y have − (2 ∗ x) ≤ 2 ∗y by (tactic htest @{context} [@{simproc ring-le-cancel-numeral-factor}]i) fact } end

70.11 divide-cancel-numeral-factor notepad begin fix x y z :: 0a::{field,ring-char-0 } { assume (3 ∗x) / (4 ∗y) = z have (9 ∗x) / (12 ∗ y) = z by (tactic htest @{context} [@{simproc divide-cancel-numeral-factor}]i) fact next assume (−3 ∗x) / (4 ∗y) = z have (−99 ∗x) / (132 ∗ y) = z by (tactic htest @{context} [@{simproc divide-cancel-numeral-factor}]i) fact next assume (111 ∗x) / (−44 ∗y) = z have (999 ∗x) / (−396 ∗ y) = z by (tactic htest @{context} [@{simproc divide-cancel-numeral-factor}]i) fact next assume (11 ∗x) / (9 ∗y) = z have (−99 ∗x) / (−81 ∗ y) = z

522 by (tactic htest @{context} [@{simproc divide-cancel-numeral-factor}]i) fact next assume (2 ∗x) / y = z have (−2 ∗ x) / (−1 ∗ y) = z by (tactic htest @{context} [@{simproc divide-cancel-numeral-factor}]i) fact } end

70.12 ring-eq-cancel-factor notepad begin fix a b c d k x y :: 0a::idom { assume k = 0 ∨ x = y have x∗k = k∗y by (tactic htest @{context} [@{simproc ring-eq-cancel-factor}]i) fact next assume k = 0 ∨ 1 = y have k = k∗y by (tactic htest @{context} [@{simproc ring-eq-cancel-factor}]i) fact next assume b = 0 ∨ a∗c = 1 have a∗(b∗c) = b by (tactic htest @{context} [@{simproc ring-eq-cancel-factor}]i) fact next assume a = 0 ∨ b = 0 ∨ c = d∗x have a∗(b∗c) = d∗b∗(x∗a) by (tactic htest @{context} [@{simproc ring-eq-cancel-factor}]i) fact next assume k = 0 ∨ x = y have x∗k = k∗y by (tactic htest @{context} [@{simproc ring-eq-cancel-factor}]i) fact next assume k = 0 ∨ 1 = y have k = k∗y by (tactic htest @{context} [@{simproc ring-eq-cancel-factor}]i) fact } end

70.13 int-div-cancel-factor notepad begin fix a b c d k uu x y :: 0a::semiring-div { assume (if k = 0 then 0 else x div y) = uu have (x∗k) div (k∗y) = uu by (tactic htest @{context} [@{simproc int-div-cancel-factor}]i) fact next assume (if k = 0 then 0 else 1 div y) = uu have (k) div (k∗y) = uu by (tactic htest @{context} [@{simproc int-div-cancel-factor}]i) fact next assume (if b = 0 then 0 else a ∗ c) = uu have (a∗(b∗c)) div b = uu by (tactic htest @{context} [@{simproc int-div-cancel-factor}]i) fact next assume (if a = 0 then 0 else if b = 0 then 0 else c div (d ∗ x)) = uu

523 have (a∗(b∗c)) div (d∗b∗(x∗a)) = uu by (tactic htest @{context} [@{simproc int-div-cancel-factor}]i) fact } end lemma shows a∗(b∗c)/(y∗z) = d∗(b:: 0a::linordered-field)∗(x∗a)/z oops — FIXME: need simproc to cover this case

70.14 divide-cancel-factor notepad begin fix a b c d k uu x y :: 0a::field { assume (if k = 0 then 0 else x / y) = uu have (x∗k) / (k∗y) = uu by (tactic htest @{context} [@{simproc divide-cancel-factor}]i) fact next assume (if k = 0 then 0 else 1 / y) = uu have (k) / (k∗y) = uu by (tactic htest @{context} [@{simproc divide-cancel-factor}]i) fact next assume (if b = 0 then 0 else a ∗ c) = uu have (a∗(b∗c)) / b = uu by (tactic htest @{context} [@{simproc divide-cancel-factor}]i) fact next assume (if a = 0 then 0 else if b = 0 then 0 else c / (d ∗ x)) = uu have (a∗(b∗c)) / (d∗b∗(x∗a)) = uu by (tactic htest @{context} [@{simproc divide-cancel-factor}]i) fact } end lemma fixes a b c d x y z :: 0a::linordered-field shows a∗(b∗c)/(y∗z) = d∗(b)∗(x∗a)/z oops — FIXME: need simproc to cover this case

70.15 linordered-ring-less-cancel-factor notepad begin fix x y z :: 0a::linordered-idom { assume 0 < z =⇒ x < y have 0 < z =⇒ x∗z < y∗z by (tactic htest @{context} [@{simproc linordered-ring-less-cancel-factor}]i) fact next assume 0 < z =⇒ x < y have 0 < z =⇒ x∗z < z∗y by (tactic htest @{context} [@{simproc linordered-ring-less-cancel-factor}]i) fact next assume 0 < z =⇒ x < y have 0 < z =⇒ z∗x < y∗z

524 by (tactic htest @{context} [@{simproc linordered-ring-less-cancel-factor}]i) fact next assume 0 < z =⇒ x < y have 0 < z =⇒ z∗x < z∗y by (tactic htest @{context} [@{simproc linordered-ring-less-cancel-factor}]i) fact next This simproc now uses the simplifier to prove that terms to be canceled are posi- tive/negative. assume z-pos: 0 < z assume x < y have z∗x < z∗y by (tactic hCHANGED (asm-simp-tac (put-simpset HOL-basic-ss @{context} addsimprocs [@{simproc linordered-ring-less-cancel-factor}] addsimps [@{thm z-pos}]) 1 )i) fact } end

70.16 linordered-ring-le-cancel-factor notepad begin fix x y z :: 0a::linordered-idom { assume 0 < z =⇒ x ≤ y have 0 < z =⇒ x∗z ≤ y∗z by (tactic htest @{context} [@{simproc linordered-ring-le-cancel-factor}]i) fact next assume 0 < z =⇒ x ≤ y have 0 < z =⇒ z∗x ≤ z∗y by (tactic htest @{context} [@{simproc linordered-ring-le-cancel-factor}]i) fact } end

70.17 field-combine-numerals notepad begin fix x y z uu :: 0a::{field,ring-char-0 } { assume 5 / 6 ∗ x = uu have x / 2 + x / 3 = uu by (tactic htest @{context} [@{simproc field-combine-numerals}]i) fact next assume 6 / 9 ∗ x + y = uu have x / 3 + y + x / 3 = uu by (tactic htest @{context} [@{simproc field-combine-numerals}]i) fact next assume 9 / 9 ∗ x = uu have 2 ∗ x / 3 + x / 3 = uu by (tactic htest @{context} [@{simproc field-combine-numerals}]i) fact next assume y + z = uu have x / 2 + y − 3 ∗ x / 6 + z = uu by (tactic htest @{context} [@{simproc field-combine-numerals}]i) fact next assume 1 / 15 ∗ x + y = uu

525 have 7 ∗ x / 5 + y − 4 ∗ x / 3 = uu by (tactic htest @{context} [@{simproc field-combine-numerals}]i) fact } end lemma fixes x :: 0a::{linordered-field} shows 2 /3 ∗ x + x / 3 = uu apply (tactic htest @{context} [@{simproc field-combine-numerals}]i)? oops — FIXME: test fails

70.18 nat-combine-numerals notepad begin fix i j k m n u :: nat { assume 4 ∗k = u have k + 3 ∗k = u by (tactic htest @{context} [@{simproc nat-combine-numerals}]i) fact next

assume 4 ∗ Suc 0 + i = u have Suc (i + 3 ) = u by (tactic htest @{context} [@{simproc nat-combine-numerals}]i) fact next

assume 4 ∗ Suc 0 + (i + (j + k)) = u have Suc (i + j + 3 + k) = u by (tactic htest @{context} [@{simproc nat-combine-numerals}]i) fact next assume 2 ∗ j + 4 ∗ k = u have k + j + 3 ∗k + j = u by (tactic htest @{context} [@{simproc nat-combine-numerals}]i) fact next assume 6 ∗ Suc 0 + (5 ∗ (i ∗ j ) + (4 ∗ k + i)) = u have Suc (j ∗i + i + k + 5 + 3 ∗k + i∗j ∗4 ) = u by (tactic htest @{context} [@{simproc nat-combine-numerals}]i) fact next assume 5 ∗ (m ∗ n) = u have (2 ∗n∗m) + (3 ∗(m∗n)) = u by (tactic htest @{context} [@{simproc nat-combine-numerals}]i) fact } end

70.19 nateq-cancel-numerals notepad begin fix i j k l oo u uu vv w y z w 0 y 0 z 0 :: nat { assume Suc 0 ∗ u = 0 have 2 ∗u = (u::nat) by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next assume Suc 0 ∗ u = Suc 0 have 2 ∗u = Suc (u) by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next

526 assume i + (j + k) = 3 ∗ Suc 0 + (u + y) have (i + j + 12 + k) = u + 15 + y by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next assume 7 ∗ Suc 0 + (i + (j + k)) = u + y have (i + j + 12 + k) = u + 5 + y by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next assume 11 ∗ Suc 0 + (i + (j + k)) = u + y have (i + j + 12 + k) = Suc (u + y) by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next assume i + (j + k) = 2 ∗ Suc 0 + (u + y) have (i + j + 5 + k) = Suc (Suc (Suc (Suc (Suc (Suc (Suc (u + y))))))) by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next assume Suc 0 ∗ u + (2 ∗ y + 3 ∗ z) = Suc 0 have 2 ∗y + 3 ∗z + 2 ∗u = Suc (u) by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next assume Suc 0 ∗ u + (2 ∗ y + (3 ∗ z + (6 ∗ w + (2 ∗ y + 3 ∗ z)))) = Suc 0 have 2 ∗y + 3 ∗z + 6 ∗w + 2 ∗y + 3 ∗z + 2 ∗u = Suc (u) by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next assume Suc 0 ∗ u + (2 ∗ y + (3 ∗ z + (6 ∗ w + (2 ∗ y + 3 ∗ z)))) = 2 ∗ y 0 + (3 ∗ z 0 + (6 ∗ w 0 + (2 ∗ y 0 + (3 ∗ z 0 + vv)))) have 2 ∗y + 3 ∗z + 6 ∗w + 2 ∗y + 3 ∗z + 2 ∗u = 2 ∗y 0 + 3 ∗z 0 + 6 ∗w 0 + 2 ∗y 0 + 3 ∗z 0 + u + vv by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact next assume 2 ∗ u + (2 ∗ z + (5 ∗ Suc 0 + 2 ∗ y)) = vv have 6 + 2 ∗y + 3 ∗z + 4 ∗u = Suc (vv + 2 ∗u + z) by (tactic htest @{context} [@{simproc nateq-cancel-numerals}]i) fact } end

70.20 natless-cancel-numerals notepad begin fix length :: 0a ⇒ nat and l1 l2 xs :: 0a and f :: nat ⇒ 0a fix c i j k l m oo u uu vv w y z w 0 y 0 z 0 :: nat { assume 0 < j have (2 ∗length xs < 2 ∗length xs + j ) by (tactic htest @{context} [@{simproc natless-cancel-numerals}]i) fact next assume 0 < j have (2 ∗length xs < length xs ∗ 2 + j ) by (tactic htest @{context} [@{simproc natless-cancel-numerals}]i) fact next assume i + (j + k) < u + y

527 have (i + j + 5 + k) < Suc (Suc (Suc (Suc (Suc (u + y))))) by (tactic htest @{context} [@{simproc natless-cancel-numerals}]i) fact next assume 0 < Suc 0 ∗ (m ∗ n) + u have (2 ∗n∗m) < (3 ∗(m∗n)) + u by (tactic htest @{context} [@{simproc natless-cancel-numerals}]i) fact } end

70.21 natle-cancel-numerals notepad begin fix length :: 0a ⇒ nat and l2 l3 :: 0a and f :: nat ⇒ 0a fix c e i j k l oo u uu vv w y z w 0 y 0 z 0 :: nat { assume u + y ≤ 36 ∗ Suc 0 + (i + (j + k)) have Suc (Suc (Suc (Suc (Suc (u + y))))) ≤ ((i + j ) + 41 + k) by (tactic htest @{context} [@{simproc natle-cancel-numerals}]i) fact next assume 5 ∗ Suc 0 + (case length (f c) of 0 ⇒ 0 | Suc k ⇒ k) = 0 have (Suc (Suc (Suc (Suc (Suc (Suc (case length (f c) of 0 => 0 | Suc k => k)))))) ≤ Suc 0 ) by (tactic htest @{context} [@{simproc natle-cancel-numerals}]i) fact next assume 6 + length l2 = 0 have Suc (Suc (Suc (Suc (Suc (Suc (length l1 + length l2 )))))) ≤ length l1 by (tactic htest @{context} [@{simproc natle-cancel-numerals}]i) fact next assume 5 + length l3 = 0 have ((Suc (Suc (Suc (Suc (Suc (length (compT P E A ST mxr e) + length l3 )))))) ≤ length (compT P E A ST mxr e)) by (tactic htest @{context} [@{simproc natle-cancel-numerals}]i) fact next assume 5 + length (compT P E (A ∪ A 0 e) ST mxr c) = 0 have ((Suc (Suc (Suc (Suc (Suc (length (compT P E A ST mxr e) + length (compT P E (A Un A 0 e) ST mxr c))))))) ≤ length (compT P E A ST mxr e)) by (tactic htest @{context} [@{simproc natle-cancel-numerals}]i) fact } end

70.22 natdiff-cancel-numerals notepad begin fix length :: 0a ⇒ nat and l2 l3 :: 0a and f :: nat ⇒ 0a fix c e i j k l oo u uu vv v w x y z zz w 0 y 0 z 0 :: nat { assume i + (j + k) − 3 ∗ Suc 0 = y have (i + j + 12 + k) − 15 = y by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume 7 ∗ Suc 0 + (i + (j + k)) − 0 = y have (i + j + 12 + k) − 5 = y by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact

528 next assume u − Suc 0 ∗ Suc 0 = y have Suc u − 2 = y by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume Suc 0 ∗ Suc 0 + u − 0 = y have Suc (Suc (Suc u)) − 2 = y by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume Suc 0 ∗ Suc 0 + (i + (j + k)) − 0 = y have (i + j + 2 + k) − 1 = y by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume i + (j + k) − Suc 0 ∗ Suc 0 = y have (i + j + 1 + k) − 2 = y by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume 2 ∗ x + y − 2 ∗ (u ∗ v) = w have (2 ∗x + (u∗v) + y) − v∗3 ∗u = w by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume 2 ∗ x ∗ u ∗ v + (5 + y) − 0 = w have (2 ∗x∗u∗v + 5 + (u∗v)∗4 + y) − v∗u∗4 = w by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume 3 ∗ (u ∗ v) + (2 ∗ x ∗ u ∗ v + y) − 0 = w have (2 ∗x∗u∗v + (u∗v)∗4 + y) − v∗u = w by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume 3 ∗ u + (2 + (2 ∗ x ∗ u ∗ v + y)) − 0 = w have Suc (Suc (2 ∗x∗u∗v + u∗4 + y)) − u = w by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume Suc (Suc 0 ∗ (u ∗ v)) − 0 = w have Suc ((u∗v)∗4 ) − v∗3 ∗u = w by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume 2 − 0 = w have Suc (Suc ((u∗v)∗3 )) − v∗3 ∗u = w by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume 17 ∗ Suc 0 + (i + (j + k)) − (u + y) = zz have (i + j + 32 + k) − (u + 15 + y) = zz by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact next assume u + y − 0 = v have Suc (Suc (Suc (Suc (Suc (u + y))))) − 5 = v by (tactic htest @{context} [@{simproc natdiff-cancel-numerals}]i) fact } end

529 70.23 Factor-cancellation simprocs for type nat nat-eq-cancel-factor, nat-less-cancel-factor, nat-le-cancel-factor, nat-divide-cancel-factor, and nat-dvd-cancel-factor. notepad begin fix a b c d k x y uu :: nat { assume k = 0 ∨ x = y have x∗k = k∗y by (tactic htest @{context} [@{simproc nat-eq-cancel-factor}]i) fact next assume k = 0 ∨ Suc 0 = y have k = k∗y by (tactic htest @{context} [@{simproc nat-eq-cancel-factor}]i) fact next assume b = 0 ∨ a ∗ c = Suc 0 have a∗(b∗c) = b by (tactic htest @{context} [@{simproc nat-eq-cancel-factor}]i) fact next assume a = 0 ∨ b = 0 ∨ c = d ∗ x have a∗(b∗c) = d∗b∗(x∗a) by (tactic htest @{context} [@{simproc nat-eq-cancel-factor}]i) fact next assume 0 < k ∧ x < y have x∗k < k∗y by (tactic htest @{context} [@{simproc nat-less-cancel-factor}]i) fact next assume 0 < k ∧ Suc 0 < y have k < k∗y by (tactic htest @{context} [@{simproc nat-less-cancel-factor}]i) fact next assume 0 < b ∧ a ∗ c < Suc 0 have a∗(b∗c) < b by (tactic htest @{context} [@{simproc nat-less-cancel-factor}]i) fact next assume 0 < a ∧ 0 < b ∧ c < d ∗ x have a∗(b∗c) < d∗b∗(x∗a) by (tactic htest @{context} [@{simproc nat-less-cancel-factor}]i) fact next assume 0 < k −→ x ≤ y have x∗k ≤ k∗y by (tactic htest @{context} [@{simproc nat-le-cancel-factor}]i) fact next assume 0 < k −→ Suc 0 ≤ y have k ≤ k∗y by (tactic htest @{context} [@{simproc nat-le-cancel-factor}]i) fact next assume 0 < b −→ a ∗ c ≤ Suc 0 have a∗(b∗c) ≤ b by (tactic htest @{context} [@{simproc nat-le-cancel-factor}]i) fact next assume 0 < a −→ 0 < b −→ c ≤ d ∗ x have a∗(b∗c) ≤ d∗b∗(x∗a) by (tactic htest @{context} [@{simproc nat-le-cancel-factor}]i) fact next assume (if k = 0 then 0 else x div y) = uu have (x∗k) div (k∗y) = uu by (tactic htest @{context} [@{simproc nat-div-cancel-factor}]i) fact next assume (if k = 0 then 0 else Suc 0 div y) = uu have k div (k∗y) = uu by (tactic htest @{context} [@{simproc nat-div-cancel-factor}]i) fact next

530 assume (if b = 0 then 0 else a ∗ c) = uu have (a∗(b∗c)) div (b) = uu by (tactic htest @{context} [@{simproc nat-div-cancel-factor}]i) fact next assume (if a = 0 then 0 else if b = 0 then 0 else c div (d ∗ x)) = uu have (a∗(b∗c)) div (d∗b∗(x∗a)) = uu by (tactic htest @{context} [@{simproc nat-div-cancel-factor}]i) fact next assume k = 0 ∨ x dvd y have (x∗k) dvd (k∗y) by (tactic htest @{context} [@{simproc nat-dvd-cancel-factor}]i) fact next assume k = 0 ∨ Suc 0 dvd y have k dvd (k∗y) by (tactic htest @{context} [@{simproc nat-dvd-cancel-factor}]i) fact next assume b = 0 ∨ a ∗ c dvd Suc 0 have (a∗(b∗c)) dvd (b) by (tactic htest @{context} [@{simproc nat-dvd-cancel-factor}]i) fact next assume b = 0 ∨ Suc 0 dvd a ∗ c have b dvd (a∗(b∗c)) by (tactic htest @{context} [@{simproc nat-dvd-cancel-factor}]i) fact next assume a = 0 ∨ b = 0 ∨ c dvd d ∗ x have (a∗(b∗c)) dvd (d∗b∗(x∗a)) by (tactic htest @{context} [@{simproc nat-dvd-cancel-factor}]i) fact } end

70.24 Numeral-cancellation simprocs for type nat notepad begin fix x y z :: nat { assume 3 ∗ x = 4 ∗ y have 9 ∗x = 12 ∗ y by (tactic htest @{context} [@{simproc nat-eq-cancel-numeral-factor}]i) fact next assume 3 ∗ x < 4 ∗ y have 9 ∗x < 12 ∗ y by (tactic htest @{context} [@{simproc nat-less-cancel-numeral-factor}]i) fact next assume 3 ∗ x ≤ 4 ∗ y have 9 ∗x ≤ 12 ∗ y by (tactic htest @{context} [@{simproc nat-le-cancel-numeral-factor}]i) fact next assume (3 ∗ x) div (4 ∗ y) = z have (9 ∗x) div (12 ∗ y) = z by (tactic htest @{context} [@{simproc nat-div-cancel-numeral-factor}]i) fact next assume (3 ∗ x) dvd (4 ∗ y) have (9 ∗x) dvd (12 ∗ y) by (tactic htest @{context} [@{simproc nat-dvd-cancel-numeral-factor}]i) fact } end

70.25 Integer numeral div/mod simprocs notepad begin have (10 ::int) div 3 = 3

531 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (10 ::int) mod 3 = 1 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (10 ::int) div −3 = −4 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (10 ::int) mod −3 = −2 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (−10 ::int) div 3 = −4 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (−10 ::int) mod 3 = 2 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (−10 ::int) div −3 = 3 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (−10 ::int) mod −3 = −1 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (8452 ::int) mod 3 = 1 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (59485 ::int) div 434 = 137 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have (1000006 ::int) mod 10 = 6 by (tactic htest @{context} [@{simproc numeral-divmod}]i) have 10000000 div 2 = (5000000 ::int) by (tactic htest @{context} [@{simproc numeral-divmod}]i) have 10000001 mod 2 = (1 ::int) by (tactic htest @{context} [@{simproc numeral-divmod}]i) have 10000055 div 32 = (312501 ::int) by (tactic htest @{context} [@{simproc numeral-divmod}]i) have 10000055 mod 32 = (23 ::int) by (tactic htest @{context} [@{simproc numeral-divmod}]i) have 100094 div 144 = (695 ::int) by (tactic htest @{context} [@{simproc numeral-divmod}]i) have 100094 mod 144 = (14 ::int) by (tactic htest @{context} [@{simproc numeral-divmod}]i) end end theory Executable-Relation imports Main begin

70.26 A dedicated type for relations 70.26.1 Definition of the dedicated type for relations typedef 0a rel = UNIV :: (( 0a ∗ 0a) set) set morphisms set-of-rel rel-of-set by simp setup-lifting type-definition-rel lift-definition Rel :: 0a set => ( 0a ∗ 0a) set => 0a rel is λ XR. Id-on X Un R .

532 70.26.2 Constant definitions on relations hide-const (open) converse relcomp rtrancl Image lift-definition member :: 0a ∗ 0a => 0a rel => bool is Set.member . lift-definition converse :: 0a rel => 0a rel is Relation.converse . lift-definition union :: 0a rel => 0a rel => 0a rel is Set.union . lift-definition relcomp :: 0a rel => 0a rel => 0a rel is Relation.relcomp . lift-definition rtrancl :: 0a rel => 0a rel is Transitive-Closure.rtrancl . lift-definition Image :: 0a rel => 0a set => 0a set is Relation.Image .

70.26.3 Code generation code-datatype Rel lemma [code]: member (x, y)(Rel X R) = ((x = y ∧ x : X ) ∨ (x, y): R) by transfer auto lemma [code]: converse (Rel X R) = Rel X (Rˆ−1 ) by transfer auto lemma [code]: union (Rel X R)(Rel Y S) = Rel (X Un Y )(R Un S) by transfer auto lemma [code]: relcomp (Rel X R)(Rel Y S) = Rel (X Int Y )(Set.filter (%(x, y). y : Y ) R Un (Set.filter (%(x, y). x : X ) S Un R O S)) by transfer (auto simp add: Id-on-eqI relcomp.simps) lemma [code]: rtrancl (Rel X R) = Rel UNIV (Rˆ+) apply transfer apply auto apply (metis Id-on-iff Un-commute UNIV-I rtrancl-Un-separatorE rtrancl-eq-or-trancl) by (metis in-rtrancl-UnI trancl-into-rtrancl) lemma [code]: Image (Rel X R) S = (X Int S) Un (R ‘‘ S) by transfer auto quickcheck-generator rel constructors: Rel

533 lemma member (x, (y :: nat)) (rtrancl (union R S)) =⇒ member (x, y)(union (rtrancl R)(rtrancl S)) quickcheck[exhaustive, expect = counterexample] oops end

71 A generic phantom type theory Phantom-Type imports Main begin datatype ( 0a, 0b) phantom = phantom (of-phantom: 0b) lemma type-definition-phantom 0: type-definition of-phantom phantom UNIV by(unfold-locales) simp-all lemma phantom-comp-of-phantom [simp]: phantom ◦ of-phantom = id and of-phantom-comp-phantom [simp]: of-phantom ◦ phantom = id by(simp-all add: o-def id-def ) syntax -Phantom :: type ⇒ logic ((1Phantom/(1 0(- 0)))) translations Phantom( 0t) => CONST phantom :: - ⇒ ( 0t, -) phantom typed-print-translation h let fun phantom-tr 0 ctxt (Type (@{type-name fun}, [-, Type (@{type-name phan- tom}, [T , -])])) ts = list-comb (Syntax.const @{syntax-const -Phantom} $ Syntax-Phases.term-of-typ ctxt T , ts) | phantom-tr 0 --- = raise Match; in [(@{const-syntax phantom}, phantom-tr 0)] end i lemma of-phantom-inject [simp]: of-phantom x = of-phantom y ←→ x = y by(cases x y rule: phantom.exhaust[case-product phantom.exhaust]) simp end

72 Cardinality of types theory Cardinality imports Phantom-Type

534 begin

72.1 Preliminary lemmas lemma (in type-definition) univ: UNIV = Abs ‘ A proof show Abs ‘ A ⊆ UNIV by (rule subset-UNIV ) show UNIV ⊆ Abs ‘ A proof fix x :: 0b have x = Abs (Rep x) by (rule Rep-inverse [symmetric]) moreover have Rep x ∈ A by (rule Rep) ultimately show x ∈ Abs ‘ A by (rule image-eqI ) qed qed lemma (in type-definition) card: card (UNIV :: 0b set) = card A by (simp add: univ card-image inj-on-def Abs-inject) lemma finite-range-Some: finite (range (Some :: 0a ⇒ 0a option)) = finite (UNIV :: 0a set) by(auto dest: finite-imageD intro: inj-Some) lemma infinite-literal: ¬ finite (UNIV :: String.literal set) proof − have inj STR by(auto intro: injI ) thus ?thesis by(auto simp add: type-definition.univ[OF type-definition-literal] infinite-UNIV-listI dest: finite-imageD) qed

72.2 Cardinalities of types syntax -type-card :: type => nat ((1CARD/(1 0(- 0)))) translations CARD( 0t) => CONST card (CONST UNIV :: 0t set) print-translation h let fun card-univ-tr 0 ctxt [Const (@{const-syntax UNIV }, Type (-, [T ]))] = Syntax.const @{syntax-const -type-card} $ Syntax-Phases.term-of-typ ctxt T in [(@{const-syntax card}, card-univ-tr 0)] end i lemma card-prod [simp]: CARD( 0a × 0b) = CARD( 0a) ∗ CARD( 0b) unfolding UNIV-Times-UNIV [symmetric] by (simp only: card-cartesian-product) lemma card-UNIV-sum: CARD( 0a + 0b) = (if CARD( 0a) 6= 0 ∧ CARD( 0b) 6= 0 then CARD( 0a) + CARD( 0b) else 0 )

535 unfolding UNIV-Plus-UNIV [symmetric] by(auto simp add: card-eq-0-iff card-Plus simp del: UNIV-Plus-UNIV ) lemma card-sum [simp]: CARD( 0a + 0b) = CARD( 0a::finite) + CARD( 0b::finite) by(simp add: card-UNIV-sum) lemma card-UNIV-option: CARD( 0a option) = (if CARD( 0a) = 0 then 0 else CARD( 0a) + 1 ) proof − have (None :: 0a option) ∈/ range Some by clarsimp thus ?thesis by (simp add: UNIV-option-conv card-eq-0-iff finite-range-Some card-image) qed lemma card-option [simp]: CARD( 0a option) = Suc CARD( 0a::finite) by(simp add: card-UNIV-option) lemma card-UNIV-set: CARD( 0a set) = (if CARD( 0a) = 0 then 0 else 2 ˆ CARD( 0a)) by(simp add: Pow-UNIV [symmetric] card-eq-0-iff card-Pow del: Pow-UNIV ) lemma card-set [simp]: CARD( 0a set) = 2 ˆ CARD( 0a::finite) by(simp add: card-UNIV-set) lemma card-nat [simp]: CARD(nat) = 0 by (simp add: card-eq-0-iff ) lemma card-fun: CARD( 0a ⇒ 0b) = (if CARD( 0a) 6= 0 ∧ CARD( 0b) 6= 0 ∨ CARD( 0b) = 1 then CARD( 0b) ˆ CARD( 0a) else 0 ) proof − { assume 0 < CARD( 0a) and 0 < CARD( 0b) hence fina: finite (UNIV :: 0a set) and finb: finite (UNIV :: 0b set) by(simp-all only: card-ge-0-finite) from finite-distinct-list[OF finb] obtain bs where bs: set bs = (UNIV :: 0b set) and distb: distinct bs by blast from finite-distinct-list[OF fina] obtain as where as: set as = (UNIV :: 0a set) and dista: distinct as by blast have cb: CARD( 0b) = length bs unfolding bs[symmetric] distinct-card[OF distb] .. have ca: CARD( 0a) = length as unfolding as[symmetric] distinct-card[OF dista] .. let ?xs = map (λys. the o map-of (zip as ys)) (List.n-lists (length as) bs) have UNIV = set ?xs proof(rule UNIV-eq-I ) fix f :: 0a ⇒ 0b from as have f = the ◦ map-of (zip as (map f as)) by(auto simp add: map-of-zip-map) thus f ∈ set ?xs using bs by(auto simp add: set-n-lists) qed moreover have distinct ?xs unfolding distinct-map

536 proof(intro conjI distinct-n-lists distb inj-onI ) fix xs ys :: 0b list assume xs: xs ∈ set (List.n-lists (length as) bs) and ys: ys ∈ set (List.n-lists (length as) bs) and eq: the ◦ map-of (zip as xs) = the ◦ map-of (zip as ys) from xs ys have [simp]: length xs = length as length ys = length as by(simp-all add: length-n-lists-elem) have map-of (zip as xs) = map-of (zip as ys) proof fix x from as bs have ∃ y. map-of (zip as xs) x = Some y ∃ y. map-of (zip as ys) x = Some y by(simp-all add: map-of-zip-is-Some[symmetric]) with eq show map-of (zip as xs) x = map-of (zip as ys) x by(auto dest: fun-cong[where x=x]) qed with dista show xs = ys by(simp add: map-of-zip-inject) qed hence card (set ?xs) = length ?xs by(simp only: distinct-card) moreover have length ?xs = length bs ˆ length as by(simp add: length-n-lists) ultimately have CARD( 0a ⇒ 0b) = CARD( 0b) ˆ CARD( 0a) using cb ca by simp } moreover { assume cb: CARD( 0b) = 1 then obtain b where b: UNIV = {b :: 0b} by(auto simp add: card-Suc-eq) have eq: UNIV = {λx :: 0a. b :: 0b} proof(rule UNIV-eq-I ) fix x :: 0a ⇒ 0b { fix y have x y ∈ UNIV .. hence x y = b unfolding b by simp } thus x ∈ {λx. b} by(auto) qed have CARD( 0a ⇒ 0b) = 1 unfolding eq by simp } ultimately show ?thesis by(auto simp del: One-nat-def )(auto simp add: card-eq-0-iff dest: finite-fun-UNIVD2 finite-fun-UNIVD1 ) qed corollary finite-UNIV-fun: finite (UNIV :: ( 0a ⇒ 0b) set) ←→ finite (UNIV :: 0a set) ∧ finite (UNIV :: 0b set) ∨ CARD( 0b) = 1 (is ?lhs ←→ ?rhs) proof − have ?lhs ←→ CARD( 0a ⇒ 0b) > 0 by(simp add: card-gt-0-iff ) also have ... ←→ CARD( 0a) > 0 ∧ CARD( 0b) > 0 ∨ CARD( 0b) = 1 by(simp add: card-fun) also have ... = ?rhs by(simp add: card-gt-0-iff ) finally show ?thesis .

537 qed lemma card-literal: CARD(String.literal) = 0 by(simp add: card-eq-0-iff infinite-literal)

72.3 Classes with at least 1 and 2

Class finite already captures ”at least 1” lemma zero-less-card-finite [simp]: 0 < CARD( 0a::finite) unfolding neq0-conv [symmetric] by simp lemma one-le-card-finite [simp]: Suc 0 ≤ CARD( 0a::finite) by (simp add: less-Suc-eq-le [symmetric])

Class for cardinality ”at least 2” class card2 = finite + assumes two-le-card: 2 ≤ CARD( 0a) lemma one-less-card: Suc 0 < CARD( 0a::card2 ) using two-le-card [where 0a= 0a] by simp lemma one-less-int-card: 1 < int CARD( 0a::card2 ) using one-less-card [where 0a= 0a] by simp

72.4 A type class for deciding finiteness of types type-synonym 0a finite-UNIV = ( 0a, bool) phantom class finite-UNIV = fixes finite-UNIV :: ( 0a, bool) phantom assumes finite-UNIV : finite-UNIV = Phantom( 0a)(finite (UNIV :: 0a set)) lemma finite-UNIV-code [code-unfold]: finite (UNIV :: 0a :: finite-UNIV set) ←→ of-phantom (finite-UNIV :: 0a finite-UNIV ) by(simp add: finite-UNIV )

72.5 A type class for computing the cardinality of types definition is-list-UNIV :: 0a list ⇒ bool where is-list-UNIV xs = (let c = CARD( 0a) in if c = 0 then False else size (remdups xs) = c) lemma is-list-UNIV-iff : is-list-UNIV xs ←→ set xs = UNIV by(auto simp add: is-list-UNIV-def Let-def card-eq-0-iff List.card-set[symmetric] dest: subst[where P=finite, OF - finite-set] card-eq-UNIV-imp-eq-UNIV ) type-synonym 0a card-UNIV = ( 0a, nat) phantom

538 class card-UNIV = finite-UNIV + fixes card-UNIV :: 0a card-UNIV assumes card-UNIV : card-UNIV = Phantom( 0a) CARD( 0a)

72.6 Instantiations for card-UNIV instantiation nat :: card-UNIV begin definition finite-UNIV = Phantom(nat) False definition card-UNIV = Phantom(nat) 0 instance by intro-classes (simp-all add: finite-UNIV-nat-def card-UNIV-nat-def ) end instantiation int :: card-UNIV begin definition finite-UNIV = Phantom(int) False definition card-UNIV = Phantom(int) 0 instance by intro-classes (simp-all add: card-UNIV-int-def finite-UNIV-int-def infinite-UNIV-int) end instantiation natural :: card-UNIV begin definition finite-UNIV = Phantom(natural) False definition card-UNIV = Phantom(natural) 0 instance by standard (auto simp add: finite-UNIV-natural-def card-UNIV-natural-def card-eq-0-iff type-definition.univ [OF type-definition-natural] natural-eq-iff dest!: finite-imageD intro: inj-onI ) end instantiation integer :: card-UNIV begin definition finite-UNIV = Phantom(integer) False definition card-UNIV = Phantom(integer) 0 instance by standard (auto simp add: finite-UNIV-integer-def card-UNIV-integer-def card-eq-0-iff type-definition.univ [OF type-definition-integer] infinite-UNIV-int dest!: finite-imageD intro: inj-onI ) end instantiation list :: (type) card-UNIV begin definition finite-UNIV = Phantom( 0a list) False definition card-UNIV = Phantom( 0a list) 0 instance by intro-classes (simp-all add: card-UNIV-list-def finite-UNIV-list-def infinite-UNIV-listI ) end instantiation unit :: card-UNIV begin definition finite-UNIV = Phantom(unit) True definition card-UNIV = Phantom(unit) 1

539 instance by intro-classes (simp-all add: card-UNIV-unit-def finite-UNIV-unit-def ) end instantiation bool :: card-UNIV begin definition finite-UNIV = Phantom(bool) True definition card-UNIV = Phantom(bool) 2 instance by(intro-classes)(simp-all add: card-UNIV-bool-def finite-UNIV-bool-def ) end instantiation char :: card-UNIV begin definition finite-UNIV = Phantom(char) True definition card-UNIV = Phantom(char) 256 instance by intro-classes (simp-all add: card-UNIV-char-def card-UNIV-char finite-UNIV-char-def ) end instantiation prod :: (finite-UNIV , finite-UNIV ) finite-UNIV begin definition finite-UNIV = Phantom( 0a × 0b) (of-phantom (finite-UNIV :: 0a finite-UNIV ) ∧ of-phantom (finite-UNIV :: 0b finite-UNIV )) instance by intro-classes (simp add: finite-UNIV-prod-def finite-UNIV finite-prod) end instantiation prod :: (card-UNIV , card-UNIV ) card-UNIV begin definition card-UNIV = Phantom( 0a × 0b) (of-phantom (card-UNIV :: 0a card-UNIV ) ∗ of-phantom (card-UNIV :: 0b card-UNIV )) instance by intro-classes (simp add: card-UNIV-prod-def card-UNIV ) end instantiation sum :: (finite-UNIV , finite-UNIV ) finite-UNIV begin definition finite-UNIV = Phantom( 0a + 0b) (of-phantom (finite-UNIV :: 0a finite-UNIV ) ∧ of-phantom (finite-UNIV :: 0b finite-UNIV )) instance by intro-classes (simp add: UNIV-Plus-UNIV [symmetric] finite-UNIV-sum-def finite-UNIV del: UNIV-Plus-UNIV ) end instantiation sum :: (card-UNIV , card-UNIV ) card-UNIV begin definition card-UNIV = Phantom( 0a + 0b) (let ca = of-phantom (card-UNIV :: 0a card-UNIV ); cb = of-phantom (card-UNIV :: 0b card-UNIV ) in if ca 6= 0 ∧ cb 6= 0 then ca + cb else 0 ) instance by intro-classes (auto simp add: card-UNIV-sum-def card-UNIV card-UNIV-sum) end instantiation fun :: (finite-UNIV , card-UNIV ) finite-UNIV begin definition finite-UNIV = Phantom( 0a ⇒ 0b) (let cb = of-phantom (card-UNIV :: 0b card-UNIV ) in cb = 1 ∨ of-phantom (finite-UNIV :: 0a finite-UNIV ) ∧ cb 6= 0 )

540 instance by intro-classes (auto simp add: finite-UNIV-fun-def Let-def card-UNIV finite-UNIV finite-UNIV-fun card-gt-0-iff ) end instantiation fun :: (card-UNIV , card-UNIV ) card-UNIV begin definition card-UNIV = Phantom( 0a ⇒ 0b) (let ca = of-phantom (card-UNIV :: 0a card-UNIV ); cb = of-phantom (card-UNIV :: 0b card-UNIV ) in if ca 6= 0 ∧ cb 6= 0 ∨ cb = 1 then cb ˆ ca else 0 ) instance by intro-classes (simp add: card-UNIV-fun-def card-UNIV Let-def card-fun) end instantiation option :: (finite-UNIV ) finite-UNIV begin definition finite-UNIV = Phantom( 0a option)(of-phantom (finite-UNIV :: 0a finite-UNIV )) instance by intro-classes (simp add: finite-UNIV-option-def finite-UNIV ) end instantiation option :: (card-UNIV ) card-UNIV begin definition card-UNIV = Phantom( 0a option) (let c = of-phantom (card-UNIV :: 0a card-UNIV ) in if c 6= 0 then Suc c else 0 ) instance by intro-classes (simp add: card-UNIV-option-def card-UNIV card-UNIV-option) end instantiation String.literal :: card-UNIV begin definition finite-UNIV = Phantom(String.literal) False definition card-UNIV = Phantom(String.literal) 0 instance by intro-classes (simp-all add: card-UNIV-literal-def finite-UNIV-literal-def infinite-literal card-literal) end instantiation set :: (finite-UNIV ) finite-UNIV begin definition finite-UNIV = Phantom( 0a set)(of-phantom (finite-UNIV :: 0a finite-UNIV )) instance by intro-classes (simp add: finite-UNIV-set-def finite-UNIV Finite-Set.finite-set) end instantiation set :: (card-UNIV ) card-UNIV begin definition card-UNIV = Phantom( 0a set) (let c = of-phantom (card-UNIV :: 0a card-UNIV ) in if c = 0 then 0 else 2 ˆ c) instance by intro-classes (simp add: card-UNIV-set-def card-UNIV-set card-UNIV ) end lemma UNIV-finite-1 : UNIV = set [finite-1 .a1] by(auto intro: finite-1 .exhaust) lemma UNIV-finite-2 : UNIV = set [finite-2 .a1, finite-2 .a2] by(auto intro: finite-2 .exhaust)

541 lemma UNIV-finite-3 : UNIV = set [finite-3 .a1, finite-3 .a2, finite-3 .a3] by(auto intro: finite-3 .exhaust) lemma UNIV-finite-4 : UNIV = set [finite-4 .a1, finite-4 .a2, finite-4 .a3, finite-4 .a4] by(auto intro: finite-4 .exhaust) lemma UNIV-finite-5 : UNIV = set [finite-5 .a1, finite-5 .a2, finite-5 .a3, finite-5 .a4, finite-5 .a5] by(auto intro: finite-5 .exhaust) instantiation Enum.finite-1 :: card-UNIV begin definition finite-UNIV = Phantom(Enum.finite-1 ) True definition card-UNIV = Phantom(Enum.finite-1 ) 1 instance by intro-classes (simp-all add: UNIV-finite-1 card-UNIV-finite-1-def finite-UNIV-finite-1-def ) end instantiation Enum.finite-2 :: card-UNIV begin definition finite-UNIV = Phantom(Enum.finite-2 ) True definition card-UNIV = Phantom(Enum.finite-2 ) 2 instance by intro-classes (simp-all add: UNIV-finite-2 card-UNIV-finite-2-def finite-UNIV-finite-2-def ) end instantiation Enum.finite-3 :: card-UNIV begin definition finite-UNIV = Phantom(Enum.finite-3 ) True definition card-UNIV = Phantom(Enum.finite-3 ) 3 instance by intro-classes (simp-all add: UNIV-finite-3 card-UNIV-finite-3-def finite-UNIV-finite-3-def ) end instantiation Enum.finite-4 :: card-UNIV begin definition finite-UNIV = Phantom(Enum.finite-4 ) True definition card-UNIV = Phantom(Enum.finite-4 ) 4 instance by intro-classes (simp-all add: UNIV-finite-4 card-UNIV-finite-4-def finite-UNIV-finite-4-def ) end instantiation Enum.finite-5 :: card-UNIV begin definition finite-UNIV = Phantom(Enum.finite-5 ) True definition card-UNIV = Phantom(Enum.finite-5 ) 5 instance by intro-classes (simp-all add: UNIV-finite-5 card-UNIV-finite-5-def finite-UNIV-finite-5-def ) end

542 72.7 Code setup for sets

Implement CARD( 0a) via card-UNIV-class.card-UNIV and provide imple- mentations for finite, card, op ⊆, and op =if the calling context already provides finite-UNIV and card-UNIV instances. If we implemented the lat- ter always via card-UNIV-class.card-UNIV, we would require instances of essentially all element types, i.e., a lot of instantiation proofs and – at run time – possibly slow dictionary constructions. context begin qualified definition card-UNIV 0 :: 0a card-UNIV where [code del]: card-UNIV 0 = Phantom( 0a) CARD( 0a) lemma CARD-code [code-unfold]: CARD( 0a) = of-phantom (card-UNIV 0 :: 0a card-UNIV ) by(simp add: card-UNIV 0-def ) lemma card-UNIV 0-code [code]: card-UNIV 0 = card-UNIV by(simp add: card-UNIV card-UNIV 0-def ) end lemma card-Compl: finite A =⇒ card (− A) = card (UNIV :: 0a set) − card (A :: 0a set) by (metis Compl-eq-Diff-UNIV card-Diff-subset top-greatest) context fixes xs :: 0a :: finite-UNIV list begin qualified definition finite 0 :: 0a set ⇒ bool where [simp, code del, code-abbrev]: finite 0 = finite lemma finite 0-code [code]: finite 0 (set xs) ←→ True finite 0 (List.coset xs) ←→ of-phantom (finite-UNIV :: 0a finite-UNIV ) by(simp-all add: card-gt-0-iff finite-UNIV ) end context fixes xs :: 0a :: card-UNIV list begin qualified definition card 0 :: 0a set ⇒ nat where [simp, code del, code-abbrev]: card 0 = card lemma card 0-code [code]:

543 card 0 (set xs) = length (remdups xs) card 0 (List.coset xs) = of-phantom (card-UNIV :: 0a card-UNIV ) − length (remdups xs) by(simp-all add: List.card-set card-Compl card-UNIV ) qualified definition subset 0 :: 0a set ⇒ 0a set ⇒ bool where [simp, code del, code-abbrev]: subset 0 = op ⊆ lemma subset 0-code [code]: subset 0 A (List.coset ys) ←→ (∀ y ∈ set ys. y ∈/ A) subset 0 (set ys) B ←→ (∀ y ∈ set ys. y ∈ B) subset 0 (List.coset xs)(set ys) ←→ (let n = CARD( 0a) in n > 0 ∧ card(set (xs @ ys)) = n) by(auto simp add: Let-def card-gt-0-iff dest: card-eq-UNIV-imp-eq-UNIV intro: arg-cong[where f =card]) (metis finite-compl finite-set rev-finite-subset) qualified definition eq-set :: 0a set ⇒ 0a set ⇒ bool where [simp, code del, code-abbrev]: eq-set = op = lemma eq-set-code [code]: fixes ys defines rhs ≡ let n = CARD( 0a) in if n = 0 then False else let xs 0 = remdups xs; ys 0 = remdups ys in length xs 0 + length ys 0 = n ∧ (∀ x ∈ set xs 0. x ∈/ set ys 0) ∧ (∀ y ∈ set ys 0. y ∈/ set xs 0) shows eq-set (List.coset xs)(set ys) ←→ rhs and eq-set (set ys)(List.coset xs) ←→ rhs and eq-set (set xs)(set ys) ←→ (∀ x ∈ set xs. x ∈ set ys) ∧ (∀ y ∈ set ys. y ∈ set xs) and eq-set (List.coset xs)(List.coset ys) ←→ (∀ x ∈ set xs. x ∈ set ys) ∧ (∀ y ∈ set ys. y ∈ set xs) proof goal-cases { case 1 show ?case (is ?lhs ←→ ?rhs) proof show ?rhs if ?lhs using that by (auto simp add: rhs-def Let-def List.card-set[symmetric] card-Un-Int[where A=set xs and B=− set xs] card-UNIV Compl-partition card-gt-0-iff dest: sym)(metis finite-compl finite-set) show ?lhs if ?rhs proof − have [[ ∀ y∈set xs. y ∈/ set ys; ∀ x∈set ys. x ∈/ set xs ]] =⇒ set xs ∩ set ys = {} by blast

544 with that show ?thesis by (auto simp add: rhs-def Let-def List.card-set[symmetric] card-UNIV card-gt-0-iff card-Un-Int[where A=set xs and B=set ys] dest: card-eq-UNIV-imp-eq-UNIV split: if-split-asm) qed qed } moreover case 2 ultimately show ?case unfolding eq-set-def by blast next case 3 show ?case unfolding eq-set-def List.coset-def by blast next case 4 show ?case unfolding eq-set-def List.coset-def by blast qed end

Provide more informative exceptions than Match for non-rewritten cases. If generated code raises one these exceptions, then a code equation calls the mentioned operator for an element type that is not an instance of card-UNIV and is therefore not implemented via card-UNIV-class.card-UNIV. Con- strain the element type with sort card-UNIV to change this. lemma card-coset-error [code]: card (List.coset xs) = Code.abort (STR 00card (List.coset -) requires type class instance card-UNIV 00) (λ-. card (List.coset xs)) by(simp) lemma coset-subseteq-set-code [code]: List.coset xs ⊆ set ys ←→ (if xs = [] ∧ ys = [] then False else Code.abort (STR 00subset-eq (List.coset -)(List.set -) requires type class instance card-UNIV 00) (λ-. List.coset xs ⊆ set ys)) by simp notepad begin — test code setup have List.coset [True] = set [False] ∧ List.coset [] ⊆ List.set [True, False] ∧ finite (List.coset [True]) by eval end end

545 73 Almost everywhere constant functions theory FinFun imports Cardinality begin This theory defines functions which are constant except for finitely many points (FinFun) and introduces a type finfin along with a number of opera- tors for them. The code generator is set up such that such functions can be represented as data in the generated code and all operators are executable. For details, see Formalising FinFuns - Generating Code for Functions as Data by A. Lochbihler in TPHOLs 2009.

73.1 The map-default operation definition map-default :: 0b ⇒ ( 0a * 0b) ⇒ 0a ⇒ 0b where map-default b f a ≡ case f a of None ⇒ b | Some b 0 ⇒ b 0 lemma map-default-delete [simp]: map-default b (f (a := None)) = (map-default b f )(a := b) by(simp add: map-default-def fun-eq-iff ) lemma map-default-insert: map-default b (f (a 7→ b 0)) = (map-default b f )(a := b 0) by(simp add: map-default-def fun-eq-iff ) lemma map-default-empty [simp]: map-default b empty = (λa. b) by(simp add: fun-eq-iff map-default-def ) lemma map-default-inject: fixes g g 0 :: 0a * 0b assumes infin-eq: ¬ finite (UNIV :: 0a set) ∨ b = b 0 and fin: finite (dom g) and b: b ∈/ ran g and fin 0: finite (dom g 0) and b 0: b 0 ∈/ ran g 0 and eq 0: map-default b g = map-default b 0 g 0 shows b = b 0 g = g 0 proof − from infin-eq show bb 0: b = b 0 proof assume infin: ¬ finite (UNIV :: 0a set) from fin fin 0 have finite (dom g ∪ dom g 0) by auto with infin have UNIV − (dom g ∪ dom g 0) 6= {} by(auto dest: finite-subset) then obtain a where a: a ∈/ dom g ∪ dom g 0 by auto hence map-default b g a = b map-default b 0 g 0 a = b 0 by(auto simp add: map-default-def ) with eq 0 show b = b 0 by simp qed

show g = g 0

546 proof fix x show g x = g 0 x proof(cases g x) case None hence map-default b g x = b by(simp add: map-default-def ) with bb 0 eq 0 have map-default b 0 g 0 x = b 0 by simp with b 0 have g 0 x = None by(simp add: map-default-def ran-def split: option.split-asm) with None show ?thesis by simp next case (Some c) with b have cb: c 6= b by(auto simp add: ran-def ) moreover from Some have map-default b g x = c by(simp add: map-default-def ) with eq 0 have map-default b 0 g 0 x = c by simp ultimately have g 0 x = Some c using b 0 bb 0 by(auto simp add: map-default-def split: option.splits) with Some show ?thesis by simp qed qed qed

73.2 The finfun type definition finfun = {f :: 0a⇒ 0b. ∃ b. finite {a. f a 6= b}} typedef ( 0a, 0b) finfun ((- ⇒f /-)[22 , 21 ] 21 ) = finfun :: ( 0a => 0b) set morphisms finfun-apply Abs-finfun proof − have ∃ f . finite {x. f x 6= undefined} proof show finite {x. (λy. undefined) x 6= undefined} by auto qed then show ?thesis unfolding finfun-def by auto qed type-notation finfun ((- ⇒f /-)[22 , 21 ] 21 ) setup-lifting type-definition-finfun lemma fun-upd-finfun: y(a := b) ∈ finfun ←→ y ∈ finfun proof − { fix b 0 have finite {a 0. (y(a := b)) a 0 6= b 0} = finite {a 0. y a 0 6= b 0} proof(cases b = b 0) case True hence {a 0. (y(a := b)) a 0 6= b 0} = {a 0. y a 0 6= b 0} − {a} by auto thus ?thesis by simp next

547 case False hence {a 0. (y(a := b)) a 0 6= b 0} = insert a {a 0. y a 0 6= b 0} by auto thus ?thesis by simp qed } thus ?thesis unfolding finfun-def by blast qed lemma const-finfun:(λx. a) ∈ finfun by(auto simp add: finfun-def ) lemma finfun-left-compose: assumes y ∈ finfun shows g ◦ y ∈ finfun proof − from assms obtain b where finite {a. y a 6= b} unfolding finfun-def by blast hence finite {c. g (y c) 6= g b} proof(induct {a. y a 6= b} arbitrary: y) case empty hence y = (λa. b) by(auto) thus ?case by(simp) next case (insert x F ) note IH = hVy. F = {a. y a 6= b} =⇒ finite {c. g (y c) 6= g b}i from hinsert x F = {a. y a 6= b}i hx ∈/ F i have F : F = {a. (y(x := b)) a 6= b} by(auto) show ?case proof(cases g (y x) = g b) case True hence {c. g ((y(x := b)) c) 6= g b} = {c. g (y c) 6= g b} by auto with IH [OF F ] show ?thesis by simp next case False hence {c. g (y c) 6= g b} = insert x {c. g ((y(x := b)) c) 6= g b} by auto with IH [OF F ] show ?thesis by(simp) qed qed thus ?thesis unfolding finfun-def by auto qed lemma assumes y ∈ finfun shows fst-finfun: fst ◦ y ∈ finfun and snd-finfun: snd ◦ y ∈ finfun proof − from assms obtain b c where bc: finite {a. y a 6= (b, c)} unfolding finfun-def by auto have {a. fst (y a) 6= b} ⊆ {a. y a 6= (b, c)} and {a. snd (y a) 6= c} ⊆ {a. y a 6= (b, c)} by auto hence finite {a. fst (y a) 6= b}

548 and finite {a. snd (y a) 6= c} using bc by(auto intro: finite-subset) thus fst ◦ y ∈ finfun snd ◦ y ∈ finfun unfolding finfun-def by auto qed lemma map-of-finfun: map-of xs ∈ finfun unfolding finfun-def by(induct xs)(auto simp add: Collect-neg-eq Collect-conj-eq Collect-imp-eq intro: finite-subset) lemma Diag-finfun:(λx. (f x, g x)) ∈ finfun ←→ f ∈ finfun ∧ g ∈ finfun by(auto intro: finite-subset simp add: Collect-neg-eq Collect-imp-eq Collect-conj-eq finfun-def ) lemma finfun-right-compose: assumes g: g ∈ finfun and inj : inj f shows g o f ∈ finfun proof − from g obtain b where b: finite {a. g a 6= b} unfolding finfun-def by blast moreover have f ‘ {a. g (f a) 6= b} ⊆ {a. g a 6= b} by auto moreover from inj have inj-on f {a. g (f a) 6= b} by(rule subset-inj-on) blast ultimately have finite {a. g (f a) 6= b} by(blast intro: finite-imageD[where f =f ] finite-subset) thus ?thesis unfolding finfun-def by auto qed lemma finfun-curry: assumes fin: f ∈ finfun shows curry f ∈ finfun curry f a ∈ finfun proof − from fin obtain c where c: finite {ab. f ab 6= c} unfolding finfun-def by blast moreover have {a. ∃ b. f (a, b) 6= c} = fst ‘ {ab. f ab 6= c} by(force) hence {a. curry f a 6= (λb. c)} = fst ‘ {ab. f ab 6= c} by(auto simp add: curry-def fun-eq-iff ) ultimately have finite {a. curry f a 6= (λb. c)} by simp thus curry f ∈ finfun unfolding finfun-def by blast

have snd ‘ {ab. f ab 6= c} = {b. ∃ a. f (a, b) 6= c} by(force) hence {b. f (a, b) 6= c} ⊆ snd ‘ {ab. f ab 6= c} by auto hence finite {b. f (a, b) 6= c} by(rule finite-subset)(rule finite-imageI [OF c]) thus curry f a ∈ finfun unfolding finfun-def by auto qed bundle finfun begin lemmas [simp] = fst-finfun snd-finfun Abs-finfun-inverse finfun-apply-inverse Abs-finfun-inject finfun-apply-inject

549 Diag-finfun finfun-curry lemmas [iff ] = const-finfun fun-upd-finfun finfun-apply map-of-finfun lemmas [intro] = finfun-left-compose fst-finfun snd-finfun end lemma Abs-finfun-inject-finite: fixes x y :: 0a ⇒ 0b assumes fin: finite (UNIV :: 0a set) shows Abs-finfun x = Abs-finfun y ←→ x = y proof assume Abs-finfun x = Abs-finfun y moreover have x ∈ finfun y ∈ finfun unfolding finfun-def by(auto intro: finite-subset[OF - fin]) ultimately show x = y by(simp add: Abs-finfun-inject) qed simp lemma Abs-finfun-inject-finite-class: fixes x y :: ( 0a :: finite) ⇒ 0b shows Abs-finfun x = Abs-finfun y ←→ x = y using finite-UNIV by(simp add: Abs-finfun-inject-finite) lemma Abs-finfun-inj-finite: assumes fin: finite (UNIV :: 0a set) shows inj (Abs-finfun :: ( 0a ⇒ 0b) ⇒ 0a ⇒f 0b) proof(rule inj-onI ) fix x y :: 0a ⇒ 0b assume Abs-finfun x = Abs-finfun y moreover have x ∈ finfun y ∈ finfun unfolding finfun-def by(auto intro: finite-subset[OF - fin]) ultimately show x = y by(simp add: Abs-finfun-inject) qed lemma Abs-finfun-inverse-finite: fixes x :: 0a ⇒ 0b assumes fin: finite (UNIV :: 0a set) shows finfun-apply (Abs-finfun x) = x including finfun proof − from fin have x ∈ finfun by(auto simp add: finfun-def intro: finite-subset) thus ?thesis by simp qed lemma Abs-finfun-inverse-finite-class: fixes x :: ( 0a :: finite) ⇒ 0b

550 shows finfun-apply (Abs-finfun x) = x using finite-UNIV by(simp add: Abs-finfun-inverse-finite) lemma finfun-eq-finite-UNIV : finite (UNIV :: 0a set) =⇒ (finfun :: ( 0a ⇒ 0b) set) = UNIV unfolding finfun-def by(auto intro: finite-subset) lemma finfun-finite-UNIV-class: finfun = (UNIV :: ( 0a :: finite ⇒ 0b) set) by(simp add: finfun-eq-finite-UNIV ) lemma map-default-in-finfun: assumes fin: finite (dom f ) shows map-default b f ∈ finfun unfolding finfun-def proof(intro CollectI exI ) from fin show finite {a. map-default b f a 6= b} by(auto simp add: map-default-def dom-def Collect-conj-eq split: option.splits) qed lemma finfun-cases-map-default: obtains b g where f = Abs-finfun (map-default b g) finite (dom g) b ∈/ ran g proof − obtain y where f : f = Abs-finfun y and y: y ∈ finfun by(cases f ) from y obtain b where b: finite {a. y a 6= b} unfolding finfun-def by auto let ?g = (λa. if y a = b then None else Some (y a)) have map-default b ?g = y by(simp add: fun-eq-iff map-default-def ) with f have f = Abs-finfun (map-default b ?g) by simp moreover from b have finite (dom ?g) by(auto simp add: dom-def ) moreover have b ∈/ ran ?g by(auto simp add: ran-def ) ultimately show ?thesis by(rule that) qed

73.3 Kernel functions for type 0a ⇒f 0b lift-definition finfun-const :: 0b ⇒ 0a ⇒f 0b (K $/ - [0 ] 1 ) is λ b x. b by (rule const-finfun) lift-definition finfun-update :: 0a ⇒f 0b ⇒ 0a ⇒ 0b ⇒ 0a ⇒f 0b (- 0(- $:= - 0) [1000 ,0 ,0 ] 1000 ) is fun-upd by (simp add: fun-upd-finfun) lemma finfun-update-twist: a 6= a 0 =⇒ f (a $:= b)(a 0 $:= b 0) = f (a 0 $:= b 0)(a $:= b) by transfer (simp add: fun-upd-twist) lemma finfun-update-twice [simp]: f (a $:= b)(a $:= b 0) = f (a $:= b 0) by transfer simp

551 lemma finfun-update-const-same:(K $ b)(a $:= b) = (K $ b) by transfer (simp add: fun-eq-iff )

73.4 Code generator setup definition finfun-update-code :: 0a ⇒f 0b ⇒ 0a ⇒ 0b ⇒ 0a ⇒f 0b where [simp, code del]: finfun-update-code = finfun-update code-datatype finfun-const finfun-update-code lemma finfun-update-const-code [code]: (K $ b)(a $:= b 0) = (if b = b 0 then (K $ b) else finfun-update-code (K $ b) a b 0) by(simp add: finfun-update-const-same) lemma finfun-update-update-code [code]: (finfun-update-code f a b)(a 0 $:= b 0) = (if a = a 0 then f (a $:= b 0) else finfun-update-code (f (a 0 $:= b 0)) a b) by(simp add: finfun-update-twist)

73.5 Setup for quickcheck quickcheck-generator finfun constructors: finfun-update-code, finfun-const :: 0b ⇒ 0a ⇒f 0b

73.6 finfun-update as instance of comp-fun-commute interpretation finfun-update: comp-fun-commute λa f . f (a :: 0a $:= b 0) including finfun proof fix a a 0 :: 0a show (λf . f (a $:= b 0)) ◦ (λf . f (a 0 $:= b 0)) = (λf . f (a 0 $:= b 0)) ◦ (λf . f (a $:= b 0)) proof fix b have (finfun-apply b)(a := b 0, a 0 := b 0) = (finfun-apply b)(a 0 := b 0, a := b 0) by(cases a = a 0)(auto simp add: fun-upd-twist) then have b(a $:= b 0)(a 0 $:= b 0) = b(a 0 $:= b 0)(a $:= b 0) by(auto simp add: finfun-update-def fun-upd-twist) then show ((λf . f (a $:= b 0)) ◦ (λf . f (a 0 $:= b 0))) b = ((λf . f (a 0 $:= b 0)) ◦ (λf . f (a $:= b 0))) b by (simp add: fun-eq-iff ) qed qed lemma fold-finfun-update-finite-univ: assumes fin: finite (UNIV :: 0a set) shows Finite-Set.fold (λa f . f (a $:= b 0)) (K $ b)(UNIV :: 0a set) = (K $ b 0) proof − { fix A :: 0a set from fin have finite A by(auto intro: finite-subset)

552 hence Finite-Set.fold (λa f . f (a $:= b 0)) (K $ b) A = Abs-finfun (λa. if a ∈ A then b 0 else b) proof(induct) case (insert x F ) have (λa. if a = x then b 0 else (if a ∈ F then b 0 else b)) = (λa. if a = x ∨ a ∈ F then b 0 else b) by(auto) with insert show ?case by(simp add: finfun-const-def fun-upd-def )(simp add: finfun-update-def Abs-finfun-inverse-finite[OF fin] fun-upd-def ) qed(simp add: finfun-const-def ) } thus ?thesis by(simp add: finfun-const-def ) qed

73.7 Default value for FinFuns definition finfun-default-aux :: ( 0a ⇒ 0b) ⇒ 0b where [code del]: finfun-default-aux f = (if finite (UNIV :: 0a set) then undefined else THE b. finite {a. f a 6= b}) lemma finfun-default-aux-infinite: fixes f :: 0a ⇒ 0b assumes infin: ¬ finite (UNIV :: 0a set) and fin: finite {a. f a 6= b} shows finfun-default-aux f = b proof − let ?B = {a. f a 6= b} from fin have (THE b. finite {a. f a 6= b}) = b proof(rule the-equality) fix b 0 assume finite {a. f a 6= b 0} (is finite ?B 0) with infin fin have UNIV − (?B 0 ∪ ?B) 6= {} by(auto dest: finite-subset) then obtain a where a: a ∈/ ?B 0 ∪ ?B by auto thus b 0 = b by auto qed thus ?thesis using infin by(simp add: finfun-default-aux-def ) qed lemma finite-finfun-default-aux: fixes f :: 0a ⇒ 0b assumes fin: f ∈ finfun shows finite {a. f a 6= finfun-default-aux f } proof(cases finite (UNIV :: 0a set)) case True thus ?thesis using fin by(auto simp add: finfun-def finfun-default-aux-def intro: finite-subset) next case False from fin obtain b where b: finite {a. f a 6= b} (is finite ?B)

553 unfolding finfun-def by blast with False show ?thesis by(simp add: finfun-default-aux-infinite) qed lemma finfun-default-aux-update-const: fixes f :: 0a ⇒ 0b assumes fin: f ∈ finfun shows finfun-default-aux (f (a := b)) = finfun-default-aux f proof(cases finite (UNIV :: 0a set)) case False from fin obtain b 0 where b 0: finite {a. f a 6= b 0} unfolding finfun-def by blast hence finite {a 0. (f (a := b)) a 0 6= b 0} proof(cases b = b 0 ∧ f a 6= b 0) case True hence {a. f a 6= b 0} = insert a {a 0. (f (a := b)) a 0 6= b 0} by auto thus ?thesis using b 0 by simp next case False moreover { assume b 6= b 0 hence {a 0. (f (a := b)) a 0 6= b 0} = insert a {a. f a 6= b 0} by auto hence ?thesis using b 0 by simp } moreover { assume b = b 0 f a = b 0 hence {a 0. (f (a := b)) a 0 6= b 0} = {a. f a 6= b 0} by auto hence ?thesis using b 0 by simp } ultimately show ?thesis by blast qed with False b 0 show ?thesis by(auto simp del: fun-upd-apply simp add: finfun-default-aux-infinite) next case True thus ?thesis by(simp add: finfun-default-aux-def ) qed lift-definition finfun-default :: 0a ⇒f 0b ⇒ 0b is finfun-default-aux . lemma finite-finfun-default: finite {a. finfun-apply f a 6= finfun-default f } by transfer (erule finite-finfun-default-aux) lemma finfun-default-const: finfun-default ((K $ b) :: 0a ⇒f 0b) = (if finite (UNIV :: 0a set) then undefined else b) by(transfer)(auto simp add: finfun-default-aux-infinite finfun-default-aux-def ) lemma finfun-default-update-const: finfun-default (f (a $:= b)) = finfun-default f by transfer (simp add: finfun-default-aux-update-const) lemma finfun-default-const-code [code]: finfun-default ((K $ c) :: 0a :: card-UNIV ⇒f 0b) = (if CARD( 0a) = 0 then c else

554 undefined) by(simp add: finfun-default-const) lemma finfun-default-update-code [code]: finfun-default (finfun-update-code f a b) = finfun-default f by(simp add: finfun-default-update-const)

73.8 Recursion combinator and well-formedness conditions definition finfun-rec :: ( 0b ⇒ 0c) ⇒ ( 0a ⇒ 0b ⇒ 0c ⇒ 0c) ⇒ ( 0a ⇒f 0b) ⇒ 0c where [code del]: finfun-rec cnst upd f ≡ let b = finfun-default f ; g = THE g. f = Abs-finfun (map-default b g) ∧ finite (dom g) ∧ b ∈/ ran g in Finite-Set.fold (λa. upd a (map-default b g a)) (cnst b)(dom g) locale finfun-rec-wf-aux = fixes cnst :: 0b ⇒ 0c and upd :: 0a ⇒ 0b ⇒ 0c ⇒ 0c assumes upd-const-same: upd a b (cnst b) = cnst b and upd-commute: a 6= a 0 =⇒ upd a b (upd a 0 b 0 c) = upd a 0 b 0 (upd a b c) and upd-idemp: b 6= b 0 =⇒ upd a b 00 (upd a b 0 (cnst b)) = upd a b 00 (cnst b) begin lemma upd-left-comm: comp-fun-commute (λa. upd a (f a)) by(unfold-locales)(auto intro: upd-commute simp add: fun-eq-iff ) lemma upd-upd-twice: upd a b 00 (upd a b 0 (cnst b)) = upd a b 00 (cnst b) by(cases b 6= b 0)(auto simp add: fun-upd-def upd-const-same upd-idemp) lemma map-default-update-const: assumes fin: finite (dom f ) and anf : a ∈/ dom f and fg: f ⊆m g shows upd a d (Finite-Set.fold (λa. upd a (map-default d g a)) (cnst d)(dom f )) = Finite-Set.fold (λa. upd a (map-default d g a)) (cnst d)(dom f ) proof − let ?upd = λa. upd a (map-default d g a) let ?fr = λA. Finite-Set.fold ?upd (cnst d) A interpret gwf : comp-fun-commute ?upd by(rule upd-left-comm)

from fin anf fg show ?thesis proof(induct dom f arbitrary: f ) case empty from h{} = dom f i have f = empty by(auto simp add: dom-def ) thus ?case by(simp add: finfun-const-def upd-const-same) next

555 case (insert a 0 A) V note IH = h f . [[ A = dom f ; a ∈/ dom f ; f ⊆m g ]] =⇒ upd a d (?fr (dom f )) = ?fr (dom f )i 0 0 note fin = hfinite Ai note anf = ha ∈/ dom f i note a nA = ha ∈/ Ai 0 note domf = hinsert a A = dom f i note fg = hf ⊆m g i

from domf obtain b where b: f a 0 = Some b by auto let ?f 0 = f (a 0 := None) have upd a d (?fr (insert a 0 A)) = upd a d (upd a 0 (map-default d g a 0)(?fr A)) by(subst gwf .fold-insert[OF fin a 0nA]) rule also from b fg have g a 0 = f a 0 by(auto simp add: map-le-def intro: domI dest: bspec) hence ga 0: map-default d g a 0 = map-default d f a 0 by(simp add: map-default-def ) also from anf domf have a 6= a 0 by auto note upd-commute[OF this] 0 0 0 0 also from domf a nA anf fg have a ∈/ dom ?f ?f ⊆m g and A: A = dom ?f by(auto simp add: ran-def map-le-def ) 0 0 note A also note IH [OF A ha ∈/ dom ?f i h?f ⊆m g i] also have upd a 0 (map-default d f a 0)(?fr (dom (f (a 0 := None)))) = ?fr (dom f ) unfolding domf [symmetric] gwf .fold-insert[OF fin a 0nA] ga 0 unfolding A .. also have insert a 0 (dom ?f 0) = dom f using domf by auto finally show ?case . qed qed lemma map-default-update-twice: assumes fin: finite (dom f ) and anf : a ∈/ dom f and fg: f ⊆m g shows upd a d 00 (upd a d 0 (Finite-Set.fold (λa. upd a (map-default d g a)) (cnst d)(dom f ))) = upd a d 00 (Finite-Set.fold (λa. upd a (map-default d g a)) (cnst d)(dom f )) proof − let ?upd = λa. upd a (map-default d g a) let ?fr = λA. Finite-Set.fold ?upd (cnst d) A interpret gwf : comp-fun-commute ?upd by(rule upd-left-comm)

from fin anf fg show ?thesis proof(induct dom f arbitrary: f ) case empty from h{} = dom f i have f = empty by(auto simp add: dom-def ) thus ?case by(auto simp add: finfun-const-def finfun-update-def upd-upd-twice) next case (insert a 0 A) V 00 0 note IH = h f . [[A = dom f ; a ∈/ dom f ; f ⊆m g]] =⇒ upd a d (upd a d (?fr 00 (dom f ))) = upd a d (?fr (dom f ))i 0 0 note fin = hfinite Ai note anf = ha ∈/ dom f i note a nA = ha ∈/ Ai 0 note domf = hinsert a A = dom f i note fg = hf ⊆m g i

556 from domf obtain b where b: f a 0 = Some b by auto let ?f 0 = f (a 0 := None) let ?b 0 = case f a 0 of None ⇒ d | Some b ⇒ b from domf have upd a d 00 (upd a d 0 (?fr (dom f ))) = upd a d 00 (upd a d 0 (?fr (insert a 0 A))) by simp also note gwf .fold-insert[OF fin a 0nA] also from b fg have g a 0 = f a 0 by(auto simp add: map-le-def intro: domI dest: bspec) hence ga 0: map-default d g a 0 = map-default d f a 0 by(simp add: map-default-def ) also from anf domf have ana 0: a 6= a 0 by auto note upd-commute[OF this] also note upd-commute[OF ana 0] 0 0 0 0 also from domf a nA anf fg have a ∈/ dom ?f ?f ⊆m g and A: A = dom ?f by(auto simp add: ran-def map-le-def ) 0 0 note A also note IH [OF A ha ∈/ dom ?f i h?f ⊆m g i] also note upd-commute[OF ana 0[symmetric]] also note ga 0[symmetric] also note A[symmetric] also note gwf .fold-insert[symmetric, OF fin a 0nA] also note domf finally show ?case . qed qed lemma map-default-eq-id [simp]: map-default d ((λa. Some (f a)) |‘ {a. f a 6= d}) = f by(auto simp add: map-default-def restrict-map-def ) lemma finite-rec-cong1 : assumes f : comp-fun-commute f and g: comp-fun-commute g and fin: finite A and eq: Va. a ∈ A =⇒ f a = g a shows Finite-Set.fold f z A = Finite-Set.fold g z A proof − interpret f : comp-fun-commute f by(rule f ) interpret g: comp-fun-commute g by(rule g) { fix B assume BsubA: B ⊆ A with fin have finite B by(blast intro: finite-subset) hence B ⊆ A =⇒ Finite-Set.fold f z B = Finite-Set.fold g z B proof(induct) case empty thus ?case by simp next case (insert a B) note finB = hfinite B i note anB = ha ∈/ B i note sub = hinsert a B ⊆ Ai note IH = hB ⊆ A =⇒ Finite-Set.fold f z B = Finite-Set.fold g z B i from sub anB have BpsubA: B ⊂ A and BsubA: B ⊆ A and aA: a ∈ A by auto from IH [OF BsubA] eq[OF aA] finB anB show ?case by(auto) qed

557 with BsubA have Finite-Set.fold f z B = Finite-Set.fold g z B by blast } thus ?thesis by blast qed lemma finfun-rec-upd [simp]: finfun-rec cnst upd (f (a 0 $:= b 0)) = upd a 0 b 0 (finfun-rec cnst upd f ) including finfun proof − obtain b where b: b = finfun-default f by auto let ?the = λf g. f = Abs-finfun (map-default b g) ∧ finite (dom g) ∧ b ∈/ ran g obtain g where g: g = The (?the f ) by blast obtain y where f : f = Abs-finfun y and y: y ∈ finfun by (cases f ) from f y b have bfin: finite {a. y a 6= b} by(simp add: finfun-default-def finite-finfun-default-aux)

let ?g = (λa. Some (y a)) |‘ {a. y a 6= b} from bfin have fing: finite (dom ?g) by auto have bran: b ∈/ ran ?g by(auto simp add: ran-def restrict-map-def ) have yg: y = map-default b ?g by simp have gg: g = ?g unfolding g proof(rule the-equality) from f y bfin show ?the f ?g by(auto)(simp add: restrict-map-def ran-def split: if-split-asm) next fix g 0 assume ?the f g 0 hence fin 0: finite (dom g 0) and ran 0: b ∈/ ran g 0 and eq: Abs-finfun (map-default b ?g) = Abs-finfun (map-default b g 0) using f yg by auto from fin 0 fing have map-default b ?g ∈ finfun map-default b g 0 ∈ finfun by(blast intro: map-default-in-finfun)+ with eq have map-default b ?g = map-default b g 0 by simp with fing bran fin 0 ran 0 show g 0 = ?g by(rule map-default-inject[OF disjI2 [OF refl], THEN sym]) qed

show ?thesis proof(cases b 0 = b) case True note b 0b = True

let ?g 0 = (λa. Some ((y(a 0 := b)) a)) |‘ {a. (y(a 0 := b)) a 6= b} from bfin b 0b have fing 0: finite (dom ?g 0) by(auto simp add: Collect-conj-eq Collect-imp-eq intro: finite-subset) have brang 0: b ∈/ ran ?g 0 by(auto simp add: ran-def restrict-map-def )

let ?b 0 = λa. case ?g 0 a of None ⇒ b | Some b ⇒ b let ?b = map-default b ?g from upd-left-comm upd-left-comm fing 0

558 have Finite-Set.fold (λa. upd a (?b 0 a)) (cnst b)(dom ?g 0) = Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g 0) by(rule finite-rec-cong1 )(auto simp add: restrict-map-def b 0b b map-default-def ) also interpret gwf : comp-fun-commute λa. upd a (?b a) by(rule upd-left-comm) have Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g 0) = upd a 0 b 0 (Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g)) proof(cases y a 0 = b) case True with b 0b have g 0: ?g 0 = ?g by(auto simp add: restrict-map-def ) from True have a 0ndomg: a 0 ∈/ dom ?g by auto from f b 0b b show ?thesis unfolding g 0 by(subst map-default-update-const[OF fing a 0ndomg map-le-refl, symmetric]) simp next case False hence domg: dom ?g = insert a 0 (dom ?g 0) by auto from False b 0b have a 0ndomg 0: a 0 ∈/ dom ?g 0 by auto have Finite-Set.fold (λa. upd a (?b a)) (cnst b)(insert a 0 (dom ?g 0)) = upd a 0 (?b a 0)(Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g 0)) using fing 0 a 0ndomg 0 unfolding b 0b by(rule gwf .fold-insert) hence upd a 0 b (Finite-Set.fold (λa. upd a (?b a)) (cnst b)(insert a 0 (dom ?g 0))) = upd a 0 b (upd a 0 (?b a 0)(Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g 0))) by simp 0 0 0 also from b b have g leg: ?g ⊆m ?g by(auto simp add: restrict-map-def map-le-def ) note map-default-update-twice[OF fing 0 a 0ndomg 0 this, of b ?b a 0 b] also note map-default-update-const[OF fing 0 a 0ndomg 0 g 0leg, of b] finally show ?thesis unfolding b 0b domg[unfolded b 0b] by(rule sym) qed also have The (?the (f (a 0 $:= b 0))) = ?g 0 proof(rule the-equality) from f y b b 0b brang 0 fing 0 show ?the (f (a 0 $:= b 0)) ?g 0 by(auto simp del: fun-upd-apply simp add: finfun-update-def ) next fix g 0 assume ?the (f (a 0 $:= b 0)) g 0 hence fin 0: finite (dom g 0) and ran 0: b ∈/ ran g 0 and eq: f (a 0 $:= b 0) = Abs-finfun (map-default b g 0) by(auto simp del: fun-upd-apply) from fin 0 fing 0 have map-default b g 0 ∈ finfun map-default b ?g 0 ∈ finfun by(blast intro: map-default-in-finfun)+ with eq f b 0b b have map-default b ?g 0 = map-default b g 0 by(simp del: fun-upd-apply add: finfun-update-def ) with fing 0 brang 0 fin 0 ran 0 show g 0 = ?g 0 by(rule map-default-inject[OF disjI2 [OF refl], THEN sym]) qed ultimately show ?thesis unfolding finfun-rec-def Let-def b gg[unfolded g b] using bfin b 0b b

559 by(simp only: finfun-default-update-const map-default-def ) next case False note b 0b = this let ?g 0 = ?g(a 0 7→ b 0) let ?b 0 = map-default b ?g 0 let ?b = map-default b ?g from fing have fing 0: finite (dom ?g 0) by auto from bran b 0b have bnrang 0: b ∈/ ran ?g 0 by(auto simp add: ran-def ) have ffmg 0: map-default b ?g 0 = y(a 0 := b 0) by(auto simp add: map-default-def restrict-map-def ) with f y have f-Abs: f (a 0 $:= b 0) = Abs-finfun (map-default b ?g 0) by(auto simp add: finfun-update-def ) have g 0: The (?the (f (a 0 $:= b 0))) = ?g 0 proof (rule the-equality) from fing 0 bnrang 0 f-Abs show ?the (f (a 0 $:= b 0)) ?g 0 by(auto simp add: finfun-update-def restrict-map-def ) next fix g 0 assume ?the (f (a 0 $:= b 0)) g 0 hence f 0: f (a 0 $:= b 0) = Abs-finfun (map-default b g 0) and fin 0: finite (dom g 0) and brang 0: b ∈/ ran g 0 by auto from fing 0 fin 0 have map-default b ?g 0 ∈ finfun map-default b g 0 ∈ finfun by(auto intro: map-default-in-finfun) with f 0 f-Abs have map-default b g 0 = map-default b ?g 0 by simp with fin 0 brang 0 fing 0 bnrang 0 show g 0 = ?g 0 by(rule map-default-inject[OF disjI2 [OF refl]]) qed have dom: dom (((λa. Some (y a)) |‘ {a. y a 6= b})(a 0 7→ b 0)) = insert a 0 (dom ((λa. Some (y a)) |‘ {a. y a 6= b})) by auto show ?thesis proof(cases y a 0 = b) case True hence a 0ndomg: a 0 ∈/ dom ?g by auto from f y b 0b True have yff : y = map-default b (?g 0 |‘ dom ?g) by(auto simp add: restrict-map-def map-default-def intro!: ext) hence f 0: f = Abs-finfun (map-default b (?g 0 |‘ dom ?g)) using f by simp interpret g 0wf : comp-fun-commute λa. upd a (?b 0 a) by(rule upd-left-comm) from upd-left-comm upd-left-comm fing have Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g) = Finite-Set.fold (λa. upd a (?b 0 a)) (cnst b)(dom ?g) by(rule finite-rec-cong1 )(auto simp add: restrict-map-def b 0b True map-default-def ) thus ?thesis unfolding finfun-rec-def Let-def finfun-default-update-const b[symmetric] unfolding g 0 g[symmetric] gg g 0wf .fold-insert[OF fing a 0ndomg, of cnst b, folded dom] by −(rule arg-cong2 [where f =upd a 0], simp-all add: map-default-def ) next case False

560 hence insert a 0 (dom ?g) = dom ?g by auto moreover { let ?g 00 = ?g(a 0 := None) let ?b 00 = map-default b ?g 00 from False have domg: dom ?g = insert a 0 (dom ?g 00) by auto from False have a 0ndomg 00: a 0 ∈/ dom ?g 00 by auto have fing 00: finite (dom ?g 00) by(rule finite-subset[OF - fing]) auto have bnrang 00: b ∈/ ran ?g 00 by(auto simp add: ran-def restrict-map-def ) interpret gwf : comp-fun-commute λa. upd a (?b a) by(rule upd-left-comm) interpret g 0wf : comp-fun-commute λa. upd a (?b 0 a) by(rule upd-left-comm) have upd a 0 b 0 (Finite-Set.fold (λa. upd a (?b a)) (cnst b)(insert a 0 (dom ?g 00))) = upd a 0 b 0 (upd a 0 (?b a 0)(Finite-Set.fold (λa. upd a (?b a)) (cnst b) (dom ?g 00))) unfolding gwf .fold-insert[OF fing 00 a 0ndomg 00] f .. 00 00 also have g leg: ?g |‘ dom ?g ⊆m ?g by(auto simp add: map-le-def ) have dom (?g |‘ dom ?g 00) = dom ?g 00 by auto note map-default-update-twice[where d=b and f = ?g |‘ dom ?g 00 and a=a 0 and d 0=?b a 0 and d 00=b 0 and g=?g, unfolded this, OF fing 00 a 0ndomg 00 g 00leg] also have b 0: b 0 = ?b 0 a 0 by(auto simp add: map-default-def ) from upd-left-comm upd-left-comm fing 00 have Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g 00) = Finite-Set.fold (λa. upd a (?b 0 a)) (cnst b)(dom ?g 00) by(rule finite-rec-cong1 )(auto simp add: restrict-map-def b 0b map-default-def ) with b 0 have upd a 0 b 0 (Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g 00)) = upd a 0 (?b 0 a 0)(Finite-Set.fold (λa. upd a (?b 0 a)) (cnst b)(dom ?g 00)) by simp also note g 0wf .fold-insert[OF fing 00 a 0ndomg 00, symmetric] finally have upd a 0 b 0 (Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g)) = Finite-Set.fold (λa. upd a (?b 0 a)) (cnst b)(dom ?g) unfolding domg . } ultimately have Finite-Set.fold (λa. upd a (?b 0 a)) (cnst b)(insert a 0 (dom ?g)) = upd a 0 b 0 (Finite-Set.fold (λa. upd a (?b a)) (cnst b)(dom ?g)) by simp thus ?thesis unfolding finfun-rec-def Let-def finfun-default-update-const b[symmetric] g[symmetric] g 0 dom[symmetric] using b 0b gg by(simp add: map-default-insert) qed qed qed end locale finfun-rec-wf = finfun-rec-wf-aux + assumes const-update-all:

561 finite (UNIV :: 0a set) =⇒ Finite-Set.fold (λa. upd a b 0)(cnst b)(UNIV :: 0a set) = cnst b 0 begin lemma finfun-rec-const [simp]: finfun-rec cnst upd (K $ c) = cnst c including finfun proof(cases finite (UNIV :: 0a set)) case False hence finfun-default ((K $ c) :: 0a ⇒f 0b) = c by(simp add: finfun-default-const) moreover have (THE g :: 0a * 0b. (K $ c) = Abs-finfun (map-default c g) ∧ finite (dom g) ∧ c ∈/ ran g) = empty proof (rule the-equality) show (K $ c) = Abs-finfun (map-default c empty) ∧ finite (dom empty) ∧ c ∈/ ran empty by(auto simp add: finfun-const-def ) next fix g :: 0a * 0b assume (K $ c) = Abs-finfun (map-default c g) ∧ finite (dom g) ∧ c ∈/ ran g hence g:(K $ c) = Abs-finfun (map-default c g) and fin: finite (dom g) and ran: c ∈/ ran g by blast+ from g map-default-in-finfun[OF fin, of c] have map-default c g = (λa. c) by(simp add: finfun-const-def ) moreover have map-default c empty = (λa. c) by simp ultimately show g = empty by−(rule map-default-inject[OF disjI2 [OF refl] fin ran], auto) qed ultimately show ?thesis by(simp add: finfun-rec-def ) next case True hence default: finfun-default ((K $ c) :: 0a ⇒f 0b) = undefined by(simp add: finfun-default-const) let ?the = λg :: 0a * 0b. (K $ c) = Abs-finfun (map-default undefined g) ∧ finite (dom g) ∧ undefined ∈/ ran g show ?thesis proof(cases c = undefined) case True have the: The ?the = empty proof (rule the-equality) from True show ?the empty by(auto simp add: finfun-const-def ) next fix g 0 assume ?the g 0 hence fg:(K $ c) = Abs-finfun (map-default undefined g 0) and fin: finite (dom g 0) and g: undefined ∈/ ran g 0 by simp-all from fin have map-default undefined g 0 ∈ finfun by(rule map-default-in-finfun) with fg have map-default undefined g 0 = (λa. c) by(auto simp add: finfun-const-def intro: Abs-finfun-inject[THEN iffD1 , symmetric]) with True show g 0 = empty

562 by −(rule map-default-inject(2 )[OF - fin g], auto) qed show ?thesis unfolding finfun-rec-def using hfinite UNIV i True unfolding Let-def the default by(simp) next case False have the: The ?the = (λa :: 0a. Some c) proof (rule the-equality) from False True show ?the (λa :: 0a. Some c) by(auto simp add: map-default-def [abs-def ] finfun-const-def dom-def ran-def ) next fix g 0 :: 0a * 0b assume ?the g 0 hence fg:(K $ c) = Abs-finfun (map-default undefined g 0) and fin: finite (dom g 0) and g: undefined ∈/ ran g 0 by simp-all from fin have map-default undefined g 0 ∈ finfun by(rule map-default-in-finfun) with fg have map-default undefined g 0 = (λa. c) by(auto simp add: finfun-const-def intro: Abs-finfun-inject[THEN iffD1 ]) with True False show g 0 = (λa:: 0a. Some c) by − (rule map-default-inject(2 )[OF - fin g], auto simp add: dom-def ran-def map-default-def [abs-def ]) qed show ?thesis unfolding finfun-rec-def using True False unfolding Let-def the default by(simp add: dom-def map-default-def const-update-all) qed qed end

73.9 Weak induction rule and case analysis for FinFuns lemma finfun-weak-induct [consumes 0 , case-names const update]: assumes const: Vb. P (K $ b) and update: Vf a b. P f =⇒ P (f (a $:= b)) shows P x including finfun proof(induct x rule: Abs-finfun-induct) case (Abs-finfun y) then obtain b where finite {a. y a 6= b} unfolding finfun-def by blast thus ?case using hy ∈ finfun i proof(induct {a. y a 6= b} arbitrary: y rule: finite-induct) case empty hence Va. y a = b by blast hence y = (λa. b) by(auto) hence Abs-finfun y = finfun-const b unfolding finfun-const-def by simp thus ?case by(simp add: const) next case (insert a A) note IH = hVy. [[ A = {a. y a 6= b}; y ∈ finfun ]] =⇒ P (Abs-finfun y)i

563 note y = hy ∈ finfun i with hinsert a A = {a. y a 6= b}i ha ∈/ Ai have A = {a 0. (y(a := b)) a 0 6= b} y(a := b) ∈ finfun by auto from IH [OF this] have P (finfun-update (Abs-finfun (y(a := b))) a (y a)) by(rule update) thus ?case using y unfolding finfun-update-def by simp qed qed lemma finfun-exhaust-disj :(∃ b. x = finfun-const b) ∨ (∃ f a b. x = finfun-update f a b) by(induct x rule: finfun-weak-induct) blast+ lemma finfun-exhaust: obtains b where x = (K $ b) | f a b where x = f (a $:= b) by(atomize-elim)(rule finfun-exhaust-disj ) lemma finfun-rec-unique: fixes f :: 0a ⇒f 0b ⇒ 0c assumes c: Vc. f (K $ c) = cnst c and u: Vg a b. f (g(a $:= b)) = upd g a b (f g) and c 0: Vc. f 0 (K $ c) = cnst c and u 0: Vg a b. f 0 (g(a $:= b)) = upd g a b (f 0 g) shows f = f 0 proof fix g :: 0a ⇒f 0b show f g = f 0 g by(induct g rule: finfun-weak-induct)(auto simp add: c u c 0 u 0) qed

73.10 Function application notation finfun-apply (infixl $ 999 ) interpretation finfun-apply-aux: finfun-rec-wf-aux λb. b λa 0 b c. if (a = a 0) then b else c by(unfold-locales) auto interpretation finfun-apply: finfun-rec-wf λb. b λa 0 b c. if (a = a 0) then b else c proof(unfold-locales) fix b 0 b :: 0a assume fin: finite (UNIV :: 0b set) { fix A :: 0b set interpret comp-fun-commute λa 0. If (a = a 0) b 0 by(rule finfun-apply-aux.upd-left-comm) from fin have finite A by(auto intro: finite-subset) hence Finite-Set.fold (λa 0. If (a = a 0) b 0) b A = (if a ∈ A then b 0 else b) by induct auto } from this[of UNIV ] show Finite-Set.fold (λa 0. If (a = a 0) b 0) b UNIV = b 0 by

564 simp qed lemma finfun-apply-def : op $ = (λf a. finfun-rec (λb. b)(λa 0 b c. if (a = a 0) then b else c) f ) proof(rule finfun-rec-unique) fix c show op $ (K $ c) = (λa. c) by(simp add: finfun-const.rep-eq) next fix g a b show op $ g(a $:= b) = (λc. if c = a then b else g $ c) by(auto simp add: finfun-update-def fun-upd-finfun Abs-finfun-inverse finfun-apply) qed auto lemma finfun-upd-apply: f (a $:= b) $ a 0 = (if a = a 0 then b else f $ a 0) and finfun-upd-apply-code [code]: (finfun-update-code f a b) $ a 0 = (if a = a 0 then b else f $ a 0) by(simp-all add: finfun-apply-def ) lemma finfun-const-apply [simp, code]: (K $ b) $ a = b by(simp add: finfun-apply-def ) lemma finfun-upd-apply-same [simp]: f (a $:= b) $ a = b by(simp add: finfun-upd-apply) lemma finfun-upd-apply-other [simp]: a 6= a 0 =⇒ f (a $:= b) $ a 0 = f $ a 0 by(simp add: finfun-upd-apply) lemma finfun-ext:(Va. f $ a = g $ a) =⇒ f = g by(auto simp add: finfun-apply-inject[symmetric]) lemma expand-finfun-eq:(f = g) = (op $ f = op $ g) by(auto intro: finfun-ext) lemma finfun-upd-triv [simp]: f (x $:= f $ x) = f by(simp add: expand-finfun-eq fun-eq-iff finfun-upd-apply) lemma finfun-const-inject [simp]: (K $ b) = (K $ b 0) ≡ b = b 0 by(simp add: expand-finfun-eq fun-eq-iff ) lemma finfun-const-eq-update: ((K $ b) = f (a $:= b 0)) = (b = b 0 ∧ (∀ a 0. a 6= a 0 −→ f $ a 0 = b)) by(auto simp add: expand-finfun-eq fun-eq-iff finfun-upd-apply)

73.11 Function composition definition finfun-comp :: ( 0a ⇒ 0b) ⇒ 0c ⇒f 0a ⇒ 0c ⇒f 0b (infixr ◦$ 55 ) where [code del]: g ◦$ f = finfun-rec (λb. (K $ g b)) (λa b c. c(a $:= g b)) f

565 notation (ASCII ) finfun-comp (infixr o$ 55 ) interpretation finfun-comp-aux: finfun-rec-wf-aux (λb. (K $ g b)) (λa b c. c(a $:= g b)) by(unfold-locales)(auto simp add: finfun-upd-apply intro: finfun-ext) interpretation finfun-comp: finfun-rec-wf (λb. (K $ g b)) (λa b c. c(a $:= g b)) proof fix b 0 b :: 0a assume fin: finite (UNIV :: 0c set) { fix A :: 0c set from fin have finite A by(auto intro: finite-subset) hence Finite-Set.fold (λ(a :: 0c) c. c(a $:= g b 0)) (K $ g b) A = Abs-finfun (λa. if a ∈ A then g b 0 else g b) by induct (simp-all add: finfun-const-def , auto simp add: finfun-update-def Abs-finfun-inverse-finite fun-upd-def Abs-finfun-inject-finite fun-eq-iff fin) } from this[of UNIV ] show Finite-Set.fold (λ(a :: 0c) c. c(a $:= g b 0)) (K $ g b) UNIV = (K $ g b 0) by(simp add: finfun-const-def ) qed lemma finfun-comp-const [simp, code]: g ◦$ (K $ c) = (K $ g c) by(simp add: finfun-comp-def ) lemma finfun-comp-update [simp]: g ◦$ (f (a $:= b)) = (g ◦$ f )(a $:= g b) and finfun-comp-update-code [code]: g ◦$ (finfun-update-code f a b) = finfun-update-code (g ◦$ f ) a (g b) by(simp-all add: finfun-comp-def ) lemma finfun-comp-apply [simp]: op $ (g ◦$ f ) = g ◦ op $ f by(induct f rule: finfun-weak-induct)(auto simp add: finfun-upd-apply) lemma finfun-comp-comp-collapse [simp]: f ◦$ g ◦$ h = (f ◦ g) ◦$ h by(induct h rule: finfun-weak-induct) simp-all lemma finfun-comp-const1 [simp]: (λx. c) ◦$ f = (K $ c) by(induct f rule: finfun-weak-induct)(auto intro: finfun-ext simp add: finfun-upd-apply) lemma finfun-comp-id1 [simp]: (λx. x) ◦$ f = f id ◦$ f = f by(induct f rule: finfun-weak-induct) auto lemma finfun-comp-conv-comp: g ◦$ f = Abs-finfun (g ◦ op $ f ) including finfun proof − have (λf . g ◦$ f ) = (λf . Abs-finfun (g ◦ op $ f )) proof(rule finfun-rec-unique)

566 { fix c show Abs-finfun (g ◦ op $ (K $ c)) = (K $ g c) by(simp add: finfun-comp-def o-def )(simp add: finfun-const-def ) } { fix g 0 a b show Abs-finfun (g ◦ op $ g 0(a $:= b)) = (Abs-finfun (g ◦ op $ g 0))(a $:= g b) proof − obtain y where y: y ∈ finfun and g 0: g 0 = Abs-finfun y by(cases g 0) moreover from g 0 have (g ◦ op $ g 0) ∈ finfun by(simp add: finfun-left-compose) moreover have g ◦ y(a := b) = (g ◦ y)(a := g b) by(auto) ultimately show ?thesis by(simp add: finfun-comp-def finfun-update-def ) qed } qed auto thus ?thesis by(auto simp add: fun-eq-iff ) qed definition finfun-comp2 :: 0b ⇒f 0c ⇒ ( 0a ⇒ 0b) ⇒ 0a ⇒f 0c (infixr $◦ 55 ) where [code del]: g $◦ f = Abs-finfun (op $ g ◦ f ) notation (ASCII ) finfun-comp2 (infixr $o 55 ) lemma finfun-comp2-const [code, simp]: finfun-comp2 (K $ c) f = (K $ c) including finfun by(simp add: finfun-comp2-def finfun-const-def comp-def ) lemma finfun-comp2-update: assumes inj : inj f shows finfun-comp2 (g(b $:= c)) f = (if b ∈ range f then (finfun-comp2 g f )(inv f b $:= c) else finfun-comp2 g f ) including finfun proof(cases b ∈ range f ) case True from inj have Vx. (op $ g)(f x := c) ◦ f = (op $ g ◦ f )(x := c) by(auto intro!: ext dest: injD) with inj True show ?thesis by(auto simp add: finfun-comp2-def finfun-update-def finfun-right-compose) next case False hence (op $ g)(b := c) ◦ f = op $ g ◦ f by(auto simp add: fun-eq-iff ) with False show ?thesis by(auto simp add: finfun-comp2-def finfun-update-def ) qed

73.12 Universal quantification definition finfun-All-except :: 0a list ⇒ 0a ⇒f bool ⇒ bool where [code del]: finfun-All-except A P ≡ ∀ a. a ∈ set A ∨ P $ a lemma finfun-All-except-const: finfun-All-except A (K $ b) ←→ b ∨ set A = UNIV by(auto simp add: finfun-All-except-def )

567 lemma finfun-All-except-const-finfun-UNIV-code [code]: finfun-All-except A (K $ b) = (b ∨ is-list-UNIV A) by(simp add: finfun-All-except-const is-list-UNIV-iff ) lemma finfun-All-except-update: finfun-All-except A f (a $:= b) = ((a ∈ set A ∨ b) ∧ finfun-All-except (a # A) f ) by(fastforce simp add: finfun-All-except-def finfun-upd-apply) lemma finfun-All-except-update-code [code]: fixes a :: 0a :: card-UNIV shows finfun-All-except A (finfun-update-code f a b) = ((a ∈ set A ∨ b) ∧ finfun-All-except (a # A) f ) by(simp add: finfun-All-except-update) definition finfun-All :: 0a ⇒f bool ⇒ bool where finfun-All = finfun-All-except [] lemma finfun-All-const [simp]: finfun-All (K $ b) = b by(simp add: finfun-All-def finfun-All-except-def ) lemma finfun-All-update: finfun-All f (a $:= b) = (b ∧ finfun-All-except [a] f ) by(simp add: finfun-All-def finfun-All-except-update) lemma finfun-All-All: finfun-All P = All (op $ P) by(simp add: finfun-All-def finfun-All-except-def ) definition finfun-Ex :: 0a ⇒f bool ⇒ bool where finfun-Ex P = Not (finfun-All (Not ◦$ P)) lemma finfun-Ex-Ex: finfun-Ex P = Ex (op $ P) unfolding finfun-Ex-def finfun-All-All by simp lemma finfun-Ex-const [simp]: finfun-Ex (K $ b) = b by(simp add: finfun-Ex-def )

73.13 A diagonal operator for FinFuns definition finfun-Diag :: 0a ⇒f 0b ⇒ 0a ⇒f 0c ⇒ 0a ⇒f ( 0b × 0c) ((1 0($-,/ -$ 0)) [0 , 0 ] 1000 ) where [code del]: ($f , g$) = finfun-rec (λb. Pair b ◦$ g)(λa b c. c(a $:= (b, g $ a))) f interpretation finfun-Diag-aux: finfun-rec-wf-aux λb. Pair b ◦$ g λa b c. c(a $:= (b, g $ a)) by(unfold-locales)(simp-all add: expand-finfun-eq fun-eq-iff finfun-upd-apply) interpretation finfun-Diag: finfun-rec-wf λb. Pair b ◦$ g λa b c. c(a $:= (b, g $

568 a)) proof fix b 0 b :: 0a assume fin: finite (UNIV :: 0c set) { fix A :: 0c set interpret comp-fun-commute λa c. c(a $:= (b 0, g $ a)) by(rule finfun-Diag-aux.upd-left-comm) from fin have finite A by(auto intro: finite-subset) hence Finite-Set.fold (λa c. c(a $:= (b 0, g $ a))) (Pair b ◦$ g) A = Abs-finfun (λa. (if a ∈ A then b 0 else b, g $ a)) by(induct)(simp-all add: finfun-const-def finfun-comp-conv-comp o-def , auto simp add: finfun-update-def Abs-finfun-inverse-finite fun-upd-def Abs-finfun-inject-finite fun-eq-iff fin) } from this[of UNIV ] show Finite-Set.fold (λa c. c(a $:= (b 0, g $ a))) (Pair b ◦$ g) UNIV = Pair b 0 ◦$ g by(simp add: finfun-const-def finfun-comp-conv-comp o-def ) qed lemma finfun-Diag-const1 : ($K $ b, g$) = Pair b ◦$ g by(simp add: finfun-Diag-def )

Do not use ($K $ ?b, ?g$) = Pair ?b ◦$ ?g for the code generator because Pair b is injective, i.e. if g is free of redundant updates, there is no need to check for redundant updates as is done for op ◦$. lemma finfun-Diag-const-code [code]: ($K $ b, K $ c$) = (K $ (b, c)) ($K $ b, finfun-update-code g a c$) = finfun-update-code ($K $ b, g$) a (b, c) by(simp-all add: finfun-Diag-const1 ) lemma finfun-Diag-update1 : ($f (a $:= b), g$) = ($f , g$)(a $:= (b, g $ a)) and finfun-Diag-update1-code [code]: ($finfun-update-code f a b, g$) = ($f , g$)(a $:= (b, g $ a)) by(simp-all add: finfun-Diag-def ) lemma finfun-Diag-const2 : ($f , K $ c$) = (λb. (b, c)) ◦$ f by(induct f rule: finfun-weak-induct)(auto intro!: finfun-ext simp add: finfun-upd-apply finfun-Diag-const1 finfun-Diag-update1 ) lemma finfun-Diag-update2 : ($f , g(a $:= c)$) = ($f , g$)(a $:= (f $ a, c)) by(induct f rule: finfun-weak-induct)(auto intro!: finfun-ext simp add: finfun-upd-apply finfun-Diag-const1 finfun-Diag-update1 ) lemma finfun-Diag-const-const [simp]: ($K $ b, K $ c$) = (K $ (b, c)) by(simp add: finfun-Diag-const1 ) lemma finfun-Diag-const-update: ($K $ b, g(a $:= c)$) = ($K $ b, g$)(a $:= (b, c)) by(simp add: finfun-Diag-const1 ) lemma finfun-Diag-update-const:

569 ($f (a $:= b), K $ c$) = ($f , K $ c$)(a $:= (b, c)) by(simp add: finfun-Diag-def ) lemma finfun-Diag-update-update: ($f (a $:= b), g(a 0 $:= c)$) = (if a = a 0 then ($f , g$)(a $:= (b, c)) else ($f , g$)(a $:= (b, g $ a))(a 0 $:= (f $ a 0, c))) by(auto simp add: finfun-Diag-update1 finfun-Diag-update2 ) lemma finfun-Diag-apply [simp]: op $ ($f , g$) = (λx. (f $ x, g $ x)) by(induct f rule: finfun-weak-induct)(auto simp add: finfun-Diag-const1 finfun-Diag-update1 finfun-upd-apply) lemma finfun-Diag-conv-Abs-finfun: ($f , g$) = Abs-finfun ((λx. (f $ x, g $ x))) including finfun proof − have (λf :: 0a ⇒f 0b. ($f , g$)) = (λf . Abs-finfun ((λx. (f $ x, g $ x)))) proof(rule finfun-rec-unique) { fix c show Abs-finfun (λx. ((K $ c) $ x, g $ x)) = Pair c ◦$ g by(simp add: finfun-comp-conv-comp o-def finfun-const-def ) } { fix g 0 a b show Abs-finfun (λx. (g 0(a $:= b) $ x, g $ x)) = (Abs-finfun (λx. (g 0 $ x, g $ x)))(a $:= (b, g $ a)) by(auto simp add: finfun-update-def fun-eq-iff simp del: fun-upd-apply) simp } qed(simp-all add: finfun-Diag-const1 finfun-Diag-update1 ) thus ?thesis by(auto simp add: fun-eq-iff ) qed lemma finfun-Diag-eq: ($f , g$) = ($f 0, g 0$) ←→ f = f 0 ∧ g = g 0 by(auto simp add: expand-finfun-eq fun-eq-iff ) definition finfun-fst :: 0a ⇒f ( 0b × 0c) ⇒ 0a ⇒f 0b where [code]: finfun-fst f = fst ◦$ f lemma finfun-fst-const: finfun-fst (K $ bc) = (K $ fst bc) by(simp add: finfun-fst-def ) lemma finfun-fst-update: finfun-fst (f (a $:= bc)) = (finfun-fst f )(a $:= fst bc) and finfun-fst-update-code: finfun-fst (finfun-update-code f a bc) = (finfun-fst f )(a $:= fst bc) by(simp-all add: finfun-fst-def ) lemma finfun-fst-comp-conv: finfun-fst (f ◦$ g) = (fst ◦ f ) ◦$ g by(simp add: finfun-fst-def ) lemma finfun-fst-conv [simp]: finfun-fst ($f , g$) = f by(induct f rule: finfun-weak-induct)(simp-all add: finfun-Diag-const1 finfun-fst-comp-conv o-def finfun-Diag-update1 finfun-fst-update)

570 lemma finfun-fst-conv-Abs-finfun: finfun-fst = (λf . Abs-finfun (fst ◦ op $ f )) by(simp add: finfun-fst-def [abs-def ] finfun-comp-conv-comp) definition finfun-snd :: 0a ⇒f ( 0b × 0c) ⇒ 0a ⇒f 0c where [code]: finfun-snd f = snd ◦$ f lemma finfun-snd-const: finfun-snd (K $ bc) = (K $ snd bc) by(simp add: finfun-snd-def ) lemma finfun-snd-update: finfun-snd (f (a $:= bc)) = (finfun-snd f )(a $:= snd bc) and finfun-snd-update-code [code]: finfun-snd (finfun-update-code f a bc) = (finfun-snd f )(a $:= snd bc) by(simp-all add: finfun-snd-def ) lemma finfun-snd-comp-conv: finfun-snd (f ◦$ g) = (snd ◦ f ) ◦$ g by(simp add: finfun-snd-def ) lemma finfun-snd-conv [simp]: finfun-snd ($f , g$) = g apply(induct f rule: finfun-weak-induct) apply(auto simp add: finfun-Diag-const1 finfun-snd-comp-conv o-def finfun-Diag-update1 finfun-snd-update finfun-upd-apply intro: finfun-ext) done lemma finfun-snd-conv-Abs-finfun: finfun-snd = (λf . Abs-finfun (snd ◦ op $ f )) by(simp add: finfun-snd-def [abs-def ] finfun-comp-conv-comp) lemma finfun-Diag-collapse [simp]: ($finfun-fst f , finfun-snd f $) = f by(induct f rule: finfun-weak-induct)(simp-all add: finfun-fst-const finfun-snd-const finfun-fst-update finfun-snd-update finfun-Diag-update-update)

73.14 Currying for FinFuns definition finfun-curry :: ( 0a × 0b) ⇒f 0c ⇒ 0a ⇒f 0b ⇒f 0c where [code del]: finfun-curry = finfun-rec (finfun-const ◦ finfun-const)(λ(a, b) c f . f (a $:= (f $ a)(b $:= c))) interpretation finfun-curry-aux: finfun-rec-wf-aux finfun-const ◦ finfun-const λ(a, b) c f . f (a $:= (f $ a)(b $:= c)) apply(unfold-locales) apply(auto simp add: split-def finfun-update-twist finfun-upd-apply split-paired-all finfun-update-const-same) done interpretation finfun-curry: finfun-rec-wf finfun-const ◦ finfun-const λ(a, b) c f . f (a $:= (f $ a)(b $:= c)) proof(unfold-locales) fix b 0 b :: 0b

571 assume fin: finite (UNIV :: ( 0c × 0a) set) hence fin1 : finite (UNIV :: 0c set) and fin2 : finite (UNIV :: 0a set) unfolding UNIV-Times-UNIV [symmetric] by(fastforce dest: finite-cartesian-productD1 finite-cartesian-productD2 )+ note [simp] = Abs-finfun-inverse-finite[OF fin] Abs-finfun-inverse-finite[OF fin1 ] Abs-finfun-inverse-finite[OF fin2 ] { fix A :: ( 0c × 0a) set interpret comp-fun-commute λa :: 0c × 0a. (λ(a, b) c f . f (a $:= (f $ a)(b $:= c))) a b 0 by(rule finfun-curry-aux.upd-left-comm) from fin have finite A by(auto intro: finite-subset) hence Finite-Set.fold (λa :: 0c × 0a. (λ(a, b) c f . f (a $:= (f $ a)(b $:= c))) a b 0) ((finfun-const ◦ finfun-const) b) A = Abs-finfun (λa. Abs-finfun (λb 00. if (a, b 00) ∈ A then b 0 else b)) by induct (simp-all, auto simp add: finfun-update-def finfun-const-def split-def intro!: arg-cong[where f =Abs-finfun] ext) } from this[of UNIV ] show Finite-Set.fold (λa :: 0c × 0a. (λ(a, b) c f . f (a $:= (f $ a)(b $:= c))) a b 0) ((finfun-const ◦ finfun-const) b) UNIV = (finfun-const ◦ finfun-const) b 0 by(simp add: finfun-const-def ) qed lemma finfun-curry-const [simp, code]: finfun-curry (K $ c) = (K $ K $ c) by(simp add: finfun-curry-def ) lemma finfun-curry-update [simp]: finfun-curry (f ((a, b) $:= c)) = (finfun-curry f )(a $:= (finfun-curry f $ a)(b $:= c)) and finfun-curry-update-code [code]: finfun-curry (finfun-update-code f (a, b) c) = (finfun-curry f )(a $:= (finfun-curry f $ a)(b $:= c)) by(simp-all add: finfun-curry-def ) lemma finfun-Abs-finfun-curry: assumes fin: f ∈ finfun shows (λa. Abs-finfun (curry f a)) ∈ finfun including finfun proof − from fin obtain c where c: finite {ab. f ab 6= c} unfolding finfun-def by blast have {a. ∃ b. f (a, b) 6= c} = fst ‘ {ab. f ab 6= c} by(force) hence {a. curry f a 6= (λx. c)} = fst ‘ {ab. f ab 6= c} by(auto simp add: curry-def fun-eq-iff ) with fin c have finite {a. Abs-finfun (curry f a) 6= (K $ c)} by(simp add: finfun-const-def finfun-curry) thus ?thesis unfolding finfun-def by auto qed lemma finfun-curry-conv-curry: fixes f :: ( 0a × 0b) ⇒f 0c shows finfun-curry f = Abs-finfun (λa. Abs-finfun (curry (finfun-apply f ) a))

572 including finfun proof − have finfun-curry = (λf :: ( 0a × 0b) ⇒f 0c. Abs-finfun (λa. Abs-finfun (curry (finfun-apply f ) a))) proof(rule finfun-rec-unique) fix c show finfun-curry (K $ c) = (K $ K $ c) by simp fix f a show finfun-curry (f (a $:= c)) = (finfun-curry f )(fst a $:= (finfun-curry f $ (fst a))(snd a $:= c)) by(cases a) simp show Abs-finfun (λa. Abs-finfun (curry (finfun-apply (K $ c)) a)) = (K $ K $ c) by(simp add: finfun-curry-def finfun-const-def curry-def ) fix g b show Abs-finfun (λaa. Abs-finfun (curry (op $ g(a $:= b)) aa)) = (Abs-finfun (λa. Abs-finfun (curry (op $ g) a)))( fst a $:= ((Abs-finfun (λa. Abs-finfun (curry (op $ g) a))) $ (fst a))(snd a $:= b)) by(cases a)(auto intro!: ext arg-cong[where f =Abs-finfun] simp add: finfun-curry-def finfun-update-def finfun-Abs-finfun-curry) qed thus ?thesis by(auto simp add: fun-eq-iff ) qed

73.15 Executable equality for FinFuns lemma eq-finfun-All-ext:(f = g) ←→ finfun-All ((λ(x, y). x = y) ◦$ ($f , g$)) by(simp add: expand-finfun-eq fun-eq-iff finfun-All-All o-def ) instantiation finfun :: ({card-UNIV ,equal},equal) equal begin definition eq-finfun-def [code]: HOL.equal f g ←→ finfun-All ((λ(x, y). x = y) ◦$ ($f , g$)) instance by(intro-classes)(simp add: eq-finfun-All-ext eq-finfun-def ) end lemma [code nbe]: HOL.equal (f :: - ⇒f -) f ←→ True by (fact equal-refl)

73.16 An operator that explicitly removes all redundant up- dates in the generated representations definition finfun-clearjunk :: 0a ⇒f 0b ⇒ 0a ⇒f 0b where [simp, code del]: finfun-clearjunk = id lemma finfun-clearjunk-const [code]: finfun-clearjunk (K $ b) = (K $ b) by simp lemma finfun-clearjunk-update [code]:

573 finfun-clearjunk (finfun-update-code f a b) = f (a $:= b) by simp

73.17 The domain of a FinFun as a FinFun definition finfun-dom :: ( 0a ⇒f 0b) ⇒ ( 0a ⇒f bool) where [code del]: finfun-dom f = Abs-finfun (λa. f $ a 6= finfun-default f ) lemma finfun-dom-const: finfun-dom ((K $ c) :: 0a ⇒f 0b) = (K $ finite (UNIV :: 0a set) ∧ c 6= undefined) unfolding finfun-dom-def finfun-default-const by(auto)(simp-all add: finfun-const-def )

finfun-dom raises an exception when called on a FinFun whose domain is a finite type. For such FinFuns, the default value (and as such the domain) is undefined. lemma finfun-dom-const-code [code]: finfun-dom ((K $ c) :: ( 0a :: card-UNIV ) ⇒f 0b) = (if CARD( 0a) = 0 then (K $ False) else Code.abort (STR 00finfun-dom called on finite type 00)(λ-. finfun-dom (K $ c))) by(simp add: finfun-dom-const card-UNIV card-eq-0-iff ) lemma finfun-dom-finfunI :(λa. f $ a 6= finfun-default f ) ∈ finfun using finite-finfun-default[of f ] by(simp add: finfun-def exI [where x=False]) lemma finfun-dom-update [simp]: finfun-dom (f (a $:= b)) = (finfun-dom f )(a $:= (b 6= finfun-default f )) including finfun unfolding finfun-dom-def finfun-update-def apply(simp add: finfun-default-update-const finfun-dom-finfunI ) apply(fold finfun-update.rep-eq) apply(simp add: finfun-upd-apply fun-eq-iff fun-upd-def finfun-default-update-const) done lemma finfun-dom-update-code [code]: finfun-dom (finfun-update-code f a b) = finfun-update-code (finfun-dom f ) a (b 6= finfun-default f ) by(simp) lemma finite-finfun-dom: finite {x. finfun-dom f $ x} proof(induct f rule: finfun-weak-induct) case (const b) thus ?case by (cases finite (UNIV :: 0a set) ∧ b 6= undefined) (auto simp add: finfun-dom-const UNIV-def [symmetric] Set.empty-def [symmetric]) next case (update f a b) have {x. finfun-dom f (a $:= b) $ x} = (if b = finfun-default f then {x. finfun-dom f $ x} − {a} else insert a {x.

574 finfun-dom f $ x}) by (auto simp add: finfun-upd-apply split: if-split-asm) thus ?case using update by simp qed

73.18 The domain of a FinFun as a sorted list definition finfun-to-list :: ( 0a :: linorder) ⇒f 0b ⇒ 0a list where finfun-to-list f = (THE xs. set xs = {x. finfun-dom f $ x} ∧ sorted xs ∧ distinct xs) lemma set-finfun-to-list [simp]: set (finfun-to-list f ) = {x. finfun-dom f $ x} (is ?thesis1 ) and sorted-finfun-to-list: sorted (finfun-to-list f )(is ?thesis2 ) and distinct-finfun-to-list: distinct (finfun-to-list f )(is ?thesis3 ) proof (atomize (full)) show ?thesis1 ∧ ?thesis2 ∧ ?thesis3 unfolding finfun-to-list-def by(rule theI 0)(rule finite-sorted-distinct-unique finite-finfun-dom)+ qed lemma finfun-const-False-conv-bot: op $ (K $ False) = bot by auto lemma finfun-const-True-conv-top: op $ (K $ True) = top by auto lemma finfun-to-list-const: finfun-to-list ((K $ c) :: ( 0a :: {linorder} ⇒f 0b)) = (if ¬ finite (UNIV :: 0a set) ∨ c = undefined then [] else THE xs. set xs = UNIV ∧ sorted xs ∧ distinct xs) by(auto simp add: finfun-to-list-def finfun-const-False-conv-bot finfun-const-True-conv-top finfun-dom-const) lemma finfun-to-list-const-code [code]: finfun-to-list ((K $ c) :: ( 0a :: {linorder, card-UNIV } ⇒f 0b)) = (if CARD( 0a) = 0 then [] else Code.abort (STR 00finfun-to-list called on finite type 00)(λ-. finfun-to-list ((K $ c) :: ( 0a ⇒f 0b)))) by(auto simp add: finfun-to-list-const card-UNIV card-eq-0-iff ) lemma remove1-insort-insert-same: x ∈/ set xs =⇒ remove1 x (insort-insert x xs) = xs by (metis insort-insert-insort remove1-insort) lemma finfun-dom-conv: finfun-dom f $ x ←→ f $ x 6= finfun-default f by(induct f rule: finfun-weak-induct)(auto simp add: finfun-dom-const finfun-default-const finfun-default-update-const finfun-upd-apply)

575 lemma finfun-to-list-update: finfun-to-list (f (a $:= b)) = (if b = finfun-default f then List.remove1 a (finfun-to-list f ) else List.insort-insert a (finfun-to-list f )) proof(subst finfun-to-list-def , rule the-equality) fix xs assume set xs = {x. finfun-dom f (a $:= b) $ x} ∧ sorted xs ∧ distinct xs hence eq: set xs = {x. finfun-dom f (a $:= b) $ x} and [simp]: sorted xs distinct xs by simp-all show xs = (if b = finfun-default f then remove1 a (finfun-to-list f ) else insort-insert a (finfun-to-list f )) proof(cases b = finfun-default f ) case [simp]: True show ?thesis proof(cases finfun-dom f $ a) case True have finfun-to-list f = insort-insert a xs unfolding finfun-to-list-def proof(rule the-equality) have set (insort-insert a xs) = insert a (set xs) by(simp add: set-insort-insert) also note eq also have insert a {x. finfun-dom f (a $:= b) $ x} = {x. finfun-dom f $ x} using True by(auto simp add: finfun-upd-apply split: if-split-asm) finally show 1 : set (insort-insert a xs) = {x. finfun-dom f $ x} ∧ sorted (insort-insert a xs) ∧ distinct (insort-insert a xs) by(simp add: sorted-insort-insert distinct-insort-insert)

fix xs 0 assume set xs 0 = {x. finfun-dom f $ x} ∧ sorted xs 0 ∧ distinct xs 0 thus xs 0 = insort-insert a xs using 1 by(auto dest: sorted-distinct-set-unique) qed with eq True show ?thesis by(simp add: remove1-insort-insert-same) next case False hence f $ a = b by(auto simp add: finfun-dom-conv) hence f : f (a $:= b) = f by(simp add: expand-finfun-eq fun-eq-iff finfun-upd-apply) from eq have finfun-to-list f = xs unfolding f finfun-to-list-def by(auto elim: sorted-distinct-set-unique intro!: the-equality) with eq False show ?thesis unfolding f by(simp add: remove1-idem) qed next case False show ?thesis proof(cases finfun-dom f $ a) case True have finfun-to-list f = xs unfolding finfun-to-list-def

576 proof(rule the-equality) have finfun-dom f = finfun-dom f (a $:= b) using False True by(simp add: expand-finfun-eq fun-eq-iff finfun-upd-apply) with eq show 1 : set xs = {x. finfun-dom f $ x} ∧ sorted xs ∧ distinct xs by(simp del: finfun-dom-update)

fix xs 0 assume set xs 0 = {x. finfun-dom f $ x} ∧ sorted xs 0 ∧ distinct xs 0 thus xs 0 = xs using 1 by(auto elim: sorted-distinct-set-unique) qed thus ?thesis using False True eq by(simp add: insort-insert-triv) next case False have finfun-to-list f = remove1 a xs unfolding finfun-to-list-def proof(rule the-equality) have set (remove1 a xs) = set xs − {a} by simp also note eq also have {x. finfun-dom f (a $:= b) $ x} − {a} = {x. finfun-dom f $ x} using False by(auto simp add: finfun-upd-apply split: if-split-asm) finally show 1 : set (remove1 a xs) = {x. finfun-dom f $ x} ∧ sorted (remove1 a xs) ∧ distinct (remove1 a xs) by(simp add: sorted-remove1 )

fix xs 0 assume set xs 0 = {x. finfun-dom f $ x} ∧ sorted xs 0 ∧ distinct xs 0 thus xs 0 = remove1 a xs using 1 by(blast intro: sorted-distinct-set-unique) qed thus ?thesis using False eq hb 6= finfun-default f i by (simp add: insort-insert-insort insort-remove1 ) qed qed qed (auto simp add: distinct-finfun-to-list sorted-finfun-to-list sorted-remove1 set-insort-insert sorted-insort-insert distinct-insort-insert finfun-upd-apply split: if-split-asm) lemma finfun-to-list-update-code [code]: finfun-to-list (finfun-update-code f a b) = (if b = finfun-default f then List.remove1 a (finfun-to-list f ) else List.insort-insert a (finfun-to-list f )) by(simp add: finfun-to-list-update)

More type class instantiations lemma card-eq-1-iff : card A = 1 ←→ A 6= {} ∧ (∀ x∈A. ∀ y∈A. x = y) (is ?lhs ←→ ?rhs) proof assume ?lhs moreover { fix x y

577 assume A: x ∈ A y ∈ A and neq: x 6= y have finite A using h?lhs i by(simp add: card-ge-0-finite) from neq have 2 = card {x, y} by simp also have ... ≤ card A using A hfinite Ai by(auto intro: card-mono) finally have False using h?lhs i by simp } ultimately show ?rhs by auto next assume ?rhs hence A = {THE x. x ∈ A} by safe (auto intro: theI the-equality[symmetric]) also have card ... = 1 by simp finally show ?lhs . qed lemma card-UNIV-finfun: defines F == finfun :: ( 0a ⇒ 0b) set shows CARD( 0a ⇒f 0b) = (if CARD( 0a) 6= 0 ∧ CARD( 0b) 6= 0 ∨ CARD( 0b) = 1 then CARD( 0b) ˆ CARD( 0a) else 0 ) proof(cases 0 < CARD( 0a) ∧ 0 < CARD( 0b) ∨ CARD( 0b) = 1 ) case True from True have F = UNIV proof assume b: CARD( 0b) = 1 hence ∀ x :: 0b. x = undefined by(auto simp add: card-eq-1-iff simp del: One-nat-def ) thus ?thesis by(auto simp add: finfun-def F-def intro: exI [where x=undefined]) qed(auto simp add: finfun-def card-gt-0-iff F-def intro: finite-subset[where B=UNIV ]) moreover have CARD( 0a ⇒f 0b) = card F unfolding type-definition.Abs-image[OF type-definition-finfun, symmetric] by(auto intro!: card-image inj-onI simp add: Abs-finfun-inject F-def ) ultimately show ?thesis by(simp add: card-fun) next case False hence infinite: ¬ (finite (UNIV :: 0a set) ∧ finite (UNIV :: 0b set)) and b: CARD( 0b) 6= 1 by(simp-all add: card-eq-0-iff ) from b obtain b1 b2 :: 0b where b1 6= b2 by(auto simp add: card-eq-1-iff simp del: One-nat-def ) let ?f = λa a 0 :: 0a. if a = a 0 then b1 else b2 from infinite have ¬ finite (UNIV :: ( 0a ⇒f 0b) set) proof(rule contrapos-nn[OF - conjI ]) assume finite: finite (UNIV :: ( 0a ⇒f 0b) set) hence finite F unfolding type-definition.Abs-image[OF type-definition-finfun, symmetric] F-def by(rule finite-imageD)(auto intro: inj-onI simp add: Abs-finfun-inject) hence finite (range ?f ) by(rule finite-subset[rotated 1 ])(auto simp add: F-def finfun-def hb1 6= b2 i intro!: exI [where x=b2 ])

578 thus finite (UNIV :: 0a set) by(rule finite-imageD)(auto intro: inj-onI simp add: fun-eq-iff hb1 6= b2 i split: if-split-asm)

from finite have finite (range (λb. ((K $ b) :: 0a ⇒f 0b))) by(rule finite-subset[rotated 1 ]) simp thus finite (UNIV :: 0b set) by(rule finite-imageD)(auto intro!: inj-onI ) qed with False show ?thesis by auto qed lemma finite-UNIV-finfun: finite (UNIV :: ( 0a ⇒f 0b) set) ←→ (finite (UNIV :: 0a set) ∧ finite (UNIV :: 0b set) ∨ CARD( 0b) = 1 ) (is ?lhs ←→ ?rhs) proof − have ?lhs ←→ CARD( 0a ⇒f 0b) > 0 by(simp add: card-gt-0-iff ) also have ... ←→ CARD( 0a) > 0 ∧ CARD( 0b) > 0 ∨ CARD( 0b) = 1 by(simp add: card-UNIV-finfun) also have ... = ?rhs by(simp add: card-gt-0-iff ) finally show ?thesis . qed instantiation finfun :: (finite-UNIV , card-UNIV ) finite-UNIV begin definition finite-UNIV = Phantom( 0a ⇒f 0b) (let cb = of-phantom (card-UNIV :: 0b card-UNIV ) in cb = 1 ∨ of-phantom (finite-UNIV :: 0a finite-UNIV ) ∧ cb 6= 0 ) instance by intro-classes (auto simp add: finite-UNIV-finfun-def Let-def card-UNIV finite-UNIV finite-UNIV-finfun card-gt-0-iff ) end instantiation finfun :: (card-UNIV , card-UNIV ) card-UNIV begin definition card-UNIV = Phantom( 0a ⇒f 0b) (let ca = of-phantom (card-UNIV :: 0a card-UNIV ); cb = of-phantom (card-UNIV :: 0b card-UNIV ) in if ca 6= 0 ∧ cb 6= 0 ∨ cb = 1 then cb ˆ ca else 0 ) instance by intro-classes (simp add: card-UNIV-finfun-def card-UNIV Let-def card-UNIV-finfun) end

73.18.1 Bundles for concrete syntax bundle finfun-syntax begin type-notation finfun ((- ⇒f /-)[22 , 21 ] 21 )

579 notation finfun-const (K $/ - [0 ] 1 ) and finfun-update (- 0(- $:= - 0)[1000 , 0 , 0 ] 1000 ) and finfun-apply (infixl $ 999 ) and finfun-comp (infixr ◦$ 55 ) and finfun-comp2 (infixr $◦ 55 ) and finfun-Diag ((1 0($-,/ -$ 0)) [0 , 0 ] 1000 ) notation (ASCII ) finfun-comp (infixr o$ 55 ) and finfun-comp2 (infixr $o 55 ) end bundle no-finfun-syntax begin no-type-notation finfun ((- ⇒f /-)[22 , 21 ] 21 ) no-notation finfun-const (K $/ - [0 ] 1 ) and finfun-update (- 0(- $:= - 0)[1000 , 0 , 0 ] 1000 ) and finfun-apply (infixl $ 999 ) and finfun-comp (infixr ◦$ 55 ) and finfun-comp2 (infixr $◦ 55 ) and finfun-Diag ((1 0($-,/ -$ 0)) [0 , 0 ] 1000 ) no-notation (ASCII ) finfun-comp (infixr o$ 55 ) and finfun-comp2 (infixr $o 55 ) end unbundle no-finfun-syntax end

74 Predicates modelled as FinFuns theory FinFunPred imports ∼∼/src/HOL/Library/FinFun begin unbundle finfun-syntax Instantiate FinFun predicates just like predicates 0 0 type-synonym a pred f = a ⇒f bool

580 instantiation finfun :: (type, ord) ord begin definition le-finfun-def [code del]: f ≤ g ←→ (∀ x. f $ x ≤ g $ x) definition [code del]: (f :: 0a ⇒f 0b) < g ←→ f ≤ g ∧ ¬ g ≤ f instance .. lemma le-finfun-code [code]: f ≤ g ←→ finfun-All ((λ(x, y). x ≤ y) ◦$ ($f , g$)) by(simp add: le-finfun-def finfun-All-All o-def ) end instance finfun :: (type, preorder) preorder by(intro-classes)(auto simp add: less-finfun-def le-finfun-def intro: order-trans) instance finfun :: (type, order) order by(intro-classes)(auto simp add: le-finfun-def order-antisym-conv intro: finfun-ext) instantiation finfun :: (type, order-bot) order-bot begin definition bot = finfun-const bot instance by(intro-classes)(simp add: bot-finfun-def le-finfun-def ) end lemma bot-finfun-apply [simp]: op $ bot = (λ-. bot) by(auto simp add: bot-finfun-def ) instantiation finfun :: (type, order-top) order-top begin definition top = finfun-const top instance by(intro-classes)(simp add: top-finfun-def le-finfun-def ) end lemma top-finfun-apply [simp]: op $ top = (λ-. top) by(auto simp add: top-finfun-def ) instantiation finfun :: (type, inf ) inf begin definition [code]: inf f g = (λ(x, y). inf x y) ◦$ ($f , g$) instance .. end lemma inf-finfun-apply [simp]: op $ (inf f g) = inf (op $ f )(op $ g) by(auto simp add: inf-finfun-def o-def inf-fun-def ) instantiation finfun :: (type, sup) sup begin definition [code]: sup f g = (λ(x, y). sup x y) ◦$ ($f , g$) instance ..

581 end lemma sup-finfun-apply [simp]: op $ (sup f g) = sup (op $ f )(op $ g) by(auto simp add: sup-finfun-def o-def sup-fun-def ) instance finfun :: (type, semilattice-inf ) semilattice-inf by(intro-classes)(simp-all add: inf-finfun-def le-finfun-def ) instance finfun :: (type, semilattice-sup) semilattice-sup by(intro-classes)(simp-all add: sup-finfun-def le-finfun-def ) instance finfun :: (type, lattice) lattice .. instance finfun :: (type, bounded-lattice) bounded-lattice by(intro-classes) instance finfun :: (type, distrib-lattice) distrib-lattice by(intro-classes)(simp add: sup-finfun-def inf-finfun-def expand-finfun-eq o-def sup-inf-distrib1 ) instantiation finfun :: (type, minus) minus begin definition f − g = case-prod (op −) ◦$ ($f , g$) instance .. end lemma minus-finfun-apply [simp]: op $ (f − g) = op $ f − op $ g by(simp add: minus-finfun-def o-def fun-diff-def ) instantiation finfun :: (type, uminus) uminus begin definition − A = uminus ◦$ A instance .. end lemma uminus-finfun-apply [simp]: op $ (− g) = − op $ g by(simp add: uminus-finfun-def o-def fun-Compl-def ) instance finfun :: (type, boolean-algebra) boolean-algebra by(intro-classes) (simp-all add: uminus-finfun-def inf-finfun-def expand-finfun-eq sup-fun-def inf-fun-def fun-Compl-def o-def inf-compl-bot sup-compl-top diff-eq)

Replicate predicate operations for FinFuns 0 abbreviation finfun-empty :: a pred f ({}f ) where {}f ≡ bot

0 abbreviation finfun-UNIV :: a pred f where finfun-UNIV ≡ top

0 0 definition finfun-single :: a ⇒ a pred f where [code]: finfun-single x = finfun-empty(x $:= True)

582 lemma finfun-single-apply [simp]: finfun-single x $ y ←→ x = y by(simp add: finfun-single-def finfun-upd-apply) lemma [iff ]: shows finfun-single-neq-bot: finfun-single x 6= bot and bot-neq-finfun-single: bot 6= finfun-single x by(simp-all add: expand-finfun-eq fun-eq-iff ) lemma finfun-leI [intro!]: (!!x. A $ x =⇒ B $ x) =⇒ A ≤ B by(simp add: le-finfun-def ) lemma finfun-leD [elim]: [[ A ≤ B; A $ x ]] =⇒ B $ x by(simp add: le-finfun-def )

Bounded quantification. Warning: finfun-Ball and finfun-Ex may raise an exception, they should not be used for quickcheck 0 0 0 definition finfun-Ball-except :: a list ⇒ a pred f ⇒ ( a ⇒ bool) ⇒ bool where [code del]: finfun-Ball-except xs A P = (∀ a. A $ a −→ a ∈ set xs ∨ P a) lemma finfun-Ball-except-const: finfun-Ball-except xs (K $ b) P ←→ ¬ b ∨ set xs = UNIV ∨ Code.abort (STR 00finfun-ball-except 00)(λu. finfun-Ball-except xs (K $ b) P) by(auto simp add: finfun-Ball-except-def ) lemma finfun-Ball-except-const-finfun-UNIV-code [code]: finfun-Ball-except xs (K $ b) P ←→ ¬ b ∨ is-list-UNIV xs ∨ Code.abort (STR 00finfun-ball-except 00)(λu. finfun-Ball-except xs (K $ b) P) by(auto simp add: finfun-Ball-except-def is-list-UNIV-iff ) lemma finfun-Ball-except-update: finfun-Ball-except xs (A(a $:= b)) P = ((a ∈ set xs ∨ (b −→ P a)) ∧ finfun-Ball-except (a # xs) AP) by(fastforce simp add: finfun-Ball-except-def finfun-upd-apply split: if-split-asm) lemma finfun-Ball-except-update-code [code]: fixes a :: 0a :: card-UNIV shows finfun-Ball-except xs (finfun-update-code f a b) P = ((a ∈ set xs ∨ (b −→ P a)) ∧ finfun-Ball-except (a # xs) f P) by(simp add: finfun-Ball-except-update)

0 0 definition finfun-Ball :: a pred f ⇒ ( a ⇒ bool) ⇒ bool where [code del]: finfun-Ball A P = Ball {x. A $ x} P lemma finfun-Ball-code [code]: finfun-Ball = finfun-Ball-except [] by(auto intro!: ext simp add: finfun-Ball-except-def finfun-Ball-def )

583 0 0 0 definition finfun-Bex-except :: a list ⇒ a pred f ⇒ ( a ⇒ bool) ⇒ bool where [code del]: finfun-Bex-except xs A P = (∃ a. A $ a ∧ a ∈/ set xs ∧ P a) lemma finfun-Bex-except-const: finfun-Bex-except xs (K $ b) P ←→ b ∧ set xs 6= UNIV ∧ Code.abort (STR 00finfun-Bex-except 00)(λu. finfun-Bex-except xs (K $ b) P) by(auto simp add: finfun-Bex-except-def ) lemma finfun-Bex-except-const-finfun-UNIV-code [code]: finfun-Bex-except xs (K $ b) P ←→ b ∧ ¬ is-list-UNIV xs ∧ Code.abort (STR 00finfun-Bex-except 00)(λu. finfun-Bex-except xs (K $ b) P) by(auto simp add: finfun-Bex-except-def is-list-UNIV-iff ) lemma finfun-Bex-except-update: finfun-Bex-except xs (A(a $:= b)) P ←→ (a ∈/ set xs ∧ b ∧ P a) ∨ finfun-Bex-except (a # xs) AP by(fastforce simp add: finfun-Bex-except-def finfun-upd-apply dest: bspec split: if-split-asm) lemma finfun-Bex-except-update-code [code]: fixes a :: 0a :: card-UNIV shows finfun-Bex-except xs (finfun-update-code f a b) P ←→ ((a ∈/ set xs ∧ b ∧ P a) ∨ finfun-Bex-except (a # xs) f P) by(simp add: finfun-Bex-except-update)

0 0 definition finfun-Bex :: a pred f ⇒ ( a ⇒ bool) ⇒ bool where [code del]: finfun-Bex A P = Bex {x. A $ x} P lemma finfun-Bex-code [code]: finfun-Bex = finfun-Bex-except [] by(auto intro!: ext simp add: finfun-Bex-except-def finfun-Bex-def )

Automatically replace predicate operations by finfun predicate operations where possible lemma iso-finfun-le [code-unfold]: op $ A ≤ op $ B ←→ A ≤ B by (metis le-finfun-def le-funD le-funI ) lemma iso-finfun-less [code-unfold]: op $ A < op $ B ←→ A < B by (metis iso-finfun-le less-finfun-def less-fun-def ) lemma iso-finfun-eq [code-unfold]: op $ A = op $ B ←→ A = B by(simp only: expand-finfun-eq) lemma iso-finfun-sup [code-unfold]: sup (op $ A)(op $ B) = op $ (sup A B) by(simp) lemma iso-finfun-disj [code-unfold]:

584 A $ x ∨ B $ x ←→ sup A B $ x by(simp add: sup-fun-def ) lemma iso-finfun-inf [code-unfold]: inf (op $ A)(op $ B) = op $ (inf A B) by(simp) lemma iso-finfun-conj [code-unfold]: A $ x ∧ B $ x ←→ inf A B $ x by(simp add: inf-fun-def ) lemma iso-finfun-empty-conv [code-unfold]: (λ-. False) = op $ {}f by simp lemma iso-finfun-UNIV-conv [code-unfold]: (λ-. True) = op $ finfun-UNIV by simp lemma iso-finfun-upd [code-unfold]: 0 fixes A :: a pred f shows (op $ A)(x := b) = op $ (A(x $:= b)) by(simp add: fun-eq-iff ) lemma iso-finfun-uminus [code-unfold]: 0 fixes A :: a pred f shows − op $ A = op $ (− A) by(simp) lemma iso-finfun-minus [code-unfold]: 0 fixes A :: a pred f shows op $ A − op $ B = op $ (A − B) by(simp) Do not declare the following two theorems as [code-unfold], because this causes quickcheck to fail frequently when bounded quantification is used which raises an exception. For code generation, the same problems occur, but then, no randomly generated FinFun is usually around. lemma iso-finfun-Ball-Ball: (∀ x. A $ x −→ P x) ←→ finfun-Ball A P by(simp add: finfun-Ball-def ) lemma iso-finfun-Bex-Bex: (∃ x. A $ x ∧ P x) ←→ finfun-Bex A P by(simp add: finfun-Bex-def ) Test code setup notepad begin have inf ((λ- :: nat. False)(1 := True, 2 := True)) ((λ-. True)(3 := False)) ≤

585 sup ((λ-. False)(1 := True, 5 := True)) (− ((λ-. True)(2 := False, 3 := False))) by eval end declare iso-finfun-Ball-Ball[code-unfold] notepad begin have (∀ x. ((λ- :: nat. False)(1 := True, 2 := True)) x −→ x < 3 ) by eval end declare iso-finfun-Ball-Ball[code-unfold del] end

75 Examples for the set comprehension to point- free simproc theory Set-Comprehension-Pointfree-Examples imports Main begin declare [[simproc add: finite-Collect]] lemma finite (UNIV :: 0a set) ==> finite {p. EX x:: 0a. p = (x, x)} by simp lemma finite A ==> finite B ==> finite {f a b| a b. a : A ∧ b : B} by simp lemma finite B ==> finite A 0 ==> finite {f a b| a b. a : A ∧ a : A 0 ∧ b : B} by simp lemma finite A ==> finite B ==> finite {f a b| a b. a : A ∧ b : B ∧ b : B 0} by simp lemma finite A ==> finite B ==> finite C ==> finite {f a b c| a b c. a : A ∧ b : B ∧ c : C } by simp lemma finite A ==> finite B ==> finite C ==> finite D ==> finite {f a b c d| a b c d. a : A ∧ b : B ∧ c : C ∧ d : D} by simp

586 lemma finite A ==> finite B ==> finite C ==> finite D ==> finite E ==> finite {f a b c d e | a b c d e. a : A ∧ b : B ∧ c : C ∧ d : D ∧ e : E} by simp lemma finite A ==> finite B ==> finite C ==> finite D ==> finite E =⇒ finite {f a d c b e | e b c d a. b : B ∧ a : A ∧ e : E 0 ∧ c : C ∧ d : D ∧ e : E ∧ b : B 0} by simp lemma [[ finite A ; finite B ; finite C ; finite D ]] =⇒ finite ({f a b c d| a b c d. a : A ∧ b : B ∧ c : C ∧ d : D}) by simp lemma finite ((λ(a,b,c,d). f a b c d) ‘ (A × B × C × D)) =⇒ finite ({f a b c d| a b c d. a : A ∧ b : B ∧ c : C ∧ d : D}) by simp lemma finite S ==> finite {s 0. EX s:S. s 0 = f a e s} by simp lemma finite A ==> finite B ==> finite {f a b| a b. a : A ∧ b : B ∧ a ∈/ Z } by simp lemma finite A ==> finite B ==> finite R ==> finite {f a b x y| a b x y. a : A ∧ b : B ∧ (x,y) ∈ R} by simp lemma finite A ==> finite B ==> finite R ==> finite {f a b x y| a b x y. a : A ∧ (x,y) ∈ R ∧ b : B} by simp lemma finite A ==> finite B ==> finite R ==> finite {f a (x, b) y| y b x a. a : A ∧ (x,y) ∈ R ∧ b : B} by simp lemma finite A ==> finite AA ==> finite B ==> finite {f a b| a b. (a : A ∨ a : AA) ∧ b : B ∧ a ∈/ Z } by simp

587 lemma finite A1 ==> finite A2 ==> finite A3 ==> finite A4 ==> finite A5 ==> finite B ==> finite {f a b c | a b c. ((a : A1 ∧ a : A2 ) ∨ (a : A3 ∧ (a : A4 ∨ a : A5 ))) ∧ b : B ∧ a ∈/ Z } apply simp oops lemma finite B ==> finite {c. EX x. x : B & c = a ∗ x} by simp lemma finite A ==> finite B ==> finite {f a ∗ g b |a b. a : A & b : B} by simp lemma finite S ==> inj (%(x, y). g x y) ==> finite {f x y| x y. g x y : S} by (auto intro: finite-vimageI ) lemma finite A ==> finite S ==> inj (%(x, y). g x y) ==> finite {f x y z | x y z. g x y : S & z : A} by (auto intro: finite-vimageI ) lemma finite S ==> finite A ==> inj (%(x, y). g x y) ==> inj (%(x, y). h x y) ==> finite {f a b c d | a b c d. g a c : S & h b d : A} by (auto intro: finite-vimageI ) lemma assumes finite S shows finite {(a,b,c,d). ([a, b], [c, d]) : S} using assms by (auto intro!: finite-vimageI simp add: inj-on-def ) schematic-goal finite {x :: ? 0A ⇒ ? 0B ⇒ bool. ∃ a b. x = Pair-Rep a b} = finite ((λ(b :: ? 0B, a:: ? 0A). Pair-Rep a b) ‘ (UNIV × UNIV )) by simp declare [[simproc del: finite-Collect]]

76 Testing simproc in code generation definition union :: nat set => nat set => nat set where union A B = {x. x : A ∨ x : B} definition common-subsets :: nat set => nat set => nat set set

588 where common-subsets S1 S2 = {S. S ⊆ S1 ∧ S ⊆ S2 } definition products :: nat set => nat set => nat set where products A B = {c. EX a b. a : A & b : B & c = a ∗ b} export-code products in Haskell export-code union common-subsets products in Haskell end

77 Futures and parallel lists for code generated towards Isabelle/ML theory Parallel imports Main begin

77.1 Futures datatype 0a future = fork unit ⇒ 0a primrec join :: 0a future ⇒ 0a where join (fork f ) = f () lemma future-eqI [intro!]: assumes join f = join g shows f = g using assms by (cases f , cases g)(simp add: ext) code-printing type-constructor future * (Eval) - future | constant fork * (Eval) Future.fork | constant join * (Eval) Future.join code-reserved Eval Future future

77.2 Parallel lists definition map :: ( 0a ⇒ 0b) ⇒ 0a list ⇒ 0b list where [simp]: map = List.map definition forall :: ( 0a ⇒ bool) ⇒ 0a list ⇒ bool where forall = list-all lemma forall-all [simp]: forall P xs ←→ (∀ x∈set xs. P x)

589 by (simp add: forall-def list-all-iff ) definition exists :: ( 0a ⇒ bool) ⇒ 0a list ⇒ bool where exists = list-ex lemma exists-ex [simp]: exists P xs ←→ (∃ x∈set xs. P x) by (simp add: exists-def list-ex-iff ) code-printing constant map * (Eval) Par 0-List.map | constant forall * (Eval) Par 0-List.forall | constant exists * (Eval) Par 0-List.exists code-reserved Eval Par-List hide-const (open) fork join map exists forall end

78 Debugging facilities for code generated towards Isabelle/ML theory Debug imports Main begin context begin qualified definition trace :: String.literal ⇒ unit where [simp]: trace s = () qualified definition tracing :: String.literal ⇒ 0a ⇒ 0a where [simp]: tracing s = id lemma [code]: tracing s = (let u = trace s in id) by simp qualified definition flush :: 0a ⇒ unit where [simp]: flush x = () qualified definition flushing :: 0a ⇒ 0b ⇒ 0b where [simp]: flushing x = id lemma [code, code-unfold]:

590 flushing x = (let u = flush x in id) by simp qualified definition timing :: String.literal ⇒ ( 0a ⇒ 0b) ⇒ 0a ⇒ 0b where [simp]: timing s f x = f x end code-printing constant Debug.trace * (Eval) Output.tracing | constant Debug.flush * (Eval) Output.tracing/ (@{make 0-string} -) — note indirection via antiquotation | constant Debug.timing * (Eval) Timing.timeap 0-msg code-reserved Eval Output Timing end

79 A simple example demonstrating parallelism for code generated towards Isabelle/ML theory Parallel-Example imports Complex-Main ∼∼/src/HOL/Library/Parallel ∼∼/src/HOL/Library/Debug begin

79.1 Compute-intensive examples. 79.1.1 Fragments of the harmonic series definition harmonic :: nat ⇒ rat where harmonic n = sum-list (map (λn. 1 / of-nat n)[1 ..

79.1.2 The sieve of Erathostenes

The attentive reader may relate this ad-hoc implementation to the arith- metic notion of prime numbers as a little exercise. primrec mark :: nat ⇒ nat ⇒ bool list ⇒ bool list where mark - - [] = [] | mark m n (p # ps) = (case n of 0 ⇒ False # mark m m ps | Suc n ⇒ p # mark m n ps) lemma length-mark [simp]: length (mark m n ps) = length ps by (induct ps arbitrary: n)(simp-all split: nat.split) function sieve :: nat ⇒ bool list ⇒ bool list where sieve m ps = (case dropWhile Not ps of [] ⇒ ps

591 | p#ps 0 ⇒ let n = m − length ps 0 in takeWhile Not ps @ p # sieve m (mark n n ps 0)) by pat-completeness auto termination — tuning of this proof is left as an exercise to the reader apply (relation measure (length ◦ snd)) apply rule apply (auto simp add: length-dropWhile-le) proof − fix ps qs q assume dropWhile Not ps = q # qs then have length (q # qs) = length (dropWhile Not ps) by simp then have length qs < length (dropWhile Not ps) by simp moreover have length (dropWhile Not ps) ≤ length ps by (simp add: length-dropWhile-le) ultimately show length qs < length ps by auto qed primrec natify :: nat ⇒ bool list ⇒ nat list where natify - [] = [] | natify n (p#ps) = (if p then n # natify (Suc n) ps else natify (Suc n) ps) primrec list-primes where list-primes (Suc n) = natify 1 (sieve n (False # replicate n True))

79.1.3 Naive factorisation function factorise-from :: nat ⇒ nat ⇒ nat list where factorise-from k n = (if 1 < k ∧ k ≤ n then let (q, r) = Divides.divmod-nat n k in if r = 0 then k # factorise-from k q else factorise-from (Suc k) n else []) by pat-completeness auto termination factorise-from — tuning of this proof is left as an exercise to the reader term measure apply (relation measure (λ(k, n). 2 ∗ n − k)) apply (auto simp add: prod-eq-iff ) apply (case-tac k ≤ 2 ∗ q) apply (rule diff-less-mono) apply auto done definition factorise :: nat ⇒ nat list where factorise n = factorise-from 2 n

592 79.2 Concurrent computation via futures definition computation-harmonic :: unit ⇒ rat where computation-harmonic - = Debug.timing (STR 00harmonic example 00) harmonic 300 definition computation-primes :: unit ⇒ nat list where computation-primes - = Debug.timing (STR 00primes example 00) list-primes 4000 definition computation-future :: unit ⇒ nat list × rat where computation-future = Debug.timing (STR 00overall computation 00) (λ() ⇒ let c = Parallel.fork computation-harmonic in (computation-primes (), Parallel.join c)) value computation-future () definition computation-factorise :: nat ⇒ nat list where computation-factorise = Debug.timing (STR 00factorise 00) factorise definition computation-parallel :: unit ⇒ nat list list where computation-parallel - = Debug.timing (STR 00overall computation 00) (Parallel.map computation-factorise)[20000 ..<20100 ] value computation-parallel () end

80 Immutable Arrays with Code Generation theory IArray imports Main begin

Immutable arrays are lists wrapped up in an additional constructor. There are no update operations. Hence code generation can safely implement this type by efficient target language arrays. Currently only SML is provided. Should be extended to other target languages and more operations. Note that arrays cannot be printed directly but only by turning them into lists first. Arrays could be converted back into lists for printing if they were wrapped up in an additional constructor. context begin datatype 0a iarray = IArray 0a list qualified primrec list-of :: 0a iarray ⇒ 0a list where list-of (IArray xs) = xs

593 qualified definition of-fun :: (nat ⇒ 0a) ⇒ nat ⇒ 0a iarray where [simp]: of-fun f n = IArray (map f [0 ..

80.1 Code Generation code-reserved SML Vector code-printing type-constructor iarray * (SML) - Vector.vector | constant IArray * (SML) Vector.fromList | constant IArray.all * (SML) Vector.all | constant IArray.exists * (SML) Vector.exists lemma [code]: size (as :: 0a iarray) = Suc (length (IArray.list-of as)) by (cases as) simp lemma [code]: size-iarray f as = Suc (size-list f (IArray.list-of as)) by (cases as) simp lemma [code]: rec-iarray f as = f (IArray.list-of as) by (cases as) simp lemma [code]: case-iarray f as = f (IArray.list-of as) by (cases as) simp lemma [code]: set-iarray as = set (IArray.list-of as)

594 by (cases as) auto lemma [code]: map-iarray f as = IArray (map f (IArray.list-of as)) by (cases as) auto lemma [code]: rel-iarray r as bs = list-all2 r (IArray.list-of as)(IArray.list-of bs) by (cases as, cases bs) auto lemma [code]: HOL.equal as bs ←→ HOL.equal (IArray.list-of as)(IArray.list-of bs) by (cases as, cases bs)(simp add: equal) context begin qualified primrec tabulate :: integer × (integer ⇒ 0a) ⇒ 0a iarray where tabulate (n, f ) = IArray (map (f ◦ integer-of-nat)[0 ..

595 begin qualified definition length 0 :: 0a iarray ⇒ integer where [code del, simp]: length 0 as = integer-of-nat (List.length (IArray.list-of as)) end lemma [code]: IArray.length 0 (IArray as) = integer-of-nat (List.length as) by simp lemma [code]: IArray.length as = nat-of-integer (IArray.length 0 as) by simp context term-syntax begin lemma [code]: Code-Evaluation.term-of (as :: 0a::typerep iarray) = Code-Evaluation.Const (STR 00IArray.iarray.IArray 00)(TYPEREP( 0a list ⇒ 0a iarray)) <·> (Code-Evaluation.term-of (IArray.list-of as)) by (subst term-of-anything) rule end code-printing constant IArray.length 0 * (SML) Vector.length end

81 Implementation of integer numbers by target- language integers theory Code-Target-Int imports ../GCD begin code-datatype int-of-integer declare [[code drop: integer-of-int]] context includes integer.lifting begin lemma [code]: integer-of-int (int-of-integer k) = k

596 by transfer rule lemma [code]: Int.Pos = int-of-integer ◦ integer-of-num by transfer (simp add: fun-eq-iff ) lemma [code]: Int.Neg = int-of-integer ◦ uminus ◦ integer-of-num by transfer (simp add: fun-eq-iff ) lemma [code-abbrev]: int-of-integer (numeral k) = Int.Pos k by transfer simp lemma [code-abbrev]: int-of-integer (− numeral k) = Int.Neg k by transfer simp lemma [code, symmetric, code-post]: 0 = int-of-integer 0 by transfer simp lemma [code, symmetric, code-post]: 1 = int-of-integer 1 by transfer simp lemma [code-post]: int-of-integer (− 1 ) = − 1 by simp lemma [code]: k + l = int-of-integer (of-int k + of-int l) by transfer simp lemma [code]: − k = int-of-integer (− of-int k) by transfer simp lemma [code]: k − l = int-of-integer (of-int k − of-int l) by transfer simp lemma [code]: Int.dup k = int-of-integer (Code-Numeral.dup (of-int k)) by transfer simp declare [[code drop: Int.sub]] lemma [code]:

597 k ∗ l = int-of-integer (of-int k ∗ of-int l) by simp lemma [code]: k div l = int-of-integer (of-int k div of-int l) by simp lemma [code]: k mod l = int-of-integer (of-int k mod of-int l) by simp lemma [code]: divmod m n = map-prod int-of-integer int-of-integer (divmod m n) unfolding prod-eq-iff divmod-def map-prod-def case-prod-beta fst-conv snd-conv by transfer simp lemma [code]: HOL.equal k l = HOL.equal (of-int k :: integer)(of-int l) by transfer (simp add: equal) lemma [code]: k ≤ l ←→ (of-int k :: integer) ≤ of-int l by transfer rule lemma [code]: k < l ←→ (of-int k :: integer) < of-int l by transfer rule declare [[code drop: gcd :: int ⇒ - lcm :: int ⇒ -]] lemma gcd-int-of-integer [code]: gcd (int-of-integer x)(int-of-integer y) = int-of-integer (gcd x y) by transfer rule lemma lcm-int-of-integer [code]: lcm (int-of-integer x)(int-of-integer y) = int-of-integer (lcm x y) by transfer rule end lemma (in ring-1 ) of-int-code-if : of-int k = (if k = 0 then 0 else if k < 0 then − of-int (− k) else let l = 2 ∗ of-int (k div 2 ); j = k mod 2 in if j = 0 then l else l + 1 ) proof − from div-mult-mod-eq have ∗: of-int k = of-int (k div 2 ∗ 2 + k mod 2 ) by

598 simp show ?thesis by (simp add: Let-def of-int-add [symmetric]) (simp add: ∗ mult.commute) qed declare of-int-code-if [code] lemma [code]: nat = nat-of-integer ◦ of-int including integer.lifting by transfer (simp add: fun-eq-iff ) code-identifier code-module Code-Target-Int * (SML) Arith and (OCaml) Arith and (Haskell) Arith end

82 Implementation of natural numbers by target- language integers theory Code-Target-Nat imports Code-Abstract-Nat begin

82.1 Implementation for nat context includes natural.lifting integer.lifting begin lift-definition Nat :: integer ⇒ nat is nat . lemma [code-post]: Nat 0 = 0 Nat 1 = 1 Nat (numeral k) = numeral k by (transfer, simp)+ lemma [code-abbrev]: integer-of-nat = of-nat by transfer rule lemma [code-unfold]: Int.nat (int-of-integer k) = nat-of-integer k by transfer rule

599 lemma [code abstype]: Code-Target-Nat.Nat (integer-of-nat n) = n by transfer simp lemma [code abstract]: integer-of-nat (nat-of-integer k) = max 0 k by transfer auto lemma [code-abbrev]: nat-of-integer (numeral k) = nat-of-num k by transfer (simp add: nat-of-num-numeral) lemma [code abstract]: integer-of-nat (nat-of-num n) = integer-of-num n by transfer (simp add: nat-of-num-numeral) lemma [code abstract]: integer-of-nat 0 = 0 by transfer simp lemma [code abstract]: integer-of-nat 1 = 1 by transfer simp lemma [code]: Suc n = n + 1 by simp lemma [code abstract]: integer-of-nat (m + n) = of-nat m + of-nat n by transfer simp lemma [code abstract]: integer-of-nat (m − n) = max 0 (of-nat m − of-nat n) by transfer simp lemma [code abstract]: integer-of-nat (m ∗ n) = of-nat m ∗ of-nat n by transfer (simp add: of-nat-mult) lemma [code abstract]: integer-of-nat (m div n) = of-nat m div of-nat n by transfer (simp add: zdiv-int) lemma [code abstract]: integer-of-nat (m mod n) = of-nat m mod of-nat n by transfer (simp add: zmod-int) lemma [code]:

600 Divides.divmod-nat m n = (m div n, m mod n) by (fact divmod-nat-div-mod) lemma [code]: divmod m n = map-prod nat-of-integer nat-of-integer (divmod m n) by (simp only: prod-eq-iff divmod-def map-prod-def case-prod-beta fst-conv snd-conv) (transfer, simp-all only: nat-div-distrib nat-mod-distrib zero-le-numeral nat-numeral) lemma [code]: HOL.equal m n = HOL.equal (of-nat m :: integer)(of-nat n) by transfer (simp add: equal) lemma [code]: m ≤ n ←→ (of-nat m :: integer) ≤ of-nat n by simp lemma [code]: m < n ←→ (of-nat m :: integer) < of-nat n by simp lemma num-of-nat-code [code]: num-of-nat = num-of-integer ◦ of-nat by transfer (simp add: fun-eq-iff ) end lemma (in semiring-1 ) of-nat-code-if : of-nat n = (if n = 0 then 0 else let (m, q) = Divides.divmod-nat n 2 ; m 0 = 2 ∗ of-nat m in if q = 0 then m 0 else m 0 + 1 ) proof − from div-mult-mod-eq have ∗: of-nat n = of-nat (n div 2 ∗ 2 + n mod 2 ) by simp show ?thesis by (simp add: Let-def divmod-nat-div-mod of-nat-add [symmetric]) (simp add: ∗ mult.commute of-nat-mult add.commute) qed declare of-nat-code-if [code] definition int-of-nat :: nat ⇒ int where [code-abbrev]: int-of-nat = of-nat lemma [code]: int-of-nat n = int-of-integer (of-nat n) by (simp add: int-of-nat-def )

601 lemma [code abstract]: integer-of-nat (nat k) = max 0 (integer-of-int k) including integer.lifting by transfer auto lemma term-of-nat-code [code]: — Use nat-of-integer in term reconstruction instead of Code-Target-Nat.Nat such that reconstructed terms can be fed back to the code generator term-of-class.term-of n = Code-Evaluation.App (Code-Evaluation.Const (STR 00Code-Numeral.nat-of-integer 00) (typerep.Typerep (STR 00fun 00) [typerep.Typerep (STR 00Code-Numeral.integer 00) [], typerep.Typerep (STR 00Nat.nat 00) []])) (term-of-class.term-of (integer-of-nat n)) by (simp add: term-of-anything) lemma nat-of-integer-code-post [code-post]: nat-of-integer 0 = 0 nat-of-integer 1 = 1 nat-of-integer (numeral k) = numeral k including integer.lifting by (transfer, simp)+ code-identifier code-module Code-Target-Nat * (SML) Arith and (OCaml) Arith and (Haskell) Arith end

83 Implementation of natural and integer num- bers by target-language integers theory Code-Target-Numeral imports Code-Target-Int Code-Target-Nat begin end theory IArray-Examples imports ∼∼/src/HOL/Library/IArray ∼∼/src/HOL/Library/Code-Target-Numeral begin lemma IArray [True,False] !! 1 = False by eval lemma IArray.length (IArray [[],[]]) = 2 by eval lemma IArray.list-of (IArray [1 ,3 ::int]) = [1 ,3 ]

602 by eval lemma IArray.list-of (IArray.of-fun (%n. n∗n) 5 ) = [0 ,1 ,4 ,9 ,16 ] by eval lemma ¬ IArray.all (λx. x > 2 )(IArray [1 ,3 ::int]) by eval lemma IArray.exists (λx. x > 2 )(IArray [1 ,3 ::int]) by eval fun sum2 :: 0a::monoid-add iarray ⇒ nat ⇒ 0a ⇒ 0a where sum2 A n s = (if n=0 then s else sum2 A (n − 1 )(s + A!!(n − 1 ))) definition sum :: 0a::monoid-add iarray ⇒ 0a where sum A = sum2 A (IArray.length A) 0 lemma sum (IArray [1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ::int]) = 45 by eval end theory Simps-Case-Conv imports Main keywords simps-of-case case-of-simps :: thy-decl abbrevs simps-of-case = case-of-simps = begin

ML-file simps-case-conv.ML end theory Simps-Case-Conv-Examples imports ∼∼/src/HOL/Library/Simps-Case-Conv begin

84 Tests for the Simps¡-¿Case conversion tools fun foo where foo (x # xs) Nil = 0 | foo (x # xs)(y # ys) = foo [] [] | foo Nil (y # ys) = 1 | foo Nil Nil = 3 fun bar where bar x 0 y = 0 + x |

603 bar x (Suc n) y = n + x definition split-rule-test :: ((nat => 0a) + ( 0b ∗ (( 0b => 0a) option))) => ( 0a => nat) => nat where split-rule-test x f = f (case x of Inl af ⇒ af 1 | Inr (b, None) => inv f 0 | Inr (b, Some g) => g b) definition test where test x y = (case x of None => (case y of [] => 1 | - # - => 2 ) | Some x => x) definition nosplit where nosplit x = x @(case x of [] ⇒ [1 ] | xs ⇒ xs)

Function with complete, non-overlapping patterns case-of-simps foo-cases1 : foo.simps lemma fixes xs :: 0a list and ys :: 0b list shows foo xs ys = (case (xs, ys) of ( [], []) ⇒ 3 | ([], y # ys) ⇒ 1 | (x # xs, []) ⇒ 0 | (x # xs, y # ys) ⇒ foo ([] :: 0a list) ([] :: 0b list)) by (fact foo-cases1 )

Redundant equations are ignored case-of-simps foo-cases2 : foo.simps foo.simps lemma fixes xs :: 0a list and ys :: 0b list shows foo xs ys = (case (xs, ys) of ( [], []) ⇒ 3 | ([], y # ys) ⇒ 1 | (x # xs, []) ⇒ 0 | (x # xs, y # ys) ⇒ foo ([] :: 0a list) ([] :: 0b list)) by (fact foo-cases2 )

Variable patterns case-of-simps bar-cases: bar.simps print-theorems

Case expression not at top level simps-of-case split-rule-test-simps: split-rule-test-def lemma split-rule-test (Inl x) f = f (x 1 ) split-rule-test (Inr (x, None)) f = f (inv f 0 ) split-rule-test (Inr (x, Some y)) f = f (y x) by (fact split-rule-test-simps)+

604 Argument occurs both as case parameter and seperately simps-of-case nosplit-simps1 : nosplit-def lemma nosplit [] = [] @ [1 ] nosplit (x # xs) = (x # xs)@ x # xs by (fact nosplit-simps1 )+

Nested case expressions simps-of-case test-simps1 : test-def lemma test None [] = 1 test None (x # xs) = 2 test (Some x) y = x by (fact test-simps1 )+

Single-constructor patterns case-of-simps fst-conv-simps: fst-conv lemma fst x = (case x of (a,b) ⇒ a) by (fact fst-conv-simps)

Partial split of case simps-of-case nosplit-simps2 : nosplit-def (splits: list.split) lemma nosplit [] = [] @ [1 ] nosplit (x # xs) = (x # xs)@ x # xs by (fact nosplit-simps1 )+ simps-of-case test-simps2 : test-def (splits: option.split) lemma test None y = (case y of [] ⇒ 1 | x # xs ⇒ 2 ) test (Some x) y = x by (fact test-simps2 )+

Reversal case-of-simps test-def1 : test-simps1 lemma test x y = (case (x,y) of (None, []) ⇒ 1 | (None, -#-) ⇒ 2 | (Some x, -) ⇒ x) by (fact test-def1 )

Case expressions on RHS case-of-simps test-def2 : test-simps2 lemma test xs y = (case (xs, y) of (None, []) ⇒ 1 | (None, x # xa) ⇒ 2 | (Some x, y) ⇒ x) by (fact test-def2 )

605 Partial split of simps case-of-simps foo-cons-def : foo.simps(1 ,2 ) lemma fixes xs :: 0a list and ys :: 0b list shows foo (x # xs) ys = (case (x,xs,ys) of (-,-,[]) ⇒ 0 | (-,-,- # -) ⇒ foo ([] :: 0a list) ([] :: 0b list)) by (fact foo-cons-def ) end

85 Isabelle/ML basics theory ML imports Main begin

86 ML expressions

The Isabelle command ML allows to embed Isabelle/ML source into the formal text. It is type-checked, compiled, and run within that environment. Note that side-effects should be avoided, unless the intention is to change global parameters of the run-time environment (rare). ML top-level bindings are managed within the theory context.

ML h1 + 1 i

ML hval a = 1 i ML hval b = 1 i ML hval c = a + bi

87 Antiquotations

There are some language extensions (via antiquotations), as explained in the “Isabelle/Isar implementation manual”, chapter 0.

ML hlength []i ML h@{assert} (length [] = 0 )i

Formal entities from the surrounding context may be referenced as follows: term 1 + 1 — term within theory source

ML h@{term 1 + 1 } (∗ term as symbolic ML datatype value ∗)i

ML h@{term 1 + (1 ::int)}i

606 ML h (∗ formal source with position information ∗) val s = h1 + 1 i;

(∗ read term via old−style string interface ∗) val t = Syntax.read-term @{context} (Syntax.implode-input s); i

88 Recursive ML evaluation

ML h ML hML hval a = @{thm refl}ii; ML hval b = @{thm sym}i; val c = @{thm trans} val thms = [a, b, c]; i

89 IDE support

ML embedded into the Isabelle environment is connected to the Prover IDE. Poly/ML provides:

• precise positions for warnings / errors

• markup for defining positions of identifiers

• markup for inferred types of sub-expressions

• pretty-printing of ML values with markup

• completion of ML names

• source-level debugger

ML hfn i => fn list => length list + i i

90 Example: factorial and ackermann function in Isabelle/ML

ML h fun factorial 0 = 1 | factorial n = n ∗ factorial (n − 1 ) i

ML hfactorial 42 i ML hfactorial 10000 div factorial 9999 i

607 See http://mathworld.wolfram.com/AckermannFunction.html.

ML h fun ackermann 0 n = n + 1 | ackermann m 0 = ackermann (m − 1 ) 1 | ackermann m n = ackermann (m − 1 )(ackermann m (n − 1 )) i

ML htimeit (fn () => ackermann 3 10 )i

91 Parallel Isabelle/ML

Future.fork/join/cancel manage parallel evaluation. Note that within Isabelle theory documents, the top-level command bound- ary may not be transgressed without special precautions. This is normally managed by the system when performing parallel proof checking.

ML h val x = Future.fork (fn () => ackermann 3 10 ); val y = Future.fork (fn () => ackermann 3 10 ); val z = Future.join x + Future.join y i

The Par_List module provides high-level combinators for parallel list oper- ations.

ML htimeit (fn () => map (fn n => ackermann 3 n)(1 upto 10 ))i ML htimeit (fn () => Par-List.map (fn n => ackermann 3 n)(1 upto 10 ))i

92 Function specifications in Isabelle/HOL fun factorial :: nat ⇒ nat where factorial 0 = 1 | factorial (Suc n) = Suc n ∗ factorial n term factorial 4 — symbolic term value factorial 4 — evaluation via ML code generation in the background declare [[ML-source-trace]] ML h@{term factorial 4 }i — symbolic term in ML ML h@{code factorial}i — ML code from function specification fun ackermann :: nat ⇒ nat ⇒ nat where ackermann 0 n = n + 1 | ackermann (Suc m) 0 = ackermann m 1 | ackermann (Suc m)(Suc n) = ackermann m (ackermann (Suc m) n)

608 value ackermann 3 5 end theory Rewrite imports Main begin consts rewrite-HOLE :: 0a::{} ( ) ◊ lemma eta-expand: fixes f :: 0a::{} ⇒ 0b::{} shows f ≡ λx. f x . lemma rewr-imp: assumes PROP A ≡ PROP B shows (PROP A =⇒ PROP C ) ≡ (PROP B =⇒ PROP C ) apply (rule Pure.equal-intr-rule) apply (drule equal-elim-rule2 [OF assms]; assumption) apply (drule equal-elim-rule1 [OF assms]; assumption) done lemma imp-cong-eq: (PROP A =⇒ (PROP B =⇒ PROP C ) ≡ (PROP B 0 =⇒ PROP C 0)) ≡ ((PROP B =⇒ PROP A =⇒ PROP C ) ≡ (PROP B 0 =⇒ PROP A =⇒ PROP C 0)) apply (intro Pure.equal-intr-rule) apply (drule (1 ) cut-rl; drule Pure.equal-elim-rule1 Pure.equal-elim-rule2 ; assumption)+ apply (drule Pure.equal-elim-rule1 Pure.equal-elim-rule2 ; assumption)+ done

ML-file cconv.ML ML-file rewrite.ML end theory Rewrite-Examples imports Main ∼∼/src/HOL/Library/Rewrite begin

93 The rewrite Proof Method by Example lemma fixes a::int and b::int and c::int assumes P (b + a) shows P (a + b) by (rewrite at a + b add.commute)

609 (rule assms) lemma fixes a b c :: int assumes f (a − a + (a − a)) + f ( 0 + c) = f 0 + f c shows f (a − a + (a − a)) + f ((a − a) + c) = f 0 + f c by (rewrite in f - + f = - diff-self ) fact ◊ lemma fixes a b c :: int assumes f (a − a + 0 ) + f ((a − a) + c) = f 0 + f c shows f (a − a + (a − a)) + f ((a − a) + c) = f 0 + f c by (rewrite at f (- + ) + f - = - diff-self ) fact ◊ lemma fixes a b c :: int assumes f ( 0 + (a − a)) + f ((a − a) + c) = f 0 + f c shows f (a − a + (a − a)) + f ((a − a) + c) = f 0 + f c by (rewrite in f ( + -) + - = - diff-self ) fact ◊ lemma fixes a b c :: int assumes f (a − a + 0 ) + f ((a − a) + c) = f 0 + f c shows f (a − a + (a − a)) + f ((a − a) + c) = f 0 + f c by (rewrite in f (- + ) + - = - diff-self ) fact ◊ lemma fixes x y :: nat showsx + y > c =⇒ y + x > c by (rewrite at > c add.commute) assumption ◊ lemma fixes x y :: nat assumes y + x > c =⇒ y + x > c shows x + y > c =⇒ y + x > c by (rewrite in asm add.commute) fact lemma fixes x y :: nat assumes y + x > c =⇒ y + x > c shows x + y > c =⇒ y + x > c by (rewrite in x + y > c at asm add.commute) fact lemma fixes x y :: nat assumes y + x > c =⇒ y + x > c shows x + y > c =⇒ y + x > c

610 by (rewrite at > c at asm add.commute) fact ◊ lemma assumes P {x::int. y + 1 = 1 + x} shows P {x::int. y + 1 = x + 1 } by (rewrite at x+1 in {x::int. } add.commute) fact ◊ lemma assumes P {x::int. y + 1 = 1 + x} shows P {x::int. y + 1 = x + 1 } by (rewrite at any-identifier-will-work+1 in {any-identifier-will-work::int. } add.commute) ◊ fact lemma assumes P {(x::nat, y::nat, z). x + z ∗ 3 = Q (λs t. s ∗ t + y − 3 )} shows P {(x::nat, y::nat, z). x + z ∗ 3 = Q (λs t. y + s ∗ t − 3 )} by (rewrite at b + d ∗ e in λ(a, b, c). - = Q (λd e. ) add.commute) fact ◊ lemma assumes PROP P ≡ PROP Q shows PROP R =⇒ PROP P =⇒ PROP Q by (rewrite at asm assms) lemma assumes PROP P ≡ PROP Q shows PROP R =⇒ PROP R =⇒ PROP P =⇒ PROP Q by (rewrite at asm assms) lemma assumes (PROP P =⇒ PROP Q) ≡ (PROP S =⇒ PROP R) shows PROP S =⇒ (PROP P =⇒ PROP Q) =⇒ PROP R apply (rewrite at asm assms) apply assumption done

lemma test-theorem: fixes x :: nat shows x ≤ y =⇒ x ≥ y =⇒ x = y by (rule Orderings.order-antisym) lemma fixes f :: nat ⇒ nat

611 shows f x ≤ 0 =⇒ f x ≥ 0 =⇒ f x = 0 apply (rewrite at f x to 0 test-theorem) apply assumption apply assumption apply (rule refl) done lemma assumes rewr: PROP P =⇒ PROP Q =⇒ PROP R ≡ PROP R 0 assumes A1 : PROP S =⇒ PROP T =⇒ PROP U =⇒ PROP P assumes A2 : PROP S =⇒ PROP T =⇒ PROP U =⇒ PROP Q assumes C : PROP S =⇒ PROP R 0 =⇒ PROP T =⇒ PROP U =⇒ PROP V shows PROP S =⇒ PROP R =⇒ PROP T =⇒ PROP U =⇒ PROP V apply (rewrite at asm rewr) apply (fact A1 ) apply (fact A2 ) apply (fact C ) done

fun f :: nat ⇒ nat where f n = n definition f-inv (I :: nat ⇒ bool) n ≡ f n lemma annotate-f : f = f-inv I by (simp add: f-inv-def fun-eq-iff ) lemma assumes P (λn. f-inv (λ-. True) n + 1 ) = x shows P (λn. f n + 1 ) = x by (rewrite to f-inv (λ-. True) annotate-f ) fact lemma assumes P (λn. f-inv (λx. n < x + 1 ) n + 1 ) = x shows P (λn. f n + 1 ) = x by (rewrite in λn. to f-inv (λx. n < x + 1 ) annotate-f ) fact ◊ lemma assumes P (λn. f-inv (λx. n < x + 1 ) n + 1 ) = x shows P (λn. f n + 1 ) = x by (rewrite in λabc. to f-inv (λx. abc < x + 1 ) annotate-f ) fact ◊

612 lemma assumes P (2 + 1 ) shows Vx y. P (1 + 2 :: nat) by (rewrite in P (1 + 2 ) at for (x) add.commute) fact lemma assumes Vx y. P (y + x) shows Vx y. P (x + y :: nat) by (rewrite in P (x + -) at for (x y) add.commute) fact lemma assumes Vx y z. y + x + z = z + y + (x::int) shows Vx y z. x + y + z = z + y + (x::int) by (rewrite at x + y in x + y + z in for (x y z) add.commute) fact lemma assumes Vx y z. z + (x + y) = z + y + (x::int) shows Vx y z. x + y + z = z + y + (x::int) by (rewrite at (- + y) + z in for (y z) add.commute) fact lemma assumes Vx y z. x + y + z = y + z + (x::int) shows Vx y z. x + y + z = z + y + (x::int) by (rewrite at + - at - = in for () add.commute) fact ◊ ◊ lemma assumes eq: Vx. P x =⇒ g x = x assumes f1 : Vx. Q x =⇒ P x assumes f2 : Vx. Q x =⇒ x shows Vx. Q x =⇒ g x apply (rewrite at g x in for (x) eq) apply (fact f1 ) apply (fact f2 ) done lemma assumes (V(x::int). x < 1 + x) and (x::int) + 1 > x shows (V(x::int). x + 1 > x) =⇒ (x::int) + 1 > x by (rewrite at x + 1 in for (x) at asm add.commute) (rule assms) lemma assumes Va b. P ((a + 1 ) ∗ (1 + b)) shows Va b :: nat. P ((a + 1 ) ∗ (b + 1 )) apply (tactic h let

613 val (x, ctxt) = yield-singleton Variable.add-fixes x @{context} (∗ Note that the pattern order is reversed ∗) val pat = [ Rewrite.For [(x, SOME @{typ nat})], Rewrite.In, Rewrite.Term (@{const plus(nat)} $ Free (x, @{typ nat}) $ @{term 1 :: nat}, [])] val to = NONE in CCONVERSION (Rewrite.rewrite-conv ctxt (pat, to)@{thms add.commute}) 1 end i) apply (fact assms) done lemma assumes Q (λb :: int. P (λa. a + b)(λa. a + b)) shows Q (λb :: int. P (λa. a + b)(λa. b + a)) apply (tactic h let val (x, ctxt) = yield-singleton Variable.add-fixes x @{context} val pat = [ Rewrite.Concl, Rewrite.In, Rewrite.Term (Free (Q, (@{typ int} −−> TVar (( 0b,0 ), [])) −−> @{typ bool}) $ Abs (x, @{typ int}, Rewrite.mk-hole 1 (@{typ int} −−> TVar (( 0b,0 ), [])) $ Bound 0 ), [(x, @{typ int})]), Rewrite.In, Rewrite.Term (@{const plus(int)} $ Free (x, @{typ int}) $ Var ((c, 0 ), @{typ int}), []) ] val to = NONE in CCONVERSION (Rewrite.rewrite-conv ctxt (pat, to)@{thms add.commute}) 1 end i) apply (fact assms) done

ML h val ct = @{cprop Q (λb :: int. P (λa. a + b)(λa. b + a))} val (x, ctxt) = yield-singleton Variable.add-fixes x @{context} val pat = [ Rewrite.Concl, Rewrite.In, Rewrite.Term (Free (Q, (@{typ int} −−> TVar (( 0b,0 ), [])) −−> @{typ bool}) $ Abs (x, @{typ int}, Rewrite.mk-hole 1 (@{typ int} −−> TVar (( 0b,0 ), [])) $ Bound 0 ), [(x, @{typ int})]), Rewrite.In,

614 Rewrite.Term (@{const plus(int)} $ Free (x, @{typ int}) $ Var ((c, 0 ), @{typ int}), []) ] val to = NONE val th = Rewrite.rewrite-conv ctxt (pat, to)@{thms add.commute} ct i

94 Regression tests

ML h val ct = @{cterm (λb :: int. (λa. b + a))} val (x, ctxt) = yield-singleton Variable.add-fixes x @{context} val pat = [ Rewrite.In, Rewrite.Term (@{const plus(int)} $ Var ((c, 0 ), @{typ int}) $ Var ((c, 0 ), @{typ int}), []) ] val to = NONE val - = case try (Rewrite.rewrite-conv ctxt (pat, to)@{thms add.commute}) ct of NONE => () | - => error should not have matched anything i

ML h Rewrite.params-pconv (Conv.all-conv |> K |> K )@{context} (Vartab.empty, []) @{cterm Vx. PROP A} i lemma assumes eq: PROP A =⇒ PROP B ≡ PROP C assumes f1 : PROP D =⇒ PROP A assumes f2 : PROP D =⇒ PROP C shows Vx. PROP D =⇒ PROP B apply (rewrite eq) apply (fact f1 ) apply (fact f2 ) done end

95 Examples for proof methods ”sat” and ”satx” theory SAT-Examples imports Main begin

615 lemma True by sat lemma a | ∼a by sat lemma (a | b)& ∼a =⇒ b by sat lemma (a & b) | (c & d) =⇒ (a & b) | (c & d) by sat lemma (a & b) | (c & d) =⇒ (a & b) | (c & d) by satx lemma (a & b | c & d)&(e & f | g & h) | (i & j | k & l)&(m & n | p & q) =⇒ (a & b | c & d)&(e & f | g & h) | (i & j | k & l)&(m & n | p & q) by sat lemma (a & b | c & d)&(e & f | g & h) | (i & j | k & l)&(m & n | p & q) =⇒ (a & b | c & d)&(e & f | g & h) | (i & j | k & l)&(m & n | p & q) by satx lemma P=P=P=P=P=P=P=P=P=P by sat lemma P=P=P=P=P=P=P=P=P=P by satx lemma !! a b c. [| a | b | c | d ; e | f | (a & d); ∼(a | (c & ∼c)) | b ; ∼(b &(x | ∼x)) | c ; ∼(d | False) | c ; ∼(c | (∼p &(p | (q & ∼q)))) |] ==> False by sat lemma !! a b c. [| a | b | c | d ; e | f | (a & d); ∼(a | (c & ∼c)) | b ; ∼(b &(x | ∼x)) | c ; ∼(d | False) | c ; ∼(c | (∼p &(p | (q & ∼q)))) |] ==> False by satx

616 eta-Equivalence lemma (ALL x. P x) | ∼ All P by sat declare [[sat-trace = false]] declare [[quick-and-dirty = false]] method-setup rawsat = h Scan.succeed (SIMPLE-METHOD 0 o SAT .rawsat-tac) i SAT solver (no preprocessing)

lemma assumes 1 : ∼x0 and 2 : ∼x30 and 3 : ∼x29 and 4 : ∼x59 and 5 : x1 | x31 | x0 and 6 : x2 | x32 | x1 and 7 : x3 | x33 | x2 and 8 : x4 | x34 | x3 and 9 : x35 | x4 and 10 : x5 | x36 | x30 and 11 : x6 | x37 | x5 | x31 and 12 : x7 | x38 | x6 | x32 and 13 : x8 | x39 | x7 | x33 and 14 : x9 | x40 | x8 | x34 and 15 : x41 | x9 | x35 and 16 : x10 | x42 | x36 and 17 : x11 | x43 | x10 | x37 and 18 : x12 | x44 | x11 | x38 and 19 : x13 | x45 | x12 | x39 and 20 : x14 | x46 | x13 | x40 and 21 : x47 | x14 | x41 and 22 : x15 | x48 | x42 and 23 : x16 | x49 | x15 | x43 and 24 : x17 | x50 | x16 | x44 and 25 : x18 | x51 | x17 | x45 and 26 : x19 | x52 | x18 | x46 and 27 : x53 | x19 | x47 and 28 : x20 | x54 | x48 and 29 : x21 | x55 | x20 | x49 and 30 : x22 | x56 | x21 | x50 and 31 : x23 | x57 | x22 | x51 and 32 : x24 | x58 | x23 | x52 and 33 : x59 | x24 | x53 and 34 : x25 | x54 and 35 : x26 | x25 | x55 and 36 : x27 | x26 | x56

617 and 37 : x28 | x27 | x57 and 38 : x29 | x28 | x58 and 39 : ∼x1 | ∼x31 and 40 : ∼x1 | ∼x0 and 41 : ∼x31 | ∼x0 and 42 : ∼x2 | ∼x32 and 43 : ∼x2 | ∼x1 and 44 : ∼x32 | ∼x1 and 45 : ∼x3 | ∼x33 and 46 : ∼x3 | ∼x2 and 47 : ∼x33 | ∼x2 and 48 : ∼x4 | ∼x34 and 49 : ∼x4 | ∼x3 and 50 : ∼x34 | ∼x3 and 51 : ∼x35 | ∼x4 and 52 : ∼x5 | ∼x36 and 53 : ∼x5 | ∼x30 and 54 : ∼x36 | ∼x30 and 55 : ∼x6 | ∼x37 and 56 : ∼x6 | ∼x5 and 57 : ∼x6 | ∼x31 and 58 : ∼x37 | ∼x5 and 59 : ∼x37 | ∼x31 and 60 : ∼x5 | ∼x31 and 61 : ∼x7 | ∼x38 and 62 : ∼x7 | ∼x6 and 63 : ∼x7 | ∼x32 and 64 : ∼x38 | ∼x6 and 65 : ∼x38 | ∼x32 and 66 : ∼x6 | ∼x32 and 67 : ∼x8 | ∼x39 and 68 : ∼x8 | ∼x7 and 69 : ∼x8 | ∼x33 and 70 : ∼x39 | ∼x7 and 71 : ∼x39 | ∼x33 and 72 : ∼x7 | ∼x33 and 73 : ∼x9 | ∼x40 and 74 : ∼x9 | ∼x8 and 75 : ∼x9 | ∼x34 and 76 : ∼x40 | ∼x8 and 77 : ∼x40 | ∼x34 and 78 : ∼x8 | ∼x34 and 79 : ∼x41 | ∼x9 and 80 : ∼x41 | ∼x35 and 81 : ∼x9 | ∼x35 and 82 : ∼x10 | ∼x42 and 83 : ∼x10 | ∼x36 and 84 : ∼x42 | ∼x36 and 85 : ∼x11 | ∼x43

618 and 86 : ∼x11 | ∼x10 and 87 : ∼x11 | ∼x37 and 88 : ∼x43 | ∼x10 and 89 : ∼x43 | ∼x37 and 90 : ∼x10 | ∼x37 and 91 : ∼x12 | ∼x44 and 92 : ∼x12 | ∼x11 and 93 : ∼x12 | ∼x38 and 94 : ∼x44 | ∼x11 and 95 : ∼x44 | ∼x38 and 96 : ∼x11 | ∼x38 and 97 : ∼x13 | ∼x45 and 98 : ∼x13 | ∼x12 and 99 : ∼x13 | ∼x39 and 100 : ∼x45 | ∼x12 and 101 : ∼x45 | ∼x39 and 102 : ∼x12 | ∼x39 and 103 : ∼x14 | ∼x46 and 104 : ∼x14 | ∼x13 and 105 : ∼x14 | ∼x40 and 106 : ∼x46 | ∼x13 and 107 : ∼x46 | ∼x40 and 108 : ∼x13 | ∼x40 and 109 : ∼x47 | ∼x14 and 110 : ∼x47 | ∼x41 and 111 : ∼x14 | ∼x41 and 112 : ∼x15 | ∼x48 and 113 : ∼x15 | ∼x42 and 114 : ∼x48 | ∼x42 and 115 : ∼x16 | ∼x49 and 116 : ∼x16 | ∼x15 and 117 : ∼x16 | ∼x43 and 118 : ∼x49 | ∼x15 and 119 : ∼x49 | ∼x43 and 120 : ∼x15 | ∼x43 and 121 : ∼x17 | ∼x50 and 122 : ∼x17 | ∼x16 and 123 : ∼x17 | ∼x44 and 124 : ∼x50 | ∼x16 and 125 : ∼x50 | ∼x44 and 126 : ∼x16 | ∼x44 and 127 : ∼x18 | ∼x51 and 128 : ∼x18 | ∼x17 and 129 : ∼x18 | ∼x45 and 130 : ∼x51 | ∼x17 and 131 : ∼x51 | ∼x45 and 132 : ∼x17 | ∼x45 and 133 : ∼x19 | ∼x52 and 134 : ∼x19 | ∼x18

619 and 135 : ∼x19 | ∼x46 and 136 : ∼x52 | ∼x18 and 137 : ∼x52 | ∼x46 and 138 : ∼x18 | ∼x46 and 139 : ∼x53 | ∼x19 and 140 : ∼x53 | ∼x47 and 141 : ∼x19 | ∼x47 and 142 : ∼x20 | ∼x54 and 143 : ∼x20 | ∼x48 and 144 : ∼x54 | ∼x48 and 145 : ∼x21 | ∼x55 and 146 : ∼x21 | ∼x20 and 147 : ∼x21 | ∼x49 and 148 : ∼x55 | ∼x20 and 149 : ∼x55 | ∼x49 and 150 : ∼x20 | ∼x49 and 151 : ∼x22 | ∼x56 and 152 : ∼x22 | ∼x21 and 153 : ∼x22 | ∼x50 and 154 : ∼x56 | ∼x21 and 155 : ∼x56 | ∼x50 and 156 : ∼x21 | ∼x50 and 157 : ∼x23 | ∼x57 and 158 : ∼x23 | ∼x22 and 159 : ∼x23 | ∼x51 and 160 : ∼x57 | ∼x22 and 161 : ∼x57 | ∼x51 and 162 : ∼x22 | ∼x51 and 163 : ∼x24 | ∼x58 and 164 : ∼x24 | ∼x23 and 165 : ∼x24 | ∼x52 and 166 : ∼x58 | ∼x23 and 167 : ∼x58 | ∼x52 and 168 : ∼x23 | ∼x52 and 169 : ∼x59 | ∼x24 and 170 : ∼x59 | ∼x53 and 171 : ∼x24 | ∼x53 and 172 : ∼x25 | ∼x54 and 173 : ∼x26 | ∼x25 and 174 : ∼x26 | ∼x55 and 175 : ∼x25 | ∼x55 and 176 : ∼x27 | ∼x26 and 177 : ∼x27 | ∼x56 and 178 : ∼x26 | ∼x56 and 179 : ∼x28 | ∼x27 and 180 : ∼x28 | ∼x57 and 181 : ∼x27 | ∼x57 and 182 : ∼x29 | ∼x28 and 183 : ∼x29 | ∼x58

620 and 184 : ∼x28 | ∼x58 shows False using assms by rawsat — this is without CNF conversion

lemma assumes 1 : x0 | x1 | x2 | x3 | x4 | x5 | x6 and 2 : x7 | x8 | x9 | x10 | x11 | x12 | x13 and 3 : x14 | x15 | x16 | x17 | x18 | x19 | x20 and 4 : x21 | x22 | x23 | x24 | x25 | x26 | x27 and 5 : x28 | x29 | x30 | x31 | x32 | x33 | x34 and 6 : x35 | x36 | x37 | x38 | x39 | x40 | x41 and 7 : x42 | x43 | x44 | x45 | x46 | x47 | x48 and 8 : x49 | x50 | x51 | x52 | x53 | x54 | x55 and 9 : ∼x0 | ∼x7 and 10 : ∼x0 | ∼x14 and 11 : ∼x0 | ∼x21 and 12 : ∼x0 | ∼x28 and 13 : ∼x0 | ∼x35 and 14 : ∼x0 | ∼x42 and 15 : ∼x0 | ∼x49 and 16 : ∼x7 | ∼x14 and 17 : ∼x7 | ∼x21 and 18 : ∼x7 | ∼x28 and 19 : ∼x7 | ∼x35 and 20 : ∼x7 | ∼x42 and 21 : ∼x7 | ∼x49 and 22 : ∼x14 | ∼x21 and 23 : ∼x14 | ∼x28 and 24 : ∼x14 | ∼x35 and 25 : ∼x14 | ∼x42 and 26 : ∼x14 | ∼x49 and 27 : ∼x21 | ∼x28 and 28 : ∼x21 | ∼x35 and 29 : ∼x21 | ∼x42 and 30 : ∼x21 | ∼x49 and 31 : ∼x28 | ∼x35 and 32 : ∼x28 | ∼x42 and 33 : ∼x28 | ∼x49 and 34 : ∼x35 | ∼x42 and 35 : ∼x35 | ∼x49 and 36 : ∼x42 | ∼x49 and 37 : ∼x1 | ∼x8 and 38 : ∼x1 | ∼x15 and 39 : ∼x1 | ∼x22 and 40 : ∼x1 | ∼x29 and 41 : ∼x1 | ∼x36

621 and 42 : ∼x1 | ∼x43 and 43 : ∼x1 | ∼x50 and 44 : ∼x8 | ∼x15 and 45 : ∼x8 | ∼x22 and 46 : ∼x8 | ∼x29 and 47 : ∼x8 | ∼x36 and 48 : ∼x8 | ∼x43 and 49 : ∼x8 | ∼x50 and 50 : ∼x15 | ∼x22 and 51 : ∼x15 | ∼x29 and 52 : ∼x15 | ∼x36 and 53 : ∼x15 | ∼x43 and 54 : ∼x15 | ∼x50 and 55 : ∼x22 | ∼x29 and 56 : ∼x22 | ∼x36 and 57 : ∼x22 | ∼x43 and 58 : ∼x22 | ∼x50 and 59 : ∼x29 | ∼x36 and 60 : ∼x29 | ∼x43 and 61 : ∼x29 | ∼x50 and 62 : ∼x36 | ∼x43 and 63 : ∼x36 | ∼x50 and 64 : ∼x43 | ∼x50 and 65 : ∼x2 | ∼x9 and 66 : ∼x2 | ∼x16 and 67 : ∼x2 | ∼x23 and 68 : ∼x2 | ∼x30 and 69 : ∼x2 | ∼x37 and 70 : ∼x2 | ∼x44 and 71 : ∼x2 | ∼x51 and 72 : ∼x9 | ∼x16 and 73 : ∼x9 | ∼x23 and 74 : ∼x9 | ∼x30 and 75 : ∼x9 | ∼x37 and 76 : ∼x9 | ∼x44 and 77 : ∼x9 | ∼x51 and 78 : ∼x16 | ∼x23 and 79 : ∼x16 | ∼x30 and 80 : ∼x16 | ∼x37 and 81 : ∼x16 | ∼x44 and 82 : ∼x16 | ∼x51 and 83 : ∼x23 | ∼x30 and 84 : ∼x23 | ∼x37 and 85 : ∼x23 | ∼x44 and 86 : ∼x23 | ∼x51 and 87 : ∼x30 | ∼x37 and 88 : ∼x30 | ∼x44 and 89 : ∼x30 | ∼x51 and 90 : ∼x37 | ∼x44

622 and 91 : ∼x37 | ∼x51 and 92 : ∼x44 | ∼x51 and 93 : ∼x3 | ∼x10 and 94 : ∼x3 | ∼x17 and 95 : ∼x3 | ∼x24 and 96 : ∼x3 | ∼x31 and 97 : ∼x3 | ∼x38 and 98 : ∼x3 | ∼x45 and 99 : ∼x3 | ∼x52 and 100 : ∼x10 | ∼x17 and 101 : ∼x10 | ∼x24 and 102 : ∼x10 | ∼x31 and 103 : ∼x10 | ∼x38 and 104 : ∼x10 | ∼x45 and 105 : ∼x10 | ∼x52 and 106 : ∼x17 | ∼x24 and 107 : ∼x17 | ∼x31 and 108 : ∼x17 | ∼x38 and 109 : ∼x17 | ∼x45 and 110 : ∼x17 | ∼x52 and 111 : ∼x24 | ∼x31 and 112 : ∼x24 | ∼x38 and 113 : ∼x24 | ∼x45 and 114 : ∼x24 | ∼x52 and 115 : ∼x31 | ∼x38 and 116 : ∼x31 | ∼x45 and 117 : ∼x31 | ∼x52 and 118 : ∼x38 | ∼x45 and 119 : ∼x38 | ∼x52 and 120 : ∼x45 | ∼x52 and 121 : ∼x4 | ∼x11 and 122 : ∼x4 | ∼x18 and 123 : ∼x4 | ∼x25 and 124 : ∼x4 | ∼x32 and 125 : ∼x4 | ∼x39 and 126 : ∼x4 | ∼x46 and 127 : ∼x4 | ∼x53 and 128 : ∼x11 | ∼x18 and 129 : ∼x11 | ∼x25 and 130 : ∼x11 | ∼x32 and 131 : ∼x11 | ∼x39 and 132 : ∼x11 | ∼x46 and 133 : ∼x11 | ∼x53 and 134 : ∼x18 | ∼x25 and 135 : ∼x18 | ∼x32 and 136 : ∼x18 | ∼x39 and 137 : ∼x18 | ∼x46 and 138 : ∼x18 | ∼x53 and 139 : ∼x25 | ∼x32

623 and 140 : ∼x25 | ∼x39 and 141 : ∼x25 | ∼x46 and 142 : ∼x25 | ∼x53 and 143 : ∼x32 | ∼x39 and 144 : ∼x32 | ∼x46 and 145 : ∼x32 | ∼x53 and 146 : ∼x39 | ∼x46 and 147 : ∼x39 | ∼x53 and 148 : ∼x46 | ∼x53 and 149 : ∼x5 | ∼x12 and 150 : ∼x5 | ∼x19 and 151 : ∼x5 | ∼x26 and 152 : ∼x5 | ∼x33 and 153 : ∼x5 | ∼x40 and 154 : ∼x5 | ∼x47 and 155 : ∼x5 | ∼x54 and 156 : ∼x12 | ∼x19 and 157 : ∼x12 | ∼x26 and 158 : ∼x12 | ∼x33 and 159 : ∼x12 | ∼x40 and 160 : ∼x12 | ∼x47 and 161 : ∼x12 | ∼x54 and 162 : ∼x19 | ∼x26 and 163 : ∼x19 | ∼x33 and 164 : ∼x19 | ∼x40 and 165 : ∼x19 | ∼x47 and 166 : ∼x19 | ∼x54 and 167 : ∼x26 | ∼x33 and 168 : ∼x26 | ∼x40 and 169 : ∼x26 | ∼x47 and 170 : ∼x26 | ∼x54 and 171 : ∼x33 | ∼x40 and 172 : ∼x33 | ∼x47 and 173 : ∼x33 | ∼x54 and 174 : ∼x40 | ∼x47 and 175 : ∼x40 | ∼x54 and 176 : ∼x47 | ∼x54 and 177 : ∼x6 | ∼x13 and 178 : ∼x6 | ∼x20 and 179 : ∼x6 | ∼x27 and 180 : ∼x6 | ∼x34 and 181 : ∼x6 | ∼x41 and 182 : ∼x6 | ∼x48 and 183 : ∼x6 | ∼x55 and 184 : ∼x13 | ∼x20 and 185 : ∼x13 | ∼x27 and 186 : ∼x13 | ∼x34 and 187 : ∼x13 | ∼x41 and 188 : ∼x13 | ∼x48

624 and 189 : ∼x13 | ∼x55 and 190 : ∼x20 | ∼x27 and 191 : ∼x20 | ∼x34 and 192 : ∼x20 | ∼x41 and 193 : ∼x20 | ∼x48 and 194 : ∼x20 | ∼x55 and 195 : ∼x27 | ∼x34 and 196 : ∼x27 | ∼x41 and 197 : ∼x27 | ∼x48 and 198 : ∼x27 | ∼x55 and 199 : ∼x34 | ∼x41 and 200 : ∼x34 | ∼x48 and 201 : ∼x34 | ∼x55 and 202 : ∼x41 | ∼x48 and 203 : ∼x41 | ∼x55 and 204 : ∼x48 | ∼x55 shows False using assms by rawsat — this is without CNF conversion

Function benchmark takes the name of an existing DIMACS CNF file, parses this file, passes the problem to a SAT solver, and checks the proof of un- satisfiability found by the solver. The function measures the time spent on proof reconstruction (at least real time also includes time spent in the SAT solver), and additionally returns the number of resolution steps in the proof.

ML h fun benchmark dimacsfile = let val prop-fm = SAT-Solver.read-dimacs-cnf-file (Path.explode dimacsfile) fun and-to-list (Prop-Logic.And (fm1 , fm2 )) acc = and-to-list fm2 (fm1 :: acc) | and-to-list fm acc = rev (fm :: acc) val clauses = and-to-list prop-fm [] val terms = map (HOLogic.mk-Trueprop o Prop-Logic.term-of-prop-formula) clauses val cterms = map (Thm.cterm-of @{context}) terms val start = Timing.start () val - = SAT .rawsat-thm @{context} cterms in (Timing.result start, ! SAT .counter) end; i end

625 96 A decision procedure for universal multivari- ate real arithmetic with addition, multiplica- tion and ordering using semidefinite program- ming theory Sum-of-Squares imports Complex-Main begin

ML-file positivstellensatz.ML ML-file Sum-of-Squares/sum-of-squares.ML ML-file Sum-of-Squares/positivstellensatz-tools.ML ML-file Sum-of-Squares/sos-wrapper.ML end theory SOS imports ∼∼/src/HOL/Library/Sum-of-Squares begin lemma (3 ::real) ∗ x + 7 ∗ a < 4 & 3 < 2 ∗ x =⇒ a < 0 by sos lemma a1 ≥ 0 ∧ a2 ≥ 0 ∧ (a1 ∗ a1 + a2 ∗ a2 = b1 ∗ b1 + b2 ∗ b2 + 2 ) ∧ (a1 ∗ b1 + a2 ∗ b2 = 0 ) −→ a1 ∗ a2 − b1 ∗ b2 ≥ (0 ::real) by sos lemma (3 ::real) ∗ x + 7 ∗ a < 4 & 3 < 2 ∗ x −→ a < 0 by sos lemma (0 ::real) ≤ x ∧ x ≤ 1 ∧ 0 ≤ y ∧ y ≤ 1 −→ x 2 + y2 < 1 ∨ (x − 1 )2 + y2 < 1 ∨ x 2 + (y − 1 )2 < 1 ∨ (x − 1 )2 + (y − 1 )2 < 1 by sos lemma (0 ::real) ≤ x ∧ 0 ≤ y ∧ 0 ≤ z ∧ x + y + z ≤ 3 −→ x ∗ y + x ∗ z + y ∗ z ≥ 3 ∗ x ∗ y ∗ z by sos lemma (x::real)2 + y2 + z 2 = 1 −→ (x + y + z)2 ≤ 3 by sos lemma w 2 + x 2 + y2 + z 2 = 1 −→ (w + x + y + z)2 ≤ (4 ::real) by sos lemma (x::real) ≥ 1 ∧ y ≥ 1 −→ x ∗ y ≥ x + y − 1

626 by sos lemma (x::real) > 1 ∧ y > 1 −→ x ∗ y > x + y − 1 by sos lemma |x| ≤ 1 −→ |64 ∗ xˆ7 − 112 ∗ xˆ5 + 56 ∗ xˆ3 − 7 ∗ x| ≤ (1 ::real) by sos

One component of denominator in dodecahedral example. lemma 2 ≤ x ∧ x ≤ 125841 / 50000 ∧ 2 ≤ y ∧ y ≤ 125841 / 50000 ∧ 2 ≤ z ∧ z ≤ 125841 / 50000 −→ 2 ∗ (x ∗ z + x ∗ y + y ∗ z) − (x ∗ x + y ∗ y + z ∗ z) ≥ (0 ::real) by sos

Over a larger but simpler interval. lemma (2 ::real) ≤ x ∧ x ≤ 4 ∧ 2 ≤ y ∧ y ≤ 4 ∧ 2 ≤ z ∧ z ≤ 4 −→ 0 ≤ 2 ∗ (x ∗ z + x ∗ y + y ∗ z) − (x ∗ x + y ∗ y + z ∗ z) by sos

We can do 12. I think 12 is a sharp bound; see PP’s certificate. lemma 2 ≤ (x::real) ∧ x ≤ 4 ∧ 2 ≤ y ∧ y ≤ 4 ∧ 2 ≤ z ∧ z ≤ 4 −→ 12 ≤ 2 ∗ (x ∗ z + x ∗ y + y ∗ z) − (x ∗ x + y ∗ y + z ∗ z) by sos

Inequality from sci.math (see ”Leon-Sotelo, por favor”). lemma 0 ≤ (x::real) ∧ 0 ≤ y ∧ x ∗ y = 1 −→ x + y ≤ x 2 + y2 by sos lemma 0 ≤ (x::real) ∧ 0 ≤ y ∧ x ∗ y = 1 −→ x ∗ y ∗ (x + y) ≤ x 2 + y2 by sos lemma 0 ≤ (x::real) ∧ 0 ≤ y −→ x ∗ y ∗ (x + y)2 ≤ (x 2 + y2)2 by sos lemma (0 ::real) ≤ a ∧ 0 ≤ b ∧ 0 ≤ c ∧ c ∗ (2 ∗ a + b)ˆ3 / 27 ≤ x −→ c ∗ a2 ∗ b ≤ x by sos lemma (0 ::real) < x −→ 0 < 1 + x + x 2 by sos lemma (0 ::real) ≤ x −→ 0 < 1 + x + x 2 by sos lemma (0 ::real) < 1 + x 2 by sos lemma (0 ::real) ≤ 1 + 2 ∗ x + x 2

627 by sos lemma (0 ::real) < 1 + |x| by sos lemma (0 ::real) < 1 + (1 + x)2 ∗ |x| by sos lemma |(1 ::real) + x 2| = (1 ::real) + x 2 by sos lemma (3 ::real) ∗ x + 7 ∗ a < 4 ∧ 3 < 2 ∗ x −→ a < 0 by sos lemma (0 ::real) < x −→ 1 < y −→ y ∗ x ≤ z −→ x < z by sos lemma (1 ::real) < x −→ x 2 < y −→ 1 < y by sos lemma (b::real)2 < 4 ∗ a ∗ c −→ a ∗ x 2 + b ∗ x + c 6= 0 by sos lemma (b::real)2 < 4 ∗ a ∗ c −→ a ∗ x 2 + b ∗ x + c 6= 0 by sos lemma (a::real) ∗ x 2 + b ∗ x + c = 0 −→ b2 ≥ 4 ∗ a ∗ c by sos lemma (0 ::real) ≤ b ∧ 0 ≤ c ∧ 0 ≤ x ∧ 0 ≤ y ∧ x 2 = c ∧ y2 = a2 ∗ c + b −→ a ∗ c ≤ y ∗ x by sos lemma |x − z| ≤ e ∧ |y − z| ≤ e ∧ 0 ≤ u ∧ 0 ≤ v ∧ u + v = 1 −−> |(u ∗ x + v ∗ y) − z| ≤ (e::real) by sos lemma (x::real) − y − 2 ∗ xˆ4 = 0 ∧ 0 ≤ x ∧ x ≤ 2 ∧ 0 ≤ y ∧ y ≤ 3 −→ y2 − 7 ∗ y − 12 ∗ x + 17 ≥ 0 oops lemma (0 ::real) ≤ x −→ (1 + x + x 2) / (1 + x 2) ≤ 1 + x by sos lemma (0 ::real) ≤ x −→ 1 − x ≤ 1 / (1 + x + x 2) by sos lemma (x::real) ≤ 1 / 2 −→ − x − 2 ∗ x 2 ≤ − x / (1 − x)

628 by sos lemma 4 ∗ r 2 = p2 − 4 ∗ q ∧ r ≥ (0 ::real) ∧ x 2 + p ∗ x + q = 0 −→ 2 ∗ (x::real) = − p + 2 ∗ r ∨ 2 ∗ x = − p − 2 ∗ r by sos end theory SOS-Cert imports ∼∼/src/HOL/Library/Sum-of-Squares begin lemma (3 ::real) ∗ x + 7 ∗ a < 4 ∧ 3 < 2 ∗ x =⇒ a < 0 by (sos ((R<1 + (((A<1 ∗ R<1 ) ∗ (R<2 ∗ [1 ]ˆ2 )) + (((A<0 ∗ R<1 ) ∗ (R<3 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<14 ∗ [1 ]ˆ2 ))))))) lemma a1 ≥ 0 ∧ a2 ≥ 0 ∧ (a1 ∗ a1 + a2 ∗ a2 = b1 ∗ b1 + b2 ∗ b2 + 2 ) ∧ (a1 ∗ b1 + a2 ∗ b2 = 0 ) −→ a1 ∗ a2 − b1 ∗ b2 ≥ (0 ::real) by (sos (((A<0 ∗ R<1 ) + (([∼1 /2 ∗a1 ∗b2 + ∼1 /2 ∗a2 ∗b1 ] ∗ A=0 ) + (([∼1 /2 ∗a1 ∗a2 + 1 /2 ∗b1 ∗b2 ] ∗ A=1 ) + (((A<0 ∗ R<1 ) ∗ ((R<1 /2 ∗ [b2 ]ˆ2 ) + (R<1 /2 ∗ [b1 ]ˆ2 ))) + ((A<=0 ∗ (A<=1 ∗ R<1 )) ∗ ((R<1 /2 ∗ [b2 ]ˆ2 ) + ((R<1 /2 ∗ [b1 ]ˆ2 ) + ((R<1 /2 ∗ [a2 ]ˆ2 ) + (R<1 /2 ∗ [a1 ]ˆ2 ))))))))))) lemma (3 ::real) ∗ x + 7 ∗ a < 4 ∧ 3 < 2 ∗ x −→ a < 0 by (sos ((R<1 + (((A<1 ∗ R<1 ) ∗ (R<2 ∗ [1 ]ˆ2 )) + (((A<0 ∗ R<1 ) ∗ (R<3 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<14 ∗ [1 ]ˆ2 ))))))) lemma (0 ::real) ≤ x ∧ x ≤ 1 ∧ 0 ≤ y ∧ y ≤ 1 −→ x 2 + y2 < 1 ∨ (x − 1 )2 + y2 < 1 ∨ x 2 + (y − 1 )2 < 1 ∨ (x − 1 )2 + (y − 1 )2 < 1 by (sos ((R<1 + (((A<=3 ∗ (A<=4 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ (A<=7 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + (((A<=1 ∗ (A<=6 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ (A<=5 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )))))))) lemma (0 ::real) ≤ x ∧ 0 ≤ y ∧ 0 ≤ z ∧ x + y + z ≤ 3 −→ x ∗ y + x ∗ z + y ∗ z ≥ 3 ∗ x ∗ y ∗ z by (sos (((A<0 ∗ R<1 ) + (((A<0 ∗ R<1 ) ∗ (R<1 /2 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ R<1 ) ∗ (R<1 /2 ∗ [∼1 ∗x + y]ˆ2 )) + (((A<=1 ∗ R<1 ) ∗ (R<1 /2 ∗ [∼1 ∗x + z]ˆ2 )) + (((A<=1 ∗ (A<=2 ∗ (A<=3 ∗ R<1 ))) ∗ (R<1 /2 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ R<1 ) ∗ (R<1 /2 ∗ [∼1 ∗y + z]ˆ2 )) + (((A<=0 ∗ (A<=2 ∗ (A<=3 ∗ R<1 ))) ∗ (R<1 /2 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ (A<=1 ∗ (A<=3 ∗ R<1 ))) ∗ (R<1 /2 ∗ [1 ]ˆ2 ))))))))))) lemma (x::real)2 + y2 + z 2 = 1 −→ (x + y + z)2 ≤ 3 by (sos (((A<0 ∗ R<1 ) + (([∼3 ] ∗ A=0 ) + (R<1 ∗ ((R<2 ∗ [∼1 /2 ∗x + ∼1 /2 ∗y + z]ˆ2 ) + (R<3 /2 ∗ [∼1 ∗x + y]ˆ2 )))))))

629 lemma w 2 + x 2 + y2 + z 2 = 1 −→ (w + x + y + z)2 ≤ (4 ::real) by (sos (((A<0 ∗ R<1 ) + (([∼4 ] ∗ A=0 ) + (R<1 ∗ ((R<3 ∗ [∼1 /3 ∗w + ∼1 /3 ∗x + ∼1 /3 ∗y + z]ˆ2 ) + ((R<8 /3 ∗ [∼1 /2 ∗w + ∼1 /2 ∗x + y]ˆ2 ) + (R<2 ∗ [∼1 ∗w + x]ˆ2 )))))))) lemma (x::real) ≥ 1 ∧ y ≥ 1 −→ x ∗ y ≥ x + y − 1 by (sos (((A<0 ∗ R<1 ) + ((A<=0 ∗ (A<=1 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 ))))) lemma (x::real) > 1 ∧ y > 1 −→ x ∗ y > x + y − 1 by (sos ((((A<0 ∗ A<1 ) ∗ R<1 ) + ((A<=0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 ))))) lemma |x| ≤ 1 −→ |64 ∗ xˆ7 − 112 ∗ xˆ5 + 56 ∗ xˆ3 − 7 ∗ x| ≤ (1 ::real) by (sos ((((A<0 ∗ R<1 ) + ((A<=1 ∗ R<1 ) ∗ (R<1 ∗ [∼8 ∗xˆ3 + ∼4 ∗xˆ2 + 4 ∗x + 1 ]ˆ2 )))) & ((((A<0 ∗ A<1 ) ∗ R<1 ) + ((A<=1 ∗ (A<0 ∗ R<1 )) ∗ (R<1 ∗ [8 ∗xˆ3 + ∼4 ∗xˆ2 + ∼4 ∗x + 1 ]ˆ2 )))))) One component of denominator in dodecahedral example. lemma 2 ≤ x ∧ x ≤ 125841 / 50000 ∧ 2 ≤ y ∧ y ≤ 125841 / 50000 ∧ 2 ≤ z ∧ z ≤ 125841 / 50000 −→ 2 ∗ (x ∗ z + x ∗ y + y ∗ z) − (x ∗ x + y ∗ y + z ∗ z) ≥ (0 ::real) by (sos (((A<0 ∗ R<1 ) + ((R<1 ∗ ((R<5749028157 /5000000000 ∗ [∼25000 /222477 ∗x + ∼25000 /222477 ∗y + ∼25000 /222477 ∗z + 1 ]ˆ2 ) + ((R<864067 /1779816 ∗ [419113 /864067 ∗x + 419113 /864067 ∗y + z]ˆ2 ) + ((R<320795 /864067 ∗ [419113 /1283180 ∗x + y]ˆ2 ) + (R<1702293 /5132720 ∗ [x]ˆ2 ))))) + (((A<=4 ∗ (A<=5 ∗ R<1 )) ∗ (R<3 /2 ∗ [1 ]ˆ2 )) + (((A<=3 ∗ (A<=5 ∗ R<1 )) ∗ (R<1 /2 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ (A<=4 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ (A<=3 ∗ R<1 )) ∗ (R<3 /2 ∗ [1 ]ˆ2 )) + (((A<=1 ∗ (A<=5 ∗ R<1 )) ∗ (R<1 /2 ∗ [1 ]ˆ2 )) + (((A<=1 ∗ (A<=3 ∗ R<1 )) ∗ (R<1 /2 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ (A<=4 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ (A<=2 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ (A<=1 ∗ R<1 )) ∗ (R<3 /2 ∗ [1 ]ˆ2 )))))))))))))) Over a larger but simpler interval. lemma (2 ::real) ≤ x ∧ x ≤ 4 ∧ 2 ≤ y ∧ y ≤ 4 ∧ 2 ≤ z ∧ z ≤ 4 −→ 0 ≤ 2 ∗ (x ∗ z + x ∗ y + y ∗ z) − (x ∗ x + y ∗ y + z ∗ z) by (sos ((R<1 + ((R<1 ∗ ((R<1 ∗ [∼1 /6 ∗x + ∼1 /6 ∗y + ∼1 /6 ∗z + 1 ]ˆ2 ) + ((R<1 /18 ∗ [∼1 /2 ∗x + ∼1 /2 ∗y + z]ˆ2 ) + (R<1 /24 ∗ [∼1 ∗x + y]ˆ2 )))) + (((A<0 ∗ R<1 ) ∗ (R<1 /12 ∗ [1 ]ˆ2 )) + (((A<=4 ∗ (A<=5 ∗ R<1 )) ∗ (R<1 /6 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ (A<=4 ∗ R<1 )) ∗ (R<1 /6 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ (A<=3 ∗ R<1 )) ∗ (R<1 /6 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ (A<=4 ∗ R<1 )) ∗ (R<1 /6 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ (A<=2 ∗ R<1 )) ∗ (R<1 /6 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ (A<=1 ∗ R<1 )) ∗ (R<1 /6 ∗ [1 ]ˆ2 )))))))))))) We can do 12. I think 12 is a sharp bound; see PP’s certificate. lemma 2 ≤ (x::real) ∧ x ≤ 4 ∧ 2 ≤ y ∧ y ≤ 4 ∧ 2 ≤ z ∧ z ≤ 4 −→ 12 ≤ 2 ∗ (x ∗ z + x ∗ y + y ∗ z) − (x ∗ x + y ∗ y + z ∗ z) by (sos (((A<0 ∗ R<1 ) + (((A<=4 ∗ R<1 ) ∗ (R<2 /3 ∗ [1 ]ˆ2 )) + (((A<=4 ∗ (A<=5 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + (((A<=3 ∗ (A<=4 ∗ R<1 )) ∗ (R<1 /3 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ R<1 ) ∗ (R<2 /3 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ (A<=5 ∗ R<1 )) ∗ (R<1 /3 ∗ [1 ]ˆ2 )) + (((A<=2 ∗ (A<=4 ∗ R<1 )) ∗ (R<8 /3 ∗ [1 ]ˆ2 )) + (((A<=2

630 ∗ (A<=3 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + (((A<=1 ∗ (A<=4 ∗ R<1 )) ∗ (R<1 /3 ∗ [1 ]ˆ2 )) + (((A<=1 ∗ (A<=2 ∗ R<1 )) ∗ (R<1 /3 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ R<1 ) ∗ (R<2 /3 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ (A<=5 ∗ R<1 )) ∗ (R<1 /3 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ (A<=4 ∗ R<1 )) ∗ (R<8 /3 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ (A<=3 ∗ R<1 )) ∗ (R<1 /3 ∗ [1 ]ˆ2 )) + (((A<=0 ∗ (A<=2 ∗ R<1 )) ∗ (R<8 /3 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ (A<=1 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )))))))))))))))))))

Inequality from sci.math (see ”Leon-Sotelo, por favor”). lemma 0 ≤ (x::real) ∧ 0 ≤ y ∧ x ∗ y = 1 −→ x + y ≤ x 2 + y2 by (sos (((A<0 ∗ R<1 ) + (([1 ] ∗ A=0 ) + (R<1 ∗ ((R<1 ∗ [∼1 /2 ∗x + ∼1 /2 ∗y + 1 ]ˆ2 ) + (R<3 /4 ∗ [∼1 ∗x + y]ˆ2 ))))))) lemma 0 ≤ (x::real) ∧ 0 ≤ y ∧ x ∗ y = 1 −→ x ∗ y ∗ (x + y) ≤ x 2 + y2 by (sos (((A<0 ∗ R<1 ) + (([∼1 ∗x + ∼1 ∗y + 1 ] ∗ A=0 ) + (R<1 ∗ ((R<1 ∗ [∼1 /2 ∗x + ∼1 /2 ∗y + 1 ]ˆ2 ) + (R<3 /4 ∗ [∼1 ∗x + y]ˆ2 ))))))) lemma 0 ≤ (x::real) ∧ 0 ≤ y −→ x ∗ y ∗ (x + y)2 ≤ (x 2 + y2)2 by (sos (((A<0 ∗ R<1 ) + (R<1 ∗ ((R<1 ∗ [∼1 /2 ∗xˆ2 + yˆ2 + ∼1 /2 ∗x∗y]ˆ2 ) + (R<3 /4 ∗ [∼1 ∗xˆ2 + x∗y]ˆ2 )))))) lemma (0 ::real) ≤ a ∧ 0 ≤ b ∧ 0 ≤ c ∧ c ∗ (2 ∗ a + b)ˆ3 / 27 ≤ x −→ c ∗ a2 ∗ b ≤ x by (sos (((A<0 ∗ R<1 ) + (((A<=3 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )) + (((A<=1 ∗ (A<=2 ∗ R<1 )) ∗ (R<1 /27 ∗ [∼1 ∗a + b]ˆ2 )) + ((A<=0 ∗ (A<=2 ∗ R<1 )) ∗ (R<8 /27 ∗ [∼1 ∗a + b]ˆ2 ))))))) lemma (0 ::real) < x −→ 0 < 1 + x + x 2 by (sos ((R<1 + ((R<1 ∗ (R<1 ∗ [x]ˆ2 )) + (((A<0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 ))))))) lemma (0 ::real) ≤ x −→ 0 < 1 + x + x 2 by (sos ((R<1 + ((R<1 ∗ (R<1 ∗ [x]ˆ2 )) + (((A<=1 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 ))))))) lemma (0 ::real) < 1 + x 2 by (sos ((R<1 + ((R<1 ∗ (R<1 ∗ [x]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )))))) lemma (0 ::real) ≤ 1 + 2 ∗ x + x 2 by (sos (((A<0 ∗ R<1 ) + (R<1 ∗ (R<1 ∗ [x + 1 ]ˆ2 ))))) lemma (0 ::real) < 1 + |x| by (sos ((R<1 + (((A<=1 ∗ R<1 ) ∗ (R<1 /2 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<1 /2 ∗ [1 ]ˆ2 )))))) lemma (0 ::real) < 1 + (1 + x)2 ∗ |x| by (sos (((R<1 + (((A<=1 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<1 ∗ [x + 1 ]ˆ2 ))))) & ((R<1 + (((A<0 ∗ R<1 ) ∗ (R<1 ∗ [x + 1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )))))))

631 lemma |(1 ::real) + x 2| = (1 ::real) + x 2 by (sos (() & (((R<1 + ((R<1 ∗ (R<1 ∗ [x]ˆ2 )) + ((A<1 ∗ R<1 ) ∗ (R<1 /2 ∗ [1 ]ˆ2 ))))) & ((R<1 + ((R<1 ∗ (R<1 ∗ [x]ˆ2 )) + ((A<0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )))))))) lemma (3 ::real) ∗ x + 7 ∗ a < 4 ∧ 3 < 2 ∗ x −→ a < 0 by (sos ((R<1 + (((A<1 ∗ R<1 ) ∗ (R<2 ∗ [1 ]ˆ2 )) + (((A<0 ∗ R<1 ) ∗ (R<3 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<14 ∗ [1 ]ˆ2 ))))))) lemma (0 ::real) < x −→ 1 < y −→ y ∗ x ≤ z −→ x < z by (sos ((((A<0 ∗ A<1 ) ∗ R<1 ) + (((A<=1 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )))))) lemma (1 ::real) < x −→ x 2 < y −→ 1 < y by (sos ((((A<0 ∗ A<1 ) ∗ R<1 ) + ((R<1 ∗ ((R<1 /10 ∗ [∼2 ∗x + y + 1 ]ˆ2 ) + (R<1 /10 ∗ [∼1 ∗x + y]ˆ2 ))) + (((A<1 ∗ R<1 ) ∗ (R<1 /2 ∗ [1 ]ˆ2 )) + (((A<0 ∗ R<1 ) ∗ (R<1 ∗ [x]ˆ2 )) + (((A<=0 ∗ R<1 ) ∗ ((R<1 /10 ∗ [x + 1 ]ˆ2 ) + (R<1 /10 ∗ [x]ˆ2 ))) + (((A<=0 ∗ (A<1 ∗ R<1 )) ∗ (R<1 /5 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ (A<0 ∗ R<1 )) ∗ (R<1 /5 ∗ [1 ]ˆ2 )))))))))) lemma (b::real)2 < 4 ∗ a ∗ c −→ a ∗ x 2 + b ∗ x + c 6= 0 by (sos (((A<0 ∗ R<1 ) + (R<1 ∗ (R<1 ∗ [2 ∗a∗x + b]ˆ2 ))))) lemma (b::real)2 < 4 ∗ a ∗ c −→ a ∗ xˆ2 + b ∗ x + c 6= 0 by (sos (((A<0 ∗ R<1 ) + (R<1 ∗ (R<1 ∗ [2 ∗a∗x + b]ˆ2 ))))) lemma (a::real) ∗ x 2 + b ∗ x + c = 0 −→ b2 ≥ 4 ∗ a ∗ c by (sos (((A<0 ∗ R<1 ) + (R<1 ∗ (R<1 ∗ [2 ∗a∗x + b]ˆ2 ))))) lemma (0 ::real) ≤ b ∧ 0 ≤ c ∧ 0 ≤ x ∧ 0 ≤ y ∧ x 2 = c ∧ y2 = a2 ∗ c + b −→ a ∗ c ≤ y ∗ x by (sos (((A<0 ∗ (A<0 ∗ R<1 )) + (((A<=2 ∗ (A<=3 ∗ (A<0 ∗ R<1 ))) ∗ (R<2 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ (A<=1 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )))))) lemma |x − z| ≤ e ∧ |y − z| ≤ e ∧ 0 ≤ u ∧ 0 ≤ v ∧ u + v = 1 −→ |(u ∗ x + v ∗ y) − z| ≤ (e::real) by (sos ((((A<0 ∗ R<1 ) + (((A<=3 ∗ (A<=6 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=1 ∗ (A<=5 ∗ R<1 )) ∗ (R<1 ∗ [1 ]ˆ2 ))))) & ((((A<0 ∗ A<1 ) ∗ R<1 ) + (((A<=3 ∗ (A<=5 ∗ (A<0 ∗ R<1 ))) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=1 ∗ (A<=4 ∗ (A<0 ∗ R<1 ))) ∗ (R<1 ∗ [1 ]ˆ2 ))))))) lemma (x::real) − y − 2 ∗ xˆ4 = 0 ∧ 0 ≤ x ∧ x ≤ 2 ∧ 0 ≤ y ∧ y ≤ 3 −→ y2 − 7 ∗ y − 12 ∗ x + 17 ≥ 0 oops lemma (0 ::real) ≤ x −→ (1 + x + x 2) / (1 + x 2) ≤ 1 + x

632 by (sos (((((A<0 ∗ A<1 ) ∗ R<1 ) + ((A<=0 ∗ (A<0 ∗ R<1 )) ∗ (R<1 ∗ [x]ˆ2 )))) & ((R<1 + ((R<1 ∗ (R<1 ∗ [x]ˆ2 )) + ((A<0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 ))))))) lemma (0 ::real) ≤ x −→ 1 − x ≤ 1 / (1 + x + x 2) by (sos (((R<1 + (([∼4 /3 ] ∗ A=0 ) + ((R<1 ∗ ((R<1 /3 ∗ [3 /2 ∗x + 1 ]ˆ2 ) + (R<7 /12 ∗ [x]ˆ2 ))) + ((A<=0 ∗ R<1 ) ∗ (R<1 /3 ∗ [1 ]ˆ2 )))))) & (((((A<0 ∗ A<1 ) ∗ R<1 ) + ((A<=0 ∗ (A<0 ∗ R<1 )) ∗ (R<1 ∗ [x]ˆ2 )))) & ((R<1 + ((R<1 ∗ (R<1 ∗ [x]ˆ2 )) + (((A<0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 )) + ((A<=0 ∗ R<1 ) ∗ (R<1 ∗ [1 ]ˆ2 ))))))))) lemma (x::real) ≤ 1 / 2 −→ − x − 2 ∗ x 2 ≤ − x / (1 − x) by (sos ((((A<0 ∗ A<1 ) ∗ R<1 ) + ((A<=0 ∗ (A<0 ∗ R<1 )) ∗ (R<1 ∗ [x]ˆ2 ))))) lemma 4 ∗ r 2 = p2 − 4 ∗ q ∧ r ≥ (0 ::real) ∧ x 2 + p ∗ x + q = 0 −→ 2 ∗ (x::real) = − p + 2 ∗ r ∨ 2 ∗ x = − p − 2 ∗ r by (sos ((((((A<0 ∗ A<1 ) ∗ R<1 ) + ([∼4 ] ∗ A=0 ))) & ((((A<0 ∗ A<1 ) ∗ R<1 ) + ([4 ] ∗ A=0 )))) & (((((A<0 ∗ A<1 ) ∗ R<1 ) + ([4 ] ∗ A=0 ))) & ((((A<0 ∗ A<1 ) ∗ R<1 ) + ([∼4 ] ∗ A=0 )))))) end

97 Bertrand’s Ballot Theorem theory Ballot imports Complex-Main ∼∼/src/HOL/Library/FuncSet begin

97.1 Preliminaries lemma card-bij 0: assumes f ∈ A → B Vx. x ∈ A =⇒ g (f x) = x and g ∈ B → A Vx. x ∈ B =⇒ f (g x) = x shows card A = card B apply (rule bij-betw-same-card) apply (rule bij-betwI ) apply fact+ done

97.2 Formalization of Problem Statement 97.2.1 Basic Definitions datatype vote = A | B definition

633 all-countings a b = card {f ∈ {1 .. a + b} →E {A, B}. card {x ∈ {1 .. a + b}. f x = A} = a ∧ card {x ∈ {1 .. a + b}. f x = B} = b} definition valid-countings a b = card {f ∈{1 ..a+b} →E {A, B}. card {x∈{1 ..a+b}. f x = A} = a ∧ card {x∈{1 ..a+b}. f x = B} = b ∧ (∀ m∈{1 ..a+b}. card {x∈{1 ..m}. f x = A} > card {x∈{1 ..m}. f x = B})}

97.2.2 Equivalence with Set Cardinality lemma Collect-on-transfer: assumes rel-set R X Y shows rel-fun (rel-fun R op =) (rel-set R)(λP. {x∈X . P x})(λP. {y∈Y . P y}) using assms unfolding rel-fun-def rel-set-def by fast lemma rel-fun-trans: rel-fun P Q g g 0 =⇒ rel-fun R P f f 0 =⇒ rel-fun R Q (λx. g (f x)) (λy. g 0 (f 0 y)) by (auto simp: rel-fun-def ) lemma rel-fun-trans2 : rel-fun P1 (rel-fun P2 Q) g g 0 =⇒ rel-fun R P1 f1 f1 0 =⇒ rel-fun R P2 f2 f2 0 =⇒ rel-fun R Q (λx. g (f1 x)(f2 x)) (λy. g 0 (f1 0 y)(f2 0 y)) by (auto simp: rel-fun-def ) lemma rel-fun-trans2 0: rel-fun R (op =) f1 f1 0 =⇒ rel-fun R (op =) f2 f2 0 =⇒ rel-fun R (op =) (λx. g (f1 x)(f2 x)) (λy. g (f1 0 y)(f2 0 y)) by (auto simp: rel-fun-def ) lemma rel-fun-const: rel-fun R (op =) (λx. a)(λy. a) by auto lemma rel-fun-conj : rel-fun R (op =) f f 0 =⇒ rel-fun R (op =) g g 0 =⇒ rel-fun R (op =) (λx. f x ∧ g x)(λy. f 0 y ∧ g 0 y) by (auto simp: rel-fun-def ) lemma rel-fun-ball: (Vi. i ∈ I =⇒ rel-fun R (op =) (f i)(f 0 i)) =⇒ rel-fun R (op =) (λx. ∀ i∈I . f i x)(λy. ∀ i∈I . f 0 i y) by (auto simp: rel-fun-def rel-set-def ) lemma shows all-countings-set: all-countings a b = card {V ∈Pow {0 ..

634 and valid-countings-set: valid-countings a b = card {V ∈Pow {0 .. m − card ({0 ..

define R where R f V ←→ V ⊆ {0 ..

have f ∈ extensional {1 ..a + b} =⇒ ∃ V ∈Pow {0 ..

have P: rel-fun R (rel-fun P op =) (λf x. f x = A)(λV y. y ∈ V ) by (auto simp: P-def R-def Suc-le-eq gr0-conv-Suc rel-fun-def )

have eq-B: x = B ←→ x 6= A for x by (cases x; simp)

{ fix f and m :: nat have card {x∈{1 ..m}. f x = B} = card ({1 ..m} − {x∈{1 ..m}. f x = A}) by (simp add: eq-B set-diff-eq cong: conj-cong) also have ... = m − card {x∈{1 ..m}. f x = A} by (subst card-Diff-subset) auto finally have card {x∈{1 ..m}. f x = B} = m − card {x∈{1 ..m}. f x = A} . }

635 note card-B = this

note transfers = rel-fun-const card-transfer[THEN rel-funD, OF unique-R] rel-fun-conj rel-fun-ball Collect-on-transfer[THEN rel-funD, OF total-R] Collect-on-transfer[THEN rel-funD, OF total-P] rel-fun-trans[OF card-transfer, OF unique-P] rel-fun-trans[OF Collect-on-transfer[OF total-P]] rel-fun-trans2 0[where g=op =] rel-fun-trans2 0[where g=op <] rel-fun-trans2 0[where g=op −]

have all-countings a b = card {f ∈ extensional {1 ..a + b}. card {x ∈ {1 ..a + b}. f x = A} = a} using card-B by (simp add: all-countings-def PiE-iff vote.nchotomy cong: conj-cong) also have ... = card {V ∈Pow {0 ..

have valid-countings a b = card {f ∈extensional {1 ..a+b}. card {x∈{1 ..a+b}. f x = A} = a ∧ (∀ m∈{1 ..a+b}. card {x∈{1 ..m}. f x = A} > m − card {x∈{1 ..m}. f x = A})} using card-B by (simp add: valid-countings-def PiE-iff vote.nchotomy cong: conj-cong) also have ... = card {V ∈Pow {0 .. m − card {x∈{0 ..

97.3 Facts About valid-countings 97.3.1 Non-Recursive Cases lemma card-V-eq-a: V ⊆ {0 ..

636 lemma Ico-subset-finite: i ⊆ {a ..< b::nat} =⇒ finite i by (auto dest: finite-subset) lemma Icc-Suc2 : a ≤ b =⇒ {a..Suc b} = insert (Suc b) {a..b} by auto lemma Ico-Suc2 : a ≤ b =⇒ {a..

637 by auto show ?Q V (Suc ?l) = ?Q V (Suc a + b) using hb

have Suc a ∗ (a − Suc b) + (Suc a − b) ∗ Suc b = (Suc a ∗ a − Suc a ∗ Suc b) + (Suc a ∗ Suc b − Suc b ∗ b) by (simp add: sign-simps) also have ... = (Suc a ∗ a + (Suc a ∗ Suc b − Suc b ∗ b)) − Suc a ∗ Suc b using hb

have (Suc a ∗ Suc (a + b)) ∗ ((Suc a + Suc b) ∗ valid-countings (Suc a) (Suc b)) = (Suc a + Suc b) ∗ Suc a ∗ ((a + Suc b) ∗ valid-countings a (Suc b) + (Suc a + b) ∗ valid-countings (Suc a) b) unfolding valid-countings-Suc-Suc[OF hb < a i] by (simp add: field-simps) also have ... = (Suc a + Suc b) ∗ ((a − Suc b) ∗ (Suc a ∗ (Suc (a + b) choose a)) + (Suc a − b) ∗ (Suc a ∗ (Suc (a + b) choose Suc a))) unfolding Suc-a Suc-b by (simp add: field-simps)

638 also have ... = (Suc a ∗ (a − Suc b) + (Suc a − b) ∗ Suc b) ∗ (Suc (Suc a + b) ∗ (Suc a + b choose a)) unfolding Suc-times-binomial-add by (simp add: field-simps) also have ... = Suc a ∗ (Suc a ∗ (a − Suc b) + (Suc a − b) ∗ Suc b) ∗ (Suc a + Suc b choose Suc a) unfolding Suc-times-binomial-eq by (simp add: field-simps) also have ... = (Suc a ∗ Suc (a + b)) ∗ ((Suc a − Suc b) ∗ (Suc a + Suc b choose Suc a)) unfolding rearrange by (simp only: mult-ac) finally show ?thesis unfolding mult-cancel1 by simp qed qed (simp add: valid-countings-a-0 ) qed lemma valid-countings-eq[code]: valid-countings a b = (if a + b = 0 then 1 else ((a − b) ∗ ((a + b) choose a)) div (a + b)) by (simp add: valid-countings[symmetric] valid-countings-a-0 )

97.4 Relation Between valid-countings and all-countings lemma main-nat:(a + b) ∗ valid-countings a b = (a − b) ∗ all-countings a b unfolding valid-countings all-countings .. lemma main-real: assumes b < a shows valid-countings a b = (a − b) / (a + b) ∗ all-countings a b using assms proof − from main-nat[of a b] hb < a i have (real a + real b) ∗ real (valid-countings a b) = (real a − real b) ∗ real (all-countings a b) by (simp only: of-nat-add[symmetric] of-nat-mult[symmetric]) auto from this hb < a i show ?thesis by (subst mult-left-cancel[of real a + real b, symmetric]) auto qed lemma valid-countings a b = (if a ≤ b then (if b = 0 then 1 else 0 ) else (a − b) / (a + b) ∗ all-countings a b) proof (cases a ≤ b) case False from this show ?thesis by (simp add: main-real) next case True from this show ?thesis by (auto simp add: valid-countings-a-0 all-countings valid-countings-eq-zero) qed

639 97.4.1 Executable Definition declare all-countings-def [code del] declare all-countings[code] value all-countings 1 0 value all-countings 0 1 value all-countings 1 1 value all-countings 2 1 value all-countings 1 2 value all-countings 2 4 value all-countings 4 2

97.4.2 Executable Definition declare valid-countings-def [code del] value valid-countings 1 0 value valid-countings 0 1 value valid-countings 1 1 value valid-countings 2 1 value valid-countings 1 2 value valid-countings 2 4 value valid-countings 4 2 end

98 The Erdoes-Szekeres Theorem theory Erdoes-Szekeres imports Main begin

98.1 Addition to Lattices-Big Theory lemma Max-gr: assumes finite A assumes a ∈ A a > x shows x < Max A using assms Max-ge less-le-trans by blast

98.2 Additions to Finite-Set Theory lemma obtain-subset-with-card-n: assumes n ≤ card S obtains T where T ⊆ S card T = n proof − from assms obtain n 0 where card S = n + n 0 by (metis le-add-diff-inverse) from this that show ?thesis proof (induct n 0 arbitrary: S)

640 case 0 from this show ?case by auto next case Suc from this show ?case by (simp add: card-Suc-eq)(metis subset-insertI2 ) qed qed lemma exists-set-with-max-card: assumes finite S S 6= {} shows ∃ s ∈ S. card s = Max (card ‘ S) using assms proof (induct S rule: finite.induct) case (insertI S 0 s 0) show ?case proof (cases S 0 6= {}) case True from this insertI .hyps(2 ) obtain s where s: s ∈ S 0 card s = Max (card ‘ S 0) by auto from this(1 ) have that:(if card s ≥ card s 0 then s else s 0) ∈ insert s 0 S 0 by auto have card (if card s ≥ card s 0 then s else s 0) = Max (card ‘ insert s 0 S 0) 0 using insertI (1 ) hS 6= {}i s by auto from this that show ?thesis by blast qed (auto) qed (auto)

98.3 Definition of Monotonicity over a Carrier Set definition mono-on f R S = (∀ i∈S. ∀ j ∈S. i ≤ j −→ R (f i)(f j )) lemma mono-on-empty [simp]: mono-on f R {} unfolding mono-on-def by auto lemma mono-on-singleton [simp]: reflp R =⇒ mono-on f R {x} unfolding mono-on-def reflp-def by auto lemma mono-on-subset: T ⊆ S =⇒ mono-on f R S =⇒ mono-on f R T unfolding mono-on-def by (simp add: subset-iff ) lemma not-mono-on-subset: T ⊆ S =⇒ ¬ mono-on f R T =⇒ ¬ mono-on f R S unfolding mono-on-def by blast lemma [simp]: reflp (op ≤ :: 0a::order ⇒ - ⇒ bool) reflp (op ≥ :: 0a::order ⇒ - ⇒ bool) transp (op ≤ :: 0a::order ⇒ - ⇒ bool) transp (op ≥ :: 0a::order ⇒ - ⇒ bool) unfolding reflp-def transp-def by auto

641 98.4 The Erdoes-Szekeres Theorem following Seidenberg’s (1959) argument lemma Erdoes-Szekeres: fixes f :: - ⇒ 0a::linorder shows (∃ S. S ⊆ {0 ..m ∗ n} ∧ card S = m + 1 ∧ mono-on f (op ≤) S) ∨ (∃ S. S ⊆ {0 ..m ∗ n} ∧ card S = n + 1 ∧ mono-on f (op ≥) S) proof (rule ccontr) let ?max-subseq = λR k. Max (card ‘ {S. S ⊆ {0 ..k} ∧ mono-on f R S ∧ k ∈ S}) define phi where phi k = (?max-subseq (op ≤) k, ?max-subseq (op ≥) k) for k

have one-member: VR k. reflp R =⇒ {k} ∈ {S. S ⊆ {0 ..k} ∧ mono-on f R S ∧ k ∈ S} by auto

{ fix R assume reflp: reflp (R :: 0a::linorder ⇒ -) from one-member[OF this] have non-empty: Vk. {S. S ⊆ {0 ..k} ∧ mono-on f R S ∧ k ∈ S}= 6 {} by force from one-member[OF reflp] have Vk. card {k} ∈ card ‘ {S. S ⊆ {0 ..k} ∧ mono-on f R S ∧ k ∈ S} by blast from this have lower-bound: Vk. k ≤ m ∗ n =⇒ ?max-subseq R k ≥ 1 by (auto intro!: Max-ge)

fix b assume not-mono-at: ∀ S. S ⊆ {0 ..m ∗ n} ∧ card S = b + 1 −→ ¬ mono-on f R S

{ fix S assume S ⊆ {0 ..m ∗ n} card S ≥ b + 1 moreover from hcard S ≥ b + 1 i obtain T where T ⊆ S ∧ card T = Suc b using obtain-subset-with-card-n by (metis Suc-eq-plus1 ) ultimately have ¬ mono-on f R S using not-mono-at by (auto dest: not-mono-on-subset) } from this have ∀ S. S ⊆ {0 ..m ∗ n} ∧ mono-on f R S −→ card S ≤ b by (metis Suc-eq-plus1 Suc-leI not-le) from this have Vk. k ≤ m ∗ n =⇒ ∀ S. S ⊆ {0 ..k} ∧ mono-on f R S −→ card S ≤ b using order-trans by force from this non-empty have upper-bound: Vk. k ≤ m ∗ n =⇒ ?max-subseq R k ≤ b by (auto intro: Max.boundedI )

from upper-bound lower-bound have Vk. k ≤ m ∗ n =⇒ 1 ≤ ?max-subseq R k ∧ ?max-subseq R k ≤ b by auto

642 } note bounds = this

assume contraposition: ¬ ?thesis from contraposition bounds[of op ≤ m] bounds[of op ≥ n] have Vk. k ≤ m ∗ n =⇒ 1 ≤ ?max-subseq (op ≤) k ∧ ?max-subseq (op ≤) k ≤ m and Vk. k ≤ m ∗ n =⇒ 1 ≤ ?max-subseq (op ≥) k ∧ ?max-subseq (op ≥) k ≤ n using reflp-def by simp+ from this have ∀ i ∈ {0 ..m ∗ n}. phi i ∈ {1 ..m} × {1 ..n} unfolding phi-def by auto from this have subseteq: phi ‘ {0 ..m ∗ n} ⊆ {1 ..m} × {1 ..n} by blast have card-product: card ({1 ..m} × {1 ..n}) = m ∗ n by (simp add: card-cartesian-product) have finite ({1 ..m} × {1 ..n}) by blast from subseteq card-product this have card-le: card (phi ‘ {0 ..m ∗ n}) ≤ m ∗ n by (metis card-mono)

{ fix i j assume i < (j :: nat) { fix R assume R: reflp (R :: 0a::linorder ⇒ -) transp R R (f i)(f j ) from one-member[OF hreflp Ri, of i] have ∃ S ∈ {S. S ⊆ {0 ..i} ∧ mono-on f R S ∧ i ∈ S}. card S = ?max-subseq R i by (intro exists-set-with-max-card) auto from this obtain S where S: S ⊆ {0 ..i} ∧ mono-on f R S ∧ i ∈ S card S = ?max-subseq R i by auto from S hi < j i finite-subset have j ∈/ S finite S insert j S ⊆ {0 ..j } by auto from S(1 ) R hi < j i this have mono-on f R (insert j S) unfolding mono-on-def reflp-def transp-def by (metis atLeastAtMost-iff insert-iff le-antisym subsetCE) from this have d: insert j S ∈ {S. S ⊆ {0 ..j } ∧ mono-on f R S ∧ j ∈ S} using hinsert j S ⊆ {0 ..j }i by blast from this hj ∈/ S i S(1 ) have card (insert j S) ∈ card ‘ {S. S ⊆ {0 ..j } ∧ mono-on f R S ∧ j ∈ S} ∧ card S < card (insert j S) by (auto intro!: imageI )(auto simp add: hfinite S i) from this S(2 ) have ?max-subseq R i < ?max-subseq R j by (auto intro: Max-gr) } note max-subseq-increase = this have ?max-subseq (op ≤) i < ?max-subseq (op ≤) j ∨ ?max-subseq (op ≥) i < ?max-subseq (op ≥) j proof (cases f j ≥ f i) case True from this max-subseq-increase[of op ≤, simplified] show ?thesis by simp next case False from this max-subseq-increase[of op ≥, simplified] show ?thesis by simp

643 qed from this have phi i 6= phi j using phi-def by auto } from this have inj phi unfolding inj-on-def by (metis less-linear) from this have card-eq: card (phi ‘ {0 ..m ∗ n}) = m ∗ n + 1 by (simp add: card-image inj-on-def ) from card-le card-eq show False by simp qed end

99 Sum of Powers theory Sum-of-Powers imports Complex-Main begin

99.1 Additions to Binomial Theory lemma (in field-char-0 ) one-plus-of-nat-neq-zero [simp]: 1 + of-nat n 6= 0 proof − have of-nat (Suc n) 6= of-nat 0 unfolding of-nat-eq-iff by simp then show ?thesis by simp qed lemma of-nat-binomial-eq-mult-binomial-Suc: assumes k ≤ n shows (of-nat :: (nat ⇒ ( 0a :: field-char-0 ))) (n choose k) = of-nat (n + 1 − k) / of-nat (n + 1 ) ∗ of-nat (Suc n choose k) proof (cases k) case 0 then show ?thesis by simp next case (Suc l) have of-nat (n + 1 ) ∗ (Q i=0 ..

644 with assms show ?thesis by (simp add: binomial-altdef-of-nat prod-dividef ) qed lemma real-binomial-eq-mult-binomial-Suc: assumes k ≤ n shows (n choose k) = (n + 1 − k) / (n + 1 ) ∗ (Suc n choose k) by (metis Suc-eq-plus1 add.commute assms le-SucI of-nat-Suc of-nat-binomial-eq-mult-binomial-Suc of-nat-diff )

99.2 Preliminaries lemma integrals-eq: assumes f 0 = g 0 assumes V x. ((λx. f x − g x) has-real-derivative 0 )(at x) shows f x = g x proof − show f x = g x proof (cases x 6= 0 ) case True from assms DERIV-const-ratio-const[OF this, of λx. f x − g x 0 ] show ?thesis by auto qed (simp add: assms) qed lemma sum-diff : ((P i≤n::nat. f (i + 1 ) − f i):: 0a::field) = f (n + 1 ) − f 0 by (induct n)(auto simp add: field-simps) declare One-nat-def [simp del]

99.3 Bernoulli Numbers and Bernoulli Polynomials declare sum.cong [fundef-cong] fun bernoulli :: nat ⇒ real where bernoulli 0 = (1 ::real) | bernoulli (Suc n) = (−1 / (n + 2 )) ∗ (P k ≤ n. ((n + 2 choose k) ∗ bernoulli k)) declare bernoulli.simps[simp del] definition bernpoly n = (λx. P k ≤ n. (n choose k) ∗ bernoulli k ∗ x ˆ (n − k))

99.4 Basic Observations on Bernoulli Polynomials lemma bernpoly-0 : bernpoly n 0 = bernoulli n proof (cases n) case 0

645 then show bernpoly n 0 = bernoulli n unfolding bernpoly-def bernoulli.simps by auto next case (Suc n 0) have (P k≤n 0. real (Suc n 0 choose k) ∗ bernoulli k ∗ 0 ˆ (Suc n 0 − k)) = 0 by (rule sum.neutral) auto with Suc show ?thesis unfolding bernpoly-def by simp qed lemma sum-binomial-times-bernoulli: (P k≤n. ((Suc n) choose k) ∗ bernoulli k) = (if n = 0 then 1 else 0 ) proof (cases n) case 0 then show ?thesis by (simp add: bernoulli.simps) next case Suc then show ?thesis by (simp add: bernoulli.simps) (simp add: field-simps add-2-eq-Suc 0[symmetric] del: add-2-eq-Suc add-2-eq-Suc 0) qed

99.5 Sum of Powers with Bernoulli Polynomials lemma bernpoly-derivative [derivative-intros]: (bernpoly (Suc n) has-real-derivative ((n + 1 ) ∗ bernpoly n x)) (at x) proof − have (bernpoly (Suc n) has-real-derivative (P k≤n. real (Suc n − k) ∗ x ˆ (n − k) ∗ (real (Suc n choose k) ∗ bernoulli k))) (at x) unfolding bernpoly-def by (rule DERIV-cong)(fast intro!: derivative-intros, simp) moreover have (P k≤n. real (Suc n − k) ∗ x ˆ (n − k) ∗ (real (Suc n choose k) ∗ bernoulli k)) = (n + 1 ) ∗ bernpoly n x unfolding bernpoly-def by (auto intro: sum.cong simp add: sum-distrib-left real-binomial-eq-mult-binomial-Suc[of - n] Suc-eq-plus1 of-nat-diff ) ultimately show ?thesis by auto qed lemma diff-bernpoly: bernpoly n (x + 1 ) − bernpoly n x = n ∗ x ˆ (n − 1 ) proof (induct n arbitrary: x) case 0 show ?case unfolding bernpoly-def by auto next case (Suc n) have bernpoly (Suc n)(0 + 1 ) − bernpoly (Suc n) 0 = (Suc n) ∗ 0 ˆ n unfolding bernpoly-0 unfolding bernpoly-def by (simp add: sum-binomial-times-bernoulli zero-power)

646 then have const: bernpoly (Suc n)(0 + 1 ) − bernpoly (Suc n) 0 = real (Suc n) ∗ 0 ˆ n by (simp add: power-0-left) have hyps 0: Vx. (real n + 1 ) ∗ bernpoly n (x + 1 ) − (real n + 1 ) ∗ bernpoly n x = real n ∗ x ˆ (n − Suc 0 ) ∗ real (Suc n) unfolding right-diff-distrib[symmetric] by (simp add: Suc.hyps One-nat-def ) note [derivative-intros] = DERIV-chain 0[where f = λx::real. x + 1 and g = bernpoly (Suc n) and s=UNIV ] have derivative: Vx. ((%x. bernpoly (Suc n)(x + 1 ) − bernpoly (Suc n) x − real (Suc n) ∗ x ˆ n) has-real-derivative 0 )(at x) by (rule DERIV-cong)(fast intro!: derivative-intros, simp add: hyps 0) from integrals-eq[OF const derivative] show ?case by simp qed lemma sum-of-powers:(P k≤n::nat. (real k) ˆ m) = (bernpoly (Suc m)(n + 1 ) − bernpoly (Suc m) 0 ) / (m + 1 ) proof − from diff-bernpoly[of Suc m, simplified] have (m + (1 ::real)) ∗ (P k≤n. (real k) ˆ m) = (P k≤n. bernpoly (Suc m)(real k + 1 ) − bernpoly (Suc m)(real k)) by (auto simp add: sum-distrib-left intro!: sum.cong) also have ... = (P k≤n. bernpoly (Suc m)(real (k + 1 )) − bernpoly (Suc m) (real k)) by simp also have ... = bernpoly (Suc m)(n + 1 ) − bernpoly (Suc m) 0 by (simp only: sum-diff [where f =λk. bernpoly (Suc m)(real k)]) simp finally show ?thesis by (auto simp add: field-simps intro!: eq-divide-imp) qed

99.6 Instances for Square And Cubic Numbers lemma binomial-unroll: n > 0 =⇒ (n choose k) = (if k = 0 then 1 else (n − 1 ) choose (k − 1 ) + ((n − 1 ) choose k)) by (auto simp add: gr0-conv-Suc) lemma sum-unroll: (P k≤n::nat. f k) = (if n = 0 then f 0 else f n + (P k≤n − 1 . f k)) by auto (metis One-nat-def Suc-pred add.commute sum-atMost-Suc) lemma bernoulli-unroll: n > 0 =⇒ bernoulli n = − 1 / (real n + 1 ) ∗ (P k≤n − 1 . real (n + 1 choose k) ∗ bernoulli k) by (cases n)(simp add: bernoulli.simps One-nat-def )+ lemmas unroll = binomial-unroll bernoulli.simps(1 ) bernoulli-unroll sum-unroll bernpoly-def lemma sum-of-squares:(P k≤n::nat. k ˆ 2 ) = (2 ∗ n ˆ 3 + 3 ∗ n ˆ 2 + n) / 6 proof − have real (P k≤n::nat. k ˆ 2 ) = (P k≤n::nat. (real k) ˆ 2 ) by simp

647 also have ... = (bernpoly 3 (real (n + 1 )) − bernpoly 3 0 ) / real (3 :: nat) by (auto simp add: sum-of-powers) also have ... = (2 ∗ n ˆ 3 + 3 ∗ n ˆ 2 + n) / 6 by (simp add: unroll algebra-simps power2-eq-square power3-eq-cube One-nat-def [symmetric]) finally show ?thesis by simp qed lemma sum-of-squares-nat:(P k≤n::nat. k ˆ 2 ) = (2 ∗ n ˆ 3 + 3 ∗ n ˆ 2 + n) div 6 proof − from sum-of-squares have real (6 ∗ (P k≤n. k ˆ 2 )) = real (2 ∗ n ˆ 3 + 3 ∗ n ˆ 2 + n) by (auto simp add: field-simps) then have 6 ∗ (P k≤n. k ˆ 2 ) = 2 ∗ n ˆ 3 + 3 ∗ n ˆ 2 + n using of-nat-eq-iff by blast then show ?thesis by auto qed lemma sum-of-cubes:(P k≤n::nat. k ˆ 3 ) = (n ˆ 2 + n) ˆ 2 / 4 proof − have two-plus-two: 2 + 2 = 4 by simp have power4-eq: Vx::real. x ˆ 4 = x ∗ x ∗ x ∗ x by (simp only: two-plus-two[symmetric] power-add power2-eq-square) have real (P k≤n::nat. k ˆ 3 ) = (P k≤n::nat. (real k) ˆ 3 ) by simp also have ... = ((bernpoly 4 (n + 1 ) − bernpoly 4 0 )) / (real (4 :: nat)) by (auto simp add: sum-of-powers) also have ... = ((n ˆ 2 + n) / 2 ) ˆ 2 by (simp add: unroll algebra-simps power2-eq-square power4-eq power3-eq-cube) finally show ?thesis by (simp add: power-divide) qed lemma sum-of-cubes-nat:(P k≤n::nat. k ˆ 3 ) = (n ˆ 2 + n) ˆ 2 div 4 proof − from sum-of-cubes have real (4 ∗ (P k≤n. k ˆ 3 )) = real ((n ˆ 2 + n) ˆ 2 ) by (auto simp add: field-simps) then have 4 ∗ (P k≤n. k ˆ 3 ) = (n ˆ 2 + n) ˆ 2 using of-nat-eq-iff by blast then show ?thesis by auto qed end

100 A SAT-based Sudoku Solver theory Sudoku imports Main begin

See the paper “A SAT-based Sudoku Solver” (Tjark Weber, published at

648 LPAR’05) for further explanations. (The paper describes an older version of this theory that used the model finder refute to find Sudoku solutions. The refute tool has since been superseded by nitpick, which is used below.) no-notation Groups.one-class.one (1 ) datatype digit = A (1 ) | B (2 ) | C (3 ) | D (4 ) | E (5 ) | F (6 ) | G (7 ) | H (8 ) | I (9 ) definition valid :: digit => digit => digit => digit => digit => digit => digit => digit => digit => bool where

valid x1 x2 x3 x4 x5 x6 x7 x8 x9 == (x1 6= x2 ) ∧ (x1 6= x3 ) ∧ (x1 6= x4 ) ∧ (x1 6= x5 ) ∧ (x1 6= x6 ) ∧ (x1 6= x7 ) ∧ (x1 6= x8 ) ∧ (x1 6= x9 ) ∧ (x2 6= x3 ) ∧ (x2 6= x4 ) ∧ (x2 6= x5 ) ∧ (x2 6= x6 ) ∧ (x2 6= x7 ) ∧ (x2 6= x8 ) ∧ (x2 6= x9 ) ∧ (x3 6= x4 ) ∧ (x3 6= x5 ) ∧ (x3 6= x6 ) ∧ (x3 6= x7 ) ∧ (x3 6= x8 ) ∧ (x3 6= x9 ) ∧ (x4 6= x5 ) ∧ (x4 6= x6 ) ∧ (x4 6= x7 ) ∧ (x4 6= x8 ) ∧ (x4 6= x9 ) ∧ (x5 6= x6 ) ∧ (x5 6= x7 ) ∧ (x5 6= x8 ) ∧ (x5 6= x9 ) ∧ (x6 6= x7 ) ∧ (x6 6= x8 ) ∧ (x6 6= x9 ) ∧ (x7 6= x8 ) ∧ (x7 6= x9 ) ∧ (x8 6= x9 ) definition sudoku :: digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => digit => bool where

sudoku x11 x12 x13 x14 x15 x16 x17 x18 x19 x21 x22 x23 x24 x25 x26 x27 x28 x29 x31 x32 x33 x34 x35 x36 x37 x38 x39 x41 x42 x43 x44 x45 x46 x47 x48 x49 x51 x52 x53 x54 x55 x56 x57 x58 x59 x61 x62 x63 x64 x65 x66 x67 x68 x69 x71 x72 x73 x74 x75 x76 x77 x78 x79

649 x81 x82 x83 x84 x85 x86 x87 x88 x89 x91 x92 x93 x94 x95 x96 x97 x98 x99 ==

valid x11 x12 x13 x14 x15 x16 x17 x18 x19 ∧ valid x21 x22 x23 x24 x25 x26 x27 x28 x29 ∧ valid x31 x32 x33 x34 x35 x36 x37 x38 x39 ∧ valid x41 x42 x43 x44 x45 x46 x47 x48 x49 ∧ valid x51 x52 x53 x54 x55 x56 x57 x58 x59 ∧ valid x61 x62 x63 x64 x65 x66 x67 x68 x69 ∧ valid x71 x72 x73 x74 x75 x76 x77 x78 x79 ∧ valid x81 x82 x83 x84 x85 x86 x87 x88 x89 ∧ valid x91 x92 x93 x94 x95 x96 x97 x98 x99

∧ valid x11 x21 x31 x41 x51 x61 x71 x81 x91 ∧ valid x12 x22 x32 x42 x52 x62 x72 x82 x92 ∧ valid x13 x23 x33 x43 x53 x63 x73 x83 x93 ∧ valid x14 x24 x34 x44 x54 x64 x74 x84 x94 ∧ valid x15 x25 x35 x45 x55 x65 x75 x85 x95 ∧ valid x16 x26 x36 x46 x56 x66 x76 x86 x96 ∧ valid x17 x27 x37 x47 x57 x67 x77 x87 x97 ∧ valid x18 x28 x38 x48 x58 x68 x78 x88 x98 ∧ valid x19 x29 x39 x49 x59 x69 x79 x89 x99

∧ valid x11 x12 x13 x21 x22 x23 x31 x32 x33 ∧ valid x14 x15 x16 x24 x25 x26 x34 x35 x36 ∧ valid x17 x18 x19 x27 x28 x29 x37 x38 x39 ∧ valid x41 x42 x43 x51 x52 x53 x61 x62 x63 ∧ valid x44 x45 x46 x54 x55 x56 x64 x65 x66 ∧ valid x47 x48 x49 x57 x58 x59 x67 x68 x69 ∧ valid x71 x72 x73 x81 x82 x83 x91 x92 x93 ∧ valid x74 x75 x76 x84 x85 x86 x94 x95 x96 ∧ valid x77 x78 x79 x87 x88 x89 x97 x98 x99

Just an arbitrary Sudoku grid: theorem ¬ sudoku x11 x12 x13 x14 x15 x16 x17 x18 x19 x21 x22 x23 x24 x25 x26 x27 x28 x29 x31 x32 x33 x34 x35 x36 x37 x38 x39 x41 x42 x43 x44 x45 x46 x47 x48 x49 x51 x52 x53 x54 x55 x56 x57 x58 x59 x61 x62 x63 x64 x65 x66 x67 x68 x69 x71 x72 x73 x74 x75 x76 x77 x78 x79 x81 x82 x83 x84 x85 x86 x87 x88 x89 x91 x92 x93 x94 x95 x96 x97 x98 x99 nitpick [expect=genuine] oops

An “easy” Sudoku: theorem ¬ sudoku

650 5 3 x13 x14 7 x16 x17 x18 x19 6 x22 x23 1 9 5 x27 x28 x29 x31 9 8 x34 x35 x36 x37 6 x39 8 x42 x43 x44 6 x46 x47 x48 3 4 x52 x53 8 x55 3 x57 x58 1 7 x62 x63 x64 2 x66 x67 x68 6 x71 6 x73 x74 x75 x76 2 8 x79 x81 x82 x83 4 1 9 x87 x88 5 x91 x92 x93 x94 8 x96 x97 7 9 nitpick [expect=genuine] oops

A “hard” Sudoku: theorem ¬ sudoku x11 2 x13 x14 x15 x16 x17 x18 x19 x21 x22 x23 6 x25 x26 x27 x28 3 x31 7 4 x34 8 x36 x37 x38 x39 x41 x42 x43 x44 x45 3 x47 x48 2 x51 8 x53 x54 4 x56 x57 1 x59 6 x62 x63 5 x65 x66 x67 x68 x69 x71 x72 x73 x74 1 x76 7 8 x79 5 x82 x83 x84 x85 9 x87 x88 x89 x91 x92 x93 x94 x95 x96 x97 4 x99 nitpick [expect=genuine] oops

Some “exceptionally difficult” Sudokus, taken from http://en.wikipedia.org/ w/index.php?title=Algorithmics of sudoku&oldid=254685903 (accessed De- cember 2, 2008).

Rating Program: gsf’s sudoku q1 (rating) Rating: 99408 Poster: JPF Label: Easter Monster 1...... 2.9.4...5...6...7...5.9.3...... 7...... 85..4.7.....6...3...9.8...2.....1 1..|...|..2 .9.|4..|.5. ..6|...|7.. ------+------+------.5.|9.3|...... |.7.|...... |85.|.4. ------+------+------7..|...|6.. .3.|..9|.8. ..2|...|..1

651 theorem ¬ sudoku 1 x12 x13 x14 x15 x16 x17 x18 2 x21 9 x23 4 x25 x26 x27 5 x29 x31 x32 6 x34 x35 x36 7 x38 x39 x41 5 x43 9 x45 3 x47 x48 x49 x51 x52 x53 x54 7 x56 x57 x58 x59 x61 x62 x63 8 5 x66 x67 4 x69 7 x72 x73 x74 x75 x76 6 x78 x79 x81 3 x83 x84 x85 9 x87 8 x89 x91 x92 2 x94 x95 x96 x97 x98 1 nitpick [expect=genuine] oops

Rating Program: gsf’s sudoku q1 (Processing time) Rating: 4m19s@2 GHz Poster: tarek Label: tarek071223170000-052 ..1..4...... 6.3.5...9.....8.....7.3...... 285...7.6..3...8...6..92...... 4...1... ..1|..4|...... |.6.|3.5 ...|9..|... ------+------+------8..|...|7.3 ...|...|.28 5..|.7.|6.. ------+------+------3..|.8.|..6 ..9|2..|... .4.|..1|... theorem ¬ sudoku x11 x12 1 x14 x15 4 x17 x18 x19 x21 x22 x23 x24 6 x26 3 x28 5 x31 x32 x33 9 x35 x36 x37 x38 x39 8 x42 x43 x44 x45 x46 7 x48 3 x51 x52 x53 x54 x55 x56 x57 2 8 5 x62 x63 x64 7 x66 6 x68 x69 3 x72 x73 x74 8 x76 x77 x78 6 x81 x82 9 2 x85 x86 x87 x88 x89 x91 4 x93 x94 x95 1 x97 x98 x99 nitpick [expect=genuine] oops

Rating Program: Nicolas Juillerat’s Sudoku explainer 1.2.1 Rating: 11.9

652 Poster: tarek Label: golden nugget ...... 39.....1..5..3.5.8....8.9...6.7...2...1..4...... 9.8..5..2....6..4..7...... |...|.39 ...|..1|..5 ..3|.5.|8.. ------+------+------..8|.9.|..6 .7.|..2|... 1..|4..|... ------+------+------..9|.8.|.5. .2.|...|6.. 4..|7..|... theorem ¬ sudoku x11 x12 x13 x14 x15 x16 x17 3 9 x21 x22 x23 x24 x25 1 x27 x28 5 x31 x32 3 x34 5 x36 8 x38 x39 x41 x42 8 x44 9 x46 x47 x48 6 x51 7 x53 x54 x55 2 x57 x58 x59 1 x62 x63 4 x65 x66 x67 x68 x69 x71 x72 9 x74 8 x76 x77 5 x79 x81 2 x83 x84 x85 x86 6 x88 x89 4 x92 x93 7 x95 x96 x97 x98 x99 nitpick [expect=genuine] oops

Rating Program: dukuso’s suexrat9 Rating: 4483 Poster: coloin Label: col-02-08-071 .2.4.37...... 32...... 4.4.2...7.8...5...... 1...5.....9...3.9....7..1..86.. .2.|4.3|7.. ...|...|.32 ...|...|..4 ------+------+------.4.|2..|.7. 8..|.5.|...... |..1|... ------+------+------5..|...|9.. .3.|9..|..7 ..1|..8|6..

653 theorem ¬ sudoku x11 2 x13 4 x15 3 7 x18 x19 x21 x22 x23 x24 x25 x26 x27 3 2 x31 x32 x33 x34 x35 x36 x37 x38 4 x41 4 x43 2 x45 x46 x47 7 x49 8 x52 x53 x54 5 x56 x57 x58 x59 x61 x62 x63 x64 x65 1 x67 x68 x69 5 x72 x73 x74 x75 x76 9 x78 x79 x81 3 x83 9 x85 x86 x87 x88 7 x91 x92 1 x94 x95 8 6 x98 x99 nitpick [expect=genuine] oops

Rating Program: dukuso’s suexratt (10000 2 option) Rating: 2141 Poster: tarek Label: golden nugget ...... 39.....1..5..3.5.8....8.9...6.7...2...1..4...... 9.8..5..2....6..4..7...... |...|.39 ...|..1|..5 ..3|.5.|8.. ------+------+------..8|.9.|..6 .7.|..2|... 1..|4..|... ------+------+------..9|.8.|.5. .2.|...|6.. 4..|7..|... theorem ¬ sudoku x11 x12 x13 x14 x15 x16 x17 3 9 x21 x22 x23 x24 x25 1 x27 x28 5 x31 x32 3 x34 5 x36 8 x38 x39 x41 x42 8 x44 9 x46 x47 x48 6 x51 7 x53 x54 x55 2 x57 x58 x59 1 x62 x63 4 x65 x66 x67 x68 x69 x71 x72 9 x74 8 x76 x77 5 x79 x81 2 x83 x84 x85 x86 6 x88 x89 4 x92 x93 7 x95 x96 x97 x98 x99 nitpick [expect=genuine] oops end

654 101 The sieve of Eratosthenes theory Eratosthenes imports Main Primes begin

101.1 Preliminary: strict divisibility context dvd begin abbreviation dvd-strict :: 0a ⇒ 0a ⇒ bool (infixl dvd 0-strict 50 ) where b dvd-strict a ≡ b dvd a ∧ ¬ a dvd b end

101.2 Main corpus

The sieve is modelled as a list of booleans, where False means marked out. type-synonym marks = bool list definition numbers-of-marks :: nat ⇒ marks ⇒ nat set where numbers-of-marks n bs = fst ‘ {x ∈ set (enumerate n bs). snd x} lemma numbers-of-marks-simps [simp, code]: numbers-of-marks n [] = {} numbers-of-marks n (True # bs) = insert n (numbers-of-marks (Suc n) bs) numbers-of-marks n (False # bs) = numbers-of-marks (Suc n) bs by (auto simp add: numbers-of-marks-def intro!: image-eqI ) lemma numbers-of-marks-Suc: numbers-of-marks (Suc n) bs = Suc ‘ numbers-of-marks n bs by (auto simp add: numbers-of-marks-def enumerate-Suc-eq image-iff Bex-def ) lemma numbers-of-marks-replicate-False [simp]: numbers-of-marks n (replicate m False) = {} by (auto simp add: numbers-of-marks-def enumerate-replicate-eq) lemma numbers-of-marks-replicate-True [simp]: numbers-of-marks n (replicate m True) = {n..

655 sorted-list-of-set (numbers-of-marks n bs) = map fst (filter snd (enumerate n bs)) by (auto simp add: numbers-of-marks-def distinct-map intro!: sorted-filter distinct-filter inj-onI sorted-distinct-set-unique)

Marking out multiples in a sieve definition mark-out :: nat ⇒ marks ⇒ marks where mark-out n bs = map (λ(q, b). b ∧ ¬ Suc n dvd Suc (Suc q)) (enumerate n bs) lemma mark-out-Nil [simp]: mark-out n [] = [] by (simp add: mark-out-def ) lemma length-mark-out [simp]: length (mark-out n bs) = length bs by (simp add: mark-out-def ) lemma numbers-of-marks-mark-out: numbers-of-marks n (mark-out m bs) = {q ∈ numbers-of-marks n bs. ¬ Suc m dvd Suc q − n} by (auto simp add: numbers-of-marks-def mark-out-def in-set-enumerate-eq image-iff nth-enumerate-eq less-eq-dvd-minus)

Auxiliary operation for efficient implementation definition mark-out-aux :: nat ⇒ nat ⇒ marks ⇒ marks where mark-out-aux n m bs = map (λ(q, b). b ∧ (q < m + n ∨ ¬ Suc n dvd Suc (Suc q) + (n − m mod Suc n))) (enumerate n bs) lemma mark-out-code [code]: mark-out n bs = mark-out-aux n n bs proof − have aux: False if A: Suc n dvd Suc (Suc a) and B: a < n + n and C : n ≤ a for a proof (cases n = 0 ) case True with ABC show ?thesis by simp next case False define m where m = Suc n then have m > 0 by simp from False have n > 0 by simp from A obtain q where q: Suc (Suc a) = Suc n ∗ q by (rule dvdE) have q > 0 proof (rule ccontr) assume ¬ q > 0 with q show False by simp qed

656 with hn > 0 i have Suc n ∗ q ≥ 2 by (auto simp add: gr0-conv-Suc) with q have a: a = Suc n ∗ q − 2 by simp with B have q + n ∗ q < n + n + 2 by auto then have m ∗ q < m ∗ 2 by (simp add: m-def ) with hm > 0 i have q < 2 by simp with hq > 0 i have q = 1 by simp with a have a = n − 1 by simp with hn > 0 i C show False by simp qed show ?thesis by (auto simp add: mark-out-def mark-out-aux-def in-set-enumerate-eq intro: aux) qed lemma mark-out-aux-simps [simp, code]: mark-out-aux n m [] = [] mark-out-aux n 0 (b # bs) = False # mark-out-aux n n bs mark-out-aux n (Suc m)(b # bs) = b # mark-out-aux n m bs proof goal-cases case 1 show ?case by (simp add: mark-out-aux-def ) next case 2 show ?case by (auto simp add: mark-out-code [symmetric] mark-out-aux-def mark-out-def enumerate-Suc-eq in-set-enumerate-eq less-eq-dvd-minus) next case 3 { define v where v = Suc m define w where w = Suc n fix q assume m + n ≤ q then obtain r where q: q = m + n + r by (auto simp add: le-iff-add) { fix u from w-def have u mod w < w by simp then have u + (w − u mod w) = w + (u − u mod w) by simp then have u + (w − u mod w) = w + u div w ∗ w by (simp add: minus-mod-eq-div-mult) } then have w dvd v + w + r + (w − v mod w) ←→ w dvd m + w + r + (w − m mod w) by (simp add: add.assoc add.left-commute [of m] add.left-commute [of v] dvd-add-left-iff dvd-add-right-iff ) moreover from q have Suc q = m + w + r by (simp add: w-def ) moreover from q have Suc (Suc q) = v + w + r by (simp add: v-def w-def ) ultimately have w dvd Suc (Suc (q + (w − v mod w))) ←→ w dvd Suc (q + (w − m mod w))

657 by (simp only: add-Suc [symmetric]) then have Suc n dvd Suc (Suc (Suc (q + n) − Suc m mod Suc n)) ←→ Suc n dvd Suc (Suc (q + n − m mod Suc n)) by (simp add: v-def w-def Suc-diff-le trans-le-add2 ) } then show ?case by (auto simp add: mark-out-aux-def enumerate-Suc-eq in-set-enumerate-eq not-less) qed

Main entry point to sieve fun sieve :: nat ⇒ marks ⇒ marks where sieve n [] = [] | sieve n (False # bs) = False # sieve (Suc n) bs | sieve n (True # bs) = True # sieve (Suc n)(mark-out n bs)

There are the following possible optimisations here:

• sieve can abort as soon as n is too big to let mark-out have any effect.

• Search for further primes can be given up as soon as the search position exceeds the square root of the maximum candidate.

This is left as an constructive exercise to the reader. lemma numbers-of-marks-sieve: numbers-of-marks (Suc n)(sieve n bs) = {q ∈ numbers-of-marks (Suc n) bs. ∀ m ∈ numbers-of-marks (Suc n) bs. ¬ m dvd-strict q} proof (induct n bs rule: sieve.induct) case 1 show ?case by simp next case 2 then show ?case by simp next case (3 n bs) have aux: n ∈ Suc ‘ M ←→ n > 0 ∧ n − 1 ∈ M (is ?lhs ←→ ?rhs) for M n proof show ?rhs if ?lhs using that by auto show ?lhs if ?rhs proof − from that have n > 0 and n − 1 ∈ M by auto then have Suc (n − 1 ) ∈ Suc ‘ M by blast with hn > 0 i show n ∈ Suc ‘ M by simp qed qed have aux1 : False if Suc (Suc n) ≤ m and m dvd Suc n for m :: nat

658 proof − from hm dvd Suc n i obtain q where Suc n = m ∗ q .. with hSuc (Suc n) ≤ m i have Suc (m ∗ q) ≤ m by simp then have m ∗ q < m by arith then have q = 0 by simp with hSuc n = m ∗ q i show ?thesis by simp qed have aux2 : m dvd q if 1 : ∀ q>0 . 1 < q −→ Suc n < q −→ q ≤ Suc (n + length bs) −→ bs !(q − Suc (Suc n)) −→ ¬ Suc n dvd q −→ q dvd m −→ m dvd q and 2 : ¬ Suc n dvd m q dvd m and 3 : Suc n < q q ≤ Suc (n + length bs) bs !(q − Suc (Suc n)) for m q :: nat proof − from 1 have ∗: Vq. Suc n < q =⇒ q ≤ Suc (n + length bs) =⇒ bs !(q − Suc (Suc n)) =⇒ ¬ Suc n dvd q =⇒ q dvd m =⇒ m dvd q by auto from 2 have ¬ Suc n dvd q by (auto elim: dvdE) moreover note 3 moreover note hq dvd m i ultimately show ?thesis by (auto intro: ∗) qed from 3 show ?case apply (simp-all add: numbers-of-marks-mark-out numbers-of-marks-Suc Compr-image-eq inj-image-eq-iff in-numbers-of-marks-eq Ball-def imp-conjL aux) apply safe apply (simp-all add: less-diff-conv2 le-diff-conv2 dvd-minus-self not-less) apply (clarsimp dest!: aux1 ) apply (simp add: Suc-le-eq less-Suc-eq-le) apply (rule aux2 ) apply (clarsimp dest!: aux1 )+ done qed

Relation of the sieve algorithm to actual primes definition primes-upto :: nat ⇒ nat list where primes-upto n = sorted-list-of-set {m. m ≤ n ∧ prime m} lemma set-primes-upto: set (primes-upto n) = {m. m ≤ n ∧ prime m} by (simp add: primes-upto-def ) lemma sorted-primes-upto [iff ]: sorted (primes-upto n) by (simp add: primes-upto-def ) lemma distinct-primes-upto [iff ]: distinct (primes-upto n) by (simp add: primes-upto-def ) lemma set-primes-upto-sieve:

659 set (primes-upto n) = numbers-of-marks 2 (sieve 1 (replicate (n − 1 ) True)) proof − consider n = 0 ∨ n = 1 | n > 1 by arith then show ?thesis proof cases case 1 then show ?thesis by (auto simp add: numbers-of-marks-sieve numeral-2-eq-2 set-primes-upto dest: prime-gt-Suc-0-nat) next case 2 { fix m q assume Suc (Suc 0 ) ≤ q and q < Suc n and m dvd q then have m < Suc n by (auto dest: dvd-imp-le) assume ∗: ∀ m∈{Suc (Suc 0 )..

660 apply (simp-all only: set-primes-upto-sieve numbers-of-marks-def ) apply auto done then show ?thesis by (simp add: sorted-list-of-set-numbers-of-marks) qed lemma prime-in-primes-upto: prime n ←→ n ∈ set (primes-upto n) by (simp add: set-primes-upto)

101.3 Application: smallest prime beyond a certain number definition smallest-prime-beyond :: nat ⇒ nat where smallest-prime-beyond n = (LEAST p. prime p ∧ p ≥ n) lemma prime-smallest-prime-beyond [iff ]: prime (smallest-prime-beyond n)(is ?P) and smallest-prime-beyond-le [iff ]: smallest-prime-beyond n ≥ n (is ?Q) proof − let ?least = LEAST p. prime p ∧ p ≥ n from primes-infinite obtain q where prime q ∧ q ≥ n by (metis finite-nat-set-iff-bounded-le mem-Collect-eq nat-le-linear) then have prime ?least ∧ ?least ≥ n by (rule LeastI ) then show ?P and ?Q by (simp-all add: smallest-prime-beyond-def ) qed lemma smallest-prime-beyond-smallest: prime p =⇒ p ≥ n =⇒ smallest-prime-beyond n ≤ p by (simp only: smallest-prime-beyond-def )(auto intro: Least-le) lemma smallest-prime-beyond-eq: prime p =⇒ p ≥ n =⇒ (Vq. prime q =⇒ q ≥ n =⇒ q ≥ p) =⇒ smallest-prime-beyond n = p by (simp only: smallest-prime-beyond-def )(auto intro: Least-equality) definition smallest-prime-between :: nat ⇒ nat ⇒ nat option where smallest-prime-between m n = (if (∃ p. prime p ∧ m ≤ p ∧ p ≤ n) then Some (smallest-prime-beyond m) else None) lemma smallest-prime-between-None: smallest-prime-between m n = None ←→ (∀ q. m ≤ q ∧ q ≤ n −→ ¬ prime q) by (auto simp add: smallest-prime-between-def ) lemma smallest-prime-betwen-Some:

661 smallest-prime-between m n = Some p ←→ smallest-prime-beyond m = p ∧ p ≤ n by (auto simp add: smallest-prime-between-def dest: smallest-prime-beyond-smallest [of - m]) lemma [code]: smallest-prime-between m n = List.find (λp. p ≥ m)(primes-upto n) proof − have List.find (λp. p ≥ m)(primes-upto n) = Some (smallest-prime-beyond m) if assms: m ≤ p prime p p ≤ n for p proof − define A where A = {p. p ≤ n ∧ prime p ∧ m ≤ p} from assms have smallest-prime-beyond m ≤ p by (auto intro: smallest-prime-beyond-smallest) from this hp ≤ n i have ∗: smallest-prime-beyond m ≤ n by (rule order-trans) from assms have ex: ∃ p≤n. prime p ∧ m ≤ p by auto then have finite A by (auto simp add: A-def ) with ∗ have Min A = smallest-prime-beyond m by (auto simp add: A-def intro: Min-eqI smallest-prime-beyond-smallest) with ex sorted-primes-upto show ?thesis by (auto simp add: set-primes-upto sorted-find-Min A-def ) qed then show ?thesis by (auto simp add: smallest-prime-between-def find-None-iff set-primes-upto intro!: sym [of - None]) qed definition smallest-prime-beyond-aux :: nat ⇒ nat ⇒ nat where smallest-prime-beyond-aux k n = smallest-prime-beyond n lemma [code]: smallest-prime-beyond-aux k n = (case smallest-prime-between n (k ∗ n) of Some p ⇒ p | None ⇒ smallest-prime-beyond-aux (Suc k) n) by (simp add: smallest-prime-beyond-aux-def smallest-prime-betwen-Some split: option.split) lemma [code]: smallest-prime-beyond n = smallest-prime-beyond-aux 2 n by (simp add: smallest-prime-beyond-aux-def ) end

662 102 Examples for code generation timing measures theory Code-Timing imports ∼∼/src/HOL/Number-Theory/Eratosthenes begin declare [[code-timing]] definition primes-upto :: nat ⇒ int list where primes-upto = map int ◦ Eratosthenes.primes-upto definition required-symbols - = (primes-upto, 0 :: nat, Suc, 1 :: nat, numeral :: num ⇒ nat, Num.One, Num.Bit0 , Num.Bit1 , Code-Evaluation.TERM-OF-EQUAL :: int list itself )

ML h local val ctxt = @{context}; val consts = [@{const-name required-symbols}]; in val simp = Code-Simp.static-conv { ctxt = ctxt, consts = consts, simpset = NONE }; val nbe = Nbe.static-conv { ctxt = ctxt, consts = consts }; val eval = Code-Evaluation.static-conv { ctxt = ctxt, consts = consts }; end; i

ML-val h simp @{context} @{cterm primes-upto 100 } i

ML-val h simp @{context} @{cterm primes-upto 200 } i

ML-val h nbe @{context} @{cterm primes-upto 200 } i

ML-val h nbe @{context} @{cterm primes-upto 400 } i

ML-val h nbe @{context} @{cterm primes-upto 600 } i

663 ML-val h eval @{context} @{cterm primes-upto 800 } i

ML-val h eval @{context} @{cterm primes-upto 1000 } i end

103 Permutations as abstract type theory Perm imports Main begin

This theory introduces basics about permutations, i.e. almost everywhere fix bijections. But it is by no means complete. Grieviously missing are cycles since these would require more elaboration, e.g. the concept of distinct lists equivalent under rotation, which maybe would also deserve its own theory. But see theory src/HOL/ex/Perm-Fragments.thy for fragments on that.

103.1 Abstract type of permutations typedef 0a perm = {f :: 0a ⇒ 0a. bij f ∧ finite {a. f a 6= a}} morphisms apply Perm proof show id ∈ ?perm by simp qed setup-lifting type-definition-perm notation apply (infixl h$i 999 ) no-notation apply (op h$i) lemma bij-apply [simp]: bij (apply f ) using apply [of f ] by simp lemma perm-eqI : assumes Va. f h$i a = g h$i a shows f = g using assms by transfer (simp add: fun-eq-iff ) lemma perm-eq-iff : f = g ←→ (∀ a. f h$i a = g h$i a) by (auto intro: perm-eqI )

664 lemma apply-inj : f h$i a = f h$i b ←→ a = b by (rule inj-eq)(rule bij-is-inj , simp) lift-definition affected :: 0a perm ⇒ 0a set is λf . {a. f a 6= a} . lemma in-affected: a ∈ affected f ←→ f h$i a 6= a by transfer simp lemma finite-affected [simp]: finite (affected f ) by transfer simp lemma apply-affected [simp]: f h$i a ∈ affected f ←→ a ∈ affected f proof transfer fix f :: 0a ⇒ 0a and a :: 0a assume bij f ∧ finite {b. f b 6= b} then have bij f by simp interpret bijection f by standard (rule hbij f i) have f a ∈ {a. f a = a} ←→ a ∈ {a. f a = a} (is ?P ←→ ?Q) by auto then show f a ∈ {a. f a 6= a} ←→ a ∈ {a. f a 6= a} by simp qed lemma card-affected-not-one: card (affected f ) 6= 1 proof interpret bijection apply f by standard (rule bij-apply) assume card (affected f ) = 1 then obtain a where ∗: affected f = {a} by (rule card-1-singletonE) then have ∗∗: f h$i a 6= a by (simp add: in-affected [symmetric]) with ∗ have f h$i a ∈/ affected f by simp then have f h$i (f h$i a) = f h$i a by (simp add: in-affected) then have inv (apply f )(f h$i (f h$i a)) = inv (apply f )(f h$i a) by simp with ∗∗ show False by simp qed

665 103.2 Identity, composition and inversion instantiation Perm.perm :: (type) {monoid-mult, inverse} begin lift-definition one-perm :: 0a perm is id by simp lemma apply-one [simp]: apply 1 = id by (fact one-perm.rep-eq) lemma affected-one [simp]: affected 1 = {} by transfer simp lemma affected-empty-iff [simp]: affected f = {} ←→ f = 1 by transfer auto lift-definition times-perm :: 0a perm ⇒ 0a perm ⇒ 0a perm is comp proof fix f g :: 0a ⇒ 0a assume bij f ∧ finite {a. f a 6= a} bij g ∧finite {a. g a 6= a} then have finite ({a. f a 6= a} ∪ {a. g a 6= a}) by simp moreover have {a. (f ◦ g) a 6= a} ⊆ {a. f a 6= a} ∪ {a. g a 6= a} by auto ultimately show finite {a. (f ◦ g) a 6= a} by (auto intro: finite-subset) qed (auto intro: bij-comp) lemma apply-times: apply (f ∗ g) = apply f ◦ apply g by (fact times-perm.rep-eq) lemma apply-sequence: f h$i (g h$i a) = apply (f ∗ g) a by (simp add: apply-times) lemma affected-times [simp]: affected (f ∗ g) ⊆ affected f ∪ affected g by transfer auto lift-definition inverse-perm :: 0a perm ⇒ 0a perm is inv proof transfer

666 fix f :: 0a ⇒ 0a and a assume bij f ∧ finite {b. f b 6= b} then have bij f and fin: finite {b. f b 6= b} by auto interpret bijection f by standard (rule hbij f i) from fin show bij (inv f ) ∧ finite {a. inv f a 6= a} by (simp add: bij-inv) qed instance by standard (transfer; simp add: comp-assoc)+ end lemma apply-inverse: apply (inverse f ) = inv (apply f ) by (fact inverse-perm.rep-eq) lemma affected-inverse [simp]: affected (inverse f ) = affected f proof transfer fix f :: 0a ⇒ 0a and a assume bij f ∧ finite {b. f b 6= b} then have bij f by simp interpret bijection f by standard (rule hbij f i) show {a. inv f a 6= a} = {a. f a 6= a} by simp qed global-interpretation perm: group times 1 :: 0a perm inverse proof fix f :: 0a perm show 1 ∗ f = f by transfer simp show inverse f ∗ f = 1 proof transfer fix f :: 0a ⇒ 0a and a assume bij f ∧ finite {b. f b 6= b} then have bij f by simp interpret bijection f by standard (rule hbij f i) show inv f ◦ f = id by simp qed qed declare perm.inverse-distrib-swap [simp] lemma perm-mult-commute: assumes affected f ∩ affected g = {}

667 shows g ∗ f = f ∗ g proof (rule perm-eqI ) fix a from assms have ∗: a ∈ affected f =⇒ a ∈/ affected g a ∈ affected g =⇒ a ∈/ affected f for a by auto consider a ∈ affected f ∧ a ∈/ affected g ∧ f h$i a ∈ affected f | a ∈/ affected f ∧ a ∈ affected g ∧ f h$i a ∈/ affected f | a ∈/ affected f ∧ a ∈/ affected g using assms by auto then show (g ∗ f ) h$i a = (f ∗ g) h$i a proof cases case 1 with ∗ have f h$i a ∈/ affected g by auto with 1 show ?thesis by (simp add: in-affected apply-times) next case 2 with ∗ have g h$i a ∈/ affected f by auto with 2 show ?thesis by (simp add: in-affected apply-times) next case 3 then show ?thesis by (simp add: in-affected apply-times) qed qed lemma apply-power: apply (f ˆ n) = apply f ˆˆ n by (induct n)(simp-all add: apply-times) lemma perm-power-inverse: inverse f ˆ n = inverse ((f :: 0a perm) ˆ n) proof (induct n) case 0 then show ?case by simp next case (Suc n) then show ?case unfolding power-Suc2 [of f ] by simp qed

103.3 Orbit and order of elements definition orbit :: 0a perm ⇒ 0a ⇒ 0a set where orbit f a = range (λn. (f ˆ n) h$i a)

668 lemma in-orbitI : assumes (f ˆ n) h$i a = b shows b ∈ orbit f a using assms by (auto simp add: orbit-def ) lemma apply-power-self-in-orbit [simp]: (f ˆ n) h$i a ∈ orbit f a by (rule in-orbitI ) rule lemma in-orbit-self [simp]: a ∈ orbit f a using apply-power-self-in-orbit [of - 0 ] by simp lemma apply-self-in-orbit [simp]: f h$i a ∈ orbit f a using apply-power-self-in-orbit [of - 1 ] by simp lemma orbit-not-empty [simp]: orbit f a 6= {} using in-orbit-self [of a f ] by blast lemma not-in-affected-iff-orbit-eq-singleton: a ∈/ affected f ←→ orbit f a = {a} (is ?P ←→ ?Q) proof assume ?P then have f h$i a = a by (simp add: in-affected) then have (f ˆ n) h$i a = a for n by (induct n)(simp-all add: apply-times) then show ?Q by (auto simp add: orbit-def ) next assume ?Q then show ?P by (auto simp add: orbit-def in-affected dest: range-eq-singletonD [of - - 1 ]) qed definition order :: 0a perm ⇒ 0a ⇒ nat where order f = card ◦ orbit f lemma orbit-subset-eq-affected: assumes a ∈ affected f shows orbit f a ⊆ affected f proof (rule ccontr) assume ¬ orbit f a ⊆ affected f then obtain b where b ∈ orbit f a and b ∈/ affected f by auto then have b ∈ range (λn. (f ˆ n) h$i a)

669 by (simp add: orbit-def ) then obtain n where b = (f ˆ n) h$i a by blast with hb ∈/ affected f i have (f ˆ n) h$i a ∈/ affected f by simp then have f h$i a ∈/ affected f by (induct n)(simp-all add: apply-times) with assms show False by simp qed lemma finite-orbit [simp]: finite (orbit f a) proof (cases a ∈ affected f ) case False then show ?thesis by (simp add: not-in-affected-iff-orbit-eq-singleton) next case True then have orbit f a ⊆ affected f by (rule orbit-subset-eq-affected) then show ?thesis using finite-affected by (rule finite-subset) qed lemma orbit-1 [simp]: orbit 1 a = {a} by (auto simp add: orbit-def ) lemma order-1 [simp]: order 1 a = 1 unfolding order-def by simp lemma card-orbit-eq [simp]: card (orbit f a) = order f a by (simp add: order-def ) lemma order-greater-zero [simp]: order f a > 0 by (simp only: card-gt-0-iff order-def comp-def ) simp lemma order-eq-one-iff : order f a = Suc 0 ←→ a ∈/ affected f (is ?P ←→ ?Q) proof assume ?P then have card (orbit f a) = 1 by simp then obtain b where orbit f a = {b} by (rule card-1-singletonE) with in-orbit-self [of a f ] have b = a by simp

670 with horbit f a = {b}i show ?Q by (simp add: not-in-affected-iff-orbit-eq-singleton) next assume ?Q then have orbit f a = {a} by (simp add: not-in-affected-iff-orbit-eq-singleton) then have card (orbit f a) = 1 by simp then show ?P by simp qed lemma order-greater-eq-two-iff : order f a ≥ 2 ←→ a ∈ affected f using order-eq-one-iff [of f a] apply (auto simp add: neq-iff ) using order-greater-zero [of f a] apply simp done lemma order-less-eq-affected: assumes f 6= 1 shows order f a ≤ card (affected f ) proof (cases a ∈ affected f ) from assms have affected f 6= {} by simp then obtain B b where affected f = insert b B by blast with finite-affected [of f ] have card (affected f ) ≥ 1 by (simp add: card-insert) case False then have order f a = 1 by (simp add: order-eq-one-iff ) with hcard (affected f ) ≥ 1 i show ?thesis by simp next case True have card (orbit f a) ≤ card (affected f ) by (rule card-mono)(simp-all add: True orbit-subset-eq-affected card-mono) then show ?thesis by simp qed lemma affected-order-greater-eq-two: assumes a ∈ affected f shows order f a ≥ 2 proof (rule ccontr) assume ¬ 2 ≤ order f a then have order f a < 2 by (simp add: not-le)

671 with order-greater-zero [of f a] have order f a = 1 by arith with assms show False by (simp add: order-eq-one-iff ) qed lemma order-witness-unfold: assumes n > 0 and (f ˆ n) h$i a = a shows order f a = card ((λm. (f ˆ m) h$i a) ‘ {0 .. 0 i have m mod n < n by simp ultimately show b ∈ ?B by auto next fix b assume b ∈ ?B then obtain m where (f ˆ m) h$i a = b by blast then show b ∈ orbit f a by (rule in-orbitI ) qed then have card (orbit f a) = card ?B by (simp only:) then show ?thesis by simp qed lemma inj-on-apply-range: inj-on (λm. (f ˆ m) h$i a) {..

672 case 0 then show ?case by simp next case (Suc n) then have prem: n < order f a by simp with Suc.hyps have hyp: inj-on (λm. (f ˆ m) h$i a) {.. 0 i have order f a = card ((λm. (f ˆ m) h$i a) ‘ {0 ..

673 by simp qed lemma in-orbitE: assumes b ∈ orbit f a obtains n where b = (f ˆ n) h$i a and n < order f a using assms unfolding orbit-unfold-image by blast lemma apply-power-order [simp]: (f ˆ order f a) h$i a = a proof − have (f ˆ order f a) h$i a ∈ orbit f a by simp then obtain n where ∗:(f ˆ order f a) h$i a = (f ˆ n) h$i a and n < order f a by (rule in-orbitE) show ?thesis proof (cases n) case 0 with ∗ show ?thesis by simp next case (Suc m) from order-greater-zero [of f a] have Suc (order f a − 1 ) = order f a by arith from Suc hn < order f a i have m < order f a by simp with Suc ∗ have (inverse f ) h$i ((f ˆ Suc (order f a − 1 )) h$i a) = (inverse f ) h$i ((f ˆ Suc m) h$i a) by simp then have (f ˆ (order f a − 1 )) h$i a = (f ˆ m) h$i a by (simp only: power-Suc apply-times) (simp add: apply-sequence mult.assoc [symmetric]) with inj-on-apply-range have order f a − 1 = m by (rule inj-onD) (simp-all add: hm < order f a i) with Suc have n = order f a by auto with hn < order f a i show ?thesis by simp qed qed lemma apply-power-left-mult-order [simp]: (f ˆ (n ∗ order f a)) h$i a = a

674 by (induct n)(simp-all add: power-add apply-times) lemma apply-power-right-mult-order [simp]: (f ˆ (order f a ∗ n)) h$i a = a by (simp add: ac-simps) lemma apply-power-mod-order-eq [simp]: (f ˆ (n mod order f a)) h$i a = (f ˆ n) h$i a proof − have (f ˆ n) h$i a = (f ˆ (n mod order f a + order f a ∗ (n div order f a))) h$i a by simp also have ... = (f ˆ (n mod order f a) ∗ f ˆ (order f a ∗ (n div order f a))) h$i a by (simp add: power-add [symmetric]) finally show ?thesis by (simp add: apply-times) qed lemma apply-power-eq-iff : (f ˆ m) h$i a = (f ˆ n) h$i a ←→ m mod order f a = n mod order f a (is ?P ←→ ?Q) proof assume ?Q then have (f ˆ (m mod order f a)) h$i a = (f ˆ (n mod order f a)) h$i a by simp then show ?P by simp next assume ?P then have (f ˆ (m mod order f a)) h$i a = (f ˆ (n mod order f a)) h$i a by simp with inj-on-apply-range show ?Q by (rule inj-onD) simp-all qed lemma apply-inverse-eq-apply-power-order-minus-one: (inverse f ) h$i a = (f ˆ (order f a − 1 )) h$i a proof (cases order f a) case 0 with order-greater-zero [of f a] show ?thesis by simp next case (Suc n) moreover have (f ˆ order f a) h$i a = a by simp then have ∗:(inverse f ) h$i ((f ˆ order f a) h$i a) = (inverse f ) h$i a by simp ultimately show ?thesis by (simp add: apply-sequence mult.assoc [symmetric]) qed

675 lemma apply-inverse-self-in-orbit [simp]: (inverse f ) h$i a ∈ orbit f a using apply-inverse-eq-apply-power-order-minus-one [symmetric] by (rule in-orbitI ) lemma apply-inverse-power-eq: (inverse (f ˆ n)) h$i a = (f ˆ (order f a − n mod order f a)) h$i a proof (induct n) case 0 then show ?case by simp next case (Suc n) define m where m = order f a − n mod order f a − 1 moreover have order f a − n mod order f a > 0 by simp ultimately have ∗: order f a − n mod order f a = Suc m by arith moreover from ∗ have m2 : order f a − Suc n mod order f a = (if m = 0 then order f a else m) by (auto simp add: mod-Suc) ultimately show ?case using Suc by (simp-all add: apply-times power-Suc2 [of - n] power-Suc [of - m] del: power-Suc) (simp add: apply-sequence mult.assoc [symmetric]) qed lemma apply-power-eq-self-iff : (f ˆ n) h$i a = a ←→ order f a dvd n using apply-power-eq-iff [of f n a 0 ] by (simp add: mod-eq-0-iff-dvd) lemma orbit-equiv: assumes b ∈ orbit f a shows orbit f b = orbit f a (is ?B = ?A) proof from assms obtain n where n < order f a and b: b = (f ˆ n) h$i a by (rule in-orbitE) then show ?B ⊆ ?A by (auto simp add: apply-sequence power-add [symmetric] intro: in-orbitI elim!: in-orbitE) from b have (inverse (f ˆ n)) h$i b = (inverse (f ˆ n)) h$i ((f ˆ n) h$i a) by simp then have a: a = (inverse (f ˆ n)) h$i b by (simp add: apply-sequence) then show ?A ⊆ ?B apply (auto simp add: apply-sequence power-add [symmetric] intro: in-orbitI elim!: in-orbitE) unfolding apply-times comp-def apply-inverse-power-eq

676 unfolding apply-sequence power-add [symmetric] apply (rule in-orbitI ) apply rule done qed lemma orbit-apply [simp]: orbit f (f h$i a) = orbit f a by (rule orbit-equiv) simp lemma order-apply [simp]: order f (f h$i a) = order f a by (simp only: order-def comp-def orbit-apply) lemma orbit-apply-inverse [simp]: orbit f (inverse f h$i a) = orbit f a by (rule orbit-equiv) simp lemma order-apply-inverse [simp]: order f (inverse f h$i a) = order f a by (simp only: order-def comp-def orbit-apply-inverse) lemma orbit-apply-power [simp]: orbit f ((f ˆ n) h$i a) = orbit f a by (rule orbit-equiv) simp lemma order-apply-power [simp]: order f ((f ˆ n) h$i a) = order f a by (simp only: order-def comp-def orbit-apply-power) lemma orbit-inverse [simp]: orbit (inverse f ) = orbit f proof (rule ext, rule set-eqI , rule) fix b a assume b ∈ orbit f a then obtain n where b: b = (f ˆ n) h$i a n < order f a by (rule in-orbitE) then have b = apply (inverse (inverse f ) ˆ n) a by simp then have b = apply (inverse (inverse f ˆ n)) a by (simp add: perm-power-inverse) then have b = apply (inverse f ˆ (n ∗ (order (inverse f ˆ n) a − 1 ))) a by (simp add: apply-inverse-eq-apply-power-order-minus-one power-mult) then show b ∈ orbit (inverse f ) a by simp next fix b a assume b ∈ orbit (inverse f ) a then show b ∈ orbit f a by (rule in-orbitE)

677 (simp add: apply-inverse-eq-apply-power-order-minus-one perm-power-inverse power-mult [symmetric]) qed lemma order-inverse [simp]: order (inverse f ) = order f by (simp add: order-def ) lemma orbit-disjoint: assumes orbit f a 6= orbit f b shows orbit f a ∩ orbit f b = {} proof (rule ccontr) assume orbit f a ∩ orbit f b 6= {} then obtain c where c ∈ orbit f a ∩ orbit f b by blast then have c ∈ orbit f a and c ∈ orbit f b by auto then obtain m n where c = (f ˆ m) h$i a and c = apply (f ˆ n) b by (blast elim!: in-orbitE) then have (f ˆ m) h$i a = apply (f ˆ n) b by simp then have apply (inverse f ˆ m) ((f ˆ m) h$i a) = apply (inverse f ˆ m)(apply (f ˆ n) b) by simp then have ∗: apply (inverse f ˆ m ∗ f ˆ n) b = a by (simp add: apply-sequence perm-power-inverse) have a ∈ orbit f b proof (cases n m rule: linorder-cases) case equal with ∗ show ?thesis by (simp add: perm-power-inverse) next case less moreover define q where q = m − n ultimately have m = q + n by arith with ∗ have apply (inverse f ˆ q) b = a by (simp add: power-add mult.assoc perm-power-inverse) then have a ∈ orbit (inverse f ) b by (rule in-orbitI ) then show ?thesis by simp next case greater moreover define q where q = n − m ultimately have n = m + q by arith with ∗ have apply (f ˆ q) b = a by (simp add: power-add mult.assoc [symmetric] perm-power-inverse) then show ?thesis by (rule in-orbitI ) qed

678 with assms show False by (auto dest: orbit-equiv) qed

103.4 Swaps lift-definition swap :: 0a ⇒ 0a ⇒ 0a perm (h-↔-i) is λa b. Fun.swap a b id proof fix a b :: 0a have {c. Fun.swap a b id c 6= c} ⊆ {a, b} by (auto simp add: Fun.swap-def ) then show finite {c. Fun.swap a b id c 6= c} by (rule finite-subset) simp qed simp lemma apply-swap-simp [simp]: ha↔bi h$i a = b ha↔bi h$i b = a by (transfer; simp)+ lemma apply-swap-same [simp]: c 6= a =⇒ c 6= b =⇒ ha↔bi h$i c = c by transfer simp lemma apply-swap-eq-iff [simp]: ha↔bi h$i c = a ←→ c = b ha↔bi h$i c = b ←→ c = a by (transfer; auto simp add: Fun.swap-def )+ lemma swap-1 [simp]: ha↔ai = 1 by transfer simp lemma swap-sym: hb↔ai = ha↔bi by (transfer; auto simp add: Fun.swap-def )+ lemma swap-self [simp]: ha↔bi ∗ ha↔bi = 1 by transfer (simp add: Fun.swap-def fun-eq-iff ) lemma affected-swap: a 6= b =⇒ affected ha↔bi = {a, b} by transfer (auto simp add: Fun.swap-def ) lemma inverse-swap [simp]: inverse ha↔bi = ha↔bi by transfer (auto intro: inv-equality simp: Fun.swap-def )

679 103.5 Permutations specified by cycles fun cycle :: 0a list ⇒ 0a perm (h-i) where h[]i = 1 | h[a]i = 1 | ha # b # asi = ha # asi ∗ ha↔bi We do not continue and restrict ourselves to syntax from here. See also introductory note.

103.6 Syntax bundle no-permutation-syntax begin no-notation swap (h-↔-i) no-notation cycle (h-i) no-notation apply (infixl h$i 999 ) end bundle permutation-syntax begin notation swap (h-↔-i) notation cycle (h-i) notation apply (infixl h$i 999 ) no-notation apply (op h$i) end unbundle no-permutation-syntax end

104 Lists with elements distinct as canonical ex- ample for datatype invariants theory Dlist imports Main begin

104.1 The type of distinct lists typedef 0a dlist = {xs:: 0a list. distinct xs} morphisms list-of-dlist Abs-dlist proof show [] ∈ {xs. distinct xs} by simp qed setup-lifting type-definition-dlist

680 lemma dlist-eq-iff : dxs = dys ←→ list-of-dlist dxs = list-of-dlist dys by (simp add: list-of-dlist-inject) lemma dlist-eqI : list-of-dlist dxs = list-of-dlist dys =⇒ dxs = dys by (simp add: dlist-eq-iff )

Formal, totalized constructor for 0a dlist: definition Dlist :: 0a list ⇒ 0a dlist where Dlist xs = Abs-dlist (remdups xs) lemma distinct-list-of-dlist [simp, intro]: distinct (list-of-dlist dxs) using list-of-dlist [of dxs] by simp lemma list-of-dlist-Dlist [simp]: list-of-dlist (Dlist xs) = remdups xs by (simp add: Dlist-def Abs-dlist-inverse) lemma remdups-list-of-dlist [simp]: remdups (list-of-dlist dxs) = list-of-dlist dxs by simp lemma Dlist-list-of-dlist [simp, code abstype]: Dlist (list-of-dlist dxs) = dxs by (simp add: Dlist-def list-of-dlist-inverse distinct-remdups-id)

Fundamental operations: context begin qualified definition empty :: 0a dlist where empty = Dlist [] qualified definition insert :: 0a ⇒ 0a dlist ⇒ 0a dlist where insert x dxs = Dlist (List.insert x (list-of-dlist dxs)) qualified definition remove :: 0a ⇒ 0a dlist ⇒ 0a dlist where remove x dxs = Dlist (remove1 x (list-of-dlist dxs)) qualified definition map :: ( 0a ⇒ 0b) ⇒ 0a dlist ⇒ 0b dlist where map f dxs = Dlist (remdups (List.map f (list-of-dlist dxs))) qualified definition filter :: ( 0a ⇒ bool) ⇒ 0a dlist ⇒ 0a dlist where filter P dxs = Dlist (List.filter P (list-of-dlist dxs)) qualified definition rotate :: nat ⇒ 0a dlist ⇒ 0a dlist where rotate n dxs = Dlist (List.rotate n (list-of-dlist dxs))

681 end

Derived operations: context begin qualified definition null :: 0a dlist ⇒ bool where null dxs = List.null (list-of-dlist dxs) qualified definition member :: 0a dlist ⇒ 0a ⇒ bool where member dxs = List.member (list-of-dlist dxs) qualified definition length :: 0a dlist ⇒ nat where length dxs = List.length (list-of-dlist dxs) qualified definition fold :: ( 0a ⇒ 0b ⇒ 0b) ⇒ 0a dlist ⇒ 0b ⇒ 0b where fold f dxs = List.fold f (list-of-dlist dxs) qualified definition foldr :: ( 0a ⇒ 0b ⇒ 0b) ⇒ 0a dlist ⇒ 0b ⇒ 0b where foldr f dxs = List.foldr f (list-of-dlist dxs) end

104.2 Executable version obeying invariant lemma list-of-dlist-empty [simp, code abstract]: list-of-dlist Dlist.empty = [] by (simp add: Dlist.empty-def ) lemma list-of-dlist-insert [simp, code abstract]: list-of-dlist (Dlist.insert x dxs) = List.insert x (list-of-dlist dxs) by (simp add: Dlist.insert-def ) lemma list-of-dlist-remove [simp, code abstract]: list-of-dlist (Dlist.remove x dxs) = remove1 x (list-of-dlist dxs) by (simp add: Dlist.remove-def ) lemma list-of-dlist-map [simp, code abstract]: list-of-dlist (Dlist.map f dxs) = remdups (List.map f (list-of-dlist dxs)) by (simp add: Dlist.map-def ) lemma list-of-dlist-filter [simp, code abstract]: list-of-dlist (Dlist.filter P dxs) = List.filter P (list-of-dlist dxs) by (simp add: Dlist.filter-def ) lemma list-of-dlist-rotate [simp, code abstract]: list-of-dlist (Dlist.rotate n dxs) = List.rotate n (list-of-dlist dxs) by (simp add: Dlist.rotate-def )

682 Explicit executable conversion definition dlist-of-list [simp]: dlist-of-list = Dlist lemma [code abstract]: list-of-dlist (dlist-of-list xs) = remdups xs by simp

Equality instantiation dlist :: (equal) equal begin definition HOL.equal dxs dys ←→ HOL.equal (list-of-dlist dxs)(list-of-dlist dys) instance by standard (simp add: equal-dlist-def equal list-of-dlist-inject) end declare equal-dlist-def [code] lemma [code nbe]: HOL.equal (dxs :: 0a::equal dlist) dxs ←→ True by (fact equal-refl)

104.3 Induction principle and case distinction lemma dlist-induct [case-names empty insert, induct type: dlist]: assumes empty: P Dlist.empty assumes insrt: Vx dxs. ¬ Dlist.member dxs x =⇒ P dxs =⇒ P (Dlist.insert x dxs) shows P dxs proof (cases dxs) case (Abs-dlist xs) then have distinct xs and dxs: dxs = Dlist xs by (simp-all add: Dlist-def distinct-remdups-id) from hdistinct xs i have P (Dlist xs) proof (induct xs) case Nil from empty show ?case by (simp add: Dlist.empty-def ) next case (Cons x xs) then have ¬ Dlist.member (Dlist xs) x and P (Dlist xs) by (simp-all add: Dlist.member-def List.member-def ) with insrt have P (Dlist.insert x (Dlist xs)) . with Cons show ?case by (simp add: Dlist.insert-def distinct-remdups-id) qed with dxs show P dxs by simp qed lemma dlist-case [cases type: dlist]:

683 obtains (empty) dxs = Dlist.empty | (insert) x dys where ¬ Dlist.member dys x and dxs = Dlist.insert x dys proof (cases dxs) case (Abs-dlist xs) then have dxs: dxs = Dlist xs and distinct: distinct xs by (simp-all add: Dlist-def distinct-remdups-id) show thesis proof (cases xs) case Nil with dxs have dxs = Dlist.empty by (simp add: Dlist.empty-def ) with empty show ?thesis . next case (Cons x xs) with dxs distinct have ¬ Dlist.member (Dlist xs) x and dxs = Dlist.insert x (Dlist xs) by (simp-all add: Dlist.member-def List.member-def Dlist.insert-def distinct-remdups-id) with insert show ?thesis . qed qed

104.4 Functorial structure functor map: map by (simp-all add: remdups-map-remdups fun-eq-iff dlist-eq-iff )

104.5 Quickcheck generators quickcheck-generator dlist predicate: distinct constructors: Dlist.empty, Dlist.insert

104.6 BNF instance context begin qualified fun wpull :: ( 0a × 0b) list ⇒ ( 0b × 0c) list ⇒ ( 0a × 0c) list where wpull [] ys = [] | wpull xs [] = [] | wpull ((a, b)# xs) ((b 0, c)# ys) = (if b ∈ snd ‘ set xs then (a, the (map-of (rev ((b 0, c)# ys)) b)) # wpull xs ((b 0, c)# ys) else if b 0 ∈ fst ‘ set ys then (the (map-of (map prod.swap (rev ((a, b)# xs))) b 0), c)# wpull ((a, b)# xs) ys else (a, c)# wpull xs ys) qualified lemma wpull-eq-Nil-iff [simp]: wpull xs ys = [] ←→ xs = [] ∨ ys = [] by(cases (xs, ys) rule: wpull.cases) simp-all qualified lemma wpull-induct [consumes 1 ,

684 case-names Nil left[xs eq in-set IH ] right[xs ys eq in-set IH ] step[xs ys eq IH ] ]: assumes eq: remdups (map snd xs) = remdups (map fst ys) and Nil: P [] [] and left: Va b xs b 0 c ys. [[ b ∈ snd ‘ set xs; remdups (map snd xs) = remdups (map fst ((b 0, c)# ys)); (b, the (map-of (rev ((b 0, c)# ys)) b)) ∈ set ((b 0, c)# ys); P xs ((b 0, c)# ys) ]] =⇒ P ((a, b)# xs) ((b 0, c)# ys) and right: Va b xs b 0 c ys. [[ b ∈/ snd ‘ set xs; b 0 ∈ fst ‘ set ys; remdups (map snd ((a, b)# xs)) = remdups (map fst ys); (the (map-of (map prod.swap (rev ((a, b)#xs))) b 0), b 0) ∈ set ((a, b)# xs); P ((a, b)# xs) ys ]] =⇒ P ((a, b)# xs) ((b 0, c)# ys) and step: Va b xs c ys. [[ b ∈/ snd ‘ set xs; b ∈/ fst ‘ set ys; remdups (map snd xs) = remdups (map fst ys); P xs ys ]] =⇒ P ((a, b)# xs) ((b, c)# ys) shows P xs ys using eq proof(induction xs ys rule: wpull.induct) case 1 thus ?case by(simp add: Nil) next case 2 thus ?case by(simp split: if-split-asm) next case Cons:(3 a b xs b 0 c ys) let ?xs = (a, b)# xs and ?ys = (b 0, c)# ys consider (xs) b ∈ snd ‘ set xs | (ys) b ∈/ snd ‘ set xs b 0 ∈ fst ‘ set ys | (step) b ∈/ snd ‘ set xs b 0 ∈/ fst ‘ set ys by auto thus ?case proof cases case xs with Cons.prems have eq: remdups (map snd xs) = remdups (map fst ?ys) by auto from xs eq have b ∈ fst ‘ set ?ys by (metis list.set-map set-remdups) hence map-of (rev ?ys) b 6= None unfolding map-of-eq-None-iff by auto then obtain c 0 where map-of (rev ?ys) b = Some c 0 by blast then have (b, the (map-of (rev ?ys) b)) ∈ set ?ys by(auto dest: map-of-SomeD split: if-split-asm) from xs eq this Cons.IH (1 )[OF xs eq] show ?thesis by(rule left) next case ys from ys Cons.prems have eq: remdups (map snd ?xs) = remdups (map fst ys) by auto from ys eq have b 0 ∈ snd ‘ set ?xs by (metis list.set-map set-remdups) hence map-of (map prod.swap (rev ?xs)) b 0 6= None unfolding map-of-eq-None-iff by(auto simp add: image-image) then obtain a 0 where map-of (map prod.swap (rev ?xs)) b 0 = Some a 0 by

685 blast then have (the (map-of (map prod.swap (rev ?xs)) b 0), b 0) ∈ set ?xs by(auto dest: map-of-SomeD split: if-split-asm) from ys eq this Cons.IH (2 )[OF ys eq] show ?thesis by(rule right) next case ∗: step hence remdups (map snd xs) = remdups (map fst ys) b = b 0 using Cons.prems by auto 0 from ∗ this(1 ) Cons.IH (3 )[OF ∗ this(1 )] show ?thesis unfolding hb = b i by(rule step) qed qed qualified lemma set-wpull-subset: assumes remdups (map snd xs) = remdups (map fst ys) shows set (wpull xs ys) ⊆ set xs O set ys using assms by(induction xs ys rule: wpull-induct) auto qualified lemma set-fst-wpull: assumes remdups (map snd xs) = remdups (map fst ys) shows fst ‘ set (wpull xs ys) = fst ‘ set xs using assms by(induction xs ys rule: wpull-induct)(auto intro: rev-image-eqI ) qualified lemma set-snd-wpull: assumes remdups (map snd xs) = remdups (map fst ys) shows snd ‘ set (wpull xs ys) = snd ‘ set ys using assms by(induction xs ys rule: wpull-induct)(auto intro: rev-image-eqI ) qualified lemma wpull: assumes distinct xs and distinct ys and set xs ⊆ {(x, y). R x y} and set ys ⊆ {(x, y). S x y} and eq: remdups (map snd xs) = remdups (map fst ys) shows ∃ zs. distinct zs ∧ set zs ⊆ {(x, y). (R OO S) x y} ∧ remdups (map fst zs) = remdups (map fst xs) ∧ remdups (map snd zs) = remdups (map snd ys) proof(intro exI conjI ) let ?zs = remdups (wpull xs ys) show distinct ?zs by simp show set ?zs ⊆ {(x, y). (R OO S) x y} using assms(3 −4 ) set-wpull-subset[OF eq] by fastforce show remdups (map fst ?zs) = remdups (map fst xs) unfolding remdups-map-remdups using eq by(induction xs ys rule: wpull-induct)(auto simp add: set-fst-wpull intro: rev-image-eqI ) show remdups (map snd ?zs) = remdups (map snd ys) unfolding remdups-map-remdups using eq by(induction xs ys rule: wpull-induct)(auto simp add: set-snd-wpull intro: rev-image-eqI )

686 qed qualified lift-definition set :: 0a dlist ⇒ 0a set is List.set . qualified lemma map-transfer [transfer-rule]: (rel-fun op = (rel-fun (pcr-dlist op =) (pcr-dlist op =))) (λf x. remdups (List.map f x)) Dlist.map by(simp add: rel-fun-def dlist.pcr-cr-eq cr-dlist-def Dlist.map-def remdups-remdups) bnf 0a dlist map: Dlist.map sets: set bd: natLeq wits: Dlist.empty unfolding OO-Grp-alt mem-Collect-eq subgoal by(rule ext)(simp add: dlist-eq-iff ) subgoal by(rule ext)(simp add: dlist-eq-iff remdups-map-remdups) subgoal by(simp add: dlist-eq-iff set-def cong: list.map-cong) subgoal by(simp add: set-def fun-eq-iff ) subgoal by(simp add: natLeq-card-order) subgoal by(simp add: natLeq-cinfinite) subgoal by(rule ordLess-imp-ordLeq)(simp add: finite-iff-ordLess-natLeq[symmetric] set-def ) subgoal by(rule predicate2I )(transfer; auto simp add: wpull) subgoal by(simp add: set-def ) done lifting-update dlist.lifting lifting-forget dlist.lifting end end

105 Fragments on permuations theory Perm-Fragments imports ∼∼/src/HOL/Library/Perm ∼∼/src/HOL/Library/Dlist begin unbundle permutation-syntax On cycles lemma cycle-prod-list: ha # asi = prod-list (map (λb. ha↔bi)(rev as)) by (induct as) simp-all lemma cycle-append [simp]: ha # as @ bsi = ha # bsi ∗ ha # asi

687 proof (induct as rule: cycle.induct) case (3 b c as) then have ha #(b # as)@ bsi = ha # bsi ∗ ha # b # asi by simp then have ha # as @ bsi ∗ ha↔bi = ha # bsi ∗ ha # asi ∗ ha↔bi by (simp add: ac-simps) then have ha # as @ bsi ∗ ha↔bi ∗ ha↔bi = ha # bsi ∗ ha # asi ∗ ha↔bi ∗ ha↔bi by simp then have ha # as @ bsi = ha # bsi ∗ ha # asi by (simp add: ac-simps) then show ha #(b # c # as)@ bsi = ha # bsi ∗ ha # b # c # asi by (simp add: ac-simps) qed simp-all lemma affected-cycle: affected hasi ⊆ set as proof (induct as rule: cycle.induct) case (3 a b as) from affected-times have affected (ha # asi ∗ ha↔bi) ⊆ affected ha # asi ∪ affected ha↔bi . moreover from 3 have affected (ha # asi) ⊆ insert a (set as) by simp moreover have affected ha↔bi ⊆ {a, b} by (cases a = b)(simp-all add: affected-swap) ultimately have affected (ha # asi ∗ ha↔bi) ⊆ insert a (insert b (set as)) by blast then show ?case by auto qed simp-all lemma orbit-cycle-non-elem: assumes a ∈/ set as shows orbit hasi a = {a} unfolding not-in-affected-iff-orbit-eq-singleton [symmetric] using assms affected-cycle [of as] by blast lemma inverse-cycle: assumes distinct as shows inverse hasi = hrev asi using assms proof (induct as rule: cycle.induct) case (3 a b as) then have ∗: inverse ha # asi = hrev (a # as)i and distinct: distinct (a # b # as)

688 by simp-all show inverse ha # b # asi = hrev (a # b # as)i proof (cases as rule: rev-cases) case Nil with ∗ show ?thesis by (simp add: swap-sym) next case (snoc cs c) with distinct have distinct (a # b # cs @[c]) by simp then have ∗∗: ha↔bi ∗ hc↔ai = hc↔ai ∗ hc↔bi by transfer (auto simp add: comp-def Fun.swap-def ) with snoc ∗ show ?thesis by (simp add: mult.assoc [symmetric]) qed qed simp-all lemma order-cycle-non-elem: assumes a ∈/ set as shows order hasi a = 1 proof − from assms have orbit hasi a = {a} by (rule orbit-cycle-non-elem) then have card (orbit hasi a) = card {a} by simp then show ?thesis by simp qed lemma orbit-cycle-elem: assumes distinct as and a ∈ set as shows orbit hasi a = set as oops — (we need rotation here lemma order-cycle-elem: assumes distinct as and a ∈ set as shows order hasi a = length as oops

Adding fixpoints definition fixate :: 0a ⇒ 0a perm ⇒ 0a perm where fixate a f = (if a ∈ affected f then f ∗ happly (inverse f ) a↔ai else f ) lemma affected-fixate-trivial: assumes a ∈/ affected f shows affected (fixate a f ) = affected f using assms by (simp add: fixate-def ) lemma affected-fixate-binary-circle:

689 assumes order f a = 2 shows affected (fixate a f ) = affected f − {a, apply f a} (is ?A = ?B) proof (rule set-eqI ) interpret bijection apply f by standard simp fix b from assms order-greater-eq-two-iff [of f a] have a ∈ affected f by simp moreover have apply (f ˆ 2 ) a = a by (simp add: assms [symmetric]) ultimately show b ∈ ?A ←→ b ∈ ?B by (cases b ∈ {a, apply (inverse f ) a}) (auto simp add: in-affected power2-eq-square apply-inverse apply-times fixate-def ) qed lemma affected-fixate-no-binary-circle: assumes order f a > 2 shows affected (fixate a f ) = affected f − {a} (is ?A = ?B) proof (rule set-eqI ) interpret bijection apply f by standard simp fix b from assms order-greater-eq-two-iff [of f a] have a ∈ affected f by simp moreover from assms have apply f (apply f a) 6= a using apply-power-eq-iff [of f 2 a 0 ] by (simp add: power2-eq-square apply-times) ultimately show b ∈ ?A ←→ b ∈ ?B by (cases b ∈ {a, apply (inverse f ) a}) (auto simp add: in-affected apply-inverse apply-times fixate-def ) qed lemma affected-fixate: affected (fixate a f ) ⊆ affected f − {a} proof − have a ∈/ affected f ∨ order f a = 2 ∨ order f a > 2 by (auto simp add: not-less dest: affected-order-greater-eq-two) then consider a ∈/ affected f | order f a = 2 | order f a > 2 by blast then show ?thesis apply cases using affected-fixate-trivial [of a f ] affected-fixate-binary-circle [of f a] affected-fixate-no-binary-circle [of f a] by auto qed lemma orbit-fixate-self [simp]:

690 orbit (fixate a f ) a = {a} proof − have apply (f ∗ inverse f ) a = a by simp then have apply f (apply (inverse f ) a) = a by (simp only: apply-times comp-apply) then show ?thesis by (simp add: fixate-def not-in-affected-iff-orbit-eq-singleton [symmetric] in-affected apply-times) qed lemma order-fixate-self [simp]: order (fixate a f ) a = 1 proof − have card (orbit (fixate a f ) a) = card {a} by simp then show ?thesis by (simp only: card-orbit-eq) simp qed lemma assumes b ∈/ orbit f a shows orbit (fixate b f ) a = orbit f a oops lemma assumes b ∈ orbit f a and b 6= a shows orbit (fixate b f ) a = orbit f a − {b} oops

Distilling cycles from permutations inductive-set orbits :: 0a perm ⇒ 0a set set for f where in-orbitsI : a ∈ affected f =⇒ orbit f a ∈ orbits f lemma orbits-unfold: orbits f = orbit f ‘ affected f by (auto intro: in-orbitsI elim: orbits.cases) lemma in-orbit-affected: assumes b ∈ orbit f a assumes a ∈ affected f shows b ∈ affected f proof (cases a = b) case True with assms show ?thesis by simp next case False with assms have {a, b} ⊆ orbit f a by auto also from assms have orbit f a ⊆ affected f

691 by (blast intro!: orbit-subset-eq-affected) finally show ?thesis by simp qed lemma Union-orbits [simp]: S orbits f = affected f by (auto simp add: orbits.simps intro: in-orbitsI in-orbit-affected) lemma finite-orbits [simp]: finite (orbits f ) by (simp add: orbits-unfold) lemma card-in-orbits: assumes A ∈ orbits f shows card A ≥ 2 using assms by cases (auto dest: affected-order-greater-eq-two) lemma disjoint-orbits: assumes A ∈ orbits f and B ∈ orbits f and A 6= B shows A ∩ B = {} using hA ∈ orbits f i apply cases using hB ∈ orbits f i apply cases using hA 6= B i apply (simp-all add: orbit-disjoint) done definition trace :: 0a ⇒ 0a perm ⇒ 0a list where trace a f = map (λn. apply (f ˆ n) a)[0 ..

692 with hfinite Ai show ?thesis by (simp add: sorted-list-of-set) qed

Misc primrec subtract :: 0a list ⇒ 0a list ⇒ 0a list where subtract [] ys = ys | subtract (x # xs) ys = subtract xs (removeAll x ys) lemma length-subtract-less-eq [simp]: length (subtract xs ys) ≤ length ys proof (induct xs arbitrary: ys) case Nil then show ?case by simp next case (Cons x xs) then have length (subtract xs (removeAll x ys)) ≤ length (removeAll x ys) . also have length (removeAll x ys) ≤ length ys by simp finally show ?case by simp qed end

106 Argo theory Argo-Examples imports Complex-Main begin

This theory is intended to showcase and test different features of the argo proof method. The argo proof method can be applied to propositional problems, problems involving equality reasoning and problems of linear real arithmetic. The argo proof method provides two options. To specify an upper limit of the proof methods run time in seconds, use the option argo-timeout. To specify the amount of output, use the option argo-trace with value none for no tracing output, value basic for viewing the underlying propositions and some timings, and value full for additionally inspecting the proof replay steps. declare[[argo-trace = full]]

106.1 Propositional logic notepad begin

693 have True by argo next have ∼False by argo next fix P :: bool assume False then have P by argo next fix P :: bool assume ∼True then have P by argo next fix P :: bool assume P then have P by argo next fix P :: bool assume ∼∼P then have P by argo next fix PQR :: bool assume P & Q & R then have R & P & Q by argo next fix PQR :: bool assume P &(Q & True & R)&(Q & P)& True then have R & P & Q by argo next fix P Q1 Q2 Q3 Q4 Q5 :: bool assume Q1 &(Q2 & P & Q3 )&(Q4 & ∼P & Q5 ) then have ∼True by argo next fix P Q1 Q2 Q3 :: bool assume (Q1 & False)& Q2 & Q3 then have P::bool by argo next fix PQR :: bool assume P | Q | R then have R | P | Q by argo next fix PQR :: bool assume P | (Q | False | R) | (Q | P) | False then have R | P | Q by argo next fix P Q1 Q2 Q3 Q4 :: bool have (Q1 & P & Q2 ) −−> False | (Q3 | (Q4 | P) | False) by argo next fix Q1 Q2 Q3 Q4 :: bool have Q1 | (Q2 | True | Q3 ) | Q4 by argo

694 next fix PQR :: bool assume (P & Q) | (P & ∼Q) | (P & R) | (P & ∼R) then have P by argo next fix P :: bool assume P = True then have P by argo next fix P :: bool assume False = P then have ∼P by argo next fix PQ :: bool assume P = (∼P) then have Q by argo next fix P :: bool have (∼P) = (∼P) by argo next fix PQ :: bool assume P and ∼Q then have P = (∼Q) by argo next fix PQ :: bool assume ((P::bool) = Q) | (Q = P) then have (P −−> Q)&(Q −−> P) by argo next fix PQ :: bool assume (P::bool) = Q then have Q = P by argo next fix PQR :: bool assume if P then Q else R then have Q | R by argo next fix PQ :: bool assume P | Q and P | ∼Q and ∼P | Q and ∼P | ∼Q then have False by argo next fix PQR :: bool assume P | Q | R and P | Q | ∼R and P | ∼Q | R and P | ∼Q | ∼R and ∼P | Q | R

695 and ∼P | Q | ∼R and ∼P | ∼Q | R and ∼P | ∼Q | ∼R then have False by argo next fix abcdefghijklmnpq :: bool assume (a & b | c & d)&(e & f | g & h) | (i & j | k & l)&(m & n | p & q) then have (a & b | c & d)&(e & f | g & h) | (i & j | k & l)&(m & n | p & q) by argo next fix P :: bool have P=P=P=P=P=P=P=P=P=P by argo next fix a b c d e f p q x :: bool assume a | b | c | d and e | f | (a & d) and ∼(a | (c & ∼c)) | b and ∼(b &(x | ∼x)) | c and ∼(d | False) | c and ∼(c | (∼p &(p | (q & ∼q)))) then have False by argo end

106.2 Equality, congruence and predicates notepad begin fix t :: 0a have t = t by argo next fix t u :: 0a assume t = u then have u = t by argo next fix s t u :: 0a assume s = t and t = u then have s = u by argo next fix s t u v :: 0a assume s = t and t = u and u = v and u = s then have s = v by argo next fix s t u v w :: 0a assume s = t and t = u and s = v and v = w then have w = u by argo next fix s t u a b c :: 0a assume s = t and t = u and a = b and b = c then have s = a −−> c = u by argo

696 next fix a b c d :: 0a assume (a = b & b = c) | (a = d & d = c) then have a = c by argo next fix a b1 b2 b3 b4 c d :: 0a assume (a = b1 & ((b1 = b2 & b2 = b3 ) | (b1 = b4 & b4 = b3 )) & b3 = c) | (a = d & d = c) then have a = c by argo next fix a b :: 0a have (if True then a else b) = a by argo next fix a b :: 0a have (if False then a else b) = b by argo next fix a b :: 0a have (if ¬True then a else b) = b by argo next fix a b :: 0a have (if ¬False then a else b) = a by argo next fix P :: bool fix a :: 0a have (if P then a else a) = a by argo next fix P :: bool fix a b c :: 0a assume P and a = c then have (if P then a else b) = c by argo next fix P :: bool fix a b c :: 0a assume ∼P and b = c then have (if P then a else b) = c by argo next fix PQ :: bool fix a b c d :: 0a assume P and Q and a = d then have (if P then (if Q then a else b) else c) = d by argo next fix a b c :: 0a assume a 6= b and b = c then have a 6= c by argo next fix a b c :: 0a assume a 6= b and a = c then have c 6= b by argo next

697 fix a b c d :: 0a assume a = b and c = d and b 6= d then have a 6= c by argo next fix a b c d :: 0a assume a = b and c = d and d 6= b then have a 6= c by argo next fix a b c d :: 0a assume a = b and c = d and b 6= d then have c 6= a by argo next fix a b c d :: 0a assume a = b and c = d and d 6= b then have c 6= a by argo next fix a b c d e f :: 0a assume a 6= b and b = c and b = d and d = e and a = f then have f 6= e by argo next fix a b :: 0a and f :: 0a ⇒ 0a assume a = b then have f a = f b by argo next fix a b c :: 0a and f :: 0a ⇒ 0a assume f a = f b and b = c then have f a = f c by argo next fix a :: 0a and f :: 0a ⇒ 0a assume f a = a then have f (f a) = a by argo next fix a b :: 0a and f g :: 0a ⇒ 0a assume a = b then have g (f a) = g (f b) by argo next fix a b :: 0a and f g :: 0a ⇒ 0a assume f a = b and g b = a then have f (g (f a)) = b by argo next fix a b :: 0a and g :: 0a ⇒ 0a ⇒ 0a assume a = b then have g a b = g b a by argo next fix a b :: 0a and f :: 0a ⇒ 0a and g :: 0a ⇒ 0a ⇒ 0a assume f a = b then have g (f a) b = g b (f a) by argo next fix a b c d e g h :: 0a and f :: 0a ⇒ 0a ⇒ 0a

698 assume c = d and e = c and e = b and b = h and f g h = d and f g d = a then have a = b by argo next fix a b :: 0a and P :: 0a ⇒ bool assume P a and a = b then have P b by argo next fix a b :: 0a and P :: 0a ⇒ bool assume ∼ P a and a = b then have ∼ P b by argo next fix a b c d :: 0a and P :: 0a ⇒ 0a ⇒ bool assume P a b and a = c and b = d then have P c d by argo next fix a b c d :: 0a and P :: 0a ⇒ 0a ⇒ bool assume ∼ P a b and a = c and b = d then have ∼ P c d by argo end

106.3 Linear real arithmetic 106.3.1 Negation and subtraction notepad begin fix a b :: real have −a = −1 ∗ a −(−a) = a a − b = a + −1 ∗ b a − (−b) = a + b by argo+ end

106.3.2 Multiplication notepad begin fix a b c d :: real have (2 ::real) ∗ 3 = 6 0 ∗ a = 0 a ∗ 0 = 0 1 ∗ a = a a ∗ 1 = a 2 ∗ a = a ∗ 2 2 ∗ a ∗ 3 = 6 ∗ a 2 ∗ a ∗ 3 ∗ 5 = 30 ∗ a a ∗ 0 ∗ b = 0

699 a ∗ (0 ∗ b) = 0 a ∗ (b ∗ c) = (a ∗ b) ∗ c a ∗ (b ∗ (c ∗ d)) = ((a ∗ b) ∗ c) ∗ d a ∗ (b + c + d) = a ∗ b + a ∗ c + a ∗ d by argo+ end

106.3.3 Division notepad begin fix a b c :: real have (6 ::real) / 2 = 3 a / 0 = a / 0 a / 0 <= a / 0 ∼(a / 0 < a / 0 ) 0 / a = 0 a / 1 = a a / 3 = 1 /3 ∗ a 6 ∗ a / 2 = 3 ∗ a a / ((5 ∗ b) / 2 ) = 2 /5 ∗ a / b a / (5 ∗ (b / 2 )) = 2 /5 ∗ a / b (a / 5 ) ∗ (b / 2 ) = 1 /10 ∗ a ∗ b a / (3 ∗ b) = 1 /3 ∗ a / b (a + b) / 5 = 1 /5 ∗ a + 1 /5 ∗ b a / (5 ∗ 1 /5 ) = a by argo+ end

106.3.4 Addition notepad begin fix a b c d :: real have a + b = b + a a + b + c = c + b + a a + b + c + d = d + c + b + a a + (b + (c + d)) = ((a + b) + c) + d (5 ::real) + −3 = 2 (3 ::real) + 5 + −1 = 7 2 + a = a + 2 a + b + a = b + 2 ∗ a −1 + a + −1 + 2 + b + 5 /3 + b + 1 /3 + 5 ∗ b + 2 /3 = 8 /3 + a + 7 ∗ b 1 + b + b + 5 ∗ b + 3 ∗ a + 7 + a + 2 = 10 + 4 ∗ a + 7 ∗ b by argo+ end

700 106.3.5 Minimum and maximum notepad begin fix a b :: real have min (3 ::real) 5 = 3 min (5 ::real) 3 = 3 min (3 ::real)(−5 ) = −5 min (−5 ::real) 3 = −5 min a a = a a ≤ b −→ min a b = a a > b −→ min a b = b min a b ≤ a min a b ≤ b min a b = min b a by argo+ next fix a b :: real have max (3 ::real) 5 = 5 max (5 ::real) 3 = 5 max (3 ::real)(−5 ) = 3 max (−5 ::real) 3 = 3 max a a = a a ≤ b −→ max a b = b a > b −→ max a b = a a ≤ max a b b ≤ max a b max a b = max b a by argo+ next fix a b :: real have min a b ≤ max a b min a b + max a b = a + b a < b −→ min a b < max a b by argo+ end

106.3.6 Absolute value notepad begin fix a :: real have abs (3 ::real) = 3 abs (−3 ::real) = 3 0 ≤ abs a a ≤ abs a

701 a ≥ 0 −→ abs a = a a < 0 −→ abs a = −a abs (abs a) = abs a by argo+ end

106.3.7 Equality notepad begin fix a b c d :: real have (3 ::real) = 3 ∼((3 ::real) = 4 ) ∼((4 ::real) = 3 ) 3 ∗ a = 5 −−> a = 5 /3 −3 ∗ a = 5 −−> −5 /3 = a 5 = 3 ∗ a −−> 5 /3 = a 5 = −3 ∗ a −−> a = −5 /3 2 + 3 ∗ a = 4 −−> a = 2 /3 4 = 2 + 3 ∗ a −−> 2 /3 = a 2 + 3 ∗ a + 5 ∗ b + c = 4 −−> 3 ∗ a + 5 ∗ b + c = 2 4 = 2 + 3 ∗ a + 5 ∗ b + c −−> 2 = 3 ∗ a + 5 ∗ b + c −2 ∗ a + b + −3 ∗ c = 7 −−> −7 = 2 ∗ a + −1 ∗ b + 3 ∗ c 7 = −2 ∗ a + b + −3 ∗ c −−> 2 ∗ a + −1 ∗ b + 3 ∗ c = −7 −2 ∗ a + b + −3 ∗ c + 4 ∗ d = 7 −−> −7 = 2 ∗ a + −1 ∗ b + 3 ∗ c + −4 ∗ d 7 = −2 ∗ a + b + −3 ∗ c + 4 ∗ d −−> 2 ∗ a + −1 ∗ b + 3 ∗ c + −4 ∗ d = −7 a + 3 ∗ b = 5 ∗ c + b −−> a + 2 ∗ b + −5 ∗ c = 0 by argo+ end

106.3.8 Less-equal notepad begin fix a b c d :: real have (3 ::real) <= 3 (3 ::real) <= 4 ∼((4 ::real) <= 3 ) 3 ∗ a <= 5 −−> a <= 5 /3 −3 ∗ a <= 5 −−> −5 /3 <= a 5 <= 3 ∗ a −−> 5 /3 <= a 5 <= −3 ∗ a −−> a <= −5 /3 2 + 3 ∗ a <= 4 −−> a <= 2 /3 4 <= 2 + 3 ∗ a −−> 2 /3 <= a 2 + 3 ∗ a + 5 ∗ b + c <= 4 −−> 3 ∗ a + 5 ∗ b + c <= 2 4 <= 2 + 3 ∗ a + 5 ∗ b + c −−> 2 <= 3 ∗ a + 5 ∗ b + c

702 −2 ∗ a + b + −3 ∗ c <= 7 −−> −7 <= 2 ∗ a + −1 ∗ b + 3 ∗ c 7 <= −2 ∗ a + b + −3 ∗ c −−> 2 ∗ a + −1 ∗ b + 3 ∗ c <= −7 −2 ∗ a + b + −3 ∗ c + 4 ∗ d <= 7 −−> −7 <= 2 ∗ a + −1 ∗ b + 3 ∗ c + −4 ∗ d 7 <= −2 ∗ a + b + −3 ∗ c + 4 ∗ d −−> 2 ∗ a + −1 ∗ b + 3 ∗ c + −4 ∗ d <= −7 a + 3 ∗ b <= 5 ∗ c + b −−> a + 2 ∗ b + −5 ∗ c <= 0 by argo+ end

106.3.9 Less notepad begin fix a b c d :: real have (3 ::real) < 4 ∼((3 ::real) < 3 ) ∼((4 ::real) < 3 ) 3 ∗ a < 5 −−> a < 5 /3 −3 ∗ a < 5 −−> −5 /3 < a 5 < 3 ∗ a −−> 5 /3 < a 5 < −3 ∗ a −−> a < −5 /3 2 + 3 ∗ a < 4 −−> a < 2 /3 4 < 2 + 3 ∗ a −−> 2 /3 < a 2 + 3 ∗ a + 5 ∗ b + c < 4 −−> 3 ∗ a + 5 ∗ b + c < 2 4 < 2 + 3 ∗ a + 5 ∗ b + c −−> 2 < 3 ∗ a + 5 ∗ b + c −2 ∗ a + b + −3 ∗ c < 7 −−> −7 < 2 ∗ a + −1 ∗ b + 3 ∗ c 7 < −2 ∗ a + b + −3 ∗ c −−> 2 ∗ a + −1 ∗ b + 3 ∗ c < −7 −2 ∗ a + b + −3 ∗ c + 4 ∗ d < 7 −−> −7 < 2 ∗ a + −1 ∗ b + 3 ∗ c + −4 ∗ d 7 < −2 ∗ a + b + −3 ∗ c + 4 ∗ d −−> 2 ∗ a + −1 ∗ b + 3 ∗ c + −4 ∗ d < −7 a + 3 ∗ b < 5 ∗ c + b −−> a + 2 ∗ b + −5 ∗ c < 0 by argo+ end

106.3.10 Other examples notepad begin have (0 ::real) < 1 (47 ::real) + 11 < 8 ∗ 15 by argo+ next fix a :: real assume a < 3 then have a < 5 a <= 5 ∼(5 < a) ∼(5 <= a) by argo+ next

703 fix a :: real assume a <= 3 then have a < 5 a <= 5 ∼(5 < a) ∼(5 <= a) by argo+ next fix a :: real assume ∼(3 < a) then have a < 5 a <= 5 ∼(5 < a) ∼(5 <= a) by argo+ next fix a :: real assume ∼(3 <= a) then have a < 5 a <= 5 ∼(5 < a) ∼(5 <= a) by argo+ next fix a :: real have a < 3 | a = 3 | a > 3 by argo next fix a b :: real assume 0 < a and a < b then have 0 < b by argo next fix a b :: real assume 0 < a and a ≤ b then have 0 ≤ b by argo next fix a b :: real assume 0 ≤ a and a < b then have 0 ≤ b by argo next fix a b :: real assume 0 ≤ a and a ≤ b then have 0 ≤ b by argo next fix a b c :: real assume 2 ≤ a and 3 ≤ b and c ≤ 5 then have −2 ∗ a + −3 ∗ b + 5 ∗ c < 13 by argo next fix a b c :: real assume 2 ≤ a and 3 ≤ b and c ≤ 5 then have −2 ∗ a + −3 ∗ b + 5 ∗ c ≤ 12 by argo next fix a b :: real assume a = 2 and b = 3 then have a + b > 5 ∨ a < b by argo next fix a b c :: real assume 5 < b + c and a + c < 0 and a > 0 then have b > 0 by argo next fix a b c :: real assume a + b < 7 and 5 < b + c and a + c < 0 and a > 0

704 then have 0 < b ∧ b < 7 by argo next fix a b c :: real assume a < b and b < c and c < a then have False by argo next fix a b :: real assume a − 5 > b then have b < a by argo next fix a b :: real have (a − b) − a = (a − a) − b by argo next fix n m n 0 m 0 :: real have (n < m & m < n 0) | (n < m & m = n 0) | (n < n 0 & n 0 < m) | (n = n 0 & n 0 < m) | (n = m & m < n 0) | (n 0 < m & m < n) | (n 0 < m & m = n) | (n 0 < n & n < m) | (n 0 = n & n < m) | (n 0 = m & m < n) | (m < n & n < n 0) | (m < n & n 0 = n) | (m < n 0 & n 0 < n) | (m = n & n < n 0) | (m = n 0 & n 0 < n) | (n 0 = m & m = n) by argo end

106.4 Larger examples declare[[argo-trace = basic, argo-timeout = 60 ]]

Translated from TPTP problem library: PUZ015-2.006.dimacs lemma assumes 1 : ∼x0 and 2 : ∼x30 and 3 : ∼x29 and 4 : ∼x59 and 5 : x1 | x31 | x0 and 6 : x2 | x32 | x1 and 7 : x3 | x33 | x2 and 8 : x4 | x34 | x3 and 9 : x35 | x4 and 10 : x5 | x36 | x30 and 11 : x6 | x37 | x5 | x31 and 12 : x7 | x38 | x6 | x32 and 13 : x8 | x39 | x7 | x33 and 14 : x9 | x40 | x8 | x34 and 15 : x41 | x9 | x35 and 16 : x10 | x42 | x36 and 17 : x11 | x43 | x10 | x37 and 18 : x12 | x44 | x11 | x38 and 19 : x13 | x45 | x12 | x39

705 and 20 : x14 | x46 | x13 | x40 and 21 : x47 | x14 | x41 and 22 : x15 | x48 | x42 and 23 : x16 | x49 | x15 | x43 and 24 : x17 | x50 | x16 | x44 and 25 : x18 | x51 | x17 | x45 and 26 : x19 | x52 | x18 | x46 and 27 : x53 | x19 | x47 and 28 : x20 | x54 | x48 and 29 : x21 | x55 | x20 | x49 and 30 : x22 | x56 | x21 | x50 and 31 : x23 | x57 | x22 | x51 and 32 : x24 | x58 | x23 | x52 and 33 : x59 | x24 | x53 and 34 : x25 | x54 and 35 : x26 | x25 | x55 and 36 : x27 | x26 | x56 and 37 : x28 | x27 | x57 and 38 : x29 | x28 | x58 and 39 : ∼x1 | ∼x31 and 40 : ∼x1 | ∼x0 and 41 : ∼x31 | ∼x0 and 42 : ∼x2 | ∼x32 and 43 : ∼x2 | ∼x1 and 44 : ∼x32 | ∼x1 and 45 : ∼x3 | ∼x33 and 46 : ∼x3 | ∼x2 and 47 : ∼x33 | ∼x2 and 48 : ∼x4 | ∼x34 and 49 : ∼x4 | ∼x3 and 50 : ∼x34 | ∼x3 and 51 : ∼x35 | ∼x4 and 52 : ∼x5 | ∼x36 and 53 : ∼x5 | ∼x30 and 54 : ∼x36 | ∼x30 and 55 : ∼x6 | ∼x37 and 56 : ∼x6 | ∼x5 and 57 : ∼x6 | ∼x31 and 58 : ∼x37 | ∼x5 and 59 : ∼x37 | ∼x31 and 60 : ∼x5 | ∼x31 and 61 : ∼x7 | ∼x38 and 62 : ∼x7 | ∼x6 and 63 : ∼x7 | ∼x32 and 64 : ∼x38 | ∼x6 and 65 : ∼x38 | ∼x32 and 66 : ∼x6 | ∼x32 and 67 : ∼x8 | ∼x39 and 68 : ∼x8 | ∼x7

706 and 69 : ∼x8 | ∼x33 and 70 : ∼x39 | ∼x7 and 71 : ∼x39 | ∼x33 and 72 : ∼x7 | ∼x33 and 73 : ∼x9 | ∼x40 and 74 : ∼x9 | ∼x8 and 75 : ∼x9 | ∼x34 and 76 : ∼x40 | ∼x8 and 77 : ∼x40 | ∼x34 and 78 : ∼x8 | ∼x34 and 79 : ∼x41 | ∼x9 and 80 : ∼x41 | ∼x35 and 81 : ∼x9 | ∼x35 and 82 : ∼x10 | ∼x42 and 83 : ∼x10 | ∼x36 and 84 : ∼x42 | ∼x36 and 85 : ∼x11 | ∼x43 and 86 : ∼x11 | ∼x10 and 87 : ∼x11 | ∼x37 and 88 : ∼x43 | ∼x10 and 89 : ∼x43 | ∼x37 and 90 : ∼x10 | ∼x37 and 91 : ∼x12 | ∼x44 and 92 : ∼x12 | ∼x11 and 93 : ∼x12 | ∼x38 and 94 : ∼x44 | ∼x11 and 95 : ∼x44 | ∼x38 and 96 : ∼x11 | ∼x38 and 97 : ∼x13 | ∼x45 and 98 : ∼x13 | ∼x12 and 99 : ∼x13 | ∼x39 and 100 : ∼x45 | ∼x12 and 101 : ∼x45 | ∼x39 and 102 : ∼x12 | ∼x39 and 103 : ∼x14 | ∼x46 and 104 : ∼x14 | ∼x13 and 105 : ∼x14 | ∼x40 and 106 : ∼x46 | ∼x13 and 107 : ∼x46 | ∼x40 and 108 : ∼x13 | ∼x40 and 109 : ∼x47 | ∼x14 and 110 : ∼x47 | ∼x41 and 111 : ∼x14 | ∼x41 and 112 : ∼x15 | ∼x48 and 113 : ∼x15 | ∼x42 and 114 : ∼x48 | ∼x42 and 115 : ∼x16 | ∼x49 and 116 : ∼x16 | ∼x15 and 117 : ∼x16 | ∼x43

707 and 118 : ∼x49 | ∼x15 and 119 : ∼x49 | ∼x43 and 120 : ∼x15 | ∼x43 and 121 : ∼x17 | ∼x50 and 122 : ∼x17 | ∼x16 and 123 : ∼x17 | ∼x44 and 124 : ∼x50 | ∼x16 and 125 : ∼x50 | ∼x44 and 126 : ∼x16 | ∼x44 and 127 : ∼x18 | ∼x51 and 128 : ∼x18 | ∼x17 and 129 : ∼x18 | ∼x45 and 130 : ∼x51 | ∼x17 and 131 : ∼x51 | ∼x45 and 132 : ∼x17 | ∼x45 and 133 : ∼x19 | ∼x52 and 134 : ∼x19 | ∼x18 and 135 : ∼x19 | ∼x46 and 136 : ∼x52 | ∼x18 and 137 : ∼x52 | ∼x46 and 138 : ∼x18 | ∼x46 and 139 : ∼x53 | ∼x19 and 140 : ∼x53 | ∼x47 and 141 : ∼x19 | ∼x47 and 142 : ∼x20 | ∼x54 and 143 : ∼x20 | ∼x48 and 144 : ∼x54 | ∼x48 and 145 : ∼x21 | ∼x55 and 146 : ∼x21 | ∼x20 and 147 : ∼x21 | ∼x49 and 148 : ∼x55 | ∼x20 and 149 : ∼x55 | ∼x49 and 150 : ∼x20 | ∼x49 and 151 : ∼x22 | ∼x56 and 152 : ∼x22 | ∼x21 and 153 : ∼x22 | ∼x50 and 154 : ∼x56 | ∼x21 and 155 : ∼x56 | ∼x50 and 156 : ∼x21 | ∼x50 and 157 : ∼x23 | ∼x57 and 158 : ∼x23 | ∼x22 and 159 : ∼x23 | ∼x51 and 160 : ∼x57 | ∼x22 and 161 : ∼x57 | ∼x51 and 162 : ∼x22 | ∼x51 and 163 : ∼x24 | ∼x58 and 164 : ∼x24 | ∼x23 and 165 : ∼x24 | ∼x52 and 166 : ∼x58 | ∼x23

708 and 167 : ∼x58 | ∼x52 and 168 : ∼x23 | ∼x52 and 169 : ∼x59 | ∼x24 and 170 : ∼x59 | ∼x53 and 171 : ∼x24 | ∼x53 and 172 : ∼x25 | ∼x54 and 173 : ∼x26 | ∼x25 and 174 : ∼x26 | ∼x55 and 175 : ∼x25 | ∼x55 and 176 : ∼x27 | ∼x26 and 177 : ∼x27 | ∼x56 and 178 : ∼x26 | ∼x56 and 179 : ∼x28 | ∼x27 and 180 : ∼x28 | ∼x57 and 181 : ∼x27 | ∼x57 and 182 : ∼x29 | ∼x28 and 183 : ∼x29 | ∼x58 and 184 : ∼x28 | ∼x58 shows False using assms by argo

Translated from TPTP problem library: MSC007-1.008.dimacs lemma assumes 1 : x0 | x1 | x2 | x3 | x4 | x5 | x6 and 2 : x7 | x8 | x9 | x10 | x11 | x12 | x13 and 3 : x14 | x15 | x16 | x17 | x18 | x19 | x20 and 4 : x21 | x22 | x23 | x24 | x25 | x26 | x27 and 5 : x28 | x29 | x30 | x31 | x32 | x33 | x34 and 6 : x35 | x36 | x37 | x38 | x39 | x40 | x41 and 7 : x42 | x43 | x44 | x45 | x46 | x47 | x48 and 8 : x49 | x50 | x51 | x52 | x53 | x54 | x55 and 9 : ∼x0 | ∼x7 and 10 : ∼x0 | ∼x14 and 11 : ∼x0 | ∼x21 and 12 : ∼x0 | ∼x28 and 13 : ∼x0 | ∼x35 and 14 : ∼x0 | ∼x42 and 15 : ∼x0 | ∼x49 and 16 : ∼x7 | ∼x14 and 17 : ∼x7 | ∼x21 and 18 : ∼x7 | ∼x28 and 19 : ∼x7 | ∼x35 and 20 : ∼x7 | ∼x42 and 21 : ∼x7 | ∼x49 and 22 : ∼x14 | ∼x21 and 23 : ∼x14 | ∼x28 and 24 : ∼x14 | ∼x35 and 25 : ∼x14 | ∼x42 and 26 : ∼x14 | ∼x49

709 and 27 : ∼x21 | ∼x28 and 28 : ∼x21 | ∼x35 and 29 : ∼x21 | ∼x42 and 30 : ∼x21 | ∼x49 and 31 : ∼x28 | ∼x35 and 32 : ∼x28 | ∼x42 and 33 : ∼x28 | ∼x49 and 34 : ∼x35 | ∼x42 and 35 : ∼x35 | ∼x49 and 36 : ∼x42 | ∼x49 and 37 : ∼x1 | ∼x8 and 38 : ∼x1 | ∼x15 and 39 : ∼x1 | ∼x22 and 40 : ∼x1 | ∼x29 and 41 : ∼x1 | ∼x36 and 42 : ∼x1 | ∼x43 and 43 : ∼x1 | ∼x50 and 44 : ∼x8 | ∼x15 and 45 : ∼x8 | ∼x22 and 46 : ∼x8 | ∼x29 and 47 : ∼x8 | ∼x36 and 48 : ∼x8 | ∼x43 and 49 : ∼x8 | ∼x50 and 50 : ∼x15 | ∼x22 and 51 : ∼x15 | ∼x29 and 52 : ∼x15 | ∼x36 and 53 : ∼x15 | ∼x43 and 54 : ∼x15 | ∼x50 and 55 : ∼x22 | ∼x29 and 56 : ∼x22 | ∼x36 and 57 : ∼x22 | ∼x43 and 58 : ∼x22 | ∼x50 and 59 : ∼x29 | ∼x36 and 60 : ∼x29 | ∼x43 and 61 : ∼x29 | ∼x50 and 62 : ∼x36 | ∼x43 and 63 : ∼x36 | ∼x50 and 64 : ∼x43 | ∼x50 and 65 : ∼x2 | ∼x9 and 66 : ∼x2 | ∼x16 and 67 : ∼x2 | ∼x23 and 68 : ∼x2 | ∼x30 and 69 : ∼x2 | ∼x37 and 70 : ∼x2 | ∼x44 and 71 : ∼x2 | ∼x51 and 72 : ∼x9 | ∼x16 and 73 : ∼x9 | ∼x23 and 74 : ∼x9 | ∼x30 and 75 : ∼x9 | ∼x37

710 and 76 : ∼x9 | ∼x44 and 77 : ∼x9 | ∼x51 and 78 : ∼x16 | ∼x23 and 79 : ∼x16 | ∼x30 and 80 : ∼x16 | ∼x37 and 81 : ∼x16 | ∼x44 and 82 : ∼x16 | ∼x51 and 83 : ∼x23 | ∼x30 and 84 : ∼x23 | ∼x37 and 85 : ∼x23 | ∼x44 and 86 : ∼x23 | ∼x51 and 87 : ∼x30 | ∼x37 and 88 : ∼x30 | ∼x44 and 89 : ∼x30 | ∼x51 and 90 : ∼x37 | ∼x44 and 91 : ∼x37 | ∼x51 and 92 : ∼x44 | ∼x51 and 93 : ∼x3 | ∼x10 and 94 : ∼x3 | ∼x17 and 95 : ∼x3 | ∼x24 and 96 : ∼x3 | ∼x31 and 97 : ∼x3 | ∼x38 and 98 : ∼x3 | ∼x45 and 99 : ∼x3 | ∼x52 and 100 : ∼x10 | ∼x17 and 101 : ∼x10 | ∼x24 and 102 : ∼x10 | ∼x31 and 103 : ∼x10 | ∼x38 and 104 : ∼x10 | ∼x45 and 105 : ∼x10 | ∼x52 and 106 : ∼x17 | ∼x24 and 107 : ∼x17 | ∼x31 and 108 : ∼x17 | ∼x38 and 109 : ∼x17 | ∼x45 and 110 : ∼x17 | ∼x52 and 111 : ∼x24 | ∼x31 and 112 : ∼x24 | ∼x38 and 113 : ∼x24 | ∼x45 and 114 : ∼x24 | ∼x52 and 115 : ∼x31 | ∼x38 and 116 : ∼x31 | ∼x45 and 117 : ∼x31 | ∼x52 and 118 : ∼x38 | ∼x45 and 119 : ∼x38 | ∼x52 and 120 : ∼x45 | ∼x52 and 121 : ∼x4 | ∼x11 and 122 : ∼x4 | ∼x18 and 123 : ∼x4 | ∼x25 and 124 : ∼x4 | ∼x32

711 and 125 : ∼x4 | ∼x39 and 126 : ∼x4 | ∼x46 and 127 : ∼x4 | ∼x53 and 128 : ∼x11 | ∼x18 and 129 : ∼x11 | ∼x25 and 130 : ∼x11 | ∼x32 and 131 : ∼x11 | ∼x39 and 132 : ∼x11 | ∼x46 and 133 : ∼x11 | ∼x53 and 134 : ∼x18 | ∼x25 and 135 : ∼x18 | ∼x32 and 136 : ∼x18 | ∼x39 and 137 : ∼x18 | ∼x46 and 138 : ∼x18 | ∼x53 and 139 : ∼x25 | ∼x32 and 140 : ∼x25 | ∼x39 and 141 : ∼x25 | ∼x46 and 142 : ∼x25 | ∼x53 and 143 : ∼x32 | ∼x39 and 144 : ∼x32 | ∼x46 and 145 : ∼x32 | ∼x53 and 146 : ∼x39 | ∼x46 and 147 : ∼x39 | ∼x53 and 148 : ∼x46 | ∼x53 and 149 : ∼x5 | ∼x12 and 150 : ∼x5 | ∼x19 and 151 : ∼x5 | ∼x26 and 152 : ∼x5 | ∼x33 and 153 : ∼x5 | ∼x40 and 154 : ∼x5 | ∼x47 and 155 : ∼x5 | ∼x54 and 156 : ∼x12 | ∼x19 and 157 : ∼x12 | ∼x26 and 158 : ∼x12 | ∼x33 and 159 : ∼x12 | ∼x40 and 160 : ∼x12 | ∼x47 and 161 : ∼x12 | ∼x54 and 162 : ∼x19 | ∼x26 and 163 : ∼x19 | ∼x33 and 164 : ∼x19 | ∼x40 and 165 : ∼x19 | ∼x47 and 166 : ∼x19 | ∼x54 and 167 : ∼x26 | ∼x33 and 168 : ∼x26 | ∼x40 and 169 : ∼x26 | ∼x47 and 170 : ∼x26 | ∼x54 and 171 : ∼x33 | ∼x40 and 172 : ∼x33 | ∼x47 and 173 : ∼x33 | ∼x54

712 and 174 : ∼x40 | ∼x47 and 175 : ∼x40 | ∼x54 and 176 : ∼x47 | ∼x54 and 177 : ∼x6 | ∼x13 and 178 : ∼x6 | ∼x20 and 179 : ∼x6 | ∼x27 and 180 : ∼x6 | ∼x34 and 181 : ∼x6 | ∼x41 and 182 : ∼x6 | ∼x48 and 183 : ∼x6 | ∼x55 and 184 : ∼x13 | ∼x20 and 185 : ∼x13 | ∼x27 and 186 : ∼x13 | ∼x34 and 187 : ∼x13 | ∼x41 and 188 : ∼x13 | ∼x48 and 189 : ∼x13 | ∼x55 and 190 : ∼x20 | ∼x27 and 191 : ∼x20 | ∼x34 and 192 : ∼x20 | ∼x41 and 193 : ∼x20 | ∼x48 and 194 : ∼x20 | ∼x55 and 195 : ∼x27 | ∼x34 and 196 : ∼x27 | ∼x41 and 197 : ∼x27 | ∼x48 and 198 : ∼x27 | ∼x55 and 199 : ∼x34 | ∼x41 and 200 : ∼x34 | ∼x48 and 201 : ∼x34 | ∼x55 and 202 : ∼x41 | ∼x48 and 203 : ∼x41 | ∼x55 and 204 : ∼x48 | ∼x55 shows False using assms by argo lemma 0 ≤ (yc::real) ∧ 0 ≤ yd ∧ 0 ≤ yb ∧ 0 ≤ ya =⇒ 0 ≤ yf ∧ 0 ≤ xh ∧ 0 ≤ ye ∧ 0 ≤ yg =⇒ 0 ≤ yw ∧ 0 ≤ xs ∧ 0 ≤ yu =⇒ 0 ≤ aea ∧ 0 ≤ aee ∧ 0 ≤ aed =⇒ 0 ≤ zy ∧ 0 ≤ xz ∧ 0 ≤ zw =⇒ 0 ≤ zb ∧ 0 ≤ za ∧ 0 ≤ yy ∧ 0 ≤ yz =⇒ 0 ≤ zp ∧ 0 ≤ zo ∧ 0 ≤ yq =⇒ 0 ≤ adp ∧ 0 ≤ aeb ∧ 0 ≤ aec =⇒ 0 ≤ acm ∧ 0 ≤ aco ∧ 0 ≤ acn =⇒ 0 ≤ abl =⇒

713 0 ≤ zr ∧ 0 ≤ zq ∧ 0 ≤ abh =⇒ 0 ≤ abq ∧ 0 ≤ zd ∧ 0 ≤ abo =⇒ 0 ≤ acd ∧ 0 ≤ acc ∧ 0 ≤ xi ∧ 0 ≤ acb =⇒ 0 ≤ acp ∧ 0 ≤ acr ∧ 0 ≤ acq =⇒ 0 ≤ xw ∧ 0 ≤ xr ∧ 0 ≤ xv ∧ 0 ≤ xu =⇒ 0 ≤ zc ∧ 0 ≤ acg ∧ 0 ≤ ach =⇒ 0 ≤ zt ∧ 0 ≤ zs ∧ 0 ≤ xy =⇒ 0 ≤ ady ∧ 0 ≤ adw ∧ 0 ≤ zg =⇒ 0 ≤ abd ∧ 0 ≤ abc ∧ 0 ≤ yr ∧ 0 ≤ abb =⇒ 0 ≤ adi ∧ 0 ≤ x ∧ 0 ≤ adh ∧ 0 ≤ xa =⇒ 0 ≤ aak ∧ 0 ≤ aai ∧ 0 ≤ aad =⇒ 0 ≤ aba ∧ 0 ≤ zh ∧ 0 ≤ aay =⇒ 0 ≤ abg ∧ 0 ≤ ys ∧ 0 ≤ abe =⇒ 0 ≤ abs1 ∧ 0 ≤ yt ∧ 0 ≤ abr ∧ 0 ≤ zu =⇒ 0 ≤ abv ∧ 0 ≤ zn ∧ 0 ≤ abw ∧ 0 ≤ zm =⇒ 0 ≤ adl ∧ 0 ≤ adn =⇒ 0 ≤ acf ∧ 0 ≤ aca =⇒ 0 ≤ ads ∧ 0 ≤ aaq =⇒ 0 ≤ ada =⇒ 0 ≤ aaf ∧ 0 ≤ aac ∧ 0 ≤ aag =⇒ 0 ≤ aal ∧ 0 ≤ acu ∧ 0 ≤ acs ∧ 0 ≤ act =⇒ 0 ≤ aas ∧ 0 ≤ xb ∧ 0 ≤ aat =⇒ 0 ≤ zk ∧ 0 ≤ zj ∧ 0 ≤ zi =⇒ 0 ≤ ack ∧ 0 ≤ acj ∧ 0 ≤ xc ∧ 0 ≤ aci =⇒ 0 ≤ aav ∧ 0 ≤ aah ∧ 0 ≤ xd =⇒ 0 ≤ abt ∧ 0 ≤ xo ∧ 0 ≤ abu ∧ 0 ≤ xn =⇒ 0 ≤ adc ∧ 0 ≤ abz ∧ 0 ≤ adc ∧ 0 ≤ abz =⇒ 0 ≤ xt ∧ 0 ≤ zz ∧ 0 ≤ aab ∧ 0 ≤ aaa =⇒ 0 ≤ adq ∧ 0 ≤ xl ∧ 0 ≤ adr ∧ 0 ≤ adb =⇒ 0 ≤ zf ∧ 0 ≤ yh ∧ 0 ≤ yi =⇒ 0 ≤ aao ∧ 0 ≤ aam ∧ 0 ≤ xe =⇒ 0 ≤ abk ∧ 0 ≤ aby ∧ 0 ≤ abj ∧ 0 ≤ abx =⇒ 0 ≤ yp =⇒ 0 ≤ yl ∧ 0 ≤ yj ∧ 0 ≤ ym =⇒ 0 ≤ acw =⇒ 0 ≤ adk ∧

714 0 ≤ adg ∧ 0 ≤ adj ∧ 0 ≤ adf =⇒ 0 ≤ adv ∧ 0 ≤ xf ∧ 0 ≤ adu =⇒ yc + yd + yb + ya = 1 =⇒ yf + xh + ye + yg = 1 =⇒ yw + xs + yu = 1 =⇒ aea + aee + aed = 1 =⇒ zy + xz + zw = 1 =⇒ zb + za + yy + yz = 1 =⇒ zp + zo + yq = 1 =⇒ adp + aeb + aec = 1 =⇒ acm + aco + acn = 1 =⇒ abl + abl = 1 =⇒ zr + zq + abh = 1 =⇒ abq + zd + abo = 1 =⇒ acd + acc + xi + acb = 1 =⇒ acp + acr + acq = 1 =⇒ xw + xr + xv + xu = 1 =⇒ zc + acg + ach = 1 =⇒ zt + zs + xy = 1 =⇒ ady + adw + zg = 1 =⇒ abd + abc + yr + abb = 1 =⇒ adi + x + adh + xa = 1 =⇒ aak + aai + aad = 1 =⇒ aba + zh + aay = 1 =⇒ abg + ys + abe = 1 =⇒ abs1 + yt + abr + zu = 1 =⇒ abv + zn + abw + zm = 1 =⇒ adl + adn = 1 =⇒ acf + aca = 1 =⇒ ads + aaq = 1 =⇒ ada + ada = 1 =⇒ aaf + aac + aag = 1 =⇒ aal + acu + acs + act = 1 =⇒ aas + xb + aat = 1 =⇒ zk + zj + zi = 1 =⇒ ack + acj + xc + aci = 1 =⇒ aav + aah + xd = 1 =⇒ abt + xo + abu + xn = 1 =⇒ adc + abz + adc + abz = 1 =⇒ xt + zz + aab + aaa = 1 =⇒ adq + xl + adr + adb = 1 =⇒ zf + yh + yi = 1 =⇒ aao + aam + xe = 1 =⇒ abk + aby + abj + abx = 1 =⇒ yp + yp = 1 =⇒ yl + yj + ym = 1 =⇒ acw + acw + acw + acw = 1 =⇒ adk + adg + adj + adf = 1 =⇒ adv + xf + adu = 1 =⇒

715 yd = 0 ∨ yb = 0 =⇒ xh = 0 ∨ ye = 0 =⇒ yy = 0 ∨ za = 0 =⇒ acc = 0 ∨ xi = 0 =⇒ xv = 0 ∨ xr = 0 =⇒ yr = 0 ∨ abc = 0 =⇒ zn = 0 ∨ abw = 0 =⇒ xo = 0 ∨ abu = 0 =⇒ xl = 0 ∨ adr = 0 =⇒ (yr + abd < abl ∨ yr + (abd + abb) < 1 ) ∨ yr + abd = abl ∧ yr + (abd + abb) = 1 =⇒ adb + adr < xn + abu ∨ adb + adr = xn + abu =⇒ (abl < abt ∨ abl < abt + xo) ∨ abl = abt ∧ abl = abt + xo =⇒ yd + yc < abc + abd ∨ yd + yc = abc + abd =⇒ aca < abb + yr ∨ aca = abb + yr =⇒ acb + acc < xu + xv ∨ acb + acc = xu + xv =⇒ (yq < xu + xr ∨ yq + zp < xu + (xr + xw)) ∨ yq = xu + xr ∧ yq + zp = xu + (xr + xw) =⇒ (zw < xw ∨ zw < xw + xv ∨ zw + zy < xw + (xv + xu)) ∨ zw = xw ∧ zw = xw + xv ∧ zw + zy = xw + (xv + xu) =⇒ xs + yw < zs + zt ∨ xs + yw = zs + zt =⇒ aab + xt < ye + yf ∨ aab + xt = ye + yf =⇒ (ya + yb < yg + ye ∨ ya + (yb + yc) < yg + (ye + yf )) ∨ ya + yb = yg + ye ∧ ya + (yb + yc) = yg + (ye + yf ) =⇒ (xu + xv < acb + acc ∨ xu + (xv + xw) < acb + (acc + acd)) ∨ xu + xv = acb + acc ∧ xu + (xv + xw) = acb + (acc + acd) =⇒ (zs < xz + zy ∨ zs + xy < xz + (zy + zw)) ∨ zs = xz + zy ∧ zs + xy = xz + (zy + zw) =⇒ (zs + zt < xz + zy ∨

716 zs + (zt + xy) < xz + (zy + zw)) ∨ zs + zt = xz + zy ∧ zs + (zt + xy) = xz + (zy + zw) =⇒ yg + ye < ya + yb ∨ yg + ye = ya + yb =⇒ (abd < yc ∨ abd + abc < yc + yd) ∨ abd = yc ∧ abd + abc = yc + yd =⇒ (ye + yf < adr + adq ∨ ye + (yf + yg) < adr + (adq + adb)) ∨ ye + yf = adr + adq ∧ ye + (yf + yg) = adr + (adq + adb) =⇒ yh + yi < ym + yj ∨ yh + yi = ym + yj =⇒ (abq < yl ∨ abq + abo < yl + ym) ∨ abq = yl ∧ abq + abo = yl + ym =⇒ (yp < zp ∨ yp < zp + zo ∨ 1 < zp + (zo + yq)) ∨ yp = zp ∧ yp = zp + zo ∧ 1 = zp + (zo + yq) =⇒ (abb + yr < aca ∨ abb + (yr + abd) < aca + acf ) ∨ abb + yr = aca ∧ abb + (yr + abd) = aca + acf =⇒ adw + zg < abe + ys ∨ adw + zg = abe + ys =⇒ zd + abq < ys + abg ∨ zd + abq = ys + abg =⇒ yt + abs1 < aby + abk ∨ yt + abs1 = aby + abk =⇒ (yu < abx ∨ yu < abx + aby ∨ yu + yw < abx + (aby + abk)) ∨ yu = abx ∧ yu = abx + aby ∧ yu + yw = abx + (aby + abk) =⇒ aaf < adv ∨ aaf = adv =⇒ abj + abk < yy + zb ∨ abj + abk = yy + zb =⇒ (abb < yz ∨ abb + abc < yz + za ∨ abb + (abc + abd) < yz + (za + zb)) ∨ abb = yz ∧ abb + abc = yz + za ∧ abb + (abc + abd) = yz + (za + zb) =⇒ (acg + zc < zd + abq ∨ acg + (zc + ach) < zd + (abq + abo)) ∨ acg + zc = zd + abq ∧ acg + (zc + ach) =

717 zd + (abq + abo) =⇒ zf < acm ∨ zf = acm =⇒ (zg + ady < acn + acm ∨ zg + (ady + adw) < acn + (acm + aco)) ∨ zg + ady = acn + acm ∧ zg + (ady + adw) = acn + (acm + aco) =⇒ aay + zh < zi + zj ∨ aay + zh = zi + zj =⇒ zy < zk ∨ zy = zk =⇒ (adn < zm + zn ∨ adn + adl < zm + (zn + abv)) ∨ adn = zm + zn ∧ adn + adl = zm + (zn + abv) =⇒ zo + zp < zs + zt ∨ zo + zp = zs + zt =⇒ zq + zr < zs + zt ∨ zq + zr = zs + zt =⇒ (aai < adi ∨ aai < adi + adh) ∨ aai = adi ∧ aai = adi + adh =⇒ (abr < acj ∨ abr + (abs1 + zu) < acj + (aci + ack)) ∨ abr = acj ∧ abr + (abs1 + zu) = acj + (aci + ack) =⇒ (abl < zw ∨ 1 < zw + zy) ∨ abl = zw ∧ 1 = zw + zy =⇒ (zz + aaa < act + acu ∨ zz + (aaa + aab) < act + (acu + aal)) ∨ zz + aaa = act + acu ∧ zz + (aaa + aab) = act + (acu + aal) =⇒ (aam < aac ∨ aam + aao < aac + aaf ) ∨ aam = aac ∧ aam + aao = aac + aaf =⇒ (aak < aaf ∨ aak + aad < aaf + aag) ∨ aak = aaf ∧ aak + aad = aaf + aag =⇒ (aah < aai ∨ aah + aav < aai + aak) ∨ aah = aai ∧ aah + aav = aai + aak =⇒ act + (acu + aal) < aam + aao ∨ act + (acu + aal) = aam + aao =⇒ (ads < aat ∨ 1 < aat + aas) ∨ ads = aat ∧ 1 = aat + aas =⇒ (aba < aas ∨ aba + aay < aas + aat) ∨ aba = aas ∧ aba + aay = aas + aat =⇒ acm < aav ∨ acm = aav =⇒ (ada < aay ∨ 1 < aay + aba) ∨

718 ada = aay ∧ 1 = aay + aba =⇒ abb + (abc + abd) < abe + abg ∨ abb + (abc + abd) = abe + abg =⇒ (abh < abj ∨ abh < abj + abk) ∨ abh = abj ∧ abh = abj + abk =⇒ 1 < abo + abq ∨ 1 = abo + abq =⇒ (acj < abr ∨ acj + aci < abr + abs1 ) ∨ acj = abr ∧ acj + aci = abr + abs1 =⇒ (abt < abv ∨ abt + abu < abv + abw) ∨ abt = abv ∧ abt + abu = abv + abw =⇒ (abx < adc ∨ abx + aby < adc + abz) ∨ abx = adc ∧ abx + aby = adc + abz =⇒ (acf < acd ∨ acf < acd + acc ∨ 1 < acd + (acc + acb)) ∨ acf = acd ∧ acf = acd + acc ∧ 1 = acd + (acc + acb) =⇒ acc + acd < acf ∨ acc + acd = acf =⇒ (acg < acq ∨ acg + ach < acq + acr) ∨ acg = acq ∧ acg + ach = acq + acr =⇒ aci + (acj + ack) < acr + acp ∨ aci + (acj + ack) = acr + acp =⇒ (acm < acp ∨ acm + acn < acp + acq ∨ acm + (acn + aco) < acp + (acq + acr)) ∨ acm = acp ∧ acm + acn = acp + acq ∧ acm + (acn + aco) = acp + (acq + acr) =⇒ (acs + act < acw + acw ∨ acs + (act + acu) < acw + (acw + acw)) ∨ acs + act = acw + acw ∧ acs + (act + acu) = acw + (acw + acw) =⇒ (ada < adb + adr ∨ 1 < adb + (adr + adq)) ∨ ada = adb + adr ∧ 1 = adb + (adr + adq) =⇒ (adc + adc < adf + adg ∨ adc + (adc + abz) < adf + (adg + adk)) ∨ adc + adc = adf + adg ∧ adc + (adc + abz) = adf + (adg + adk) =⇒ adh + adi < adj + adk ∨ adh + adi = adj + adk =⇒

719 (adl < aec ∨ 1 < aec + adp) ∨ adl = aec ∧ 1 = aec + adp =⇒ (adq < ads ∨ adq + adr < ads) ∨ adq = ads ∧ adq + adr = ads =⇒ adu + adv < aed + aea ∨ adu + adv = aed + aea =⇒ (adw < aee ∨ adw + ady < aee + aea) ∨ adw = aee ∧ adw + ady = aee + aea =⇒ (aeb < aed ∨ aeb + aec < aed + aee) ∨ aeb = aed ∧ aeb + aec = aed + aee =⇒ False by argo end

107 Numeral Syntax for Types theory Numeral-Type imports Cardinality begin

107.1 Numeral Types typedef num0 = UNIV :: nat set .. typedef num1 = UNIV :: unit set .. typedef 0a bit0 = {0 ..< 2 ∗ int CARD( 0a::finite)} proof show 0 ∈ {0 ..< 2 ∗ int CARD( 0a)} by simp qed typedef 0a bit1 = {0 ..< 1 + 2 ∗ int CARD( 0a::finite)} proof show 0 ∈ {0 ..< 1 + 2 ∗ int CARD( 0a)} by simp qed lemma card-num0 [simp]: CARD (num0 ) = 0 unfolding type-definition.card [OF type-definition-num0 ] by simp lemma infinite-num0 : ¬ finite (UNIV :: num0 set) using card-num0 [unfolded card-eq-0-iff ] by simp lemma card-num1 [simp]: CARD(num1 ) = 1 unfolding type-definition.card [OF type-definition-num1 ] by (simp only: card-UNIV-unit)

720 lemma card-bit0 [simp]: CARD( 0a bit0 ) = 2 ∗ CARD( 0a::finite) unfolding type-definition.card [OF type-definition-bit0 ] by simp lemma card-bit1 [simp]: CARD( 0a bit1 ) = Suc (2 ∗ CARD( 0a::finite)) unfolding type-definition.card [OF type-definition-bit1 ] by simp instance num1 :: finite proof show finite (UNIV ::num1 set) unfolding type-definition.univ [OF type-definition-num1 ] using finite by (rule finite-imageI ) qed instance bit0 :: (finite) card2 proof show finite (UNIV :: 0a bit0 set) unfolding type-definition.univ [OF type-definition-bit0 ] by simp show 2 ≤ CARD( 0a bit0 ) by simp qed instance bit1 :: (finite) card2 proof show finite (UNIV :: 0a bit1 set) unfolding type-definition.univ [OF type-definition-bit1 ] by simp show 2 ≤ CARD( 0a bit1 ) by simp qed

107.2 Locales for for modular arithmetic subtypes locale mod-type = fixes n :: int and Rep :: 0a::{zero,one,plus,times,uminus,minus} ⇒ int and Abs :: int ⇒ 0a::{zero,one,plus,times,uminus,minus} assumes type: type-definition Rep Abs {0 ..

721 lemma size0 : 0 < n using size1 by simp lemmas definitions = zero-def one-def add-def mult-def minus-def diff-def lemma Rep-less-n: Rep x < n by (rule type-definition.Rep [OF type, simplified, THEN conjunct2 ]) lemma Rep-le-n: Rep x ≤ n by (rule Rep-less-n [THEN order-less-imp-le]) lemma Rep-inject-sym: x = y ←→ Rep x = Rep y by (rule type-definition.Rep-inject [OF type, symmetric]) lemma Rep-inverse: Abs (Rep x) = x by (rule type-definition.Rep-inverse [OF type]) lemma Abs-inverse: m ∈ {0 ..

722 done end locale mod-ring = mod-type n Rep Abs for n :: int and Rep :: 0a::{comm-ring-1 } ⇒ int and Abs :: int ⇒ 0a::{comm-ring-1 } begin lemma of-nat-eq: of-nat k = Abs (int k mod n) apply (induct k) apply (simp add: zero-def ) apply (simp add: Rep-simps add-def one-def zmod-simps ac-simps) done lemma of-int-eq: of-int z = Abs (z mod n) apply (cases z rule: int-diff-cases) apply (simp add: Rep-simps of-nat-eq diff-def zmod-simps) done lemma Rep-numeral: Rep (numeral w) = numeral w mod n using of-int-eq [of numeral w] by (simp add: Rep-inject-sym Rep-Abs-mod) lemma iszero-numeral: iszero (numeral w:: 0a) ←→ numeral w mod n = 0 by (simp add: Rep-inject-sym Rep-numeral Rep-0 iszero-def ) lemma cases: assumes 1 : Vz. [[(x:: 0a) = of-int z; 0 ≤ z; z < n]] =⇒ P shows P apply (cases x rule: type-definition.Abs-cases [OF type]) apply (rule-tac z=y in 1 ) apply (simp-all add: of-int-eq mod-pos-pos-trivial) done lemma induct: (Vz. [[0 ≤ z; z < n]] =⇒ P (of-int z)) =⇒ P (x:: 0a) by (cases x rule: cases) simp end

107.3 Ring class instances

Unfortunately ring-1 instance is not possible for num1, since 0 and 1 are not distinct. instantiation num1 :: {comm-ring,comm-monoid-mult,numeral}

723 begin lemma num1-eq-iff :(x::num1 ) = (y::num1 ) ←→ True by (induct x, induct y) simp instance by standard (simp-all add: num1-eq-iff ) end instantiation bit0 and bit1 :: (finite) {zero,one,plus,times,uminus,minus} begin definition Abs-bit0 0 :: int ⇒ 0a bit0 where Abs-bit0 0 x = Abs-bit0 (x mod int CARD( 0a bit0 )) definition Abs-bit1 0 :: int ⇒ 0a bit1 where Abs-bit1 0 x = Abs-bit1 (x mod int CARD( 0a bit1 )) definition 0 = Abs-bit0 0 definition 1 = Abs-bit0 1 definition x + y = Abs-bit0 0 (Rep-bit0 x + Rep-bit0 y) definition x ∗ y = Abs-bit0 0 (Rep-bit0 x ∗ Rep-bit0 y) definition x − y = Abs-bit0 0 (Rep-bit0 x − Rep-bit0 y) definition − x = Abs-bit0 0 (− Rep-bit0 x) definition 0 = Abs-bit1 0 definition 1 = Abs-bit1 1 definition x + y = Abs-bit1 0 (Rep-bit1 x + Rep-bit1 y) definition x ∗ y = Abs-bit1 0 (Rep-bit1 x ∗ Rep-bit1 y) definition x − y = Abs-bit1 0 (Rep-bit1 x − Rep-bit1 y) definition − x = Abs-bit1 0 (− Rep-bit1 x) instance .. end interpretation bit0 : mod-type int CARD( 0a::finite bit0 ) Rep-bit0 :: 0a::finite bit0 ⇒ int Abs-bit0 :: int ⇒ 0a::finite bit0 apply (rule mod-type.intro) apply (simp add: of-nat-mult type-definition-bit0 ) apply (rule one-less-int-card) apply (rule zero-bit0-def ) apply (rule one-bit0-def ) apply (rule plus-bit0-def [unfolded Abs-bit0 0-def ]) apply (rule times-bit0-def [unfolded Abs-bit0 0-def ])

724 apply (rule minus-bit0-def [unfolded Abs-bit0 0-def ]) apply (rule uminus-bit0-def [unfolded Abs-bit0 0-def ]) done interpretation bit1 : mod-type int CARD( 0a::finite bit1 ) Rep-bit1 :: 0a::finite bit1 ⇒ int Abs-bit1 :: int ⇒ 0a::finite bit1 apply (rule mod-type.intro) apply (simp add: of-nat-mult type-definition-bit1 ) apply (rule one-less-int-card) apply (rule zero-bit1-def ) apply (rule one-bit1-def ) apply (rule plus-bit1-def [unfolded Abs-bit1 0-def ]) apply (rule times-bit1-def [unfolded Abs-bit1 0-def ]) apply (rule minus-bit1-def [unfolded Abs-bit1 0-def ]) apply (rule uminus-bit1-def [unfolded Abs-bit1 0-def ]) done instance bit0 :: (finite) comm-ring-1 by (rule bit0 .comm-ring-1 ) instance bit1 :: (finite) comm-ring-1 by (rule bit1 .comm-ring-1 ) interpretation bit0 : mod-ring int CARD( 0a::finite bit0 ) Rep-bit0 :: 0a::finite bit0 ⇒ int Abs-bit0 :: int ⇒ 0a::finite bit0 .. interpretation bit1 : mod-ring int CARD( 0a::finite bit1 ) Rep-bit1 :: 0a::finite bit1 ⇒ int Abs-bit1 :: int ⇒ 0a::finite bit1 ..

Set up cases, induction, and arithmetic lemmas bit0-cases [case-names of-int, cases type: bit0 ] = bit0 .cases lemmas bit1-cases [case-names of-int, cases type: bit1 ] = bit1 .cases lemmas bit0-induct [case-names of-int, induct type: bit0 ] = bit0 .induct lemmas bit1-induct [case-names of-int, induct type: bit1 ] = bit1 .induct lemmas bit0-iszero-numeral [simp] = bit0 .iszero-numeral lemmas bit1-iszero-numeral [simp] = bit1 .iszero-numeral lemmas [simp] = eq-numeral-iff-iszero [where 0a= 0a bit0 ] for dummy :: 0a::finite lemmas [simp] = eq-numeral-iff-iszero [where 0a= 0a bit1 ] for dummy :: 0a::finite

725 107.4 Order instances instantiation bit0 and bit1 :: (finite) linorder begin definition a < b ←→ Rep-bit0 a < Rep-bit0 b definition a ≤ b ←→ Rep-bit0 a ≤ Rep-bit0 b definition a < b ←→ Rep-bit1 a < Rep-bit1 b definition a ≤ b ←→ Rep-bit1 a ≤ Rep-bit1 b instance by(intro-classes) (auto simp add: less-eq-bit0-def less-bit0-def less-eq-bit1-def less-bit1-def Rep-bit0-inject Rep-bit1-inject) end lemma (in preorder) tranclp-less: op <++ = op < by(auto simp add: fun-eq-iff intro: less-trans elim: tranclp.induct) instance bit0 and bit1 :: (finite) wellorder proof − have wf {(x :: 0a bit0 , y). x < y} by(auto simp add: trancl-def tranclp-less intro!: finite-acyclic-wf acyclicI ) thus OFCLASS( 0a bit0 , wellorder-class) by(rule wf-wellorderI ) intro-classes next have wf {(x :: 0a bit1 , y). x < y} by(auto simp add: trancl-def tranclp-less intro!: finite-acyclic-wf acyclicI ) thus OFCLASS( 0a bit1 , wellorder-class) by(rule wf-wellorderI ) intro-classes qed

107.5 Code setup and type classes for code generation

Code setup for num0 and num1 definition Num0 :: num0 where Num0 = Abs-num0 0 code-datatype Num0 instantiation num0 :: equal begin definition equal-num0 :: num0 ⇒ num0 ⇒ bool where equal-num0 = op = instance by intro-classes (simp add: equal-num0-def ) end lemma equal-num0-code [code]: equal-class.equal Num0 Num0 = True by(rule equal-refl) code-datatype 1 :: num1 instantiation num1 :: equal begin

726 definition equal-num1 :: num1 ⇒ num1 ⇒ bool where equal-num1 = op = instance by intro-classes (simp add: equal-num1-def ) end lemma equal-num1-code [code]: equal-class.equal (1 :: num1 ) 1 = True by(rule equal-refl) instantiation num1 :: enum begin definition enum-class.enum = [1 :: num1 ] definition enum-class.enum-all P = P (1 :: num1 ) definition enum-class.enum-ex P = P (1 :: num1 ) instance by intro-classes (auto simp add: enum-num1-def enum-all-num1-def enum-ex-num1-def num1-eq-iff Ball-def , (metis (full-types) num1-eq-iff )+) end instantiation num0 and num1 :: card-UNIV begin definition finite-UNIV = Phantom(num0 ) False definition card-UNIV = Phantom(num0 ) 0 definition finite-UNIV = Phantom(num1 ) True definition card-UNIV = Phantom(num1 ) 1 instance by intro-classes (simp-all add: finite-UNIV-num0-def card-UNIV-num0-def infinite-num0 finite-UNIV-num1-def card-UNIV-num1-def ) end

Code setup for 0a bit0 and 0a bit1 declare bit0 .Rep-inverse[code abstype] bit0 .Rep-0 [code abstract] bit0 .Rep-1 [code abstract] lemma Abs-bit0 0-code [code abstract]: Rep-bit0 (Abs-bit0 0 x :: 0a :: finite bit0 ) = x mod int (CARD( 0a bit0 )) by(auto simp add: Abs-bit0 0-def intro!: Abs-bit0-inverse) lemma inj-on-Abs-bit0 : inj-on (Abs-bit0 :: int ⇒ 0a bit0 ) {0 ..<2 ∗ int CARD( 0a :: finite)} by(auto intro: inj-onI simp add: Abs-bit0-inject) declare bit1 .Rep-inverse[code abstype] bit1 .Rep-0 [code abstract] bit1 .Rep-1 [code abstract]

727 lemma Abs-bit1 0-code [code abstract]: Rep-bit1 (Abs-bit1 0 x :: 0a :: finite bit1 ) = x mod int (CARD( 0a bit1 )) by(auto simp add: Abs-bit1 0-def intro!: Abs-bit1-inverse) lemma inj-on-Abs-bit1 : inj-on (Abs-bit1 :: int ⇒ 0a bit1 ) {0 ..<1 + 2 ∗ int CARD( 0a :: finite)} by(auto intro: inj-onI simp add: Abs-bit1-inject) instantiation bit0 and bit1 :: (finite) equal begin definition equal-class.equal x y ←→ Rep-bit0 x = Rep-bit0 y definition equal-class.equal x y ←→ Rep-bit1 x = Rep-bit1 y instance by intro-classes (simp-all add: equal-bit0-def equal-bit1-def Rep-bit0-inject Rep-bit1-inject) end instantiation bit0 :: (finite) enum begin definition (enum-class.enum :: 0a bit0 list) = map (Abs-bit0 0 ◦ int)(upt 0 (CARD( 0a bit0 ))) definition enum-class.enum-all P = (∀ b :: 0a bit0 ∈ set enum-class.enum. P b) definition enum-class.enum-ex P = (∃ b :: 0a bit0 ∈ set enum-class.enum. P b) instance proof(intro-classes) show distinct (enum-class.enum :: 0a bit0 list) by (simp add: enum-bit0-def distinct-map inj-on-def Abs-bit0 0-def Abs-bit0-inject mod-pos-pos-trivial)

show univ-eq:(UNIV :: 0a bit0 set) = set enum-class.enum unfolding enum-bit0-def type-definition.Abs-image[OF type-definition-bit0 , sym- metric] by(simp add: image-comp [symmetric] inj-on-Abs-bit0 card-image image-int-atLeastLessThan) (auto intro!: image-cong[OF refl] simp add: Abs-bit0 0-def mod-pos-pos-trivial)

fix P :: 0a bit0 ⇒ bool show enum-class.enum-all P = Ball UNIV P and enum-class.enum-ex P = Bex UNIV P by(simp-all add: enum-all-bit0-def enum-ex-bit0-def univ-eq) qed end instantiation bit1 :: (finite) enum begin definition (enum-class.enum :: 0a bit1 list) = map (Abs-bit1 0 ◦ int)(upt 0 (CARD( 0a bit1 ))) definition enum-class.enum-all P = (∀ b :: 0a bit1 ∈ set enum-class.enum. P b)

728 definition enum-class.enum-ex P = (∃ b :: 0a bit1 ∈ set enum-class.enum. P b) instance proof(intro-classes) show distinct (enum-class.enum :: 0a bit1 list) by(simp only: Abs-bit1 0-def zmod-int[symmetric] enum-bit1-def distinct-map Suc-eq-plus1 card-bit1 o-apply inj-on-def ) (clarsimp simp add: Abs-bit1-inject)

show univ-eq:(UNIV :: 0a bit1 set) = set enum-class.enum unfolding enum-bit1-def type-definition.Abs-image[OF type-definition-bit1 , sym- metric] by(simp add: image-comp [symmetric] inj-on-Abs-bit1 card-image image-int-atLeastLessThan) (auto intro!: image-cong[OF refl] simp add: Abs-bit1 0-def mod-pos-pos-trivial)

fix P :: 0a bit1 ⇒ bool show enum-class.enum-all P = Ball UNIV P and enum-class.enum-ex P = Bex UNIV P by(simp-all add: enum-all-bit1-def enum-ex-bit1-def univ-eq) qed end instantiation bit0 and bit1 :: (finite) finite-UNIV begin definition finite-UNIV = Phantom( 0a bit0 ) True definition finite-UNIV = Phantom( 0a bit1 ) True instance by intro-classes (simp-all add: finite-UNIV-bit0-def finite-UNIV-bit1-def ) end instantiation bit0 and bit1 :: ({finite,card-UNIV }) card-UNIV begin definition card-UNIV = Phantom( 0a bit0 )(2 ∗ of-phantom (card-UNIV :: 0a card-UNIV )) definition card-UNIV = Phantom( 0a bit1 )(1 + 2 ∗ of-phantom (card-UNIV :: 0a card-UNIV )) instance by intro-classes (simp-all add: card-UNIV-bit0-def card-UNIV-bit1-def card-UNIV ) end

107.6 Syntax syntax -NumeralType :: num-token => type (-) -NumeralType0 :: type (0 ) -NumeralType1 :: type (1 ) translations (type) 1 == (type) num1 (type) 0 == (type) num0

729 parse-translation h let fun mk-bintype n = let fun mk-bit 0 = Syntax.const @{type-syntax bit0 } | mk-bit 1 = Syntax.const @{type-syntax bit1 }; fun bin-of n = if n = 1 then Syntax.const @{type-syntax num1 } else if n = 0 then Syntax.const @{type-syntax num0 } else if n = ∼1 then raise TERM (negative type numeral, []) else let val (q, r) = Integer.div-mod n 2 ; in mk-bit r $ bin-of q end; in bin-of n end;

fun numeral-tr [Free (str, -)] = mk-bintype (the (Int.fromString str)) | numeral-tr ts = raise TERM (numeral-tr, ts);

in [(@{syntax-const -NumeralType}, K numeral-tr)] end; i print-translation h let fun int-of [] = 0 | int-of (b :: bs) = b + 2 ∗ int-of bs;

fun bin-of (Const (@{type-syntax num0 }, -)) = [] | bin-of (Const (@{type-syntax num1 }, -)) = [1 ] | bin-of (Const (@{type-syntax bit0 }, -) $ bs) = 0 :: bin-of bs | bin-of (Const (@{type-syntax bit1 }, -) $ bs) = 1 :: bin-of bs | bin-of t = raise TERM (bin-of , [t]);

fun bit-tr 0 b [t] = let val rev-digs = b :: bin-of t handle TERM - => raise Match val i = int-of rev-digs; val num = string-of-int (abs i); in Syntax.const @{syntax-const -NumeralType} $ Syntax.free num end | bit-tr 0 b - = raise Match; in [(@{type-syntax bit0 }, K (bit-tr 0 0 )), (@{type-syntax bit1 }, K (bit-tr 0 1 ))] end; i

730 107.7 Examples lemma CARD(0 ) = 0 by simp lemma CARD(17 ) = 17 by simp lemma 8 ∗ 11 ˆ 3 − 6 = (2 ::5 ) by simp end

108 Assigning lengths to types by type classes theory Type-Length imports Numeral-Type begin The aim of this is to allow any type as index type, but to provide a default in- stantiation for numeral types. This independence requires some duplication with the definitions in Numeral_Type.thy. class len0 = fixes len-of :: 0a itself ⇒ nat syntax -type-length :: type ⇒ nat ((1LENGTH /(1 0(- 0)))) translations LENGTH ( 0a) * CONST len-of (CONST Pure.type :: 0a itself ) print-translation h let fun len-of-itself-tr 0 ctxt [Const (@{const-syntax Pure.type}, Type (-, [T ]))] = Syntax.const @{syntax-const -type-length} $ Syntax-Phases.term-of-typ ctxt T in [(@{const-syntax len-of }, len-of-itself-tr 0)] end i

Some theorems are only true on words with length greater 0. class len = len0 + assumes len-gt-0 [iff ]: 0 < LENGTH ( 0a) instantiation num0 and num1 :: len0 begin definition len-num0 : len-of (- :: num0 itself ) = 0 definition len-num1 : len-of (- :: num1 itself ) = 1 instance .. end instantiation bit0 and bit1 :: (len0 ) len0 begin

731 definition len-bit0 : len-of (- :: 0a::len0 bit0 itself ) = 2 ∗ LENGTH ( 0a) definition len-bit1 : len-of (- :: 0a::len0 bit1 itself ) = 2 ∗ LENGTH ( 0a) + 1 instance .. end lemmas len-of-numeral-defs [simp] = len-num0 len-num1 len-bit0 len-bit1 instance num1 :: len by standard simp instance bit0 :: (len) len by standard simp instance bit1 :: (len0 ) len by standard simp end

109 Proof of concept for algebraically founded bit word types theory Word-Type imports Main ∼∼/src/HOL/Library/Type-Length begin

109.1 Truncating bit representations of numeric types class semiring-bits = semiring-div-parity + assumes semiring-bits:(1 + 2 ∗ a) mod of-nat (2 ∗ n) = 1 + 2 ∗ (a mod of-nat n) begin definition bitrunc :: nat ⇒ 0a ⇒ 0a where bitrunc-eq-mod: bitrunc n a = a mod of-nat (2 ˆ n) lemma bitrunc-bitrunc [simp]: bitrunc n (bitrunc n a) = bitrunc n a by (simp add: bitrunc-eq-mod) lemma bitrunc-0 [simp]: bitrunc 0 a = 0 by (simp add: bitrunc-eq-mod) lemma bitrunc-Suc [simp]: bitrunc (Suc n) a = bitrunc n (a div 2 ) ∗ 2 + a mod 2 proof −

732 define b and c where b = a div 2 and c = a mod 2 then have a: a = b ∗ 2 + c and c = 0 ∨ c = 1 by (simp-all add: div-mult-mod-eq parity) from hc = 0 ∨ c = 1 i have bitrunc (Suc n)(b ∗ 2 + c) = bitrunc n b ∗ 2 + c proof assume c = 0 moreover have (2 ∗ b) mod (2 ∗ 2 ˆ n) = 2 ∗ (b mod 2 ˆ n) by (simp add: mod-mult-mult1 ) ultimately show ?thesis by (simp add: bitrunc-eq-mod ac-simps) next assume c = 1 with semiring-bits [of b 2 ˆ n] show ?thesis by (simp add: bitrunc-eq-mod ac-simps) qed with a show ?thesis by (simp add: b-def c-def ) qed lemma bitrunc-of-0 [simp]: bitrunc n 0 = 0 by (simp add: bitrunc-eq-mod) lemma bitrunc-plus: bitrunc n (bitrunc n a + bitrunc n b) = bitrunc n (a + b) by (simp add: bitrunc-eq-mod mod-add-eq [symmetric]) lemma bitrunc-of-1-eq-0-iff [simp]: bitrunc n 1 = 0 ←→ n = 0 by (induct n) simp-all end instance nat :: semiring-bits by standard (simp add: mod-Suc Suc-double-not-eq-double) instance int :: semiring-bits by standard (simp add: pos-zmod-mult-2 ) lemma bitrunc-uminus: fixes k :: int shows bitrunc n (− (bitrunc n k)) = bitrunc n (− k) by (simp add: bitrunc-eq-mod mod-minus-eq [symmetric]) lemma bitrunc-minus: fixes k l :: int

733 shows bitrunc n (bitrunc n k − bitrunc n l) = bitrunc n (k − l) by (simp add: bitrunc-eq-mod mod-diff-eq [symmetric]) lemma bitrunc-nonnegative [simp]: fixes k :: int shows bitrunc n k ≥ 0 by (simp add: bitrunc-eq-mod) definition signed-bitrunc :: nat ⇒ int ⇒ int where signed-bitrunc-eq-bitrunc: signed-bitrunc n k = bitrunc (Suc n)(k + 2 ˆ n) − 2 ˆ n lemma signed-bitrunc-eq-bitrunc 0: assumes n > 0 shows signed-bitrunc (n − Suc 0 ) k = bitrunc n (k + 2 ˆ (n − 1 )) − 2 ˆ (n − 1 ) using assms by (simp add: signed-bitrunc-eq-bitrunc) lemma signed-bitrunc-0 [simp]: signed-bitrunc 0 k = − (k mod 2 ) proof (cases even k) case True then have odd (k + 1 ) by simp then have (k + 1 ) mod 2 = 1 by (simp add: even-iff-mod-2-eq-zero) with True show ?thesis by (simp add: signed-bitrunc-eq-bitrunc) next case False then show ?thesis by (simp add: signed-bitrunc-eq-bitrunc odd-iff-mod-2-eq-one) qed lemma signed-bitrunc-Suc [simp]: signed-bitrunc (Suc n) k = signed-bitrunc n (k div 2 ) ∗ 2 + k mod 2 using zero-not-eq-two by (simp add: signed-bitrunc-eq-bitrunc algebra-simps) lemma signed-bitrunc-of-0 [simp]: signed-bitrunc n 0 = 0 by (simp add: signed-bitrunc-eq-bitrunc bitrunc-eq-mod) lemma signed-bitrunc-of-minus-1 [simp]: signed-bitrunc n (− 1 ) = − 1 by (induct n) simp-all lemma signed-bitrunc-eq-iff-bitrunc-eq: assumes n > 0 shows signed-bitrunc (n − Suc 0 ) k = signed-bitrunc (n − Suc 0 ) l ←→ bitrunc

734 n k = bitrunc n l (is ?P ←→ ?Q) proof − from assms obtain m where m: n = Suc m by (cases n) auto show ?thesis proof assume ?Q have bitrunc (Suc m)(k + 2 ˆ m) = bitrunc (Suc m)(bitrunc (Suc m) k + bitrunc (Suc m)(2 ˆ m)) by (simp only: bitrunc-plus) also have ... = bitrunc (Suc m)(bitrunc (Suc m) l + bitrunc (Suc m)(2 ˆ m)) by (simp only: h?Q i m [symmetric]) also have ... = bitrunc (Suc m)(l + 2 ˆ m) by (simp only: bitrunc-plus) finally show ?P by (simp only: signed-bitrunc-eq-bitrunc m) simp next assume ?P with assms have (k + 2 ˆ (n − Suc 0 )) mod 2 ˆ n = (l + 2 ˆ (n − Suc 0 )) mod 2 ˆ n by (simp add: signed-bitrunc-eq-bitrunc 0 bitrunc-eq-mod) then have (i + (k + 2 ˆ (n − Suc 0 ))) mod 2 ˆ n = (i + (l + 2 ˆ (n − Suc 0 ))) mod 2 ˆ n for i by (metis mod-add-eq) then have k mod 2 ˆ n = l mod 2 ˆ n by (metis add-diff-cancel-right 0 uminus-add-conv-diff ) then show ?Q by (simp add: bitrunc-eq-mod) qed qed

109.2 Bit strings as quotient type 109.2.1 Basic properties quotient-type (overloaded) 0a word = int / λk l. bitrunc LENGTH ( 0a) k = bitrunc LENGTH ( 0a::len0 ) l by (auto intro!: equivpI reflpI sympI transpI ) instantiation word :: (len0 ) {semiring-numeral, comm-semiring-0 , comm-ring} begin lift-definition zero-word :: 0a word is 0 . lift-definition one-word :: 0a word is 1 .

735 lift-definition plus-word :: 0a word ⇒ 0a word ⇒ 0a word is plus by (subst bitrunc-plus [symmetric]) (simp add: bitrunc-plus) lift-definition uminus-word :: 0a word ⇒ 0a word is uminus by (subst bitrunc-uminus [symmetric]) (simp add: bitrunc-uminus) lift-definition minus-word :: 0a word ⇒ 0a word ⇒ 0a word is minus by (subst bitrunc-minus [symmetric]) (simp add: bitrunc-minus) lift-definition times-word :: 0a word ⇒ 0a word ⇒ 0a word is times by (auto simp add: bitrunc-eq-mod intro: mod-mult-cong) instance by standard (transfer; simp add: algebra-simps)+ end instance word :: (len) comm-ring-1 by standard (transfer; simp)+

109.2.2 Conversions lemma [transfer-rule]: rel-fun HOL.eq pcr-word int of-nat proof − note transfer-rule-of-nat [transfer-rule] show ?thesis by transfer-prover qed lemma [transfer-rule]: rel-fun HOL.eq pcr-word (λk. k) of-int proof − note transfer-rule-of-int [transfer-rule] have rel-fun HOL.eq pcr-word (of-int :: int ⇒ int)(of-int :: int ⇒ 0a word) by transfer-prover then show ?thesis by (simp add: id-def ) qed context semiring-1 begin lift-definition unsigned :: 0b::len0 word ⇒ 0a is of-nat ◦ nat ◦ bitrunc LENGTH ( 0b) by simp

736 lemma unsigned-0 [simp]: unsigned 0 = 0 by transfer simp end context semiring-char-0 begin lemma word-eq-iff-unsigned: a = b ←→ unsigned a = unsigned b by safe (transfer; simp add: eq-nat-nat-iff ) end context ring-1 begin lift-definition signed :: 0b::len word ⇒ 0a is of-int ◦ signed-bitrunc (LENGTH ( 0b) − 1 ) by (simp add: signed-bitrunc-eq-iff-bitrunc-eq [symmetric]) lemma signed-0 [simp]: signed 0 = 0 by transfer simp end lemma unsigned-of-nat [simp]: unsigned (of-nat n :: 0a word) = bitrunc LENGTH ( 0a::len) n by transfer (simp add: nat-eq-iff bitrunc-eq-mod zmod-int) lemma of-nat-unsigned [simp]: of-nat (unsigned a) = a by transfer simp lemma of-int-unsigned [simp]: of-int (unsigned a) = a by transfer simp context ring-char-0 begin lemma word-eq-iff-signed: a = b ←→ signed a = signed b by safe (transfer; auto simp add: signed-bitrunc-eq-iff-bitrunc-eq) end

737 lemma signed-of-int [simp]: signed (of-int k :: 0a word) = signed-bitrunc (LENGTH ( 0a::len) − 1 ) k by transfer simp lemma of-int-signed [simp]: of-int (signed a) = a by transfer (simp add: signed-bitrunc-eq-bitrunc bitrunc-eq-mod zdiff-zmod-left)

109.2.3 Properties 109.2.4 Division instantiation word :: (len0 ) modulo begin lift-definition divide-word :: 0a word ⇒ 0a word ⇒ 0a word is λa b. bitrunc LENGTH ( 0a) a div bitrunc LENGTH ( 0a) b by simp lift-definition modulo-word :: 0a word ⇒ 0a word ⇒ 0a word is λa b. bitrunc LENGTH ( 0a) a mod bitrunc LENGTH ( 0a) b by simp instance .. end

109.2.5 Orderings instantiation word :: (len0 ) linorder begin lift-definition less-eq-word :: 0a word ⇒ 0a word ⇒ bool is λa b. bitrunc LENGTH ( 0a) a ≤ bitrunc LENGTH ( 0a) b by simp lift-definition less-word :: 0a word ⇒ 0a word ⇒ bool is λa b. bitrunc LENGTH ( 0a) a < bitrunc LENGTH ( 0a) b by simp instance by standard (transfer; auto)+ end context linordered-semidom begin lemma word-less-eq-iff-unsigned:

738 a ≤ b ←→ unsigned a ≤ unsigned b by (transfer fixing: less-eq)(simp add: nat-le-eq-zle) lemma word-less-iff-unsigned: a < b ←→ unsigned a < unsigned b by (transfer fixing: less)(auto dest: preorder-class.le-less-trans [OF bitrunc-nonnegative]) end end

110 Meson test cases theory Meson-Test imports Main begin

WARNING: there are many potential conflicts between variables used below and constants declared in HOL! hide-const (open) implies union inter subset quotient sum

Test data for the MESON proof procedure (Excludes the equality problems 51, 52, 56, 58)

110.1 Interactive examples lemma problem-25 : (∃ x. P x)&(∀ x. L x −−> ∼ (M x & R x)) & (∀ x. P x −−> (M x & L x)) & ((∀ x. P x −−> Q x) | (∃ x. P x & R x)) −−> (∃ x. Q x & P x) apply (rule ccontr) ML-prf h val ctxt = @{context}; val prem25 = Thm.assume @{cprop ¬ ?thesis}; val nnf25 = Meson.make-nnf ctxt prem25 ; val xsko25 = Meson.skolemize ctxt nnf25 ; i apply (tactic hcut-tac xsko25 1 THEN REPEAT (eresolve-tac @{context} [exE] 1 )i) ML-val h val ctxt = @{context}; val [-, sko25 ] = #prems (#1 (Subgoal.focus ctxt 1 NONE (#goal @{Isar.goal}))); val clauses25 = Meson.make-clauses ctxt [sko25 ]; (∗7 clauses∗) val horns25 = Meson.make-horns clauses25 ;(∗16 Horn clauses∗) val go25 :: - = Meson.gocls clauses25 ;

val ctxt 0 = fold Thm.declare-hyps (maps Thm.chyps-of (go25 :: horns25 )) ctxt; Goal.prove ctxt 0 [] [] @{prop False} (fn - => resolve-tac ctxt 0 [go25 ] 1 THEN

739 Meson.depth-prolog-tac ctxt 0 horns25 ); i oops lemma problem-26 : ((∃ x. p x) = (∃ x. q x)) & (∀ x. ∀ y. p x & q y −−> (r x = s y)) −−> ((∀ x. p x −−> r x) = (∀ x. q x −−> s x)) apply (rule ccontr) ML-prf h val ctxt = @{context}; val prem26 = Thm.assume @{cprop ¬ ?thesis} val nnf26 = Meson.make-nnf ctxt prem26 ; val xsko26 = Meson.skolemize ctxt nnf26 ; i apply (tactic hcut-tac xsko26 1 THEN REPEAT (eresolve-tac @{context} [exE] 1 )i) ML-val h val ctxt = @{context}; val [-, sko26 ] = #prems (#1 (Subgoal.focus ctxt 1 NONE (#goal @{Isar.goal}))); val clauses26 = Meson.make-clauses ctxt [sko26 ]; val - = @{assert} (length clauses26 = 9 ); val horns26 = Meson.make-horns clauses26 ; val - = @{assert} (length horns26 = 24 ); val go26 :: - = Meson.gocls clauses26 ;

val ctxt 0 = fold Thm.declare-hyps (maps Thm.chyps-of (go26 :: horns26 )) ctxt; Goal.prove ctxt 0 [] [] @{prop False} (fn - => resolve-tac ctxt 0 [go26 ] 1 THEN Meson.depth-prolog-tac ctxt 0 horns26 ); (∗7 ms∗) (∗Proof is of length 107 !!∗) i oops lemma problem-43 : — NOW PROVED AUTOMATICALLY!! (∀ x. ∀ y. q x y = (∀ z. p z x = (p z y::bool))) −−> (∀ x. (∀ y. q x y = (q y x::bool))) apply (rule ccontr) ML-prf h val ctxt = @{context}; val prem43 = Thm.assume @{cprop ¬ ?thesis}; val nnf43 = Meson.make-nnf ctxt prem43 ; val xsko43 = Meson.skolemize ctxt nnf43 ; i apply (tactic hcut-tac xsko43 1 THEN REPEAT (eresolve-tac @{context} [exE] 1 )i) ML-val h val ctxt = @{context}; val [-, sko43 ] = #prems (#1 (Subgoal.focus ctxt 1 NONE (#goal @{Isar.goal}))); val clauses43 = Meson.make-clauses ctxt [sko43 ];

740 val - = @{assert} (length clauses43 = 6 ); val horns43 = Meson.make-horns clauses43 ; val - = @{assert} (length horns43 = 16 ); val go43 :: - = Meson.gocls clauses43 ;

val ctxt 0 = fold Thm.declare-hyps (maps Thm.chyps-of (go43 :: horns43 )) ctxt; Goal.prove ctxt 0 [] [] @{prop False} (fn - => resolve-tac ctxt 0 [go43 ] 1 THEN Meson.best-prolog-tac ctxt 0 Meson.size-of-subgoals horns43 ); (∗7ms∗) i oops

MORE and MUCH HARDER test data for the MESON proof procedure (courtesy John Harrison). abbreviation EQU001-0-ax equal ≡ (∀ X . equal(X :: 0a,X )) & (∀ YX . equal(X :: 0a,Y ) −−> equal(Y :: 0a,X )) & (∀ YXZ . equal(X :: 0a,Y )& equal(Y :: 0a,Z ) −−> equal(X :: 0a,Z )) abbreviation BOO002-0-ax equal INVERSE multiplicative-identity additive-identity multiply product add sum ≡ (∀ XY . sum(X :: 0a,Y ,add(X :: 0a,Y ))) & (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) & (∀ YXZ . sum(X :: 0a,Y ,Z ) −−> sum(Y :: 0a,X ,Z )) & (∀ YXZ . product(X :: 0a,Y ,Z ) −−> product(Y :: 0a,X ,Z )) & (∀ X . sum(additive-identity:: 0a,X ,X )) & (∀ X . sum(X :: 0a,additive-identity,X )) & (∀ X . product(multiplicative-identity:: 0a,X ,X )) & (∀ X . product(X :: 0a,multiplicative-identity,X )) & (∀ Y Z X V3 V1 V2 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & product(X :: 0a,V3 ,V4 ) −−> sum(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 X V3 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & sum(V1 :: 0a,V2 ,V4 ) −−> product(X :: 0a,V3 ,V4 )) & (∀ Y Z V3 X V1 V2 V4 . product(Y :: 0a,X ,V1 )& product(Z :: 0a,X ,V2 )& sum(Y :: 0a,Z ,V3 ) & product(V3 :: 0a,X ,V4 ) −−> sum(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 V3 X V4 . product(Y :: 0a,X ,V1 )& product(Z :: 0a,X ,V2 )& sum(Y :: 0a,Z ,V3 ) & sum(V1 :: 0a,V2 ,V4 ) −−> product(V3 :: 0a,X ,V4 )) & (∀ Y Z X V3 V1 V2 V4 . sum(X :: 0a,Y ,V1 )& sum(X :: 0a,Z ,V2 )& product(Y :: 0a,Z ,V3 ) & sum(X :: 0a,V3 ,V4 ) −−> product(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 X V3 V4 . sum(X :: 0a,Y ,V1 )& sum(X :: 0a,Z ,V2 )& product(Y :: 0a,Z ,V3 ) & product(V1 :: 0a,V2 ,V4 ) −−> sum(X :: 0a,V3 ,V4 )) & (∀ Y Z V3 X V1 V2 V4 . sum(Y :: 0a,X ,V1 )& sum(Z :: 0a,X ,V2 )& product(Y :: 0a,Z ,V3 ) & sum(V3 :: 0a,X ,V4 ) −−> product(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 V3 X V4 . sum(Y :: 0a,X ,V1 )& sum(Z :: 0a,X ,V2 )& product(Y :: 0a,Z ,V3 ) & product(V1 :: 0a,V2 ,V4 ) −−> sum(V3 :: 0a,X ,V4 )) & (∀ X . sum(INVERSE(X ),X ,multiplicative-identity)) & (∀ X . sum(X :: 0a,INVERSE(X ),multiplicative-identity)) & (∀ X . product(INVERSE(X ),X ,additive-identity)) & (∀ X . product(X :: 0a,INVERSE(X ),additive-identity)) & (∀ XYUV . sum(X :: 0a,Y ,U )& sum(X :: 0a,Y ,V ) −−> equal(U :: 0a,V )) &

741 (∀ XYUV . product(X :: 0a,Y ,U )& product(X :: 0a,Y ,V ) −−> equal(U :: 0a,V )) abbreviation BOO002-0-eq INVERSE multiply add product sum equal ≡ (∀ XYWZ . equal(X :: 0a,Y )& sum(X :: 0a,W ,Z ) −−> sum(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& sum(W :: 0a,X ,Z ) −−> sum(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& sum(W :: 0a,Z ,X ) −−> sum(W :: 0a,Z ,Y )) & (∀ XYWZ . equal(X :: 0a,Y )& product(X :: 0a,W ,Z ) −−> product(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& product(W :: 0a,X ,Z ) −−> product(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& product(W :: 0a,Z ,X ) −−> product(W :: 0a,Z ,Y )) & (∀ XYW . equal(X :: 0a,Y ) −−> equal(add(X :: 0a,W ),add(Y :: 0a,W ))) & (∀ XWY . equal(X :: 0a,Y ) −−> equal(add(W :: 0a,X ),add(W :: 0a,Y ))) & (∀ XYW . equal(X :: 0a,Y ) −−> equal(multiply(X :: 0a,W ),multiply(Y :: 0a,W ))) & (∀ XWY . equal(X :: 0a,Y ) −−> equal(multiply(W :: 0a,X ),multiply(W :: 0a,Y ))) & (∀ XY . equal(X :: 0a,Y ) −−> equal(INVERSE(X ),INVERSE(Y ))) lemma BOO003-1 : EQU001-0-ax equal & BOO002-0-ax equal INVERSE multiplicative-identity additive-identity multiply product add sum & BOO002-0-eq INVERSE multiply add product sum equal & (∼product(x:: 0a,x,x)) −−> False oops lemma BOO004-1 : EQU001-0-ax equal & BOO002-0-ax equal INVERSE multiplicative-identity additive-identity multiply product add sum & BOO002-0-eq INVERSE multiply add product sum equal & (∼sum(x:: 0a,x,x)) −−> False oops lemma BOO005-1 : EQU001-0-ax equal & BOO002-0-ax equal INVERSE multiplicative-identity additive-identity multiply product add sum & BOO002-0-eq INVERSE multiply add product sum equal & (∼sum(x:: 0a,multiplicative-identity,multiplicative-identity)) −−> False oops lemma BOO006-1 :

742 EQU001-0-ax equal & BOO002-0-ax equal INVERSE multiplicative-identity additive-identity multiply product add sum & BOO002-0-eq INVERSE multiply add product sum equal & (∼product(x:: 0a,additive-identity,additive-identity)) −−> False oops lemma BOO011-1 : EQU001-0-ax equal & BOO002-0-ax equal INVERSE multiplicative-identity additive-identity multiply product add sum & BOO002-0-eq INVERSE multiply add product sum equal & (∼equal(INVERSE(additive-identity),multiplicative-identity)) −−> False by meson abbreviation CAT003-0-ax f1 compos codomain domain equal there-exists equiv- alent ≡ (∀ YX . equivalent(X :: 0a,Y ) −−> there-exists(X )) & (∀ XY . equivalent(X :: 0a,Y ) −−> equal(X :: 0a,Y )) & (∀ XY . there-exists(X )& equal(X :: 0a,Y ) −−> equivalent(X :: 0a,Y )) & (∀ X . there-exists(domain(X )) −−> there-exists(X )) & (∀ X . there-exists(codomain(X )) −−> there-exists(X )) & (∀ YX . there-exists(compos(X :: 0a,Y )) −−> there-exists(domain(X ))) & (∀ XY . there-exists(compos(X :: 0a,Y )) −−> equal(domain(X ),codomain(Y ))) & (∀ XY . there-exists(domain(X )) & equal(domain(X ),codomain(Y )) −−> there-exists(compos(X :: 0a,Y ))) & (∀ XYZ . equal(compos(X :: 0a,compos(Y :: 0a,Z )),compos(compos(X :: 0a,Y ),Z ))) & (∀ X . equal(compos(X :: 0a,domain(X )),X )) & (∀ X . equal(compos(codomain(X ),X ),X )) & (∀ XY . equivalent(X :: 0a,Y ) −−> there-exists(Y )) & (∀ XY . there-exists(X )& there-exists(Y )& equal(X :: 0a,Y ) −−> equivalent(X :: 0a,Y )) & (∀ YX . there-exists(compos(X :: 0a,Y )) −−> there-exists(codomain(X ))) & (∀ XY . there-exists(f1 (X :: 0a,Y )) | equal(X :: 0a,Y )) & (∀ XY . equal(X :: 0a,f1 (X :: 0a,Y )) | equal(Y :: 0a,f1 (X :: 0a,Y )) | equal(X :: 0a,Y )) & (∀ XY . equal(X :: 0a,f1 (X :: 0a,Y )) & equal(Y :: 0a,f1 (X :: 0a,Y )) −−> equal(X :: 0a,Y )) abbreviation CAT003-0-eq f1 compos codomain domain equivalent there-exists equal ≡ (∀ XY . equal(X :: 0a,Y )& there-exists(X ) −−> there-exists(Y )) & (∀ XYZ . equal(X :: 0a,Y )& equivalent(X :: 0a,Z ) −−> equivalent(Y :: 0a,Z )) & (∀ XZY . equal(X :: 0a,Y )& equivalent(Z :: 0a,X ) −−> equivalent(Z :: 0a,Y )) & (∀ XY . equal(X :: 0a,Y ) −−> equal(domain(X ),domain(Y ))) & (∀ XY . equal(X :: 0a,Y ) −−> equal(codomain(X ),codomain(Y ))) & (∀ XYZ . equal(X :: 0a,Y ) −−> equal(compos(X :: 0a,Z ),compos(Y :: 0a,Z ))) &

743 (∀ XZY . equal(X :: 0a,Y ) −−> equal(compos(Z :: 0a,X ),compos(Z :: 0a,Y ))) & (∀ ABC . equal(A:: 0a,B) −−> equal(f1 (A:: 0a,C ),f1 (B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(f1 (F 0:: 0a,D),f1 (F 0:: 0a,E))) lemma CAT001-3 : EQU001-0-ax equal & CAT003-0-ax f1 compos codomain domain equal there-exists equivalent & CAT003-0-eq f1 compos codomain domain equivalent there-exists equal & (there-exists(compos(a:: 0a,b))) & (∀ YXZ . equal(compos(compos(a:: 0a,b),X ),Y )& equal(compos(compos(a:: 0a,b),Z ),Y ) −−> equal(X :: 0a,Z )) & (there-exists(compos(b:: 0a,h))) & (equal(compos(b:: 0a,h),compos(b:: 0a,g))) & (∼equal(h:: 0a,g)) −−> False by meson lemma CAT003-3 : EQU001-0-ax equal & CAT003-0-ax f1 compos codomain domain equal there-exists equivalent & CAT003-0-eq f1 compos codomain domain equivalent there-exists equal & (there-exists(compos(a:: 0a,b))) & (∀ YXZ . equal(compos(X :: 0a,compos(a:: 0a,b)),Y )& equal(compos(Z :: 0a,compos(a:: 0a,b)),Y ) −−> equal(X :: 0a,Z )) & (there-exists(h)) & (equal(compos(h:: 0a,a),compos(g:: 0a,a))) & (∼equal(g:: 0a,h)) −−> False by meson abbreviation CAT001-0-ax equal codomain domain identity-map compos product defined ≡ (∀ XY . defined(X :: 0a,Y ) −−> product(X :: 0a,Y ,compos(X :: 0a,Y ))) & (∀ ZXY . product(X :: 0a,Y ,Z ) −−> defined(X :: 0a,Y )) & (∀ X Xy Y Z . product(X :: 0a,Y ,Xy)& defined(Xy:: 0a,Z ) −−> defined(Y :: 0a,Z )) & (∀ Y Xy Z X Yz. product(X :: 0a,Y ,Xy)& product(Y :: 0a,Z ,Yz)& defined(Xy:: 0a,Z ) −−> defined(X :: 0a,Yz)) & (∀ Xy Y Z X Yz Xyz. product(X :: 0a,Y ,Xy)& product(Xy:: 0a,Z ,Xyz)& prod- uct(Y :: 0a,Z ,Yz) −−> product(X :: 0a,Yz,Xyz)) & (∀ Z Yz X Y . product(Y :: 0a,Z ,Yz)& defined(X :: 0a,Yz) −−> defined(X :: 0a,Y )) & (∀ Y X Yz Xy Z . product(Y :: 0a,Z ,Yz)& product(X :: 0a,Y ,Xy)& defined(X :: 0a,Yz) −−> defined(Xy:: 0a,Z )) & (∀ Yz X Y Xy Z Xyz. product(Y :: 0a,Z ,Yz)& product(X :: 0a,Yz,Xyz)& prod- uct(X :: 0a,Y ,Xy) −−> product(Xy:: 0a,Z ,Xyz)) & (∀ YXZ . defined(X :: 0a,Y )& defined(Y :: 0a,Z )& identity-map(Y ) −−> de- fined(X :: 0a,Z )) & (∀ X . identity-map(domain(X ))) &

744 (∀ X . identity-map(codomain(X ))) & (∀ X . defined(X :: 0a,domain(X ))) & (∀ X . defined(codomain(X ),X )) & (∀ X . product(X :: 0a,domain(X ),X )) & (∀ X . product(codomain(X ),X ,X )) & (∀ XY . defined(X :: 0a,Y )& identity-map(X ) −−> product(X :: 0a,Y ,Y )) & (∀ YX . defined(X :: 0a,Y )& identity-map(Y ) −−> product(X :: 0a,Y ,X )) & (∀ XYZW . product(X :: 0a,Y ,Z )& product(X :: 0a,Y ,W ) −−> equal(Z :: 0a,W )) abbreviation CAT001-0-eq compos defined identity-map codomain domain product equal ≡ (∀ XYZW . equal(X :: 0a,Y )& product(X :: 0a,Z ,W ) −−> product(Y :: 0a,Z ,W )) & (∀ XZYW . equal(X :: 0a,Y )& product(Z :: 0a,X ,W ) −−> product(Z :: 0a,Y ,W )) & (∀ XZWY . equal(X :: 0a,Y )& product(Z :: 0a,W ,X ) −−> product(Z :: 0a,W ,Y )) & (∀ XY . equal(X :: 0a,Y ) −−> equal(domain(X ),domain(Y ))) & (∀ XY . equal(X :: 0a,Y ) −−> equal(codomain(X ),codomain(Y ))) & (∀ XY . equal(X :: 0a,Y )& identity-map(X ) −−> identity-map(Y )) & (∀ XYZ . equal(X :: 0a,Y )& defined(X :: 0a,Z ) −−> defined(Y :: 0a,Z )) & (∀ XZY . equal(X :: 0a,Y )& defined(Z :: 0a,X ) −−> defined(Z :: 0a,Y )) & (∀ XZY . equal(X :: 0a,Y ) −−> equal(compos(Z :: 0a,X ),compos(Z :: 0a,Y ))) & (∀ XYZ . equal(X :: 0a,Y ) −−> equal(compos(X :: 0a,Z ),compos(Y :: 0a,Z ))) lemma CAT005-1 : EQU001-0-ax equal & CAT001-0-ax equal codomain domain identity-map compos product defined & CAT001-0-eq compos defined identity-map codomain domain product equal & (defined(a:: 0a,d)) & (identity-map(d)) & (∼equal(domain(a),d)) −−> False oops lemma CAT007-1 : EQU001-0-ax equal & CAT001-0-ax equal codomain domain identity-map compos product defined & CAT001-0-eq compos defined identity-map codomain domain product equal & (equal(domain(a),codomain(b))) & (∼defined(a:: 0a,b)) −−> False by meson lemma CAT018-1 : EQU001-0-ax equal & CAT001-0-ax equal codomain domain identity-map compos product defined & CAT001-0-eq compos defined identity-map codomain domain product equal &

745 (defined(a:: 0a,b)) & (defined(b:: 0a,c)) & (∼defined(a:: 0a,compos(b:: 0a,c))) −−> False oops lemma COL001-2 : EQU001-0-ax equal & (∀ XYZ . equal(apply(apply(apply(s:: 0a,X ),Y ),Z ),apply(apply(X :: 0a,Z ),apply(Y :: 0a,Z )))) & (∀ YX . equal(apply(apply(k:: 0a,X ),Y ),X )) & (∀ XYZ . equal(apply(apply(apply(b:: 0a,X ),Y ),Z ),apply(X :: 0a,apply(Y :: 0a,Z )))) & (∀ X . equal(apply(i:: 0a,X ),X )) & (∀ ABC . equal(A:: 0a,B) −−> equal(apply(A:: 0a,C ),apply(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(apply(F 0:: 0a,D),apply(F 0:: 0a,E))) & (∀ X . equal(apply(apply(apply(s:: 0a,apply(b:: 0a,X )),i),apply(apply(s:: 0a,apply(b:: 0a,X )),i)),apply(x:: 0a,apply(apply(apply(s:: 0a,apply(b:: 0a,X )),i),apply(apply(s:: 0a,apply(b:: 0a,X )),i))))) & (∀ Y . ∼equal(Y :: 0a,apply(combinator:: 0a,Y ))) −−> False by meson lemma COL023-1 : EQU001-0-ax equal & (∀ XYZ . equal(apply(apply(apply(b:: 0a,X ),Y ),Z ),apply(X :: 0a,apply(Y :: 0a,Z )))) & (∀ XYZ . equal(apply(apply(apply(n:: 0a,X ),Y ),Z ),apply(apply(apply(X :: 0a,Z ),Y ),Z ))) & (∀ ABC . equal(A:: 0a,B) −−> equal(apply(A:: 0a,C ),apply(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(apply(F 0:: 0a,D),apply(F 0:: 0a,E))) & (∀ Y . ∼equal(Y :: 0a,apply(combinator:: 0a,Y ))) −−> False by meson lemma COL032-1 : EQU001-0-ax equal & (∀ X . equal(apply(m:: 0a,X ),apply(X :: 0a,X ))) & (∀ YXZ . equal(apply(apply(apply(q:: 0a,X ),Y ),Z ),apply(Y :: 0a,apply(X :: 0a,Z )))) & (∀ ABC . equal(A:: 0a,B) −−> equal(apply(A:: 0a,C ),apply(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(apply(F 0:: 0a,D),apply(F 0:: 0a,E))) & (∀ GH . equal(G:: 0a,H ) −−> equal(f (G),f (H ))) & (∀ Y . ∼equal(apply(Y :: 0a,f (Y )),apply(f (Y ),apply(Y :: 0a,f (Y ))))) −−> False by meson lemma COL052-2 : EQU001-0-ax equal & (∀ XYW . equal(response(compos(X :: 0a,Y ),W ),response(X :: 0a,response(Y :: 0a,W ))))

746 & (∀ XY . agreeable(X ) −−> equal(response(X :: 0a,common-bird(Y )),response(Y :: 0a,common-bird(Y )))) & (∀ ZX . equal(response(X :: 0a,Z ),response(compatible(X ),Z )) −−> agreeable(X )) & (∀ AB. equal(A:: 0a,B) −−> equal(common-bird(A),common-bird(B))) & (∀ CD. equal(C :: 0a,D) −−> equal(compatible(C ),compatible(D))) & (∀ QR. equal(Q:: 0a,R)& agreeable(Q) −−> agreeable(R)) & (∀ ABC . equal(A:: 0a,B) −−> equal(compos(A:: 0a,C ),compos(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(compos(F 0:: 0a,D),compos(F 0:: 0a,E))) & (∀ GHI 0. equal(G:: 0a,H ) −−> equal(response(G:: 0a,I 0),response(H :: 0a,I 0))) & (∀ JLK 0. equal(J :: 0a,K 0) −−> equal(response(L:: 0a,J ),response(L:: 0a,K 0))) & (agreeable(c)) & (∼agreeable(a)) & (equal(c:: 0a,compos(a:: 0a,b))) −−> False oops lemma COL075-2 : EQU001-0-ax equal & (∀ YX . equal(apply(apply(k:: 0a,X ),Y ),X )) & (∀ XYZ . equal(apply(apply(apply(abstraction:: 0a,X ),Y ),Z ),apply(apply(X :: 0a,apply(k:: 0a,Z )),apply(Y :: 0a,Z )))) & (∀ DEF 0. equal(D:: 0a,E) −−> equal(apply(D:: 0a,F 0),apply(E:: 0a,F 0))) & (∀ GI 0 H . equal(G:: 0a,H ) −−> equal(apply(I 0:: 0a,G),apply(I 0:: 0a,H ))) & (∀ AB. equal(A:: 0a,B) −−> equal(b(A),b(B))) & (∀ CD. equal(C :: 0a,D) −−> equal(c(C ),c(D))) & (∀ Y . ∼equal(apply(apply(Y :: 0a,b(Y )),c(Y )),apply(b(Y ),b(Y )))) −−> False oops lemma COM001-1 : (∀ Goal-state Start-state. follows(Goal-state:: 0a,Start-state) −−> succeeds(Goal-state:: 0a,Start-state)) & (∀ Goal-state Intermediate-state Start-state. succeeds(Goal-state:: 0a,Intermediate-state) & succeeds(Intermediate-state:: 0a,Start-state) −−> succeeds(Goal-state:: 0a,Start-state)) & (∀ Start-state Label Goal-state. has(Start-state:: 0a,goto(Label)) & labels(Label:: 0a,Goal-state) −−> succeeds(Goal-state:: 0a,Start-state)) & (∀ Start-state Condition Goal-state. has(Start-state:: 0a,ifthen(Condition:: 0a,Goal-state)) −−> succeeds(Goal-state:: 0a,Start-state)) & (labels(loop:: 0a,p3 )) & (has(p3 :: 0a,ifthen(equal(register-j :: 0a,n),p4 ))) & (has(p4 :: 0a,goto(out))) & (follows(p5 :: 0a,p4 )) & (follows(p8 :: 0a,p3 )) & (has(p8 :: 0a,goto(loop))) & (∼succeeds(p3 :: 0a,p3 )) −−> False by meson

747 lemma COM002-1 : (∀ Goal-state Start-state. follows(Goal-state:: 0a,Start-state) −−> succeeds(Goal-state:: 0a,Start-state)) & (∀ Goal-state Intermediate-state Start-state. succeeds(Goal-state:: 0a,Intermediate-state) & succeeds(Intermediate-state:: 0a,Start-state) −−> succeeds(Goal-state:: 0a,Start-state)) & (∀ Start-state Label Goal-state. has(Start-state:: 0a,goto(Label)) & labels(Label:: 0a,Goal-state) −−> succeeds(Goal-state:: 0a,Start-state)) & (∀ Start-state Condition Goal-state. has(Start-state:: 0a,ifthen(Condition:: 0a,Goal-state)) −−> succeeds(Goal-state:: 0a,Start-state)) & (has(p1 :: 0a,assign(register-j :: 0a,num0 ))) & (follows(p2 :: 0a,p1 )) & (has(p2 :: 0a,assign(register-k:: 0a,num1 ))) & (labels(loop:: 0a,p3 )) & (follows(p3 :: 0a,p2 )) & (has(p3 :: 0a,ifthen(equal(register-j :: 0a,n),p4 ))) & (has(p4 :: 0a,goto(out))) & (follows(p5 :: 0a,p4 )) & (follows(p6 :: 0a,p3 )) & (has(p6 :: 0a,assign(register-k:: 0a,mtimes(num2 :: 0a,register-k)))) & (follows(p7 :: 0a,p6 )) & (has(p7 :: 0a,assign(register-j :: 0a,mplus(register-j :: 0a,num1 )))) & (follows(p8 :: 0a,p7 )) & (has(p8 :: 0a,goto(loop))) & (∼succeeds(p3 :: 0a,p3 )) −−> False by meson lemma COM002-2 : (∀ Goal-state Start-state. ∼(fails(Goal-state:: 0a,Start-state)& follows(Goal-state:: 0a,Start-state))) & (∀ Goal-state Intermediate-state Start-state. fails(Goal-state:: 0a,Start-state) −−> fails(Goal-state:: 0a,Intermediate-state) | fails(Intermediate-state:: 0a,Start-state)) & (∀ Start-state Label Goal-state. ∼(fails(Goal-state:: 0a,Start-state)& has(Start-state:: 0a,goto(Label)) & labels(Label:: 0a,Goal-state))) & (∀ Start-state Condition Goal-state. ∼(fails(Goal-state:: 0a,Start-state)& has(Start-state:: 0a,ifthen(Condition:: 0a,Goal-state)))) & (has(p1 :: 0a,assign(register-j :: 0a,num0 ))) & (follows(p2 :: 0a,p1 )) & (has(p2 :: 0a,assign(register-k:: 0a,num1 ))) & (labels(loop:: 0a,p3 )) & (follows(p3 :: 0a,p2 )) & (has(p3 :: 0a,ifthen(equal(register-j :: 0a,n),p4 ))) & (has(p4 :: 0a,goto(out))) & (follows(p5 :: 0a,p4 )) & (follows(p6 :: 0a,p3 )) & (has(p6 :: 0a,assign(register-k:: 0a,mtimes(num2 :: 0a,register-k)))) &

748 (follows(p7 :: 0a,p6 )) & (has(p7 :: 0a,assign(register-j :: 0a,mplus(register-j :: 0a,num1 )))) & (follows(p8 :: 0a,p7 )) & (has(p8 :: 0a,goto(loop))) & (fails(p3 :: 0a,p3 )) −−> False by meson lemma COM003-2 : (∀ XYZ . program-decides(X )& program(Y ) −−> decides(X :: 0a,Y ,Z )) & (∀ X . program-decides(X ) | program(f2 (X ))) & (∀ X . decides(X :: 0a,f2 (X ),f1 (X )) −−> program-decides(X )) & (∀ X . program-program-decides(X ) −−> program(X )) & (∀ X . program-program-decides(X ) −−> program-decides(X )) & (∀ X . program(X )& program-decides(X ) −−> program-program-decides(X )) & (∀ X . algorithm-program-decides(X ) −−> algorithm(X )) & (∀ X . algorithm-program-decides(X ) −−> program-decides(X )) & (∀ X . algorithm(X )& program-decides(X ) −−> algorithm-program-decides(X )) & (∀ YX . program-halts2 (X :: 0a,Y ) −−> program(X )) & (∀ XY . program-halts2 (X :: 0a,Y ) −−> halts2 (X :: 0a,Y )) & (∀ XY . program(X )& halts2 (X :: 0a,Y ) −−> program-halts2 (X :: 0a,Y )) & (∀ WXYZ . halts3-outputs(X :: 0a,Y ,Z ,W ) −−> halts3 (X :: 0a,Y ,Z )) & (∀ YZXW . halts3-outputs(X :: 0a,Y ,Z ,W ) −−> outputs(X :: 0a,W )) & (∀ YZXW . halts3 (X :: 0a,Y ,Z )& outputs(X :: 0a,W ) −−> halts3-outputs(X :: 0a,Y ,Z ,W )) & (∀ YX . program-not-halts2 (X :: 0a,Y ) −−> program(X )) & (∀ XY . ∼(program-not-halts2 (X :: 0a,Y )& halts2 (X :: 0a,Y ))) & (∀ XY . program(X ) −−> program-not-halts2 (X :: 0a,Y ) | halts2 (X :: 0a,Y )) & (∀ WXY . halts2-outputs(X :: 0a,Y ,W ) −−> halts2 (X :: 0a,Y )) & (∀ YXW . halts2-outputs(X :: 0a,Y ,W ) −−> outputs(X :: 0a,W )) & (∀ YXW . halts2 (X :: 0a,Y )& outputs(X :: 0a,W ) −−> halts2-outputs(X :: 0a,Y ,W )) & (∀ XWYZ . program-halts2-halts3-outputs(X :: 0a,Y ,Z ,W ) −−> program-halts2 (Y :: 0a,Z )) & (∀ XYZW . program-halts2-halts3-outputs(X :: 0a,Y ,Z ,W ) −−> halts3-outputs(X :: 0a,Y ,Z ,W )) & (∀ XYZW . program-halts2 (Y :: 0a,Z )& halts3-outputs(X :: 0a,Y ,Z ,W ) −−> program-halts2-halts3-outputs(X :: 0a,Y ,Z ,W )) & (∀ XWYZ . program-not-halts2-halts3-outputs(X :: 0a,Y ,Z ,W ) −−> program-not-halts2 (Y :: 0a,Z )) & (∀ XYZW . program-not-halts2-halts3-outputs(X :: 0a,Y ,Z ,W ) −−> halts3-outputs(X :: 0a,Y ,Z ,W )) & (∀ XYZW . program-not-halts2 (Y :: 0a,Z )& halts3-outputs(X :: 0a,Y ,Z ,W ) −−> program-not-halts2-halts3-outputs(X :: 0a,Y ,Z ,W )) & (∀ XWY . program-halts2-halts2-outputs(X :: 0a,Y ,W ) −−> program-halts2 (Y :: 0a,Y )) & (∀ XYW . program-halts2-halts2-outputs(X :: 0a,Y ,W ) −−> halts2-outputs(X :: 0a,Y ,W )) &

749 (∀ XYW . program-halts2 (Y :: 0a,Y )& halts2-outputs(X :: 0a,Y ,W ) −−> program-halts2-halts2-outputs(X :: 0a,Y ,W )) & (∀ XWY . program-not-halts2-halts2-outputs(X :: 0a,Y ,W ) −−> program-not-halts2 (Y :: 0a,Y )) & (∀ XYW . program-not-halts2-halts2-outputs(X :: 0a,Y ,W ) −−> halts2-outputs(X :: 0a,Y ,W )) & (∀ XYW . program-not-halts2 (Y :: 0a,Y )& halts2-outputs(X :: 0a,Y ,W ) −−> program-not-halts2-halts2-outputs(X :: 0a,Y ,W )) & (∀ X . algorithm-program-decides(X ) −−> program-program-decides(c1 )) & (∀ WYZ . program-program-decides(W ) −−> program-halts2-halts3-outputs(W :: 0a,Y ,Z ,good)) & (∀ WYZ . program-program-decides(W ) −−> program-not-halts2-halts3-outputs(W :: 0a,Y ,Z ,bad)) & (∀ W . program(W )& program-halts2-halts3-outputs(W :: 0a,f3 (W ),f3 (W ),good) & program-not-halts2-halts3-outputs(W :: 0a,f3 (W ),f3 (W ),bad) −−> program(c2 )) & (∀ WY . program(W )& program-halts2-halts3-outputs(W :: 0a,f3 (W ),f3 (W ),good) & program-not-halts2-halts3-outputs(W :: 0a,f3 (W ),f3 (W ),bad) −−> program-halts2-halts2-outputs(c2 :: 0a,Y ,good)) & (∀ WY . program(W )& program-halts2-halts3-outputs(W :: 0a,f3 (W ),f3 (W ),good) & program-not-halts2-halts3-outputs(W :: 0a,f3 (W ),f3 (W ),bad) −−> program-not-halts2-halts2-outputs(c2 :: 0a,Y ,bad)) & (∀ V . program(V )& program-halts2-halts2-outputs(V :: 0a,f4 (V ),good)& program-not-halts2-halts2-outputs(V :: 0a,f4 (V ),bad) −−> program(c3 )) & (∀ VY . program(V )& program-halts2-halts2-outputs(V :: 0a,f4 (V ),good)& program-not-halts2-halts2-outputs(V :: 0a,f4 (V ),bad) & program-halts2 (Y :: 0a,Y ) −−> halts2 (c3 :: 0a,Y )) & (∀ VY . program(V )& program-halts2-halts2-outputs(V :: 0a,f4 (V ),good)& program-not-halts2-halts2-outputs(V :: 0a,f4 (V ),bad) −−> program-not-halts2-halts2-outputs(c3 :: 0a,Y ,bad)) & (algorithm-program-decides(c4 )) −−> False by meson lemma COM004-1 : EQU001-0-ax equal & (∀ CDPQXY . failure-node(X :: 0a,or(C :: 0a,P)) & failure-node(Y :: 0a,or(D:: 0a,Q)) & contradictory(P:: 0a,Q)& siblings(X :: 0a,Y ) −−> failure-node(parent-of (X :: 0a,Y ),or(C :: 0a,D))) & (∀ X . contradictory(negate(X ),X )) & (∀ X . contradictory(X :: 0a,negate(X ))) & (∀ X . siblings(left-child-of (X ),right-child-of (X ))) & (∀ DE. equal(D:: 0a,E) −−> equal(left-child-of (D),left-child-of (E))) & (∀ F 0 G. equal(F 0:: 0a,G) −−> equal(negate(F 0),negate(G))) & (∀ HI 0 J . equal(H :: 0a,I 0) −−> equal(or(H :: 0a,J ),or(I 0:: 0a,J ))) & (∀ K 0 ML. equal(K 0:: 0a,L) −−> equal(or(M :: 0a,K 0),or(M :: 0a,L))) & (∀ NO 0 P. equal(N :: 0a,O 0) −−> equal(parent-of (N :: 0a,P),parent-of (O 0:: 0a,P))) & (∀ QS 0 R. equal(Q:: 0a,R) −−> equal(parent-of (S 0:: 0a,Q),parent-of (S 0:: 0a,R))) & (∀ T 0 U . equal(T 0:: 0a,U ) −−> equal(right-child-of (T 0),right-child-of (U ))) &

750 (∀ VWX . equal(V :: 0a,W )& contradictory(V :: 0a,X ) −−> contradictory(W :: 0a,X )) & (∀ Y A1 Z . equal(Y :: 0a,Z )& contradictory(A1 :: 0a,Y ) −−> contradictory(A1 :: 0a,Z )) & (∀ B1 C1 D1 . equal(B1 :: 0a,C1 )& failure-node(B1 :: 0a,D1 ) −−> failure-node(C1 :: 0a,D1 )) & (∀ E1 G1 F1 . equal(E1 :: 0a,F1 )& failure-node(G1 :: 0a,E1 ) −−> failure-node(G1 :: 0a,F1 )) & (∀ H1 I1 J1 . equal(H1 :: 0a,I1 )& siblings(H1 :: 0a,J1 ) −−> siblings(I1 :: 0a,J1 )) & (∀ K1 M1 L1 . equal(K1 :: 0a,L1 )& siblings(M1 :: 0a,K1 ) −−> siblings(M1 :: 0a,L1 )) & (failure-node(n-left:: 0a,or(EMPTY :: 0a,atom))) & (failure-node(n-right:: 0a,or(EMPTY :: 0a,negate(atom)))) & (equal(n-left:: 0a,left-child-of (n))) & (equal(n-right:: 0a,right-child-of (n))) & (∀ Z . ∼failure-node(Z :: 0a,or(EMPTY :: 0a,EMPTY ))) −−> False oops abbreviation GEO001-0-ax continuous lower-dimension-point-3 lower-dimension-point-2 lower-dimension-point-1 extension euclid2 euclid1 outer-pasch equidistant equal between ≡ (∀ XY . between(X :: 0a,Y ,X ) −−> equal(X :: 0a,Y )) & (∀ VXYZ . between(X :: 0a,Y ,V )& between(Y :: 0a,Z ,V ) −−> between(X :: 0a,Y ,Z )) & (∀ YXVZ . between(X :: 0a,Y ,Z )& between(X :: 0a,Y ,V ) −−> equal(X :: 0a,Y ) | between(X :: 0a,Z ,V ) | between(X :: 0a,V ,Z )) & (∀ YX . equidistant(X :: 0a,Y ,Y ,X )) & (∀ ZXY . equidistant(X :: 0a,Y ,Z ,Z ) −−> equal(X :: 0a,Y )) & (∀ X Y Z V V2 W . equidistant(X :: 0a,Y ,Z ,V )& equidistant(X :: 0a,Y ,V2 ,W ) −−> equidistant(Z :: 0a,V ,V2 ,W )) & (∀ WXZVY . between(X :: 0a,W ,V )& between(Y :: 0a,V ,Z ) −−> between(X :: 0a,outer-pasch(W :: 0a,X ,Y ,Z ,V ),Y )) & (∀ WXYZV . between(X :: 0a,W ,V )& between(Y :: 0a,V ,Z ) −−> between(Z :: 0a,W ,outer-pasch(W :: 0a,X ,Y ,Z ,V ))) & (∀ WXYZV . between(X :: 0a,V ,W )& between(Y :: 0a,V ,Z ) −−> equal(X :: 0a,V ) | between(X :: 0a,Z ,euclid1 (W :: 0a,X ,Y ,Z ,V ))) & (∀ WXYZV . between(X :: 0a,V ,W )& between(Y :: 0a,V ,Z ) −−> equal(X :: 0a,V ) | between(X :: 0a,Y ,euclid2 (W :: 0a,X ,Y ,Z ,V ))) & (∀ WXYZV . between(X :: 0a,V ,W )& between(Y :: 0a,V ,Z ) −−> equal(X :: 0a,V ) | between(euclid1 (W :: 0a,X ,Y ,Z ,V ),W ,euclid2 (W :: 0a,X ,Y ,Z ,V ))) & (∀ X1 Y1 X Y Z V Z1 V1 . equidistant(X :: 0a,Y ,X1 ,Y1 )& equidistant(Y :: 0a,Z ,Y1 ,Z1 ) & equidistant(X :: 0a,V ,X1 ,V1 )& equidistant(Y :: 0a,V ,Y1 ,V1 )& between(X :: 0a,Y ,Z ) & between(X1 :: 0a,Y1 ,Z1 ) −−> equal(X :: 0a,Y ) | equidistant(Z :: 0a,V ,Z1 ,V1 )) & (∀ XYWV . between(X :: 0a,Y ,extension(X :: 0a,Y ,W ,V ))) & (∀ XYWV . equidistant(Y :: 0a,extension(X :: 0a,Y ,W ,V ),W ,V )) & (∼between(lower-dimension-point-1 :: 0a,lower-dimension-point-2 ,lower-dimension-point-3 )) & (∼between(lower-dimension-point-2 :: 0a,lower-dimension-point-3 ,lower-dimension-point-1 )) &

751 (∼between(lower-dimension-point-3 :: 0a,lower-dimension-point-1 ,lower-dimension-point-2 )) & (∀ ZXYWV . equidistant(X :: 0a,W ,X ,V )& equidistant(Y :: 0a,W ,Y ,V )& equidis- tant(Z :: 0a,W ,Z ,V ) −−> between(X :: 0a,Y ,Z ) | between(Y :: 0a,Z ,X ) | between(Z :: 0a,X ,Y ) | equal(W :: 0a,V )) & (∀ X Y Z X1 Z1 V . equidistant(V :: 0a,X ,V ,X1 )& equidistant(V :: 0a,Z ,V ,Z1 )& between(V :: 0a,X ,Z )& between(X :: 0a,Y ,Z ) −−> equidistant(V :: 0a,Y ,Z ,continuous(X :: 0a,Y ,Z ,X1 ,Z1 ,V ))) & (∀ X Y Z X1 V Z1 . equidistant(V :: 0a,X ,V ,X1 )& equidistant(V :: 0a,Z ,V ,Z1 )& between(V :: 0a,X ,Z )& between(X :: 0a,Y ,Z ) −−> between(X1 :: 0a,continuous(X :: 0a,Y ,Z ,X1 ,Z1 ,V ),Z1 )) abbreviation GEO001-0-eq continuous extension euclid2 euclid1 outer-pasch equidistant between equal ≡ (∀ XYWZ . equal(X :: 0a,Y )& between(X :: 0a,W ,Z ) −−> between(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& between(W :: 0a,X ,Z ) −−> between(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& between(W :: 0a,Z ,X ) −−> between(W :: 0a,Z ,Y )) & (∀ XYVWZ . equal(X :: 0a,Y )& equidistant(X :: 0a,V ,W ,Z ) −−> equidis- tant(Y :: 0a,V ,W ,Z )) & (∀ XVYWZ . equal(X :: 0a,Y )& equidistant(V :: 0a,X ,W ,Z ) −−> equidis- tant(V :: 0a,Y ,W ,Z )) & (∀ XVWYZ . equal(X :: 0a,Y )& equidistant(V :: 0a,W ,X ,Z ) −−> equidis- tant(V :: 0a,W ,Y ,Z )) & (∀ XVWZY . equal(X :: 0a,Y )& equidistant(V :: 0a,W ,Z ,X ) −−> equidis- tant(V :: 0a,W ,Z ,Y )) & (∀ X Y V1 V2 V3 V4 . equal(X :: 0a,Y ) −−> equal(outer-pasch(X :: 0a,V1 ,V2 ,V3 ,V4 ),outer-pasch(Y :: 0a,V1 ,V2 ,V3 ,V4 ))) & (∀ X V1 Y V2 V3 V4 . equal(X :: 0a,Y ) −−> equal(outer-pasch(V1 :: 0a,X ,V2 ,V3 ,V4 ),outer-pasch(V1 :: 0a,Y ,V2 ,V3 ,V4 ))) & (∀ X V1 V2 Y V3 V4 . equal(X :: 0a,Y ) −−> equal(outer-pasch(V1 :: 0a,V2 ,X ,V3 ,V4 ),outer-pasch(V1 :: 0a,V2 ,Y ,V3 ,V4 ))) & (∀ X V1 V2 V3 Y V4 . equal(X :: 0a,Y ) −−> equal(outer-pasch(V1 :: 0a,V2 ,V3 ,X ,V4 ),outer-pasch(V1 :: 0a,V2 ,V3 ,Y ,V4 ))) & (∀ X V1 V2 V3 V4 Y . equal(X :: 0a,Y ) −−> equal(outer-pasch(V1 :: 0a,V2 ,V3 ,V4 ,X ),outer-pasch(V1 :: 0a,V2 ,V3 ,V4 ,Y ))) & (∀ ABCDEF 0. equal(A:: 0a,B) −−> equal(euclid1 (A:: 0a,C ,D,E,F 0),euclid1 (B:: 0a,C ,D,E,F 0))) & (∀ GI 0 HJK 0 L. equal(G:: 0a,H ) −−> equal(euclid1 (I 0:: 0a,G,J ,K 0,L),euclid1 (I 0:: 0a,H ,J ,K 0,L))) & (∀ MO 0 PNQR. equal(M :: 0a,N ) −−> equal(euclid1 (O 0:: 0a,P,M ,Q,R),euclid1 (O 0:: 0a,P,N ,Q,R))) & (∀ S 0 UVWT 0 X . equal(S 0:: 0a,T 0) −−> equal(euclid1 (U :: 0a,V ,W ,S 0,X ),euclid1 (U :: 0a,V ,W ,T 0,X ))) & (∀ Y A1 B1 C1 D1 Z . equal(Y :: 0a,Z ) −−> equal(euclid1 (A1 :: 0a,B1 ,C1 ,D1 ,Y ),euclid1 (A1 :: 0a,B1 ,C1 ,D1 ,Z ))) & (∀ E1 F1 G1 H1 I1 J1 . equal(E1 :: 0a,F1 ) −−> equal(euclid2 (E1 :: 0a,G1 ,H1 ,I1 ,J1 ),euclid2 (F1 :: 0a,G1 ,H1 ,I1 ,J1 ))) &

752 (∀ K1 M1 L1 N1 O1 P1 . equal(K1 :: 0a,L1 ) −−> equal(euclid2 (M1 :: 0a,K1 ,N1 ,O1 ,P1 ),euclid2 (M1 :: 0a,L1 ,N1 ,O1 ,P1 ))) & (∀ Q1 S1 T1 R1 U1 V1 . equal(Q1 :: 0a,R1 ) −−> equal(euclid2 (S1 :: 0a,T1 ,Q1 ,U1 ,V1 ),euclid2 (S1 :: 0a,T1 ,R1 ,U1 ,V1 ))) & (∀ W1 Y1 Z1 A2 X1 B2 . equal(W1 :: 0a,X1 ) −−> equal(euclid2 (Y1 :: 0a,Z1 ,A2 ,W1 ,B2 ),euclid2 (Y1 :: 0a,Z1 ,A2 ,X1 ,B2 ))) & (∀ C2 E2 F2 G2 H2 D2 . equal(C2 :: 0a,D2 ) −−> equal(euclid2 (E2 :: 0a,F2 ,G2 ,H2 ,C2 ),euclid2 (E2 :: 0a,F2 ,G2 ,H2 ,D2 ))) & (∀ X Y V1 V2 V3 . equal(X :: 0a,Y ) −−> equal(extension(X :: 0a,V1 ,V2 ,V3 ),extension(Y :: 0a,V1 ,V2 ,V3 ))) & (∀ X V1 Y V2 V3 . equal(X :: 0a,Y ) −−> equal(extension(V1 :: 0a,X ,V2 ,V3 ),extension(V1 :: 0a,Y ,V2 ,V3 ))) & (∀ X V1 V2 Y V3 . equal(X :: 0a,Y ) −−> equal(extension(V1 :: 0a,V2 ,X ,V3 ),extension(V1 :: 0a,V2 ,Y ,V3 ))) & (∀ X V1 V2 V3 Y . equal(X :: 0a,Y ) −−> equal(extension(V1 :: 0a,V2 ,V3 ,X ),extension(V1 :: 0a,V2 ,V3 ,Y ))) & (∀ X Y V1 V2 V3 V4 V5 . equal(X :: 0a,Y ) −−> equal(continuous(X :: 0a,V1 ,V2 ,V3 ,V4 ,V5 ),continuous(Y :: 0a,V1 ,V2 ,V3 ,V4 ,V5 ))) & (∀ X V1 Y V2 V3 V4 V5 . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,X ,V2 ,V3 ,V4 ,V5 ),continuous(V1 :: 0a,Y ,V2 ,V3 ,V4 ,V5 ))) & (∀ X V1 V2 Y V3 V4 V5 . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,V2 ,X ,V3 ,V4 ,V5 ),continuous(V1 :: 0a,V2 ,Y ,V3 ,V4 ,V5 ))) & (∀ X V1 V2 V3 Y V4 V5 . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,V2 ,V3 ,X ,V4 ,V5 ),continuous(V1 :: 0a,V2 ,V3 ,Y ,V4 ,V5 ))) & (∀ X V1 V2 V3 V4 Y V5 . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,V2 ,V3 ,V4 ,X ,V5 ),continuous(V1 :: 0a,V2 ,V3 ,V4 ,Y ,V5 ))) & (∀ X V1 V2 V3 V4 V5 Y . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,V2 ,V3 ,V4 ,V5 ,X ),continuous(V1 :: 0a,V2 ,V3 ,V4 ,V5 ,Y )))

lemma GEO003-1 : EQU001-0-ax equal & GEO001-0-ax continuous lower-dimension-point-3 lower-dimension-point-2 lower-dimension-point-1 extension euclid2 euclid1 outer-pasch equidistant equal between & GEO001-0-eq continuous extension euclid2 euclid1 outer-pasch equidistant between equal & (∼between(a:: 0a,b,b)) −−> False by meson abbreviation GEO002-ax-eq continuous euclid2 euclid1 lower-dimension-point-3 lower-dimension-point-2 lower-dimension-point-1 inner-pasch extension between equal equidistant ≡ (∀ YX . equidistant(X :: 0a,Y ,Y ,X )) & (∀ X Y Z V V2 W . equidistant(X :: 0a,Y ,Z ,V )& equidistant(X :: 0a,Y ,V2 ,W ) −−> equidistant(Z :: 0a,V ,V2 ,W )) & (∀ ZXY . equidistant(X :: 0a,Y ,Z ,Z ) −−> equal(X :: 0a,Y )) & (∀ XYWV . between(X :: 0a,Y ,extension(X :: 0a,Y ,W ,V ))) & (∀ XYWV . equidistant(Y :: 0a,extension(X :: 0a,Y ,W ,V ),W ,V )) &

753 (∀ X1 Y1 X Y Z V Z1 V1 . equidistant(X :: 0a,Y ,X1 ,Y1 )& equidistant(Y :: 0a,Z ,Y1 ,Z1 ) & equidistant(X :: 0a,V ,X1 ,V1 )& equidistant(Y :: 0a,V ,Y1 ,V1 )& between(X :: 0a,Y ,Z ) & between(X1 :: 0a,Y1 ,Z1 ) −−> equal(X :: 0a,Y ) | equidistant(Z :: 0a,V ,Z1 ,V1 )) & (∀ XY . between(X :: 0a,Y ,X ) −−> equal(X :: 0a,Y )) & (∀ UVWXY . between(U :: 0a,V ,W )& between(Y :: 0a,X ,W ) −−> between(V :: 0a,inner-pasch(U :: 0a,V ,W ,X ,Y ),Y )) & (∀ VWXYU . between(U :: 0a,V ,W )& between(Y :: 0a,X ,W ) −−> between(X :: 0a,inner-pasch(U :: 0a,V ,W ,X ,Y ),U )) & (∼between(lower-dimension-point-1 :: 0a,lower-dimension-point-2 ,lower-dimension-point-3 )) & (∼between(lower-dimension-point-2 :: 0a,lower-dimension-point-3 ,lower-dimension-point-1 )) & (∼between(lower-dimension-point-3 :: 0a,lower-dimension-point-1 ,lower-dimension-point-2 )) & (∀ ZXYWV . equidistant(X :: 0a,W ,X ,V )& equidistant(Y :: 0a,W ,Y ,V )& equidis- tant(Z :: 0a,W ,Z ,V ) −−> between(X :: 0a,Y ,Z ) | between(Y :: 0a,Z ,X ) | between(Z :: 0a,X ,Y ) | equal(W :: 0a,V )) & (∀ UVWXY . between(U :: 0a,W ,Y )& between(V :: 0a,W ,X ) −−> equal(U :: 0a,W ) | between(U :: 0a,V ,euclid1 (U :: 0a,V ,W ,X ,Y ))) & (∀ UVWXY . between(U :: 0a,W ,Y )& between(V :: 0a,W ,X ) −−> equal(U :: 0a,W ) | between(U :: 0a,X ,euclid2 (U :: 0a,V ,W ,X ,Y ))) & (∀ UVWXY . between(U :: 0a,W ,Y )& between(V :: 0a,W ,X ) −−> equal(U :: 0a,W ) | between(euclid1 (U :: 0a,V ,W ,X ,Y ),Y ,euclid2 (U :: 0a,V ,W ,X ,Y ))) & (∀ U V V1 W X X1 . equidistant(U :: 0a,V ,U ,V1 )& equidistant(U :: 0a,X ,U ,X1 )& between(U :: 0a,V ,X )& between(V :: 0a,W ,X ) −−> between(V1 :: 0a,continuous(U :: 0a,V ,V1 ,W ,X ,X1 ),X1 )) & (∀ U V V1 W X X1 . equidistant(U :: 0a,V ,U ,V1 )& equidistant(U :: 0a,X ,U ,X1 )& between(U :: 0a,V ,X )& between(V :: 0a,W ,X ) −−> equidistant(U :: 0a,W ,U ,continuous(U :: 0a,V ,V1 ,W ,X ,X1 ))) & (∀ XYWZ . equal(X :: 0a,Y )& between(X :: 0a,W ,Z ) −−> between(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& between(W :: 0a,X ,Z ) −−> between(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& between(W :: 0a,Z ,X ) −−> between(W :: 0a,Z ,Y )) & (∀ XYVWZ . equal(X :: 0a,Y )& equidistant(X :: 0a,V ,W ,Z ) −−> equidis- tant(Y :: 0a,V ,W ,Z )) & (∀ XVYWZ . equal(X :: 0a,Y )& equidistant(V :: 0a,X ,W ,Z ) −−> equidis- tant(V :: 0a,Y ,W ,Z )) & (∀ XVWYZ . equal(X :: 0a,Y )& equidistant(V :: 0a,W ,X ,Z ) −−> equidis- tant(V :: 0a,W ,Y ,Z )) & (∀ XVWZY . equal(X :: 0a,Y )& equidistant(V :: 0a,W ,Z ,X ) −−> equidis- tant(V :: 0a,W ,Z ,Y )) & (∀ X Y V1 V2 V3 V4 . equal(X :: 0a,Y ) −−> equal(inner-pasch(X :: 0a,V1 ,V2 ,V3 ,V4 ),inner-pasch(Y :: 0a,V1 ,V2 ,V3 ,V4 ))) & (∀ X V1 Y V2 V3 V4 . equal(X :: 0a,Y ) −−> equal(inner-pasch(V1 :: 0a,X ,V2 ,V3 ,V4 ),inner-pasch(V1 :: 0a,Y ,V2 ,V3 ,V4 ))) & (∀ X V1 V2 Y V3 V4 . equal(X :: 0a,Y ) −−> equal(inner-pasch(V1 :: 0a,V2 ,X ,V3 ,V4 ),inner-pasch(V1 :: 0a,V2 ,Y ,V3 ,V4 ))) &

754 (∀ X V1 V2 V3 Y V4 . equal(X :: 0a,Y ) −−> equal(inner-pasch(V1 :: 0a,V2 ,V3 ,X ,V4 ),inner-pasch(V1 :: 0a,V2 ,V3 ,Y ,V4 ))) & (∀ X V1 V2 V3 V4 Y . equal(X :: 0a,Y ) −−> equal(inner-pasch(V1 :: 0a,V2 ,V3 ,V4 ,X ),inner-pasch(V1 :: 0a,V2 ,V3 ,V4 ,Y ))) & (∀ ABCDEF 0. equal(A:: 0a,B) −−> equal(euclid1 (A:: 0a,C ,D,E,F 0),euclid1 (B:: 0a,C ,D,E,F 0))) & (∀ GI 0 HJK 0 L. equal(G:: 0a,H ) −−> equal(euclid1 (I 0:: 0a,G,J ,K 0,L),euclid1 (I 0:: 0a,H ,J ,K 0,L))) & (∀ MO 0 PNQR. equal(M :: 0a,N ) −−> equal(euclid1 (O 0:: 0a,P,M ,Q,R),euclid1 (O 0:: 0a,P,N ,Q,R))) & (∀ S 0 UVWT 0 X . equal(S 0:: 0a,T 0) −−> equal(euclid1 (U :: 0a,V ,W ,S 0,X ),euclid1 (U :: 0a,V ,W ,T 0,X ))) & (∀ Y A1 B1 C1 D1 Z . equal(Y :: 0a,Z ) −−> equal(euclid1 (A1 :: 0a,B1 ,C1 ,D1 ,Y ),euclid1 (A1 :: 0a,B1 ,C1 ,D1 ,Z ))) & (∀ E1 F1 G1 H1 I1 J1 . equal(E1 :: 0a,F1 ) −−> equal(euclid2 (E1 :: 0a,G1 ,H1 ,I1 ,J1 ),euclid2 (F1 :: 0a,G1 ,H1 ,I1 ,J1 ))) & (∀ K1 M1 L1 N1 O1 P1 . equal(K1 :: 0a,L1 ) −−> equal(euclid2 (M1 :: 0a,K1 ,N1 ,O1 ,P1 ),euclid2 (M1 :: 0a,L1 ,N1 ,O1 ,P1 ))) & (∀ Q1 S1 T1 R1 U1 V1 . equal(Q1 :: 0a,R1 ) −−> equal(euclid2 (S1 :: 0a,T1 ,Q1 ,U1 ,V1 ),euclid2 (S1 :: 0a,T1 ,R1 ,U1 ,V1 ))) & (∀ W1 Y1 Z1 A2 X1 B2 . equal(W1 :: 0a,X1 ) −−> equal(euclid2 (Y1 :: 0a,Z1 ,A2 ,W1 ,B2 ),euclid2 (Y1 :: 0a,Z1 ,A2 ,X1 ,B2 ))) & (∀ C2 E2 F2 G2 H2 D2 . equal(C2 :: 0a,D2 ) −−> equal(euclid2 (E2 :: 0a,F2 ,G2 ,H2 ,C2 ),euclid2 (E2 :: 0a,F2 ,G2 ,H2 ,D2 ))) & (∀ X Y V1 V2 V3 . equal(X :: 0a,Y ) −−> equal(extension(X :: 0a,V1 ,V2 ,V3 ),extension(Y :: 0a,V1 ,V2 ,V3 ))) & (∀ X V1 Y V2 V3 . equal(X :: 0a,Y ) −−> equal(extension(V1 :: 0a,X ,V2 ,V3 ),extension(V1 :: 0a,Y ,V2 ,V3 ))) & (∀ X V1 V2 Y V3 . equal(X :: 0a,Y ) −−> equal(extension(V1 :: 0a,V2 ,X ,V3 ),extension(V1 :: 0a,V2 ,Y ,V3 ))) & (∀ X V1 V2 V3 Y . equal(X :: 0a,Y ) −−> equal(extension(V1 :: 0a,V2 ,V3 ,X ),extension(V1 :: 0a,V2 ,V3 ,Y ))) & (∀ X Y V1 V2 V3 V4 V5 . equal(X :: 0a,Y ) −−> equal(continuous(X :: 0a,V1 ,V2 ,V3 ,V4 ,V5 ),continuous(Y :: 0a,V1 ,V2 ,V3 ,V4 ,V5 ))) & (∀ X V1 Y V2 V3 V4 V5 . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,X ,V2 ,V3 ,V4 ,V5 ),continuous(V1 :: 0a,Y ,V2 ,V3 ,V4 ,V5 ))) & (∀ X V1 V2 Y V3 V4 V5 . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,V2 ,X ,V3 ,V4 ,V5 ),continuous(V1 :: 0a,V2 ,Y ,V3 ,V4 ,V5 ))) & (∀ X V1 V2 V3 Y V4 V5 . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,V2 ,V3 ,X ,V4 ,V5 ),continuous(V1 :: 0a,V2 ,V3 ,Y ,V4 ,V5 ))) & (∀ X V1 V2 V3 V4 Y V5 . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,V2 ,V3 ,V4 ,X ,V5 ),continuous(V1 :: 0a,V2 ,V3 ,V4 ,Y ,V5 ))) & (∀ X V1 V2 V3 V4 V5 Y . equal(X :: 0a,Y ) −−> equal(continuous(V1 :: 0a,V2 ,V3 ,V4 ,V5 ,X ),continuous(V1 :: 0a,V2 ,V3 ,V4 ,V5 ,Y ))) lemma GEO017-2 : EQU001-0-ax equal & GEO002-ax-eq continuous euclid2 euclid1 lower-dimension-point-3 lower-dimension-point-2 lower-dimension-point-1 inner-pasch extension

755 between equal equidistant & (equidistant(u:: 0a,v,w,x)) & (∼equidistant(u:: 0a,v,x,w)) −−> False oops lemma GEO027-3 : EQU001-0-ax equal & GEO002-ax-eq continuous euclid2 euclid1 lower-dimension-point-3 lower-dimension-point-2 lower-dimension-point-1 inner-pasch extension between equal equidistant & (∀ UV . equal(reflection(U :: 0a,V ),extension(U :: 0a,V ,U ,V ))) & (∀ XYZ . equal(X :: 0a,Y ) −−> equal(reflection(X :: 0a,Z ),reflection(Y :: 0a,Z ))) & (∀ A1 C1 B1 . equal(A1 :: 0a,B1 ) −−> equal(reflection(C1 :: 0a,A1 ),reflection(C1 :: 0a,B1 ))) & (∀ UV . equidistant(U :: 0a,V ,U ,V )) & (∀ WXUV . equidistant(U :: 0a,V ,W ,X ) −−> equidistant(W :: 0a,X ,U ,V )) & (∀ VUWX . equidistant(U :: 0a,V ,W ,X ) −−> equidistant(V :: 0a,U ,W ,X )) & (∀ UVXW . equidistant(U :: 0a,V ,W ,X ) −−> equidistant(U :: 0a,V ,X ,W )) & (∀ VUXW . equidistant(U :: 0a,V ,W ,X ) −−> equidistant(V :: 0a,U ,X ,W )) & (∀ WXVU . equidistant(U :: 0a,V ,W ,X ) −−> equidistant(W :: 0a,X ,V ,U )) & (∀ XWUV . equidistant(U :: 0a,V ,W ,X ) −−> equidistant(X :: 0a,W ,U ,V )) & (∀ XWVU . equidistant(U :: 0a,V ,W ,X ) −−> equidistant(X :: 0a,W ,V ,U )) & (∀ WXUVYZ . equidistant(U :: 0a,V ,W ,X )& equidistant(W :: 0a,X ,Y ,Z ) −−> equidistant(U :: 0a,V ,Y ,Z )) & (∀ UVW . equal(V :: 0a,extension(U :: 0a,V ,W ,W ))) & (∀ WXUVY . equal(Y :: 0a,extension(U :: 0a,V ,W ,X )) −−> between(U :: 0a,V ,Y )) & (∀ UV . between(U :: 0a,V ,reflection(U :: 0a,V ))) & (∀ UV . equidistant(V :: 0a,reflection(U :: 0a,V ),U ,V )) & (∀ UV . equal(U :: 0a,V ) −−> equal(V :: 0a,reflection(U :: 0a,V ))) & (∀ U . equal(U :: 0a,reflection(U :: 0a,U ))) & (∀ UV . equal(V :: 0a,reflection(U :: 0a,V )) −−> equal(U :: 0a,V )) & (∀ UV . equidistant(U :: 0a,U ,V ,V )) & (∀ V V1 U W U1 W1 . equidistant(U :: 0a,V ,U1 ,V1 )& equidistant(V :: 0a,W ,V1 ,W1 ) & between(U :: 0a,V ,W )& between(U1 :: 0a,V1 ,W1 ) −−> equidistant(U :: 0a,W ,U1 ,W1 )) & (∀ UVWX . between(U :: 0a,V ,W )& between(U :: 0a,V ,X )& equidistant(V :: 0a,W ,V ,X ) −−> equal(U :: 0a,V ) | equal(W :: 0a,X )) & (between(u:: 0a,v,w)) & (∼equal(u:: 0a,v)) & (∼equal(w:: 0a,extension(u:: 0a,v,v,w))) −−> False oops lemma GEO058-2 : EQU001-0-ax equal & GEO002-ax-eq continuous euclid2 euclid1 lower-dimension-point-3 lower-dimension-point-2 lower-dimension-point-1 inner-pasch extension

756 between equal equidistant & (∀ UV . equal(reflection(U :: 0a,V ),extension(U :: 0a,V ,U ,V ))) & (∀ XYZ . equal(X :: 0a,Y ) −−> equal(reflection(X :: 0a,Z ),reflection(Y :: 0a,Z ))) & (∀ A1 C1 B1 . equal(A1 :: 0a,B1 ) −−> equal(reflection(C1 :: 0a,A1 ),reflection(C1 :: 0a,B1 ))) & (equal(v:: 0a,reflection(u:: 0a,v))) & (∼equal(u:: 0a,v)) −−> False oops lemma GEO079-1 : (∀ UVWXYZ . right-angle(U :: 0a,V ,W )& right-angle(X :: 0a,Y ,Z ) −−> eq(U :: 0a,V ,W ,X ,Y ,Z )) & (∀ UVWXYZ . CONGRUENT (U :: 0a,V ,W ,X ,Y ,Z ) −−> eq(U :: 0a,V ,W ,X ,Y ,Z )) & (∀ VWUX . trapezoid(U :: 0a,V ,W ,X ) −−> parallel(V :: 0a,W ,U ,X )) & (∀ UVXY . parallel(U :: 0a,V ,X ,Y ) −−> eq(X :: 0a,V ,U ,V ,X ,Y )) & (trapezoid(a:: 0a,b,c,d)) & (∼eq(a:: 0a,c,b,c,a,d)) −−> False by meson abbreviation GRP003-0-ax equal multiply INVERSE identity product ≡ (∀ X . product(identity:: 0a,X ,X )) & (∀ X . product(X :: 0a,identity,X )) & (∀ X . product(INVERSE(X ),X ,identity)) & (∀ X . product(X :: 0a,INVERSE(X ),identity)) & (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) & (∀ XYZW . product(X :: 0a,Y ,Z )& product(X :: 0a,Y ,W ) −−> equal(Z :: 0a,W )) & (∀ YUZXVW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(U :: 0a,Z ,W ) −−> product(X :: 0a,V ,W )) & (∀ YXVUZW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(X :: 0a,V ,W ) −−> product(U :: 0a,Z ,W )) abbreviation GRP003-0-eq product multiply INVERSE equal ≡ (∀ XY . equal(X :: 0a,Y ) −−> equal(INVERSE(X ),INVERSE(Y ))) & (∀ XYW . equal(X :: 0a,Y ) −−> equal(multiply(X :: 0a,W ),multiply(Y :: 0a,W ))) & (∀ XWY . equal(X :: 0a,Y ) −−> equal(multiply(W :: 0a,X ),multiply(W :: 0a,Y ))) & (∀ XYWZ . equal(X :: 0a,Y )& product(X :: 0a,W ,Z ) −−> product(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& product(W :: 0a,X ,Z ) −−> product(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& product(W :: 0a,Z ,X ) −−> product(W :: 0a,Z ,Y )) lemma GRP001-1 : EQU001-0-ax equal &

757 GRP003-0-ax equal multiply INVERSE identity product & GRP003-0-eq product multiply INVERSE equal & (∀ X . product(X :: 0a,X ,identity)) & (product(a:: 0a,b,c)) & (∼product(b:: 0a,a,c)) −−> False oops lemma GRP008-1 : EQU001-0-ax equal & GRP003-0-ax equal multiply INVERSE identity product & GRP003-0-eq product multiply INVERSE equal & (∀ AB. equal(A:: 0a,B) −−> equal(h(A),h(B))) & (∀ CD. equal(C :: 0a,D) −−> equal(j (C ),j (D))) & (∀ AB. equal(A:: 0a,B)& q(A) −−> q(B)) & (∀ BAC . q(A)& product(A:: 0a,B,C ) −−> product(B:: 0a,A,C )) & (∀ A. product(j (A),A,h(A)) | product(A:: 0a,j (A),h(A)) | q(A)) & (∀ A. product(j (A),A,h(A)) & product(A:: 0a,j (A),h(A)) −−> q(A)) & (∼q(identity)) −−> False by meson lemma GRP013-1 : EQU001-0-ax equal & GRP003-0-ax equal multiply INVERSE identity product & GRP003-0-eq product multiply INVERSE equal & (∀ A. product(A:: 0a,A,identity)) & (product(a:: 0a,b,c)) & (product(INVERSE(a),INVERSE(b),d)) & (∀ ACB. product(INVERSE(A),INVERSE(B),C ) −−> product(A:: 0a,C ,B)) & (∼product(c:: 0a,d,identity)) −−> False oops lemma GRP037-3 : EQU001-0-ax equal & GRP003-0-ax equal multiply INVERSE identity product & GRP003-0-eq product multiply INVERSE equal & (∀ ABC . subgroup-member(A)& subgroup-member(B)& product(A:: 0a,INVERSE(B),C ) −−> subgroup-member(C )) & (∀ AB. equal(A:: 0a,B)& subgroup-member(A) −−> subgroup-member(B)) & (∀ A. subgroup-member(A) −−> product(Gidentity:: 0a,A,A)) & (∀ A. subgroup-member(A) −−> product(A:: 0a,Gidentity,A)) & (∀ A. subgroup-member(A) −−> product(A:: 0a,Ginverse(A),Gidentity)) & (∀ A. subgroup-member(A) −−> product(Ginverse(A),A,Gidentity)) & (∀ A. subgroup-member(A) −−> subgroup-member(Ginverse(A))) & (∀ AB. equal(A:: 0a,B) −−> equal(Ginverse(A),Ginverse(B))) & (∀ ACDB. product(A:: 0a,B,C )& product(A:: 0a,D,C ) −−> equal(D:: 0a,B)) & (∀ BCDA. product(A:: 0a,B,C )& product(D:: 0a,B,C ) −−> equal(D:: 0a,A)) &

758 (subgroup-member(a)) & (subgroup-member(Gidentity)) & (∼equal(INVERSE(a),Ginverse(a))) −−> False by meson lemma GRP031-2 : (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) & (∀ XYZW . product(X :: 0a,Y ,Z )& product(X :: 0a,Y ,W ) −−> equal(Z :: 0a,W )) & (∀ YUZXVW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(U :: 0a,Z ,W ) −−> product(X :: 0a,V ,W )) & (∀ YXVUZW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(X :: 0a,V ,W ) −−> product(U :: 0a,Z ,W )) & (∀ A. product(A:: 0a,INVERSE(A),identity)) & (∀ A. product(A:: 0a,identity,A)) & (∀ A. ∼product(A:: 0a,a,identity)) −−> False by meson lemma GRP034-4 : (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) & (∀ X . product(identity:: 0a,X ,X )) & (∀ X . product(X :: 0a,identity,X )) & (∀ X . product(X :: 0a,INVERSE(X ),identity)) & (∀ YUZXVW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(U :: 0a,Z ,W ) −−> product(X :: 0a,V ,W )) & (∀ YXVUZW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(X :: 0a,V ,W ) −−> product(U :: 0a,Z ,W )) & (∀ BAC . subgroup-member(A)& subgroup-member(B)& product(B:: 0a,INVERSE(A),C ) −−> subgroup-member(C )) & (subgroup-member(a)) & (∼subgroup-member(INVERSE(a))) −−> False by meson lemma GRP047-2 : (∀ X . product(identity:: 0a,X ,X )) & (∀ X . product(INVERSE(X ),X ,identity)) & (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) & (∀ XYZW . product(X :: 0a,Y ,Z )& product(X :: 0a,Y ,W ) −−> equal(Z :: 0a,W )) & (∀ YUZXVW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(U :: 0a,Z ,W ) −−> product(X :: 0a,V ,W )) & (∀ YXVUZW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(X :: 0a,V ,W ) −−> product(U :: 0a,Z ,W )) & (∀ XWZY . equal(X :: 0a,Y )& product(W :: 0a,Z ,X ) −−> product(W :: 0a,Z ,Y )) & (equal(a:: 0a,b)) &

759 (∼equal(multiply(c:: 0a,a),multiply(c:: 0a,b))) −−> False by meson lemma GRP130-1-002 : (group-element(e-1 )) & (group-element(e-2 )) & (∼equal(e-1 :: 0a,e-2 )) & (∼equal(e-2 :: 0a,e-1 )) & (∀ XY . group-element(X )& group-element(Y ) −−> product(X :: 0a,Y ,e-1 ) | product(X :: 0a,Y ,e-2 )) & (∀ XYWZ . product(X :: 0a,Y ,W )& product(X :: 0a,Y ,Z ) −−> equal(W :: 0a,Z )) & (∀ XYWZ . product(X :: 0a,W ,Y )& product(X :: 0a,Z ,Y ) −−> equal(W :: 0a,Z )) & (∀ YXWZ . product(W :: 0a,Y ,X )& product(Z :: 0a,Y ,X ) −−> equal(W :: 0a,Z )) & (∀ Z1 Z2 Y X . product(X :: 0a,Y ,Z1 )& product(X :: 0a,Z1 ,Z2 ) −−> product(Z2 :: 0a,Y ,X )) −−> False oops abbreviation GRP004-0-ax INVERSE identity multiply equal ≡ (∀ X . equal(multiply(identity:: 0a,X ),X )) & (∀ X . equal(multiply(INVERSE(X ),X ),identity)) & (∀ XYZ . equal(multiply(multiply(X :: 0a,Y ),Z ),multiply(X :: 0a,multiply(Y :: 0a,Z )))) & (∀ AB. equal(A:: 0a,B) −−> equal(INVERSE(A),INVERSE(B))) & (∀ CDE. equal(C :: 0a,D) −−> equal(multiply(C :: 0a,E),multiply(D:: 0a,E))) & (∀ F 0 HG. equal(F 0:: 0a,G) −−> equal(multiply(H :: 0a,F 0),multiply(H :: 0a,G))) abbreviation GRP004-2-ax multiply least-upper-bound greatest-lower-bound equal ≡ (∀ YX . equal(greatest-lower-bound(X :: 0a,Y ),greatest-lower-bound(Y :: 0a,X ))) & (∀ YX . equal(least-upper-bound(X :: 0a,Y ),least-upper-bound(Y :: 0a,X ))) & (∀ XYZ . equal(greatest-lower-bound(X :: 0a,greatest-lower-bound(Y :: 0a,Z )),greatest-lower-bound(greatest-lower-bound(X :: 0a,Y ),Z ))) & (∀ XYZ . equal(least-upper-bound(X :: 0a,least-upper-bound(Y :: 0a,Z )),least-upper-bound(least-upper-bound(X :: 0a,Y ),Z ))) & (∀ X . equal(least-upper-bound(X :: 0a,X ),X )) & (∀ X . equal(greatest-lower-bound(X :: 0a,X ),X )) & (∀ YX . equal(least-upper-bound(X :: 0a,greatest-lower-bound(X :: 0a,Y )),X )) & (∀ YX . equal(greatest-lower-bound(X :: 0a,least-upper-bound(X :: 0a,Y )),X )) & (∀ YXZ . equal(multiply(X :: 0a,least-upper-bound(Y :: 0a,Z )),least-upper-bound(multiply(X :: 0a,Y ),multiply(X :: 0a,Z )))) & (∀ YXZ . equal(multiply(X :: 0a,greatest-lower-bound(Y :: 0a,Z )),greatest-lower-bound(multiply(X :: 0a,Y ),multiply(X :: 0a,Z )))) & (∀ YZX . equal(multiply(least-upper-bound(Y :: 0a,Z ),X ),least-upper-bound(multiply(Y :: 0a,X ),multiply(Z :: 0a,X )))) & (∀ YZX . equal(multiply(greatest-lower-bound(Y :: 0a,Z ),X ),greatest-lower-bound(multiply(Y :: 0a,X ),multiply(Z :: 0a,X ))))

760 & (∀ ABC . equal(A:: 0a,B) −−> equal(greatest-lower-bound(A:: 0a,C ),greatest-lower-bound(B:: 0a,C ))) & (∀ ACB. equal(A:: 0a,B) −−> equal(greatest-lower-bound(C :: 0a,A),greatest-lower-bound(C :: 0a,B))) & (∀ ABC . equal(A:: 0a,B) −−> equal(least-upper-bound(A:: 0a,C ),least-upper-bound(B:: 0a,C ))) & (∀ ACB. equal(A:: 0a,B) −−> equal(least-upper-bound(C :: 0a,A),least-upper-bound(C :: 0a,B))) & (∀ ABC . equal(A:: 0a,B) −−> equal(multiply(A:: 0a,C ),multiply(B:: 0a,C ))) & (∀ ACB. equal(A:: 0a,B) −−> equal(multiply(C :: 0a,A),multiply(C :: 0a,B))) lemma GRP156-1 : EQU001-0-ax equal & GRP004-0-ax INVERSE identity multiply equal & GRP004-2-ax multiply least-upper-bound greatest-lower-bound equal & (equal(least-upper-bound(a:: 0a,b),b)) & (∼equal(greatest-lower-bound(multiply(a:: 0a,c),multiply(b:: 0a,c)),multiply(a:: 0a,c))) −−> False by meson lemma GRP168-1 : EQU001-0-ax equal & GRP004-0-ax INVERSE identity multiply equal & GRP004-2-ax multiply least-upper-bound greatest-lower-bound equal & (equal(least-upper-bound(a:: 0a,b),b)) & (∼equal(least-upper-bound(multiply(INVERSE(c),multiply(a:: 0a,c)),multiply(INVERSE(c),multiply(b:: 0a,c))),multiply(INVERSE(c),multiply(b:: 0a,c)))) −−> False by meson abbreviation HEN002-0-ax identity Zero Divide equal mless-equal ≡ (∀ XY . mless-equal(X :: 0a,Y ) −−> equal(Divide(X :: 0a,Y ),Zero)) & (∀ XY . equal(Divide(X :: 0a,Y ),Zero) −−> mless-equal(X :: 0a,Y )) & (∀ YX . mless-equal(Divide(X :: 0a,Y ),X )) & (∀ XYZ . mless-equal(Divide(Divide(X :: 0a,Z ),Divide(Y :: 0a,Z )),Divide(Divide(X :: 0a,Y ),Z ))) & (∀ X . mless-equal(Zero:: 0a,X )) & (∀ XY . mless-equal(X :: 0a,Y )& mless-equal(Y :: 0a,X ) −−> equal(X :: 0a,Y )) & (∀ X . mless-equal(X :: 0a,identity)) abbreviation HEN002-0-eq mless-equal Divide equal ≡ (∀ ABC . equal(A:: 0a,B) −−> equal(Divide(A:: 0a,C ),Divide(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(Divide(F 0:: 0a,D),Divide(F 0:: 0a,E))) & (∀ GHI 0. equal(G:: 0a,H )& mless-equal(G:: 0a,I 0) −−> mless-equal(H :: 0a,I 0)) & (∀ JLK 0. equal(J :: 0a,K 0)& mless-equal(L:: 0a,J ) −−> mless-equal(L:: 0a,K 0))

761 lemma HEN003-3 : EQU001-0-ax equal & HEN002-0-ax identity Zero Divide equal mless-equal & HEN002-0-eq mless-equal Divide equal & (∼equal(Divide(a:: 0a,a),Zero)) −−> False oops lemma HEN007-2 : EQU001-0-ax equal & (∀ XY . mless-equal(X :: 0a,Y ) −−> quotient(X :: 0a,Y ,Zero)) & (∀ XY . quotient(X :: 0a,Y ,Zero) −−> mless-equal(X :: 0a,Y )) & (∀ YZX . quotient(X :: 0a,Y ,Z ) −−> mless-equal(Z :: 0a,X )) & (∀ Y X V3 V2 V1 Z V4 V5 . quotient(X :: 0a,Y ,V1 )& quotient(Y :: 0a,Z ,V2 )& quotient(X :: 0a,Z ,V3 )& quotient(V3 :: 0a,V2 ,V4 )& quotient(V1 :: 0a,Z ,V5 ) −−> mless-equal(V4 :: 0a,V5 )) & (∀ X . mless-equal(Zero:: 0a,X )) & (∀ XY . mless-equal(X :: 0a,Y )& mless-equal(Y :: 0a,X ) −−> equal(X :: 0a,Y )) & (∀ X . mless-equal(X :: 0a,identity)) & (∀ XY . quotient(X :: 0a,Y ,Divide(X :: 0a,Y ))) & (∀ XYZW . quotient(X :: 0a,Y ,Z )& quotient(X :: 0a,Y ,W ) −−> equal(Z :: 0a,W )) & (∀ XYWZ . equal(X :: 0a,Y )& quotient(X :: 0a,W ,Z ) −−> quotient(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& quotient(W :: 0a,X ,Z ) −−> quotient(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& quotient(W :: 0a,Z ,X ) −−> quotient(W :: 0a,Z ,Y )) & (∀ XZY . equal(X :: 0a,Y )& mless-equal(Z :: 0a,X ) −−> mless-equal(Z :: 0a,Y )) & (∀ XYZ . equal(X :: 0a,Y )& mless-equal(X :: 0a,Z ) −−> mless-equal(Y :: 0a,Z )) & (∀ XYW . equal(X :: 0a,Y ) −−> equal(Divide(X :: 0a,W ),Divide(Y :: 0a,W ))) & (∀ XWY . equal(X :: 0a,Y ) −−> equal(Divide(W :: 0a,X ),Divide(W :: 0a,Y ))) & (∀ X . quotient(X :: 0a,identity,Zero)) & (∀ X . quotient(Zero:: 0a,X ,Zero)) & (∀ X . quotient(X :: 0a,X ,Zero)) & (∀ X . quotient(X :: 0a,Zero,X )) & (∀ YXZ . mless-equal(X :: 0a,Y )& mless-equal(Y :: 0a,Z ) −−> mless-equal(X :: 0a,Z )) & (∀ W1 X Z W2 Y . quotient(X :: 0a,Y ,W1 )& mless-equal(W1 :: 0a,Z )& quotient(X :: 0a,Z ,W2 ) −−> mless-equal(W2 :: 0a,Y )) & (mless-equal(x:: 0a,y)) & (quotient(z:: 0a,y,zQy)) & (quotient(z:: 0a,x,zQx)) & (∼mless-equal(zQy:: 0a,zQx)) −−> False oops lemma HEN008-4 : EQU001-0-ax equal &

762 HEN002-0-ax identity Zero Divide equal mless-equal & HEN002-0-eq mless-equal Divide equal & (∀ X . equal(Divide(X :: 0a,identity),Zero)) & (∀ X . equal(Divide(Zero:: 0a,X ),Zero)) & (∀ X . equal(Divide(X :: 0a,X ),Zero)) & (equal(Divide(a:: 0a,Zero),a)) & (∀ YXZ . mless-equal(X :: 0a,Y )& mless-equal(Y :: 0a,Z ) −−> mless-equal(X :: 0a,Z )) & (∀ XZY . mless-equal(Divide(X :: 0a,Y ),Z ) −−> mless-equal(Divide(X :: 0a,Z ),Y )) & (∀ YZX . mless-equal(X :: 0a,Y ) −−> mless-equal(Divide(Z :: 0a,Y ),Divide(Z :: 0a,X ))) & (mless-equal(a:: 0a,b)) & (∼mless-equal(Divide(a:: 0a,c),Divide(b:: 0a,c))) −−> False oops lemma HEN009-5 : EQU001-0-ax equal & (∀ YX . equal(Divide(Divide(X :: 0a,Y ),X ),Zero)) & (∀ XYZ . equal(Divide(Divide(Divide(X :: 0a,Z ),Divide(Y :: 0a,Z )),Divide(Divide(X :: 0a,Y ),Z )),Zero)) & (∀ X . equal(Divide(Zero:: 0a,X ),Zero)) & (∀ XY . equal(Divide(X :: 0a,Y ),Zero)& equal(Divide(Y :: 0a,X ),Zero) −−> equal(X :: 0a,Y )) & (∀ X . equal(Divide(X :: 0a,identity),Zero)) & (∀ ABC . equal(A:: 0a,B) −−> equal(Divide(A:: 0a,C ),Divide(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(Divide(F 0:: 0a,D),Divide(F 0:: 0a,E))) & (∀ YXZ . equal(Divide(X :: 0a,Y ),Zero)& equal(Divide(Y :: 0a,Z ),Zero) −−> equal(Divide(X :: 0a,Z ),Zero)) & (∀ XZY . equal(Divide(Divide(X :: 0a,Y ),Z ),Zero) −−> equal(Divide(Divide(X :: 0a,Z ),Y ),Zero)) & (∀ YZX . equal(Divide(X :: 0a,Y ),Zero) −−> equal(Divide(Divide(Z :: 0a,Y ),Divide(Z :: 0a,X )),Zero)) & (∼equal(Divide(identity:: 0a,a),Divide(identity:: 0a,Divide(identity:: 0a,Divide(identity:: 0a,a))))) & (equal(Divide(identity:: 0a,a),b)) & (equal(Divide(identity:: 0a,b),c)) & (equal(Divide(identity:: 0a,c),d)) & (∼equal(b:: 0a,d)) −−> False by meson lemma HEN012-3 : EQU001-0-ax equal & HEN002-0-ax identity Zero Divide equal mless-equal & HEN002-0-eq mless-equal Divide equal & (∼mless-equal(a:: 0a,a)) −−> False oops

763 lemma LCL010-1 : (∀ XY . is-a-theorem(equivalent(X :: 0a,Y )) & is-a-theorem(X ) −−> is-a-theorem(Y )) & (∀ XZY . is-a-theorem(equivalent(equivalent(X :: 0a,Y ),equivalent(equivalent(X :: 0a,Z ),equivalent(Z :: 0a,Y ))))) & (∼is-a-theorem(equivalent(equivalent(a:: 0a,b),equivalent(equivalent(c:: 0a,b),equivalent(a:: 0a,c))))) −−> False by meson lemma LCL077-2 : (∀ XY . is-a-theorem(implies(X ,Y )) & is-a-theorem(X ) −−> is-a-theorem(Y )) & (∀ YX . is-a-theorem(implies(X ,implies(Y ,X )))) & (∀ YXZ . is-a-theorem(implies(implies(X ,implies(Y ,Z )),implies(implies(X ,Y ),implies(X ,Z ))))) & (∀ YX . is-a-theorem(implies(implies(not(X ),not(Y )),implies(Y ,X )))) & (∀ X2 X1 X3 . is-a-theorem(implies(X1 ,X2 )) & is-a-theorem(implies(X2 ,X3 )) −−> is-a-theorem(implies(X1 ,X3 ))) & (∼is-a-theorem(implies(not(not(a)),a))) −−> False by meson lemma LCL082-1 : (∀ XY . is-a-theorem(implies(X :: 0a,Y )) & is-a-theorem(X ) −−> is-a-theorem(Y )) & (∀ YZUX . is-a-theorem(implies(implies(implies(X :: 0a,Y ),Z ),implies(implies(Z :: 0a,X ),implies(U :: 0a,X ))))) & (∼is-a-theorem(implies(a:: 0a,implies(b:: 0a,a)))) −−> False by meson lemma LCL111-1 : (∀ XY . is-a-theorem(implies(X ,Y )) & is-a-theorem(X ) −−> is-a-theorem(Y )) & (∀ YX . is-a-theorem(implies(X ,implies(Y ,X )))) & (∀ YXZ . is-a-theorem(implies(implies(X ,Y ),implies(implies(Y ,Z ),implies(X ,Z ))))) & (∀ YX . is-a-theorem(implies(implies(implies(X ,Y ),Y ),implies(implies(Y ,X ),X )))) & (∀ YX . is-a-theorem(implies(implies(not(X ),not(Y )),implies(Y ,X )))) & (∼is-a-theorem(implies(implies(a,b),implies(implies(c,a),implies(c,b))))) −−> False by meson lemma LCL143-1 :

764 (∀ X . equal(X ,X )) & (∀ YX . equal(X ,Y ) −−> equal(Y ,X )) & (∀ YXZ . equal(X ,Y )& equal(Y ,Z ) −−> equal(X ,Z )) & (∀ X . equal(implies(true,X ),X )) & (∀ YXZ . equal(implies(implies(X ,Y ),implies(implies(Y ,Z ),implies(X ,Z ))),true)) & (∀ YX . equal(implies(implies(X ,Y ),Y ),implies(implies(Y ,X ),X ))) & (∀ YX . equal(implies(implies(not(X ),not(Y )),implies(Y ,X )),true)) & (∀ ABC . equal(A,B) −−> equal(implies(A,C ),implies(B,C ))) & (∀ DF 0 E. equal(D,E) −−> equal(implies(F 0,D),implies(F 0,E))) & (∀ GH . equal(G,H ) −−> equal(not(G),not(H ))) & (∀ XY . equal(big-V (X ,Y ),implies(implies(X ,Y ),Y ))) & (∀ XY . equal(big-hat(X ,Y ),not(big-V (not(X ),not(Y ))))) & (∀ XY . ordered(X ,Y ) −−> equal(implies(X ,Y ),true)) & (∀ XY . equal(implies(X ,Y ),true) −−> ordered(X ,Y )) & (∀ ABC . equal(A,B) −−> equal(big-V (A,C ),big-V (B,C ))) & (∀ DF 0 E. equal(D,E) −−> equal(big-V (F 0,D),big-V (F 0,E))) & (∀ GHI 0. equal(G,H ) −−> equal(big-hat(G,I 0),big-hat(H ,I 0))) & (∀ JLK 0. equal(J ,K 0) −−> equal(big-hat(L,J ),big-hat(L,K 0))) & (∀ MNO 0. equal(M ,N )& ordered(M ,O 0) −−> ordered(N ,O 0)) & (∀ PRQ. equal(P,Q)& ordered(R,P) −−> ordered(R,Q)) & (ordered(x,y)) & (∼ordered(implies(z,x),implies(z,y))) −−> False by meson lemma LCL182-1 : (∀ A. axiom(or(not(or(A,A)),A))) & (∀ BA. axiom(or(not(A),or(B,A)))) & (∀ BA. axiom(or(not(or(A,B)),or(B,A)))) & (∀ BAC . axiom(or(not(or(A,or(B,C ))),or(B,or(A,C ))))) & (∀ ACB. axiom(or(not(or(not(A),B)),or(not(or(C ,A)),or(C ,B))))) & (∀ X . axiom(X ) −−> theorem(X )) & (∀ XY . axiom(or(not(Y ),X )) & theorem(Y ) −−> theorem(X )) & (∀ XYZ . axiom(or(not(X ),Y )) & theorem(or(not(Y ),Z )) −−> theorem(or(not(X ),Z ))) & (∼theorem(or(not(or(not(p),q)),or(not(not(q)),not(p))))) −−> False by meson lemma LCL200-1 : (∀ A. axiom(or(not(or(A,A)),A))) & (∀ BA. axiom(or(not(A),or(B,A)))) & (∀ BA. axiom(or(not(or(A,B)),or(B,A)))) & (∀ BAC . axiom(or(not(or(A,or(B,C ))),or(B,or(A,C ))))) & (∀ ACB. axiom(or(not(or(not(A),B)),or(not(or(C ,A)),or(C ,B))))) & (∀ X . axiom(X ) −−> theorem(X )) & (∀ XY . axiom(or(not(Y ),X )) & theorem(Y ) −−> theorem(X )) & (∀ XYZ . axiom(or(not(X ),Y )) & theorem(or(not(Y ),Z )) −−> theorem(or(not(X ),Z )))

765 & (∼theorem(or(not(not(or(p,q))),not(q)))) −−> False by meson lemma LCL215-1 : (∀ A. axiom(or(not(or(A,A)),A))) & (∀ BA. axiom(or(not(A),or(B,A)))) & (∀ BA. axiom(or(not(or(A,B)),or(B,A)))) & (∀ BAC . axiom(or(not(or(A,or(B,C ))),or(B,or(A,C ))))) & (∀ ACB. axiom(or(not(or(not(A),B)),or(not(or(C ,A)),or(C ,B))))) & (∀ X . axiom(X ) −−> theorem(X )) & (∀ XY . axiom(or(not(Y ),X )) & theorem(Y ) −−> theorem(X )) & (∀ XYZ . axiom(or(not(X ),Y )) & theorem(or(not(Y ),Z )) −−> theorem(or(not(X ),Z ))) & (∼theorem(or(not(or(not(p),q)),or(not(or(p,q)),q)))) −−> False by meson lemma LCL230-2 : (q −−> p | r)& (∼p)& (q)& (∼r) −−> False by meson lemma LDA003-1 : EQU001-0-ax equal & (∀ YXZ . equal(f (X :: 0a,f (Y :: 0a,Z )),f (f (X :: 0a,Y ),f (X :: 0a,Z )))) & (∀ XY . left(X :: 0a,f (X :: 0a,Y ))) & (∀ YXZ . left(X :: 0a,Y )& left(Y :: 0a,Z ) −−> left(X :: 0a,Z )) & (equal(num2 :: 0a,f (num1 :: 0a,num1 ))) & (equal(num3 :: 0a,f (num2 :: 0a,num1 ))) & (equal(u:: 0a,f (num2 :: 0a,num2 ))) & (∀ ABC . equal(A:: 0a,B) −−> equal(f (A:: 0a,C ),f (B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(f (F 0:: 0a,D),f (F 0:: 0a,E))) & (∀ GHI 0. equal(G:: 0a,H )& left(G:: 0a,I 0) −−> left(H :: 0a,I 0)) & (∀ JLK 0. equal(J :: 0a,K 0)& left(L:: 0a,J ) −−> left(L:: 0a,K 0)) & (∼left(num3 :: 0a,u)) −−> False oops

lemma MSC002-1 : (at(something:: 0a,here,now)) & (∀ Place Situation. hand-at(Place:: 0a,Situation) −−> hand-at(Place:: 0a,let-go(Situation))) & (∀ Place Another-place Situation. hand-at(Place:: 0a,Situation) −−> hand-at(Another-place:: 0a,go(Another-place:: 0a,Situation)))

766 & (∀ Thing Situation. ∼held(Thing:: 0a,let-go(Situation))) & (∀ Situation Thing. at(Thing:: 0a,here,Situation) −−> red(Thing)) & (∀ Thing Place Situation. at(Thing:: 0a,Place,Situation) −−> at(Thing:: 0a,Place,let-go(Situation))) & (∀ Thing Place Situation. at(Thing:: 0a,Place,Situation) −−> at(Thing:: 0a,Place,pick-up(Situation))) & (∀ Thing Place Situation. at(Thing:: 0a,Place,Situation) −−> grabbed(Thing:: 0a,pick-up(go(Place:: 0a,let-go(Situation))))) & (∀ Thing Situation. red(Thing)& put(Thing:: 0a,there,Situation) −−> answer(Situation)) & (∀ Place Thing Another-place Situation. at(Thing:: 0a,Place,Situation)& grabbed(Thing:: 0a,Situation) −−> put(Thing:: 0a,Another-place,go(Another-place:: 0a,Situation))) & (∀ Thing Place Another-place Situation. at(Thing:: 0a,Place,Situation) −−> held(Thing:: 0a,Situation) | at(Thing:: 0a,Place,go(Another-place:: 0a,Situation))) & (∀ One-place Thing Place Situation. hand-at(One-place:: 0a,Situation)& held(Thing:: 0a,Situation) −−> at(Thing:: 0a,Place,go(Place:: 0a,Situation))) & (∀ Place Thing Situation. hand-at(Place:: 0a,Situation)& at(Thing:: 0a,Place,Situation) −−> held(Thing:: 0a,pick-up(Situation))) & (∀ Situation. ∼answer(Situation)) −−> False by meson lemma MSC003-1 : (∀ Number-of-small-parts Small-part Big-part Number-of-mid-parts Mid-part. has-parts(Big-part:: 0a,Number-of-mid-parts,Mid-part) −−> in 0(object-in(Big-part:: 0a,Mid-part,Small-part,Number-of-mid-parts,Number-of-small-parts),Mid-part) | has-parts(Big-part:: 0a,mtimes(Number-of-mid-parts:: 0a,Number-of-small-parts),Small-part)) & (∀ Big-part Mid-part Number-of-mid-parts Number-of-small-parts Small-part. has-parts(Big-part:: 0a,Number-of-mid-parts,Mid-part) & has-parts(object-in(Big-part:: 0a,Mid-part,Small-part,Number-of-mid-parts,Number-of-small-parts),Number-of-small-parts,Small-part) −−> has-parts(Big-part:: 0a,mtimes(Number-of-mid-parts:: 0a,Number-of-small-parts),Small-part)) & (in 0(john:: 0a,boy)) & (∀ X . in 0(X :: 0a,boy) −−> in 0(X :: 0a,human)) & (∀ X . in 0(X :: 0a,hand) −−> has-parts(X :: 0a,num5 ,fingers)) & (∀ X . in 0(X :: 0a,human) −−> has-parts(X :: 0a,num2 ,arm)) & (∀ X . in 0(X :: 0a,arm) −−> has-parts(X :: 0a,num1 ,hand)) & (∼has-parts(john:: 0a,mtimes(num2 :: 0a,num1 ),hand)) −−> False by meson lemma MSC004-1 : (∀ Number-of-small-parts Small-part Big-part Number-of-mid-parts Mid-part. has-parts(Big-part:: 0a,Number-of-mid-parts,Mid-part) −−> in 0(object-in(Big-part:: 0a,Mid-part,Small-part,Number-of-mid-parts,Number-of-small-parts),Mid-part) | has-parts(Big-part:: 0a,mtimes(Number-of-mid-parts:: 0a,Number-of-small-parts),Small-part)) & (∀ Big-part Mid-part Number-of-mid-parts Number-of-small-parts Small-part. has-parts(Big-part:: 0a,Number-of-mid-parts,Mid-part) & has-parts(object-in(Big-part:: 0a,Mid-part,Small-part,Number-of-mid-parts,Number-of-small-parts),Number-of-small-parts,Small-part) −−> has-parts(Big-part:: 0a,mtimes(Number-of-mid-parts:: 0a,Number-of-small-parts),Small-part))

767 & (in 0(john:: 0a,boy)) & (∀ X . in 0(X :: 0a,boy) −−> in 0(X :: 0a,human)) & (∀ X . in 0(X :: 0a,hand) −−> has-parts(X :: 0a,num5 ,fingers)) & (∀ X . in 0(X :: 0a,human) −−> has-parts(X :: 0a,num2 ,arm)) & (∀ X . in 0(X :: 0a,arm) −−> has-parts(X :: 0a,num1 ,hand)) & (∼has-parts(john:: 0a,mtimes(mtimes(num2 :: 0a,num1 ),num5 ),fingers)) −−> False by meson lemma MSC005-1 : (value(truth:: 0a,truth)) & (value(falsity:: 0a,falsity)) & (∀ XY . value(X :: 0a,truth)& value(Y :: 0a,truth) −−> value(xor(X :: 0a,Y ),falsity)) & (∀ XY . value(X :: 0a,truth)& value(Y :: 0a,falsity) −−> value(xor(X :: 0a,Y ),truth)) & (∀ XY . value(X :: 0a,falsity)& value(Y :: 0a,truth) −−> value(xor(X :: 0a,Y ),truth)) & (∀ XY . value(X :: 0a,falsity)& value(Y :: 0a,falsity) −−> value(xor(X :: 0a,Y ),falsity)) & (∀ Value. ∼value(xor(xor(xor(xor(truth:: 0a,falsity),falsity),truth),falsity),Value)) −−> False by meson lemma MSC006-1 : (∀ YXZ . p(X :: 0a,Y )& p(Y :: 0a,Z ) −−> p(X :: 0a,Z )) & (∀ YXZ . q(X :: 0a,Y )& q(Y :: 0a,Z ) −−> q(X :: 0a,Z )) & (∀ YX . q(X :: 0a,Y ) −−> q(Y :: 0a,X )) & (∀ XY . p(X :: 0a,Y ) | q(X :: 0a,Y )) & (∼p(a:: 0a,b)) & (∼q(c:: 0a,d)) −−> False by meson lemma NUM001-1 : (∀ A. equal(A:: 0a,A)) & (∀ BAC . equal(A:: 0a,B)& equal(B:: 0a,C ) −−> equal(A:: 0a,C )) & (∀ BA. equal(add(A:: 0a,B),add(B:: 0a,A))) & (∀ ABC . equal(add(A:: 0a,add(B:: 0a,C )),add(add(A:: 0a,B),C ))) & (∀ BA. equal(subtract(add(A:: 0a,B),B),A)) & (∀ AB. equal(A:: 0a,subtract(add(A:: 0a,B),B))) & (∀ ACB. equal(add(subtract(A:: 0a,B),C ),subtract(add(A:: 0a,C ),B))) & (∀ ACB. equal(subtract(add(A:: 0a,B),C ),add(subtract(A:: 0a,C ),B))) & (∀ ACBD. equal(A:: 0a,B)& equal(C :: 0a,add(A:: 0a,D)) −−> equal(C :: 0a,add(B:: 0a,D))) & (∀ ACDB. equal(A:: 0a,B)& equal(C :: 0a,add(D:: 0a,A)) −−> equal(C :: 0a,add(D:: 0a,B))) &

768 (∀ ACBD. equal(A:: 0a,B)& equal(C :: 0a,subtract(A:: 0a,D)) −−> equal(C :: 0a,subtract(B:: 0a,D))) & (∀ ACDB. equal(A:: 0a,B)& equal(C :: 0a,subtract(D:: 0a,A)) −−> equal(C :: 0a,subtract(D:: 0a,B))) & (∼equal(add(add(a:: 0a,b),c),add(a:: 0a,add(b:: 0a,c)))) −−> False by meson abbreviation NUM001-0-ax multiply successor num0 add equal ≡ (∀ A. equal(add(A:: 0a,num0 ),A)) & (∀ AB. equal(add(A:: 0a,successor(B)),successor(add(A:: 0a,B)))) & (∀ A. equal(multiply(A:: 0a,num0 ),num0 )) & (∀ BA. equal(multiply(A:: 0a,successor(B)),add(multiply(A:: 0a,B),A))) & (∀ AB. equal(successor(A),successor(B)) −−> equal(A:: 0a,B)) & (∀ AB. equal(A:: 0a,B) −−> equal(successor(A),successor(B))) abbreviation NUM001-1-ax predecessor-of-1st-minus-2nd successor add equal mless ≡ (∀ ACB. mless(A:: 0a,B)& mless(C :: 0a,A) −−> mless(C :: 0a,B)) & (∀ ABC . equal(add(successor(A),B),C ) −−> mless(B:: 0a,C )) & (∀ AB. mless(A:: 0a,B) −−> equal(add(successor(predecessor-of-1st-minus-2nd(B:: 0a,A)),A),B)) abbreviation NUM001-2-ax equal mless divides ≡ (∀ AB. divides(A:: 0a,B) −−> mless(A:: 0a,B) | equal(A:: 0a,B)) & (∀ AB. mless(A:: 0a,B) −−> divides(A:: 0a,B)) & (∀ AB. equal(A:: 0a,B) −−> divides(A:: 0a,B)) lemma NUM021-1 : EQU001-0-ax equal & NUM001-0-ax multiply successor num0 add equal & NUM001-1-ax predecessor-of-1st-minus-2nd successor add equal mless & NUM001-2-ax equal mless divides & (mless(b:: 0a,c)) & (∼mless(b:: 0a,a)) & (divides(c:: 0a,a)) & (∀ A. ∼equal(successor(A),num0 )) −−> False by meson lemma NUM024-1 : EQU001-0-ax equal & NUM001-0-ax multiply successor num0 add equal & NUM001-1-ax predecessor-of-1st-minus-2nd successor add equal mless & (∀ BA. equal(add(A:: 0a,B),add(B:: 0a,A))) & (∀ BAC . equal(add(A:: 0a,B),add(C :: 0a,B)) −−> equal(A:: 0a,C )) & (mless(a:: 0a,a)) & (∀ A. ∼equal(successor(A),num0 )) −−> False oops

769 abbreviation SET004-0-ax not-homomorphism2 not-homomorphism1 homomorphism compatible operation cantor diagonalise subset-relation one-to-one choice apply regular function identity-relation single-valued-class compos powerClass sum-class omega inductive successor-relation successor image 0 rng domain range-of INVERSE flip rot domain-of null-class restrct difference union complement intersection element-relation second first cross-product ordered-pair singleton unordered-pair equal universal-class not-subclass-element member subclass ≡ (∀ XUY . subclass(X :: 0a,Y )& member(U :: 0a,X ) −−> member(U :: 0a,Y )) & (∀ XY . member(not-subclass-element(X :: 0a,Y ),X ) | subclass(X :: 0a,Y )) & (∀ XY . member(not-subclass-element(X :: 0a,Y ),Y ) −−> subclass(X :: 0a,Y )) & (∀ X . subclass(X :: 0a,universal-class)) & (∀ XY . equal(X :: 0a,Y ) −−> subclass(X :: 0a,Y )) & (∀ YX . equal(X :: 0a,Y ) −−> subclass(Y :: 0a,X )) & (∀ XY . subclass(X :: 0a,Y )& subclass(Y :: 0a,X ) −−> equal(X :: 0a,Y )) & (∀ XUY . member(U :: 0a,unordered-pair(X :: 0a,Y )) −−> equal(U :: 0a,X ) | equal(U :: 0a,Y )) & (∀ XY . member(X :: 0a,universal-class) −−> member(X :: 0a,unordered-pair(X :: 0a,Y ))) & (∀ XY . member(Y :: 0a,universal-class) −−> member(Y :: 0a,unordered-pair(X :: 0a,Y ))) & (∀ XY . member(unordered-pair(X :: 0a,Y ),universal-class)) & (∀ X . equal(unordered-pair(X :: 0a,X ),singleton(X ))) & (∀ XY . equal(unordered-pair(singleton(X ),unordered-pair(X :: 0a,singleton(Y ))),ordered-pair(X :: 0a,Y ))) & (∀ VYUX . member(ordered-pair(U :: 0a,V ),cross-product(X :: 0a,Y )) −−> mem- ber(U :: 0a,X )) & (∀ UXVY . member(ordered-pair(U :: 0a,V ),cross-product(X :: 0a,Y )) −−> mem- ber(V :: 0a,Y )) & (∀ UVXY . member(U :: 0a,X )& member(V :: 0a,Y ) −−> member(ordered-pair(U :: 0a,V ),cross-product(X :: 0a,Y ))) & (∀ XYZ . member(Z :: 0a,cross-product(X :: 0a,Y )) −−> equal(ordered-pair(first(Z ),second(Z )),Z )) & (subclass(element-relation:: 0a,cross-product(universal-class:: 0a,universal-class))) & (∀ XY . member(ordered-pair(X :: 0a,Y ),element-relation) −−> member(X :: 0a,Y )) & (∀ XY . member(ordered-pair(X :: 0a,Y ),cross-product(universal-class:: 0a,universal-class)) & member(X :: 0a,Y ) −−> member(ordered-pair(X :: 0a,Y ),element-relation)) & (∀ YZX . member(Z :: 0a,intersection(X :: 0a,Y )) −−> member(Z :: 0a,X )) & (∀ XZY . member(Z :: 0a,intersection(X :: 0a,Y )) −−> member(Z :: 0a,Y )) & (∀ ZXY . member(Z :: 0a,X )& member(Z :: 0a,Y ) −−> member(Z :: 0a,intersection(X :: 0a,Y ))) & (∀ ZX . ∼(member(Z :: 0a,complement(X )) & member(Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,universal-class) −−> member(Z :: 0a,complement(X )) | member(Z :: 0a,X )) & (∀ XY . equal(complement(intersection(complement(X ),complement(Y ))),union(X :: 0a,Y ))) &

770 (∀ XY . equal(intersection(complement(intersection(X :: 0a,Y )),complement(intersection(complement(X ),complement(Y )))),difference(X :: 0a,Y ))) & (∀ Xr X Y . equal(intersection(Xr:: 0a,cross-product(X :: 0a,Y )),restrct(Xr:: 0a,X ,Y ))) & (∀ Xr X Y . equal(intersection(cross-product(X :: 0a,Y ),Xr),restrct(Xr:: 0a,X ,Y ))) & (∀ ZX . ∼(equal(restrct(X :: 0a,singleton(Z ),universal-class),null-class)& mem- ber(Z :: 0a,domain-of (X )))) & (∀ ZX . member(Z :: 0a,universal-class) −−> equal(restrct(X :: 0a,singleton(Z ),universal-class),null-class) | member(Z :: 0a,domain-of (X ))) & (∀ X . subclass(rot(X ),cross-product(cross-product(universal-class:: 0a,universal-class),universal-class))) & (∀ VWUX . member(ordered-pair(ordered-pair(U :: 0a,V ),W ),rot(X )) −−> mem- ber(ordered-pair(ordered-pair(V :: 0a,W ),U ),X )) & (∀ UVWX . member(ordered-pair(ordered-pair(V :: 0a,W ),U ),X )& member(ordered-pair(ordered-pair(U :: 0a,V ),W ),cross-product(cross-product(universal-class:: 0a,universal-class),universal-class)) −−> member(ordered-pair(ordered-pair(U :: 0a,V ),W ),rot(X ))) & (∀ X . subclass(flip(X ),cross-product(cross-product(universal-class:: 0a,universal-class),universal-class))) & (∀ VUWX . member(ordered-pair(ordered-pair(U :: 0a,V ),W ),flip(X )) −−> mem- ber(ordered-pair(ordered-pair(V :: 0a,U ),W ),X )) & (∀ UVWX . member(ordered-pair(ordered-pair(V :: 0a,U ),W ),X )& member(ordered-pair(ordered-pair(U :: 0a,V ),W ),cross-product(cross-product(universal-class:: 0a,universal-class),universal-class)) −−> member(ordered-pair(ordered-pair(U :: 0a,V ),W ),flip(X ))) & (∀ Y . equal(domain-of (flip(cross-product(Y :: 0a,universal-class))),INVERSE(Y ))) & (∀ Z . equal(domain-of (INVERSE(Z )),range-of (Z ))) & (∀ ZXY . equal(first(not-subclass-element(restrct(Z :: 0a,X ,singleton(Y )),null-class)),domain(Z :: 0a,X ,Y ))) & (∀ ZXY . equal(second(not-subclass-element(restrct(Z :: 0a,singleton(X ),Y ),null-class)),rng(Z :: 0a,X ,Y ))) & (∀ Xr X . equal(range-of (restrct(Xr:: 0a,X ,universal-class)),image 0(Xr:: 0a,X ))) & (∀ X . equal(union(X :: 0a,singleton(X )),successor(X ))) & (subclass(successor-relation:: 0a,cross-product(universal-class:: 0a,universal-class))) & (∀ XY . member(ordered-pair(X :: 0a,Y ),successor-relation) −−> equal(successor(X ),Y )) & (∀ XY . equal(successor(X ),Y )& member(ordered-pair(X :: 0a,Y ),cross-product(universal-class:: 0a,universal-class)) −−> member(ordered-pair(X :: 0a,Y ),successor-relation)) & (∀ X . inductive(X ) −−> member(null-class:: 0a,X )) & (∀ X . inductive(X ) −−> subclass(image 0(successor-relation:: 0a,X ),X )) & (∀ X . member(null-class:: 0a,X )& subclass(image 0(successor-relation:: 0a,X ),X ) −−> inductive(X )) & (inductive(omega)) & (∀ Y . inductive(Y ) −−> subclass(omega:: 0a,Y )) & (member(omega:: 0a,universal-class)) & (∀ X . equal(domain-of (restrct(element-relation:: 0a,universal-class,X )),sum-class(X ))) & (∀ X . member(X :: 0a,universal-class) −−> member(sum-class(X ),universal-class)) & (∀ X . equal(complement(image 0(element-relation:: 0a,complement(X ))),powerClass(X )))

771 & (∀ U . member(U :: 0a,universal-class) −−> member(powerClass(U ),universal-class)) & (∀ Yr Xr. subclass(compos(Yr:: 0a,Xr),cross-product(universal-class:: 0a,universal-class))) & (∀ Z Yr Xr Y . member(ordered-pair(Y :: 0a,Z ),compos(Yr:: 0a,Xr)) −−> mem- ber(Z :: 0a,image 0(Yr:: 0a,image 0(Xr:: 0a,singleton(Y ))))) & (∀ Y Z Yr Xr. member(Z :: 0a,image 0(Yr:: 0a,image 0(Xr:: 0a,singleton(Y )))) & mem- ber(ordered-pair(Y :: 0a,Z ),cross-product(universal-class:: 0a,universal-class)) −−> mem- ber(ordered-pair(Y :: 0a,Z ),compos(Yr:: 0a,Xr))) & (∀ X . single-valued-class(X ) −−> subclass(compos(X :: 0a,INVERSE(X )),identity-relation)) & (∀ X . subclass(compos(X :: 0a,INVERSE(X )),identity-relation) −−> single-valued-class(X )) & (∀ Xf . function(Xf ) −−> subclass(Xf :: 0a,cross-product(universal-class:: 0a,universal-class))) & (∀ Xf . function(Xf ) −−> subclass(compos(Xf :: 0a,INVERSE(Xf )),identity-relation)) & (∀ Xf . subclass(Xf :: 0a,cross-product(universal-class:: 0a,universal-class)) & sub- class(compos(Xf :: 0a,INVERSE(Xf )),identity-relation) −−> function(Xf )) & (∀ Xf X . function(Xf )& member(X :: 0a,universal-class) −−> member(image 0(Xf :: 0a,X ),universal-class)) & (∀ X . equal(X :: 0a,null-class) | member(regular(X ),X )) & (∀ X . equal(X :: 0a,null-class) | equal(intersection(X :: 0a,regular(X )),null-class)) & (∀ Xf Y . equal(sum-class(image 0(Xf :: 0a,singleton(Y ))),apply(Xf :: 0a,Y ))) & (function(choice)) & (∀ Y . member(Y :: 0a,universal-class) −−> equal(Y :: 0a,null-class) | member(apply(choice:: 0a,Y ),Y )) & (∀ Xf . one-to-one(Xf ) −−> function(Xf )) & (∀ Xf . one-to-one(Xf ) −−> function(INVERSE(Xf ))) & (∀ Xf . function(INVERSE(Xf )) & function(Xf ) −−> one-to-one(Xf )) & (equal(intersection(cross-product(universal-class:: 0a,universal-class),intersection(cross-product(universal-class:: 0a,universal-class),complement(compos(complement(element-relation),INVERSE(element-relation))))),subset-relation)) & (equal(intersection(INVERSE(subset-relation),subset-relation),identity-relation)) & (∀ Xr. equal(complement(domain-of (intersection(Xr:: 0a,identity-relation))),diagonalise(Xr))) & (∀ X . equal(intersection(domain-of (X ),diagonalise(compos(INVERSE(element-relation),X ))),cantor(X ))) & (∀ Xf . operation(Xf ) −−> function(Xf )) & (∀ Xf . operation(Xf ) −−> equal(cross-product(domain-of (domain-of (Xf )),domain-of (domain-of (Xf ))),domain-of (Xf ))) & (∀ Xf . operation(Xf ) −−> subclass(range-of (Xf ),domain-of (domain-of (Xf )))) & (∀ Xf . function(Xf )& equal(cross-product(domain-of (domain-of (Xf )),domain-of (domain-of (Xf ))),domain-of (Xf )) & subclass(range-of (Xf ),domain-of (domain-of (Xf ))) −−> operation(Xf )) & (∀ Xf1 Xf2 Xh. compatible(Xh:: 0a,Xf1 ,Xf2 ) −−> function(Xh)) & (∀ Xf2 Xf1 Xh. compatible(Xh:: 0a,Xf1 ,Xf2 ) −−> equal(domain-of (domain-of (Xf1 )),domain-of (Xh))) &

772 (∀ Xf1 Xh Xf2 . compatible(Xh:: 0a,Xf1 ,Xf2 ) −−> subclass(range-of (Xh),domain-of (domain-of (Xf2 )))) & (∀ Xh Xh1 Xf1 Xf2 . function(Xh)& equal(domain-of (domain-of (Xf1 )),domain-of (Xh)) & subclass(range-of (Xh),domain-of (domain-of (Xf2 ))) −−> compatible(Xh1 :: 0a,Xf1 ,Xf2 )) & (∀ Xh Xf2 Xf1 . homomorphism(Xh:: 0a,Xf1 ,Xf2 ) −−> operation(Xf1 )) & (∀ Xh Xf1 Xf2 . homomorphism(Xh:: 0a,Xf1 ,Xf2 ) −−> operation(Xf2 )) & (∀ Xh Xf1 Xf2 . homomorphism(Xh:: 0a,Xf1 ,Xf2 ) −−> compatible(Xh:: 0a,Xf1 ,Xf2 )) & (∀ Xf2 Xh Xf1 X Y . homomorphism(Xh:: 0a,Xf1 ,Xf2 )& member(ordered-pair(X :: 0a,Y ),domain-of (Xf1 )) −−> equal(apply(Xf2 :: 0a,ordered-pair(apply(Xh:: 0a,X ),apply(Xh:: 0a,Y ))),apply(Xh:: 0a,apply(Xf1 :: 0a,ordered-pair(X :: 0a,Y ))))) & (∀ Xh Xf1 Xf2 . operation(Xf1 )& operation(Xf2 )& compatible(Xh:: 0a,Xf1 ,Xf2 ) −−> member(ordered-pair(not-homomorphism1 (Xh:: 0a,Xf1 ,Xf2 ),not-homomorphism2 (Xh:: 0a,Xf1 ,Xf2 )),domain-of (Xf1 )) | homomorphism(Xh:: 0a,Xf1 ,Xf2 )) & (∀ Xh Xf1 Xf2 . operation(Xf1 )& operation(Xf2 )& compatible(Xh:: 0a,Xf1 ,Xf2 ) & equal(apply(Xf2 :: 0a,ordered-pair(apply(Xh:: 0a,not-homomorphism1 (Xh:: 0a,Xf1 ,Xf2 )),apply(Xh:: 0a,not-homomorphism2 (Xh:: 0a,Xf1 ,Xf2 )))),apply(Xh:: 0a,apply(Xf1 :: 0a,ordered-pair(not-homomorphism1 (Xh:: 0a,Xf1 ,Xf2 ),not-homomorphism2 (Xh:: 0a,Xf1 ,Xf2 ))))) −−> homomorphism(Xh:: 0a,Xf1 ,Xf2 )) abbreviation SET004-0-eq subclass single-valued-class operation one-to-one member inductive homomorphism function compatible unordered-pair union sum-class successor singleton second rot restrct regular range-of rng powerClass ordered-pair not-subclass-element not-homomorphism2 not-homomorphism1 INVERSE intersection image 0 flip first domain-of domain difference diagonalise cross-product compos complement cantor apply equal ≡ (∀ DEF 0. equal(D:: 0a,E) −−> equal(apply(D:: 0a,F 0),apply(E:: 0a,F 0))) & (∀ GI 0 H . equal(G:: 0a,H ) −−> equal(apply(I 0:: 0a,G),apply(I 0:: 0a,H ))) & (∀ JK 0. equal(J :: 0a,K 0) −−> equal(cantor(J ),cantor(K 0))) & (∀ LM . equal(L:: 0a,M ) −−> equal(complement(L),complement(M ))) & (∀ NO 0 P. equal(N :: 0a,O 0) −−> equal(compos(N :: 0a,P),compos(O 0:: 0a,P))) & (∀ QS 0 R. equal(Q:: 0a,R) −−> equal(compos(S 0:: 0a,Q),compos(S 0:: 0a,R))) & (∀ T 0 UV . equal(T 0:: 0a,U ) −−> equal(cross-product(T 0:: 0a,V ),cross-product(U :: 0a,V ))) & (∀ WYX . equal(W :: 0a,X ) −−> equal(cross-product(Y :: 0a,W ),cross-product(Y :: 0a,X ))) & (∀ Z A1 . equal(Z :: 0a,A1 ) −−> equal(diagonalise(Z ),diagonalise(A1 ))) & (∀ B1 C1 D1 . equal(B1 :: 0a,C1 ) −−> equal(difference(B1 :: 0a,D1 ),difference(C1 :: 0a,D1 ))) & (∀ E1 G1 F1 . equal(E1 :: 0a,F1 ) −−> equal(difference(G1 :: 0a,E1 ),difference(G1 :: 0a,F1 ))) & (∀ H1 I1 J1 K1 . equal(H1 :: 0a,I1 ) −−> equal(domain(H1 :: 0a,J1 ,K1 ),domain(I1 :: 0a,J1 ,K1 ))) & (∀ L1 N1 M1 O1 . equal(L1 :: 0a,M1 ) −−> equal(domain(N1 :: 0a,L1 ,O1 ),domain(N1 :: 0a,M1 ,O1 ))) & (∀ P1 R1 S1 Q1 . equal(P1 :: 0a,Q1 ) −−> equal(domain(R1 :: 0a,S1 ,P1 ),domain(R1 :: 0a,S1 ,Q1 ))) & (∀ T1 U1 . equal(T1 :: 0a,U1 ) −−> equal(domain-of (T1 ),domain-of (U1 ))) & (∀ V1 W1 . equal(V1 :: 0a,W1 ) −−> equal(first(V1 ),first(W1 ))) &

773 (∀ X1 Y1 . equal(X1 :: 0a,Y1 ) −−> equal(flip(X1 ),flip(Y1 ))) & (∀ Z1 A2 B2 . equal(Z1 :: 0a,A2 ) −−> equal(image 0(Z1 :: 0a,B2 ),image 0(A2 :: 0a,B2 ))) & (∀ C2 E2 D2 . equal(C2 :: 0a,D2 ) −−> equal(image 0(E2 :: 0a,C2 ),image 0(E2 :: 0a,D2 ))) & (∀ F2 G2 H2 . equal(F2 :: 0a,G2 ) −−> equal(intersection(F2 :: 0a,H2 ),intersection(G2 :: 0a,H2 ))) & (∀ I2 K2 J2 . equal(I2 :: 0a,J2 ) −−> equal(intersection(K2 :: 0a,I2 ),intersection(K2 :: 0a,J2 ))) & (∀ L2 M2 . equal(L2 :: 0a,M2 ) −−> equal(INVERSE(L2 ),INVERSE(M2 ))) & (∀ N2 O2 P2 Q2 . equal(N2 :: 0a,O2 ) −−> equal(not-homomorphism1 (N2 :: 0a,P2 ,Q2 ),not-homomorphism1 (O2 :: 0a,P2 ,Q2 ))) & (∀ R2 T2 S2 U2 . equal(R2 :: 0a,S2 ) −−> equal(not-homomorphism1 (T2 :: 0a,R2 ,U2 ),not-homomorphism1 (T2 :: 0a,S2 ,U2 ))) & (∀ V2 X2 Y2 W2 . equal(V2 :: 0a,W2 ) −−> equal(not-homomorphism1 (X2 :: 0a,Y2 ,V2 ),not-homomorphism1 (X2 :: 0a,Y2 ,W2 ))) & (∀ Z2 A3 B3 C3 . equal(Z2 :: 0a,A3 ) −−> equal(not-homomorphism2 (Z2 :: 0a,B3 ,C3 ),not-homomorphism2 (A3 :: 0a,B3 ,C3 ))) & (∀ D3 F3 E3 G3 . equal(D3 :: 0a,E3 ) −−> equal(not-homomorphism2 (F3 :: 0a,D3 ,G3 ),not-homomorphism2 (F3 :: 0a,E3 ,G3 ))) & (∀ H3 J3 K3 I3 . equal(H3 :: 0a,I3 ) −−> equal(not-homomorphism2 (J3 :: 0a,K3 ,H3 ),not-homomorphism2 (J3 :: 0a,K3 ,I3 ))) & (∀ L3 M3 N3 . equal(L3 :: 0a,M3 ) −−> equal(not-subclass-element(L3 :: 0a,N3 ),not-subclass-element(M3 :: 0a,N3 ))) & (∀ O3 Q3 P3 . equal(O3 :: 0a,P3 ) −−> equal(not-subclass-element(Q3 :: 0a,O3 ),not-subclass-element(Q3 :: 0a,P3 ))) & (∀ R3 S3 T3 . equal(R3 :: 0a,S3 ) −−> equal(ordered-pair(R3 :: 0a,T3 ),ordered-pair(S3 :: 0a,T3 ))) & (∀ U3 W3 V3 . equal(U3 :: 0a,V3 ) −−> equal(ordered-pair(W3 :: 0a,U3 ),ordered-pair(W3 :: 0a,V3 ))) & (∀ X3 Y3 . equal(X3 :: 0a,Y3 ) −−> equal(powerClass(X3 ),powerClass(Y3 ))) & (∀ Z3 A4 B4 C4 . equal(Z3 :: 0a,A4 ) −−> equal(rng(Z3 :: 0a,B4 ,C4 ),rng(A4 :: 0a,B4 ,C4 ))) & (∀ D4 F4 E4 G4 . equal(D4 :: 0a,E4 ) −−> equal(rng(F4 :: 0a,D4 ,G4 ),rng(F4 :: 0a,E4 ,G4 ))) & (∀ H4 J4 K4 I4 . equal(H4 :: 0a,I4 ) −−> equal(rng(J4 :: 0a,K4 ,H4 ),rng(J4 :: 0a,K4 ,I4 ))) & (∀ L4 M4 . equal(L4 :: 0a,M4 ) −−> equal(range-of (L4 ),range-of (M4 ))) & (∀ N4 O4 . equal(N4 :: 0a,O4 ) −−> equal(regular(N4 ),regular(O4 ))) & (∀ P4 Q4 R4 S4 . equal(P4 :: 0a,Q4 ) −−> equal(restrct(P4 :: 0a,R4 ,S4 ),restrct(Q4 :: 0a,R4 ,S4 ))) & (∀ T4 V4 U4 W4 . equal(T4 :: 0a,U4 ) −−> equal(restrct(V4 :: 0a,T4 ,W4 ),restrct(V4 :: 0a,U4 ,W4 ))) & (∀ X4 Z4 A5 Y4 . equal(X4 :: 0a,Y4 ) −−> equal(restrct(Z4 :: 0a,A5 ,X4 ),restrct(Z4 :: 0a,A5 ,Y4 ))) & (∀ B5 C5 . equal(B5 :: 0a,C5 ) −−> equal(rot(B5 ),rot(C5 ))) & (∀ D5 E5 . equal(D5 :: 0a,E5 ) −−> equal(second(D5 ),second(E5 ))) & (∀ F5 G5 . equal(F5 :: 0a,G5 ) −−> equal(singleton(F5 ),singleton(G5 ))) & (∀ H5 I5 . equal(H5 :: 0a,I5 ) −−> equal(successor(H5 ),successor(I5 ))) &

774 (∀ J5 K5 . equal(J5 :: 0a,K5 ) −−> equal(sum-class(J5 ),sum-class(K5 ))) & (∀ L5 M5 N5 . equal(L5 :: 0a,M5 ) −−> equal(union(L5 :: 0a,N5 ),union(M5 :: 0a,N5 ))) & (∀ O5 Q5 P5 . equal(O5 :: 0a,P5 ) −−> equal(union(Q5 :: 0a,O5 ),union(Q5 :: 0a,P5 ))) & (∀ R5 S5 T5 . equal(R5 :: 0a,S5 ) −−> equal(unordered-pair(R5 :: 0a,T5 ),unordered-pair(S5 :: 0a,T5 ))) & (∀ U5 W5 V5 . equal(U5 :: 0a,V5 ) −−> equal(unordered-pair(W5 :: 0a,U5 ),unordered-pair(W5 :: 0a,V5 ))) & (∀ X5 Y5 Z5 A6 . equal(X5 :: 0a,Y5 )& compatible(X5 :: 0a,Z5 ,A6 ) −−> compati- ble(Y5 :: 0a,Z5 ,A6 )) & (∀ B6 D6 C6 E6 . equal(B6 :: 0a,C6 )& compatible(D6 :: 0a,B6 ,E6 ) −−> compati- ble(D6 :: 0a,C6 ,E6 )) & (∀ F6 H6 I6 G6 . equal(F6 :: 0a,G6 )& compatible(H6 :: 0a,I6 ,F6 ) −−> compati- ble(H6 :: 0a,I6 ,G6 )) & (∀ J6 K6 . equal(J6 :: 0a,K6 )& function(J6 ) −−> function(K6 )) & (∀ L6 M6 N6 O6 . equal(L6 :: 0a,M6 )& homomorphism(L6 :: 0a,N6 ,O6 ) −−> ho- momorphism(M6 :: 0a,N6 ,O6 )) & (∀ P6 R6 Q6 S6 . equal(P6 :: 0a,Q6 )& homomorphism(R6 :: 0a,P6 ,S6 ) −−> ho- momorphism(R6 :: 0a,Q6 ,S6 )) & (∀ T6 V6 W6 U6 . equal(T6 :: 0a,U6 )& homomorphism(V6 :: 0a,W6 ,T6 ) −−> ho- momorphism(V6 :: 0a,W6 ,U6 )) & (∀ X6 Y6 . equal(X6 :: 0a,Y6 )& inductive(X6 ) −−> inductive(Y6 )) & (∀ Z6 A7 B7 . equal(Z6 :: 0a,A7 )& member(Z6 :: 0a,B7 ) −−> member(A7 :: 0a,B7 )) & (∀ C7 E7 D7 . equal(C7 :: 0a,D7 )& member(E7 :: 0a,C7 ) −−> member(E7 :: 0a,D7 )) & (∀ F7 G7 . equal(F7 :: 0a,G7 )& one-to-one(F7 ) −−> one-to-one(G7 )) & (∀ H7 I7 . equal(H7 :: 0a,I7 )& operation(H7 ) −−> operation(I7 )) & (∀ J7 K7 . equal(J7 :: 0a,K7 )& single-valued-class(J7 ) −−> single-valued-class(K7 )) & (∀ L7 M7 N7 . equal(L7 :: 0a,M7 )& subclass(L7 :: 0a,N7 ) −−> subclass(M7 :: 0a,N7 )) & (∀ O7 Q7 P7 . equal(O7 :: 0a,P7 )& subclass(Q7 :: 0a,O7 ) −−> subclass(Q7 :: 0a,P7 )) abbreviation SET004-1-ax range-of function maps apply application-function singleton-relation element-relation complement intersection single-valued3 singleton image 0 domain single-valued2 second single-valued1 identity-relation INVERSE not-subclass-element first domain-of domain-relation composition-function compos equal ordered-pair member universal-class cross-product compose-class subclass ≡ (∀ X . subclass(compose-class(X ),cross-product(universal-class:: 0a,universal-class))) & (∀ XYZ . member(ordered-pair(Y :: 0a,Z ),compose-class(X )) −−> equal(compos(X :: 0a,Y ),Z )) & (∀ YZX . member(ordered-pair(Y :: 0a,Z ),cross-product(universal-class:: 0a,universal-class)) & equal(compos(X :: 0a,Y ),Z ) −−> member(ordered-pair(Y :: 0a,Z ),compose-class(X ))) &

775 (subclass(composition-function:: 0a,cross-product(universal-class:: 0a,cross-product(universal-class:: 0a,universal-class)))) & (∀ XYZ . member(ordered-pair(X :: 0a,ordered-pair(Y :: 0a,Z )),composition-function) −−> equal(compos(X :: 0a,Y ),Z )) & (∀ XY . member(ordered-pair(X :: 0a,Y ),cross-product(universal-class:: 0a,universal-class)) −−> member(ordered-pair(X :: 0a,ordered-pair(Y :: 0a,compos(X :: 0a,Y ))),composition-function)) & (subclass(domain-relation:: 0a,cross-product(universal-class:: 0a,universal-class))) & (∀ XY . member(ordered-pair(X :: 0a,Y ),domain-relation) −−> equal(domain-of (X ),Y )) & (∀ X . member(X :: 0a,universal-class) −−> member(ordered-pair(X :: 0a,domain-of (X )),domain-relation)) & (∀ X . equal(first(not-subclass-element(compos(X :: 0a,INVERSE(X )),identity-relation)),single-valued1 (X ))) & (∀ X . equal(second(not-subclass-element(compos(X :: 0a,INVERSE(X )),identity-relation)),single-valued2 (X ))) & (∀ X . equal(domain(X :: 0a,image 0(INVERSE(X ),singleton(single-valued1 (X ))),single-valued2 (X )),single-valued3 (X ))) & (equal(intersection(complement(compos(element-relation:: 0a,complement(identity-relation))),element-relation),singleton-relation)) & (subclass(application-function:: 0a,cross-product(universal-class:: 0a,cross-product(universal-class:: 0a,universal-class)))) & (∀ ZYX . member(ordered-pair(X :: 0a,ordered-pair(Y :: 0a,Z )),application-function) −−> member(Y :: 0a,domain-of (X ))) & (∀ XYZ . member(ordered-pair(X :: 0a,ordered-pair(Y :: 0a,Z )),application-function) −−> equal(apply(X :: 0a,Y ),Z )) & (∀ ZXY . member(ordered-pair(X :: 0a,ordered-pair(Y :: 0a,Z )),cross-product(universal-class:: 0a,cross-product(universal-class:: 0a,universal-class))) & member(Y :: 0a,domain-of (X )) −−> member(ordered-pair(X :: 0a,ordered-pair(Y :: 0a,apply(X :: 0a,Y ))),application-function)) & (∀ X Y Xf . maps(Xf :: 0a,X ,Y ) −−> function(Xf )) & (∀ Y Xf X . maps(Xf :: 0a,X ,Y ) −−> equal(domain-of (Xf ),X )) & (∀ X Xf Y . maps(Xf :: 0a,X ,Y ) −−> subclass(range-of (Xf ),Y )) & (∀ Xf Y . function(Xf )& subclass(range-of (Xf ),Y ) −−> maps(Xf :: 0a,domain-of (Xf ),Y )) abbreviation SET004-1-eq maps single-valued3 single-valued2 single-valued1 compose-class equal ≡ (∀ LM . equal(L:: 0a,M ) −−> equal(compose-class(L),compose-class(M ))) & (∀ N2 O2 . equal(N2 :: 0a,O2 ) −−> equal(single-valued1 (N2 ),single-valued1 (O2 ))) & (∀ P2 Q2 . equal(P2 :: 0a,Q2 ) −−> equal(single-valued2 (P2 ),single-valued2 (Q2 ))) & (∀ R2 S2 . equal(R2 :: 0a,S2 ) −−> equal(single-valued3 (R2 ),single-valued3 (S2 ))) & (∀ X2 Y2 Z2 A3 . equal(X2 :: 0a,Y2 )& maps(X2 :: 0a,Z2 ,A3 ) −−> maps(Y2 :: 0a,Z2 ,A3 )) & (∀ B3 D3 C3 E3 . equal(B3 :: 0a,C3 )& maps(D3 :: 0a,B3 ,E3 ) −−> maps(D3 :: 0a,C3 ,E3 )) & (∀ F3 H3 I3 G3 . equal(F3 :: 0a,G3 )& maps(H3 :: 0a,I3 ,F3 ) −−> maps(H3 :: 0a,I3 ,G3 ))

776 abbreviation NUM004-0-ax integer-of omega ordinal-multiply add-relation ordinal-add recursion apply range-of union-of-range-map function recursion-equation-functions rest-relation rest-of limit-ordinals kind-1-ordinals successor-relation image 0 universal-class sum-class element-relation ordinal-numbers section not-well-ordering ordered-pair least member well-ordering singleton domain-of segment null-class intersection asymmetric compos transitive cross-product connected identity-relation complement restrct subclass irreflexive symmetrization-of INVERSE union equal ≡ (∀ X . equal(union(X :: 0a,INVERSE(X )),symmetrization-of (X ))) & (∀ XY . irreflexive(X :: 0a,Y ) −−> subclass(restrct(X :: 0a,Y ,Y ),complement(identity-relation))) & (∀ XY . subclass(restrct(X :: 0a,Y ,Y ),complement(identity-relation)) −−> irreflex- ive(X :: 0a,Y )) & (∀ YX . connected(X :: 0a,Y ) −−> subclass(cross-product(Y :: 0a,Y ),union(identity-relation:: 0a,symmetrization-of (X )))) & (∀ XY . subclass(cross-product(Y :: 0a,Y ),union(identity-relation:: 0a,symmetrization-of (X ))) −−> connected(X :: 0a,Y )) & (∀ Xr Y . transitive(Xr:: 0a,Y ) −−> subclass(compos(restrct(Xr:: 0a,Y ,Y ),restrct(Xr:: 0a,Y ,Y )),restrct(Xr:: 0a,Y ,Y ))) & (∀ Xr Y . subclass(compos(restrct(Xr:: 0a,Y ,Y ),restrct(Xr:: 0a,Y ,Y )),restrct(Xr:: 0a,Y ,Y )) −−> transitive(Xr:: 0a,Y )) & (∀ Xr Y . asymmetric(Xr:: 0a,Y ) −−> equal(restrct(intersection(Xr:: 0a,INVERSE(Xr)),Y ,Y ),null-class)) & (∀ Xr Y . equal(restrct(intersection(Xr:: 0a,INVERSE(Xr)),Y ,Y ),null-class) −−> asymmetric(Xr:: 0a,Y )) & (∀ Xr Y Z . equal(segment(Xr:: 0a,Y ,Z ),domain-of (restrct(Xr:: 0a,Y ,singleton(Z ))))) & (∀ XY . well-ordering(X :: 0a,Y ) −−> connected(X :: 0a,Y )) & (∀ Y Xr U . well-ordering(Xr:: 0a,Y )& subclass(U :: 0a,Y ) −−> equal(U :: 0a,null-class) | member(least(Xr:: 0a,U ),U )) & (∀ Y V Xr U . well-ordering(Xr:: 0a,Y )& subclass(U :: 0a,Y )& member(V :: 0a,U ) −−> member(least(Xr:: 0a,U ),U )) & (∀ Y Xr U . well-ordering(Xr:: 0a,Y )& subclass(U :: 0a,Y ) −−> equal(segment(Xr:: 0a,U ,least(Xr:: 0a,U )),null-class)) & (∀ Y V U Xr. ∼(well-ordering(Xr:: 0a,Y )& subclass(U :: 0a,Y )& member(V :: 0a,U ) & member(ordered-pair(V :: 0a,least(Xr:: 0a,U )),Xr))) & (∀ Xr Y . connected(Xr:: 0a,Y )& equal(not-well-ordering(Xr:: 0a,Y ),null-class) −−> well-ordering(Xr:: 0a,Y )) & (∀ Xr Y . connected(Xr:: 0a,Y ) −−> subclass(not-well-ordering(Xr:: 0a,Y ),Y ) | well-ordering(Xr:: 0a,Y )) & (∀ V Xr Y . member(V :: 0a,not-well-ordering(Xr:: 0a,Y )) & equal(segment(Xr:: 0a,not-well-ordering(Xr:: 0a,Y ),V ),null-class) & connected(Xr:: 0a,Y ) −−> well-ordering(Xr:: 0a,Y )) & (∀ Xr Y Z . section(Xr:: 0a,Y ,Z ) −−> subclass(Y :: 0a,Z )) & (∀ Xr Z Y . section(Xr:: 0a,Y ,Z ) −−> subclass(domain-of (restrct(Xr:: 0a,Z ,Y )),Y )) & (∀ Xr Y Z . subclass(Y :: 0a,Z )& subclass(domain-of (restrct(Xr:: 0a,Z ,Y )),Y ) −−> section(Xr:: 0a,Y ,Z )) & (∀ X . member(X :: 0a,ordinal-numbers) −−> well-ordering(element-relation:: 0a,X ))

777 & (∀ X . member(X :: 0a,ordinal-numbers) −−> subclass(sum-class(X ),X )) & (∀ X . well-ordering(element-relation:: 0a,X )& subclass(sum-class(X ),X )& mem- ber(X :: 0a,universal-class) −−> member(X :: 0a,ordinal-numbers)) & (∀ X . well-ordering(element-relation:: 0a,X )& subclass(sum-class(X ),X ) −−> member(X :: 0a,ordinal-numbers) | equal(X :: 0a,ordinal-numbers)) & (equal(union(singleton(null-class),image 0(successor-relation:: 0a,ordinal-numbers)),kind-1-ordinals)) & (equal(intersection(complement(kind-1-ordinals),ordinal-numbers),limit-ordinals)) & (∀ X . subclass(rest-of (X ),cross-product(universal-class:: 0a,universal-class))) & (∀ VUX . member(ordered-pair(U :: 0a,V ),rest-of (X )) −−> member(U :: 0a,domain-of (X ))) & (∀ XUV . member(ordered-pair(U :: 0a,V ),rest-of (X )) −−> equal(restrct(X :: 0a,U ,universal-class),V )) & (∀ UVX . member(U :: 0a,domain-of (X )) & equal(restrct(X :: 0a,U ,universal-class),V ) −−> member(ordered-pair(U :: 0a,V ),rest-of (X ))) & (subclass(rest-relation:: 0a,cross-product(universal-class:: 0a,universal-class))) & (∀ XY . member(ordered-pair(X :: 0a,Y ),rest-relation) −−> equal(rest-of (X ),Y )) & (∀ X . member(X :: 0a,universal-class) −−> member(ordered-pair(X :: 0a,rest-of (X )),rest-relation)) & (∀ XZ . member(X :: 0a,recursion-equation-functions(Z )) −−> function(Z )) & (∀ ZX . member(X :: 0a,recursion-equation-functions(Z )) −−> function(X )) & (∀ ZX . member(X :: 0a,recursion-equation-functions(Z )) −−> member(domain-of (X ),ordinal-numbers)) & (∀ ZX . member(X :: 0a,recursion-equation-functions(Z )) −−> equal(compos(Z :: 0a,rest-of (X )),X )) & (∀ XZ . function(Z )& function(X )& member(domain-of (X ),ordinal-numbers)& equal(compos(Z :: 0a,rest-of (X )),X ) −−> member(X :: 0a,recursion-equation-functions(Z ))) & (subclass(union-of-range-map:: 0a,cross-product(universal-class:: 0a,universal-class))) & (∀ XY . member(ordered-pair(X :: 0a,Y ),union-of-range-map) −−> equal(sum-class(range-of (X )),Y )) & (∀ XY . member(ordered-pair(X :: 0a,Y ),cross-product(universal-class:: 0a,universal-class)) & equal(sum-class(range-of (X )),Y ) −−> member(ordered-pair(X :: 0a,Y ),union-of-range-map)) & (∀ XY . equal(apply(recursion(X :: 0a,successor-relation,union-of-range-map),Y ),ordinal-add(X :: 0a,Y ))) & (∀ XY . equal(recursion(null-class:: 0a,apply(add-relation:: 0a,X ),union-of-range-map),ordinal-multiply(X :: 0a,Y ))) & (∀ X . member(X :: 0a,omega) −−> equal(integer-of (X ),X )) & (∀ X . member(X :: 0a,omega) | equal(integer-of (X ),null-class)) abbreviation NUM004-0-eq well-ordering transitive section irreflexive connected asymmetric symmetrization-of segment rest-of recursion-equation-functions recursion ordinal-multiply ordinal-add not-well-ordering least integer-of equal ≡

778 (∀ DE. equal(D:: 0a,E) −−> equal(integer-of (D),integer-of (E))) & (∀ F 0 GH . equal(F 0:: 0a,G) −−> equal(least(F 0:: 0a,H ),least(G:: 0a,H ))) & (∀ I 0 K 0 J . equal(I 0:: 0a,J ) −−> equal(least(K 0:: 0a,I 0),least(K 0:: 0a,J ))) & (∀ LMN . equal(L:: 0a,M ) −−> equal(not-well-ordering(L:: 0a,N ),not-well-ordering(M :: 0a,N ))) & (∀ O 0 QP. equal(O 0:: 0a,P) −−> equal(not-well-ordering(Q:: 0a,O 0),not-well-ordering(Q:: 0a,P))) & (∀ RS 0 T 0. equal(R:: 0a,S 0) −−> equal(ordinal-add(R:: 0a,T 0),ordinal-add(S 0:: 0a,T 0))) & (∀ UWV . equal(U :: 0a,V ) −−> equal(ordinal-add(W :: 0a,U ),ordinal-add(W :: 0a,V ))) & (∀ XYZ . equal(X :: 0a,Y ) −−> equal(ordinal-multiply(X :: 0a,Z ),ordinal-multiply(Y :: 0a,Z ))) & (∀ A1 C1 B1 . equal(A1 :: 0a,B1 ) −−> equal(ordinal-multiply(C1 :: 0a,A1 ),ordinal-multiply(C1 :: 0a,B1 ))) & (∀ F1 G1 H1 I1 . equal(F1 :: 0a,G1 ) −−> equal(recursion(F1 :: 0a,H1 ,I1 ),recursion(G1 :: 0a,H1 ,I1 ))) & (∀ J1 L1 K1 M1 . equal(J1 :: 0a,K1 ) −−> equal(recursion(L1 :: 0a,J1 ,M1 ),recursion(L1 :: 0a,K1 ,M1 ))) & (∀ N1 P1 Q1 O1 . equal(N1 :: 0a,O1 ) −−> equal(recursion(P1 :: 0a,Q1 ,N1 ),recursion(P1 :: 0a,Q1 ,O1 ))) & (∀ R1 S1 . equal(R1 :: 0a,S1 ) −−> equal(recursion-equation-functions(R1 ),recursion-equation-functions(S1 ))) & (∀ T1 U1 . equal(T1 :: 0a,U1 ) −−> equal(rest-of (T1 ),rest-of (U1 ))) & (∀ V1 W1 X1 Y1 . equal(V1 :: 0a,W1 ) −−> equal(segment(V1 :: 0a,X1 ,Y1 ),segment(W1 :: 0a,X1 ,Y1 ))) & (∀ Z1 B2 A2 C2 . equal(Z1 :: 0a,A2 ) −−> equal(segment(B2 :: 0a,Z1 ,C2 ),segment(B2 :: 0a,A2 ,C2 ))) & (∀ D2 F2 G2 E2 . equal(D2 :: 0a,E2 ) −−> equal(segment(F2 :: 0a,G2 ,D2 ),segment(F2 :: 0a,G2 ,E2 ))) & (∀ H2 I2 . equal(H2 :: 0a,I2 ) −−> equal(symmetrization-of (H2 ),symmetrization-of (I2 ))) & (∀ J2 K2 L2 . equal(J2 :: 0a,K2 )& asymmetric(J2 :: 0a,L2 ) −−> asymmetric(K2 :: 0a,L2 )) & (∀ M2 O2 N2 . equal(M2 :: 0a,N2 )& asymmetric(O2 :: 0a,M2 ) −−> asymmetric(O2 :: 0a,N2 )) & (∀ P2 Q2 R2 . equal(P2 :: 0a,Q2 )& connected(P2 :: 0a,R2 ) −−> connected(Q2 :: 0a,R2 )) & (∀ S2 U2 T2 . equal(S2 :: 0a,T2 )& connected(U2 :: 0a,S2 ) −−> connected(U2 :: 0a,T2 )) & (∀ V2 W2 X2 . equal(V2 :: 0a,W2 )& irreflexive(V2 :: 0a,X2 ) −−> irreflexive(W2 :: 0a,X2 )) & (∀ Y2 A3 Z2 . equal(Y2 :: 0a,Z2 )& irreflexive(A3 :: 0a,Y2 ) −−> irreflexive(A3 :: 0a,Z2 )) & (∀ B3 C3 D3 E3 . equal(B3 :: 0a,C3 )& section(B3 :: 0a,D3 ,E3 ) −−> section(C3 :: 0a,D3 ,E3 )) & (∀ F3 H3 G3 I3 . equal(F3 :: 0a,G3 )& section(H3 :: 0a,F3 ,I3 ) −−> section(H3 :: 0a,G3 ,I3 )) & (∀ J3 L3 M3 K3 . equal(J3 :: 0a,K3 )& section(L3 :: 0a,M3 ,J3 ) −−> section(L3 :: 0a,M3 ,K3 ))

779 & (∀ N3 O3 P3 . equal(N3 :: 0a,O3 )& transitive(N3 :: 0a,P3 ) −−> transitive(O3 :: 0a,P3 )) & (∀ Q3 S3 R3 . equal(Q3 :: 0a,R3 )& transitive(S3 :: 0a,Q3 ) −−> transitive(S3 :: 0a,R3 )) & (∀ T3 U3 V3 . equal(T3 :: 0a,U3 )& well-ordering(T3 :: 0a,V3 ) −−> well-ordering(U3 :: 0a,V3 )) & (∀ W3 Y3 X3 . equal(W3 :: 0a,X3 )& well-ordering(Y3 :: 0a,W3 ) −−> well-ordering(Y3 :: 0a,X3 )) lemma NUM180-1 : EQU001-0-ax equal & SET004-0-ax not-homomorphism2 not-homomorphism1 homomorphism compatible operation cantor diagonalise subset-relation one-to-one choice apply regular function identity-relation single-valued-class compos powerClass sum-class omega inductive successor-relation successor image 0 rng domain range-of INVERSE flip rot domain-of null-class restrct difference union complement intersection element-relation second first cross-product ordered-pair singleton unordered-pair equal universal-class not-subclass-element member subclass & SET004-0-eq subclass single-valued-class operation one-to-one member inductive homomorphism function compatible unordered-pair union sum-class successor singleton second rot restrct regular range-of rng powerClass ordered-pair not-subclass-element not-homomorphism2 not-homomorphism1 INVERSE intersection image 0 flip first domain-of domain difference diagonalise cross-product compos complement cantor apply equal & SET004-1-ax range-of function maps apply application-function singleton-relation element-relation complement intersection single-valued3 singleton image 0 domain single-valued2 second single-valued1 identity-relation INVERSE not-subclass-element first domain-of domain-relation composition-function compos equal ordered-pair member universal-class cross-product compose-class subclass & SET004-1-eq maps single-valued3 single-valued2 single-valued1 compose-class equal & NUM004-0-ax integer-of omega ordinal-multiply add-relation ordinal-add recursion apply range-of union-of-range-map function recursion-equation-functions rest-relation rest-of limit-ordinals kind-1-ordinals successor-relation image 0 universal-class sum-class element-relation ordinal-numbers section not-well-ordering ordered-pair least member well-ordering singleton domain-of segment null-class intersection asymmetric compos transitive cross-product connected identity-relation complement restrct subclass irreflexive symmetrization-of INVERSE union equal & NUM004-0-eq well-ordering transitive section irreflexive connected asymmetric symmetrization-of segment rest-of recursion-equation-functions recursion ordinal-multiply ordinal-add

780 not-well-ordering least integer-of equal & (∼subclass(limit-ordinals:: 0a,ordinal-numbers)) −−> False by meson

lemma NUM228-1 : EQU001-0-ax equal & SET004-0-ax not-homomorphism2 not-homomorphism1 homomorphism compatible operation cantor diagonalise subset-relation one-to-one choice apply regular function identity-relation single-valued-class compos powerClass sum-class omega inductive successor-relation successor image 0 rng domain range-of INVERSE flip rot domain-of null-class restrct difference union complement intersection element-relation second first cross-product ordered-pair singleton unordered-pair equal universal-class not-subclass-element member subclass & SET004-0-eq subclass single-valued-class operation one-to-one member inductive homomorphism function compatible unordered-pair union sum-class successor singleton second rot restrct regular range-of rng powerClass ordered-pair not-subclass-element not-homomorphism2 not-homomorphism1 INVERSE intersection image 0 flip first domain-of domain difference diagonalise cross-product compos complement cantor apply equal & SET004-1-ax range-of function maps apply application-function singleton-relation element-relation complement intersection single-valued3 singleton image 0 domain single-valued2 second single-valued1 identity-relation INVERSE not-subclass-element first domain-of domain-relation composition-function compos equal ordered-pair member universal-class cross-product compose-class subclass & SET004-1-eq maps single-valued3 single-valued2 single-valued1 compose-class equal & NUM004-0-ax integer-of omega ordinal-multiply add-relation ordinal-add recursion apply range-of union-of-range-map function recursion-equation-functions rest-relation rest-of limit-ordinals kind-1-ordinals successor-relation image 0 universal-class sum-class element-relation ordinal-numbers section not-well-ordering ordered-pair least member well-ordering singleton domain-of segment null-class intersection asymmetric compos transitive cross-product connected identity-relation complement restrct subclass irreflexive symmetrization-of INVERSE union equal & NUM004-0-eq well-ordering transitive section irreflexive connected asymmetric symmetrization-of segment rest-of recursion-equation-functions recursion ordinal-multiply ordinal-add not-well-ordering least integer-of equal & (∼function(z)) & (∼equal(recursion-equation-functions(z),null-class)) −−> False by meson

781 lemma PLA002-1 : (∀ Situation1 Situation2 . warm(Situation1 ) | cold(Situation2 )) & (∀ Situation. at(a:: 0a,Situation) −−> at(b:: 0a,walk(b:: 0a,Situation))) & (∀ Situation. at(a:: 0a,Situation) −−> at(b:: 0a,drive(b:: 0a,Situation))) & (∀ Situation. at(b:: 0a,Situation) −−> at(a:: 0a,walk(a:: 0a,Situation))) & (∀ Situation. at(b:: 0a,Situation) −−> at(a:: 0a,drive(a:: 0a,Situation))) & (∀ Situation. cold(Situation)& at(b:: 0a,Situation) −−> at(c:: 0a,skate(c:: 0a,Situation))) & (∀ Situation. cold(Situation)& at(c:: 0a,Situation) −−> at(b:: 0a,skate(b:: 0a,Situation))) & (∀ Situation. warm(Situation)& at(b:: 0a,Situation) −−> at(d:: 0a,climb(d:: 0a,Situation))) & (∀ Situation. warm(Situation)& at(d:: 0a,Situation) −−> at(b:: 0a,climb(b:: 0a,Situation))) & (∀ Situation. at(c:: 0a,Situation) −−> at(d:: 0a,go(d:: 0a,Situation))) & (∀ Situation. at(d:: 0a,Situation) −−> at(c:: 0a,go(c:: 0a,Situation))) & (∀ Situation. at(c:: 0a,Situation) −−> at(e:: 0a,go(e:: 0a,Situation))) & (∀ Situation. at(e:: 0a,Situation) −−> at(c:: 0a,go(c:: 0a,Situation))) & (∀ Situation. at(d:: 0a,Situation) −−> at(f :: 0a,go(f :: 0a,Situation))) & (∀ Situation. at(f :: 0a,Situation) −−> at(d:: 0a,go(d:: 0a,Situation))) & (at(f :: 0a,s0 )) & (∀ S 0. ∼at(a:: 0a,S 0)) −−> False by meson abbreviation PLA001-0-ax putdown on pickup do holding table differ clear EMPTY and 0 holds ≡ (∀ X Y State. holds(X :: 0a,State)& holds(Y :: 0a,State) −−> holds(and 0(X :: 0a,Y ),State)) & (∀ State X . holds(EMPTY :: 0a,State)& holds(clear(X ),State)& differ(X :: 0a,table) −−> holds(holding(X ),do(pickup(X ),State))) & (∀ Y X State. holds(on(X :: 0a,Y ),State)& holds(clear(X ),State)& holds(EMPTY :: 0a,State) −−> holds(clear(Y ),do(pickup(X ),State))) & (∀ Y State X Z . holds(on(X :: 0a,Y ),State)& differ(X :: 0a,Z ) −−> holds(on(X :: 0a,Y ),do(pickup(Z ),State))) & (∀ State X Z . holds(clear(X ),State)& differ(X :: 0a,Z ) −−> holds(clear(X ),do(pickup(Z ),State))) & (∀ X Y State. holds(holding(X ),State)& holds(clear(Y ),State) −−> holds(EMPTY :: 0a,do(putdown(X :: 0a,Y ),State))) & (∀ X Y State. holds(holding(X ),State)& holds(clear(Y ),State) −−> holds(on(X :: 0a,Y ),do(putdown(X :: 0a,Y ),State))) & (∀ X Y State. holds(holding(X ),State)& holds(clear(Y ),State) −−> holds(clear(X ),do(putdown(X :: 0a,Y ),State))) & (∀ Z W X Y State. holds(on(X :: 0a,Y ),State) −−> holds(on(X :: 0a,Y ),do(putdown(Z :: 0a,W ),State))) & (∀ X State Z Y . holds(clear(Z ),State)& differ(Z :: 0a,Y ) −−> holds(clear(Z ),do(putdown(X :: 0a,Y ),State)))

782 abbreviation PLA001-1-ax EMPTY clear s0 on holds table d c b a differ ≡ (∀ YX . differ(Y :: 0a,X ) −−> differ(X :: 0a,Y )) & (differ(a:: 0a,b)) & (differ(a:: 0a,c)) & (differ(a:: 0a,d)) & (differ(a:: 0a,table)) & (differ(b:: 0a,c)) & (differ(b:: 0a,d)) & (differ(b:: 0a,table)) & (differ(c:: 0a,d)) & (differ(c:: 0a,table)) & (differ(d:: 0a,table)) & (holds(on(a:: 0a,table),s0 )) & (holds(on(b:: 0a,table),s0 )) & (holds(on(c:: 0a,d),s0 )) & (holds(on(d:: 0a,table),s0 )) & (holds(clear(a),s0 )) & (holds(clear(b),s0 )) & (holds(clear(c),s0 )) & (holds(EMPTY :: 0a,s0 )) & (∀ State. holds(clear(table),State)) lemma PLA006-1 : PLA001-0-ax putdown on pickup do holding table differ clear EMPTY and 0 holds & PLA001-1-ax EMPTY clear s0 on holds table d c b a differ & (∀ State. ∼holds(on(c:: 0a,table),State)) −−> False by meson lemma PLA017-1 : PLA001-0-ax putdown on pickup do holding table differ clear EMPTY and 0 holds & PLA001-1-ax EMPTY clear s0 on holds table d c b a differ & (∀ State. ∼holds(on(a:: 0a,c),State)) −−> False by meson lemma PLA022-1 : PLA001-0-ax putdown on pickup do holding table differ clear EMPTY and 0 holds & PLA001-1-ax EMPTY clear s0 on holds table d c b a differ & (∀ State. ∼holds(and 0(on(c:: 0a,d),on(a:: 0a,c)),State)) −−> False by meson lemma PLA022-2 : PLA001-0-ax putdown on pickup do holding table differ clear EMPTY and 0 holds

783 & PLA001-1-ax EMPTY clear s0 on holds table d c b a differ & (∀ State. ∼holds(and 0(on(a:: 0a,c),on(c:: 0a,d)),State)) −−> False by meson lemma PRV001-1 : (∀ XYZ . q1 (X :: 0a,Y ,Z )& mless-or-equal(X :: 0a,Y ) −−> q2 (X :: 0a,Y ,Z )) & (∀ XYZ . q1 (X :: 0a,Y ,Z ) −−> mless-or-equal(X :: 0a,Y ) | q3 (X :: 0a,Y ,Z )) & (∀ ZXY . q2 (X :: 0a,Y ,Z ) −−> q4 (X :: 0a,Y ,Y )) & (∀ ZYX . q3 (X :: 0a,Y ,Z ) −−> q4 (X :: 0a,Y ,X )) & (∀ X . mless-or-equal(X :: 0a,X )) & (∀ XY . mless-or-equal(X :: 0a,Y )& mless-or-equal(Y :: 0a,X ) −−> equal(X :: 0a,Y )) & (∀ YXZ . mless-or-equal(X :: 0a,Y )& mless-or-equal(Y :: 0a,Z ) −−> mless-or-equal(X :: 0a,Z )) & (∀ YX . mless-or-equal(X :: 0a,Y ) | mless-or-equal(Y :: 0a,X )) & (∀ XY . equal(X :: 0a,Y ) −−> mless-or-equal(X :: 0a,Y )) & (∀ XYZ . equal(X :: 0a,Y )& mless-or-equal(X :: 0a,Z ) −−> mless-or-equal(Y :: 0a,Z )) & (∀ XZY . equal(X :: 0a,Y )& mless-or-equal(Z :: 0a,X ) −−> mless-or-equal(Z :: 0a,Y )) & (q1 (a:: 0a,b,c)) & (∀ W . ∼(q4 (a:: 0a,b,W )& mless-or-equal(a:: 0a,W )& mless-or-equal(b:: 0a,W )& mless-or-equal(W :: 0a,a))) & (∀ W . ∼(q4 (a:: 0a,b,W )& mless-or-equal(a:: 0a,W )& mless-or-equal(b:: 0a,W )& mless-or-equal(W :: 0a,b))) −−> False by meson abbreviation SWV001-1-ax mless-THAN successor predecessor equal ≡ (∀ X . equal(predecessor(successor(X )),X )) & (∀ X . equal(successor(predecessor(X )),X )) & (∀ XY . equal(predecessor(X ),predecessor(Y )) −−> equal(X :: 0a,Y )) & (∀ XY . equal(successor(X ),successor(Y )) −−> equal(X :: 0a,Y )) & (∀ X . mless-THAN (predecessor(X ),X )) & (∀ X . mless-THAN (X :: 0a,successor(X ))) & (∀ XYZ . mless-THAN (X :: 0a,Y )& mless-THAN (Y :: 0a,Z ) −−> mless-THAN (X :: 0a,Z )) & (∀ XY . mless-THAN (X :: 0a,Y ) | mless-THAN (Y :: 0a,X ) | equal(X :: 0a,Y )) & (∀ X . ∼mless-THAN (X :: 0a,X )) & (∀ YX . ∼(mless-THAN (X :: 0a,Y )& mless-THAN (Y :: 0a,X ))) & (∀ YXZ . equal(X :: 0a,Y )& mless-THAN (X :: 0a,Z ) −−> mless-THAN (Y :: 0a,Z )) & (∀ YZX . equal(X :: 0a,Y )& mless-THAN (Z :: 0a,X ) −−> mless-THAN (Z :: 0a,Y )) abbreviation SWV001-0-eq a successor predecessor equal ≡ (∀ XY . equal(X :: 0a,Y ) −−> equal(predecessor(X ),predecessor(Y ))) & (∀ XY . equal(X :: 0a,Y ) −−> equal(successor(X ),successor(Y ))) &

784 (∀ XY . equal(X :: 0a,Y ) −−> equal(a(X ),a(Y ))) lemma PRV003-1 : EQU001-0-ax equal & SWV001-1-ax mless-THAN successor predecessor equal & SWV001-0-eq a successor predecessor equal & (∼mless-THAN (n:: 0a,j )) & (mless-THAN (k:: 0a,j )) & (∼mless-THAN (k:: 0a,i)) & (mless-THAN (i:: 0a,n)) & (mless-THAN (a(j ),a(k))) & (∀ X . mless-THAN (X :: 0a,j )& mless-THAN (a(X ),a(k)) −−> mless-THAN (X :: 0a,i)) & (∀ X . mless-THAN (One:: 0a,i)& mless-THAN (a(X ),a(predecessor(i))) −−> mless-THAN (X :: 0a,i) | mless-THAN (n:: 0a,X )) & (∀ X . ∼(mless-THAN (One:: 0a,X )& mless-THAN (X :: 0a,i)& mless-THAN (a(X ),a(predecessor(X ))))) & (mless-THAN (j :: 0a,i)) −−> False by meson lemma PRV005-1 : EQU001-0-ax equal & SWV001-1-ax mless-THAN successor predecessor equal & SWV001-0-eq a successor predecessor equal & (∼mless-THAN (n:: 0a,k)) & (∼mless-THAN (k:: 0a,l)) & (∼mless-THAN (k:: 0a,i)) & (mless-THAN (l:: 0a,n)) & (mless-THAN (One:: 0a,l)) & (mless-THAN (a(k),a(predecessor(l)))) & (∀ X . mless-THAN (X :: 0a,successor(n)) & mless-THAN (a(X ),a(k)) −−> mless-THAN (X :: 0a,l)) & (∀ X . mless-THAN (One:: 0a,l)& mless-THAN (a(X ),a(predecessor(l))) −−> mless-THAN (X :: 0a,l) | mless-THAN (n:: 0a,X )) & (∀ X . ∼(mless-THAN (One:: 0a,X )& mless-THAN (X :: 0a,l)& mless-THAN (a(X ),a(predecessor(X ))))) −−> False by meson lemma PRV006-1 : EQU001-0-ax equal & SWV001-1-ax mless-THAN successor predecessor equal & SWV001-0-eq a successor predecessor equal & (∼mless-THAN (n:: 0a,m)) & (mless-THAN (i:: 0a,m)) & (mless-THAN (i:: 0a,n)) & (∼mless-THAN (i:: 0a,One)) &

785 (mless-THAN (a(i),a(m))) & (∀ X . mless-THAN (X :: 0a,successor(n)) & mless-THAN (a(X ),a(m)) −−> mless-THAN (X :: 0a,i)) & (∀ X . mless-THAN (One:: 0a,i)& mless-THAN (a(X ),a(predecessor(i))) −−> mless-THAN (X :: 0a,i) | mless-THAN (n:: 0a,X )) & (∀ X . ∼(mless-THAN (One:: 0a,X )& mless-THAN (X :: 0a,i)& mless-THAN (a(X ),a(predecessor(X ))))) −−> False by meson lemma PRV009-1 : (∀ YX . mless-or-equal(X :: 0a,Y ) | mless(Y :: 0a,X )) & (mless(j :: 0a,i)) & (mless-or-equal(m:: 0a,p)) & (mless-or-equal(p:: 0a,q)) & (mless-or-equal(q:: 0a,n)) & (∀ XY . mless-or-equal(m:: 0a,X )& mless(X :: 0a,i)& mless(j :: 0a,Y )& mless-or-equal(Y :: 0a,n) −−> mless-or-equal(a(X ),a(Y ))) & (∀ XY . mless-or-equal(m:: 0a,X )& mless-or-equal(X :: 0a,Y )& mless-or-equal(Y :: 0a,j ) −−> mless-or-equal(a(X ),a(Y ))) & (∀ XY . mless-or-equal(i:: 0a,X )& mless-or-equal(X :: 0a,Y )& mless-or-equal(Y :: 0a,n) −−> mless-or-equal(a(X ),a(Y ))) & (∼mless-or-equal(a(p),a(q))) −−> False by meson lemma PUZ012-1 : (∀ X . equal-fruits(X :: 0a,X )) & (∀ X . equal-boxes(X :: 0a,X )) & (∀ XY . ∼(label(X :: 0a,Y )& contains(X :: 0a,Y ))) & (∀ X . contains(boxa:: 0a,X ) | contains(boxb:: 0a,X ) | contains(boxc:: 0a,X )) & (∀ X . contains(X :: 0a,apples) | contains(X :: 0a,bananas) | contains(X :: 0a,oranges)) & (∀ XYZ . contains(X :: 0a,Y )& contains(X :: 0a,Z ) −−> equal-fruits(Y :: 0a,Z )) & (∀ YXZ . contains(X :: 0a,Y )& contains(Z :: 0a,Y ) −−> equal-boxes(X :: 0a,Z )) & (∼equal-boxes(boxa:: 0a,boxb)) & (∼equal-boxes(boxb:: 0a,boxc)) & (∼equal-boxes(boxa:: 0a,boxc)) & (∼equal-fruits(apples:: 0a,bananas)) & (∼equal-fruits(bananas:: 0a,oranges)) & (∼equal-fruits(apples:: 0a,oranges)) & (label(boxa:: 0a,apples)) & (label(boxb:: 0a,oranges)) & (label(boxc:: 0a,bananas)) & (contains(boxb:: 0a,apples)) & (∼(contains(boxa:: 0a,bananas)& contains(boxc:: 0a,oranges))) −−> False by meson

786 lemma PUZ020-1 : EQU001-0-ax equal & (∀ AB. equal(A:: 0a,B) −−> equal(statement-by(A),statement-by(B))) & (∀ X . person(X ) −−> knight(X ) | knave(X )) & (∀ X . ∼(person(X )& knight(X )& knave(X ))) & (∀ XY . says(X :: 0a,Y )& a-truth(Y ) −−> a-truth(Y )) & (∀ XY . ∼(says(X :: 0a,Y )& equal(X :: 0a,Y ))) & (∀ YX . says(X :: 0a,Y ) −−> equal(Y :: 0a,statement-by(X ))) & (∀ XY . ∼(person(X )& equal(X :: 0a,statement-by(Y )))) & (∀ X . person(X )& a-truth(statement-by(X )) −−> knight(X )) & (∀ X . person(X ) −−> a-truth(statement-by(X )) | knave(X )) & (∀ XY . equal(X :: 0a,Y )& knight(X ) −−> knight(Y )) & (∀ XY . equal(X :: 0a,Y )& knave(X ) −−> knave(Y )) & (∀ XY . equal(X :: 0a,Y )& person(X ) −−> person(Y )) & (∀ XYZ . equal(X :: 0a,Y )& says(X :: 0a,Z ) −−> says(Y :: 0a,Z )) & (∀ XZY . equal(X :: 0a,Y )& says(Z :: 0a,X ) −−> says(Z :: 0a,Y )) & (∀ XY . equal(X :: 0a,Y )& a-truth(X ) −−> a-truth(Y )) & (∀ XY . knight(X )& says(X :: 0a,Y ) −−> a-truth(Y )) & (∀ XY . ∼(knave(X )& says(X :: 0a,Y )& a-truth(Y ))) & (person(husband)) & (person(wife)) & (∼equal(husband:: 0a,wife)) & (says(husband:: 0a,statement-by(husband))) & (a-truth(statement-by(husband)) & knight(husband) −−> knight(wife)) & (knight(husband) −−> a-truth(statement-by(husband))) & (a-truth(statement-by(husband)) | knight(wife)) & (knight(wife) −−> a-truth(statement-by(husband))) & (∼knight(husband)) −−> False by meson lemma PUZ025-1 : (∀ X . a-truth(truthteller(X )) | a-truth(liar(X ))) & (∀ X . ∼(a-truth(truthteller(X )) & a-truth(liar(X )))) & (∀ Truthteller Statement. a-truth(truthteller(Truthteller)) & a-truth(says(Truthteller:: 0a,Statement)) −−> a-truth(Statement)) & (∀ Liar Statement. ∼(a-truth(liar(Liar)) & a-truth(says(Liar:: 0a,Statement)) & a-truth(Statement))) & (∀ Statement Truthteller. a-truth(Statement)& a-truth(says(Truthteller:: 0a,Statement)) −−> a-truth(truthteller(Truthteller))) & (∀ Statement Liar. a-truth(says(Liar:: 0a,Statement)) −−> a-truth(Statement) | a-truth(liar(Liar))) & (∀ ZXY . people(X :: 0a,Y ,Z )& a-truth(liar(X )) & a-truth(liar(Y )) −−> a-truth(equal-type(X :: 0a,Y ))) & (∀ ZXY . people(X :: 0a,Y ,Z )& a-truth(truthteller(X )) & a-truth(truthteller(Y )) −−> a-truth(equal-type(X :: 0a,Y ))) & (∀ XY . a-truth(equal-type(X :: 0a,Y )) & a-truth(truthteller(X )) −−> a-truth(truthteller(Y ))) & (∀ XY . a-truth(equal-type(X :: 0a,Y )) & a-truth(liar(X )) −−> a-truth(liar(Y )))

787 & (∀ XY . a-truth(truthteller(X )) −−> a-truth(equal-type(X :: 0a,Y )) | a-truth(liar(Y ))) & (∀ XY . a-truth(liar(X )) −−> a-truth(equal-type(X :: 0a,Y )) | a-truth(truthteller(Y ))) & (∀ YX . a-truth(equal-type(X :: 0a,Y )) −−> a-truth(equal-type(Y :: 0a,X ))) & (∀ XY . ask-1-if-2 (X :: 0a,Y )& a-truth(truthteller(X )) & a-truth(Y ) −−> an- swer(yes)) & (∀ XY . ask-1-if-2 (X :: 0a,Y )& a-truth(truthteller(X )) −−> a-truth(Y ) | an- swer(no)) & (∀ XY . ask-1-if-2 (X :: 0a,Y )& a-truth(liar(X )) & a-truth(Y ) −−> answer(no)) & (∀ XY . ask-1-if-2 (X :: 0a,Y )& a-truth(liar(X )) −−> a-truth(Y ) | answer(yes)) & (people(b:: 0a,c,a)) & (people(a:: 0a,b,a)) & (people(a:: 0a,c,b)) & (people(c:: 0a,b,a)) & (a-truth(says(a:: 0a,equal-type(b:: 0a,c)))) & (ask-1-if-2 (c:: 0a,equal-type(a:: 0a,b))) & (∀ Answer. ∼answer(Answer)) −−> False oops

lemma PUZ029-1 : (∀ X . dances-on-tightropes(X ) | eats-pennybuns(X ) | old(X )) & (∀ X . pig(X )& liable-to-giddiness(X ) −−> treated-with-respect(X )) & (∀ X . wise(X )& balloonist(X ) −−> has-umbrella(X )) & (∀ X . ∼(looks-ridiculous(X )& eats-pennybuns(X )& eats-lunch-in-public(X ))) & (∀ X . balloonist(X )& young(X ) −−> liable-to-giddiness(X )) & (∀ X . fat(X )& looks-ridiculous(X ) −−> dances-on-tightropes(X ) | eats-lunch-in-public(X )) & (∀ X . ∼(liable-to-giddiness(X )& wise(X )& dances-on-tightropes(X ))) & (∀ X . pig(X )& has-umbrella(X ) −−> looks-ridiculous(X )) & (∀ X . treated-with-respect(X ) −−> dances-on-tightropes(X ) | fat(X )) & (∀ X . young(X ) | old(X )) & (∀ X . ∼(young(X )& old(X ))) & (wise(piggy)) & (young(piggy)) & (pig(piggy)) & (balloonist(piggy)) −−> False by meson abbreviation RNG001-0-ax equal additive-inverse add multiply product additive-identity sum ≡ (∀ X . sum(additive-identity:: 0a,X ,X )) & (∀ X . sum(X :: 0a,additive-identity,X )) & (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) &

788 (∀ XY . sum(X :: 0a,Y ,add(X :: 0a,Y ))) & (∀ X . sum(additive-inverse(X ),X ,additive-identity)) & (∀ X . sum(X :: 0a,additive-inverse(X ),additive-identity)) & (∀ YUZXVW . sum(X :: 0a,Y ,U )& sum(Y :: 0a,Z ,V )& sum(U :: 0a,Z ,W ) −−> sum(X :: 0a,V ,W )) & (∀ YXVUZW . sum(X :: 0a,Y ,U )& sum(Y :: 0a,Z ,V )& sum(X :: 0a,V ,W ) −−> sum(U :: 0a,Z ,W )) & (∀ YXZ . sum(X :: 0a,Y ,Z ) −−> sum(Y :: 0a,X ,Z )) & (∀ YUZXVW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(U :: 0a,Z ,W ) −−> product(X :: 0a,V ,W )) & (∀ YXVUZW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(X :: 0a,V ,W ) −−> product(U :: 0a,Z ,W )) & (∀ Y Z X V3 V1 V2 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & product(X :: 0a,V3 ,V4 ) −−> sum(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 X V3 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & sum(V1 :: 0a,V2 ,V4 ) −−> product(X :: 0a,V3 ,V4 )) & (∀ Y Z V3 X V1 V2 V4 . product(Y :: 0a,X ,V1 )& product(Z :: 0a,X ,V2 )& sum(Y :: 0a,Z ,V3 ) & product(V3 :: 0a,X ,V4 ) −−> sum(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 V3 X V4 . product(Y :: 0a,X ,V1 )& product(Z :: 0a,X ,V2 )& sum(Y :: 0a,Z ,V3 ) & sum(V1 :: 0a,V2 ,V4 ) −−> product(V3 :: 0a,X ,V4 )) & (∀ XYUV . sum(X :: 0a,Y ,U )& sum(X :: 0a,Y ,V ) −−> equal(U :: 0a,V )) & (∀ XYUV . product(X :: 0a,Y ,U )& product(X :: 0a,Y ,V ) −−> equal(U :: 0a,V )) abbreviation RNG001-0-eq product multiply sum add additive-inverse equal ≡ (∀ XY . equal(X :: 0a,Y ) −−> equal(additive-inverse(X ),additive-inverse(Y ))) & (∀ XYW . equal(X :: 0a,Y ) −−> equal(add(X :: 0a,W ),add(Y :: 0a,W ))) & (∀ XWY . equal(X :: 0a,Y ) −−> equal(add(W :: 0a,X ),add(W :: 0a,Y ))) & (∀ XYWZ . equal(X :: 0a,Y )& sum(X :: 0a,W ,Z ) −−> sum(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& sum(W :: 0a,X ,Z ) −−> sum(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& sum(W :: 0a,Z ,X ) −−> sum(W :: 0a,Z ,Y )) & (∀ XYW . equal(X :: 0a,Y ) −−> equal(multiply(X :: 0a,W ),multiply(Y :: 0a,W ))) & (∀ XWY . equal(X :: 0a,Y ) −−> equal(multiply(W :: 0a,X ),multiply(W :: 0a,Y ))) & (∀ XYWZ . equal(X :: 0a,Y )& product(X :: 0a,W ,Z ) −−> product(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& product(W :: 0a,X ,Z ) −−> product(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& product(W :: 0a,Z ,X ) −−> product(W :: 0a,Z ,Y )) lemma RNG001-3 : (∀ X . sum(additive-identity:: 0a,X ,X )) & (∀ X . sum(additive-inverse(X ),X ,additive-identity)) & (∀ YUZXVW . sum(X :: 0a,Y ,U )& sum(Y :: 0a,Z ,V )& sum(U :: 0a,Z ,W ) −−> sum(X :: 0a,V ,W )) & (∀ YXVUZW . sum(X :: 0a,Y ,U )& sum(Y :: 0a,Z ,V )& sum(X :: 0a,V ,W ) −−> sum(U :: 0a,Z ,W )) & (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) &

789 (∀ Y Z X V3 V1 V2 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & product(X :: 0a,V3 ,V4 ) −−> sum(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 X V3 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & sum(V1 :: 0a,V2 ,V4 ) −−> product(X :: 0a,V3 ,V4 )) & (∼product(a:: 0a,additive-identity,additive-identity)) −−> False oops abbreviation RNG-other-ax multiply add equal product additive-identity additive-inverse sum ≡ (∀ X . sum(X :: 0a,additive-inverse(X ),additive-identity)) & (∀ YUZXVW . sum(X :: 0a,Y ,U )& sum(Y :: 0a,Z ,V )& sum(U :: 0a,Z ,W ) −−> sum(X :: 0a,V ,W )) & (∀ YXVUZW . sum(X :: 0a,Y ,U )& sum(Y :: 0a,Z ,V )& sum(X :: 0a,V ,W ) −−> sum(U :: 0a,Z ,W )) & (∀ YXZ . sum(X :: 0a,Y ,Z ) −−> sum(Y :: 0a,X ,Z )) & (∀ YUZXVW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(U :: 0a,Z ,W ) −−> product(X :: 0a,V ,W )) & (∀ YXVUZW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(X :: 0a,V ,W ) −−> product(U :: 0a,Z ,W )) & (∀ Y Z X V3 V1 V2 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & product(X :: 0a,V3 ,V4 ) −−> sum(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 X V3 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & sum(V1 :: 0a,V2 ,V4 ) −−> product(X :: 0a,V3 ,V4 )) & (∀ Y Z V3 X V1 V2 V4 . product(Y :: 0a,X ,V1 )& product(Z :: 0a,X ,V2 )& sum(Y :: 0a,Z ,V3 ) & product(V3 :: 0a,X ,V4 ) −−> sum(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 V3 X V4 . product(Y :: 0a,X ,V1 )& product(Z :: 0a,X ,V2 )& sum(Y :: 0a,Z ,V3 ) & sum(V1 :: 0a,V2 ,V4 ) −−> product(V3 :: 0a,X ,V4 )) & (∀ XYUV . sum(X :: 0a,Y ,U )& sum(X :: 0a,Y ,V ) −−> equal(U :: 0a,V )) & (∀ XYUV . product(X :: 0a,Y ,U )& product(X :: 0a,Y ,V ) −−> equal(U :: 0a,V )) & (∀ XY . equal(X :: 0a,Y ) −−> equal(additive-inverse(X ),additive-inverse(Y ))) & (∀ XYW . equal(X :: 0a,Y ) −−> equal(add(X :: 0a,W ),add(Y :: 0a,W ))) & (∀ XYWZ . equal(X :: 0a,Y )& sum(X :: 0a,W ,Z ) −−> sum(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& sum(W :: 0a,X ,Z ) −−> sum(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& sum(W :: 0a,Z ,X ) −−> sum(W :: 0a,Z ,Y )) & (∀ XYW . equal(X :: 0a,Y ) −−> equal(multiply(X :: 0a,W ),multiply(Y :: 0a,W ))) & (∀ XYWZ . equal(X :: 0a,Y )& product(X :: 0a,W ,Z ) −−> product(Y :: 0a,W ,Z )) & (∀ XWYZ . equal(X :: 0a,Y )& product(W :: 0a,X ,Z ) −−> product(W :: 0a,Y ,Z )) & (∀ XWZY . equal(X :: 0a,Y )& product(W :: 0a,Z ,X ) −−> product(W :: 0a,Z ,Y ))

lemma RNG001-5 : EQU001-0-ax equal & (∀ X . sum(additive-identity:: 0a,X ,X )) & (∀ X . sum(X :: 0a,additive-identity,X )) &

790 (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) & (∀ XY . sum(X :: 0a,Y ,add(X :: 0a,Y ))) & (∀ X . sum(additive-inverse(X ),X ,additive-identity)) & RNG-other-ax multiply add equal product additive-identity additive-inverse sum & (∼product(a:: 0a,additive-identity,additive-identity)) −−> False oops lemma RNG011-5 : EQU001-0-ax equal & (∀ ABC . equal(A:: 0a,B) −−> equal(add(A:: 0a,C ),add(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(add(F 0:: 0a,D),add(F 0:: 0a,E))) & (∀ GH . equal(G:: 0a,H ) −−> equal(additive-inverse(G),additive-inverse(H ))) & (∀ I 0 JK 0. equal(I 0:: 0a,J ) −−> equal(multiply(I 0:: 0a,K 0),multiply(J :: 0a,K 0))) & (∀ LNM . equal(L:: 0a,M ) −−> equal(multiply(N :: 0a,L),multiply(N :: 0a,M ))) & (∀ ABCD. equal(A:: 0a,B) −−> equal(associator(A:: 0a,C ,D),associator(B:: 0a,C ,D))) & (∀ EGF 0 H . equal(E:: 0a,F 0) −−> equal(associator(G:: 0a,E,H ),associator(G:: 0a,F 0,H ))) & (∀ I 0 K 0 LJ . equal(I 0:: 0a,J ) −−> equal(associator(K 0:: 0a,L,I 0),associator(K 0:: 0a,L,J ))) & (∀ MNO 0. equal(M :: 0a,N ) −−> equal(commutator(M :: 0a,O 0),commutator(N :: 0a,O 0))) & (∀ PRQ. equal(P:: 0a,Q) −−> equal(commutator(R:: 0a,P),commutator(R:: 0a,Q))) & (∀ YX . equal(add(X :: 0a,Y ),add(Y :: 0a,X ))) & (∀ XYZ . equal(add(add(X :: 0a,Y ),Z ),add(X :: 0a,add(Y :: 0a,Z )))) & (∀ X . equal(add(X :: 0a,additive-identity),X )) & (∀ X . equal(add(additive-identity:: 0a,X ),X )) & (∀ X . equal(add(X :: 0a,additive-inverse(X )),additive-identity)) & (∀ X . equal(add(additive-inverse(X ),X ),additive-identity)) & (equal(additive-inverse(additive-identity),additive-identity)) & (∀ XY . equal(add(X :: 0a,add(additive-inverse(X ),Y )),Y )) & (∀ XY . equal(additive-inverse(add(X :: 0a,Y )),add(additive-inverse(X ),additive-inverse(Y )))) & (∀ X . equal(additive-inverse(additive-inverse(X )),X )) & (∀ X . equal(multiply(X :: 0a,additive-identity),additive-identity)) & (∀ X . equal(multiply(additive-identity:: 0a,X ),additive-identity)) & (∀ XY . equal(multiply(additive-inverse(X ),additive-inverse(Y )),multiply(X :: 0a,Y ))) & (∀ XY . equal(multiply(X :: 0a,additive-inverse(Y )),additive-inverse(multiply(X :: 0a,Y )))) & (∀ XY . equal(multiply(additive-inverse(X ),Y ),additive-inverse(multiply(X :: 0a,Y )))) & (∀ YXZ . equal(multiply(X :: 0a,add(Y :: 0a,Z )),add(multiply(X :: 0a,Y ),multiply(X :: 0a,Z )))) & (∀ XYZ . equal(multiply(add(X :: 0a,Y ),Z ),add(multiply(X :: 0a,Z ),multiply(Y :: 0a,Z )))) &

791 (∀ XY . equal(multiply(multiply(X :: 0a,Y ),Y ),multiply(X :: 0a,multiply(Y :: 0a,Y )))) & (∀ XYZ . equal(associator(X :: 0a,Y ,Z ),add(multiply(multiply(X :: 0a,Y ),Z ),additive-inverse(multiply(X :: 0a,multiply(Y :: 0a,Z )))))) & (∀ XY . equal(commutator(X :: 0a,Y ),add(multiply(Y :: 0a,X ),additive-inverse(multiply(X :: 0a,Y ))))) & (∀ XY . equal(multiply(multiply(associator(X :: 0a,X ,Y ),X ),associator(X :: 0a,X ,Y )),additive-identity)) & (∼equal(multiply(multiply(associator(a:: 0a,a,b),a),associator(a:: 0a,a,b)),additive-identity)) −−> False by meson lemma RNG023-6 : EQU001-0-ax equal & (∀ YX . equal(add(X :: 0a,Y ),add(Y :: 0a,X ))) & (∀ XYZ . equal(add(X :: 0a,add(Y :: 0a,Z )),add(add(X :: 0a,Y ),Z ))) & (∀ X . equal(add(additive-identity:: 0a,X ),X )) & (∀ X . equal(add(X :: 0a,additive-identity),X )) & (∀ X . equal(multiply(additive-identity:: 0a,X ),additive-identity)) & (∀ X . equal(multiply(X :: 0a,additive-identity),additive-identity)) & (∀ X . equal(add(additive-inverse(X ),X ),additive-identity)) & (∀ X . equal(add(X :: 0a,additive-inverse(X )),additive-identity)) & (∀ YXZ . equal(multiply(X :: 0a,add(Y :: 0a,Z )),add(multiply(X :: 0a,Y ),multiply(X :: 0a,Z )))) & (∀ XYZ . equal(multiply(add(X :: 0a,Y ),Z ),add(multiply(X :: 0a,Z ),multiply(Y :: 0a,Z )))) & (∀ X . equal(additive-inverse(additive-inverse(X )),X )) & (∀ XY . equal(multiply(multiply(X :: 0a,Y ),Y ),multiply(X :: 0a,multiply(Y :: 0a,Y )))) & (∀ XY . equal(multiply(multiply(X :: 0a,X ),Y ),multiply(X :: 0a,multiply(X :: 0a,Y )))) & (∀ XYZ . equal(associator(X :: 0a,Y ,Z ),add(multiply(multiply(X :: 0a,Y ),Z ),additive-inverse(multiply(X :: 0a,multiply(Y :: 0a,Z )))))) & (∀ XY . equal(commutator(X :: 0a,Y ),add(multiply(Y :: 0a,X ),additive-inverse(multiply(X :: 0a,Y ))))) & (∀ DEF 0. equal(D:: 0a,E) −−> equal(add(D:: 0a,F 0),add(E:: 0a,F 0))) & (∀ GI 0 H . equal(G:: 0a,H ) −−> equal(add(I 0:: 0a,G),add(I 0:: 0a,H ))) & (∀ JK 0. equal(J :: 0a,K 0) −−> equal(additive-inverse(J ),additive-inverse(K 0))) & (∀ LMNO 0. equal(L:: 0a,M ) −−> equal(associator(L:: 0a,N ,O 0),associator(M :: 0a,N ,O 0))) & (∀ PRQS 0. equal(P:: 0a,Q) −−> equal(associator(R:: 0a,P,S 0),associator(R:: 0a,Q,S 0))) & (∀ T 0 VWU . equal(T 0:: 0a,U ) −−> equal(associator(V :: 0a,W ,T 0),associator(V :: 0a,W ,U ))) & (∀ XYZ . equal(X :: 0a,Y ) −−> equal(commutator(X :: 0a,Z ),commutator(Y :: 0a,Z ))) & (∀ A1 C1 B1 . equal(A1 :: 0a,B1 ) −−> equal(commutator(C1 :: 0a,A1 ),commutator(C1 :: 0a,B1 ))) &

792 (∀ D1 E1 F1 . equal(D1 :: 0a,E1 ) −−> equal(multiply(D1 :: 0a,F1 ),multiply(E1 :: 0a,F1 ))) & (∀ G1 I1 H1 . equal(G1 :: 0a,H1 ) −−> equal(multiply(I1 :: 0a,G1 ),multiply(I1 :: 0a,H1 ))) & (∼equal(associator(x:: 0a,x,y),additive-identity)) −−> False by meson lemma RNG028-2 : EQU001-0-ax equal & (∀ X . equal(add(additive-identity:: 0a,X ),X )) & (∀ X . equal(multiply(additive-identity:: 0a,X ),additive-identity)) & (∀ X . equal(multiply(X :: 0a,additive-identity),additive-identity)) & (∀ X . equal(add(additive-inverse(X ),X ),additive-identity)) & (∀ XY . equal(additive-inverse(add(X :: 0a,Y )),add(additive-inverse(X ),additive-inverse(Y )))) & (∀ X . equal(additive-inverse(additive-inverse(X )),X )) & (∀ YXZ . equal(multiply(X :: 0a,add(Y :: 0a,Z )),add(multiply(X :: 0a,Y ),multiply(X :: 0a,Z )))) & (∀ XYZ . equal(multiply(add(X :: 0a,Y ),Z ),add(multiply(X :: 0a,Z ),multiply(Y :: 0a,Z )))) & (∀ XY . equal(multiply(multiply(X :: 0a,Y ),Y ),multiply(X :: 0a,multiply(Y :: 0a,Y )))) & (∀ XY . equal(multiply(multiply(X :: 0a,X ),Y ),multiply(X :: 0a,multiply(X :: 0a,Y )))) & (∀ XY . equal(multiply(additive-inverse(X ),Y ),additive-inverse(multiply(X :: 0a,Y )))) & (∀ XY . equal(multiply(X :: 0a,additive-inverse(Y )),additive-inverse(multiply(X :: 0a,Y )))) & (equal(additive-inverse(additive-identity),additive-identity)) & (∀ YX . equal(add(X :: 0a,Y ),add(Y :: 0a,X ))) & (∀ XYZ . equal(add(X :: 0a,add(Y :: 0a,Z )),add(add(X :: 0a,Y ),Z ))) & (∀ ZXY . equal(add(X :: 0a,Z ),add(Y :: 0a,Z )) −−> equal(X :: 0a,Y )) & (∀ ZXY . equal(add(Z :: 0a,X ),add(Z :: 0a,Y )) −−> equal(X :: 0a,Y )) & (∀ DEF 0. equal(D:: 0a,E) −−> equal(add(D:: 0a,F 0),add(E:: 0a,F 0))) & (∀ GI 0 H . equal(G:: 0a,H ) −−> equal(add(I 0:: 0a,G),add(I 0:: 0a,H ))) & (∀ JK 0. equal(J :: 0a,K 0) −−> equal(additive-inverse(J ),additive-inverse(K 0))) & (∀ D1 E1 F1 . equal(D1 :: 0a,E1 ) −−> equal(multiply(D1 :: 0a,F1 ),multiply(E1 :: 0a,F1 ))) & (∀ G1 I1 H1 . equal(G1 :: 0a,H1 ) −−> equal(multiply(I1 :: 0a,G1 ),multiply(I1 :: 0a,H1 ))) & (∀ XYZ . equal(associator(X :: 0a,Y ,Z ),add(multiply(multiply(X :: 0a,Y ),Z ),additive-inverse(multiply(X :: 0a,multiply(Y :: 0a,Z )))))) & (∀ LMNO 0. equal(L:: 0a,M ) −−> equal(associator(L:: 0a,N ,O 0),associator(M :: 0a,N ,O 0))) & (∀ PRQS 0. equal(P:: 0a,Q) −−> equal(associator(R:: 0a,P,S 0),associator(R:: 0a,Q,S 0))) & (∀ T 0 VWU . equal(T 0:: 0a,U ) −−> equal(associator(V :: 0a,W ,T 0),associator(V :: 0a,W ,U ))) &

793 (∀ XY . ∼equal(multiply(multiply(Y :: 0a,X ),Y ),multiply(Y :: 0a,multiply(X :: 0a,Y )))) & (∀ XYZ . ∼equal(associator(Y :: 0a,X ,Z ),additive-inverse(associator(X :: 0a,Y ,Z )))) & (∀ XYZ . ∼equal(associator(Z :: 0a,Y ,X ),additive-inverse(associator(X :: 0a,Y ,Z )))) & (∼equal(multiply(multiply(cx:: 0a,multiply(cy:: 0a,cx)),cz),multiply(cx:: 0a,multiply(cy:: 0a,multiply(cx:: 0a,cz))))) −−> False by meson lemma RNG038-2 : (∀ X . sum(X :: 0a,additive-identity,X )) & (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) & (∀ XY . sum(X :: 0a,Y ,add(X :: 0a,Y ))) & RNG-other-ax multiply add equal product additive-identity additive-inverse sum & (∀ X . product(additive-identity:: 0a,X ,additive-identity)) & (∀ X . product(X :: 0a,additive-identity,additive-identity)) & (∀ XY . equal(X :: 0a,additive-identity) −−> product(X :: 0a,h(X :: 0a,Y ),Y )) & (product(a:: 0a,b,additive-identity)) & (∼equal(a:: 0a,additive-identity)) & (∼equal(b:: 0a,additive-identity)) −−> False by meson lemma RNG040-2 : EQU001-0-ax equal & RNG001-0-eq product multiply sum add additive-inverse equal & (∀ X . sum(additive-identity:: 0a,X ,X )) & (∀ X . sum(X :: 0a,additive-identity,X )) & (∀ XY . product(X :: 0a,Y ,multiply(X :: 0a,Y ))) & (∀ XY . sum(X :: 0a,Y ,add(X :: 0a,Y ))) & (∀ X . sum(additive-inverse(X ),X ,additive-identity)) & (∀ X . sum(X :: 0a,additive-inverse(X ),additive-identity)) & (∀ YUZXVW . sum(X :: 0a,Y ,U )& sum(Y :: 0a,Z ,V )& sum(U :: 0a,Z ,W ) −−> sum(X :: 0a,V ,W )) & (∀ YXVUZW . sum(X :: 0a,Y ,U )& sum(Y :: 0a,Z ,V )& sum(X :: 0a,V ,W ) −−> sum(U :: 0a,Z ,W )) & (∀ YXZ . sum(X :: 0a,Y ,Z ) −−> sum(Y :: 0a,X ,Z )) & (∀ YUZXVW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(U :: 0a,Z ,W ) −−> product(X :: 0a,V ,W )) & (∀ YXVUZW . product(X :: 0a,Y ,U )& product(Y :: 0a,Z ,V )& product(X :: 0a,V ,W ) −−> product(U :: 0a,Z ,W )) & (∀ Y Z X V3 V1 V2 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & product(X :: 0a,V3 ,V4 ) −−> sum(V1 :: 0a,V2 ,V4 )) & (∀ Y Z V1 V2 X V3 V4 . product(X :: 0a,Y ,V1 )& product(X :: 0a,Z ,V2 )& sum(Y :: 0a,Z ,V3 ) & sum(V1 :: 0a,V2 ,V4 ) −−> product(X :: 0a,V3 ,V4 )) & (∀ XYUV . sum(X :: 0a,Y ,U )& sum(X :: 0a,Y ,V ) −−> equal(U :: 0a,V )) &

794 (∀ XYUV . product(X :: 0a,Y ,U )& product(X :: 0a,Y ,V ) −−> equal(U :: 0a,V )) & (∀ A. product(A:: 0a,multiplicative-identity,A)) & (∀ A. product(multiplicative-identity:: 0a,A,A)) & (∀ A. product(A:: 0a,h(A),multiplicative-identity) | equal(A:: 0a,additive-identity)) & (∀ A. product(h(A),A,multiplicative-identity) | equal(A:: 0a,additive-identity)) & (∀ BAC . product(A:: 0a,B,C ) −−> product(B:: 0a,A,C )) & (∀ AB. equal(A:: 0a,B) −−> equal(h(A),h(B))) & (sum(b:: 0a,c,d)) & (product(d:: 0a,a,additive-identity)) & (product(b:: 0a,a,l)) & (product(c:: 0a,a,n)) & (∼sum(l:: 0a,n,additive-identity)) −−> False by meson lemma RNG041-1 : EQU001-0-ax equal & RNG001-0-ax equal additive-inverse add multiply product additive-identity sum & RNG001-0-eq product multiply sum add additive-inverse equal & (∀ AB. equal(A:: 0a,B) −−> equal(h(A),h(B))) & (∀ A. product(additive-identity:: 0a,A,additive-identity)) & (∀ A. product(A:: 0a,additive-identity,additive-identity)) & (∀ A. product(A:: 0a,multiplicative-identity,A)) & (∀ A. product(multiplicative-identity:: 0a,A,A)) & (∀ A. product(A:: 0a,h(A),multiplicative-identity) | equal(A:: 0a,additive-identity)) & (∀ A. product(h(A),A,multiplicative-identity) | equal(A:: 0a,additive-identity)) & (product(a:: 0a,b,additive-identity)) & (∼equal(a:: 0a,additive-identity)) & (∼equal(b:: 0a,additive-identity)) −−> False oops lemma ROB010-1 : EQU001-0-ax equal & (∀ YX . equal(add(X :: 0a,Y ),add(Y :: 0a,X ))) & (∀ XYZ . equal(add(add(X :: 0a,Y ),Z ),add(X :: 0a,add(Y :: 0a,Z )))) & (∀ YX . equal(negate(add(negate(add(X :: 0a,Y )),negate(add(X :: 0a,negate(Y ))))),X )) & (∀ ABC . equal(A:: 0a,B) −−> equal(add(A:: 0a,C ),add(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(add(F 0:: 0a,D),add(F 0:: 0a,E))) & (∀ GH . equal(G:: 0a,H ) −−> equal(negate(G),negate(H ))) & (equal(negate(add(a:: 0a,negate(b))),c)) & (∼equal(negate(add(c:: 0a,negate(add(b:: 0a,a)))),a)) −−> False oops

795 lemma ROB013-1 : EQU001-0-ax equal & (∀ YX . equal(add(X :: 0a,Y ),add(Y :: 0a,X ))) & (∀ XYZ . equal(add(add(X :: 0a,Y ),Z ),add(X :: 0a,add(Y :: 0a,Z )))) & (∀ YX . equal(negate(add(negate(add(X :: 0a,Y )),negate(add(X :: 0a,negate(Y ))))),X )) & (∀ ABC . equal(A:: 0a,B) −−> equal(add(A:: 0a,C ),add(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(add(F 0:: 0a,D),add(F 0:: 0a,E))) & (∀ GH . equal(G:: 0a,H ) −−> equal(negate(G),negate(H ))) & (equal(negate(add(a:: 0a,b)),c)) & (∼equal(negate(add(c:: 0a,negate(add(negate(b),a)))),a)) −−> False by meson lemma ROB016-1 : EQU001-0-ax equal & (∀ YX . equal(add(X :: 0a,Y ),add(Y :: 0a,X ))) & (∀ XYZ . equal(add(add(X :: 0a,Y ),Z ),add(X :: 0a,add(Y :: 0a,Z )))) & (∀ YX . equal(negate(add(negate(add(X :: 0a,Y )),negate(add(X :: 0a,negate(Y ))))),X )) & (∀ ABC . equal(A:: 0a,B) −−> equal(add(A:: 0a,C ),add(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(add(F 0:: 0a,D),add(F 0:: 0a,E))) & (∀ GH . equal(G:: 0a,H ) −−> equal(negate(G),negate(H ))) & (∀ JK 0 L. equal(J :: 0a,K 0) −−> equal(multiply(J :: 0a,L),multiply(K 0:: 0a,L))) & (∀ MO 0 N . equal(M :: 0a,N ) −−> equal(multiply(O 0:: 0a,M ),multiply(O 0:: 0a,N ))) & (∀ PQ. equal(P:: 0a,Q) −−> equal(successor(P),successor(Q))) & (∀ RS 0. equal(R:: 0a,S 0)& positive-integer(R) −−> positive-integer(S 0)) & (∀ X . equal(multiply(One:: 0a,X ),X )) & (∀ VX . positive-integer(X ) −−> equal(multiply(successor(V ),X ),add(X :: 0a,multiply(V :: 0a,X )))) & (positive-integer(One)) & (∀ X . positive-integer(X ) −−> positive-integer(successor(X ))) & (equal(negate(add(d:: 0a,e)),negate(e))) & (positive-integer(k)) & (∀ Vk X Y . equal(negate(add(negate(Y ),negate(add(X :: 0a,negate(Y ))))),X )& positive-integer(Vk) −−> equal(negate(add(Y :: 0a,multiply(Vk:: 0a,add(X :: 0a,negate(add(X :: 0a,negate(Y ))))))),negate(Y ))) & (∼equal(negate(add(e:: 0a,multiply(k:: 0a,add(d:: 0a,negate(add(d:: 0a,negate(e))))))),negate(e))) −−> False oops lemma ROB021-1 : EQU001-0-ax equal & (∀ YX . equal(add(X :: 0a,Y ),add(Y :: 0a,X ))) & (∀ XYZ . equal(add(add(X :: 0a,Y ),Z ),add(X :: 0a,add(Y :: 0a,Z )))) & (∀ YX . equal(negate(add(negate(add(X :: 0a,Y )),negate(add(X :: 0a,negate(Y ))))),X ))

796 & (∀ ABC . equal(A:: 0a,B) −−> equal(add(A:: 0a,C ),add(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(add(F 0:: 0a,D),add(F 0:: 0a,E))) & (∀ GH . equal(G:: 0a,H ) −−> equal(negate(G),negate(H ))) & (∀ XY . equal(negate(X ),negate(Y )) −−> equal(X :: 0a,Y )) & (∼equal(add(negate(add(a:: 0a,negate(b))),negate(add(negate(a),negate(b)))),b)) −−> False oops lemma SET005-1 : (∀ Subset Element Superset. member(Element:: 0a,Subset)& subset(Subset:: 0a,Superset) −−> member(Element:: 0a,Superset)) & (∀ Superset Subset. subset(Subset:: 0a,Superset) | member(member-of-1-not-of-2 (Subset:: 0a,Superset),Subset)) & (∀ Subset Superset. member(member-of-1-not-of-2 (Subset:: 0a,Superset),Superset) −−> subset(Subset:: 0a,Superset)) & (∀ Subset Superset. equal-sets(Subset:: 0a,Superset) −−> subset(Subset:: 0a,Superset)) & (∀ Subset Superset. equal-sets(Superset:: 0a,Subset) −−> subset(Subset:: 0a,Superset)) & (∀ Set2 Set1 . subset(Set1 :: 0a,Set2 )& subset(Set2 :: 0a,Set1 ) −−> equal-sets(Set2 :: 0a,Set1 )) & (∀ Set2 Intersection Element Set1 . intersection(Set1 :: 0a,Set2 ,Intersection)& mem- ber(Element:: 0a,Intersection) −−> member(Element:: 0a,Set1 )) & (∀ Set1 Intersection Element Set2 . intersection(Set1 :: 0a,Set2 ,Intersection)& mem- ber(Element:: 0a,Intersection) −−> member(Element:: 0a,Set2 )) & (∀ Set2 Set1 Element Intersection. intersection(Set1 :: 0a,Set2 ,Intersection)& mem- ber(Element:: 0a,Set2 )& member(Element:: 0a,Set1 ) −−> member(Element:: 0a,Intersection)) & (∀ Set2 Intersection Set1 . member(h(Set1 :: 0a,Set2 ,Intersection),Intersection) | intersection(Set1 :: 0a,Set2 ,Intersection) | member(h(Set1 :: 0a,Set2 ,Intersection),Set1 )) & (∀ Set1 Intersection Set2 . member(h(Set1 :: 0a,Set2 ,Intersection),Intersection) | intersection(Set1 :: 0a,Set2 ,Intersection) | member(h(Set1 :: 0a,Set2 ,Intersection),Set2 )) & (∀ Set1 Set2 Intersection. member(h(Set1 :: 0a,Set2 ,Intersection),Intersection)& member(h(Set1 :: 0a,Set2 ,Intersection),Set2 )& member(h(Set1 :: 0a,Set2 ,Intersection),Set1 ) −−> intersection(Set1 :: 0a,Set2 ,Intersection)) & (intersection(a:: 0a,b,aIb)) & (intersection(b:: 0a,c,bIc)) & (intersection(a:: 0a,bIc,aIbIc)) & (∼intersection(aIb:: 0a,c,aIbIc)) −−> False oops

lemma SET009-1 : (∀ Subset Element Superset. member(Element:: 0a,Subset)& ssubset(Subset:: 0a,Superset)

797 −−> member(Element:: 0a,Superset)) & (∀ Superset Subset. ssubset(Subset:: 0a,Superset) | member(member-of-1-not-of-2 (Subset:: 0a,Superset),Subset)) & (∀ Subset Superset. member(member-of-1-not-of-2 (Subset:: 0a,Superset),Superset) −−> ssubset(Subset:: 0a,Superset)) & (∀ Subset Superset. equal-sets(Subset:: 0a,Superset) −−> ssubset(Subset:: 0a,Superset)) & (∀ Subset Superset. equal-sets(Superset:: 0a,Subset) −−> ssubset(Subset:: 0a,Superset)) & (∀ Set2 Set1 . ssubset(Set1 :: 0a,Set2 )& ssubset(Set2 :: 0a,Set1 ) −−> equal-sets(Set2 :: 0a,Set1 )) & (∀ Set2 Difference Element Set1 . difference(Set1 :: 0a,Set2 ,Difference)& mem- ber(Element:: 0a,Difference) −−> member(Element:: 0a,Set1 )) & (∀ Element A-set Set1 Set2 . ∼(member(Element:: 0a,Set1 )& member(Element:: 0a,Set2 ) & difference(A-set:: 0a,Set1 ,Set2 ))) & (∀ Set1 Difference Element Set2 . member(Element:: 0a,Set1 )& difference(Set1 :: 0a,Set2 ,Difference) −−> member(Element:: 0a,Difference) | member(Element:: 0a,Set2 )) & (∀ Set1 Set2 Difference. difference(Set1 :: 0a,Set2 ,Difference) | member(k(Set1 :: 0a,Set2 ,Difference),Set1 ) | member(k(Set1 :: 0a,Set2 ,Difference),Difference)) & (∀ Set1 Set2 Difference. member(k(Set1 :: 0a,Set2 ,Difference),Set2 ) −−> mem- ber(k(Set1 :: 0a,Set2 ,Difference),Difference) | difference(Set1 :: 0a,Set2 ,Difference)) & (∀ Set1 Set2 Difference. member(k(Set1 :: 0a,Set2 ,Difference),Difference)& mem- ber(k(Set1 :: 0a,Set2 ,Difference),Set1 ) −−> member(k(Set1 :: 0a,Set2 ,Difference),Set2 ) | difference(Set1 :: 0a,Set2 ,Difference)) & (ssubset(d:: 0a,a)) & (difference(b:: 0a,a,bDa)) & (difference(b:: 0a,d,bDd)) & (∼ssubset(bDa:: 0a,bDd)) −−> False by meson lemma SET025-4 : EQU001-0-ax equal & (∀ YX . member(X :: 0a,Y ) −−> little-set(X )) & (∀ XY . little-set(f1 (X :: 0a,Y )) | equal(X :: 0a,Y )) & (∀ XY . member(f1 (X :: 0a,Y ),X ) | member(f1 (X :: 0a,Y ),Y ) | equal(X :: 0a,Y )) & (∀ XY . member(f1 (X :: 0a,Y ),X )& member(f1 (X :: 0a,Y ),Y ) −−> equal(X :: 0a,Y )) & (∀ XUY . member(U :: 0a,non-ordered-pair(X :: 0a,Y )) −−> equal(U :: 0a,X ) | equal(U :: 0a,Y )) & (∀ YUX . little-set(U )& equal(U :: 0a,X ) −−> member(U :: 0a,non-ordered-pair(X :: 0a,Y ))) & (∀ XUY . little-set(U )& equal(U :: 0a,Y ) −−> member(U :: 0a,non-ordered-pair(X :: 0a,Y ))) & (∀ XY . little-set(non-ordered-pair(X :: 0a,Y ))) & (∀ X . equal(singleton-set(X ),non-ordered-pair(X :: 0a,X ))) & (∀ XY . equal(ordered-pair(X :: 0a,Y ),non-ordered-pair(singleton-set(X ),non-ordered-pair(X :: 0a,Y )))) & (∀ X . ordered-pair-predicate(X ) −−> little-set(f2 (X ))) &

798 (∀ X . ordered-pair-predicate(X ) −−> little-set(f3 (X ))) & (∀ X . ordered-pair-predicate(X ) −−> equal(X :: 0a,ordered-pair(f2 (X ),f3 (X )))) & (∀ XYZ . little-set(Y )& little-set(Z )& equal(X :: 0a,ordered-pair(Y :: 0a,Z )) −−> ordered-pair-predicate(X )) & (∀ ZX . member(Z :: 0a,first(X )) −−> little-set(f4 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,first(X )) −−> little-set(f5 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,first(X )) −−> equal(X :: 0a,ordered-pair(f4 (Z :: 0a,X ),f5 (Z :: 0a,X )))) & (∀ ZX . member(Z :: 0a,first(X )) −−> member(Z :: 0a,f4 (Z :: 0a,X ))) & (∀ XVZU . little-set(U )& little-set(V )& equal(X :: 0a,ordered-pair(U :: 0a,V )) & member(Z :: 0a,U ) −−> member(Z :: 0a,first(X ))) & (∀ ZX . member(Z :: 0a,second(X )) −−> little-set(f6 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,second(X )) −−> little-set(f7 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,second(X )) −−> equal(X :: 0a,ordered-pair(f6 (Z :: 0a,X ),f7 (Z :: 0a,X )))) & (∀ ZX . member(Z :: 0a,second(X )) −−> member(Z :: 0a,f7 (Z :: 0a,X ))) & (∀ XUZV . little-set(U )& little-set(V )& equal(X :: 0a,ordered-pair(U :: 0a,V )) & member(Z :: 0a,V ) −−> member(Z :: 0a,second(X ))) & (∀ Z . member(Z :: 0a,estin) −−> ordered-pair-predicate(Z )) & (∀ Z . member(Z :: 0a,estin) −−> member(first(Z ),second(Z ))) & (∀ Z . little-set(Z )& ordered-pair-predicate(Z )& member(first(Z ),second(Z )) −−> member(Z :: 0a,estin)) & (∀ YZX . member(Z :: 0a,intersection(X :: 0a,Y )) −−> member(Z :: 0a,X )) & (∀ XZY . member(Z :: 0a,intersection(X :: 0a,Y )) −−> member(Z :: 0a,Y )) & (∀ XZY . member(Z :: 0a,X )& member(Z :: 0a,Y ) −−> member(Z :: 0a,intersection(X :: 0a,Y ))) & (∀ ZX . ∼(member(Z :: 0a,complement(X )) & member(Z :: 0a,X ))) & (∀ ZX . little-set(Z ) −−> member(Z :: 0a,complement(X )) | member(Z :: 0a,X )) & (∀ XY . equal(union(X :: 0a,Y ),complement(intersection(complement(X ),complement(Y ))))) & (∀ ZX . member(Z :: 0a,domain-of (X )) −−> ordered-pair-predicate(f8 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,domain-of (X )) −−> member(f8 (Z :: 0a,X ),X )) & (∀ ZX . member(Z :: 0a,domain-of (X )) −−> equal(Z :: 0a,first(f8 (Z :: 0a,X )))) & (∀ X Z Xp. little-set(Z )& ordered-pair-predicate(Xp)& member(Xp:: 0a,X )& equal(Z :: 0a,first(Xp)) −−> member(Z :: 0a,domain-of (X ))) & (∀ XYZ . member(Z :: 0a,cross-product(X :: 0a,Y )) −−> ordered-pair-predicate(Z )) & (∀ YZX . member(Z :: 0a,cross-product(X :: 0a,Y )) −−> member(first(Z ),X )) & (∀ XZY . member(Z :: 0a,cross-product(X :: 0a,Y )) −−> member(second(Z ),Y )) & (∀ XZY . little-set(Z )& ordered-pair-predicate(Z )& member(first(Z ),X )& member(second(Z ),Y ) −−> member(Z :: 0a,cross-product(X :: 0a,Y ))) & (∀ XZ . member(Z :: 0a,inv1 X ) −−> ordered-pair-predicate(Z )) & (∀ ZX . member(Z :: 0a,inv1 X ) −−> member(ordered-pair(second(Z ),first(Z )),X )) & (∀ ZX . little-set(Z )& ordered-pair-predicate(Z )& member(ordered-pair(second(Z ),first(Z )),X ) −−> member(Z :: 0a,inv1 X )) & (∀ ZX . member(Z :: 0a,rot-right(X )) −−> little-set(f9 (Z :: 0a,X ))) &

799 (∀ ZX . member(Z :: 0a,rot-right(X )) −−> little-set(f10 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,rot-right(X )) −−> little-set(f11 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,rot-right(X )) −−> equal(Z :: 0a,ordered-pair(f9 (Z :: 0a,X ),ordered-pair(f10 (Z :: 0a,X ),f11 (Z :: 0a,X ))))) & (∀ ZX . member(Z :: 0a,rot-right(X )) −−> member(ordered-pair(f10 (Z :: 0a,X ),ordered-pair(f11 (Z :: 0a,X ),f9 (Z :: 0a,X ))),X )) & (∀ ZVWUX . little-set(Z )& little-set(U )& little-set(V )& little-set(W )& equal(Z :: 0a,ordered-pair(U :: 0a,ordered-pair(V :: 0a,W ))) & member(ordered-pair(V :: 0a,ordered-pair(W :: 0a,U )),X ) −−> member(Z :: 0a,rot-right(X ))) & (∀ ZX . member(Z :: 0a,flip-range-of (X )) −−> little-set(f12 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,flip-range-of (X )) −−> little-set(f13 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,flip-range-of (X )) −−> little-set(f14 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,flip-range-of (X )) −−> equal(Z :: 0a,ordered-pair(f12 (Z :: 0a,X ),ordered-pair(f13 (Z :: 0a,X ),f14 (Z :: 0a,X ))))) & (∀ ZX . member(Z :: 0a,flip-range-of (X )) −−> member(ordered-pair(f12 (Z :: 0a,X ),ordered-pair(f14 (Z :: 0a,X ),f13 (Z :: 0a,X ))),X )) & (∀ ZUWVX . little-set(Z )& little-set(U )& little-set(V )& little-set(W )& equal(Z :: 0a,ordered-pair(U :: 0a,ordered-pair(V :: 0a,W ))) & member(ordered-pair(U :: 0a,ordered-pair(W :: 0a,V )),X ) −−> member(Z :: 0a,flip-range-of (X ))) & (∀ X . equal(successor(X ),union(X :: 0a,singleton-set(X )))) & (∀ Z . ∼member(Z :: 0a,empty-set)) & (∀ Z . little-set(Z ) −−> member(Z :: 0a,universal-set)) & (little-set(infinity)) & (member(empty-set:: 0a,infinity)) & (∀ X . member(X :: 0a,infinity) −−> member(successor(X ),infinity)) & (∀ ZX . member(Z :: 0a,sigma(X )) −−> member(f16 (Z :: 0a,X ),X )) & (∀ ZX . member(Z :: 0a,sigma(X )) −−> member(Z :: 0a,f16 (Z :: 0a,X ))) & (∀ XZY . member(Y :: 0a,X )& member(Z :: 0a,Y ) −−> member(Z :: 0a,sigma(X ))) & (∀ U . little-set(U ) −−> little-set(sigma(U ))) & (∀ XUY . ssubset(X :: 0a,Y )& member(U :: 0a,X ) −−> member(U :: 0a,Y )) & (∀ YX . ssubset(X :: 0a,Y ) | member(f17 (X :: 0a,Y ),X )) & (∀ XY . member(f17 (X :: 0a,Y ),Y ) −−> ssubset(X :: 0a,Y )) & (∀ XY . proper-subset(X :: 0a,Y ) −−> ssubset(X :: 0a,Y )) & (∀ XY . ∼(proper-subset(X :: 0a,Y )& equal(X :: 0a,Y ))) & (∀ XY . ssubset(X :: 0a,Y ) −−> proper-subset(X :: 0a,Y ) | equal(X :: 0a,Y )) & (∀ ZX . member(Z :: 0a,powerset(X )) −−> ssubset(Z :: 0a,X )) & (∀ ZX . little-set(Z )& ssubset(Z :: 0a,X ) −−> member(Z :: 0a,powerset(X ))) & (∀ U . little-set(U ) −−> little-set(powerset(U ))) & (∀ ZX . relation(Z )& member(X :: 0a,Z ) −−> ordered-pair-predicate(X )) & (∀ Z . relation(Z ) | member(f18 (Z ),Z )) & (∀ Z . ordered-pair-predicate(f18 (Z )) −−> relation(Z )) & (∀ UXVW . single-valued-set(X )& little-set(U )& little-set(V )& little-set(W ) & member(ordered-pair(U :: 0a,V ),X )& member(ordered-pair(U :: 0a,W ),X ) −−> equal(V :: 0a,W )) & (∀ X . single-valued-set(X ) | little-set(f19 (X ))) & (∀ X . single-valued-set(X ) | little-set(f20 (X ))) & (∀ X . single-valued-set(X ) | little-set(f21 (X ))) & (∀ X . single-valued-set(X ) | member(ordered-pair(f19 (X ),f20 (X )),X )) &

800 (∀ X . single-valued-set(X ) | member(ordered-pair(f19 (X ),f21 (X )),X )) & (∀ X . equal(f20 (X ),f21 (X )) −−> single-valued-set(X )) & (∀ Xf . function(Xf ) −−> relation(Xf )) & (∀ Xf . function(Xf ) −−> single-valued-set(Xf )) & (∀ Xf . relation(Xf )& single-valued-set(Xf ) −−> function(Xf )) & (∀ Z X Xf . member(Z :: 0a,image 0(X :: 0a,Xf )) −−> ordered-pair-predicate(f22 (Z :: 0a,X ,Xf ))) & (∀ Z X Xf . member(Z :: 0a,image 0(X :: 0a,Xf )) −−> member(f22 (Z :: 0a,X ,Xf ),Xf )) & (∀ Z Xf X . member(Z :: 0a,image 0(X :: 0a,Xf )) −−> member(first(f22 (Z :: 0a,X ,Xf )),X )) & (∀ X Xf Z . member(Z :: 0a,image 0(X :: 0a,Xf )) −−> equal(second(f22 (Z :: 0a,X ,Xf )),Z )) & (∀ Xf X Y Z . little-set(Z )& ordered-pair-predicate(Y )& member(Y :: 0a,Xf )& member(first(Y ),X )& equal(second(Y ),Z ) −−> member(Z :: 0a,image 0(X :: 0a,Xf ))) & (∀ X Xf . little-set(X )& function(Xf ) −−> little-set(image 0(X :: 0a,Xf ))) & (∀ XUY . ∼(disjoint(X :: 0a,Y )& member(U :: 0a,X )& member(U :: 0a,Y ))) & (∀ YX . disjoint(X :: 0a,Y ) | member(f23 (X :: 0a,Y ),X )) & (∀ XY . disjoint(X :: 0a,Y ) | member(f23 (X :: 0a,Y ),Y )) & (∀ X . equal(X :: 0a,empty-set) | member(f24 (X ),X )) & (∀ X . equal(X :: 0a,empty-set) | disjoint(f24 (X ),X )) & (function(f25 )) & (∀ X . little-set(X ) −−> equal(X :: 0a,empty-set) | member(f26 (X ),X )) & (∀ X . little-set(X ) −−> equal(X :: 0a,empty-set) | member(ordered-pair(X :: 0a,f26 (X )),f25 )) & (∀ ZX . member(Z :: 0a,range-of (X )) −−> ordered-pair-predicate(f27 (Z :: 0a,X ))) & (∀ ZX . member(Z :: 0a,range-of (X )) −−> member(f27 (Z :: 0a,X ),X )) & (∀ ZX . member(Z :: 0a,range-of (X )) −−> equal(Z :: 0a,second(f27 (Z :: 0a,X )))) & (∀ X Z Xp. little-set(Z )& ordered-pair-predicate(Xp)& member(Xp:: 0a,X )& equal(Z :: 0a,second(Xp)) −−> member(Z :: 0a,range-of (X ))) & (∀ Z . member(Z :: 0a,identity-relation) −−> ordered-pair-predicate(Z )) & (∀ Z . member(Z :: 0a,identity-relation) −−> equal(first(Z ),second(Z ))) & (∀ Z . little-set(Z )& ordered-pair-predicate(Z )& equal(first(Z ),second(Z )) −−> member(Z :: 0a,identity-relation)) & (∀ XY . equal(restrct(X :: 0a,Y ),intersection(X :: 0a,cross-product(Y :: 0a,universal-set)))) & (∀ Xf . one-to-one-function(Xf ) −−> function(Xf )) & (∀ Xf . one-to-one-function(Xf ) −−> function(inv1 Xf )) & (∀ Xf . function(Xf )& function(inv1 Xf ) −−> one-to-one-function(Xf )) & (∀ Z Xf Y . member(Z :: 0a,apply(Xf :: 0a,Y )) −−> ordered-pair-predicate(f28 (Z :: 0a,Xf ,Y ))) & (∀ Z Y Xf . member(Z :: 0a,apply(Xf :: 0a,Y )) −−> member(f28 (Z :: 0a,Xf ,Y ),Xf )) & (∀ Z Xf Y . member(Z :: 0a,apply(Xf :: 0a,Y )) −−> equal(first(f28 (Z :: 0a,Xf ,Y )),Y )) & (∀ Z Xf Y . member(Z :: 0a,apply(Xf :: 0a,Y )) −−> member(Z :: 0a,second(f28 (Z :: 0a,Xf ,Y )))) &

801 (∀ Xf Y Z W . ordered-pair-predicate(W )& member(W :: 0a,Xf )& equal(first(W ),Y ) & member(Z :: 0a,second(W )) −−> member(Z :: 0a,apply(Xf :: 0a,Y ))) & (∀ Xf X Y . equal(apply-to-two-arguments(Xf :: 0a,X ,Y ),apply(Xf :: 0a,ordered-pair(X :: 0a,Y )))) & (∀ X Y Xf . maps(Xf :: 0a,X ,Y ) −−> function(Xf )) & (∀ Y Xf X . maps(Xf :: 0a,X ,Y ) −−> equal(domain-of (Xf ),X )) & (∀ X Xf Y . maps(Xf :: 0a,X ,Y ) −−> ssubset(range-of (Xf ),Y )) & (∀ X Xf Y . function(Xf )& equal(domain-of (Xf ),X )& ssubset(range-of (Xf ),Y ) −−> maps(Xf :: 0a,X ,Y )) & (∀ Xf Xs. closed(Xs:: 0a,Xf ) −−> little-set(Xs)) & (∀ Xs Xf . closed(Xs:: 0a,Xf ) −−> little-set(Xf )) & (∀ Xf Xs. closed(Xs:: 0a,Xf ) −−> maps(Xf :: 0a,cross-product(Xs:: 0a,Xs),Xs)) & (∀ Xf Xs. little-set(Xs)& little-set(Xf )& maps(Xf :: 0a,cross-product(Xs:: 0a,Xs),Xs) −−> closed(Xs:: 0a,Xf )) & (∀ Z Xf Xg. member(Z :: 0a,composition(Xf :: 0a,Xg)) −−> little-set(f29 (Z :: 0a,Xf ,Xg))) & (∀ Z Xf Xg. member(Z :: 0a,composition(Xf :: 0a,Xg)) −−> little-set(f30 (Z :: 0a,Xf ,Xg))) & (∀ Z Xf Xg. member(Z :: 0a,composition(Xf :: 0a,Xg)) −−> little-set(f31 (Z :: 0a,Xf ,Xg))) & (∀ Z Xf Xg. member(Z :: 0a,composition(Xf :: 0a,Xg)) −−> equal(Z :: 0a,ordered-pair(f29 (Z :: 0a,Xf ,Xg),f30 (Z :: 0a,Xf ,Xg)))) & (∀ Z Xg Xf . member(Z :: 0a,composition(Xf :: 0a,Xg)) −−> member(ordered-pair(f29 (Z :: 0a,Xf ,Xg),f31 (Z :: 0a,Xf ,Xg)),Xf )) & (∀ Z Xf Xg. member(Z :: 0a,composition(Xf :: 0a,Xg)) −−> member(ordered-pair(f31 (Z :: 0a,Xf ,Xg),f30 (Z :: 0a,Xf ,Xg)),Xg)) & (∀ Z X Xf W Y Xg. little-set(Z )& little-set(X )& little-set(Y )& little-set(W )& equal(Z :: 0a,ordered-pair(X :: 0a,Y )) & member(ordered-pair(X :: 0a,W ),Xf )& mem- ber(ordered-pair(W :: 0a,Y ),Xg) −−> member(Z :: 0a,composition(Xf :: 0a,Xg))) & (∀ Xh Xs2 Xf2 Xs1 Xf1 . homomorphism(Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ) −−> closed(Xs1 :: 0a,Xf1 )) & (∀ Xh Xs1 Xf1 Xs2 Xf2 . homomorphism(Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ) −−> closed(Xs2 :: 0a,Xf2 )) & (∀ Xf1 Xf2 Xh Xs1 Xs2 . homomorphism(Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ) −−> maps(Xh:: 0a,Xs1 ,Xs2 )) & (∀ Xs2 Xs1 Xf1 Xf2 X Xh Y . homomorphism(Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 )& mem- ber(X :: 0a,Xs1 )& member(Y :: 0a,Xs1 ) −−> equal(apply(Xh:: 0a,apply-to-two-arguments(Xf1 :: 0a,X ,Y )),apply-to-two-arguments(Xf2 :: 0a,apply(Xh:: 0a,X ),apply(Xh:: 0a,Y )))) & (∀ Xh Xf1 Xs2 Xf2 Xs1 . closed(Xs1 :: 0a,Xf1 )& closed(Xs2 :: 0a,Xf2 )& maps(Xh:: 0a,Xs1 ,Xs2 ) −−> homomorphism(Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ) | member(f32 (Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ),Xs1 )) & (∀ Xh Xf1 Xs2 Xf2 Xs1 . closed(Xs1 :: 0a,Xf1 )& closed(Xs2 :: 0a,Xf2 )& maps(Xh:: 0a,Xs1 ,Xs2 ) −−> homomorphism(Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ) | member(f33 (Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ),Xs1 )) & (∀ Xh Xs1 Xf1 Xs2 Xf2 . closed(Xs1 :: 0a,Xf1 )& closed(Xs2 :: 0a,Xf2 )& maps(Xh:: 0a,Xs1 ,Xs2 ) & equal(apply(Xh:: 0a,apply-to-two-arguments(Xf1 :: 0a,f32 (Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ),f33 (Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 ))),apply-to-two-arguments(Xf2 :: 0a,apply(Xh:: 0a,f32 (Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 )),apply(Xh:: 0a,f33 (Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 )))) −−> homomorphism(Xh:: 0a,Xs1 ,Xf1 ,Xs2 ,Xf2 )) & (∀ ABC . equal(A:: 0a,B) −−> equal(f1 (A:: 0a,C ),f1 (B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(f1 (F 0:: 0a,D),f1 (F 0:: 0a,E))) &

802 (∀ A2 B2 . equal(A2 :: 0a,B2 ) −−> equal(f2 (A2 ),f2 (B2 ))) & (∀ G4 H4 . equal(G4 :: 0a,H4 ) −−> equal(f3 (G4 ),f3 (H4 ))) & (∀ O7 P7 Q7 . equal(O7 :: 0a,P7 ) −−> equal(f4 (O7 :: 0a,Q7 ),f4 (P7 :: 0a,Q7 ))) & (∀ R7 T7 S7 . equal(R7 :: 0a,S7 ) −−> equal(f4 (T7 :: 0a,R7 ),f4 (T7 :: 0a,S7 ))) & (∀ U7 V7 W7 . equal(U7 :: 0a,V7 ) −−> equal(f5 (U7 :: 0a,W7 ),f5 (V7 :: 0a,W7 ))) & (∀ X7 Z7 Y7 . equal(X7 :: 0a,Y7 ) −−> equal(f5 (Z7 :: 0a,X7 ),f5 (Z7 :: 0a,Y7 ))) & (∀ A8 B8 C8 . equal(A8 :: 0a,B8 ) −−> equal(f6 (A8 :: 0a,C8 ),f6 (B8 :: 0a,C8 ))) & (∀ D8 F8 E8 . equal(D8 :: 0a,E8 ) −−> equal(f6 (F8 :: 0a,D8 ),f6 (F8 :: 0a,E8 ))) & (∀ G8 H8 I8 . equal(G8 :: 0a,H8 ) −−> equal(f7 (G8 :: 0a,I8 ),f7 (H8 :: 0a,I8 ))) & (∀ J8 L8 K8 . equal(J8 :: 0a,K8 ) −−> equal(f7 (L8 :: 0a,J8 ),f7 (L8 :: 0a,K8 ))) & (∀ M8 N8 O8 . equal(M8 :: 0a,N8 ) −−> equal(f8 (M8 :: 0a,O8 ),f8 (N8 :: 0a,O8 ))) & (∀ P8 R8 Q8 . equal(P8 :: 0a,Q8 ) −−> equal(f8 (R8 :: 0a,P8 ),f8 (R8 :: 0a,Q8 ))) & (∀ S8 T8 U8 . equal(S8 :: 0a,T8 ) −−> equal(f9 (S8 :: 0a,U8 ),f9 (T8 :: 0a,U8 ))) & (∀ V8 X8 W8 . equal(V8 :: 0a,W8 ) −−> equal(f9 (X8 :: 0a,V8 ),f9 (X8 :: 0a,W8 ))) & (∀ GHI 0. equal(G:: 0a,H ) −−> equal(f10 (G:: 0a,I 0),f10 (H :: 0a,I 0))) & (∀ JLK 0. equal(J :: 0a,K 0) −−> equal(f10 (L:: 0a,J ),f10 (L:: 0a,K 0))) & (∀ MNO 0. equal(M :: 0a,N ) −−> equal(f11 (M :: 0a,O 0),f11 (N :: 0a,O 0))) & (∀ PRQ. equal(P:: 0a,Q) −−> equal(f11 (R:: 0a,P),f11 (R:: 0a,Q))) & (∀ S 0 T 0 U . equal(S 0:: 0a,T 0) −−> equal(f12 (S 0:: 0a,U ),f12 (T 0:: 0a,U ))) & (∀ VXW . equal(V :: 0a,W ) −−> equal(f12 (X :: 0a,V ),f12 (X :: 0a,W ))) & (∀ Y Z A1 . equal(Y :: 0a,Z ) −−> equal(f13 (Y :: 0a,A1 ),f13 (Z :: 0a,A1 ))) & (∀ B1 D1 C1 . equal(B1 :: 0a,C1 ) −−> equal(f13 (D1 :: 0a,B1 ),f13 (D1 :: 0a,C1 ))) & (∀ E1 F1 G1 . equal(E1 :: 0a,F1 ) −−> equal(f14 (E1 :: 0a,G1 ),f14 (F1 :: 0a,G1 ))) & (∀ H1 J1 I1 . equal(H1 :: 0a,I1 ) −−> equal(f14 (J1 :: 0a,H1 ),f14 (J1 :: 0a,I1 ))) & (∀ K1 L1 M1 . equal(K1 :: 0a,L1 ) −−> equal(f16 (K1 :: 0a,M1 ),f16 (L1 :: 0a,M1 ))) & (∀ N1 P1 O1 . equal(N1 :: 0a,O1 ) −−> equal(f16 (P1 :: 0a,N1 ),f16 (P1 :: 0a,O1 ))) & (∀ Q1 R1 S1 . equal(Q1 :: 0a,R1 ) −−> equal(f17 (Q1 :: 0a,S1 ),f17 (R1 :: 0a,S1 ))) & (∀ T1 V1 U1 . equal(T1 :: 0a,U1 ) −−> equal(f17 (V1 :: 0a,T1 ),f17 (V1 :: 0a,U1 ))) & (∀ W1 X1 . equal(W1 :: 0a,X1 ) −−> equal(f18 (W1 ),f18 (X1 ))) & (∀ Y1 Z1 . equal(Y1 :: 0a,Z1 ) −−> equal(f19 (Y1 ),f19 (Z1 ))) & (∀ C2 D2 . equal(C2 :: 0a,D2 ) −−> equal(f20 (C2 ),f20 (D2 ))) & (∀ E2 F2 . equal(E2 :: 0a,F2 ) −−> equal(f21 (E2 ),f21 (F2 ))) & (∀ G2 H2 I2 J2 . equal(G2 :: 0a,H2 ) −−> equal(f22 (G2 :: 0a,I2 ,J2 ),f22 (H2 :: 0a,I2 ,J2 ))) & (∀ K2 M2 L2 N2 . equal(K2 :: 0a,L2 ) −−> equal(f22 (M2 :: 0a,K2 ,N2 ),f22 (M2 :: 0a,L2 ,N2 ))) & (∀ O2 Q2 R2 P2 . equal(O2 :: 0a,P2 ) −−> equal(f22 (Q2 :: 0a,R2 ,O2 ),f22 (Q2 :: 0a,R2 ,P2 ))) & (∀ S2 T2 U2 . equal(S2 :: 0a,T2 ) −−> equal(f23 (S2 :: 0a,U2 ),f23 (T2 :: 0a,U2 ))) & (∀ V2 X2 W2 . equal(V2 :: 0a,W2 ) −−> equal(f23 (X2 :: 0a,V2 ),f23 (X2 :: 0a,W2 ))) & (∀ Y2 Z2 . equal(Y2 :: 0a,Z2 ) −−> equal(f24 (Y2 ),f24 (Z2 ))) & (∀ A3 B3 . equal(A3 :: 0a,B3 ) −−> equal(f26 (A3 ),f26 (B3 ))) & (∀ C3 D3 E3 . equal(C3 :: 0a,D3 ) −−> equal(f27 (C3 :: 0a,E3 ),f27 (D3 :: 0a,E3 ))) & (∀ F3 H3 G3 . equal(F3 :: 0a,G3 ) −−> equal(f27 (H3 :: 0a,F3 ),f27 (H3 :: 0a,G3 ))) & (∀ I3 J3 K3 L3 . equal(I3 :: 0a,J3 ) −−> equal(f28 (I3 :: 0a,K3 ,L3 ),f28 (J3 :: 0a,K3 ,L3 ))) & (∀ M3 O3 N3 P3 . equal(M3 :: 0a,N3 ) −−> equal(f28 (O3 :: 0a,M3 ,P3 ),f28 (O3 :: 0a,N3 ,P3 ))) &

803 (∀ Q3 S3 T3 R3 . equal(Q3 :: 0a,R3 ) −−> equal(f28 (S3 :: 0a,T3 ,Q3 ),f28 (S3 :: 0a,T3 ,R3 ))) & (∀ U3 V3 W3 X3 . equal(U3 :: 0a,V3 ) −−> equal(f29 (U3 :: 0a,W3 ,X3 ),f29 (V3 :: 0a,W3 ,X3 ))) & (∀ Y3 A4 Z3 B4 . equal(Y3 :: 0a,Z3 ) −−> equal(f29 (A4 :: 0a,Y3 ,B4 ),f29 (A4 :: 0a,Z3 ,B4 ))) & (∀ C4 E4 F4 D4 . equal(C4 :: 0a,D4 ) −−> equal(f29 (E4 :: 0a,F4 ,C4 ),f29 (E4 :: 0a,F4 ,D4 ))) & (∀ I4 J4 K4 L4 . equal(I4 :: 0a,J4 ) −−> equal(f30 (I4 :: 0a,K4 ,L4 ),f30 (J4 :: 0a,K4 ,L4 ))) & (∀ M4 O4 N4 P4 . equal(M4 :: 0a,N4 ) −−> equal(f30 (O4 :: 0a,M4 ,P4 ),f30 (O4 :: 0a,N4 ,P4 ))) & (∀ Q4 S4 T4 R4 . equal(Q4 :: 0a,R4 ) −−> equal(f30 (S4 :: 0a,T4 ,Q4 ),f30 (S4 :: 0a,T4 ,R4 ))) & (∀ U4 V4 W4 X4 . equal(U4 :: 0a,V4 ) −−> equal(f31 (U4 :: 0a,W4 ,X4 ),f31 (V4 :: 0a,W4 ,X4 ))) & (∀ Y4 A5 Z4 B5 . equal(Y4 :: 0a,Z4 ) −−> equal(f31 (A5 :: 0a,Y4 ,B5 ),f31 (A5 :: 0a,Z4 ,B5 ))) & (∀ C5 E5 F5 D5 . equal(C5 :: 0a,D5 ) −−> equal(f31 (E5 :: 0a,F5 ,C5 ),f31 (E5 :: 0a,F5 ,D5 ))) & (∀ G5 H5 I5 J5 K5 L5 . equal(G5 :: 0a,H5 ) −−> equal(f32 (G5 :: 0a,I5 ,J5 ,K5 ,L5 ),f32 (H5 :: 0a,I5 ,J5 ,K5 ,L5 ))) & (∀ M5 O5 N5 P5 Q5 R5 . equal(M5 :: 0a,N5 ) −−> equal(f32 (O5 :: 0a,M5 ,P5 ,Q5 ,R5 ),f32 (O5 :: 0a,N5 ,P5 ,Q5 ,R5 ))) & (∀ S5 U5 V5 T5 W5 X5 . equal(S5 :: 0a,T5 ) −−> equal(f32 (U5 :: 0a,V5 ,S5 ,W5 ,X5 ),f32 (U5 :: 0a,V5 ,T5 ,W5 ,X5 ))) & (∀ Y5 A6 B6 C6 Z5 D6 . equal(Y5 :: 0a,Z5 ) −−> equal(f32 (A6 :: 0a,B6 ,C6 ,Y5 ,D6 ),f32 (A6 :: 0a,B6 ,C6 ,Z5 ,D6 ))) & (∀ E6 G6 H6 I6 J6 F6 . equal(E6 :: 0a,F6 ) −−> equal(f32 (G6 :: 0a,H6 ,I6 ,J6 ,E6 ),f32 (G6 :: 0a,H6 ,I6 ,J6 ,F6 ))) & (∀ K6 L6 M6 N6 O6 P6 . equal(K6 :: 0a,L6 ) −−> equal(f33 (K6 :: 0a,M6 ,N6 ,O6 ,P6 ),f33 (L6 :: 0a,M6 ,N6 ,O6 ,P6 ))) & (∀ Q6 S6 R6 T6 U6 V6 . equal(Q6 :: 0a,R6 ) −−> equal(f33 (S6 :: 0a,Q6 ,T6 ,U6 ,V6 ),f33 (S6 :: 0a,R6 ,T6 ,U6 ,V6 ))) & (∀ W6 Y6 Z6 X6 A7 B7 . equal(W6 :: 0a,X6 ) −−> equal(f33 (Y6 :: 0a,Z6 ,W6 ,A7 ,B7 ),f33 (Y6 :: 0a,Z6 ,X6 ,A7 ,B7 ))) & (∀ C7 E7 F7 G7 D7 H7 . equal(C7 :: 0a,D7 ) −−> equal(f33 (E7 :: 0a,F7 ,G7 ,C7 ,H7 ),f33 (E7 :: 0a,F7 ,G7 ,D7 ,H7 ))) & (∀ I7 K7 L7 M7 N7 J7 . equal(I7 :: 0a,J7 ) −−> equal(f33 (K7 :: 0a,L7 ,M7 ,N7 ,I7 ),f33 (K7 :: 0a,L7 ,M7 ,N7 ,J7 ))) & (∀ ABC . equal(A:: 0a,B) −−> equal(apply(A:: 0a,C ),apply(B:: 0a,C ))) & (∀ DF 0 E. equal(D:: 0a,E) −−> equal(apply(F 0:: 0a,D),apply(F 0:: 0a,E))) & (∀ GHI 0 J . equal(G:: 0a,H ) −−> equal(apply-to-two-arguments(G:: 0a,I 0,J ),apply-to-two-arguments(H :: 0a,I 0,J ))) & (∀ K 0 MLN . equal(K 0:: 0a,L) −−> equal(apply-to-two-arguments(M :: 0a,K 0,N ),apply-to-two-arguments(M :: 0a,L,N ))) & (∀ O 0 QRP. equal(O 0:: 0a,P) −−> equal(apply-to-two-arguments(Q:: 0a,R,O 0),apply-to-two-arguments(Q:: 0a,R,P))) & (∀ S 0 T 0. equal(S 0:: 0a,T 0) −−> equal(complement(S 0),complement(T 0))) &

804 (∀ UVW . equal(U :: 0a,V ) −−> equal(composition(U :: 0a,W ),composition(V :: 0a,W ))) & (∀ XZY . equal(X :: 0a,Y ) −−> equal(composition(Z :: 0a,X ),composition(Z :: 0a,Y ))) & (∀ A1 B1 . equal(A1 :: 0a,B1 ) −−> equal(inv1 A1 ,inv1 B1 )) & (∀ C1 D1 E1 . equal(C1 :: 0a,D1 ) −−> equal(cross-product(C1 :: 0a,E1 ),cross-product(D1 :: 0a,E1 ))) & (∀ F1 H1 G1 . equal(F1 :: 0a,G1 ) −−> equal(cross-product(H1 :: 0a,F1 ),cross-product(H1 :: 0a,G1 ))) & (∀ I1 J1 . equal(I1 :: 0a,J1 ) −−> equal(domain-of (I1 ),domain-of (J1 ))) & (∀ I10 J10 . equal(I10 :: 0a,J10 ) −−> equal(first(I10 ),first(J10 ))) & (∀ Q10 R10 . equal(Q10 :: 0a,R10 ) −−> equal(flip-range-of (Q10 ),flip-range-of (R10 ))) & (∀ S10 T10 U10 . equal(S10 :: 0a,T10 ) −−> equal(image 0(S10 :: 0a,U10 ),image 0(T10 :: 0a,U10 ))) & (∀ V10 X10 W10 . equal(V10 :: 0a,W10 ) −−> equal(image 0(X10 :: 0a,V10 ),image 0(X10 :: 0a,W10 ))) & (∀ Y10 Z10 A11 . equal(Y10 :: 0a,Z10 ) −−> equal(intersection(Y10 :: 0a,A11 ),intersection(Z10 :: 0a,A11 ))) & (∀ B11 D11 C11 . equal(B11 :: 0a,C11 ) −−> equal(intersection(D11 :: 0a,B11 ),intersection(D11 :: 0a,C11 ))) & (∀ E11 F11 G11 . equal(E11 :: 0a,F11 ) −−> equal(non-ordered-pair(E11 :: 0a,G11 ),non-ordered-pair(F11 :: 0a,G11 ))) & (∀ H11 J11 I11 . equal(H11 :: 0a,I11 ) −−> equal(non-ordered-pair(J11 :: 0a,H11 ),non-ordered-pair(J11 :: 0a,I11 ))) & (∀ K11 L11 M11 . equal(K11 :: 0a,L11 ) −−> equal(ordered-pair(K11 :: 0a,M11 ),ordered-pair(L11 :: 0a,M11 ))) & (∀ N11 P11 O11 . equal(N11 :: 0a,O11 ) −−> equal(ordered-pair(P11 :: 0a,N11 ),ordered-pair(P11 :: 0a,O11 ))) & (∀ Q11 R11 . equal(Q11 :: 0a,R11 ) −−> equal(powerset(Q11 ),powerset(R11 ))) & (∀ S11 T11 . equal(S11 :: 0a,T11 ) −−> equal(range-of (S11 ),range-of (T11 ))) & (∀ U11 V11 W11 . equal(U11 :: 0a,V11 ) −−> equal(restrct(U11 :: 0a,W11 ),restrct(V11 :: 0a,W11 ))) & (∀ X11 Z11 Y11 . equal(X11 :: 0a,Y11 ) −−> equal(restrct(Z11 :: 0a,X11 ),restrct(Z11 :: 0a,Y11 ))) & (∀ A12 B12 . equal(A12 :: 0a,B12 ) −−> equal(rot-right(A12 ),rot-right(B12 ))) & (∀ C12 D12 . equal(C12 :: 0a,D12 ) −−> equal(second(C12 ),second(D12 ))) & (∀ K12 L12 . equal(K12 :: 0a,L12 ) −−> equal(sigma(K12 ),sigma(L12 ))) & (∀ M12 N12 . equal(M12 :: 0a,N12 ) −−> equal(singleton-set(M12 ),singleton-set(N12 ))) & (∀ O12 P12 . equal(O12 :: 0a,P12 ) −−> equal(successor(O12 ),successor(P12 ))) & (∀ Q12 R12 S12 . equal(Q12 :: 0a,R12 ) −−> equal(union(Q12 :: 0a,S12 ),union(R12 :: 0a,S12 ))) & (∀ T12 V12 U12 . equal(T12 :: 0a,U12 ) −−> equal(union(V12 :: 0a,T12 ),union(V12 :: 0a,U12 ))) & (∀ W12 X12 Y12 . equal(W12 :: 0a,X12 )& closed(W12 :: 0a,Y12 ) −−> closed(X12 :: 0a,Y12 )) & (∀ Z12 B13 A13 . equal(Z12 :: 0a,A13 )& closed(B13 :: 0a,Z12 ) −−> closed(B13 :: 0a,A13 )) &

805 (∀ C13 D13 E13 . equal(C13 :: 0a,D13 )& disjoint(C13 :: 0a,E13 ) −−> disjoint(D13 :: 0a,E13 )) & (∀ F13 H13 G13 . equal(F13 :: 0a,G13 )& disjoint(H13 :: 0a,F13 ) −−> disjoint(H13 :: 0a,G13 )) & (∀ I13 J13 . equal(I13 :: 0a,J13 )& function(I13 ) −−> function(J13 )) & (∀ K13 L13 M13 N13 O13 P13 . equal(K13 :: 0a,L13 )& homomorphism(K13 :: 0a,M13 ,N13 ,O13 ,P13 ) −−> homomorphism(L13 :: 0a,M13 ,N13 ,O13 ,P13 )) & (∀ Q13 S13 R13 T13 U13 V13 . equal(Q13 :: 0a,R13 )& homomorphism(S13 :: 0a,Q13 ,T13 ,U13 ,V13 ) −−> homomorphism(S13 :: 0a,R13 ,T13 ,U13 ,V13 )) & (∀ W13 Y13 Z13 X13 A14 B14 . equal(W13 :: 0a,X13 )& homomorphism(Y13 :: 0a,Z13 ,W13 ,A14 ,B14 ) −−> homomorphism(Y13 :: 0a,Z13 ,X13 ,A14 ,B14 )) & (∀ C14 E14 F14 G14 D14 H14 . equal(C14 :: 0a,D14 )& homomorphism(E14 :: 0a,F14 ,G14 ,C14 ,H14 ) −−> homomorphism(E14 :: 0a,F14 ,G14 ,D14 ,H14 )) & (∀ I14 K14 L14 M14 N14 J14 . equal(I14 :: 0a,J14 )& homomorphism(K14 :: 0a,L14 ,M14 ,N14 ,I14 ) −−> homomorphism(K14 :: 0a,L14 ,M14 ,N14 ,J14 )) & (∀ O14 P14 . equal(O14 :: 0a,P14 )& little-set(O14 ) −−> little-set(P14 )) & (∀ Q14 R14 S14 T14 . equal(Q14 :: 0a,R14 )& maps(Q14 :: 0a,S14 ,T14 ) −−> maps(R14 :: 0a,S14 ,T14 )) & (∀ U14 W14 V14 X14 . equal(U14 :: 0a,V14 )& maps(W14 :: 0a,U14 ,X14 ) −−> maps(W14 :: 0a,V14 ,X14 )) & (∀ Y14 A15 B15 Z14 . equal(Y14 :: 0a,Z14 )& maps(A15 :: 0a,B15 ,Y14 ) −−> maps(A15 :: 0a,B15 ,Z14 )) & (∀ C15 D15 E15 . equal(C15 :: 0a,D15 )& member(C15 :: 0a,E15 ) −−> member(D15 :: 0a,E15 )) & (∀ F15 H15 G15 . equal(F15 :: 0a,G15 )& member(H15 :: 0a,F15 ) −−> member(H15 :: 0a,G15 )) & (∀ I15 J15 . equal(I15 :: 0a,J15 )& one-to-one-function(I15 ) −−> one-to-one-function(J15 )) & (∀ K15 L15 . equal(K15 :: 0a,L15 )& ordered-pair-predicate(K15 ) −−> ordered-pair-predicate(L15 )) & (∀ M15 N15 O15 . equal(M15 :: 0a,N15 )& proper-subset(M15 :: 0a,O15 ) −−> proper-subset(N15 :: 0a,O15 )) & (∀ P15 R15 Q15 . equal(P15 :: 0a,Q15 )& proper-subset(R15 :: 0a,P15 ) −−> proper-subset(R15 :: 0a,Q15 )) & (∀ S15 T15 . equal(S15 :: 0a,T15 )& relation(S15 ) −−> relation(T15 )) & (∀ U15 V15 . equal(U15 :: 0a,V15 )& single-valued-set(U15 ) −−> single-valued-set(V15 )) & (∀ W15 X15 Y15 . equal(W15 :: 0a,X15 )& ssubset(W15 :: 0a,Y15 ) −−> ssubset(X15 :: 0a,Y15 )) & (∀ Z15 B16 A16 . equal(Z15 :: 0a,A16 )& ssubset(B16 :: 0a,Z15 ) −−> ssubset(B16 :: 0a,A16 )) & (∼little-set(ordered-pair(a:: 0a,b))) −−> False oops

lemma SET046-5 : (∀ YX . ∼(element(X :: 0a,a)& element(X :: 0a,Y )& element(Y :: 0a,X ))) & (∀ X . element(X :: 0a,f (X )) | element(X :: 0a,a)) &

806 (∀ X . element(f (X ),X ) | element(X :: 0a,a)) −−> False by meson lemma SET047-5 : (∀ XZY . set-equal(X :: 0a,Y )& element(Z :: 0a,X ) −−> element(Z :: 0a,Y )) & (∀ YZX . set-equal(X :: 0a,Y )& element(Z :: 0a,Y ) −−> element(Z :: 0a,X )) & (∀ XY . element(f (X :: 0a,Y ),X ) | element(f (X :: 0a,Y ),Y ) | set-equal(X :: 0a,Y )) & (∀ XY . element(f (X :: 0a,Y ),Y )& element(f (X :: 0a,Y ),X ) −−> set-equal(X :: 0a,Y )) & (set-equal(a:: 0a,b) | set-equal(b:: 0a,a)) & (∼(set-equal(b:: 0a,a)& set-equal(a:: 0a,b))) −−> False by meson lemma SYN034-1 : (∀ A. p(A:: 0a,a) | p(A:: 0a,f (A))) & (∀ A. p(A:: 0a,a) | p(f (A),A)) & (∀ AB. ∼(p(A:: 0a,B)& p(B:: 0a,A)& p(B:: 0a,a))) −−> False by meson lemma SYN071-1 : EQU001-0-ax equal & (equal(a:: 0a,b) | equal(c:: 0a,d)) & (equal(a:: 0a,c) | equal(b:: 0a,d)) & (∼equal(a:: 0a,d)) & (∼equal(b:: 0a,c)) −−> False by meson lemma SYN349-1 : (∀ XY . f (w(X ),g(X :: 0a,Y )) −−> f (X :: 0a,g(X :: 0a,Y ))) & (∀ XY . f (X :: 0a,g(X :: 0a,Y )) −−> f (w(X ),g(X :: 0a,Y ))) & (∀ YX . f (X :: 0a,g(X :: 0a,Y )) & f (Y :: 0a,g(X :: 0a,Y )) −−> f (g(X :: 0a,Y ),Y ) | f (g(X :: 0a,Y ),w(X ))) & (∀ YX . f (g(X :: 0a,Y ),Y )& f (Y :: 0a,g(X :: 0a,Y )) −−> f (X :: 0a,g(X :: 0a,Y )) | f (g(X :: 0a,Y ),w(X ))) & (∀ YX . f (X :: 0a,g(X :: 0a,Y )) | f (g(X :: 0a,Y ),Y ) | f (Y :: 0a,g(X :: 0a,Y )) | f (g(X :: 0a,Y ),w(X ))) & (∀ YX . f (X :: 0a,g(X :: 0a,Y )) & f (g(X :: 0a,Y ),Y ) −−> f (Y :: 0a,g(X :: 0a,Y )) | f (g(X :: 0a,Y ),w(X ))) & (∀ YX . f (X :: 0a,g(X :: 0a,Y )) & f (g(X :: 0a,Y ),w(X )) −−> f (g(X :: 0a,Y ),Y ) | f (Y :: 0a,g(X :: 0a,Y ))) & (∀ YX . f (g(X :: 0a,Y ),Y )& f (g(X :: 0a,Y ),w(X )) −−> f (X :: 0a,g(X :: 0a,Y )) | f (Y :: 0a,g(X :: 0a,Y ))) & (∀ YX . f (Y :: 0a,g(X :: 0a,Y )) & f (g(X :: 0a,Y ),w(X )) −−> f (X :: 0a,g(X :: 0a,Y )) | f (g(X :: 0a,Y ),Y )) &

807 (∀ YX . ∼(f (X :: 0a,g(X :: 0a,Y )) & f (g(X :: 0a,Y ),Y )& f (Y :: 0a,g(X :: 0a,Y )) & f (g(X :: 0a,Y ),w(X )))) −−> False oops lemma SYN352-1 : (f (a:: 0a,b)) & (∀ XY . f (X :: 0a,Y ) −−> f (b:: 0a,z(X :: 0a,Y )) | f (Y :: 0a,z(X :: 0a,Y ))) & (∀ XY . f (X :: 0a,Y ) | f (z(X :: 0a,Y ),z(X :: 0a,Y ))) & (∀ XY . f (b:: 0a,z(X :: 0a,Y )) | f (X :: 0a,z(X :: 0a,Y )) | f (z(X :: 0a,Y ),z(X :: 0a,Y ))) & (∀ XY . f (b:: 0a,z(X :: 0a,Y )) & f (X :: 0a,z(X :: 0a,Y )) −−> f (z(X :: 0a,Y ),z(X :: 0a,Y ))) & (∀ XY . ∼(f (X :: 0a,Y )& f (X :: 0a,z(X :: 0a,Y )) & f (Y :: 0a,z(X :: 0a,Y )))) & (∀ XY . f (X :: 0a,Y ) −−> f (X :: 0a,z(X :: 0a,Y )) | f (Y :: 0a,z(X :: 0a,Y ))) −−> False by meson lemma TOP001-2 : (∀ Vf U . element-of-set(U :: 0a,union-of-members(Vf )) −−> element-of-set(U :: 0a,f1 (Vf :: 0a,U ))) & (∀ U Vf . element-of-set(U :: 0a,union-of-members(Vf )) −−> element-of-collection(f1 (Vf :: 0a,U ),Vf )) & (∀ U Uu1 Vf . element-of-set(U :: 0a,Uu1 )& element-of-collection(Uu1 :: 0a,Vf ) −−> element-of-set(U :: 0a,union-of-members(Vf ))) & (∀ Vf X . basis(X :: 0a,Vf ) −−> equal-sets(union-of-members(Vf ),X )) & (∀ Vf U X . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> element-of-set(X :: 0a,f10 (Vf :: 0a,U ,X ))) & (∀ U X Vf . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> element-of-collection(f10 (Vf :: 0a,U ,X ),Vf )) & (∀ X . subset-sets(X :: 0a,X )) & (∀ XUY . subset-sets(X :: 0a,Y )& element-of-set(U :: 0a,X ) −−> element-of-set(U :: 0a,Y )) & (∀ XY . equal-sets(X :: 0a,Y ) −−> subset-sets(X :: 0a,Y )) & (∀ YX . subset-sets(X :: 0a,Y ) | element-of-set(in-1st-set(X :: 0a,Y ),X )) & (∀ XY . element-of-set(in-1st-set(X :: 0a,Y ),Y ) −−> subset-sets(X :: 0a,Y )) & (basis(cx:: 0a,f )) & (∼subset-sets(union-of-members(top-of-basis(f )),cx)) −−> False by meson lemma TOP002-2 : (∀ Vf U . element-of-collection(U :: 0a,top-of-basis(Vf )) | element-of-set(f11 (Vf :: 0a,U ),U )) & (∀ X . ∼element-of-set(X :: 0a,empty-set)) & (∼element-of-collection(empty-set:: 0a,top-of-basis(f ))) −−> False by meson lemma TOP004-1 :

808 (∀ Vf U . element-of-set(U :: 0a,union-of-members(Vf )) −−> element-of-set(U :: 0a,f1 (Vf :: 0a,U ))) & (∀ U Vf . element-of-set(U :: 0a,union-of-members(Vf )) −−> element-of-collection(f1 (Vf :: 0a,U ),Vf )) & (∀ U Uu1 Vf . element-of-set(U :: 0a,Uu1 )& element-of-collection(Uu1 :: 0a,Vf ) −−> element-of-set(U :: 0a,union-of-members(Vf ))) & (∀ Vf U Va. element-of-set(U :: 0a,intersection-of-members(Vf )) & element-of-collection(Va:: 0a,Vf ) −−> element-of-set(U :: 0a,Va)) & (∀ U Vf . element-of-set(U :: 0a,intersection-of-members(Vf )) | element-of-collection(f2 (Vf :: 0a,U ),Vf )) & (∀ Vf U . element-of-set(U :: 0a,f2 (Vf :: 0a,U )) −−> element-of-set(U :: 0a,intersection-of-members(Vf ))) & (∀ Vt X . topological-space(X :: 0a,Vt) −−> equal-sets(union-of-members(Vt),X )) & (∀ X Vt. topological-space(X :: 0a,Vt) −−> element-of-collection(empty-set:: 0a,Vt)) & (∀ X Vt. topological-space(X :: 0a,Vt) −−> element-of-collection(X :: 0a,Vt)) & (∀ X Y Z Vt. topological-space(X :: 0a,Vt)& element-of-collection(Y :: 0a,Vt)& element-of-collection(Z :: 0a,Vt) −−> element-of-collection(intersection-of-sets(Y :: 0a,Z ),Vt)) & (∀ X Vf Vt. topological-space(X :: 0a,Vt)& subset-collections(Vf :: 0a,Vt) −−> element-of-collection(union-of-members(Vf ),Vt)) & (∀ X Vt. equal-sets(union-of-members(Vt),X )& element-of-collection(empty-set:: 0a,Vt) & element-of-collection(X :: 0a,Vt) −−> topological-space(X :: 0a,Vt) | element-of-collection(f3 (X :: 0a,Vt),Vt) | subset-collections(f5 (X :: 0a,Vt),Vt)) & (∀ X Vt. equal-sets(union-of-members(Vt),X )& element-of-collection(empty-set:: 0a,Vt) & element-of-collection(X :: 0a,Vt)& element-of-collection(union-of-members(f5 (X :: 0a,Vt)),Vt) −−> topological-space(X :: 0a,Vt) | element-of-collection(f3 (X :: 0a,Vt),Vt)) & (∀ X Vt. equal-sets(union-of-members(Vt),X )& element-of-collection(empty-set:: 0a,Vt) & element-of-collection(X :: 0a,Vt) −−> topological-space(X :: 0a,Vt) | element-of-collection(f4 (X :: 0a,Vt),Vt) | subset-collections(f5 (X :: 0a,Vt),Vt)) & (∀ X Vt. equal-sets(union-of-members(Vt),X )& element-of-collection(empty-set:: 0a,Vt) & element-of-collection(X :: 0a,Vt)& element-of-collection(union-of-members(f5 (X :: 0a,Vt)),Vt) −−> topological-space(X :: 0a,Vt) | element-of-collection(f4 (X :: 0a,Vt),Vt)) & (∀ X Vt. equal-sets(union-of-members(Vt),X )& element-of-collection(empty-set:: 0a,Vt) & element-of-collection(X :: 0a,Vt)& element-of-collection(intersection-of-sets(f3 (X :: 0a,Vt),f4 (X :: 0a,Vt)),Vt) −−> topological-space(X :: 0a,Vt) | subset-collections(f5 (X :: 0a,Vt),Vt)) & (∀ X Vt. equal-sets(union-of-members(Vt),X )& element-of-collection(empty-set:: 0a,Vt) & element-of-collection(X :: 0a,Vt)& element-of-collection(intersection-of-sets(f3 (X :: 0a,Vt),f4 (X :: 0a,Vt)),Vt) & element-of-collection(union-of-members(f5 (X :: 0a,Vt)),Vt) −−> topological-space(X :: 0a,Vt)) & (∀ U X Vt. open(U :: 0a,X ,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ X U Vt. open(U :: 0a,X ,Vt) −−> element-of-collection(U :: 0a,Vt)) & (∀ X U Vt. topological-space(X :: 0a,Vt)& element-of-collection(U :: 0a,Vt) −−> open(U :: 0a,X ,Vt)) & (∀ U X Vt. closed(U :: 0a,X ,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ U X Vt. closed(U :: 0a,X ,Vt) −−> open(relative-complement-sets(U :: 0a,X ),X ,Vt)) & (∀ U X Vt. topological-space(X :: 0a,Vt)& open(relative-complement-sets(U :: 0a,X ),X ,Vt)

809 −−> closed(U :: 0a,X ,Vt)) & (∀ Vs X Vt. finer(Vt:: 0a,Vs,X ) −−> topological-space(X :: 0a,Vt)) & (∀ Vt X Vs. finer(Vt:: 0a,Vs,X ) −−> topological-space(X :: 0a,Vs)) & (∀ X Vs Vt. finer(Vt:: 0a,Vs,X ) −−> subset-collections(Vs:: 0a,Vt)) & (∀ X Vs Vt. topological-space(X :: 0a,Vt)& topological-space(X :: 0a,Vs)& subset-collections(Vs:: 0a,Vt) −−> finer(Vt:: 0a,Vs,X )) & (∀ Vf X . basis(X :: 0a,Vf ) −−> equal-sets(union-of-members(Vf ),X )) & (∀ X Vf Y Vb1 Vb2 . basis(X :: 0a,Vf )& element-of-set(Y :: 0a,X )& element-of-collection(Vb1 :: 0a,Vf ) & element-of-collection(Vb2 :: 0a,Vf )& element-of-set(Y :: 0a,intersection-of-sets(Vb1 :: 0a,Vb2 )) −−> element-of-set(Y :: 0a,f6 (X :: 0a,Vf ,Y ,Vb1 ,Vb2 ))) & (∀ X Y Vb1 Vb2 Vf . basis(X :: 0a,Vf )& element-of-set(Y :: 0a,X )& element-of-collection(Vb1 :: 0a,Vf ) & element-of-collection(Vb2 :: 0a,Vf )& element-of-set(Y :: 0a,intersection-of-sets(Vb1 :: 0a,Vb2 )) −−> element-of-collection(f6 (X :: 0a,Vf ,Y ,Vb1 ,Vb2 ),Vf )) & (∀ X Vf Y Vb1 Vb2 . basis(X :: 0a,Vf )& element-of-set(Y :: 0a,X )& element-of-collection(Vb1 :: 0a,Vf ) & element-of-collection(Vb2 :: 0a,Vf )& element-of-set(Y :: 0a,intersection-of-sets(Vb1 :: 0a,Vb2 )) −−> subset-sets(f6 (X :: 0a,Vf ,Y ,Vb1 ,Vb2 ),intersection-of-sets(Vb1 :: 0a,Vb2 ))) & (∀ Vf X . equal-sets(union-of-members(Vf ),X ) −−> basis(X :: 0a,Vf ) | element-of-set(f7 (X :: 0a,Vf ),X )) & (∀ X Vf . equal-sets(union-of-members(Vf ),X ) −−> basis(X :: 0a,Vf ) | element-of-collection(f8 (X :: 0a,Vf ),Vf )) & (∀ X Vf . equal-sets(union-of-members(Vf ),X ) −−> basis(X :: 0a,Vf ) | element-of-collection(f9 (X :: 0a,Vf ),Vf )) & (∀ X Vf . equal-sets(union-of-members(Vf ),X ) −−> basis(X :: 0a,Vf ) | element-of-set(f7 (X :: 0a,Vf ),intersection-of-sets(f8 (X :: 0a,Vf ),f9 (X :: 0a,Vf )))) & (∀ Uu9 X Vf . equal-sets(union-of-members(Vf ),X )& element-of-set(f7 (X :: 0a,Vf ),Uu9 ) & element-of-collection(Uu9 :: 0a,Vf )& subset-sets(Uu9 :: 0a,intersection-of-sets(f8 (X :: 0a,Vf ),f9 (X :: 0a,Vf ))) −−> basis(X :: 0a,Vf )) & (∀ Vf U X . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> element-of-set(X :: 0a,f10 (Vf :: 0a,U ,X ))) & (∀ U X Vf . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> element-of-collection(f10 (Vf :: 0a,U ,X ),Vf )) & (∀ Vf X U . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> subset-sets(f10 (Vf :: 0a,U ,X ),U )) & (∀ Vf U . element-of-collection(U :: 0a,top-of-basis(Vf )) | element-of-set(f11 (Vf :: 0a,U ),U )) & (∀ Vf Uu11 U . element-of-set(f11 (Vf :: 0a,U ),Uu11 )& element-of-collection(Uu11 :: 0a,Vf ) & subset-sets(Uu11 :: 0a,U ) −−> element-of-collection(U :: 0a,top-of-basis(Vf ))) & (∀ U Y X Vt. element-of-collection(U :: 0a,subspace-topology(X :: 0a,Vt,Y )) −−> topological-space(X :: 0a,Vt)) & (∀ U Vt Y X . element-of-collection(U :: 0a,subspace-topology(X :: 0a,Vt,Y )) −−> subset-sets(Y :: 0a,X )) & (∀ X Y U Vt. element-of-collection(U :: 0a,subspace-topology(X :: 0a,Vt,Y )) −−> element-of-collection(f12 (X :: 0a,Vt,Y ,U ),Vt)) & (∀ X Vt Y U . element-of-collection(U :: 0a,subspace-topology(X :: 0a,Vt,Y )) −−> equal-sets(U :: 0a,intersection-of-sets(Y :: 0a,f12 (X :: 0a,Vt,Y ,U )))) & (∀ X Vt U Y Uu12 . topological-space(X :: 0a,Vt)& subset-sets(Y :: 0a,X )& element-of-collection(Uu12 :: 0a,Vt) & equal-sets(U :: 0a,intersection-of-sets(Y :: 0a,Uu12 )) −−> element-of-collection(U :: 0a,subspace-topology(X :: 0a,Vt,Y ))) & (∀ U Y X Vt. element-of-set(U :: 0a,interior(Y :: 0a,X ,Vt)) −−> topological-space(X :: 0a,Vt))

810 & (∀ U Vt Y X . element-of-set(U :: 0a,interior(Y :: 0a,X ,Vt)) −−> subset-sets(Y :: 0a,X )) & (∀ Y X Vt U . element-of-set(U :: 0a,interior(Y :: 0a,X ,Vt)) −−> element-of-set(U :: 0a,f13 (Y :: 0a,X ,Vt,U ))) & (∀ X Vt U Y . element-of-set(U :: 0a,interior(Y :: 0a,X ,Vt)) −−> subset-sets(f13 (Y :: 0a,X ,Vt,U ),Y )) & (∀ Y U X Vt. element-of-set(U :: 0a,interior(Y :: 0a,X ,Vt)) −−> open(f13 (Y :: 0a,X ,Vt,U ),X ,Vt)) & (∀ U Y Uu13 X Vt. topological-space(X :: 0a,Vt)& subset-sets(Y :: 0a,X )& element-of-set(U :: 0a,Uu13 ) & subset-sets(Uu13 :: 0a,Y )& open(Uu13 :: 0a,X ,Vt) −−> element-of-set(U :: 0a,interior(Y :: 0a,X ,Vt))) & (∀ U Y X Vt. element-of-set(U :: 0a,closure(Y :: 0a,X ,Vt)) −−> topological-space(X :: 0a,Vt)) & (∀ U Vt Y X . element-of-set(U :: 0a,closure(Y :: 0a,X ,Vt)) −−> subset-sets(Y :: 0a,X )) & (∀ Y X Vt U V . element-of-set(U :: 0a,closure(Y :: 0a,X ,Vt)) & subset-sets(Y :: 0a,V ) & closed(V :: 0a,X ,Vt) −−> element-of-set(U :: 0a,V )) & (∀ Y X Vt U . topological-space(X :: 0a,Vt)& subset-sets(Y :: 0a,X ) −−> element-of-set(U :: 0a,closure(Y :: 0a,X ,Vt)) | subset-sets(Y :: 0a,f14 (Y :: 0a,X ,Vt,U ))) & (∀ Y U X Vt. topological-space(X :: 0a,Vt)& subset-sets(Y :: 0a,X ) −−> element-of-set(U :: 0a,closure(Y :: 0a,X ,Vt)) | closed(f14 (Y :: 0a,X ,Vt,U ),X ,Vt)) & (∀ Y X Vt U . topological-space(X :: 0a,Vt)& subset-sets(Y :: 0a,X )& element-of-set(U :: 0a,f14 (Y :: 0a,X ,Vt,U )) −−> element-of-set(U :: 0a,closure(Y :: 0a,X ,Vt))) & (∀ U Y X Vt. neighborhood(U :: 0a,Y ,X ,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ Y U X Vt. neighborhood(U :: 0a,Y ,X ,Vt) −−> open(U :: 0a,X ,Vt)) & (∀ X Vt Y U . neighborhood(U :: 0a,Y ,X ,Vt) −−> element-of-set(Y :: 0a,U )) & (∀ X Vt Y U . topological-space(X :: 0a,Vt)& open(U :: 0a,X ,Vt)& element-of-set(Y :: 0a,U ) −−> neighborhood(U :: 0a,Y ,X ,Vt)) & (∀ Z Y X Vt. limit-point(Z :: 0a,Y ,X ,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ Z Vt Y X . limit-point(Z :: 0a,Y ,X ,Vt) −−> subset-sets(Y :: 0a,X )) & (∀ Z X Vt U Y . limit-point(Z :: 0a,Y ,X ,Vt)& neighborhood(U :: 0a,Z ,X ,Vt) −−> element-of-set(f15 (Z :: 0a,Y ,X ,Vt,U ),intersection-of-sets(U :: 0a,Y ))) & (∀ Y X Vt U Z . ∼(limit-point(Z :: 0a,Y ,X ,Vt)& neighborhood(U :: 0a,Z ,X ,Vt)& eq-p(f15 (Z :: 0a,Y ,X ,Vt,U ),Z ))) & (∀ Y Z X Vt. topological-space(X :: 0a,Vt)& subset-sets(Y :: 0a,X ) −−> limit-point(Z :: 0a,Y ,X ,Vt) | neighborhood(f16 (Z :: 0a,Y ,X ,Vt),Z ,X ,Vt)) & (∀ X Vt Y Uu16 Z . topological-space(X :: 0a,Vt)& subset-sets(Y :: 0a,X )& element-of-set(Uu16 :: 0a,intersection-of-sets(f16 (Z :: 0a,Y ,X ,Vt),Y )) −−> limit-point(Z :: 0a,Y ,X ,Vt) | eq-p(Uu16 :: 0a,Z )) & (∀ U Y X Vt. element-of-set(U :: 0a,boundary(Y :: 0a,X ,Vt)) −−> topological-space(X :: 0a,Vt)) & (∀ U Y X Vt. element-of-set(U :: 0a,boundary(Y :: 0a,X ,Vt)) −−> element-of-set(U :: 0a,closure(Y :: 0a,X ,Vt))) & (∀ U Y X Vt. element-of-set(U :: 0a,boundary(Y :: 0a,X ,Vt)) −−> element-of-set(U :: 0a,closure(relative-complement-sets(Y :: 0a,X ),X ,Vt))) & (∀ U Y X Vt. topological-space(X :: 0a,Vt)& element-of-set(U :: 0a,closure(Y :: 0a,X ,Vt)) & element-of-set(U :: 0a,closure(relative-complement-sets(Y :: 0a,X ),X ,Vt)) −−> element-of-set(U :: 0a,boundary(Y :: 0a,X ,Vt))) & (∀ X Vt. hausdorff (X :: 0a,Vt) −−> topological-space(X :: 0a,Vt)) &

811 (∀ X-2 X-1 X Vt. hausdorff (X :: 0a,Vt)& element-of-set(X-1 :: 0a,X )& element-of-set(X-2 :: 0a,X ) −−> eq-p(X-1 :: 0a,X-2 ) | neighborhood(f17 (X :: 0a,Vt,X-1 ,X-2 ),X-1 ,X ,Vt)) & (∀ X-1 X-2 X Vt. hausdorff (X :: 0a,Vt)& element-of-set(X-1 :: 0a,X )& element-of-set(X-2 :: 0a,X ) −−> eq-p(X-1 :: 0a,X-2 ) | neighborhood(f18 (X :: 0a,Vt,X-1 ,X-2 ),X-2 ,X ,Vt)) & (∀ X Vt X-1 X-2 . hausdorff (X :: 0a,Vt)& element-of-set(X-1 :: 0a,X )& element-of-set(X-2 :: 0a,X ) −−> eq-p(X-1 :: 0a,X-2 ) | disjoint-s(f17 (X :: 0a,Vt,X-1 ,X-2 ),f18 (X :: 0a,Vt,X-1 ,X-2 ))) & (∀ Vt X . topological-space(X :: 0a,Vt) −−> hausdorff (X :: 0a,Vt) | element-of-set(f19 (X :: 0a,Vt),X )) & (∀ Vt X . topological-space(X :: 0a,Vt) −−> hausdorff (X :: 0a,Vt) | element-of-set(f20 (X :: 0a,Vt),X )) & (∀ X Vt. topological-space(X :: 0a,Vt)& eq-p(f19 (X :: 0a,Vt),f20 (X :: 0a,Vt)) −−> hausdorff (X :: 0a,Vt)) & (∀ X Vt Uu19 Uu20 . topological-space(X :: 0a,Vt)& neighborhood(Uu19 :: 0a,f19 (X :: 0a,Vt),X ,Vt) & neighborhood(Uu20 :: 0a,f20 (X :: 0a,Vt),X ,Vt)& disjoint-s(Uu19 :: 0a,Uu20 ) −−> hausdorff (X :: 0a,Vt)) & (∀ Va1 Va2 X Vt. separation(Va1 :: 0a,Va2 ,X ,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ Va2 X Vt Va1 . ∼(separation(Va1 :: 0a,Va2 ,X ,Vt)& equal-sets(Va1 :: 0a,empty-set))) & (∀ Va1 X Vt Va2 . ∼(separation(Va1 :: 0a,Va2 ,X ,Vt)& equal-sets(Va2 :: 0a,empty-set))) & (∀ Va2 X Va1 Vt. separation(Va1 :: 0a,Va2 ,X ,Vt) −−> element-of-collection(Va1 :: 0a,Vt)) & (∀ Va1 X Va2 Vt. separation(Va1 :: 0a,Va2 ,X ,Vt) −−> element-of-collection(Va2 :: 0a,Vt)) & (∀ Vt Va1 Va2 X . separation(Va1 :: 0a,Va2 ,X ,Vt) −−> equal-sets(union-of-sets(Va1 :: 0a,Va2 ),X )) & (∀ X Vt Va1 Va2 . separation(Va1 :: 0a,Va2 ,X ,Vt) −−> disjoint-s(Va1 :: 0a,Va2 )) & (∀ Vt X Va1 Va2 . topological-space(X :: 0a,Vt)& element-of-collection(Va1 :: 0a,Vt) & element-of-collection(Va2 :: 0a,Vt)& equal-sets(union-of-sets(Va1 :: 0a,Va2 ),X )& disjoint-s(Va1 :: 0a,Va2 ) −−> separation(Va1 :: 0a,Va2 ,X ,Vt) | equal-sets(Va1 :: 0a,empty-set) | equal-sets(Va2 :: 0a,empty-set)) & (∀ X Vt. connected-space(X :: 0a,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ Va1 Va2 X Vt. ∼(connected-space(X :: 0a,Vt)& separation(Va1 :: 0a,Va2 ,X ,Vt))) & (∀ X Vt. topological-space(X :: 0a,Vt) −−> connected-space(X :: 0a,Vt) | separa- tion(f21 (X :: 0a,Vt),f22 (X :: 0a,Vt),X ,Vt)) & (∀ Va X Vt. connected-set(Va:: 0a,X ,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ Vt Va X . connected-set(Va:: 0a,X ,Vt) −−> subset-sets(Va:: 0a,X )) & (∀ X Vt Va. connected-set(Va:: 0a,X ,Vt) −−> connected-space(Va:: 0a,subspace-topology(X :: 0a,Vt,Va))) & (∀ X Vt Va. topological-space(X :: 0a,Vt)& subset-sets(Va:: 0a,X )& connected-space(Va:: 0a,subspace-topology(X :: 0a,Vt,Va)) −−> connected-set(Va:: 0a,X ,Vt)) & (∀ Vf X Vt. open-covering(Vf :: 0a,X ,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ X Vf Vt. open-covering(Vf :: 0a,X ,Vt) −−> subset-collections(Vf :: 0a,Vt)) & (∀ Vt Vf X . open-covering(Vf :: 0a,X ,Vt) −−> equal-sets(union-of-members(Vf ),X )) &

812 (∀ Vt Vf X . topological-space(X :: 0a,Vt)& subset-collections(Vf :: 0a,Vt)& equal-sets(union-of-members(Vf ),X ) −−> open-covering(Vf :: 0a,X ,Vt)) & (∀ X Vt. compact-space(X :: 0a,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ X Vt Vf1 . compact-space(X :: 0a,Vt)& open-covering(Vf1 :: 0a,X ,Vt) −−> fi- nite 0(f23 (X :: 0a,Vt,Vf1 ))) & (∀ X Vt Vf1 . compact-space(X :: 0a,Vt)& open-covering(Vf1 :: 0a,X ,Vt) −−> subset-collections(f23 (X :: 0a,Vt,Vf1 ),Vf1 )) & (∀ Vf1 X Vt. compact-space(X :: 0a,Vt)& open-covering(Vf1 :: 0a,X ,Vt) −−> open-covering(f23 (X :: 0a,Vt,Vf1 ),X ,Vt)) & (∀ X Vt. topological-space(X :: 0a,Vt) −−> compact-space(X :: 0a,Vt) | open-covering(f24 (X :: 0a,Vt),X ,Vt)) & (∀ Uu24 X Vt. topological-space(X :: 0a,Vt)& finite 0(Uu24 )& subset-collections(Uu24 :: 0a,f24 (X :: 0a,Vt)) & open-covering(Uu24 :: 0a,X ,Vt) −−> compact-space(X :: 0a,Vt)) & (∀ Va X Vt. compact-set(Va:: 0a,X ,Vt) −−> topological-space(X :: 0a,Vt)) & (∀ Vt Va X . compact-set(Va:: 0a,X ,Vt) −−> subset-sets(Va:: 0a,X )) & (∀ X Vt Va. compact-set(Va:: 0a,X ,Vt) −−> compact-space(Va:: 0a,subspace-topology(X :: 0a,Vt,Va))) & (∀ X Vt Va. topological-space(X :: 0a,Vt)& subset-sets(Va:: 0a,X )& compact-space(Va:: 0a,subspace-topology(X :: 0a,Vt,Va)) −−> compact-set(Va:: 0a,X ,Vt)) & (basis(cx:: 0a,f )) & (∀ U . element-of-collection(U :: 0a,top-of-basis(f ))) & (∀ V . element-of-collection(V :: 0a,top-of-basis(f ))) & (∀ UV . ∼element-of-collection(intersection-of-sets(U :: 0a,V ),top-of-basis(f ))) −−> False by meson

lemma TOP004-2 : (∀ U Uu1 Vf . element-of-set(U :: 0a,Uu1 )& element-of-collection(Uu1 :: 0a,Vf ) −−> element-of-set(U :: 0a,union-of-members(Vf ))) & (∀ Vf X . basis(X :: 0a,Vf ) −−> equal-sets(union-of-members(Vf ),X )) & (∀ X Vf Y Vb1 Vb2 . basis(X :: 0a,Vf )& element-of-set(Y :: 0a,X )& element-of-collection(Vb1 :: 0a,Vf ) & element-of-collection(Vb2 :: 0a,Vf )& element-of-set(Y :: 0a,intersection-of-sets(Vb1 :: 0a,Vb2 )) −−> element-of-set(Y :: 0a,f6 (X :: 0a,Vf ,Y ,Vb1 ,Vb2 ))) & (∀ X Y Vb1 Vb2 Vf . basis(X :: 0a,Vf )& element-of-set(Y :: 0a,X )& element-of-collection(Vb1 :: 0a,Vf ) & element-of-collection(Vb2 :: 0a,Vf )& element-of-set(Y :: 0a,intersection-of-sets(Vb1 :: 0a,Vb2 )) −−> element-of-collection(f6 (X :: 0a,Vf ,Y ,Vb1 ,Vb2 ),Vf )) & (∀ X Vf Y Vb1 Vb2 . basis(X :: 0a,Vf )& element-of-set(Y :: 0a,X )& element-of-collection(Vb1 :: 0a,Vf ) & element-of-collection(Vb2 :: 0a,Vf )& element-of-set(Y :: 0a,intersection-of-sets(Vb1 :: 0a,Vb2 )) −−> subset-sets(f6 (X :: 0a,Vf ,Y ,Vb1 ,Vb2 ),intersection-of-sets(Vb1 :: 0a,Vb2 ))) & (∀ Vf U X . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> element-of-set(X :: 0a,f10 (Vf :: 0a,U ,X ))) & (∀ U X Vf . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> element-of-collection(f10 (Vf :: 0a,U ,X ),Vf )) & (∀ Vf X U . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> subset-sets(f10 (Vf :: 0a,U ,X ),U )) & (∀ Vf U . element-of-collection(U :: 0a,top-of-basis(Vf )) | element-of-set(f11 (Vf :: 0a,U ),U )) &

813 (∀ Vf Uu11 U . element-of-set(f11 (Vf :: 0a,U ),Uu11 )& element-of-collection(Uu11 :: 0a,Vf ) & subset-sets(Uu11 :: 0a,U ) −−> element-of-collection(U :: 0a,top-of-basis(Vf ))) & (∀ YXZ . subset-sets(X :: 0a,Y )& subset-sets(Y :: 0a,Z ) −−> subset-sets(X :: 0a,Z )) & (∀ YZX . element-of-set(Z :: 0a,intersection-of-sets(X :: 0a,Y )) −−> element-of-set(Z :: 0a,X )) & (∀ XZY . element-of-set(Z :: 0a,intersection-of-sets(X :: 0a,Y )) −−> element-of-set(Z :: 0a,Y )) & (∀ XZY . element-of-set(Z :: 0a,X )& element-of-set(Z :: 0a,Y ) −−> element-of-set(Z :: 0a,intersection-of-sets(X :: 0a,Y ))) & (∀ XUYV . subset-sets(X :: 0a,Y )& subset-sets(U :: 0a,V ) −−> subset-sets(intersection-of-sets(X :: 0a,U ),intersection-of-sets(Y :: 0a,V ))) & (∀ XZY . equal-sets(X :: 0a,Y )& element-of-set(Z :: 0a,X ) −−> element-of-set(Z :: 0a,Y )) & (∀ YX . equal-sets(intersection-of-sets(X :: 0a,Y ),intersection-of-sets(Y :: 0a,X ))) & (basis(cx:: 0a,f )) & (∀ U . element-of-collection(U :: 0a,top-of-basis(f ))) & (∀ V . element-of-collection(V :: 0a,top-of-basis(f ))) & (∀ UV . ∼element-of-collection(intersection-of-sets(U :: 0a,V ),top-of-basis(f ))) −−> False by meson lemma TOP005-2 : (∀ Vf U . element-of-set(U :: 0a,union-of-members(Vf )) −−> element-of-set(U :: 0a,f1 (Vf :: 0a,U ))) & (∀ U Vf . element-of-set(U :: 0a,union-of-members(Vf )) −−> element-of-collection(f1 (Vf :: 0a,U ),Vf )) & (∀ Vf U X . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> element-of-set(X :: 0a,f10 (Vf :: 0a,U ,X ))) & (∀ U X Vf . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> element-of-collection(f10 (Vf :: 0a,U ,X ),Vf )) & (∀ Vf X U . element-of-collection(U :: 0a,top-of-basis(Vf )) & element-of-set(X :: 0a,U ) −−> subset-sets(f10 (Vf :: 0a,U ,X ),U )) & (∀ Vf U . element-of-collection(U :: 0a,top-of-basis(Vf )) | element-of-set(f11 (Vf :: 0a,U ),U )) & (∀ Vf Uu11 U . element-of-set(f11 (Vf :: 0a,U ),Uu11 )& element-of-collection(Uu11 :: 0a,Vf ) & subset-sets(Uu11 :: 0a,U ) −−> element-of-collection(U :: 0a,top-of-basis(Vf ))) & (∀ XUY . element-of-set(U :: 0a,X ) −−> subset-sets(X :: 0a,Y ) | element-of-set(U :: 0a,Y )) & (∀ YXZ . subset-sets(X :: 0a,Y )& element-of-collection(Y :: 0a,Z ) −−> subset-sets(X :: 0a,union-of-members(Z ))) & (∀ XUY . subset-collections(X :: 0a,Y )& element-of-collection(U :: 0a,X ) −−> element-of-collection(U :: 0a,Y )) & (subset-collections(g:: 0a,top-of-basis(f ))) & (∼element-of-collection(union-of-members(g),top-of-basis(f ))) −−> False oops end

814 References

[1] K. McMillan. Lecture notes on verification of digital and hybrid systems. NATO summer school, http://www-cad.eecs.berkeley.edu/∼kenmcmil/ tutorial/toc.html.

[2] K. McMillan. Symbolic Model Checking: an approach to the state explo- sion problem. PhD thesis, Carnegie Mellon University, 1992.

815