| author | urbanc | 
| Thu, 23 Nov 2006 17:52:48 +0100 | |
| changeset 21488 | e1b260d204a0 | 
| parent 21416 | f23e4e75dfd3 | 
| child 21820 | 2f2b6a965ccc | 
| permissions | -rw-r--r-- | 
| 13876 | 1 | (* Title: HOL/Integ/cooper_dec.ML | 
| 2 | ID: $Id$ | |
| 3 | Author: Amine Chaieb and Tobias Nipkow, TU Muenchen | |
| 4 | ||
| 5 | File containing the implementation of Cooper Algorithm | |
| 6 | decision procedure (intensively inspired from J.Harrison) | |
| 7 | *) | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 8 | |
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 9 | |
| 13876 | 10 | signature COOPER_DEC = | 
| 11 | sig | |
| 12 | exception COOPER | |
| 13 | val is_arith_rel : term -> bool | |
| 16389 | 14 | val mk_numeral : IntInf.int -> term | 
| 15 | val dest_numeral : term -> IntInf.int | |
| 15164 | 16 | val is_numeral : term -> bool | 
| 13876 | 17 | val zero : term | 
| 18 | val one : term | |
| 16389 | 19 | val linear_cmul : IntInf.int -> term -> term | 
| 13876 | 20 | val linear_add : string list -> term -> term -> term | 
| 21 | val linear_sub : string list -> term -> term -> term | |
| 22 | val linear_neg : term -> term | |
| 23 | val lint : string list -> term -> term | |
| 24 | val linform : string list -> term -> term | |
| 16389 | 25 | val formlcm : term -> term -> IntInf.int | 
| 26 | val adjustcoeff : term -> IntInf.int -> term -> term | |
| 13876 | 27 | val unitycoeff : term -> term -> term | 
| 16389 | 28 | val divlcm : term -> term -> IntInf.int | 
| 13876 | 29 | val bset : term -> term -> term list | 
| 30 | val aset : term -> term -> term list | |
| 31 | val linrep : string list -> term -> term -> term -> term | |
| 32 | val list_disj : term list -> term | |
| 14758 
af3b71a46a1c
A new implementation for presburger arithmetic following the one suggested in technical report Chaieb Amine and Tobias Nipkow. It is generic an smaller.
 chaieb parents: 
13876diff
changeset | 33 | val list_conj : term list -> term | 
| 13876 | 34 | val simpl : term -> term | 
| 35 | val fv : term -> string list | |
| 36 | val negate : term -> term | |
| 16389 | 37 | val operations : (string * (IntInf.int * IntInf.int -> bool)) list | 
| 14758 
af3b71a46a1c
A new implementation for presburger arithmetic following the one suggested in technical report Chaieb Amine and Tobias Nipkow. It is generic an smaller.
 chaieb parents: 
13876diff
changeset | 38 | val conjuncts : term -> term list | 
| 
af3b71a46a1c
A new implementation for presburger arithmetic following the one suggested in technical report Chaieb Amine and Tobias Nipkow. It is generic an smaller.
 chaieb parents: 
13876diff
changeset | 39 | val disjuncts : term -> term list | 
| 
af3b71a46a1c
A new implementation for presburger arithmetic following the one suggested in technical report Chaieb Amine and Tobias Nipkow. It is generic an smaller.
 chaieb parents: 
13876diff
changeset | 40 | val has_bound : term -> bool | 
| 
af3b71a46a1c
A new implementation for presburger arithmetic following the one suggested in technical report Chaieb Amine and Tobias Nipkow. It is generic an smaller.
 chaieb parents: 
13876diff
changeset | 41 | val minusinf : term -> term -> term | 
| 
af3b71a46a1c
A new implementation for presburger arithmetic following the one suggested in technical report Chaieb Amine and Tobias Nipkow. It is generic an smaller.
 chaieb parents: 
