blanchet@33192: (* Title: HOL/Nitpick.thy blanchet@33192: Author: Jasmin Blanchette, TU Muenchen blanchet@35807: Copyright 2008, 2009, 2010 blanchet@33192: blanchet@33192: Nitpick: Yet another counterexample generator for Isabelle/HOL. blanchet@33192: *) blanchet@33192: blanchet@33192: header {* Nitpick: Yet Another Counterexample Generator for Isabelle/HOL *} blanchet@33192: blanchet@33192: theory Nitpick blanchet@57242: imports Record blanchet@55539: keywords blanchet@55539: "nitpick" :: diag and blanchet@55539: "nitpick_params" :: thy_decl blanchet@33192: begin blanchet@33192: blanchet@58310: datatype (dead 'a, dead 'b) fun_box = FunBox "'a \ 'b" blanchet@58310: datatype (dead 'a, dead 'b) pair_box = PairBox 'a 'b blanchet@58310: datatype (dead 'a) word = Word "'a set" blanchet@33192: blanchet@57992: typedecl bisim_iterator blanchet@34124: typedecl unsigned_bit blanchet@34124: typedecl signed_bit blanchet@34124: blanchet@57992: consts blanchet@57992: unknown :: 'a blanchet@57992: is_unknown :: "'a \ bool" blanchet@57992: bisim :: "bisim_iterator \ 'a \ 'a \ bool" blanchet@57992: bisim_iterator_max :: bisim_iterator blanchet@57992: Quot :: "'a \ 'b" blanchet@57992: safe_The :: "('a \ bool) \ 'a" blanchet@33192: blanchet@33192: text {* blanchet@33192: Alternative definitions. blanchet@33192: *} blanchet@33192: blanchet@57992: lemma Ex1_unfold[nitpick_unfold]: "Ex1 P \ \x. {x. P x} = {x}" blanchet@57992: apply (rule eq_reflection) blanchet@57992: apply (simp add: Ex1_def set_eq_iff) blanchet@57992: apply (rule iffI) blanchet@57992: apply (erule exE) blanchet@57992: apply (erule conjE) blanchet@57992: apply (rule_tac x = x in exI) blanchet@57992: apply (rule allI) blanchet@57992: apply (rename_tac y) blanchet@57992: apply (erule_tac x = y in allE) blanchet@57992: by auto blanchet@33192: blanchet@57992: lemma rtrancl_unfold[nitpick_unfold]: "r\<^sup>* \ (r\<^sup>+)\<^sup>=" haftmann@45140: by (simp only: rtrancl_trancl_reflcl) blanchet@33192: blanchet@57992: lemma rtranclp_unfold[nitpick_unfold]: "rtranclp r a b \ (a = b \ tranclp r a b)" blanchet@57992: by (rule eq_reflection) (auto dest: rtranclpD) blanchet@33192: blanchet@57992: lemma tranclp_unfold[nitpick_unfold]: blanchet@57992: "tranclp r a b \ (a, b) \ trancl {(x, y). r x y}" blanchet@57992: by (simp add: trancl_def) blanchet@33192: blanchet@54148: lemma [nitpick_simp]: blanchet@57992: "of_nat n = (if n = 0 then 0 else 1 + of_nat (n - 1))" blanchet@57992: by (cases n) auto blanchet@47909: blanchet@41046: definition prod :: "'a set \ 'b set \ ('a \ 'b) set" where blanchet@57992: "prod A B = {(a, b). a \ A \ b \ B}" blanchet@41046: haftmann@44278: definition refl' :: "('a \ 'a) set \ bool" where blanchet@57992: "refl' r \ \x. (x, x) \ r" blanchet@33192: haftmann@44278: definition wf' :: "('a \ 'a) set \ bool" where blanchet@57992: "wf' r \ acyclic r \ (finite r \ unknown)" blanchet@33192: haftmann@44278: definition card' :: "'a set \ nat" where blanchet@57992: "card' A \ if finite A then length (SOME xs. set xs = A \ distinct xs) else 0" blanchet@33192: haftmann@44278: definition setsum' :: "('a \ 'b\comm_monoid_add) \ 'a set \ 'b" where blanchet@57992: "setsum' f A \ if finite A then listsum (map f (SOME xs. set xs = A \ distinct xs)) else 0" blanchet@33192: haftmann@44278: inductive fold_graph' :: "('a \ 'b \ 'b) \ 'b \ 'a set \ 'b \ bool" where blanchet@57992: "fold_graph' f z {} z" | blanchet@57992: "\x \ A; fold_graph' f z (A - {x}) y\ \ fold_graph' f z A (f x y)" blanchet@33192: blanchet@33192: text {* blanchet@33192: The following lemmas are not strictly necessary but they help the blanchet@47909: \textit{specialize} optimization. blanchet@33192: *} blanchet@33192: blanchet@57992: lemma The_psimp[nitpick_psimp]: "P = (op =) x \ The P = x" haftmann@45970: by auto blanchet@33192: blanchet@57992: lemma Eps_psimp[nitpick_psimp]: blanchet@57992: "\P x; \ P y; Eps P = y\ \ Eps P = x" blanchet@57992: apply (cases "P (Eps P)") blanchet@57992: apply auto blanchet@57992: apply (erule contrapos_np) blanchet@57992: by (rule someI) blanchet@33192: blanchet@57992: lemma case_unit_unfold[nitpick_unfold]: blanchet@57992: "case_unit x u \ x" blanchet@57992: apply (subgoal_tac "u = ()") blanchet@57992: apply (simp only: unit.case) blanchet@57992: by simp blanchet@33192: blanchet@57992: declare unit.case[nitpick_simp del] blanchet@33556: blanchet@57992: lemma case_nat_unfold[nitpick_unfold]: blanchet@57992: "case_nat x f n \ if n = 0 then x else f (n - 1)" blanchet@57992: apply (rule eq_reflection) blanchet@57992: by (cases n) auto blanchet@33192: blanchet@57992: declare nat.case[nitpick_simp del] blanchet@33556: blanchet@57992: lemma size_list_simp[nitpick_simp]: blanchet@57992: "size_list f xs = (if xs = [] then 0 else Suc (f (hd xs) + size_list f (tl xs)))" blanchet@57992: "size xs = (if xs = [] then 0 else Suc (size (tl xs)))" blanchet@57992: by (cases xs) auto blanchet@33192: blanchet@33192: text {* blanchet@33192: Auxiliary definitions used to provide an alternative representation for blanchet@33192: @{text rat} and @{text real}. blanchet@33192: *} blanchet@33192: blanchet@33192: function nat_gcd :: "nat \ nat \ nat" where blanchet@57992: "nat_gcd x y = (if y = 0 then x else nat_gcd y (x mod y))" blanchet@57992: by auto blanchet@57992: termination blanchet@57992: apply (relation "measure (\(x, y). x + y + (if y > x then 1 else 0))") blanchet@57992: apply auto blanchet@57992: apply (metis mod_less_divisor xt1(9)) blanchet@57992: by (metis mod_mod_trivial mod_self nat_neq_iff xt1(10)) blanchet@57992: blanchet@57992: declare nat_gcd.simps[simp del] blanchet@33192: blanchet@33192: definition nat_lcm :: "nat \ nat \ nat" where blanchet@57992: "nat_lcm x y = x * y div (nat_gcd x y)" blanchet@33192: blanchet@33192: definition int_gcd :: "int \ int \ int" where blanchet@57992: "int_gcd x y = int (nat_gcd (nat (abs x)) (nat (abs y)))" blanchet@33192: blanchet@33192: definition int_lcm :: "int \ int \ int" where blanchet@57992: "int_lcm x y = int (nat_lcm (nat (abs x)) (nat (abs y)))" blanchet@33192: blanchet@33192: definition Frac :: "int \ int \ bool" where blanchet@57992: "Frac \ \(a, b). b > 0 \ int_gcd a b = 1" blanchet@33192: blanchet@57992: consts blanchet@57992: Abs_Frac :: "int \ int \ 'a" blanchet@56643: Rep_Frac :: "'a \ int \ int" blanchet@33192: blanchet@33192: definition zero_frac :: 'a where blanchet@57992: "zero_frac \ Abs_Frac (0, 1)" blanchet@33192: blanchet@33192: definition one_frac :: 'a where blanchet@57992: "one_frac \ Abs_Frac (1, 1)" blanchet@33192: blanchet@33192: definition num :: "'a \ int" where blanchet@57992: "num \ fst o Rep_Frac" blanchet@33192: blanchet@33192: definition denom :: "'a \ int" where blanchet@57992: "denom \ snd o Rep_Frac" blanchet@33192: blanchet@33192: function norm_frac :: "int \ int \ int \ int" where blanchet@57992: "norm_frac a b = blanchet@57992: (if b < 0 then norm_frac (- a) (- b) blanchet@57992: else if a = 0 \ b = 0 then (0, 1) blanchet@57992: else let c = int_gcd a b in (a div c, b div c))" blanchet@57992: by pat_completeness auto blanchet@57992: termination by (relation "measure (\(_, b). if b < 0 then 1 else 0)") auto blanchet@57992: blanchet@57992: declare norm_frac.simps[simp del] blanchet@33192: blanchet@33192: definition frac :: "int \ int \ 'a" where blanchet@57992: "frac a b \ Abs_Frac (norm_frac a b)" blanchet@33192: blanchet@33192: definition plus_frac :: "'a \ 'a \ 'a" where blanchet@57992: [nitpick_simp]: "plus_frac q r = (let d = int_lcm (denom q) (denom r) in blanchet@57992: frac (num q * (d div denom q) + num r * (d div denom r)) d)" blanchet@33192: blanchet@33192: definition times_frac :: "'a \ 'a \ 'a" where blanchet@57992: [nitpick_simp]: "times_frac q r = frac (num q * num r) (denom q * denom r)" blanchet@33192: blanchet@33192: definition uminus_frac :: "'a \ 'a" where blanchet@57992: "uminus_frac q \ Abs_Frac (- num q, denom q)" blanchet@33192: blanchet@33192: definition number_of_frac :: "int \ 'a" where blanchet@57992: "number_of_frac n \ Abs_Frac (n, 1)" blanchet@33192: blanchet@33192: definition inverse_frac :: "'a \ 'a" where blanchet@57992: "inverse_frac q \ frac (denom q) (num q)" blanchet@33192: blanchet@37397: definition less_frac :: "'a \ 'a \ bool" where blanchet@57992: [nitpick_simp]: "less_frac q r \ num (plus_frac q (uminus_frac r)) < 0" blanchet@37397: blanchet@33192: definition less_eq_frac :: "'a \ 'a \ bool" where blanchet@57992: [nitpick_simp]: "less_eq_frac q r \ num (plus_frac q (uminus_frac r)) \ 0" blanchet@33192: blanchet@33192: definition of_frac :: "'a \ 'b\{inverse,ring_1}" where blanchet@57992: "of_frac q \ of_int (num q) / of_int (denom q)" blanchet@33192: blanchet@55017: axiomatization wf_wfrec :: "('a \ 'a) set \ (('a \ 'b) \ 'a \ 'b) \ 'a \ 'b" blanchet@55017: blanchet@55017: definition wf_wfrec' :: "('a \ 'a) set \ (('a \ 'b) \ 'a \ 'b) \ 'a \ 'b" where blanchet@57992: [nitpick_simp]: "wf_wfrec' R F x = F (cut (wf_wfrec R F) R x) x" blanchet@55017: blanchet@55017: definition wfrec' :: "('a \ 'a) set \ (('a \ 'b) \ 'a \ 'b) \ 'a \ 'b" where blanchet@57992: "wfrec' R F x \ if wf R then wf_wfrec' R F x else THE y. wfrec_rel R (\f x. F (cut f R x) x) x y" blanchet@55017: wenzelm@48891: ML_file "Tools/Nitpick/kodkod.ML" wenzelm@48891: ML_file "Tools/Nitpick/kodkod_sat.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_util.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_hol.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_mono.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_preproc.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_scope.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_peephole.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_rep.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_nut.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_kodkod.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_model.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick.ML" blanchet@55199: ML_file "Tools/Nitpick/nitpick_commands.ML" wenzelm@48891: ML_file "Tools/Nitpick/nitpick_tests.ML" blanchet@33192: krauss@44016: setup {* krauss@44016: Nitpick_HOL.register_ersatz_global krauss@44016: [(@{const_name card}, @{const_name card'}), krauss@44016: (@{const_name setsum}, @{const_name setsum'}), krauss@44016: (@{const_name fold_graph}, @{const_name fold_graph'}), blanchet@55017: (@{const_name wf}, @{const_name wf'}), blanchet@55017: (@{const_name wf_wfrec}, @{const_name wf_wfrec'}), blanchet@55017: (@{const_name wfrec}, @{const_name wfrec'})] krauss@44016: *} blanchet@33561: blanchet@57992: hide_const (open) unknown is_unknown bisim bisim_iterator_max Quot safe_The FunBox PairBox Word prod blanchet@57992: refl' wf' card' setsum' fold_graph' nat_gcd nat_lcm int_gcd int_lcm Frac Abs_Frac Rep_Frac blanchet@57992: zero_frac one_frac num denom norm_frac frac plus_frac times_frac uminus_frac number_of_frac blanchet@57992: inverse_frac less_frac less_eq_frac of_frac wf_wfrec wf_wfrec wfrec' blanchet@57992: blanchet@46324: hide_type (open) bisim_iterator fun_box pair_box unsigned_bit signed_bit word blanchet@57992: blanchet@57992: hide_fact (open) Ex1_unfold rtrancl_unfold rtranclp_unfold tranclp_unfold prod_def refl'_def wf'_def blanchet@57992: card'_def setsum'_def fold_graph'_def The_psimp Eps_psimp case_unit_unfold case_nat_unfold blanchet@57992: size_list_simp nat_gcd_def nat_lcm_def int_gcd_def int_lcm_def Frac_def zero_frac_def one_frac_def blanchet@57992: num_def denom_def norm_frac_def frac_def plus_frac_def times_frac_def uminus_frac_def blanchet@57992: number_of_frac_def inverse_frac_def less_frac_def less_eq_frac_def of_frac_def wf_wfrec'_def blanchet@57992: wfrec'_def blanchet@33192: blanchet@33192: end