src/HOL/Isar_examples/Fibonacci.thy
author wenzelm
Tue, 22 Feb 2000 21:50:02 +0100
changeset 8281 188e2924433e
parent 8052 6ae3ca78a558
child 8304 e132d147374b
permissions -rw-r--r--
tuned "induct" syntax;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8051
wenzelm
parents:
diff changeset
     1
(*  Title:      HOL/Isar_examples/Fibonacci.thy
wenzelm
parents:
diff changeset
     2
    ID:         $Id$
wenzelm
parents:
diff changeset
     3
    Author:     Gertrud Bauer
wenzelm
parents:
diff changeset
     4
    Copyright   1999 Technische Universitaet Muenchen
wenzelm
parents:
diff changeset
     5
wenzelm
parents:
diff changeset
     6
The Fibonacci function.  Demonstrates the use of recdef.  Original
wenzelm
parents:
diff changeset
     7
tactic script by Lawrence C Paulson.
wenzelm
parents:
diff changeset
     8
wenzelm
parents:
diff changeset
     9
Fibonacci numbers: proofs of laws taken from
wenzelm
parents:
diff changeset
    10
wenzelm
parents:
diff changeset
    11
  R. L. Graham, D. E. Knuth, O. Patashnik.
wenzelm
parents:
diff changeset
    12
  Concrete Mathematics.
wenzelm
parents:
diff changeset
    13
  (Addison-Wesley, 1989)
wenzelm
parents:
diff changeset
    14
*)
wenzelm
parents:
diff changeset
    15
wenzelm
parents:
diff changeset
    16
header {* Fib and Gcd commute *};
wenzelm
parents:
diff changeset
    17
wenzelm
parents:
diff changeset
    18
theory Fibonacci = Primes:;
wenzelm
parents:
diff changeset
    19
wenzelm
parents:
diff changeset
    20
text_raw {*
wenzelm
parents:
diff changeset
    21
 \footnote{Isar version by Gertrud Bauer.  Original tactic script by
8052
wenzelm
parents: 8051
diff changeset
    22
 Larry Paulson.  A few proofs of laws taken from
8051
wenzelm
parents:
diff changeset
    23
 \cite{Concrete-Math}.}
wenzelm
parents:
diff changeset
    24
*};
wenzelm
parents:
diff changeset
    25
wenzelm
parents:
diff changeset
    26
wenzelm
parents:
diff changeset
    27
subsection {* Fibonacci numbers *};
wenzelm
parents:
diff changeset
    28
wenzelm
parents:
diff changeset
    29
consts fib :: "nat => nat";
wenzelm
parents:
diff changeset
    30
recdef fib less_than
wenzelm
parents:
diff changeset
    31
 "fib 0 = 0"
wenzelm
parents:
diff changeset
    32
 "fib 1 = 1"
wenzelm
parents:
diff changeset
    33
 "fib (Suc (Suc x)) = (fib x + fib (Suc x))";
wenzelm
parents:
diff changeset
    34
wenzelm
parents:
diff changeset
    35
lemmas [simp] = fib.rules;
wenzelm
parents:
diff changeset
    36
wenzelm
parents:
diff changeset
    37
lemma [simp]: "0 < fib (Suc n)";
8281
188e2924433e tuned "induct" syntax;
wenzelm
parents: 8052
diff changeset
    38
  by (induct n in function: fib) (simp+);
8051
wenzelm
parents:
diff changeset
    39
wenzelm
parents:
diff changeset
    40
wenzelm
parents:
diff changeset
    41
text {* Alternative induction rule. *};
wenzelm
parents:
diff changeset
    42
wenzelm
parents:
diff changeset
    43
theorem fib_induct: 
wenzelm
parents:
diff changeset
    44
"[| P 0; P 1; !!n. [| P (n + 1); P n |] ==> P (n + 2) |] ==> P n";
wenzelm
parents:
diff changeset
    45
  by (induct function: fib, simp+);