13876diff
changeset | 42 | val plusinf : term -> term -> term | 
| 14877 | 43 | val onatoms : (term -> term) -> term -> term | 
| 44 | val evalc : term -> term | |
| 15107 | 45 | val cooper_w : string list -> term -> (term option * term) | 
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 46 | val integer_qelim : Term.term -> Term.term | 
| 13876 | 47 | end; | 
| 48 | ||
| 20500 | 49 | structure CooperDec : COOPER_DEC = | 
| 13876 | 50 | struct | 
| 51 | ||
| 52 | (* ========================================================================= *) | |
| 53 | (* Cooper's algorithm for Presburger arithmetic. *) | |
| 54 | (* ========================================================================= *) | |
| 55 | exception COOPER; | |
| 56 | ||
| 14941 | 57 | |
| 13876 | 58 | (* ------------------------------------------------------------------------- *) | 
| 59 | (* Lift operations up to numerals. *) | |
| 60 | (* ------------------------------------------------------------------------- *) | |
| 61 | ||
| 62 | (*Assumption : The construction of atomar formulas in linearl arithmetic is based on | |
| 16389 | 63 | relation operations of Type : [IntInf.int,IntInf.int]---> bool *) | 
| 13876 | 64 | |
| 65 | (* ------------------------------------------------------------------------- *) | |
| 66 | ||
| 67 | (*Function is_arith_rel returns true if and only if the term is an atomar presburger | |
| 68 | formula *) | |
| 20500 | 69 | fun is_arith_rel tm = case tm | 
| 70 |  of Const(p, Type ("fun", [Type ("IntDef.int", []), Type ("fun", [Type ("IntDef.int", []),
 | |
| 71 |       Type ("bool", [])])])) $ _ $_ => true
 | |
| 72 | | _ => false; | |
| 13876 | 73 | |
| 74 | (*Function is_arith_rel returns true if and only if the term is an operation of the | |
| 75 | form [int,int]---> int*) | |
| 76 | ||
| 77 | (*Transform a natural number to a term*) | |
| 78 | ||
| 20713 
823967ef47f1
renamed 0 and 1 to HOL.zero and HOL.one respectivly; introduced corresponding syntactic classes
 haftmann parents: 
20500diff
changeset | 79 | fun mk_numeral 0 = Const("HOL.zero",HOLogic.intT)
 | 
| 
823967ef47f1
renamed 0 and 1 to HOL.zero and HOL.one respectivly; introduced corresponding syntactic classes
 haftmann parents: 
20500diff
changeset | 80 |    |mk_numeral 1 = Const("HOL.one",HOLogic.intT)
 | 
| 19481 
a6205c6203ea
renamed HOLogic.mk_bin to mk_binum for consistency with dest_binum
 paulson parents: 
19277diff
changeset | 81 | |mk_numeral n = (HOLogic.number_of_const HOLogic.intT) $ (HOLogic.mk_binum n); | 
| 13876 | 82 | |
| 83 | (*Transform an Term to an natural number*) | |
| 84 | ||
| 20713 
823967ef47f1
renamed 0 and 1 to HOL.zero and HOL.one respectivly; introduced corresponding syntactic classes
 haftmann parents: 
20500diff
changeset | 85 | fun dest_numeral (Const("HOL.zero",Type ("IntDef.int", []))) = 0
 | 
| 
823967ef47f1
renamed 0 and 1 to HOL.zero and HOL.one respectivly; introduced corresponding syntactic classes
 haftmann parents: 
20500diff
changeset | 86 |    |dest_numeral (Const("HOL.one",Type ("IntDef.int", []))) = 1
 | 
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 87 |    |dest_numeral (Const ("Numeral.number_of",_) $ n) = 
 | 
| 16389 | 88 | HOLogic.dest_binum n; | 
| 15661 
9ef583b08647
reverted renaming of Some/None in comments and strings;
 wenzelm parents: 
15574diff
changeset | 89 | (*Some terms often used for pattern matching*) | 
| 13876 | 90 | |
| 91 | val zero = mk_numeral 0; | |
| 92 | val one = mk_numeral 1; | |
| 93 | ||
| 94 | (*Tests if a Term is representing a number*) | |
| 95 | ||
| 96 | fun is_numeral t = (t = zero) orelse (t = one) orelse (can dest_numeral t); | |
| 97 | ||
| 98 | (*maps a unary natural function on a term containing an natural number*) | |
| 99 | ||
| 100 | fun numeral1 f n = mk_numeral (f(dest_numeral n)); | |
| 101 | ||
| 102 | (*maps a binary natural function on 2 term containing natural numbers*) | |
| 103 | ||
| 104 | fun numeral2 f m n = mk_numeral(f(dest_numeral m) (dest_numeral n)); | |
| 105 | ||
| 106 | (* ------------------------------------------------------------------------- *) | |
| 107 | (* Operations on canonical linear terms c1 * x1 + ... + cn * xn + k *) | |
| 108 | (* *) | |
| 109 | (* Note that we're quite strict: the ci must be present even if 1 *) | |
| 110 | (* (but if 0 we expect the monomial to be omitted) and k must be there *) | |
| 111 | (* even if it's zero. Thus, it's a constant iff not an addition term. *) | |
| 16389 | 112 | (* ------------------------------------------------------------------------- *) | 
| 13876 | 113 | |
| 114 | ||
| 115 | fun linear_cmul n tm = if n = 0 then zero else let fun times n k = n*k in | |
| 116 | ( case tm of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 117 |      (Const("HOL.plus",T)  $  (Const ("HOL.times",T1 ) $c1 $  x1) $ rest) => 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 118 |        Const("HOL.plus",T) $ ((Const("HOL.times",T1) $ (numeral1 (times n) c1) $ x1)) $ (linear_cmul n rest) 
 | 
| 13876 | 119 | |_ => numeral1 (times n) tm) | 
| 120 | end ; | |
| 121 | ||
| 122 | ||
| 123 | ||
| 124 | ||
| 125 | (* Whether the first of two items comes earlier in the list *) | |
| 126 | fun earlier [] x y = false | |
| 127 | |earlier (h::t) x y =if h = y then false | |
| 128 | else if h = x then true | |
| 129 | else earlier t x y ; | |
| 130 | ||
| 131 | fun earlierv vars (Bound i) (Bound j) = i < j | |
| 132 | |earlierv vars (Bound _) _ = true | |
| 133 | |earlierv vars _ (Bound _) = false | |
| 134 | |earlierv vars (Free (x,_)) (Free (y,_)) = earlier vars x y; | |
| 135 | ||
| 136 | ||
| 137 | fun linear_add vars tm1 tm2 = | |
| 138 | let fun addwith x y = x + y in | |
| 139 | (case (tm1,tm2) of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 140 | 	((Const ("HOL.plus",T1) $ ( Const("HOL.times",T2) $ c1 $  x1) $ rest1),(Const 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 141 | 	("HOL.plus",T3)$( Const("HOL.times",T4) $ c2 $  x2) $ rest2)) => 
 | 
| 13876 | 142 | if x1 = x2 then | 
| 143 | let val c = (numeral2 (addwith) c1 c2) | |
| 144 | in | |
| 145 | if c = zero then (linear_add vars rest1 rest2) | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 146 | 	      else (Const("HOL.plus",T1) $ (Const("HOL.times",T2) $ c $ x1) $ (linear_add vars  rest1 rest2)) 
 | 
| 13876 | 147 | end | 
| 148 | else | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 149 | 		if earlierv vars x1 x2 then (Const("HOL.plus",T1) $  
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 150 | 		(Const("HOL.times",T2)$ c1 $ x1) $ (linear_add vars rest1 tm2)) 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 151 |     	       else (Const("HOL.plus",T1) $ (Const("HOL.times",T2) $ c2 $ x2) $ (linear_add vars tm1 rest2)) 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 152 |    	|((Const("HOL.plus",T1) $ (Const("HOL.times",T2) $ c1 $ x1) $ rest1) ,_) => 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 153 |     	  (Const("HOL.plus",T1)$ (Const("HOL.times",T2) $ c1 $ x1) $ (linear_add vars 
 | 
| 13876 | 154 | rest1 tm2)) | 
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 155 |    	|(_, (Const("HOL.plus",T1) $(Const("HOL.times",T2) $ c2 $ x2) $ rest2)) => 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 156 |       	  (Const("HOL.plus",T1) $ (Const("HOL.times",T2) $ c2 $ x2) $ (linear_add vars tm1 
 | 
| 13876 | 157 | rest2)) | 
| 158 | | (_,_) => numeral2 (addwith) tm1 tm2) | |
| 159 | ||
| 160 | end; | |
| 161 | ||
| 162 | (*To obtain the unary - applyed on a formula*) | |
| 163 | ||
| 164 | fun linear_neg tm = linear_cmul (0 - 1) tm; | |
| 165 | ||
| 166 | (*Substraction of two terms *) | |
| 167 | ||
| 168 | fun linear_sub vars tm1 tm2 = linear_add vars tm1 (linear_neg tm2); | |
| 169 | ||
| 170 | ||
| 171 | (* ------------------------------------------------------------------------- *) | |
| 172 | (* Linearize a term. *) | |
| 173 | (* ------------------------------------------------------------------------- *) | |
| 174 | ||
| 175 | (* linearises a term from the point of view of Variable Free (x,T). | |
| 176 | After this fuction the all expressions containig ths variable will have the form | |
| 177 | c*Free(x,T) + t where c is a constant ant t is a Term which is not containing | |
| 178 | Free(x,T)*) | |
| 179 | ||
| 180 | fun lint vars tm = if is_numeral tm then tm else case tm of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 181 | (Free (x,T)) => (HOLogic.mk_binop "HOL.plus" ((HOLogic.mk_binop "HOL.times" ((mk_numeral 1),Free (x,T))), zero)) | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 182 |   |(Bound i) =>  (Const("HOL.plus",HOLogic.intT -->HOLogic.intT -->HOLogic.intT) $ 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 183 |   (Const("HOL.times",HOLogic.intT -->HOLogic.intT -->HOLogic.intT) $ (mk_numeral 1) $ (Bound i)) $ zero) 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 184 |   |(Const("HOL.uminus",_) $ t ) => (linear_neg (lint vars t)) 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 185 |   |(Const("HOL.plus",_) $ s $ t) => (linear_add vars (lint vars s) (lint vars t)) 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 186 |   |(Const("HOL.minus",_) $ s $ t) => (linear_sub vars (lint vars s) (lint vars t)) 
 | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 187 |   |(Const ("HOL.times",_) $ s $ t) => 
 | 
| 13876 | 188 | let val s' = lint vars s | 
| 189 | val t' = lint vars t | |
| 190 | in | |
| 191 | if is_numeral s' then (linear_cmul (dest_numeral s') t') | |
| 192 | else if is_numeral t' then (linear_cmul (dest_numeral t') s') | |
| 193 | ||
| 16299 
872ad146bb14
Some error messages have been eliminated as suggested by Tobias Nipkow
 chaieb parents: 
15965diff
changeset | 194 | else raise COOPER | 
| 13876 | 195 | end | 
| 16299 
872ad146bb14
Some error messages have been eliminated as suggested by Tobias Nipkow
 chaieb parents: 
15965diff
changeset | 196 | |_ => raise COOPER; | 
| 13876 | 197 | |
| 198 | ||
| 199 | ||
| 200 | (* ------------------------------------------------------------------------- *) | |
| 201 | (* Linearize the atoms in a formula, and eliminate non-strict inequalities. *) | |
| 202 | (* ------------------------------------------------------------------------- *) | |
| 203 | ||
| 204 | fun mkatom vars p t = Const(p,HOLogic.intT --> HOLogic.intT --> HOLogic.boolT) $ zero $ (lint vars t); | |
| 205 | ||
| 21416 | 206 | fun linform vars (Const ("Divides.dvd",_) $ c $ t) =
 | 
| 15164 | 207 | if is_numeral c then | 
| 13876 | 208 | let val c' = (mk_numeral(abs(dest_numeral c))) | 
| 21416 | 209 | in (HOLogic.mk_binrel "Divides.dvd" (c,lint vars t)) | 
| 13876 | 210 | end | 
| 15164 | 211 | else (warning "Nonlinear term --- Non numeral leftside at dvd" | 
| 212 | ;raise COOPER) | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 213 |   |linform vars  (Const("op =",Type ("fun",[Type ("IntDef.int", []),_])) $ s $ t ) = (mkatom vars "op =" (Const ("HOL.minus",HOLogic.intT --> HOLogic.intT --> HOLogic.intT) $ t $ s) ) 
 | 
| 19277 | 214 |   |linform vars  (Const("Orderings.less",_)$ s $t ) = (mkatom vars "Orderings.less" (Const ("HOL.minus",HOLogic.intT --> HOLogic.intT --> HOLogic.intT) $ t $ s))
 | 
| 215 |   |linform vars  (Const("op >",_) $ s $ t ) = (mkatom vars "Orderings.less" (Const ("HOL.minus",HOLogic.intT --> HOLogic.intT --> HOLogic.intT) $ s $ t)) 
 | |
| 216 |   |linform vars  (Const("Orderings.less_eq",_)$ s $ t ) = 
 | |
| 217 |         (mkatom vars "Orderings.less" (Const ("HOL.minus",HOLogic.intT --> HOLogic.intT --> HOLogic.intT) $ (Const("HOL.plus",HOLogic.intT --> HOLogic.intT --> HOLogic.intT) $t $(mk_numeral 1)) $ s)) 
 | |
| 13876 | 218 |   |linform vars  (Const("op >=",_)$ s $ t ) = 
 | 
