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