wenzelm
parents:
diff changeset
    46
wenzelm
parents:
diff changeset
    47
wenzelm
parents:
diff changeset
    48
wenzelm
parents:
diff changeset
    49
subsection {* Fib and gcd commute *};
wenzelm
parents:
diff changeset
    50
wenzelm
parents:
diff changeset
    51
text {* A few laws taken from \cite{Concrete-Math}. *};
wenzelm
parents:
diff changeset
    52
wenzelm
parents:
diff changeset
    53
lemma fib_add: 
wenzelm
parents:
diff changeset
    54
  "fib (n + k + 1) = fib (k + 1) * fib (n + 1) + fib k * fib n"
wenzelm
parents:
diff changeset
    55
  (is "?P n");
8052
wenzelm
parents: 8051
diff changeset
    56
proof (rule fib_induct [of ?P n]) -- {* see \cite[page 280]{Concrete-Math} *};
8051
wenzelm
parents:
diff changeset
    57
  show "?P 0"; by simp;
wenzelm
parents:
diff changeset
    58
  show "?P 1"; by simp;
wenzelm
parents:
diff changeset
    59
  fix n;
wenzelm
parents:
diff changeset
    60
  have "fib (n + 2 + k + 1)
wenzelm
parents:
diff changeset
    61
    = fib (n + k + 1) + fib (n + 1 + k + 1)"; by simp;
wenzelm
parents:
diff changeset
    62
  also; assume "fib (n + k + 1)
wenzelm
parents:
diff changeset
    63
    = fib (k + 1) * fib (n + 1) + fib k * fib n"
wenzelm
parents:
diff changeset
    64
      (is " _ = ?R1");
wenzelm
parents:
diff changeset
    65
  also; assume "fib (n + 1 + k + 1)
wenzelm
parents:
diff changeset
    66
    = fib (k + 1) * fib (n + 1 + 1) + fib k * fib (n + 1)"
wenzelm
parents:
diff changeset
    67
      (is " _ = ?R2");
wenzelm
parents:
diff changeset
    68
  also; have "?R1 + ?R2
wenzelm
parents:
diff changeset
    69
    = fib (k + 1) * fib (n + 2 + 1) + fib k * fib (n + 2)";
wenzelm
parents:
diff changeset
    70
    by (simp add: add_mult_distrib2);
wenzelm
parents:
diff changeset
    71
  finally; show "?P (n + 2)"; .;
wenzelm
parents:
diff changeset
    72
qed;
wenzelm
parents:
diff changeset
    73
wenzelm
parents:
diff changeset
    74
lemma gcd_fib_Suc_eq_1: "gcd (fib n, fib (n + 1)) = 1" (is "?P n");
wenzelm
parents:
diff changeset
    75
proof (rule fib_induct [of ?P n]); 
wenzelm
parents:
diff changeset
    76
  show "?P 0"; by simp;
wenzelm
parents:
diff changeset
    77
  show "?P 1"; by simp;
wenzelm
parents:
diff changeset
    78
  fix n; 
wenzelm
parents:
diff changeset
    79
  have "fib (n + 2 + 1) = fib (n + 1) + fib (n + 2)"; 
wenzelm
parents:
diff changeset
    80
    by simp;
wenzelm
parents:
diff changeset
    81
  also; have "gcd (fib (n + 2), ...) = gcd (fib (n + 2), fib (n + 1))"; 
wenzelm
parents:
diff changeset
    82
    by (simp add: gcd_add2);
wenzelm
parents:
diff changeset
    83
  also; have "... = gcd (fib (n + 1), fib (n + 1 + 1))";
wenzelm
parents:
diff changeset
    84
    by (simp add: gcd_commute);
wenzelm
parents:
diff changeset
    85
  also; assume "... = 1";
wenzelm
parents:
diff changeset
    86
  finally; show "?P (n + 2)"; .;
wenzelm
parents:
diff changeset
    87