| 19277 | 219 |         (mkatom vars "Orderings.less" (Const ("HOL.minus",HOLogic.intT --> HOLogic.intT --> 
 | 
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 220 | 	HOLogic.intT) $ (Const("HOL.plus",HOLogic.intT --> HOLogic.intT --> 
 | 
| 13876 | 221 | HOLogic.intT) $s $(mk_numeral 1)) $ t)) | 
| 222 | ||
| 223 | |linform vars fm = fm; | |
| 224 | ||
| 225 | (* ------------------------------------------------------------------------- *) | |
| 226 | (* Post-NNF transformation eliminating negated inequalities. *) | |
| 227 | (* ------------------------------------------------------------------------- *) | |
| 228 | ||
| 229 | fun posineq fm = case fm of | |
| 19277 | 230 |  (Const ("Not",_)$(Const("Orderings.less",_)$ c $ t)) =>
 | 
| 231 | (HOLogic.mk_binrel "Orderings.less" (zero , (linear_sub [] (mk_numeral 1) (linear_add [] c t ) ))) | |
| 13876 | 232 |   | ( Const ("op &",_) $ p $ q)  => HOLogic.mk_conj (posineq p,posineq q)
 | 
| 233 |   | ( Const ("op |",_) $ p $ q ) => HOLogic.mk_disj (posineq p,posineq q)
 | |
| 234 | | _ => fm; | |
| 235 | ||
| 236 | ||
| 237 | (* ------------------------------------------------------------------------- *) | |
| 238 | (* Find the LCM of the coefficients of x. *) | |
| 239 | (* ------------------------------------------------------------------------- *) | |
| 240 | (*gcd calculates gcd (a,b) and helps lcm_num calculating lcm (a,b)*) | |
| 241 | ||
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 242 | (*BEWARE: replaces Library.gcd!! There is also Library.lcm!*) | 
| 16398 | 243 | fun gcd (a:IntInf.int) b = if a=0 then b else gcd (b mod a) a ; | 
| 13876 | 244 | fun lcm_num a b = (abs a*b) div (gcd (abs a) (abs b)); | 
| 245 | ||
| 246 | fun formlcm x fm = case fm of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 247 |     (Const (p,_)$ _ $(Const ("HOL.plus", _)$(Const ("HOL.times",_)$ c $ y ) $z ) ) =>  if 
 | 
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 248 | (is_arith_rel fm) andalso (x = y) then (abs(dest_numeral c)) else 1 | 
| 13876 | 249 |   | ( Const ("Not", _) $p) => formlcm x p 
 | 
| 250 |   | ( Const ("op &",_) $ p $ q) => lcm_num (formlcm x p) (formlcm x q) 
 | |
| 251 |   | ( Const ("op |",_) $ p $ q )=> lcm_num (formlcm x p) (formlcm x q) 
 | |
| 252 | | _ => 1; | |
| 253 | ||
| 254 | (* ------------------------------------------------------------------------- *) | |
| 255 | (* Adjust all coefficients of x in formula; fold in reduction to +/- 1. *) | |
| 256 | (* ------------------------------------------------------------------------- *) | |
| 257 | ||
| 258 | fun adjustcoeff x l fm = | |
| 259 | case fm of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 260 |       (Const(p,_) $d $( Const ("HOL.plus", _)$(Const ("HOL.times",_) $ 
 | 
| 13876 | 261 | c $ y ) $z )) => if (is_arith_rel fm) andalso (x = y) then | 
| 262 | let val m = l div (dest_numeral c) | |
| 19277 | 263 | val n = (if p = "Orderings.less" then abs(m) else m) | 
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 264 | val xtm = HOLogic.mk_binop "HOL.times" ((mk_numeral (m div n)), x) | 
| 13876 | 265 | in | 
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 266 | (HOLogic.mk_binrel p ((linear_cmul n d),(HOLogic.mk_binop "HOL.plus" ( xtm ,( linear_cmul n z) )))) | 
| 13876 | 267 | end | 
| 268 | else fm | |
| 269 |   |( Const ("Not", _) $ p) => HOLogic.Not $ (adjustcoeff x l p) 
 | |
| 270 |   |( Const ("op &",_) $ p $ q) => HOLogic.conj$(adjustcoeff x l p) $(adjustcoeff x l q) 
 | |
| 271 |   |( Const ("op |",_) $ p $ q) => HOLogic.disj $(adjustcoeff x l p)$ (adjustcoeff x l q) 
 | |
| 272 | |_ => fm; | |
| 273 | ||
| 274 | (* ------------------------------------------------------------------------- *) | |
| 275 | (* Hence make coefficient of x one in existential formula. *) | |
| 276 | (* ------------------------------------------------------------------------- *) | |
| 277 | ||
| 278 | fun unitycoeff x fm = | |
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 279 | let val l = formlcm x fm | 
| 13876 | 280 | val fm' = adjustcoeff x l fm in | 
| 15267 | 281 | if l = 1 then fm' | 
| 282 | else | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 283 | let val xp = (HOLogic.mk_binop "HOL.plus" | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 284 | ((HOLogic.mk_binop "HOL.times" ((mk_numeral 1), x )), zero)) | 
| 15267 | 285 | in | 
| 21416 | 286 | HOLogic.conj $(HOLogic.mk_binrel "Divides.dvd" ((mk_numeral l) , xp )) $ (adjustcoeff x l fm) | 
| 13876 | 287 | end | 
| 288 | end; | |
| 289 | ||
| 290 | (* adjustcoeffeq l fm adjusts the coeffitients c_i of x overall in fm to l*) | |
| 291 | (* Here l must be a multiple of all c_i otherwise the obtained formula is not equivalent*) | |
| 292 | (* | |
| 293 | fun adjustcoeffeq x l fm = | |
| 294 | case fm of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 295 |       (Const(p,_) $d $( Const ("HOL.plus", _)$(Const ("HOL.times",_) $ 
 | 
| 13876 | 296 | c $ y ) $z )) => if (is_arith_rel fm) andalso (x = y) then | 
| 297 | let val m = l div (dest_numeral c) | |
| 19277 | 298 | val n = (if p = "Orderings.less" then abs(m) else m) | 
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 299 | val xtm = (HOLogic.mk_binop "HOL.times" ((mk_numeral ((m div n)*l) ), x)) | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 300 | in (HOLogic.mk_binrel p ((linear_cmul n d),(HOLogic.mk_binop "HOL.plus" ( xtm ,( linear_cmul n z) )))) | 
| 13876 | 301 | end | 
| 302 | else fm | |
| 303 |   |( Const ("Not", _) $ p) => HOLogic.Not $ (adjustcoeffeq x l p) 
 | |
| 304 |   |( Const ("op &",_) $ p $ q) => HOLogic.conj$(adjustcoeffeq x l p) $(adjustcoeffeq x l q) 
 | |
| 305 |   |( Const ("op |",_) $ p $ q) => HOLogic.disj $(adjustcoeffeq x l p)$ (adjustcoeffeq x l q) 
 | |
| 306 | |_ => fm; | |
| 307 | ||
| 308 | ||
| 309 | *) | |
| 310 | ||
| 311 | (* ------------------------------------------------------------------------- *) | |
| 312 | (* The "minus infinity" version. *) | |
| 313 | (* ------------------------------------------------------------------------- *) | |
| 314 | ||
| 315 | fun minusinf x fm = case fm of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 316 |     (Const("op =",Type ("fun",[Type ("IntDef.int", []),_])) $ (c1 ) $(Const ("HOL.plus", _) $(Const ("HOL.times",_) $ c2 $ y) $z)) => 
 | 
| 13876 | 317 | if (is_arith_rel fm) andalso (x=y) andalso (c2 = one) andalso (c1 =zero) then HOLogic.false_const | 
| 318 | else fm | |
| 319 | ||
| 19277 | 320 |   |(Const("Orderings.less",_) $ c $(Const ("HOL.plus", _) $(Const ("HOL.times",_) $ pm1 $ y ) $ z 
 | 
| 15859 | 321 | )) => if (x = y) | 
| 322 | then if (pm1 = one) andalso (c = zero) then HOLogic.false_const | |
| 323 | else if (dest_numeral pm1 = ~1) andalso (c = zero) then HOLogic.true_const | |
| 324 | else error "minusinf : term not in normal form!!!" | |
| 325 | else fm | |
| 13876 | 326 | |
| 327 |   |(Const ("Not", _) $ p) => HOLogic.Not $ (minusinf x p) 
 | |
| 328 |   |(Const ("op &",_) $ p $ q) => HOLogic.conj $ (minusinf x p) $ (minusinf x q) 
 | |
| 329 |   |(Const ("op |",_) $ p $ q) => HOLogic.disj $ (minusinf x p) $ (minusinf x q) 
 | |
| 330 | |_ => fm; | |
| 331 | ||
| 332 | (* ------------------------------------------------------------------------- *) | |
| 333 | (* The "Plus infinity" version. *) | |
| 334 | (* ------------------------------------------------------------------------- *) | |
| 335 | ||
| 336 | fun plusinf x fm = case fm of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 337 |     (Const("op =",Type ("fun",[Type ("IntDef.int", []),_])) $ (c1 ) $(Const ("HOL.plus", _) $(Const ("HOL.times",_) $ c2 $ y) $z)) =>
 | 
