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