qed;
wenzelm
parents:
diff changeset
    88
wenzelm
parents:
diff changeset
    89
lemma gcd_mult_add: "0 < n ==> gcd (n * k + m, n) = gcd (m, n)";
wenzelm
parents:
diff changeset
    90
proof -;
wenzelm
parents:
diff changeset
    91
  assume "0 < n";
wenzelm
parents:
diff changeset
    92
  hence "gcd (n * k + m, n) = gcd (n, m mod n)"; 
wenzelm
parents:
diff changeset
    93
    by (simp add: gcd_non_0 add_commute);
wenzelm
parents:
diff changeset
    94
  also; have "... = gcd (m, n)"; by (simp! add: gcd_non_0);
wenzelm
parents:
diff changeset
    95
  finally; show ?thesis; .;
wenzelm
parents:
diff changeset
    96
qed;
wenzelm
parents:
diff changeset
    97
wenzelm
parents:
diff changeset
    98
lemma gcd_fib_add: "gcd (fib m, fib (n + m)) = gcd (fib m, fib n)"; 
wenzelm
parents:
diff changeset
    99
proof (rule nat.exhaust [of m]);
wenzelm
parents:
diff changeset
   100
  assume "m = 0";
wenzelm
parents:
diff changeset
   101
  thus "gcd (fib m, fib (n + m)) = gcd (fib m, fib n)"; by simp;
wenzelm
parents:
diff changeset
   102
next;
wenzelm
parents:
diff changeset
   103
  fix k; assume "m = Suc k"; 
wenzelm
parents:
diff changeset
   104
  hence "gcd (fib m, fib (n + m)) = gcd (fib (n + k + 1), fib (k + 1))";
wenzelm
parents:
diff changeset
   105
    by (simp add: gcd_commute);
wenzelm
parents:
diff changeset
   106
  also; have "fib (n + k + 1) 
wenzelm
parents:
diff changeset
   107
    = fib (k + 1) * fib (n + 1) + fib k * fib n";
wenzelm
parents:
diff changeset
   108
    by (rule fib_add);
wenzelm
parents:
diff changeset
   109
  also; have "gcd (..., fib (k + 1)) = gcd (fib k * fib n, fib (k + 1))"; 
wenzelm
parents:
diff changeset
   110
    by (simp add: gcd_mult_add);
wenzelm
parents:
diff changeset
   111
  also; have "... = gcd (fib n, fib (k + 1))"; 
wenzelm
parents:
diff changeset
   112
    by (simp only: gcd_fib_Suc_eq_1 gcd_mult_cancel);
wenzelm
parents:
diff changeset
   113
  also; have "... = gcd (fib m, fib n)"; 
wenzelm
parents:
diff changeset
   114
    by (simp! add: gcd_commute);
wenzelm
parents:
diff changeset
   115
  finally; show ?thesis; .;
wenzelm
parents:
diff changeset
   116
qed;
wenzelm
parents:
diff changeset
   117
wenzelm
parents:
diff changeset
   118
lemma gcd_fib_diff: 
wenzelm
parents:
diff changeset
   119
  "m <= n ==> gcd (fib m, fib (n - m)) = gcd (fib m, fib n)";
wenzelm
parents:
diff changeset
   120
proof -; 
wenzelm
parents:
diff changeset
   121
  assume "m <= n";
wenzelm
parents:
diff changeset
   122
  have "gcd (fib m, fib (n - m)) = gcd (fib m, fib (n - m + m))"; 
wenzelm
parents:
diff changeset
   123
    by (simp add: gcd_fib_add);
wenzelm
parents:
diff changeset
   124
  also; have "n - m + m = n"; by (simp!); 
wenzelm
parents:
diff changeset
   125
  finally; show ?thesis; .;
wenzelm
parents:
diff changeset
   126
qed;
wenzelm
parents:
diff changeset
   127
wenzelm
parents:
diff changeset
   128