| 13876 | 338 | if (is_arith_rel fm) andalso (x=y) andalso (c2 = one) andalso (c1 =zero) then HOLogic.false_const | 
| 339 | else fm | |
| 340 | ||
| 19277 | 341 |   |(Const("Orderings.less",_) $ c $(Const ("HOL.plus", _) $(Const ("HOL.times",_) $ pm1 $ y ) $ z
 | 
| 15859 | 342 | )) => if (x = y) | 
| 343 | then if (pm1 = one) andalso (c = zero) then HOLogic.true_const | |
| 344 | else if (dest_numeral pm1 = ~1) andalso (c = zero) then HOLogic.false_const | |
| 345 | else error "plusinf : term not in normal form!!!" | |
| 346 | else fm | |
| 13876 | 347 | |
| 348 |   |(Const ("Not", _) $ p) => HOLogic.Not $ (plusinf x p)
 | |
| 349 |   |(Const ("op &",_) $ p $ q) => HOLogic.conj $ (plusinf x p) $ (plusinf x q)
 | |
| 350 |   |(Const ("op |",_) $ p $ q) => HOLogic.disj $ (plusinf x p) $ (plusinf x q)
 | |
| 351 | |_ => fm; | |
| 352 | ||
| 353 | (* ------------------------------------------------------------------------- *) | |
| 354 | (* The LCM of all the divisors that involve x. *) | |
| 355 | (* ------------------------------------------------------------------------- *) | |
| 356 | ||
| 21416 | 357 | fun divlcm x (Const("Divides.dvd",_)$ d $ (Const ("HOL.plus",_) $ (Const ("HOL.times",_) $ c $ y ) $ z ) ) =  
 | 
| 13876 | 358 | if x = y then abs(dest_numeral d) else 1 | 
| 359 |   |divlcm x ( Const ("Not", _) $ p) = divlcm x p 
 | |
| 360 |   |divlcm x ( Const ("op &",_) $ p $ q) = lcm_num (divlcm x p) (divlcm x q) 
 | |
| 361 |   |divlcm x ( Const ("op |",_) $ p $ q ) = lcm_num (divlcm x p) (divlcm x q) 
 | |
| 362 | |divlcm x _ = 1; | |
| 363 | ||
| 364 | (* ------------------------------------------------------------------------- *) | |
| 365 | (* Construct the B-set. *) | |
| 366 | (* ------------------------------------------------------------------------- *) | |
| 367 | ||
| 368 | fun bset x fm = case fm of | |
| 369 |    (Const ("Not", _) $ p) => if (is_arith_rel p) then  
 | |
| 370 | (case p of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 371 | 	      (Const("op =",Type ("fun",[Type ("IntDef.int", []),_])) $ c1 $ (Const ("HOL.plus", _) $(Const ("HOL.times",_) $c2 $y) $a ) )  
 | 
| 13876 | 372 | => if (is_arith_rel p) andalso (x= y) andalso (c2 = one) andalso (c1 = zero) | 
| 373 | then [linear_neg a] | |
| 374 | else bset x p | |
| 375 | |_ =>[]) | |
| 376 | ||
| 377 | else bset x p | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 378 |   |(Const ("op =",Type ("fun",[Type ("IntDef.int", []),_])) $ c1 $ (Const ("HOL.plus",_) $ (Const ("HOL.times",_) $c2 $ x) $ a)) =>  if (c1 =zero) andalso (c2 = one) then [linear_neg(linear_add [] a (mk_numeral 1))]  else [] 
 | 
| 19277 | 379 |   |(Const ("Orderings.less",_) $ c1$ (Const ("HOL.plus",_) $(Const ("HOL.times",_)$ c2 $ x) $ a)) => if (c1 =zero) andalso (c2 = one) then [linear_neg a] else [] 
 | 
| 13876 | 380 |   |(Const ("op &",_) $ p $ q) => (bset x p) union (bset x q) 
 | 
| 381 |   |(Const ("op |",_) $ p $ q) => (bset x p) union (bset x q) 
 | |
| 382 | |_ => []; | |
| 383 | ||
| 384 | (* ------------------------------------------------------------------------- *) | |
| 385 | (* Construct the A-set. *) | |
| 386 | (* ------------------------------------------------------------------------- *) | |
| 387 | ||
| 388 | fun aset x fm = case fm of | |
| 389 |    (Const ("Not", _) $ p) => if (is_arith_rel p) then
 | |
| 390 | (case p of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 391 | 	      (Const("op =",Type ("fun",[Type ("IntDef.int", []),_])) $ c1 $ (Const ("HOL.plus", _) $(Const ("HOL.times",_) $c2 $y) $a ) )
 | 
| 13876 | 392 | => if (x= y) andalso (c2 = one) andalso (c1 = zero) | 
| 393 | then [linear_neg a] | |
| 394 | else [] | |
| 395 | |_ =>[]) | |
| 396 | ||
| 397 | else aset x p | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 398 |   |(Const ("op =",Type ("fun",[Type ("IntDef.int", []),_])) $ c1 $ (Const ("HOL.plus",_) $ (Const ("HOL.times",_) $c2 $ x) $ a)) =>  if (c1 =zero) andalso (c2 = one) then [linear_sub [] (mk_numeral 1) a]  else []
 | 
| 19277 | 399 |   |(Const ("Orderings.less",_) $ c1$ (Const ("HOL.plus",_) $(Const ("HOL.times",_)$ c2 $ x) $ a)) => if (c1 =zero) andalso (c2 = (mk_numeral (~1))) then [a] else []
 | 
| 13876 | 400 |   |(Const ("op &",_) $ p $ q) => (aset x p) union (aset x q)
 | 
| 401 |   |(Const ("op |",_) $ p $ q) => (aset x p) union (aset x q)
 | |
| 402 | |_ => []; | |
| 403 | ||
| 404 | ||
| 405 | (* ------------------------------------------------------------------------- *) | |
| 406 | (* Replace top variable with another linear form, retaining canonicality. *) | |
| 407 | (* ------------------------------------------------------------------------- *) | |
| 408 | ||
| 409 | fun linrep vars x t fm = case fm of | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 410 |    ((Const(p,_)$ d $ (Const("HOL.plus",_)$(Const("HOL.times",_)$ c $ y) $ z))) => 
 | 
| 13876 | 411 | if (x = y) andalso (is_arith_rel fm) | 
| 412 | then | |
| 413 | let val ct = linear_cmul (dest_numeral c) t | |
| 414 | in (HOLogic.mk_binrel p (d, linear_add vars ct z)) | |
| 415 | end | |
| 416 | else fm | |
| 417 |   |(Const ("Not", _) $ p) => HOLogic.Not $ (linrep vars x t p) 
 | |
| 418 |   |(Const ("op &",_) $ p $ q) => HOLogic.conj $ (linrep vars x t p) $ (linrep vars x t q) 
 | |
| 419 |   |(Const ("op |",_) $ p $ q) => HOLogic.disj $ (linrep vars x t p) $ (linrep vars x t q) 
 | |
| 15267 | 420 | |_ => fm; | 
| 13876 | 421 | |
| 422 | (* ------------------------------------------------------------------------- *) | |
| 423 | (* Evaluation of constant expressions. *) | |
| 424 | (* ------------------------------------------------------------------------- *) | |
| 15107 | 425 | |
| 426 | (* An other implementation of divides, that covers more cases*) | |
| 427 | ||
| 428 | exception DVD_UNKNOWN | |
| 429 | ||
| 430 | fun dvd_op (d, t) = | |
| 431 | if not(is_numeral d) then raise DVD_UNKNOWN | |
| 432 | else let | |
| 433 | val dn = dest_numeral d | |
| 434 | fun coeffs_of x = case x of | |
| 435 | Const(p,_) $ tl $ tr => | |
| 19233 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 436 | if p = "HOL.plus" then (coeffs_of tl) union (coeffs_of tr) | 
| 
77ca20b0ed77
renamed HOL + - * etc. to HOL.plus HOL.minus HOL.times etc.
 haftmann parents: 
17521diff
changeset | 437 | else if p = "HOL.times" | 
| 15107 | 438 | then if (is_numeral tr) | 
| 439 | then [(dest_numeral tr) * (dest_numeral tl)] | |
| 440 | else [dest_numeral tl] | |
| 441 | else [] | |
| 442 | |_ => if (is_numeral t) then [dest_numeral t] else [] | |
| 443 | val ts = coeffs_of t | |
| 444 | in case ts of | |
| 445 | [] => raise DVD_UNKNOWN | |
| 21078 | 446 | |_ => fold_rev (fn k => fn r => r andalso (k mod dn = 0)) ts true | 
| 15107 | 447 | end; | 
| 448 | ||
| 449 | ||
| 13876 | 450 | val operations = | 
| 19277 | 451 |   [("op =",op=), ("Orderings.less",IntInf.<), ("op >",IntInf.>), ("Orderings.less_eq",IntInf.<=) , 
 | 
| 16398 | 452 |    ("op >=",IntInf.>=), 
 | 
| 21416 | 453 |    ("Divides.dvd",fn (x,y) =>((IntInf.mod(y, x)) = 0))]; 
 | 
