src/HOL/Quickcheck_Examples/Hotel_Example.thy
author bulwahn
Fri Jul 13 08:45:09 2012 +0200 (2012-07-13)
changeset 48255 968602739b54
parent 48222 fcca68383808
child 51143 0a2371e7ced3
permissions -rw-r--r--
fixed typo
bulwahn@48222
     1
theory Hotel_Example
bulwahn@48222
     2
imports Main "~~/src/HOL/Library/Predicate_Compile_Quickcheck"
bulwahn@48222
     3
begin
bulwahn@48222
     4
bulwahn@48222
     5
datatype guest = Guest0 | Guest1
bulwahn@48222
     6
datatype key = Key0 | Key1 | Key2 | Key3
bulwahn@48222
     7
datatype room = Room0
bulwahn@48222
     8
bulwahn@48222
     9
type_synonym card = "key * key"
bulwahn@48222
    10
bulwahn@48222
    11
datatype event =
bulwahn@48222
    12
   Check_in guest room card | Enter guest room card | Exit guest room
bulwahn@48222
    13
bulwahn@48222
    14
definition initk :: "room \<Rightarrow> key"
bulwahn@48222
    15
  where "initk = (%r. Key0)"
bulwahn@48222
    16
bulwahn@48222
    17
declare initk_def[code_pred_def, code]
bulwahn@48222
    18
bulwahn@48222
    19
primrec owns :: "event list \<Rightarrow> room \<Rightarrow> guest option"
bulwahn@48222
    20
where
bulwahn@48222
    21
  "owns [] r = None"
bulwahn@48222
    22
| "owns (e#s) r = (case e of
bulwahn@48222
    23
    Check_in g r' c \<Rightarrow> if r' = r then Some g else owns s r |
bulwahn@48222
    24
    Enter g r' c \<Rightarrow> owns s r |
bulwahn@48222
    25
    Exit g r' \<Rightarrow> owns s r)"
bulwahn@48222
    26
bulwahn@48222
    27
primrec currk :: "event list \<Rightarrow> room \<Rightarrow> key"
bulwahn@48222
    28
where
bulwahn@48222
    29
  "currk [] r = initk r"
bulwahn@48222
    30
| "currk (e#s) r = (let k = currk s r in
bulwahn@48222
    31
    case e of Check_in g r' (k1, k2) \<Rightarrow> if r' = r then k2 else k
bulwahn@48222
    32
            | Enter g r' c \<Rightarrow> k
bulwahn@48222
    33
            | Exit g r \<Rightarrow> k)"
bulwahn@48222
    34
bulwahn@48222
    35
primrec issued :: "event list \<Rightarrow> key set"
bulwahn@48222
    36
where
bulwahn@48222
    37
  "issued [] = range initk"
bulwahn@48222
    38
| "issued (e#s) = issued s \<union>
bulwahn@48222
    39
  (case e of Check_in g r (k1, k2) \<Rightarrow> {k2} | Enter g r c \<Rightarrow> {} | Exit g r \<Rightarrow> {})"
bulwahn@48222
    40
bulwahn@48222
    41
primrec cards :: "event list \<Rightarrow> guest \<Rightarrow> card set"
bulwahn@48222
    42
where
bulwahn@48222
    43
  "cards [] g = {}"
bulwahn@48222
    44
| "cards (e#s) g = (let C = cards s g in
bulwahn@48222
    45
                    case e of Check_in g' r c \<Rightarrow> if g' = g then insert c C
bulwahn@48222
    46
                                                else C
bulwahn@48222
    47
                            | Enter g r c \<Rightarrow> C
bulwahn@48222
    48
                            | Exit g r \<Rightarrow> C)"
bulwahn@48222
    49
bulwahn@48222
    50
primrec roomk :: "event list \<Rightarrow> room \<Rightarrow> key"
bulwahn@48222
    51
where
bulwahn@48222
    52
  "roomk [] r = initk r"