lemma if_cases: 
wenzelm
parents:
diff changeset
   129
  "[| Q ==> P x; ~ Q ==> P y |] ==> P (if Q then x else y)"; by simp;
wenzelm
parents:
diff changeset
   130
wenzelm
parents:
diff changeset
   131
lemma gcd_fib_mod: 
wenzelm
parents:
diff changeset
   132
  "0 < m ==> gcd (fib m, fib (n mod m)) = gcd (fib m, fib n)";
wenzelm
parents:
diff changeset
   133
proof (rule less_induct [of _ n]);
wenzelm
parents:
diff changeset
   134
  fix n; 
wenzelm
parents:
diff changeset
   135
  assume m: "0 < m"
wenzelm
parents:
diff changeset
   136
  and hyp: "ALL ma. ma < n 
wenzelm
parents:
diff changeset
   137
           --> gcd (fib m, fib (ma mod m)) = gcd (fib m, fib ma)";
wenzelm
parents:
diff changeset
   138
  have "n mod m = (if n < m then n else (n - m) mod m)";
wenzelm
parents:
diff changeset
   139
    by (rule mod_if);
wenzelm
parents:
diff changeset
   140
  also; have "gcd (fib m, fib ...) = gcd (fib m, fib n)";
wenzelm
parents:
diff changeset
   141
  proof (rule if_cases);
wenzelm
parents:
diff changeset
   142
    assume "~ n < m"; hence m_le_n: "m <= n"; by simp;
wenzelm
parents:
diff changeset
   143
    have "n - m < n"; by (simp! add: diff_less);
wenzelm
parents:
diff changeset
   144
    with hyp; have "gcd (fib m, fib ((n - m) mod m))
wenzelm
parents:
diff changeset
   145
       = gcd (fib m, fib (n - m))"; by simp;
wenzelm
parents:
diff changeset
   146
    also; from m_le_n; have "... = gcd (fib m, fib n)"; 
wenzelm
parents:
diff changeset
   147
      by (rule gcd_fib_diff);
wenzelm
parents:
diff changeset
   148
    finally; show "gcd (fib m, fib ((n - m) mod m)) = gcd (fib m, fib n)"; .;
wenzelm
parents:
diff changeset
   149
  qed simp;
wenzelm
parents:
diff changeset
   150
  finally; show "gcd (fib m, fib (n mod m)) = gcd (fib m, fib n)"; .;
wenzelm
parents:
diff changeset
   151
qed;
wenzelm
parents:
diff changeset
   152
wenzelm
parents:
diff changeset
   153
wenzelm
parents:
diff changeset
   154
theorem fib_gcd: "fib (gcd (m, n)) = gcd (fib m, fib n)" (is "?P m n");
wenzelm
parents:
diff changeset
   155
proof (rule gcd_induct [of ?P m n]);
wenzelm
parents:
diff changeset
   156
  fix m; show "fib (gcd (m, 0)) = gcd (fib m, fib 0)"; by simp;
wenzelm
parents:
diff changeset
   157
  fix n; assume n: "0 < n";
wenzelm
parents:
diff changeset
   158
  hence "gcd (m, n) = gcd (n, m mod n)"; by (rule gcd_non_0);
wenzelm
parents:
diff changeset
   159
  also; assume hyp: "fib ... = gcd (fib n, fib (m mod n))";
wenzelm
parents:
diff changeset
   160
  also; from n; have "... = gcd (fib n, fib m)"; by (rule gcd_fib_mod);
wenzelm
parents:
diff changeset
   161
  also; have "... = gcd (fib m, fib n)"; by (rule gcd_commute);
wenzelm
parents:
diff changeset
   162
  finally; show "fib (gcd (m, n)) = gcd (fib m, fib n)"; .;
wenzelm
parents:
diff changeset
   163
qed;
wenzelm
parents:
diff changeset
   164
wenzelm
parents:
diff changeset
   165
end;