1 (* $Id$ *) |
1 (* ID: $Id$ |
|
2 Author: Amine Chaieb, TU Muenchen |
2 |
3 |
3 (* Reification for the autimatically generated oracle for Presburger arithmetic |
4 Reification for the automatically generated oracle for Presburger arithmetic |
4 in HOL/ex/Reflected_Presburger.thy |
5 in HOL/ex/Reflected_Presburger.thy. |
5 Author : Amine Chaieb |
|
6 *) |
6 *) |
7 |
7 |
8 structure Coopereif = |
8 structure Coopereif = |
9 struct |
9 struct |
10 |
10 |
11 open GeneratedCooper; |
11 open GeneratedCooper; |
|
12 open Reflected_Presburger; |
12 |
13 |
13 fun i_of_term vs t = |
14 fun i_of_term vs t = case t |
14 case t of |
15 of Free(xn,xT) => (case AList.lookup (op aconv) vs t |
15 Free(xn,xT) => (case AList.lookup (op aconv) vs t of |
16 of NONE => error "Variable not found in the list!" |
16 NONE => error "Variable not found in the list!!" |
17 | SOME n => Bound n) |
17 | SOME n => Bound n) |
18 | @{term "0::int"} => C 0 |
18 | @{term "0::int"} => C 0 |
19 | @{term "1::int"} => C 1 |
19 | @{term "1::int"} => C 1 |
20 | Term.Bound i => Bound (Integer.nat i) |
20 | Term.Bound i => Bound (nat i) |
21 | Const(@{const_name "HOL.uminus"},_)$t' => Neg (i_of_term vs t') |
21 | Const(@{const_name "HOL.uminus"},_)$t' => Neg (i_of_term vs t') |
22 | Const(@{const_name "HOL.plus"},_)$t1$t2 => Add (i_of_term vs t1,i_of_term vs t2) |
22 | Const(@{const_name "HOL.plus"},_)$t1$t2 => Add (i_of_term vs t1,i_of_term vs t2) |
23 | Const(@{const_name "HOL.minus"},_)$t1$t2 => Sub (i_of_term vs t1,i_of_term vs t2) |
23 | Const(@{const_name "HOL.minus"},_)$t1$t2 => Sub (i_of_term vs t1,i_of_term vs t2) |
24 | Const(@{const_name "HOL.times"},_)$t1$t2 => (Mul (HOLogic.dest_number t1 |> snd,i_of_term vs t2) |
24 | Const(@{const_name "HOL.times"},_)$t1$t2 => |
|
25 (Mul (HOLogic.dest_number t1 |> snd,i_of_term vs t2) |
|
26 handle TERM _ => |
25 handle TERM _ => |
27 (Mul (HOLogic.dest_number t2 |> snd,i_of_term vs t1) |
26 (Mul (HOLogic.dest_number t2 |> snd,i_of_term vs t1) |
28 handle TERM _ => error "i_of_term: Unsupported kind of multiplication")) |
27 handle TERM _ => error "i_of_term: Unsupported kind of multiplication")) |
29 | _ => (C (HOLogic.dest_number t |> snd) |
28 | _ => (C (HOLogic.dest_number t |> snd) |
30 handle TERM _ => error "i_of_term: unknown term"); |
29 handle TERM _ => error "i_of_term: unknown term"); |
31 |
30 |
32 fun qf_of_term ps vs t = |
31 fun qf_of_term ps vs t = case t |
33 case t of |
32 of Const("True",_) => T |
34 Const("True",_) => T |
|
35 | Const("False",_) => F |
33 | Const("False",_) => F |
36 | Const(@{const_name "Orderings.less"},_)$t1$t2 => Lt (Sub (i_of_term vs t1,i_of_term vs t2)) |
34 | Const(@{const_name "Orderings.less"},_)$t1$t2 => Lt (Sub (i_of_term vs t1,i_of_term vs t2)) |
37 | Const(@{const_name "Orderings.less_eq"},_)$t1$t2 => Le (Sub(i_of_term vs t1,i_of_term vs t2)) |
35 | Const(@{const_name "Orderings.less_eq"},_)$t1$t2 => Le (Sub(i_of_term vs t1,i_of_term vs t2)) |
38 | Const(@{const_name "Divides.dvd"},_)$t1$t2 => |
36 | Const(@{const_name "Divides.dvd"},_)$t1$t2 => |
39 (Dvd(HOLogic.dest_number t1 |> snd, i_of_term vs t2) handle _ => error "qf_of_term: unsupported dvd") |
37 (Dvd(HOLogic.dest_number t1 |> snd, i_of_term vs t2) handle _ => error "qf_of_term: unsupported dvd") |
40 | @{term "op = :: int => _"}$t1$t2 => Eq (Sub (i_of_term vs t1,i_of_term vs t2)) |
38 | @{term "op = :: int => _"}$t1$t2 => Eq (Sub (i_of_term vs t1,i_of_term vs t2)) |
41 | @{term "op = :: bool => _ "}$t1$t2 => Iff(qf_of_term ps vs t1,qf_of_term ps vs t2) |
39 | @{term "op = :: bool => _ "}$t1$t2 => Iffa(qf_of_term ps vs t1,qf_of_term ps vs t2) |
42 | Const("op &",_)$t1$t2 => And(qf_of_term ps vs t1,qf_of_term ps vs t2) |
40 | Const("op &",_)$t1$t2 => And(qf_of_term ps vs t1,qf_of_term ps vs t2) |
43 | Const("op |",_)$t1$t2 => Or(qf_of_term ps vs t1,qf_of_term ps vs t2) |
41 | Const("op |",_)$t1$t2 => Or(qf_of_term ps vs t1,qf_of_term ps vs t2) |
44 | Const("op -->",_)$t1$t2 => Imp(qf_of_term ps vs t1,qf_of_term ps vs t2) |
42 | Const("op -->",_)$t1$t2 => Impa(qf_of_term ps vs t1,qf_of_term ps vs t2) |
45 | Const("Not",_)$t' => NOT(qf_of_term ps vs t') |
43 | Const("Not",_)$t' => Nota(qf_of_term ps vs t') |
46 | Const("Ex",_)$Abs(xn,xT,p) => |
44 | Const("Ex",_)$Abs(xn,xT,p) => |
47 let val (xn',p') = variant_abs (xn,xT,p) |
45 let val (xn',p') = variant_abs (xn,xT,p) |
48 val vs' = (Free (xn',xT), nat 0) :: (map (fn(v,n) => (v,1 + n)) vs) |
46 val vs' = (Free (xn',xT), Integer.nat 0) :: (map (fn(v,n) => (v,1 + n)) vs) |
49 in E (qf_of_term ps vs' p') |
47 in E (qf_of_term ps vs' p') |
50 end |
48 end |
51 | Const("All",_)$Abs(xn,xT,p) => |
49 | Const("All",_)$Abs(xn,xT,p) => |
52 let val (xn',p') = variant_abs (xn,xT,p) |
50 let val (xn',p') = variant_abs (xn,xT,p) |
53 val vs' = (Free (xn',xT), nat 0) :: (map (fn(v,n) => (v,1 + n)) vs) |
51 val vs' = (Free (xn',xT), Integer.nat 0) :: (map (fn(v,n) => (v,1 + n)) vs) |
54 in A (qf_of_term ps vs' p') |
52 in A (qf_of_term ps vs' p') |
55 end |
53 end |
56 | _ =>(case AList.lookup (op aconv) ps t of |
54 | _ =>(case AList.lookup (op aconv) ps t of |
57 NONE => error "qf_of_term ps : unknown term!" |
55 NONE => error "qf_of_term ps : unknown term!" |
58 | SOME n => Closed n); |
56 | SOME n => Closed n); |
59 |
57 |
60 local |
58 local |
61 val ops = [@{term "op &"}, @{term "op |"}, @{term "op -->"}, @{term "op = :: bool => _"}, |
59 val ops = [@{term "op &"}, @{term "op |"}, @{term "op -->"}, @{term "op = :: bool => _"}, |
62 @{term "op = :: int => _"}, @{term "op < :: int => _"}, |
60 @{term "op = :: int => _"}, @{term "op < :: int => _"}, |
63 @{term "op <= :: int => _"}, @{term "Not"}, @{term "All:: (int => _) => _"}, |
61 @{term "op <= :: int => _"}, @{term "Not"}, @{term "All:: (int => _) => _"}, |
64 @{term "Ex:: (int => _) => _"}, @{term "True"}, @{term "False"}] |
62 @{term "Ex:: (int => _) => _"}, @{term "True"}, @{term "False"}] |
65 fun ty t = Bool.not (fastype_of t = HOLogic.boolT) |
63 fun ty t = Bool.not (fastype_of t = HOLogic.boolT) |
66 in |
64 in |
67 fun term_bools acc t = |
65 |
68 case t of |
66 fun term_bools acc t = case t |
69 (l as f $ a) $ b => if ty t orelse f mem ops then term_bools (term_bools acc l)b |
67 of (l as f $ a) $ b => if ty t orelse f mem ops then term_bools (term_bools acc l)b |
70 else insert (op aconv) t acc |
68 else insert (op aconv) t acc |
71 | f $ a => if ty t orelse f mem ops then term_bools (term_bools acc f) a |
69 | f $ a => if ty t orelse f mem ops then term_bools (term_bools acc f) a |
72 else insert (op aconv) t acc |
70 else insert (op aconv) t acc |
73 | Abs p => term_bools acc (snd (variant_abs p)) |
71 | Abs p => term_bools acc (snd (variant_abs p)) |
74 | _ => if ty t orelse t mem ops then acc else insert (op aconv) t acc |
72 | _ => if ty t orelse t mem ops then acc else insert (op aconv) t acc |
|
73 |
75 end; |
74 end; |
76 |
|
77 |
75 |
78 fun start_vs t = |
76 fun start_vs t = |
79 let |
77 let |
80 val fs = term_frees t |
78 val fs = term_frees t |
81 val ps = term_bools [] t |
79 val ps = term_bools [] t |
82 in (fs ~~ (map nat (0 upto (length fs - 1))), |
80 in |
83 ps ~~ (map nat (0 upto (length ps - 1)))) |
81 (fs ~~ (map Integer.nat (0 upto (length fs - 1))), |
84 end ; |
82 ps ~~ (map Integer.nat (0 upto (length ps - 1)))) |
|
83 end; |
85 |
84 |
86 val iT = HOLogic.intT; |
85 fun term_of_i vs t = case t |
87 val bT = HOLogic.boolT; |
86 of C i => HOLogic.mk_number HOLogic.intT i |
88 fun myassoc2 l v = |
87 | Bound n => (fst o the) (find_first (fn (_, m) => m = n) vs) |
89 case l of |
88 | Neg t' => @{term "uminus :: int => _"} $ term_of_i vs t' |
90 [] => NONE |
89 | Add (t1, t2) => @{term "op +:: int => _"} $ term_of_i vs t1 $ term_of_i vs t2 |
91 | (x,v')::xs => if v = v' then SOME x |
90 | Sub (t1, t2) => Const (@{const_name "HOL.minus"}, HOLogic.intT --> HOLogic.intT --> HOLogic.intT) $ |
92 else myassoc2 xs v; |
91 term_of_i vs t1 $ term_of_i vs t2 |
|
92 | Mul (i, t2) => Const (@{const_name "HOL.times"}, HOLogic.intT --> HOLogic.intT --> HOLogic.intT) $ |
|
93 HOLogic.mk_number HOLogic.intT i $ term_of_i vs t2 |
|
94 | Cx (i, t') => term_of_i vs (Add (Mul (i, Bound (Integer.nat 0)), t')); |
93 |
95 |
94 fun term_of_i vs t = |
96 fun term_of_qf ps vs t = case t |
95 case t of |
97 of T => HOLogic.true_const |
96 C i => HOLogic.mk_number HOLogic.intT i |
98 | F => HOLogic.false_const |
97 | Bound n => valOf (myassoc2 vs n) |
99 | Lt t' => @{term "op < :: int => _ "}$ term_of_i vs t'$ @{term "0::int"} |
98 | Neg t' => @{term "uminus :: int => _"}$(term_of_i vs t') |
100 | Le t' => @{term "op <= :: int => _ "}$ term_of_i vs t' $ @{term "0::int"} |
99 | Add(t1,t2) => @{term "op +:: int => _"}$ (term_of_i vs t1)$(term_of_i vs t2) |
101 | Gt t' => @{term "op < :: int => _ "}$ @{term "0::int"}$ term_of_i vs t' |
100 | Sub(t1,t2) => Const(@{const_name "HOL.minus"},[iT,iT] ---> iT)$ |
102 | Ge t' => @{term "op <= :: int => _ "}$ @{term "0::int"}$ term_of_i vs t' |
101 (term_of_i vs t1)$(term_of_i vs t2) |
103 | Eq t' => @{term "op = :: int => _ "}$ term_of_i vs t'$ @{term "0::int"} |
102 | Mul(i,t2) => Const(@{const_name "HOL.times"},[iT,iT] ---> iT)$ |
104 | NEq t' => term_of_qf ps vs (Nota(Eq t')) |
103 (HOLogic.mk_number HOLogic.intT i)$(term_of_i vs t2) |
105 | Dvd(i,t') => @{term "op dvd :: int => _ "}$ |
104 | CX(i,t')=> term_of_i vs (Add(Mul (i,Bound (nat 0)),t')); |
106 (HOLogic.mk_number HOLogic.intT i)$(term_of_i vs t') |
105 |
107 | NDvd(i,t')=> term_of_qf ps vs (Nota(Dvd(i,t'))) |
106 fun term_of_qf ps vs t = |
108 | Nota t' => HOLogic.Not$(term_of_qf ps vs t') |
107 case t of |
109 | And(t1,t2) => HOLogic.conj$(term_of_qf ps vs t1)$(term_of_qf ps vs t2) |
108 T => HOLogic.true_const |
110 | Or(t1,t2) => HOLogic.disj$(term_of_qf ps vs t1)$(term_of_qf ps vs t2) |
109 | F => HOLogic.false_const |
111 | Impa(t1,t2) => HOLogic.imp$(term_of_qf ps vs t1)$(term_of_qf ps vs t2) |
110 | Lt t' => @{term "op < :: int => _ "}$ term_of_i vs t'$ @{term "0::int"} |
112 | Iffa(t1,t2) => HOLogic.eq_const HOLogic.boolT $ term_of_qf ps vs t1 $ term_of_qf ps vs t2 |
111 | Le t' => @{term "op <= :: int => _ "}$ term_of_i vs t' $ @{term "0::int"} |
113 | Closed n => (fst o the) (find_first (fn (_, m) => m = n) ps) |
112 | Gt t' => @{term "op < :: int => _ "}$ @{term "0::int"}$ term_of_i vs t' |
114 | NClosed n => term_of_qf ps vs (Nota (Closed n)) |
113 | Ge t' => @{term "op <= :: int => _ "}$ @{term "0::int"}$ term_of_i vs t' |
115 | _ => error "If this is raised, Isabelle/HOL or generate_code is inconsistent!"; |
114 | Eq t' => @{term "op = :: int => _ "}$ term_of_i vs t'$ @{term "0::int"} |
|
115 | NEq t' => term_of_qf ps vs (NOT(Eq t')) |
|
116 | Dvd(i,t') => @{term "op dvd :: int => _ "}$ |
|
117 (HOLogic.mk_number HOLogic.intT i)$(term_of_i vs t') |
|
118 | NDvd(i,t')=> term_of_qf ps vs (NOT(Dvd(i,t'))) |
|
119 | NOT t' => HOLogic.Not$(term_of_qf ps vs t') |
|
120 | And(t1,t2) => HOLogic.conj$(term_of_qf ps vs t1)$(term_of_qf ps vs t2) |
|
121 | Or(t1,t2) => HOLogic.disj$(term_of_qf ps vs t1)$(term_of_qf ps vs t2) |
|
122 | Imp(t1,t2) => HOLogic.imp$(term_of_qf ps vs t1)$(term_of_qf ps vs t2) |
|
123 | Iff(t1,t2) => (HOLogic.eq_const bT)$(term_of_qf ps vs t1)$ (term_of_qf ps vs t2) |
|
124 | Closed n => valOf (myassoc2 ps n) |
|
125 | NClosed n => term_of_qf ps vs (NOT (Closed n)) |
|
126 | _ => error "If this is raised, Isabelle/HOL or generate_code is inconsistent!"; |
|
127 |
116 |
128 (* The oracle *) |
117 (* The oracle *) |
129 fun cooper_oracle thy t = |
118 fun cooper_oracle thy t = |
130 let val (vs,ps) = start_vs t |
119 let |
131 in HOLogic.mk_Trueprop (HOLogic.mk_eq (t, term_of_qf ps vs (pa (qf_of_term ps vs t)))) |
120 val (vs, ps) = start_vs t; |
132 end; |
121 in HOLogic.mk_Trueprop (HOLogic.mk_eq (t, term_of_qf ps vs (pa (qf_of_term ps vs t)))) end; |
133 |
122 |
134 end; |
123 end; |