bulwahn@48222
    53
| "roomk (e#s) r = (let k = roomk s r in
bulwahn@48222
    54
    case e of Check_in g r' c \<Rightarrow> k
bulwahn@48222
    55
            | Enter g r' (x,y) \<Rightarrow> if r' = r (*& x = k*) then y else k
bulwahn@48222
    56
            | Exit g r \<Rightarrow> k)"
bulwahn@48222
    57
bulwahn@48222
    58
primrec isin :: "event list \<Rightarrow> room \<Rightarrow> guest set"
bulwahn@48222
    59
where
bulwahn@48222
    60
  "isin [] r = {}"
bulwahn@48222
    61
| "isin (e#s) r = (let G = isin s r in
bulwahn@48222
    62
                 case e of Check_in g r c \<Rightarrow> G
bulwahn@48222
    63
                 | Enter g r' c \<Rightarrow> if r' = r then {g} \<union> G else G
bulwahn@48222
    64
                 | Exit g r' \<Rightarrow> if r'=r then G - {g} else G)"
bulwahn@48222
    65
bulwahn@48222
    66
primrec hotel :: "event list \<Rightarrow> bool"
bulwahn@48222
    67
where
bulwahn@48222
    68
  "hotel []  = True"
bulwahn@48222
    69
| "hotel (e # s) = (hotel s & (case e of
bulwahn@48222
    70
  Check_in g r (k,k') \<Rightarrow> k = currk s r \<and> k' \<notin> issued s |
bulwahn@48222
    71
  Enter g r (k,k') \<Rightarrow> (k,k') : cards s g & (roomk s r : {k, k'}) |
bulwahn@48222
    72
  Exit g r \<Rightarrow> g : isin s r))"
bulwahn@48222
    73
bulwahn@48222
    74
definition no_Check_in :: "event list \<Rightarrow> room \<Rightarrow> bool" where(*>*)
bulwahn@48222
    75
[code del]: "no_Check_in s r \<equiv> \<not>(\<exists>g c. Check_in g r c \<in> set s)"
bulwahn@48222
    76
bulwahn@48222
    77
definition feels_safe :: "event list \<Rightarrow> room \<Rightarrow> bool"
bulwahn@48222
    78
where
bulwahn@48222
    79
  "feels_safe s r = (\<exists>s\<^isub>1 s\<^isub>2 s\<^isub>3 g c c'.
bulwahn@48222
    80
   s = s\<^isub>3 @ [Enter g r c] @ s\<^isub>2 @ [Check_in g r c'] @ s\<^isub>1 \<and>
bulwahn@48222
    81
   no_Check_in (s\<^isub>3 @ s\<^isub>2) r \<and> isin (s\<^isub>2 @ [Check_in g r c] @ s\<^isub>1) r = {})"
bulwahn@48222
    82
bulwahn@48222
    83
bulwahn@48222
    84
section {* Some setup *}
bulwahn@48222
    85
bulwahn@48222
    86
lemma issued_nil: "issued [] = {Key0}"
bulwahn@48222
    87
by (auto simp add: initk_def)
bulwahn@48222
    88
bulwahn@48222
    89
lemmas issued_simps[code] = issued_nil issued.simps(2)
bulwahn@48222
    90
bulwahn@48222
    91
bulwahn@48222
    92
setup {*  Predicate_Compile_Data.ignore_consts [@{const_name Set.member},
bulwahn@48222
    93
  @{const_name "issued"}, @{const_name "cards"}, @{const_name "isin"},
bulwahn@48222
    94
  @{const_name Collect}, @{const_name insert}] *}
bulwahn@48222
    95
ML {* Core_Data.force_modes_and_compilations *}
bulwahn@48222
    96
bulwahn@48222
    97
fun find_first :: "('a => 'b option) => 'a list => 'b option"
bulwahn@48222
    98
where
bulwahn@48222
    99
  "find_first f [] = None"
bulwahn@48222
   100
| "find_first f (x # xs) = (case f x of Some y => Some y | None => find_first f xs)"
bulwahn@48222
   101
bulwahn@48222
   102
consts cps_of_set :: "'a set => ('a => term list option) => term list option"
bulwahn@48222
   103
bulwahn@48222
   104
lemma
bulwahn@48222
   105
  [code]: "cps_of_set (set xs) f = find_first f xs"
bulwahn@48222
   106
sorry
bulwahn@48222
   107
bulwahn@48222
   108
consts pos_cps_of_set :: "'a set => ('a => (bool * term list) option) => code_numeral => (bool * term list) option"
bulwahn@48222
   109
consts neg_cps_of_set :: "'a set => ('a Quickcheck_Exhaustive.unknown => term list Quickcheck_Exhaustive.three_valued) => code_numeral => term list Quickcheck_Exhaustive.three_valued"
bulwahn@48222
   110
bulwahn@48222
   111
lemma
bulwahn@48222
   112
  [code]: "pos_cps_of_set (set xs) f i = find_first f xs"
bulwahn@48222
   113
sorry
bulwahn@48222
   114
bulwahn@48222
   115
consts find_first' :: "('b Quickcheck_Exhaustive.unknown => 'a Quickcheck_Exhaustive.three_valued)
bulwahn@48222
   116
    => 'b list => 'a Quickcheck_Exhaustive.three_valued"
bulwahn@48222
   117
bulwahn@48222
   118
lemma [code]:
bulwahn@48222
   119
  "find_first' f [] = Quickcheck_Exhaustive.No_value"
bulwahn@48222
   120
  "find_first' f (x # xs) = (case f (Quickcheck_Exhaustive.Known x) of Quickcheck_Exhaustive.No_value => find_first' f xs | Quickcheck_Exhaustive.Value x => Quickcheck_Exhaustive.Value x | Quickcheck_Exhaustive.Unknown_value => (case find_first' f xs of Quickcheck_Exhaustive.Value x => Quickcheck_Exhaustive.Value x | _ => Quickcheck_Exhaustive.Unknown_value))"
bulwahn@48222
   121
sorry
bulwahn@48222
   122
bulwahn@48222
   123
lemma
bulwahn@48222
   124
  [code]: "neg_cps_of_set (set xs) f i = find_first' f xs"
bulwahn@48222
   125
sorry
bulwahn@48222
   126
bulwahn@48222
   127
setup {*
bulwahn@48222
   128
let
bulwahn@48222
   129
  val Fun = Predicate_Compile_Aux.Fun
bulwahn@48222
   130
  val Input = Predicate_Compile_Aux.Input
bulwahn@48222
   131
  val Output = Predicate_Compile_Aux.Output
bulwahn@48222
   132
  val Bool = Predicate_Compile_Aux.Bool
bulwahn@48222
   133
  val oi = Fun (Output, Fun (Input, Bool))
bulwahn@48222
   134
  val ii = Fun (Input, Fun (Input, Bool))
bulwahn@48222
   135
  fun of_set compfuns (Type ("fun", [T, _])) =
bulwahn@48222
   136
    case body_type (Predicate_Compile_Aux.mk_monadT compfuns T) of
bulwahn@48222
   137
      Type ("Quickcheck_Exhaustive.three_valued", _) => 
bulwahn@48222
   138
        Const(@{const_name neg_cps_of_set}, HOLogic.mk_setT T --> (Predicate_Compile_Aux.mk_monadT compfuns T))
bulwahn@48222
   139
    | _ => Const(@{const_name pos_cps_of_set}, HOLogic.mk_setT T --> (Predicate_Compile_Aux.mk_monadT compfuns T))
bulwahn@48222
   140
  fun member compfuns (U as Type ("fun", [T, _])) =
bulwahn@48222
   141
    (absdummy T (absdummy (HOLogic.mk_setT T) (Predicate_Compile_Aux.mk_if compfuns
bulwahn@48222
   142
      (Const (@{const_name "Set.member"}, T --> HOLogic.mk_setT T --> @{typ bool}) $ Bound 1 $ Bound 0))))
bulwahn@48222
   143
 
bulwahn@48222
   144
in
bulwahn@48222
   145
  Core_Data.force_modes_and_compilations @{const_name Set.member}
bulwahn@48222
   146
    [(oi, (of_set, false)), (ii, (member, false))]
bulwahn@48222
   147
end
bulwahn@48222
   148
*}
bulwahn@48222
   149
section {* Property *}
bulwahn@48222
   150
bulwahn@48222
   151
lemma "\<lbrakk> hotel s; g \<in> isin s r \<rbrakk> \<Longrightarrow> owns s r = Some g"
bulwahn@48222
   152
quickcheck[tester = exhaustive, size = 6, expect = counterexample]
bulwahn@48222
   153
quickcheck[tester = smart_exhaustive, depth = 6, expect = counterexample]
bulwahn@48222
   154
oops
bulwahn@48222
   155
bulwahn@48222
   156
lemma
bulwahn@48222
   157
  "hotel s ==> feels_safe s r ==> g \<in> isin s r ==> owns s r = Some g"
bulwahn@48222
   158
quickcheck[smart_exhaustive, depth = 10, allow_function_inversion, expect = counterexample]
bulwahn@48222
   159
oops
bulwahn@48222
   160
bulwahn@48222
   161
section {* Refinement *}
bulwahn@48222
   162
bulwahn@48222
   163
fun split_list
bulwahn@48222
   164
where
bulwahn@48222
   165
  "split_list [] = [([], [])]"
bulwahn@48222
   166
| "split_list (z # zs) = (([], z # zs) # [(z # xs', ys'). (xs', ys') <- split_list zs])"
bulwahn@48222
   167
bulwahn@48222
   168
lemma split_list: "((xs, ys) \<in> set (split_list zs)) = (zs = xs @ ys)"
bulwahn@48222
   169
apply (induct zs arbitrary: xs ys)
bulwahn@48222
   170
apply fastforce
bulwahn@48222
   171
apply (case_tac xs)
bulwahn@48222
   172
apply auto
bulwahn@48222
   173
done
bulwahn@48222
   174
bulwahn@48222
   175
lemma [code]: "no_Check_in s r = list_all (%x. case x of Check_in g r' c => r \<noteq> r' | _ => True) s"
bulwahn@48222
   176
unfolding no_Check_in_def list_all_iff
bulwahn@48222
   177
apply auto
bulwahn@48222
   178
apply (case_tac x)
bulwahn@48222
   179
apply auto
bulwahn@48222
   180
done
bulwahn@48222
   181
bulwahn@48222
   182
lemma [code]: "feels_safe s r = list_ex (%(s3, s2, s1, g, c, c'). no_Check_in (s3 @ s2) r &
bulwahn@48222
   183
    isin (s2 @ [Check_in g r c] @ s1) r = {}) ([(s3, s2, s1, g, c, c'). (s3, Enter g' r' c # r3) <- split_list s, r' = r, (s2, Check_in g r'' c' # s1) <- split_list r3, r'' = r, g = g'])"
bulwahn@48222
   184
unfolding feels_safe_def list_ex_iff
bulwahn@48222
   185
by auto (metis split_list)+
bulwahn@48222
   186
bulwahn@48222
   187
lemma
bulwahn@48222
   188
  "hotel s ==> feels_safe s r ==> g \<in> isin s r ==> owns s r = Some g"
bulwahn@48222
   189
(* quickcheck[exhaustive, size = 9, timeout = 2000] -- maybe possible with a lot of time *)
bulwahn@48222
   190
quickcheck[narrowing, size = 7, expect = counterexample]
bulwahn@48222
   191
oops
bulwahn@48222
   192
bulwahn@48255
   193
end