| 13876 | 454 | |
| 15531 | 455 | fun applyoperation (SOME f) (a,b) = f (a, b) | 
| 13876 | 456 | |applyoperation _ (_, _) = false; | 
| 457 | ||
| 458 | (*Evaluation of constant atomic formulas*) | |
| 15107 | 459 | (*FIXME : This is an optimation but still incorrect !! *) | 
| 460 | (* | |
| 13876 | 461 | fun evalc_atom at = case at of | 
| 15107 | 462 | (Const (p,_) $ s $ t) => | 
| 21416 | 463 | (if p="Divides.dvd" then | 
| 15107 | 464 | ((if dvd_op(s,t) then HOLogic.true_const | 
| 465 | else HOLogic.false_const) | |
| 466 | handle _ => at) | |
| 467 | else | |
| 17521 | 468 | case AList.lookup (op =) operations p of | 
| 15531 | 469 | SOME f => ((if (f ((dest_numeral s),(dest_numeral t))) then HOLogic.true_const else HOLogic.false_const) | 
| 15107 | 470 | handle _ => at) | 
| 471 | | _ => at) | |
| 472 |       |Const("Not",_)$(Const (p,_) $ s $ t) =>(  
 | |
| 17521 | 473 | case AList.lookup (op =) operations p of | 
| 15531 | 474 | SOME f => ((if (f ((dest_numeral s),(dest_numeral t))) then | 
| 15107 | 475 | HOLogic.false_const else HOLogic.true_const) | 
| 476 | handle _ => at) | |
| 477 | | _ => at) | |
| 478 | | _ => at; | |
| 479 | ||
| 480 | *) | |
| 481 | ||
| 482 | fun evalc_atom at = case at of | |
| 483 | (Const (p,_) $ s $ t) => | |
| 17485 | 484 | ( case AList.lookup (op =) operations p of | 
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 485 | SOME f => ((if (f ((dest_numeral s),(dest_numeral t))) then HOLogic.true_const | 
| 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 486 | else HOLogic.false_const) | 
| 15107 | 487 | handle _ => at) | 
| 488 | | _ => at) | |
| 489 |       |Const("Not",_)$(Const (p,_) $ s $ t) =>(  
 | |
| 17485 | 490 | case AList.lookup (op =) operations p of | 
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 491 | SOME f => ((if (f ((dest_numeral s),(dest_numeral t))) | 
| 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 492 | then HOLogic.false_const else HOLogic.true_const) | 
| 15107 | 493 | handle _ => at) | 
| 494 | | _ => at) | |
| 495 | | _ => at; | |
| 496 | ||
| 497 | (*Function onatoms apllys function f on the atomic formulas involved in a.*) | |
| 13876 | 498 | |
| 499 | fun onatoms f a = if (is_arith_rel a) then f a else case a of | |
| 500 | ||
| 501 |   	(Const ("Not",_) $ p) => if is_arith_rel p then HOLogic.Not $ (f p) 
 | |
| 502 | ||
| 503 | else HOLogic.Not $ (onatoms f p) | |
| 504 |   	|(Const ("op &",_) $ p $ q) => HOLogic.conj $ (onatoms f p) $ (onatoms f q) 
 | |
| 505 |   	|(Const ("op |",_) $ p $ q) => HOLogic.disj $ (onatoms f p) $ (onatoms f q) 
 | |
| 506 |   	|(Const ("op -->",_) $ p $ q) => HOLogic.imp $ (onatoms f p) $ (onatoms f q) 
 | |
| 507 |   	|((Const ("op =", Type ("fun",[Type ("bool", []),_]))) $ p $ q) => (Const ("op =", [HOLogic.boolT, HOLogic.boolT] ---> HOLogic.boolT)) $ (onatoms f p) $ (onatoms f q) 
 | |
| 508 |   	|(Const("All",_) $ Abs(x,T,p)) => Const("All", [HOLogic.intT --> 
 | |
| 509 | HOLogic.boolT] ---> HOLogic.boolT)$ Abs (x ,T, (onatoms f p)) | |
| 510 |   	|(Const("Ex",_) $ Abs(x,T,p)) => Const("Ex", [HOLogic.intT --> HOLogic.boolT]---> HOLogic.boolT) $ Abs( x ,T, (onatoms f p)) 
 | |
| 511 | |_ => a; | |
| 512 | ||
| 513 | val evalc = onatoms evalc_atom; | |
| 514 | ||
| 515 | (* ------------------------------------------------------------------------- *) | |
| 516 | (* Hence overall quantifier elimination. *) | |
| 517 | (* ------------------------------------------------------------------------- *) | |
| 518 | ||
| 519 | ||
| 520 | (*list_disj[conj] makes a disj[conj] of a given list. used with conjucts or disjuncts | |
| 521 | it liearises iterated conj[disj]unctions. *) | |
| 522 | ||
| 523 | fun disj_help p q = HOLogic.disj $ p $ q ; | |
| 524 | ||
| 525 | fun list_disj l = | |
| 16837 | 526 | if l = [] then HOLogic.false_const else Utils.end_itlist disj_help l; | 
| 13876 | 527 | |
| 528 | fun conj_help p q = HOLogic.conj $ p $ q ; | |
| 529 | ||
| 530 | fun list_conj l = | |
| 16837 | 531 | if l = [] then HOLogic.true_const else Utils.end_itlist conj_help l; | 
| 13876 | 532 | |
| 533 | (*Simplification of Formulas *) | |
| 534 | ||
| 535 | (*Function q_bnd_chk checks if a quantified Formula makes sens : Means if in | |
| 536 | the body of the existential quantifier there are bound variables to the | |
| 537 | existential quantifier.*) | |
| 538 | ||
| 539 | fun has_bound fm =let fun has_boundh fm i = case fm of | |
| 540 | Bound n => (i = n) | |
| 541 | |Abs (_,_,p) => has_boundh p (i+1) | |
| 542 | |t1 $ t2 => (has_boundh t1 i) orelse (has_boundh t2 i) | |
| 543 | |_ =>false | |
| 544 | ||
| 545 | in case fm of | |
| 546 | Bound _ => true | |
| 547 | |Abs (_,_,p) => has_boundh p 0 | |
| 548 | |t1 $ t2 => (has_bound t1 ) orelse (has_bound t2 ) | |
| 549 | |_ =>false | |
| 550 | end; | |
| 551 | ||
| 552 | (*has_sub_abs checks if in a given Formula there are subformulas which are quantifed | |
| 553 | too. Is no used no more.*) | |
| 554 | ||
| 555 | fun has_sub_abs fm = case fm of | |
| 556 | Abs (_,_,_) => true | |
| 557 | |t1 $ t2 => (has_bound t1 ) orelse (has_bound t2 ) | |
| 558 | |_ =>false ; | |
| 559 | ||
| 560 | (*update_bounds called with i=0 udates the numeration of bounded variables because the | |
| 561 | formula will not be quantified any more.*) | |
| 562 | ||
| 563 | fun update_bounds fm i = case fm of | |
| 564 | Bound n => if n >= i then Bound (n-1) else fm | |
| 565 | |Abs (x,T,p) => Abs(x,T,(update_bounds p (i+1))) | |
| 566 | |t1 $ t2 => (update_bounds t1 i) $ (update_bounds t2 i) | |
| 567 | |_ => fm ; | |
| 568 | ||
| 569 | (*psimpl : Simplification of propositions (general purpose)*) | |
| 570 | fun psimpl1 fm = case fm of | |
| 571 |     Const("Not",_) $ Const ("False",_) => HOLogic.true_const 
 | |
| 572 |   | Const("Not",_) $ Const ("True",_) => HOLogic.false_const 
 | |
| 573 |   | Const("op &",_) $ Const ("False",_) $ q => HOLogic.false_const 
 | |
| 574 |   | Const("op &",_) $ p $ Const ("False",_)  => HOLogic.false_const 
 | |
| 575 |   | Const("op &",_) $ Const ("True",_) $ q => q 
 | |
| 576 |   | Const("op &",_) $ p $ Const ("True",_) => p 
 | |
| 577 |   | Const("op |",_) $ Const ("False",_) $ q => q 
 | |
| 578 |   | Const("op |",_) $ p $ Const ("False",_)  => p 
 | |
| 579 |   | Const("op |",_) $ Const ("True",_) $ q => HOLogic.true_const 
 | |
| 580 |   | Const("op |",_) $ p $ Const ("True",_)  => HOLogic.true_const 
 | |
| 581 |   | Const("op -->",_) $ Const ("False",_) $ q => HOLogic.true_const 
 | |
