src/HOL/ex/coopereif.ML
changeset 23515 3e7f62e68fe4
parent 23317 90be000da2a7
child 23693 d92637b15a45
equal deleted inserted replaced
23514:25e69e56355d 23515:3e7f62e68fe4
     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;