src/HOL/Decision_Procs/MIR.thy
changeset 51143 0a2371e7ced3
parent 50252 4aa34bd43228
child 51272 9c8d63b4b6be
equal deleted inserted replaced
51142:ac9e909fe55d 51143:0a2371e7ced3
     2     Author:     Amine Chaieb
     2     Author:     Amine Chaieb
     3 *)
     3 *)
     4 
     4 
     5 theory MIR
     5 theory MIR
     6 imports Complex_Main Dense_Linear_Order DP_Library
     6 imports Complex_Main Dense_Linear_Order DP_Library
     7   "~~/src/HOL/Library/Efficient_Nat" "~~/src/HOL/Library/Old_Recdef"
     7   "~~/src/HOL/Library/Code_Target_Numeral" "~~/src/HOL/Library/Old_Recdef"
     8 begin
     8 begin
     9 
     9 
    10 section {* Quantifier elimination for @{text "\<real> (0, 1, +, floor, <)"} *}
    10 section {* Quantifier elimination for @{text "\<real> (0, 1, +, floor, <)"} *}
    11 
    11 
    12 declare real_of_int_floor_cancel [simp del]
    12 declare real_of_int_floor_cancel [simp del]
  5519   file "mir.ML"*)
  5519   file "mir.ML"*)
  5520 
  5520 
  5521 oracle mirfr_oracle = {* fn (proofs, ct) =>
  5521 oracle mirfr_oracle = {* fn (proofs, ct) =>
  5522 let
  5522 let
  5523 
  5523 
       
  5524 val mk_C = @{code C} o @{code int_of_integer};
       
  5525 val mk_Dvd = @{code Dvd} o apfst @{code int_of_integer};
       
  5526 val mk_Bound = @{code Bound} o @{code nat_of_integer};
       
  5527 
  5524 fun num_of_term vs (t as Free (xn, xT)) = (case AList.lookup (op =) vs t
  5528 fun num_of_term vs (t as Free (xn, xT)) = (case AList.lookup (op =) vs t
  5525      of NONE => error "Variable not found in the list!"
  5529      of NONE => error "Variable not found in the list!"
  5526       | SOME n => @{code Bound} n)
  5530       | SOME n => mk_Bound n)
  5527   | num_of_term vs @{term "real (0::int)"} = @{code C} 0
  5531   | num_of_term vs @{term "real (0::int)"} = mk_C 0
  5528   | num_of_term vs @{term "real (1::int)"} = @{code C} 1
  5532   | num_of_term vs @{term "real (1::int)"} = mk_C 1
  5529   | num_of_term vs @{term "0::real"} = @{code C} 0
  5533   | num_of_term vs @{term "0::real"} = mk_C 0
  5530   | num_of_term vs @{term "1::real"} = @{code C} 1
  5534   | num_of_term vs @{term "1::real"} = mk_C 1
  5531   | num_of_term vs (Bound i) = @{code Bound} i
  5535   | num_of_term vs (Bound i) = mk_Bound i
  5532   | num_of_term vs (@{term "uminus :: real \<Rightarrow> real"} $ t') = @{code Neg} (num_of_term vs t')
  5536   | num_of_term vs (@{term "uminus :: real \<Rightarrow> real"} $ t') = @{code Neg} (num_of_term vs t')
  5533   | num_of_term vs (@{term "op + :: real \<Rightarrow> real \<Rightarrow> real"} $ t1 $ t2) =
  5537   | num_of_term vs (@{term "op + :: real \<Rightarrow> real \<Rightarrow> real"} $ t1 $ t2) =
  5534       @{code Add} (num_of_term vs t1, num_of_term vs t2)
  5538       @{code Add} (num_of_term vs t1, num_of_term vs t2)
  5535   | num_of_term vs (@{term "op - :: real \<Rightarrow> real \<Rightarrow> real"} $ t1 $ t2) =
  5539   | num_of_term vs (@{term "op - :: real \<Rightarrow> real \<Rightarrow> real"} $ t1 $ t2) =
  5536       @{code Sub} (num_of_term vs t1, num_of_term vs t2)
  5540       @{code Sub} (num_of_term vs t1, num_of_term vs t2)
  5537   | num_of_term vs (@{term "op * :: real \<Rightarrow> real \<Rightarrow> real"} $ t1 $ t2) =
  5541   | num_of_term vs (@{term "op * :: real \<Rightarrow> real \<Rightarrow> real"} $ t1 $ t2) =
  5538       (case (num_of_term vs t1)
  5542       (case (num_of_term vs t1)
  5539        of @{code C} i => @{code Mul} (i, num_of_term vs t2)
  5543        of @{code C} i => @{code Mul} (i, num_of_term vs t2)
  5540         | _ => error "num_of_term: unsupported Multiplication")
  5544         | _ => error "num_of_term: unsupported Multiplication")
  5541   | num_of_term vs (@{term "real :: int \<Rightarrow> real"} $ (@{term "numeral :: _ \<Rightarrow> int"} $ t')) =
  5545   | num_of_term vs (@{term "real :: int \<Rightarrow> real"} $ (@{term "numeral :: _ \<Rightarrow> int"} $ t')) =
  5542       @{code C} (HOLogic.dest_num t')
  5546       mk_C (HOLogic.dest_num t')
  5543   | num_of_term vs (@{term "real :: int \<Rightarrow> real"} $ (@{term "neg_numeral :: _ \<Rightarrow> int"} $ t')) =
  5547   | num_of_term vs (@{term "real :: int \<Rightarrow> real"} $ (@{term "neg_numeral :: _ \<Rightarrow> int"} $ t')) =
  5544       @{code C} (~ (HOLogic.dest_num t'))
  5548       mk_C (~ (HOLogic.dest_num t'))
  5545   | num_of_term vs (@{term "real :: int \<Rightarrow> real"} $ (@{term "floor :: real \<Rightarrow> int"} $ t')) =
  5549   | num_of_term vs (@{term "real :: int \<Rightarrow> real"} $ (@{term "floor :: real \<Rightarrow> int"} $ t')) =
  5546       @{code Floor} (num_of_term vs t')
  5550       @{code Floor} (num_of_term vs t')
  5547   | num_of_term vs (@{term "real :: int \<Rightarrow> real"} $ (@{term "ceiling :: real \<Rightarrow> int"} $ t')) =
  5551   | num_of_term vs (@{term "real :: int \<Rightarrow> real"} $ (@{term "ceiling :: real \<Rightarrow> int"} $ t')) =
  5548       @{code Neg} (@{code Floor} (@{code Neg} (num_of_term vs t')))
  5552       @{code Neg} (@{code Floor} (@{code Neg} (num_of_term vs t')))
  5549   | num_of_term vs (@{term "numeral :: _ \<Rightarrow> real"} $ t') =
  5553   | num_of_term vs (@{term "numeral :: _ \<Rightarrow> real"} $ t') =
  5550       @{code C} (HOLogic.dest_num t')
  5554       mk_C (HOLogic.dest_num t')
  5551   | num_of_term vs (@{term "neg_numeral :: _ \<Rightarrow> real"} $ t') =
  5555   | num_of_term vs (@{term "neg_numeral :: _ \<Rightarrow> real"} $ t') =
  5552       @{code C} (~ (HOLogic.dest_num t'))
  5556       mk_C (~ (HOLogic.dest_num t'))
  5553   | num_of_term vs t = error ("num_of_term: unknown term " ^ Syntax.string_of_term @{context} t);
  5557   | num_of_term vs t = error ("num_of_term: unknown term " ^ Syntax.string_of_term @{context} t);
  5554 
  5558 
  5555 fun fm_of_term vs @{term True} = @{code T}
  5559 fun fm_of_term vs @{term True} = @{code T}
  5556   | fm_of_term vs @{term False} = @{code F}
  5560   | fm_of_term vs @{term False} = @{code F}
  5557   | fm_of_term vs (@{term "op < :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) =
  5561   | fm_of_term vs (@{term "op < :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) =
  5559   | fm_of_term vs (@{term "op \<le> :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) =
  5563   | fm_of_term vs (@{term "op \<le> :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) =
  5560       @{code Le} (@{code Sub} (num_of_term vs t1, num_of_term vs t2))
  5564       @{code Le} (@{code Sub} (num_of_term vs t1, num_of_term vs t2))
  5561   | fm_of_term vs (@{term "op = :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) =
  5565   | fm_of_term vs (@{term "op = :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) =
  5562       @{code Eq} (@{code Sub} (num_of_term vs t1, num_of_term vs t2)) 
  5566       @{code Eq} (@{code Sub} (num_of_term vs t1, num_of_term vs t2)) 
  5563   | fm_of_term vs (@{term "op rdvd"} $ (@{term "real :: int \<Rightarrow> real"} $ (@{term "numeral :: _ \<Rightarrow> int"} $ t1)) $ t2) =
  5567   | fm_of_term vs (@{term "op rdvd"} $ (@{term "real :: int \<Rightarrow> real"} $ (@{term "numeral :: _ \<Rightarrow> int"} $ t1)) $ t2) =
  5564       @{code Dvd} (HOLogic.dest_num t1, num_of_term vs t2)
  5568       mk_Dvd (HOLogic.dest_num t1, num_of_term vs t2)
  5565   | fm_of_term vs (@{term "op rdvd"} $ (@{term "real :: int \<Rightarrow> real"} $ (@{term "neg_numeral :: _ \<Rightarrow> int"} $ t1)) $ t2) =
  5569   | fm_of_term vs (@{term "op rdvd"} $ (@{term "real :: int \<Rightarrow> real"} $ (@{term "neg_numeral :: _ \<Rightarrow> int"} $ t1)) $ t2) =
  5566       @{code Dvd} (~ (HOLogic.dest_num t1), num_of_term vs t2)
  5570       mk_Dvd (~ (HOLogic.dest_num t1), num_of_term vs t2)
  5567   | fm_of_term vs (@{term "op = :: bool \<Rightarrow> bool \<Rightarrow> bool"} $ t1 $ t2) =
  5571   | fm_of_term vs (@{term "op = :: bool \<Rightarrow> bool \<Rightarrow> bool"} $ t1 $ t2) =
  5568       @{code Iff} (fm_of_term vs t1, fm_of_term vs t2)
  5572       @{code Iff} (fm_of_term vs t1, fm_of_term vs t2)
  5569   | fm_of_term vs (@{term HOL.conj} $ t1 $ t2) =
  5573   | fm_of_term vs (@{term HOL.conj} $ t1 $ t2) =
  5570       @{code And} (fm_of_term vs t1, fm_of_term vs t2)
  5574       @{code And} (fm_of_term vs t1, fm_of_term vs t2)
  5571   | fm_of_term vs (@{term HOL.disj} $ t1 $ t2) =
  5575   | fm_of_term vs (@{term HOL.disj} $ t1 $ t2) =
  5578       @{code E} (fm_of_term (map (fn (v, n) => (v, n + 1)) vs) p)
  5582       @{code E} (fm_of_term (map (fn (v, n) => (v, n + 1)) vs) p)
  5579   | fm_of_term vs (Const (@{const_name All}, _) $ Abs (xn, xT, p)) =
  5583   | fm_of_term vs (Const (@{const_name All}, _) $ Abs (xn, xT, p)) =
  5580       @{code A} (fm_of_term (map (fn (v, n) => (v, n + 1)) vs) p)
  5584       @{code A} (fm_of_term (map (fn (v, n) => (v, n + 1)) vs) p)
  5581   | fm_of_term vs t = error ("fm_of_term : unknown term " ^ Syntax.string_of_term @{context} t);
  5585   | fm_of_term vs t = error ("fm_of_term : unknown term " ^ Syntax.string_of_term @{context} t);
  5582 
  5586 
  5583 fun term_of_num vs (@{code C} i) = @{term "real :: int \<Rightarrow> real"} $ HOLogic.mk_number HOLogic.intT i
  5587 fun term_of_num vs (@{code C} i) = @{term "real :: int \<Rightarrow> real"} $
  5584   | term_of_num vs (@{code Bound} n) = fst (the (find_first (fn (_, m) => n = m) vs))
  5588       HOLogic.mk_number HOLogic.intT (@{code integer_of_int} i)
       
  5589   | term_of_num vs (@{code Bound} n) =
       
  5590       let
       
  5591         val m = @{code integer_of_nat} n;
       
  5592       in fst (the (find_first (fn (_, q) => m = q) vs)) end
  5585   | term_of_num vs (@{code Neg} (@{code Floor} (@{code Neg} t'))) =
  5593   | term_of_num vs (@{code Neg} (@{code Floor} (@{code Neg} t'))) =
  5586       @{term "real :: int \<Rightarrow> real"} $ (@{term "ceiling :: real \<Rightarrow> int"} $ term_of_num vs t')
  5594       @{term "real :: int \<Rightarrow> real"} $ (@{term "ceiling :: real \<Rightarrow> int"} $ term_of_num vs t')
  5587   | term_of_num vs (@{code Neg} t') = @{term "uminus :: real \<Rightarrow> real"} $ term_of_num vs t'
  5595   | term_of_num vs (@{code Neg} t') = @{term "uminus :: real \<Rightarrow> real"} $ term_of_num vs t'
  5588   | term_of_num vs (@{code Add} (t1, t2)) = @{term "op + :: real \<Rightarrow> real \<Rightarrow> real"} $
  5596   | term_of_num vs (@{code Add} (t1, t2)) = @{term "op + :: real \<Rightarrow> real \<Rightarrow> real"} $
  5589       term_of_num vs t1 $ term_of_num vs t2
  5597       term_of_num vs t1 $ term_of_num vs t2
  5658 
  5666 
  5659 lemma "ALL (x::real) (y::real). \<lfloor>x\<rfloor> = \<lfloor>y\<rfloor> \<longrightarrow> 0 \<le> abs (y - x) \<and> abs (y - x) \<le> 1"
  5667 lemma "ALL (x::real) (y::real). \<lfloor>x\<rfloor> = \<lfloor>y\<rfloor> \<longrightarrow> 0 \<le> abs (y - x) \<and> abs (y - x) \<le> 1"
  5660   by mir
  5668   by mir
  5661 
  5669 
  5662 end
  5670 end
       
  5671