| 582 |   | Const("op -->",_) $ Const ("True",_) $  q => q 
 | |
| 583 |   | Const("op -->",_) $ p $ Const ("True",_)  => HOLogic.true_const 
 | |
| 584 |   | Const("op -->",_) $ p $ Const ("False",_)  => HOLogic.Not $  p 
 | |
| 585 |   | Const("op =", Type ("fun",[Type ("bool", []),_])) $ Const ("True",_) $ q => q 
 | |
| 586 |   | Const("op =", Type ("fun",[Type ("bool", []),_])) $ p $ Const ("True",_) => p 
 | |
| 587 |   | Const("op =", Type ("fun",[Type ("bool", []),_])) $ Const ("False",_) $ q => HOLogic.Not $  q 
 | |
| 588 |   | Const("op =", Type ("fun",[Type ("bool", []),_])) $ p $ Const ("False",_)  => HOLogic.Not $  p 
 | |
| 589 | | _ => fm; | |
| 590 | ||
| 591 | fun psimpl fm = case fm of | |
| 592 |    Const ("Not",_) $ p => psimpl1 (HOLogic.Not $ (psimpl p)) 
 | |
| 593 |   | Const("op &",_) $ p $ q => psimpl1 (HOLogic.mk_conj (psimpl p,psimpl q)) 
 | |
| 594 |   | Const("op |",_) $ p $ q => psimpl1 (HOLogic.mk_disj (psimpl p,psimpl q)) 
 | |
| 595 |   | Const("op -->",_) $ p $ q => psimpl1 (HOLogic.mk_imp(psimpl p,psimpl q)) 
 | |
| 15267 | 596 |   | Const("op =", Type ("fun",[Type ("bool", []),_])) $ p $ q => psimpl1 (HOLogic.mk_eq(psimpl p,psimpl q))
 | 
| 13876 | 597 | | _ => fm; | 
| 598 | ||
| 599 | ||
| 600 | (*simpl : Simplification of Terms involving quantifiers too. | |
| 601 | This function is able to drop out some quantified expressions where there are no | |
| 602 | bound varaibles.*) | |
| 603 | ||
| 604 | fun simpl1 fm = | |
| 605 | case fm of | |
| 606 |     Const("All",_) $Abs(x,_,p) => if (has_bound fm ) then fm  
 | |
| 607 | else (update_bounds p 0) | |
| 608 |   | Const("Ex",_) $ Abs (x,_,p) => if has_bound fm then fm  
 | |
| 609 | else (update_bounds p 0) | |
| 15267 | 610 | | _ => psimpl fm; | 
| 13876 | 611 | |
| 612 | fun simpl fm = case fm of | |
| 613 |     Const ("Not",_) $ p => simpl1 (HOLogic.Not $(simpl p))  
 | |
| 614 |   | Const ("op &",_) $ p $ q => simpl1 (HOLogic.mk_conj (simpl p ,simpl q))  
 | |
| 615 |   | Const ("op |",_) $ p $ q => simpl1 (HOLogic.mk_disj (simpl p ,simpl q ))  
 | |
| 616 |   | Const ("op -->",_) $ p $ q => simpl1 (HOLogic.mk_imp(simpl p ,simpl q ))  
 | |
| 617 |   | Const("op =", Type ("fun",[Type ("bool", []),_]))$ p $ q => simpl1 
 | |
| 618 | (HOLogic.mk_eq(simpl p ,simpl q )) | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 619 | (*  | Const ("All",Ta) $ Abs(Vn,VT,p) => simpl1(Const("All",Ta) $ 
 | 
| 13876 | 620 | Abs(Vn,VT,simpl p )) | 
| 621 |   | Const ("Ex",Ta)  $ Abs(Vn,VT,p) => simpl1(Const("Ex",Ta)  $ 
 | |
| 622 | Abs(Vn,VT,simpl p )) | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 623 | *) | 
| 13876 | 624 | | _ => fm; | 
| 625 | ||
| 626 | (* ------------------------------------------------------------------------- *) | |
| 627 | ||
| 628 | (* Puts fm into NNF*) | |
| 629 | ||
| 630 | fun nnf fm = if (is_arith_rel fm) then fm | |
| 631 | else (case fm of | |
| 632 |   ( Const ("op &",_) $ p $ q)  => HOLogic.conj $ (nnf p) $(nnf q) 
 | |
| 633 |   | (Const("op |",_) $ p $q) => HOLogic.disj $ (nnf p)$(nnf q) 
 | |
| 634 |   | (Const ("op -->",_)  $ p $ q) => HOLogic.disj $ (nnf (HOLogic.Not $ p)) $ (nnf q) 
 | |
| 635 |   | ((Const ("op =", Type ("fun",[Type ("bool", []),_]))) $ p $ q) =>(HOLogic.disj $ (HOLogic.conj $ (nnf p) $ (nnf q)) $ (HOLogic.conj $ (nnf (HOLogic.Not $ p) ) $ (nnf(HOLogic.Not $ q)))) 
 | |
| 636 |   | (Const ("Not",_)) $ ((Const ("Not",_)) $ p) => (nnf p) 
 | |
| 637 |   | (Const ("Not",_)) $ (( Const ("op &",_)) $ p $ q) =>HOLogic.disj $ (nnf(HOLogic.Not $ p)) $ (nnf(HOLogic.Not $q)) 
 | |
| 638 |   | (Const ("Not",_)) $ (( Const ("op |",_)) $ p $ q) =>HOLogic.conj $ (nnf(HOLogic.Not $ p)) $ (nnf(HOLogic.Not $ q)) 
 | |
| 639 |   | (Const ("Not",_)) $ (( Const ("op -->",_)) $ p $ q ) =>HOLogic.conj $ (nnf p) $(nnf(HOLogic.Not $ q)) 
 | |
| 640 |   | (Const ("Not",_)) $ ((Const ("op =", Type ("fun",[Type ("bool", []),_]))) $ p $ q ) =>(HOLogic.disj $ (HOLogic.conj $(nnf p) $ (nnf(HOLogic.Not $ q))) $ (HOLogic.conj $(nnf(HOLogic.Not $ p)) $ (nnf q))) 
 | |
| 641 | | _ => fm); | |
| 642 | ||
| 643 | ||
| 644 | (* Function remred to remove redundancy in a list while keeping the order of appearance of the | |
| 645 | elements. but VERY INEFFICIENT!! *) | |
| 646 | ||
| 647 | fun remred1 el [] = [] | |
| 648 | |remred1 el (h::t) = if el=h then (remred1 el t) else h::(remred1 el t); | |
| 649 | ||
| 650 | fun remred [] = [] | |
| 651 | |remred (x::l) = x::(remred1 x (remred l)); | |
| 652 | ||
| 653 | (*Makes sure that all free Variables are of the type integer but this function is only | |
| 654 | used temporarily, this job must be done by the parser later on.*) | |
| 655 | ||
| 656 | fun mk_uni_vars T (node $ rest) = (case node of | |
| 657 | Free (name,_) => Free (name,T) $ (mk_uni_vars T rest) | |
| 658 | |_=> (mk_uni_vars T node) $ (mk_uni_vars T rest ) ) | |
| 659 | |mk_uni_vars T (Free (v,_)) = Free (v,T) | |
| 660 | |mk_uni_vars T tm = tm; | |
| 661 | ||
| 20713 
823967ef47f1
renamed 0 and 1 to HOL.zero and HOL.one respectivly; introduced corresponding syntactic classes
 haftmann parents: 
20500diff
changeset | 662 | fun mk_uni_int T (Const ("HOL.zero",T2)) = if T = T2 then (mk_numeral 0) else (Const ("HOL.zero",T2)) 
 | 
| 
823967ef47f1
renamed 0 and 1 to HOL.zero and HOL.one respectivly; introduced corresponding syntactic classes
 haftmann parents: 
20500diff
changeset | 663 |     |mk_uni_int T (Const ("HOL.one",T2)) = if T = T2 then (mk_numeral 1) else (Const ("HOL.one",T2)) 
 | 
| 13876 | 664 | |mk_uni_int T (node $ rest) = (mk_uni_int T node) $ (mk_uni_int T rest ) | 
| 665 | |mk_uni_int T (Abs(AV,AT,p)) = Abs(AV,AT,mk_uni_int T p) | |
| 666 | |mk_uni_int T tm = tm; | |
| 667 | ||
| 668 | ||
| 16398 | 669 | (* Minusinfinity Version*) | 
| 670 | fun myupto (m:IntInf.int) n = if m > n then [] else m::(myupto (m+1) n) | |
| 671 | ||
| 13876 | 672 | fun coopermi vars1 fm = | 
| 673 | case fm of | |
| 15965 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 674 |    Const ("Ex",_) $ Abs(x0,T,p0) => 
 | 
| 
f422f8283491
Use of IntInf.int instead of int in most numeric simprocs; avoids
 paulson parents: 
