src/HOL/Predicate_Compile_Examples/Predicate_Compile_Quickcheck_Examples.thy
author haftmann
Fri Oct 10 19:55:32 2014 +0200 (2014-10-10)
changeset 58646 cd63a4b12a33
parent 58310 91ea607a34d8
child 61140 78ece168f5b5
child 61142 6d29eb7c5fb2
permissions -rw-r--r--
specialized specification: avoid trivial instances
     1 theory Predicate_Compile_Quickcheck_Examples
     2 imports "~~/src/HOL/Library/Predicate_Compile_Quickcheck"
     3 begin
     4 
     5 section {* Sets *}
     6 
     7 lemma "x \<in> {(1::nat)} ==> False"
     8 quickcheck[generator=predicate_compile_wo_ff, iterations=10]
     9 oops
    10 
    11 lemma "x \<in> {Suc 0, Suc (Suc 0)} ==> x \<noteq> Suc 0"
    12 quickcheck[generator=predicate_compile_wo_ff]
    13 oops
    14 
    15 lemma "x \<in> {Suc 0, Suc (Suc 0)} ==> x = Suc 0"
    16 quickcheck[generator=predicate_compile_wo_ff]
    17 oops
    18  
    19 lemma "x \<in> {Suc 0, Suc (Suc 0)} ==> x <= Suc 0"
    20 quickcheck[generator=predicate_compile_wo_ff]
    21 oops
    22 
    23 section {* Numerals *}
    24 
    25 lemma
    26   "x \<in> {1, 2, (3::nat)} ==> x = 1 \<or> x = 2"
    27 quickcheck[generator=predicate_compile_wo_ff]
    28 oops
    29 
    30 lemma "x \<in> {1, 2, (3::nat)} ==> x < 3"
    31 quickcheck[generator=predicate_compile_wo_ff]
    32 oops
    33 
    34 lemma
    35   "x \<in> {1, 2} \<union> {3, 4} ==> x = (1::nat) \<or> x = (2::nat)"
    36 quickcheck[generator=predicate_compile_wo_ff]
    37 oops
    38 
    39 section {* Equivalences *}
    40 
    41 inductive is_ten :: "nat => bool"
    42 where
    43   "is_ten 10"
    44 
    45 inductive is_eleven :: "nat => bool"
    46 where
    47   "is_eleven 11"
    48 
    49 lemma
    50   "is_ten x = is_eleven x"
    51 quickcheck[tester = predicate_compile_wo_ff, iterations = 1, size = 1, expect = counterexample]
    52 oops
    53 
    54 section {* Context Free Grammar *}
    55 
    56 datatype alphabet = a | b
    57 
    58 inductive_set S\<^sub>1 and A\<^sub>1 and B\<^sub>1 where
    59   "[] \<in> S\<^sub>1"
    60 | "w \<in> A\<^sub>1 \<Longrightarrow> b # w \<in> S\<^sub>1"
    61 | "w \<in> B\<^sub>1 \<Longrightarrow> a # w \<in> S\<^sub>1"
    62 | "w \<in> S\<^sub>1 \<Longrightarrow> a # w \<in> A\<^sub>1"
    63 | "w \<in> S\<^sub>1 \<Longrightarrow> b # w \<in> S\<^sub>1"
    64 | "\<lbrakk>v \<in> B\<^sub>1; v \<in> B\<^sub>1\<rbrakk> \<Longrightarrow> a # v @ w \<in> B\<^sub>1"
    65 
    66 lemma
    67   "w \<in> S\<^sub>1 \<Longrightarrow> w = []"
    68 quickcheck[tester = predicate_compile_ff_nofs, iterations=1]
    69 oops
    70 
    71 theorem S\<^sub>1_sound:
    72 "w \<in> S\<^sub>1 \<Longrightarrow> length [x \<leftarrow> w. x = a] = length [x \<leftarrow> w. x = b]"
    73 quickcheck[generator=predicate_compile_ff_nofs, size=15]
    74 oops
    75 
    76 
    77 inductive_set S\<^sub>2 and A\<^sub>2 and B\<^sub>2 where
    78   "[] \<in> S\<^sub>2"
    79 | "w \<in> A\<^sub>2 \<Longrightarrow> b # w \<in> S\<^sub>2"
    80 | "w \<in> B\<^sub>2 \<Longrightarrow> a # w \<in> S\<^sub>2"
    81 | "w \<in> S\<^sub>2 \<Longrightarrow> a # w \<in> A\<^sub>2"
    82 | "w \<in> S\<^sub>2 \<Longrightarrow> b # w \<in> B\<^sub>2"
    83 | "\<lbrakk>v \<in> B\<^sub>2; v \<in> B\<^sub>2\<rbrakk> \<Longrightarrow> a # v @ w \<in> B\<^sub>2"
    84 (*
    85 code_pred [random_dseq inductify] S\<^sub>2 .
    86 thm S\<^sub>2.random_dseq_equation
    87 thm A\<^sub>2.random_dseq_equation
    88 thm B\<^sub>2.random_dseq_equation
    89 
    90 values [random_dseq 1, 2, 8] 10 "{x. S\<^sub>2 x}"
    91 
    92 lemma "w \<in> S\<^sub>2 ==> w \<noteq> [] ==> w \<noteq> [b, a] ==> w \<in> {}"
    93 quickcheck[generator=predicate_compile, size=8]
    94 oops
    95 
    96 lemma "[x <- w. x = a] = []"
    97 quickcheck[generator=predicate_compile]
    98 oops
    99 
   100 declare list.size(3,4)[code_pred_def]
   101 
   102 (*
   103 lemma "length ([x \<leftarrow> w. x = a]) = (0::nat)"
   104 quickcheck[generator=predicate_compile]
   105 oops
   106 *)
   107 
   108 lemma
   109 "w \<in> S\<^sub>2 ==> length [x \<leftarrow> w. x = a] <= Suc (Suc 0)"
   110 quickcheck[generator=predicate_compile, size = 10, iterations = 1]
   111 oops
   112 *)
   113 theorem S\<^sub>2_sound:
   114 "w \<in> S\<^sub>2 \<longrightarrow> length [x \<leftarrow> w. x = a] = length [x \<leftarrow> w. x = b]"
   115 quickcheck[generator=predicate_compile_ff_nofs, size=5, iterations=10]
   116 oops
   117 
   118 inductive_set S\<^sub>3 and A\<^sub>3 and B\<^sub>3 where
   119   "[] \<in> S\<^sub>3"
   120 | "w \<in> A\<^sub>3 \<Longrightarrow> b # w \<in> S\<^sub>3"
   121 | "w \<in> B\<^sub>3 \<Longrightarrow> a # w \<in> S\<^sub>3"
   122 | "w \<in> S\<^sub>3 \<Longrightarrow> a # w \<in> A\<^sub>3"
   123 | "w \<in> S\<^sub>3 \<Longrightarrow> b # w \<in> B\<^sub>3"
   124 | "\<lbrakk>v \<in> B\<^sub>3; w \<in> B\<^sub>3\<rbrakk> \<Longrightarrow> a # v @ w \<in> B\<^sub>3"
   125 
   126 code_pred [inductify, skip_proof] S\<^sub>3 .
   127 thm S\<^sub>3.equation
   128 (*
   129 values 10 "{x. S\<^sub>3 x}"
   130 *)
   131 
   132 
   133 lemma S\<^sub>3_sound:
   134 "w \<in> S\<^sub>3 \<longrightarrow> length [x \<leftarrow> w. x = a] = length [x \<leftarrow> w. x = b]"
   135 quickcheck[generator=predicate_compile_ff_fs, size=10, iterations=10]
   136 oops
   137 
   138 lemma "\<not> (length w > 2) \<or> \<not> (length [x \<leftarrow> w. x = a] = length [x \<leftarrow> w. x = b])"
   139 quickcheck[size=10, tester = predicate_compile_ff_fs]
   140 oops
   141 
   142 theorem S\<^sub>3_complete:
   143 "length [x \<leftarrow> w. x = a] = length [x \<leftarrow> w. b = x] \<longrightarrow> w \<in> S\<^sub>3"
   144 (*quickcheck[generator=SML]*)
   145 quickcheck[generator=predicate_compile_ff_fs, size=10, iterations=100]
   146 oops
   147 
   148 
   149 inductive_set S\<^sub>4 and A\<^sub>4 and B\<^sub>4 where
   150   "[] \<in> S\<^sub>4"
   151 | "w \<in> A\<^sub>4 \<Longrightarrow> b # w \<in> S\<^sub>4"
   152 | "w \<in> B\<^sub>4 \<Longrightarrow> a # w \<in> S\<^sub>4"
   153 | "w \<in> S\<^sub>4 \<Longrightarrow> a # w \<in> A\<^sub>4"
   154 | "\<lbrakk>v \<in> A\<^sub>4; w \<in> A\<^sub>4\<rbrakk> \<Longrightarrow> b # v @ w \<in> A\<^sub>4"
   155 | "w \<in> S\<^sub>4 \<Longrightarrow> b # w \<in> B\<^sub>4"
   156 | "\<lbrakk>v \<in> B\<^sub>4; w \<in> B\<^sub>4\<rbrakk> \<Longrightarrow> a # v @ w \<in> B\<^sub>4"
   157 
   158 theorem S\<^sub>4_sound:
   159 "w \<in> S\<^sub>4 \<longrightarrow> length [x \<leftarrow> w. x = a] = length [x \<leftarrow> w. x = b]"
   160 quickcheck[tester = predicate_compile_ff_nofs, size=5, iterations=1]
   161 oops
   162 
   163 theorem S\<^sub>4_complete:
   164 "length [x \<leftarrow> w. x = a] = length [x \<leftarrow> w. x = b] \<longrightarrow> w \<in> S\<^sub>4"
   165 quickcheck[tester = predicate_compile_ff_nofs, size=5, iterations=1]
   166 oops
   167 
   168 hide_const a b
   169 
   170 subsection {* Lexicographic order *}
   171 (* TODO *)
   172 (*
   173 lemma
   174   "(u, v) : lexord r ==> (x @ u, y @ v) : lexord r"
   175 oops
   176 *)
   177 subsection {* IMP *}
   178 
   179 type_synonym var = nat
   180 type_synonym state = "int list"
   181 
   182 datatype com =
   183   Skip |
   184   Ass var "int" |
   185   Seq com com |
   186   IF "state list" com com |
   187   While "state list" com
   188 
   189 inductive exec :: "com => state => state => bool" where
   190   "exec Skip s s" |
   191   "exec (Ass x e) s (s[x := e])" |
   192   "exec c1 s1 s2 ==> exec c2 s2 s3 ==> exec (Seq c1 c2) s1 s3" |
   193   "s \<in> set b ==> exec c1 s t ==> exec (IF b c1 c2) s t" |
   194   "s \<notin> set b ==> exec c2 s t ==> exec (IF b c1 c2) s t" |
   195   "s \<notin> set b ==> exec (While b c) s s" |
   196   "s1 \<in> set b ==> exec c s1 s2 ==> exec (While b c) s2 s3 ==> exec (While b c) s1 s3"
   197 
   198 code_pred [random_dseq] exec .
   199 
   200 values [random_dseq 1, 2, 3] 10 "{(c, s, s'). exec c s s'}"
   201 
   202 lemma
   203   "exec c s s' ==> exec (Seq c c) s s'"
   204   quickcheck[tester = predicate_compile_wo_ff, size=2, iterations=20, expect = counterexample]
   205 oops
   206 
   207 subsection {* Lambda *}
   208 
   209 datatype type =
   210     Atom nat
   211   | Fun type type    (infixr "\<Rightarrow>" 200)
   212 
   213 datatype dB =
   214     Var nat
   215   | App dB dB (infixl "\<degree>" 200)
   216   | Abs type dB
   217 
   218 primrec
   219   nth_el :: "'a list \<Rightarrow> nat \<Rightarrow> 'a option" ("_\<langle>_\<rangle>" [90, 0] 91)
   220 where
   221   "[]\<langle>i\<rangle> = None"
   222 | "(x # xs)\<langle>i\<rangle> = (case i of 0 \<Rightarrow> Some x | Suc j \<Rightarrow> xs \<langle>j\<rangle>)"
   223 
   224 inductive nth_el' :: "'a list \<Rightarrow> nat \<Rightarrow> 'a \<Rightarrow> bool"
   225 where
   226   "nth_el' (x # xs) 0 x"
   227 | "nth_el' xs i y \<Longrightarrow> nth_el' (x # xs) (Suc i) y"
   228 
   229 inductive typing :: "type list \<Rightarrow> dB \<Rightarrow> type \<Rightarrow> bool"  ("_ \<turnstile> _ : _" [50, 50, 50] 50)
   230   where
   231     Var [intro!]: "nth_el' env x T \<Longrightarrow> env \<turnstile> Var x : T"
   232   | Abs [intro!]: "T # env \<turnstile> t : U \<Longrightarrow> env \<turnstile> Abs T t : (T \<Rightarrow> U)"
   233   | App [intro!]: "env \<turnstile> s : U \<Rightarrow> T \<Longrightarrow> env \<turnstile> t : T \<Longrightarrow> env \<turnstile> (s \<degree> t) : U"
   234 
   235 primrec
   236   lift :: "[dB, nat] => dB"
   237 where
   238     "lift (Var i) k = (if i < k then Var i else Var (i + 1))"
   239   | "lift (s \<degree> t) k = lift s k \<degree> lift t k"
   240   | "lift (Abs T s) k = Abs T (lift s (k + 1))"
   241 
   242 primrec
   243   subst :: "[dB, dB, nat] => dB"  ("_[_'/_]" [300, 0, 0] 300)
   244 where
   245     subst_Var: "(Var i)[s/k] =
   246       (if k < i then Var (i - 1) else if i = k then s else Var i)"
   247   | subst_App: "(t \<degree> u)[s/k] = t[s/k] \<degree> u[s/k]"
   248   | subst_Abs: "(Abs T t)[s/k] = Abs T (t[lift s 0 / k+1])"
   249 
   250 inductive beta :: "[dB, dB] => bool"  (infixl "\<rightarrow>\<^sub>\<beta>" 50)
   251   where
   252     beta [simp, intro!]: "Abs T s \<degree> t \<rightarrow>\<^sub>\<beta> s[t/0]"
   253   | appL [simp, intro!]: "s \<rightarrow>\<^sub>\<beta> t ==> s \<degree> u \<rightarrow>\<^sub>\<beta> t \<degree> u"
   254   | appR [simp, intro!]: "s \<rightarrow>\<^sub>\<beta> t ==> u \<degree> s \<rightarrow>\<^sub>\<beta> u \<degree> t"
   255   | abs [simp, intro!]: "s \<rightarrow>\<^sub>\<beta> t ==> Abs T s \<rightarrow>\<^sub>\<beta> Abs T t"
   256 
   257 lemma
   258   "\<Gamma> \<turnstile> t : U \<Longrightarrow> t \<rightarrow>\<^sub>\<beta> t' \<Longrightarrow> \<Gamma> \<turnstile> t' : U"
   259 quickcheck[tester = predicate_compile_ff_fs, size = 7, iterations = 10]
   260 oops
   261 
   262 subsection {* JAD *}
   263 
   264 definition matrix :: "('a :: semiring_0) list list \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where
   265   "matrix M rs cs \<longleftrightarrow> (\<forall> row \<in> set M. length row = cs) \<and> length M = rs"
   266 (*
   267 code_pred [random_dseq inductify] matrix .
   268 thm matrix.random_dseq_equation
   269 
   270 thm matrix_aux.random_dseq_equation
   271 
   272 values [random_dseq 3, 2] 10 "{(M, rs, cs). matrix (M:: int list list) rs cs}"
   273 *)
   274 lemma [code_pred_intro]:
   275   "matrix [] 0 m"
   276   "matrix xss n m ==> length xs = m ==> matrix (xs # xss) (Suc n) m"
   277 proof -
   278   show "matrix [] 0 m" unfolding matrix_def by auto
   279 next
   280   show "matrix xss n m ==> length xs = m ==> matrix (xs # xss) (Suc n) m"
   281     unfolding matrix_def by auto
   282 qed
   283 
   284 code_pred [random_dseq inductify] matrix
   285   apply (cases x)
   286   unfolding matrix_def apply fastforce
   287   apply fastforce done
   288 
   289 
   290 values [random_dseq 2, 2, 15] 6 "{(M::int list list, n, m). matrix M n m}"
   291 
   292 definition "scalar_product v w = (\<Sum> (x, y)\<leftarrow>zip v w. x * y)"
   293 
   294 definition mv :: "('a \<Colon> semiring_0) list list \<Rightarrow> 'a list \<Rightarrow> 'a list"
   295   where [simp]: "mv M v = map (scalar_product v) M"
   296 text {*
   297   This defines the matrix vector multiplication. To work properly @{term
   298 "matrix M m n \<and> length v = n"} must hold.
   299 *}
   300 
   301 subsection "Compressed matrix"
   302 
   303 definition "sparsify xs = [i \<leftarrow> zip [0..<length xs] xs. snd i \<noteq> 0]"
   304 (*
   305 lemma sparsify_length: "(i, x) \<in> set (sparsify xs) \<Longrightarrow> i < length xs"
   306   by (auto simp: sparsify_def set_zip)
   307 
   308 lemma listsum_sparsify[simp]:
   309   fixes v :: "('a \<Colon> semiring_0) list"
   310   assumes "length w = length v"
   311   shows "(\<Sum>x\<leftarrow>sparsify w. (\<lambda>(i, x). v ! i) x * snd x) = scalar_product v w"
   312     (is "(\<Sum>x\<leftarrow>_. ?f x) = _")
   313   unfolding sparsify_def scalar_product_def
   314   using assms listsum_map_filter[where f="?f" and P="\<lambda> i. snd i \<noteq> (0::'a)"]
   315   by (simp add: listsum_setsum)
   316 *)
   317 definition [simp]: "unzip w = (map fst w, map snd w)"
   318 
   319 primrec insert :: "('a \<Rightarrow> 'b \<Colon> linorder) => 'a \<Rightarrow> 'a list => 'a list" where
   320   "insert f x [] = [x]" |
   321   "insert f x (y # ys) = (if f y < f x then y # insert f x ys else x # y # ys)"
   322 
   323 primrec sort :: "('a \<Rightarrow> 'b \<Colon> linorder) \<Rightarrow> 'a list => 'a list" where
   324   "sort f [] = []" |
   325   "sort f (x # xs) = insert f x (sort f xs)"
   326 
   327 definition
   328   "length_permutate M = (unzip o sort (length o snd)) (zip [0 ..< length M] M)"
   329 (*
   330 definition
   331   "transpose M = [map (\<lambda> xs. xs ! i) (takeWhile (\<lambda> xs. i < length xs) M). i \<leftarrow> [0 ..< length (M ! 0)]]"
   332 *)
   333 definition
   334   "inflate upds = foldr (\<lambda> (i, x) upds. upds[i := x]) upds (replicate (length upds) 0)"
   335 
   336 definition
   337   "jad = apsnd transpose o length_permutate o map sparsify"
   338 
   339 definition
   340   "jad_mv v = inflate o split zip o apsnd (map listsum o transpose o map (map (\<lambda> (i, x). v ! i * x)))"
   341 
   342 lemma "matrix (M::int list list) rs cs \<Longrightarrow> False"
   343 quickcheck[tester = predicate_compile_ff_nofs, size = 6]
   344 oops
   345 
   346 lemma
   347   "\<lbrakk> matrix M rs cs ; length v = cs \<rbrakk> \<Longrightarrow> jad_mv v (jad M) = mv M v"
   348 quickcheck[tester = predicate_compile_wo_ff]
   349 oops
   350 
   351 end