blanchet@33980
|
1 |
(* Title: HOL/Tools/Nitpick/minipick.ML
|
blanchet@33192
|
2 |
Author: Jasmin Blanchette, TU Muenchen
|
blanchet@34969
|
3 |
Copyright 2009, 2010
|
blanchet@33192
|
4 |
|
blanchet@33192
|
5 |
Finite model generation for HOL formulas using Kodkod, minimalistic version.
|
blanchet@33192
|
6 |
*)
|
blanchet@33192
|
7 |
|
blanchet@33192
|
8 |
signature MINIPICK =
|
blanchet@33192
|
9 |
sig
|
blanchet@33980
|
10 |
datatype rep = SRep | RRep
|
blanchet@33980
|
11 |
type styp = Nitpick_Util.styp
|
blanchet@33980
|
12 |
|
blanchet@33980
|
13 |
val vars_for_bound_var :
|
blanchet@33980
|
14 |
(typ -> int) -> rep -> typ list -> int -> Kodkod.rel_expr list
|
blanchet@33980
|
15 |
val rel_expr_for_bound_var :
|
blanchet@33980
|
16 |
(typ -> int) -> rep -> typ list -> int -> Kodkod.rel_expr
|
blanchet@33980
|
17 |
val decls_for : rep -> (typ -> int) -> typ list -> typ -> Kodkod.decl list
|
blanchet@33980
|
18 |
val false_atom : Kodkod.rel_expr
|
blanchet@33980
|
19 |
val true_atom : Kodkod.rel_expr
|
blanchet@33980
|
20 |
val formula_from_atom : Kodkod.rel_expr -> Kodkod.formula
|
blanchet@33980
|
21 |
val atom_from_formula : Kodkod.formula -> Kodkod.rel_expr
|
blanchet@33192
|
22 |
val pick_nits_in_term : Proof.context -> (typ -> int) -> term -> string
|
blanchet@33192
|
23 |
end;
|
blanchet@33192
|
24 |
|
blanchet@33192
|
25 |
structure Minipick : MINIPICK =
|
blanchet@33192
|
26 |
struct
|
blanchet@33192
|
27 |
|
blanchet@33192
|
28 |
open Kodkod
|
blanchet@33224
|
29 |
open Nitpick_Util
|
blanchet@33224
|
30 |
open Nitpick_HOL
|
blanchet@33224
|
31 |
open Nitpick_Peephole
|
blanchet@33224
|
32 |
open Nitpick_Kodkod
|
blanchet@33192
|
33 |
|
blanchet@33980
|
34 |
datatype rep = SRep | RRep
|
blanchet@33980
|
35 |
|
blanchet@33980
|
36 |
(* Proof.context -> typ -> unit *)
|
blanchet@33192
|
37 |
fun check_type ctxt (Type ("fun", Ts)) = List.app (check_type ctxt) Ts
|
blanchet@33192
|
38 |
| check_type ctxt (Type ("*", Ts)) = List.app (check_type ctxt) Ts
|
blanchet@33192
|
39 |
| check_type _ @{typ bool} = ()
|
blanchet@33192
|
40 |
| check_type _ (TFree (_, @{sort "{}"})) = ()
|
blanchet@33192
|
41 |
| check_type _ (TFree (_, @{sort HOL.type})) = ()
|
blanchet@33192
|
42 |
| check_type ctxt T =
|
blanchet@33192
|
43 |
raise NOT_SUPPORTED ("type " ^ quote (Syntax.string_of_typ ctxt T))
|
blanchet@33192
|
44 |
|
blanchet@33980
|
45 |
(* rep -> (typ -> int) -> typ -> int list *)
|
blanchet@33980
|
46 |
fun atom_schema_of SRep card (Type ("fun", [T1, T2])) =
|
blanchet@33980
|
47 |
replicate_list (card T1) (atom_schema_of SRep card T2)
|
blanchet@33980
|
48 |
| atom_schema_of RRep card (Type ("fun", [T1, @{typ bool}])) =
|
blanchet@33980
|
49 |
atom_schema_of SRep card T1
|
blanchet@33980
|
50 |
| atom_schema_of RRep card (Type ("fun", [T1, T2])) =
|
blanchet@33980
|
51 |
atom_schema_of SRep card T1 @ atom_schema_of RRep card T2
|
blanchet@33980
|
52 |
| atom_schema_of _ card (Type ("*", Ts)) = maps (atom_schema_of SRep card) Ts
|
blanchet@33980
|
53 |
| atom_schema_of _ card T = [card T]
|
blanchet@33980
|
54 |
(* rep -> (typ -> int) -> typ -> int *)
|
blanchet@33980
|
55 |
val arity_of = length ooo atom_schema_of
|
blanchet@33192
|
56 |
|
blanchet@33192
|
57 |
(* (typ -> int) -> typ list -> int -> int *)
|
blanchet@33192
|
58 |
fun index_for_bound_var _ [_] 0 = 0
|
blanchet@33980
|
59 |
| index_for_bound_var card (_ :: Ts) 0 =
|
blanchet@33980
|
60 |
index_for_bound_var card Ts 0 + arity_of SRep card (hd Ts)
|
blanchet@33980
|
61 |
| index_for_bound_var card Ts n = index_for_bound_var card (tl Ts) (n - 1)
|
blanchet@33980
|
62 |
(* (typ -> int) -> rep -> typ list -> int -> rel_expr list *)
|
blanchet@33980
|
63 |
fun vars_for_bound_var card R Ts j =
|
blanchet@33980
|
64 |
map (curry Var 1) (index_seq (index_for_bound_var card Ts j)
|
blanchet@33980
|
65 |
(arity_of R card (nth Ts j)))
|
blanchet@33980
|
66 |
(* (typ -> int) -> rep -> typ list -> int -> rel_expr *)
|
blanchet@33980
|
67 |
val rel_expr_for_bound_var = foldl1 Product oooo vars_for_bound_var
|
blanchet@33980
|
68 |
(* rep -> (typ -> int) -> typ list -> typ -> decl list *)
|
blanchet@33980
|
69 |
fun decls_for R card Ts T =
|
blanchet@33192
|
70 |
map2 (curry DeclOne o pair 1)
|
blanchet@33980
|
71 |
(index_seq (index_for_bound_var card (T :: Ts) 0)
|
blanchet@33980
|
72 |
(arity_of R card (nth (T :: Ts) 0)))
|
blanchet@33980
|
73 |
(map (AtomSeq o rpair 0) (atom_schema_of R card T))
|
blanchet@33192
|
74 |
|
blanchet@33192
|
75 |
(* int list -> rel_expr *)
|
blanchet@33192
|
76 |
val atom_product = foldl1 Product o map Atom
|
blanchet@33192
|
77 |
|
blanchet@33192
|
78 |
val false_atom = Atom 0
|
blanchet@33192
|
79 |
val true_atom = Atom 1
|
blanchet@33192
|
80 |
|
blanchet@33192
|
81 |
(* rel_expr -> formula *)
|
blanchet@33192
|
82 |
fun formula_from_atom r = RelEq (r, true_atom)
|
blanchet@33192
|
83 |
(* formula -> rel_expr *)
|
blanchet@33192
|
84 |
fun atom_from_formula f = RelIf (f, true_atom, false_atom)
|
blanchet@33192
|
85 |
|
blanchet@33192
|
86 |
(* Proof.context -> (typ -> int) -> styp list -> term -> formula *)
|
blanchet@33980
|
87 |
fun kodkod_formula_for_term ctxt card frees =
|
blanchet@33192
|
88 |
let
|
blanchet@33192
|
89 |
(* typ -> rel_expr -> rel_expr *)
|
blanchet@33980
|
90 |
fun R_rep_from_S_rep (T as Type ("fun", [T1, @{typ bool}])) r =
|
blanchet@33192
|
91 |
let
|
blanchet@33980
|
92 |
val jss = atom_schema_of SRep card T1 |> map (rpair 0)
|
blanchet@33192
|
93 |
|> all_combinations
|
blanchet@33192
|
94 |
in
|
blanchet@33192
|
95 |
map2 (fn i => fn js =>
|
blanchet@33980
|
96 |
RelIf (formula_from_atom (Project (r, [Num i])),
|
blanchet@33192
|
97 |
atom_product js, empty_n_ary_rel (length js)))
|
blanchet@33192
|
98 |
(index_seq 0 (length jss)) jss
|
blanchet@33192
|
99 |
|> foldl1 Union
|
blanchet@33192
|
100 |
end
|
blanchet@33980
|
101 |
| R_rep_from_S_rep (Type ("fun", [T1, T2])) r =
|
blanchet@33192
|
102 |
let
|
blanchet@33980
|
103 |
val jss = atom_schema_of SRep card T1 |> map (rpair 0)
|
blanchet@33192
|
104 |
|> all_combinations
|
blanchet@33980
|
105 |
val arity2 = arity_of SRep card T2
|
blanchet@33192
|
106 |
in
|
blanchet@33192
|
107 |
map2 (fn i => fn js =>
|
blanchet@33192
|
108 |
Product (atom_product js,
|
blanchet@33192
|
109 |
Project (r, num_seq (i * arity2) arity2)
|
blanchet@33980
|
110 |
|> R_rep_from_S_rep T2))
|
blanchet@33192
|
111 |
(index_seq 0 (length jss)) jss
|
blanchet@33192
|
112 |
|> foldl1 Union
|
blanchet@33192
|
113 |
end
|
blanchet@33980
|
114 |
| R_rep_from_S_rep _ r = r
|
blanchet@33192
|
115 |
(* typ list -> typ -> rel_expr -> rel_expr *)
|
blanchet@33980
|
116 |
fun S_rep_from_R_rep Ts (T as Type ("fun", _)) r =
|
blanchet@33980
|
117 |
Comprehension (decls_for SRep card Ts T,
|
blanchet@33980
|
118 |
RelEq (R_rep_from_S_rep T
|
blanchet@33980
|
119 |
(rel_expr_for_bound_var card SRep (T :: Ts) 0), r))
|
blanchet@33980
|
120 |
| S_rep_from_R_rep _ _ r = r
|
blanchet@33192
|
121 |
(* typ list -> term -> formula *)
|
blanchet@33980
|
122 |
fun to_F Ts t =
|
blanchet@33192
|
123 |
(case t of
|
blanchet@33980
|
124 |
@{const Not} $ t1 => Not (to_F Ts t1)
|
blanchet@33192
|
125 |
| @{const False} => False
|
blanchet@33192
|
126 |
| @{const True} => True
|
blanchet@33192
|
127 |
| Const (@{const_name All}, _) $ Abs (s, T, t') =>
|
blanchet@33980
|
128 |
All (decls_for SRep card Ts T, to_F (T :: Ts) t')
|
blanchet@33192
|
129 |
| (t0 as Const (@{const_name All}, _)) $ t1 =>
|
blanchet@33980
|
130 |
to_F Ts (t0 $ eta_expand Ts t1 1)
|
blanchet@33192
|
131 |
| Const (@{const_name Ex}, _) $ Abs (s, T, t') =>
|
blanchet@33980
|
132 |
Exist (decls_for SRep card Ts T, to_F (T :: Ts) t')
|
blanchet@33192
|
133 |
| (t0 as Const (@{const_name Ex}, _)) $ t1 =>
|
blanchet@33980
|
134 |
to_F Ts (t0 $ eta_expand Ts t1 1)
|
blanchet@33192
|
135 |
| Const (@{const_name "op ="}, _) $ t1 $ t2 =>
|
blanchet@33980
|
136 |
RelEq (to_R_rep Ts t1, to_R_rep Ts t2)
|
blanchet@33192
|
137 |
| Const (@{const_name ord_class.less_eq},
|
blanchet@33192
|
138 |
Type ("fun", [Type ("fun", [_, @{typ bool}]), _])) $ t1 $ t2 =>
|
blanchet@33980
|
139 |
Subset (to_R_rep Ts t1, to_R_rep Ts t2)
|
blanchet@33980
|
140 |
| @{const "op &"} $ t1 $ t2 => And (to_F Ts t1, to_F Ts t2)
|
blanchet@33980
|
141 |
| @{const "op |"} $ t1 $ t2 => Or (to_F Ts t1, to_F Ts t2)
|
blanchet@33980
|
142 |
| @{const "op -->"} $ t1 $ t2 => Implies (to_F Ts t1, to_F Ts t2)
|
blanchet@33980
|
143 |
| t1 $ t2 => Subset (to_S_rep Ts t2, to_R_rep Ts t1)
|
blanchet@33192
|
144 |
| Free _ => raise SAME ()
|
blanchet@33192
|
145 |
| Term.Var _ => raise SAME ()
|
blanchet@33192
|
146 |
| Bound _ => raise SAME ()
|
blanchet@33192
|
147 |
| Const (s, _) => raise NOT_SUPPORTED ("constant " ^ quote s)
|
blanchet@33980
|
148 |
| _ => raise TERM ("Minipick.kodkod_formula_for_term.to_F", [t]))
|
blanchet@33980
|
149 |
handle SAME () => formula_from_atom (to_R_rep Ts t)
|
blanchet@33192
|
150 |
(* typ list -> term -> rel_expr *)
|
blanchet@33980
|
151 |
and to_S_rep Ts t =
|
blanchet@33192
|
152 |
case t of
|
blanchet@33192
|
153 |
Const (@{const_name Pair}, _) $ t1 $ t2 =>
|
blanchet@33980
|
154 |
Product (to_S_rep Ts t1, to_S_rep Ts t2)
|
blanchet@33980
|
155 |
| Const (@{const_name Pair}, _) $ _ => to_S_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
156 |
| Const (@{const_name Pair}, _) => to_S_rep Ts (eta_expand Ts t 2)
|
blanchet@33192
|
157 |
| Const (@{const_name fst}, _) $ t1 =>
|
blanchet@33980
|
158 |
let val fst_arity = arity_of SRep card (fastype_of1 (Ts, t)) in
|
blanchet@33980
|
159 |
Project (to_S_rep Ts t1, num_seq 0 fst_arity)
|
blanchet@33192
|
160 |
end
|
blanchet@33980
|
161 |
| Const (@{const_name fst}, _) => to_S_rep Ts (eta_expand Ts t 1)
|
blanchet@33192
|
162 |
| Const (@{const_name snd}, _) $ t1 =>
|
blanchet@33192
|
163 |
let
|
blanchet@33980
|
164 |
val pair_arity = arity_of SRep card (fastype_of1 (Ts, t1))
|
blanchet@33980
|
165 |
val snd_arity = arity_of SRep card (fastype_of1 (Ts, t))
|
blanchet@33192
|
166 |
val fst_arity = pair_arity - snd_arity
|
blanchet@33980
|
167 |
in Project (to_S_rep Ts t1, num_seq fst_arity snd_arity) end
|
blanchet@33980
|
168 |
| Const (@{const_name snd}, _) => to_S_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
169 |
| Bound j => rel_expr_for_bound_var card SRep Ts j
|
blanchet@33980
|
170 |
| _ => S_rep_from_R_rep Ts (fastype_of1 (Ts, t)) (to_R_rep Ts t)
|
blanchet@33192
|
171 |
(* term -> rel_expr *)
|
blanchet@33980
|
172 |
and to_R_rep Ts t =
|
blanchet@33192
|
173 |
(case t of
|
blanchet@33980
|
174 |
@{const Not} => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
175 |
| Const (@{const_name All}, _) => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
176 |
| Const (@{const_name Ex}, _) => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
177 |
| Const (@{const_name "op ="}, _) $ _ => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
178 |
| Const (@{const_name "op ="}, _) => to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33192
|
179 |
| Const (@{const_name ord_class.less_eq},
|
blanchet@33192
|
180 |
Type ("fun", [Type ("fun", [_, @{typ bool}]), _])) $ _ =>
|
blanchet@33980
|
181 |
to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33192
|
182 |
| Const (@{const_name ord_class.less_eq}, _) =>
|
blanchet@33980
|
183 |
to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33980
|
184 |
| @{const "op &"} $ _ => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
185 |
| @{const "op &"} => to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33980
|
186 |
| @{const "op |"} $ _ => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
187 |
| @{const "op |"} => to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33980
|
188 |
| @{const "op -->"} $ _ => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
189 |
| @{const "op -->"} => to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33192
|
190 |
| Const (@{const_name bot_class.bot},
|
blanchet@33192
|
191 |
T as Type ("fun", [_, @{typ bool}])) =>
|
blanchet@33980
|
192 |
empty_n_ary_rel (arity_of RRep card T)
|
blanchet@33192
|
193 |
| Const (@{const_name insert}, _) $ t1 $ t2 =>
|
blanchet@33980
|
194 |
Union (to_S_rep Ts t1, to_R_rep Ts t2)
|
blanchet@33980
|
195 |
| Const (@{const_name insert}, _) $ _ => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33980
|
196 |
| Const (@{const_name insert}, _) => to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33192
|
197 |
| Const (@{const_name trancl}, _) $ t1 =>
|
blanchet@33980
|
198 |
if arity_of RRep card (fastype_of1 (Ts, t1)) = 2 then
|
blanchet@33980
|
199 |
Closure (to_R_rep Ts t1)
|
blanchet@33192
|
200 |
else
|
blanchet@33192
|
201 |
raise NOT_SUPPORTED "transitive closure for function or pair type"
|
blanchet@33980
|
202 |
| Const (@{const_name trancl}, _) => to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33192
|
203 |
| Const (@{const_name lower_semilattice_class.inf},
|
blanchet@33192
|
204 |
Type ("fun", [Type ("fun", [_, @{typ bool}]), _])) $ t1 $ t2 =>
|
blanchet@33980
|
205 |
Intersect (to_R_rep Ts t1, to_R_rep Ts t2)
|
blanchet@33192
|
206 |
| Const (@{const_name lower_semilattice_class.inf}, _) $ _ =>
|
blanchet@33980
|
207 |
to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33192
|
208 |
| Const (@{const_name lower_semilattice_class.inf}, _) =>
|
blanchet@33980
|
209 |
to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33192
|
210 |
| Const (@{const_name upper_semilattice_class.sup},
|
blanchet@33192
|
211 |
Type ("fun", [Type ("fun", [_, @{typ bool}]), _])) $ t1 $ t2 =>
|
blanchet@33980
|
212 |
Union (to_R_rep Ts t1, to_R_rep Ts t2)
|
blanchet@33192
|
213 |
| Const (@{const_name upper_semilattice_class.sup}, _) $ _ =>
|
blanchet@33980
|
214 |
to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33192
|
215 |
| Const (@{const_name upper_semilattice_class.sup}, _) =>
|
blanchet@33980
|
216 |
to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33192
|
217 |
| Const (@{const_name minus_class.minus},
|
blanchet@33192
|
218 |
Type ("fun", [Type ("fun", [_, @{typ bool}]), _])) $ t1 $ t2 =>
|
blanchet@33980
|
219 |
Difference (to_R_rep Ts t1, to_R_rep Ts t2)
|
blanchet@33192
|
220 |
| Const (@{const_name minus_class.minus},
|
blanchet@33192
|
221 |
Type ("fun", [Type ("fun", [_, @{typ bool}]), _])) $ _ =>
|
blanchet@33980
|
222 |
to_R_rep Ts (eta_expand Ts t 1)
|
blanchet@33192
|
223 |
| Const (@{const_name minus_class.minus},
|
blanchet@33192
|
224 |
Type ("fun", [Type ("fun", [_, @{typ bool}]), _])) =>
|
blanchet@33980
|
225 |
to_R_rep Ts (eta_expand Ts t 2)
|
blanchet@33192
|
226 |
| Const (@{const_name Pair}, _) $ _ $ _ => raise SAME ()
|
blanchet@33192
|
227 |
| Const (@{const_name Pair}, _) $ _ => raise SAME ()
|
blanchet@33192
|
228 |
| Const (@{const_name Pair}, _) => raise SAME ()
|
blanchet@33192
|
229 |
| Const (@{const_name fst}, _) $ _ => raise SAME ()
|
blanchet@33192
|
230 |
| Const (@{const_name fst}, _) => raise SAME ()
|
blanchet@33192
|
231 |
| Const (@{const_name snd}, _) $ _ => raise SAME ()
|
blanchet@33192
|
232 |
| Const (@{const_name snd}, _) => raise SAME ()
|
blanchet@33980
|
233 |
| Const (_, @{typ bool}) => atom_from_formula (to_F Ts t)
|
blanchet@33192
|
234 |
| Free (x as (_, T)) =>
|
blanchet@34118
|
235 |
Rel (arity_of RRep card T, find_index (curry (op =) x) frees)
|
blanchet@33192
|
236 |
| Term.Var _ => raise NOT_SUPPORTED "schematic variables"
|
blanchet@33192
|
237 |
| Bound j => raise SAME ()
|
blanchet@33192
|
238 |
| Abs (_, T, t') =>
|
blanchet@33192
|
239 |
(case fastype_of1 (T :: Ts, t') of
|
blanchet@33980
|
240 |
@{typ bool} => Comprehension (decls_for SRep card Ts T,
|
blanchet@33980
|
241 |
to_F (T :: Ts) t')
|
blanchet@33980
|
242 |
| T' => Comprehension (decls_for SRep card Ts T @
|
blanchet@33980
|
243 |
decls_for RRep card (T :: Ts) T',
|
blanchet@33980
|
244 |
Subset (rel_expr_for_bound_var card RRep
|
blanchet@33980
|
245 |
(T' :: T :: Ts) 0,
|
blanchet@33980
|
246 |
to_R_rep (T :: Ts) t')))
|
blanchet@33192
|
247 |
| t1 $ t2 =>
|
blanchet@33192
|
248 |
(case fastype_of1 (Ts, t) of
|
blanchet@33980
|
249 |
@{typ bool} => atom_from_formula (to_F Ts t)
|
blanchet@33192
|
250 |
| T =>
|
blanchet@33192
|
251 |
let val T2 = fastype_of1 (Ts, t2) in
|
blanchet@33980
|
252 |
case arity_of SRep card T2 of
|
blanchet@33980
|
253 |
1 => Join (to_S_rep Ts t2, to_R_rep Ts t1)
|
blanchet@33192
|
254 |
| n =>
|
blanchet@33192
|
255 |
let
|
blanchet@33980
|
256 |
val arity2 = arity_of SRep card T2
|
blanchet@33980
|
257 |
val res_arity = arity_of RRep card T
|
blanchet@33192
|
258 |
in
|
blanchet@33192
|
259 |
Project (Intersect
|
blanchet@33980
|
260 |
(Product (to_S_rep Ts t2,
|
blanchet@33980
|
261 |
atom_schema_of RRep card T
|
blanchet@33192
|
262 |
|> map (AtomSeq o rpair 0) |> foldl1 Product),
|
blanchet@33980
|
263 |
to_R_rep Ts t1),
|
blanchet@33192
|
264 |
num_seq arity2 res_arity)
|
blanchet@33192
|
265 |
end
|
blanchet@33192
|
266 |
end)
|
blanchet@33192
|
267 |
| _ => raise NOT_SUPPORTED ("term " ^
|
blanchet@33192
|
268 |
quote (Syntax.string_of_term ctxt t)))
|
blanchet@33980
|
269 |
handle SAME () => R_rep_from_S_rep (fastype_of1 (Ts, t)) (to_S_rep Ts t)
|
blanchet@33980
|
270 |
in to_F [] end
|
blanchet@33192
|
271 |
|
blanchet@33192
|
272 |
(* (typ -> int) -> int -> styp -> bound *)
|
blanchet@33980
|
273 |
fun bound_for_free card i (s, T) =
|
blanchet@33980
|
274 |
let val js = atom_schema_of RRep card T in
|
blanchet@33192
|
275 |
([((length js, i), s)],
|
blanchet@33980
|
276 |
[TupleSet [], atom_schema_of RRep card T |> map (rpair 0)
|
blanchet@33192
|
277 |
|> tuple_set_from_atom_schema])
|
blanchet@33192
|
278 |
end
|
blanchet@33192
|
279 |
|
blanchet@33192
|
280 |
(* (typ -> int) -> typ list -> typ -> rel_expr -> formula *)
|
blanchet@33980
|
281 |
fun declarative_axiom_for_rel_expr card Ts (Type ("fun", [T1, T2])) r =
|
blanchet@33192
|
282 |
if body_type T2 = bool_T then
|
blanchet@33192
|
283 |
True
|
blanchet@33192
|
284 |
else
|
blanchet@33980
|
285 |
All (decls_for SRep card Ts T1,
|
blanchet@33980
|
286 |
declarative_axiom_for_rel_expr card (T1 :: Ts) T2
|
blanchet@33980
|
287 |
(List.foldl Join r (vars_for_bound_var card SRep (T1 :: Ts) 0)))
|
blanchet@33192
|
288 |
| declarative_axiom_for_rel_expr _ _ _ r = One r
|
blanchet@33980
|
289 |
(* (typ -> int) -> bool -> int -> styp -> formula *)
|
blanchet@33980
|
290 |
fun declarative_axiom_for_free card i (_, T) =
|
blanchet@33980
|
291 |
declarative_axiom_for_rel_expr card [] T (Rel (arity_of RRep card T, i))
|
blanchet@33192
|
292 |
|
blanchet@33192
|
293 |
(* Proof.context -> (typ -> int) -> term -> string *)
|
blanchet@33980
|
294 |
fun pick_nits_in_term ctxt raw_card t =
|
blanchet@33192
|
295 |
let
|
blanchet@33192
|
296 |
val thy = ProofContext.theory_of ctxt
|
blanchet@33980
|
297 |
val {overlord, ...} = Nitpick_Isar.default_params thy []
|
blanchet@33192
|
298 |
(* typ -> int *)
|
blanchet@33980
|
299 |
fun card (Type ("fun", [T1, T2])) = reasonable_power (card T2) (card T1)
|
blanchet@33980
|
300 |
| card (Type ("*", [T1, T2])) = card T1 * card T2
|
blanchet@33980
|
301 |
| card @{typ bool} = 2
|
blanchet@33980
|
302 |
| card T = Int.max (1, raw_card T)
|
blanchet@33192
|
303 |
val neg_t = @{const Not} $ ObjectLogic.atomize_term thy t
|
blanchet@33192
|
304 |
val _ = fold_types (K o check_type ctxt) neg_t ()
|
blanchet@33192
|
305 |
val frees = Term.add_frees neg_t []
|
blanchet@33980
|
306 |
val bounds = map2 (bound_for_free card) (index_seq 0 (length frees)) frees
|
blanchet@33192
|
307 |
val declarative_axioms =
|
blanchet@33980
|
308 |
map2 (declarative_axiom_for_free card) (index_seq 0 (length frees)) frees
|
blanchet@33980
|
309 |
val formula = kodkod_formula_for_term ctxt card frees neg_t
|
blanchet@33192
|
310 |
|> fold_rev (curry And) declarative_axioms
|
blanchet@33192
|
311 |
val univ_card = univ_card 0 0 0 bounds formula
|
blanchet@33192
|
312 |
val problem =
|
blanchet@33192
|
313 |
{comment = "", settings = [], univ_card = univ_card, tuple_assigns = [],
|
blanchet@33192
|
314 |
bounds = bounds, int_bounds = [], expr_assigns = [], formula = formula}
|
blanchet@33192
|
315 |
in
|
blanchet@33980
|
316 |
case solve_any_problem overlord NONE 0 1 [problem] of
|
blanchet@34121
|
317 |
NotInstalled => "unknown"
|
blanchet@34121
|
318 |
| Normal ([], _) => "none"
|
blanchet@33192
|
319 |
| Normal _ => "genuine"
|
blanchet@33192
|
320 |
| TimedOut _ => "unknown"
|
blanchet@33192
|
321 |
| Interrupted _ => "unknown"
|
blanchet@33192
|
322 |
| Error (s, _) => error ("Kodkod error: " ^ s)
|
blanchet@33192
|
323 |
end
|
blanchet@33192
|
324 |
handle NOT_SUPPORTED details =>
|
blanchet@33192
|
325 |
(warning ("Unsupported case: " ^ details ^ "."); "unknown")
|
blanchet@33980
|
326 |
|
blanchet@33192
|
327 |
end;
|