15859diff
changeset | 675 | let | 
| 20194 | 676 | val (xn,p1) = Syntax.variant_abs (x0,T,p0) | 
| 13876 | 677 | val x = Free (xn,T) | 
| 678 | val vars = (xn::vars1) | |
| 679 | val p = unitycoeff x (posineq (simpl p1)) | |
| 680 | val p_inf = simpl (minusinf x p) | |
| 681 | val bset = bset x p | |
| 16398 | 682 | val js = myupto 1 (divlcm x p) | 
| 13876 | 683 | fun p_element j b = linrep vars x (linear_add vars b (mk_numeral j)) p | 
| 684 | fun stage j = list_disj (linrep vars x (mk_numeral j) p_inf :: map (p_element j) bset) | |
| 685 | in (list_disj (map stage js)) | |
| 686 | end | |
| 687 | | _ => error "cooper: not an existential formula"; | |
| 688 | ||
| 689 | ||
| 690 | ||
| 691 | (* The plusinfinity version of cooper*) | |
| 692 | fun cooperpi vars1 fm = | |
| 693 | case fm of | |
| 694 |    Const ("Ex",_) $ Abs(x0,T,p0) => let 
 | |
| 20194 | 695 | val (xn,p1) = Syntax.variant_abs (x0,T,p0) | 
| 13876 | 696 | val x = Free (xn,T) | 
| 697 | val vars = (xn::vars1) | |
| 698 | val p = unitycoeff x (posineq (simpl p1)) | |
| 699 | val p_inf = simpl (plusinf x p) | |
| 700 | val aset = aset x p | |
| 16398 | 701 | val js = myupto 1 (divlcm x p) | 
| 13876 | 702 | fun p_element j a = linrep vars x (linear_sub vars a (mk_numeral j)) p | 
| 703 | fun stage j = list_disj (linrep vars x (mk_numeral j) p_inf :: map (p_element j) aset) | |
| 704 | in (list_disj (map stage js)) | |
| 705 | end | |
| 706 | | _ => error "cooper: not an existential formula"; | |
| 707 | ||
| 708 | ||
| 15107 | 709 | (* Try to find a withness for the formula *) | 
| 710 | ||
| 711 | fun inf_w mi d vars x p = | |
| 712 | let val f = if mi then minusinf else plusinf in | |
| 713 | case (simpl (minusinf x p)) of | |
| 15531 | 714 |    Const("True",_)  => (SOME (mk_numeral 1), HOLogic.true_const)
 | 
| 715 |   |Const("False",_) => (NONE,HOLogic.false_const)
 | |
| 15107 | 716 | |F => | 
| 717 | let | |
| 718 | fun h n = | |
| 719 | case ((simpl o evalc) (linrep vars x (mk_numeral n) F)) of | |
| 15531 | 720 | 	Const("True",_) => (SOME (mk_numeral n),HOLogic.true_const)
 | 
| 721 | |F' => if n=1 then (NONE,F') | |
| 15107 | 722 | else let val (rw,rf) = h (n-1) in | 
| 723 | (rw,HOLogic.mk_disj(F',rf)) | |
| 724 | end | |
| 725 | ||
| 726 | in (h d) | |
| 727 | end | |
| 728 | end; | |
| 729 | ||
| 730 | fun set_w d b st vars x p = let | |
| 731 | fun h ns = case ns of | |
| 15531 | 732 | [] => (NONE,HOLogic.false_const) | 
| 15107 | 733 | |n::nl => ( case ((simpl o evalc) (linrep vars x n p)) of | 
| 15531 | 734 |       Const("True",_) => (SOME n,HOLogic.true_const)
 | 
| 15107 | 735 | |F' => let val (rw,rf) = h nl | 
| 736 | in (rw,HOLogic.mk_disj(F',rf)) | |
| 737 | end) | |
| 738 | val f = if b then linear_add else linear_sub | |
| 21078 | 739 | val p_elements = fold_rev (fn i => fn l => l union (map (fn e => f [] e (mk_numeral i)) st)) (myupto 1 d) [] | 
| 15107 | 740 | in h p_elements | 
| 741 | end; | |
| 742 | ||
| 743 | fun withness d b st vars x p = case (inf_w b d vars x p) of | |
| 15531 | 744 | (SOME n,_) => (SOME n,HOLogic.true_const) | 
| 745 | |(NONE,Pinf) => (case (set_w d b st vars x p) of | |
| 746 | (SOME n,_) => (SOME n,HOLogic.true_const) | |
| 747 | |(_,Pst) => (NONE,HOLogic.mk_disj(Pinf,Pst))); | |
| 15107 | 748 | |
| 749 | ||
| 750 | ||
| 13876 | 751 | |
| 752 | (*Cooper main procedure*) | |
| 15267 | 753 | |
| 754 | exception STAGE_TRUE; | |
| 755 | ||
| 13876 | 756 | |
| 757 | fun cooper vars1 fm = | |
| 758 | case fm of | |
| 759 |    Const ("Ex",_) $ Abs(x0,T,p0) => let 
 | |
| 20194 | 760 | val (xn,p1) = Syntax.variant_abs (x0,T,p0) | 
| 13876 | 761 | val x = Free (xn,T) | 
| 762 | val vars = (xn::vars1) | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 763 | (* val p = unitycoeff x (posineq (simpl p1)) *) | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 764 | val p = unitycoeff x p1 | 
| 13876 | 765 | val ast = aset x p | 
| 766 | val bst = bset x p | |
| 16398 | 767 | val js = myupto 1 (divlcm x p) | 
| 13876 | 768 | val (p_inf,f,S ) = | 
| 15267 | 769 | if (length bst) <= (length ast) | 
| 770 | then (simpl (minusinf x p),linear_add,bst) | |
| 771 | else (simpl (plusinf x p), linear_sub,ast) | |
| 13876 | 772 | fun p_element j a = linrep vars x (f vars a (mk_numeral j)) p | 
| 773 | fun stage j = list_disj (linrep vars x (mk_numeral j) p_inf :: map (p_element j) S) | |
| 15267 | 774 | fun stageh n = ((if n = 0 then [] | 
| 775 | else | |
| 776 | let | |
| 777 | val nth_stage = simpl (evalc (stage n)) | |
| 778 | in | |
| 779 | if (nth_stage = HOLogic.true_const) | |
| 780 | then raise STAGE_TRUE | |
| 781 | else if (nth_stage = HOLogic.false_const) then stageh (n-1) | |
| 782 | else nth_stage::(stageh (n-1)) | |
| 783 | end ) | |
| 784 | handle STAGE_TRUE => [HOLogic.true_const]) | |
| 785 | val slist = stageh (divlcm x p) | |
| 786 | in (list_disj slist) | |
| 13876 | 787 | end | 
| 788 | | _ => error "cooper: not an existential formula"; | |
| 789 | ||
| 790 | ||
| 15107 | 791 | (* A Version of cooper that returns a withness *) | 
| 792 | fun cooper_w vars1 fm = | |
| 793 | case fm of | |
| 794 |    Const ("Ex",_) $ Abs(x0,T,p0) => let 
 | |
| 20194 | 795 | val (xn,p1) = Syntax.variant_abs (x0,T,p0) | 
| 15107 | 796 | val x = Free (xn,T) | 
| 797 | val vars = (xn::vars1) | |
| 798 | (* val p = unitycoeff x (posineq (simpl p1)) *) | |
| 799 | val p = unitycoeff x p1 | |
| 800 | val ast = aset x p | |
| 801 | val bst = bset x p | |
| 802 | val d = divlcm x p | |
| 803 | val (p_inf,S ) = | |
| 804 | if (length bst) <= (length ast) | |
| 805 | then (true,bst) | |
| 806 | else (false,ast) | |
| 807 | in withness d p_inf S vars x p | |
| 808 | (* fun p_element j a = linrep vars x (f vars a (mk_numeral j)) p | |
| 809 | fun stage j = list_disj (linrep vars x (mk_numeral j) p_inf :: map (p_element j) S) | |
| 810 | in (list_disj (map stage js)) | |
| 811 | *) | |
| 812 | end | |
| 813 | | _ => error "cooper: not an existential formula"; | |
| 13876 | 814 | |
| 815 | ||
| 816 | (* ------------------------------------------------------------------------- *) | |
| 817 | (* Free variables in terms and formulas. *) | |
| 818 | (* ------------------------------------------------------------------------- *) | |
| 819 | ||
| 820 | fun fvt tml = case tml of | |
| 821 | [] => [] | |
| 822 | | Free(x,_)::r => x::(fvt r) | |
| 823 | ||
| 824 | fun fv fm = fvt (term_frees fm); | |
| 825 | ||
| 826 | ||
| 827 | (* ========================================================================= *) | |
| 828 | (* Quantifier elimination. *) | |
| 829 | (* ========================================================================= *) | |
| 830 | (*conj[/disj]uncts lists iterated conj[disj]unctions*) | |
| 831 | ||
| 832 | fun disjuncts fm = case fm of | |
| 833 |     Const ("op |",_) $ p $ q => (disjuncts p) @ (disjuncts q) 
 | |
| 834 | | _ => [fm]; | |
| 835 | ||
| 836 | fun conjuncts fm = case fm of | |
| 837 |     Const ("op &",_) $p $ q => (conjuncts p) @ (conjuncts q) 
 | |
| 838 | | _ => [fm]; | |
| 839 | ||
| 840 | ||
| 841 | ||
| 842 | (* ------------------------------------------------------------------------- *) | |
| 843 | (* Lift procedure given literal modifier, formula normalizer & basic quelim. *) | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 844 | (* ------------------------------------------------------------------------- *) | 
| 15267 | 845 | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 846 | fun lift_qelim afn nfn qfn isat = | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 847 | let | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 848 | fun qelift vars fm = if (isat fm) then afn vars fm | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 849 | else | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 850 | case fm of | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 851 |   Const ("Not",_) $ p => HOLogic.Not $ (qelift vars p) 
 | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 852 |   | Const ("op &",_) $ p $q => HOLogic.conj $ (qelift vars p) $ (qelift vars q) 
 | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 853 |   | Const ("op |",_) $ p $ q => HOLogic.disj $ (qelift vars p) $ (qelift vars q) 
 | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 854 |   | Const ("op -->",_) $ p $ q => HOLogic.imp $ (qelift vars p) $ (qelift vars q) 
 | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 855 |   | Const ("op =",Type ("fun",[Type ("bool", []),_])) $ p $ q => HOLogic.mk_eq ((qelift vars p),(qelift vars q)) 
 | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 856 |   | Const ("All",QT) $ Abs(x,T,p) => HOLogic.Not $(qelift vars (Const ("Ex",QT) $ Abs(x,T,(HOLogic.Not $ p)))) 
 | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 857 |   | (e as Const ("Ex",_)) $ Abs (x,T,p)  =>  qfn vars (e$Abs (x,T,(nfn(qelift (x::vars) p))))
 | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 858 | | _ => fm | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 859 | |
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 860 | in (fn fm => qelift (fv fm) fm) | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 861 | end; | 
| 15267 | 862 | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 863 | |
| 15267 | 864 | (* | 
| 13876 | 865 | fun lift_qelim afn nfn qfn isat = | 
| 866 | let fun qelim x vars p = | |
| 867 | let val cjs = conjuncts p | |
| 15570 | 868 | val (ycjs,ncjs) = List.partition (has_bound) cjs in | 
| 13876 | 869 | (if ycjs = [] then p else | 
| 870 | let val q = (qfn vars ((HOLogic.exists_const HOLogic.intT | |
| 871 | ) $ Abs(x,HOLogic.intT,(list_conj ycjs)))) in | |
| 16837 | 872 | (fold_rev conj_help ncjs q) | 
| 13876 | 873 | end) | 
| 874 | end | |
| 875 | ||
| 876 | fun qelift vars fm = if (isat fm) then afn vars fm | |
| 877 | else | |
| 878 | case fm of | |
| 879 |       Const ("Not",_) $ p => HOLogic.Not $ (qelift vars p) 
 | |
| 880 |     | Const ("op &",_) $ p $q => HOLogic.conj $ (qelift vars p) $ (qelift vars q) 
 | |
| 881 |     | Const ("op |",_) $ p $ q => HOLogic.disj $ (qelift vars p) $ (qelift vars q) 
 | |
| 882 |     | Const ("op -->",_) $ p $ q => HOLogic.imp $ (qelift vars p) $ (qelift vars q) 
 | |
| 883 |     | Const ("op =",Type ("fun",[Type ("bool", []),_])) $ p $ q => HOLogic.mk_eq ((qelift vars p),(qelift vars q)) 
 | |
| 884 |     | Const ("All",QT) $ Abs(x,T,p) => HOLogic.Not $(qelift vars (Const ("Ex",QT) $ Abs(x,T,(HOLogic.Not $ p)))) 
 | |
| 885 |     | Const ("Ex",_) $ Abs (x,T,p)  => let  val djs = disjuncts(nfn(qelift (x::vars) p)) in 
 | |
| 886 | list_disj(map (qelim x vars) djs) end | |
| 887 | | _ => fm | |
| 888 | ||
| 889 | in (fn fm => simpl(qelift (fv fm) fm)) | |
| 890 | end; | |
| 15267 | 891 | *) | 
| 13876 | 892 | |
| 893 | (* ------------------------------------------------------------------------- *) | |
| 894 | (* Cleverer (proposisional) NNF with conditional and literal modification. *) | |
| 895 | (* ------------------------------------------------------------------------- *) | |
| 896 | ||
| 897 | (*Function Negate used by cnnf, negates a formula p*) | |
| 898 | ||
| 899 | fun negate (Const ("Not",_) $ p) = p 
 | |
| 900 | |negate p = (HOLogic.Not $ p); | |
| 901 | ||
| 902 | fun cnnf lfn = | |
| 903 | let fun cnnfh fm = case fm of | |
| 904 |       (Const ("op &",_) $ p $ q) => HOLogic.mk_conj(cnnfh p,cnnfh q) 
 | |
| 905 |     | (Const ("op |",_) $ p $ q) => HOLogic.mk_disj(cnnfh p,cnnfh q) 
 | |
| 906 |     | (Const ("op -->",_) $ p $q) => HOLogic.mk_disj(cnnfh(HOLogic.Not $ p),cnnfh q) 
 | |
| 907 |     | (Const ("op =",Type ("fun",[Type ("bool", []),_])) $ p $ q) => HOLogic.mk_disj( 
 | |
| 908 | HOLogic.mk_conj(cnnfh p,cnnfh q), | |
| 909 | HOLogic.mk_conj(cnnfh(HOLogic.Not $ p),cnnfh(HOLogic.Not $q))) | |
| 910 | ||
| 911 |     | (Const ("Not",_) $ (Const("Not",_) $ p)) => cnnfh p 
 | |
| 912 |     | (Const ("Not",_) $ (Const ("op &",_) $ p $ q)) => HOLogic.mk_disj(cnnfh(HOLogic.Not $ p),cnnfh(HOLogic.Not $ q)) 
 | |
| 913 |     | (Const ("Not",_) $(Const ("op |",_) $ (Const ("op &",_) $ p $ q) $  
 | |
| 914 |     			(Const ("op &",_) $ p1 $ r))) => if p1 = negate p then 
 | |
| 915 | HOLogic.mk_disj( | |
| 916 | cnnfh (HOLogic.mk_conj(p,cnnfh(HOLogic.Not $ q))), | |
| 917 | cnnfh (HOLogic.mk_conj(p1,cnnfh(HOLogic.Not $ r)))) | |
| 918 | else HOLogic.mk_conj( | |
| 919 | cnnfh (HOLogic.mk_disj(cnnfh (HOLogic.Not $ p),cnnfh(HOLogic.Not $ q))), | |
| 920 | cnnfh (HOLogic.mk_disj(cnnfh (HOLogic.Not $ p1),cnnfh(HOLogic.Not $ r))) | |
| 921 | ) | |
| 922 |     | (Const ("Not",_) $ (Const ("op |",_) $ p $ q)) => HOLogic.mk_conj(cnnfh(HOLogic.Not $ p),cnnfh(HOLogic.Not $ q)) 
 | |
| 923 |     | (Const ("Not",_) $ (Const ("op -->",_) $ p $q)) => HOLogic.mk_conj(cnnfh p,cnnfh(HOLogic.Not $ q)) 
 | |
| 924 |     | (Const ("Not",_) $ (Const ("op =",Type ("fun",[Type ("bool", []),_]))  $ p $ q)) => HOLogic.mk_disj(HOLogic.mk_conj(cnnfh p,cnnfh(HOLogic.Not $ q)),HOLogic.mk_conj(cnnfh(HOLogic.Not $ p),cnnfh q)) 
 | |
| 925 | | _ => lfn fm | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 926 | in cnnfh | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 927 | end; | 
| 13876 | 928 | |
| 929 | (*End- function the quantifierelimination an decion procedure of presburger formulas.*) | |
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 930 | |
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 931 | (* | 
| 13876 | 932 | val integer_qelim = simpl o evalc o (lift_qelim linform (simpl o (cnnf posineq o evalc)) cooper is_arith_rel) ; | 
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 933 | *) | 
| 15267 | 934 | |
| 935 | ||
| 14920 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 936 | val integer_qelim = simpl o evalc o (lift_qelim linform (cnnf posineq o evalc) cooper is_arith_rel) ; | 
| 
a7525235e20f
An oracle is built in. The tactic will not generate any proofs any more, if the quick_and_dirty flag is set on.
 chaieb parents: 
14877diff
changeset | 937 | |
| 13876 | 938 | end; |