(* Title: HOL/ex/PresburgerEx.thy
ID: $Id$
Author: Amine Chaieb, TU Muenchen
A formalization of quantifier elimination for Presburger arithmetic
based on a generic quantifier elimination algorithm and Cooper's
methos to eliminate on \<exists>. *)
header {* Quantifier elimination for Presburger arithmetic *}
theory Reflected_Presburger
imports Main
begin
(* Shadow syntax for integer terms *)
datatype intterm =
Cst int
| Var nat
| Neg intterm
| Add intterm intterm
| Sub intterm intterm
| Mult intterm intterm
(* interpretatation of intterms , takes bound variables and free variables *)
consts I_intterm :: "int list \<Rightarrow> intterm \<Rightarrow> int"
primrec
"I_intterm ats (Cst b) = b"
"I_intterm ats (Var n) = (ats!n)"
"I_intterm ats (Neg it) = -(I_intterm ats it)"
"I_intterm ats (Add it1 it2) = (I_intterm ats it1) + (I_intterm ats it2)"
"I_intterm ats (Sub it1 it2) = (I_intterm ats it1) - (I_intterm ats it2)"
"I_intterm ats (Mult it1 it2) = (I_intterm ats it1) * (I_intterm ats it2)"
(*Shadow syntax for Presburger formulae *)
datatype QF =
Lt intterm intterm
|Gt intterm intterm
|Le intterm intterm
|Ge intterm intterm
|Eq intterm intterm
|Divides intterm intterm
|T
|F
|NOT QF
|And QF QF
|Or QF QF
|Imp QF QF
|Equ QF QF
|QAll QF
|QEx QF
(* Interpretation of Presburger formulae *)
consts qinterp :: "int list \<Rightarrow> QF \<Rightarrow> bool"
primrec
"qinterp ats (Lt it1 it2) = (I_intterm ats it1 < I_intterm ats it2)"
"qinterp ats (Gt it1 it2) = (I_intterm ats it1 > I_intterm ats it2)"
"qinterp ats (Le it1 it2) = (I_intterm ats it1 \<le> I_intterm ats it2)"
"qinterp ats (Ge it1 it2) = (I_intterm ats it1 \<ge> I_intterm ats it2)"
"qinterp ats (Divides it1 it2) = (I_intterm ats it1 dvd I_intterm ats it2)"
"qinterp ats (Eq it1 it2) = (I_intterm ats it1 = I_intterm ats it2)"
"qinterp ats T = True"
"qinterp ats F = False"
"qinterp ats (NOT p) = (\<not>(qinterp ats p))"
"qinterp ats (And p q) = (qinterp ats p \<and> qinterp ats q)"
"qinterp ats (Or p q) = (qinterp ats p \<or> qinterp ats q)"
"qinterp ats (Imp p q) = (qinterp ats p \<longrightarrow> qinterp ats q)"
"qinterp ats (Equ p q) = (qinterp ats p = qinterp ats q)"
"qinterp ats (QAll p) = (\<forall>x. qinterp (x#ats) p)"
"qinterp ats (QEx p) = (\<exists>x. qinterp (x#ats) p)"
(* quantifier elimination based on qe, quantifier elimination for an
existential formula, with quantifier free body
Since quantifier elimination for one formula is allowed to fail,
the reult is of type QF option *)
consts lift_bin:: "('a \<Rightarrow> 'a \<Rightarrow> 'b) \<times> 'a option \<times> 'a option \<Rightarrow> 'b option"
recdef lift_bin "measure (\<lambda>(c,a,b). size a)"
"lift_bin (c,Some a,Some b) = Some (c a b)"
"lift_bin (c,x, y) = None"
lemma lift_bin_Some:
assumes ls: "lift_bin (c,x,y) = Some t"
shows "(\<exists>a. x = Some a) \<and> (\<exists>b. y = Some b)"
using ls
by (cases "x", auto) (cases "y", auto)+
consts lift_un:: "('a \<Rightarrow> 'b) \<Rightarrow> 'a option \<Rightarrow> 'b option"
primrec
"lift_un c None = None"
"lift_un c (Some p) = Some (c p)"
consts lift_qe:: "('a \<Rightarrow> 'b option) \<Rightarrow> 'a option \<Rightarrow> 'b option"
primrec
"lift_qe qe None = None"
"lift_qe qe (Some p) = qe p"
(* generic quantifier elimination *)
consts qelim :: "(QF \<Rightarrow> QF option) \<times> QF \<Rightarrow> QF option"
recdef qelim "measure (\<lambda>(qe,p). size p)"
"qelim (qe, (QAll p)) = lift_un NOT (lift_qe qe (lift_un NOT (qelim (qe ,p))))"
"qelim (qe, (QEx p)) = lift_qe qe (qelim (qe,p))"
"qelim (qe, (And p q)) = lift_bin (And, (qelim (qe, p)), (qelim (qe, q)))"
"qelim (qe, (Or p q)) = lift_bin (Or, (qelim (qe, p)), (qelim (qe, q)))"
"qelim (qe, (Imp p q)) = lift_bin (Imp, (qelim (qe, p)), (qelim (qe, q)))"
"qelim (qe, (Equ p q)) = lift_bin (Equ, (qelim (qe, p)), (qelim (qe, q)))"
"qelim (qe,NOT p) = lift_un NOT (qelim (qe,p))"
"qelim (qe, p) = Some p"
(* quantifier free-ness *)
consts isqfree :: "QF \<Rightarrow> bool"
recdef isqfree "measure size"
"isqfree (QAll p) = False"
"isqfree (QEx p) = False"
"isqfree (And p q) = (isqfree p \<and> isqfree q)"
"isqfree (Or p q) = (isqfree p \<and> isqfree q)"
"isqfree (Imp p q) = (isqfree p \<and> isqfree q)"
"isqfree (Equ p q) = (isqfree p \<and> isqfree q)"
"isqfree (NOT p) = isqfree p"
"isqfree p = True"
(* qelim lifts quantifierfreeness*)
lemma qelim_qfree:
assumes qeqf: "(\<And> q q'. \<lbrakk>isqfree q ; qe q = Some q'\<rbrakk> \<Longrightarrow> isqfree q')"
shows qff:"\<And> p'. qelim (qe, p) = Some p' \<Longrightarrow> isqfree p'"
using qeqf
proof (induct p)
case (Lt a b)
have "qelim (qe, Lt a b) = Some (Lt a b)" by simp
moreover have "qelim (qe,Lt a b) = Some p'" .
ultimately have "p' = Lt a b" by simp
moreover have "isqfree (Lt a b)" by simp
ultimately
show ?case by simp
next
case (Gt a b)
have "qelim (qe, Gt a b) = Some (Gt a b)" by simp
moreover have "qelim (qe,Gt a b) = Some p'" .
ultimately have "p' = Gt a b" by simp
moreover have "isqfree (Gt a b)" by simp
ultimately
show ?case by simp
next
case (Le a b)
have "qelim (qe, Le a b) = Some (Le a b)" by simp
moreover have "qelim (qe,Le a b) = Some p'" .
ultimately have "p' = Le a b" by simp
moreover have "isqfree (Le a b)" by simp
ultimately
show ?case by simp
next
case (Ge a b)
have "qelim (qe, Ge a b) = Some (Ge a b)" by simp
moreover have "qelim (qe,Ge a b) = Some p'" .
ultimately have "p' = Ge a b" by simp
moreover have "isqfree (Ge a b)" by simp
ultimately
show ?case by simp
next
case (Eq a b)
have "qelim (qe, Eq a b) = Some (Eq a b)" by simp
moreover have "qelim (qe,Eq a b) = Some p'" .
ultimately have "p' = Eq a b" by simp
moreover have "isqfree (Eq a b)" by simp
ultimately
show ?case by simp
next
case (Divides a b)
have "qelim (qe, Divides a b) = Some (Divides a b)" by simp
moreover have "qelim (qe,Divides a b) = Some p'" .
ultimately have "p' = Divides a b" by simp
moreover have "isqfree (Divides a b)" by simp
ultimately
show ?case by simp
next
case T
have "qelim(qe,T) = Some T" by simp
moreover have "qelim(qe,T) = Some p'" .
ultimately have "p' = T" by simp
moreover have "isqfree T" by simp
ultimately show ?case by simp
next
case F
have "qelim(qe,F) = Some F" by simp
moreover have "qelim(qe,F) = Some p'" .
ultimately have "p' = F" by simp
moreover have "isqfree F" by simp
ultimately show ?case by simp
next
case (NOT p)
from "NOT.prems" have "\<exists> p1. qelim(qe,p) = Some p1"
by (cases "qelim(qe,p)") simp_all
then obtain "p1" where p1_def: "qelim(qe,p) = Some p1" by blast
from "NOT.prems" have "\<And>q q'. \<lbrakk>isqfree q; qe q = Some q'\<rbrakk> \<Longrightarrow> isqfree q'"
by blast
with "NOT.hyps" p1_def have p1qf: "isqfree p1" by blast
then have "p' = NOT p1" using "NOT.prems" p1_def
by (cases "qelim(qe,NOT p)") simp_all
then show ?case using p1qf by simp
next
case (And p q)
from "And.prems" have p1q1: "(\<exists>p1. qelim(qe,p) = Some p1) \<and>
(\<exists>q1. qelim(qe,q) = Some q1)" using lift_bin_Some[where c="And"] by simp
from p1q1 obtain "p1" and "q1"
where p1_def: "qelim(qe,p) = Some p1"
and q1_def: "qelim(qe,q) = Some q1" by blast
from prems have qf1:"isqfree p1"
using p1_def by blast
from prems have qf2:"isqfree q1"
using q1_def by blast
from "And.prems" have "qelim(qe,And p q) = Some p'" by blast
then have "p' = And p1 q1" using p1_def q1_def by simp
then
show ?case using qf1 qf2 by simp
next
case (Or p q)
from "Or.prems" have p1q1: "(\<exists>p1. qelim(qe,p) = Some p1) \<and>
(\<exists>q1. qelim(qe,q) = Some q1)" using lift_bin_Some[where c="Or"] by simp
from p1q1 obtain "p1" and "q1"
where p1_def: "qelim(qe,p) = Some p1"
and q1_def: "qelim(qe,q) = Some q1" by blast
from prems have qf1:"isqfree p1"
using p1_def by blast
from prems have qf2:"isqfree q1"
using q1_def by blast
from "Or.prems" have "qelim(qe,Or p q) = Some p'" by blast
then have "p' = Or p1 q1" using p1_def q1_def by simp
then
show ?case using qf1 qf2 by simp
next
case (Imp p q)
from "Imp.prems" have p1q1: "(\<exists>p1. qelim(qe,p) = Some p1) \<and>
(\<exists>q1. qelim(qe,q) = Some q1)" using lift_bin_Some[where c="Imp"] by simp
from p1q1 obtain "p1" and "q1"
where p1_def: "qelim(qe,p) = Some p1"
and q1_def: "qelim(qe,q) = Some q1" by blast
from prems have qf1:"isqfree p1"
using p1_def by blast
from prems have qf2:"isqfree q1"
using q1_def by blast
from "Imp.prems" have "qelim(qe,Imp p q) = Some p'" by blast
then have "p' = Imp p1 q1" using p1_def q1_def by simp
then
show ?case using qf1 qf2 by simp
next
case (Equ p q)
from "Equ.prems" have p1q1: "(\<exists>p1. qelim(qe,p) = Some p1) \<and>
(\<exists>q1. qelim(qe,q) = Some q1)" using lift_bin_Some[where c="Equ"] by simp
from p1q1 obtain "p1" and "q1"
where p1_def: "qelim(qe,p) = Some p1"
and q1_def: "qelim(qe,q) = Some q1" by blast
from prems have qf1:"isqfree p1"
using p1_def by blast
from prems have qf2:"isqfree q1"
using q1_def by blast
from "Equ.prems" have "qelim(qe,Equ p q) = Some p'" by blast
then have "p' = Equ p1 q1" using p1_def q1_def by simp
then
show ?case using qf1 qf2 by simp
next
case (QEx p)
from "QEx.prems" have "\<exists> p1. qelim(qe,p) = Some p1"
by (cases "qelim(qe,p)") simp_all
then obtain "p1" where p1_def: "qelim(qe,p) = Some p1" by blast
from "QEx.prems" have "\<And>q q'. \<lbrakk>isqfree q; qe q = Some q'\<rbrakk> \<Longrightarrow> isqfree q'"
by blast
with "QEx.hyps" p1_def have p1qf: "isqfree p1" by blast
from "QEx.prems" have "qe p1 = Some p'" using p1_def by simp
with "QEx.prems" show ?case using p1qf
by simp
next
case (QAll p)
from "QAll.prems"
have "\<exists> p1. lift_qe qe (lift_un NOT (qelim (qe ,p))) = Some p1"
by (cases "lift_qe qe (lift_un NOT (qelim (qe ,p)))") simp_all
then obtain "p1" where
p1_def:"lift_qe qe (lift_un NOT (qelim (qe ,p))) = Some p1" by blast
then have "\<exists> p2. lift_un NOT (qelim (qe ,p)) = Some p2"
by (cases "qelim (qe ,p)") simp_all
then obtain "p2"
where p2_def:"lift_un NOT (qelim (qe ,p)) = Some p2" by blast
then have "\<exists> p3. qelim(qe,p) = Some p3" by (cases "qelim(qe,p)") simp_all
then obtain "p3" where p3_def: "qelim(qe,p) = Some p3" by blast
with prems have qf3: "isqfree p3" by blast
have p2_def2: "p2 = NOT p3" using p2_def p3_def by simp
then have qf2: "isqfree p2" using qf3 by simp
have p1_edf2: "qe p2 = Some p1" using p1_def p2_def by simp
with "QAll.prems" have qf1: "isqfree p1" using qf2 by blast
from "QAll.prems" have "p' = NOT p1" using p1_def by simp
with qf1 show ?case by simp
qed
(* qelim lifts semantical equivalence *)
lemma qelim_corr:
assumes qecorr: "(\<And> q q' ats. \<lbrakk>isqfree q ; qe q = Some q'\<rbrakk> \<Longrightarrow> (qinterp ats (QEx q)) = (qinterp ats q'))"
and qeqf: "(\<And> q q'. \<lbrakk>isqfree q ; qe q = Some q'\<rbrakk> \<Longrightarrow> isqfree q')"
shows qff:"\<And> p' ats. qelim (qe, p) = Some p' \<Longrightarrow> (qinterp ats p = qinterp ats p')" (is "\<And> p' ats. ?Qe p p' \<Longrightarrow> (?F ats p = ?F ats p')")
using qeqf qecorr
proof (induct p)
case (NOT f)
from "NOT.prems" have "\<exists>f'. ?Qe f f' " by (cases "qelim(qe,f)") simp_all
then obtain "f'" where df': "?Qe f f'" by blast
with prems have feqf': "?F ats f = ?F ats f'" by blast
from "NOT.prems" df' have "p' = NOT f'" by simp
with feqf' show ?case by simp
next
case (And f g)
from "And.prems" have f1g1: "(\<exists>f1. qelim(qe,f) = Some f1) \<and>
(\<exists>g1. qelim(qe,g) = Some g1)" using lift_bin_Some[where c="And"] by simp
from f1g1 obtain "f1" and "g1"
where f1_def: "qelim(qe, f) = Some f1"
and g1_def: "qelim(qe,g) = Some g1" by blast
from prems f1_def have feqf1: "?F ats f = ?F ats f1" by blast
from prems g1_def have geqg1: "?F ats g = ?F ats g1" by blast
from "And.prems" f1_def g1_def have "p' = And f1 g1" by simp
with feqf1 geqg1 show ?case by simp
next
case (Or f g)
from "Or.prems" have f1g1: "(\<exists>f1. qelim(qe,f) = Some f1) \<and>
(\<exists>g1. qelim(qe,g) = Some g1)" using lift_bin_Some[where c="Or"] by simp
from f1g1 obtain "f1" and "g1"
where f1_def: "qelim(qe, f) = Some f1"
and g1_def: "qelim(qe,g) = Some g1" by blast
from prems f1_def have feqf1: "?F ats f = ?F ats f1" by blast
from prems g1_def have geqg1: "?F ats g = ?F ats g1" by blast
from "Or.prems" f1_def g1_def have "p' = Or f1 g1" by simp
with feqf1 geqg1 show ?case by simp
next
case (Imp f g)
from "Imp.prems" have f1g1: "(\<exists>f1. qelim(qe,f) = Some f1) \<and>
(\<exists>g1. qelim(qe,g) = Some g1)" using lift_bin_Some[where c="Imp"] by simp
from f1g1 obtain "f1" and "g1"
where f1_def: "qelim(qe, f) = Some f1"
and g1_def: "qelim(qe,g) = Some g1" by blast
from prems f1_def have feqf1: "?F ats f = ?F ats f1" by blast
from prems g1_def have geqg1: "?F ats g = ?F ats g1" by blast
from "Imp.prems" f1_def g1_def have "p' = Imp f1 g1" by simp
with feqf1 geqg1 show ?case by simp
next
case (Equ f g)
from "Equ.prems" have f1g1: "(\<exists>f1. qelim(qe,f) = Some f1) \<and>
(\<exists>g1. qelim(qe,g) = Some g1)" using lift_bin_Some[where c="Equ"] by simp
from f1g1 obtain "f1" and "g1"
where f1_def: "qelim(qe, f) = Some f1"
and g1_def: "qelim(qe,g) = Some g1" by blast
from prems f1_def have feqf1: "?F ats f = ?F ats f1" by blast
from prems g1_def have geqg1: "?F ats g = ?F ats g1" by blast
from "Equ.prems" f1_def g1_def have "p' = Equ f1 g1" by simp
with feqf1 geqg1 show ?case by simp
next
case (QEx f)
from "QEx.prems" have "\<exists> f1. ?Qe f f1"
by (cases "qelim(qe,f)") simp_all
then obtain "f1" where f1_def: "qelim(qe,f) = Some f1" by blast
from prems have qf1:"isqfree f1" using qelim_qfree by blast
from prems have feqf1: "\<forall> ats. qinterp ats f = qinterp ats f1"
using f1_def qf1 by blast
then have "?F ats (QEx f) = ?F ats (QEx f1)"
by simp
from prems have "qelim (qe,QEx f) = Some p'" by blast
then have "\<exists> f'. qe f1 = Some f'" using f1_def by simp
then obtain "f'" where fdef': "qe f1 = Some f'" by blast
with prems have exf1: "?F ats (QEx f1) = ?F ats f'" using qf1 by blast
have fp: "?Qe (QEx f) f'" using f1_def fdef' by simp
from prems have "?Qe (QEx f) p'" by blast
then have "p' = f'" using fp by simp
then show ?case using feqf1 exf1 by simp
next
case (QAll f)
from "QAll.prems"
have "\<exists> f0. lift_un NOT (lift_qe qe (lift_un NOT (qelim (qe ,f)))) =
Some f0"
by (cases "lift_un NOT (lift_qe qe (lift_un NOT (qelim (qe ,f))))")
simp_all
then obtain "f0"
where f0_def: "lift_un NOT (lift_qe qe (lift_un NOT (qelim (qe ,f)))) =
Some f0" by blast
then have "\<exists> f1. lift_qe qe (lift_un NOT (qelim (qe ,f))) = Some f1"
by (cases "lift_qe qe (lift_un NOT (qelim (qe ,f)))") simp_all
then obtain "f1" where
f1_def:"lift_qe qe (lift_un NOT (qelim (qe ,f))) = Some f1" by blast
then have "\<exists> f2. lift_un NOT (qelim (qe ,f)) = Some f2"
by (cases "qelim (qe ,f)") simp_all
then obtain "f2"
where f2_def:"lift_un NOT (qelim (qe ,f)) = Some f2" by blast
then have "\<exists> f3. qelim(qe,f) = Some f3" by (cases "qelim(qe,f)") simp_all
then obtain "f3" where f3_def: "qelim(qe,f) = Some f3" by blast
from prems have qf3:"isqfree f3" using qelim_qfree by blast
from prems have feqf3: "\<forall> ats. qinterp ats f = qinterp ats f3"
using f3_def qf3 by blast
have f23:"f2 = NOT f3" using f2_def f3_def by simp
then have feqf2: "\<forall> ats. qinterp ats f = qinterp ats (NOT f2)"
using feqf3 by simp
have qf2: "isqfree f2" using f23 qf3 by simp
have "qe f2 = Some f1" using f1_def f2_def f23 by simp
with prems have exf2eqf1: "?F ats (QEx f2) = ?F ats f1" using qf2 by blast
have "f0 = NOT f1" using f0_def f1_def by simp
then have f0eqf1: "?F ats f0 = ?F ats (NOT f1)" by simp
from prems have "qelim (qe, QAll f) = Some p'" by blast
then have f0eqp': "p' = f0" using f0_def by simp
have "?F ats (QAll f) = (\<forall>x. ?F (x#ats) f)" by simp
also have "\<dots> = (\<not> (\<exists> x. ?F (x#ats) (NOT f)))" by simp
also have "\<dots> = (\<not> (\<exists> x. ?F (x#ats) (NOT (NOT f2))))" using feqf2
by auto
also have "\<dots> = (\<not> (\<exists> x. ?F (x#ats) f2))" by simp
also have "\<dots> = (\<not> (?F ats f1))" using exf2eqf1 by simp
finally show ?case using f0eqp' f0eqf1 by simp
qed simp_all
(* Cooper's algorithm *)
(* Transform an intform into NNF *)
consts lgth :: "QF \<Rightarrow> nat"
nnf :: "QF \<Rightarrow> QF"
primrec
"lgth (Lt it1 it2) = 1"
"lgth (Gt it1 it2) = 1"
"lgth (Le it1 it2) = 1"
"lgth (Ge it1 it2) = 1"
"lgth (Eq it1 it2) = 1"
"lgth (Divides it1 it2) = 1"
"lgth T = 1"
"lgth F = 1"
"lgth (NOT p) = 1 + lgth p"
"lgth (And p q) = 1 + lgth p + lgth q"
"lgth (Or p q) = 1 + lgth p + lgth q"
"lgth (Imp p q) = 1 + lgth p + lgth q"
"lgth (Equ p q) = 1 + lgth p + lgth q"
"lgth (QAll p) = 1 + lgth p"
"lgth (QEx p) = 1 + lgth p"
lemma [simp] :"0 < lgth q"
apply (induct_tac q)
apply(auto)
done
(* NNF *)
recdef nnf "measure (\<lambda>p. lgth p)"
"nnf (Lt it1 it2) = Le (Sub it1 it2) (Cst (- 1))"
"nnf (Gt it1 it2) = Le (Sub it2 it1) (Cst (- 1))"
"nnf (Le it1 it2) = Le it1 it2 "
"nnf (Ge it1 it2) = Le it2 it1"
"nnf (Eq it1 it2) = Eq it2 it1"
"nnf (Divides d t) = Divides d t"
"nnf T = T"
"nnf F = F"
"nnf (And p q) = And (nnf p) (nnf q)"
"nnf (Or p q) = Or (nnf p) (nnf q)"
"nnf (Imp p q) = Or (nnf (NOT p)) (nnf q)"
"nnf (Equ p q) = Or (And (nnf p) (nnf q))
(And (nnf (NOT p)) (nnf (NOT q)))"
"nnf (NOT (Lt it1 it2)) = (Le it2 it1)"
"nnf (NOT (Gt it1 it2)) = (Le it1 it2)"
"nnf (NOT (Le it1 it2)) = (Le (Sub it2 it1) (Cst (- 1)))"
"nnf (NOT (Ge it1 it2)) = (Le (Sub it1 it2) (Cst (- 1)))"
"nnf (NOT (Eq it1 it2)) = (NOT (Eq it1 it2))"
"nnf (NOT (Divides d t)) = (NOT (Divides d t))"
"nnf (NOT T) = F"
"nnf (NOT F) = T"
"nnf (NOT (NOT p)) = (nnf p)"
"nnf (NOT (And p q)) = (Or (nnf (NOT p)) (nnf (NOT q)))"
"nnf (NOT (Or p q)) = (And (nnf (NOT p)) (nnf (NOT q)))"
"nnf (NOT (Imp p q)) = (And (nnf p) (nnf (NOT q)))"
"nnf (NOT (Equ p q)) = (Or (And (nnf p) (nnf (NOT q))) (And (nnf (NOT p)) (nnf q)))"
consts isnnf :: "QF \<Rightarrow> bool"
recdef isnnf "measure (\<lambda>p. lgth p)"
"isnnf (Le it1 it2) = True"
"isnnf (Eq it1 it2) = True"
"isnnf (Divides d t) = True"
"isnnf T = True"
"isnnf F = True"
"isnnf (And p q) = (isnnf p \<and> isnnf q)"
"isnnf (Or p q) = (isnnf p \<and> isnnf q)"
"isnnf (NOT (Divides d t)) = True"
"isnnf (NOT (Eq it1 it2)) = True"
"isnnf p = False"
(* nnf preserves semantics *)
lemma nnf_corr: "isqfree p \<Longrightarrow> qinterp ats p = qinterp ats (nnf p)"
by (induct p rule: nnf.induct,simp_all)
(arith, arith, arith, arith, arith, arith, arith, arith, arith, blast)
(* the result of nnf is in NNF *)
lemma nnf_isnnf : "isqfree p \<Longrightarrow> isnnf (nnf p)"
by (induct p rule: nnf.induct, auto)
lemma nnf_isqfree: "isnnf p \<Longrightarrow> isqfree p"
by (induct p rule: isnnf.induct) auto
(* nnf preserves quantifier freeness *)
lemma nnf_qfree: "isqfree p \<Longrightarrow> isqfree(nnf p)"
using nnf_isqfree nnf_isnnf by simp
(* Linearization and normalization of formulae *)
(* Definition of linearity of an intterm *)
consts islinintterm :: "intterm \<Rightarrow> bool"
recdef islinintterm "measure size"
"islinintterm (Cst i) = True"
"islinintterm (Add (Mult (Cst i) (Var n)) (Cst i')) = (i \<noteq> 0)"
"islinintterm (Add (Mult (Cst i) (Var n)) (Add (Mult (Cst i') (Var n')) r)) = ( i \<noteq> 0 \<and> i' \<noteq> 0 \<and> n < n' \<and> islinintterm (Add (Mult (Cst i') (Var n')) r))"
"islinintterm i = False"
(* subterms of linear terms are linear *)
lemma islinintterm_subt:
assumes lr: "islinintterm (Add (Mult (Cst i) (Var n)) r)"
shows "islinintterm r"
using lr
by (induct r rule: islinintterm.induct) auto
(* c \<noteq> 0 for linear term c.n + r*)
lemma islinintterm_cnz:
assumes lr: "islinintterm (Add (Mult (Cst i) (Var n)) r)"
shows "i \<noteq> 0"
using lr
by (induct r rule: islinintterm.induct) auto
lemma islininttermc0r: "islinintterm (Add (Mult (Cst c) (Var n)) r) \<Longrightarrow> (c \<noteq> 0 \<and> islinintterm r)"
by (induct r rule: islinintterm.induct, simp_all)
(* An alternative linearity definition *)
consts islintn :: "(nat \<times> intterm) \<Rightarrow> bool"
recdef islintn "measure (\<lambda> (n,t). (size t))"
"islintn (n0, Cst i) = True"
"islintn (n0, Add (Mult (Cst i) (Var n)) r) = (i \<noteq> 0 \<and> n0 \<le> n \<and> islintn (n+1,r))"
"islintn (n0, t) = False"
constdefs islint :: "intterm \<Rightarrow> bool"
"islint t \<equiv> islintn(0,t)"
(* And the equivalence to the first definition *)
lemma islinintterm_eq_islint: "islinintterm t = islint t"
using islint_def
by (induct t rule: islinintterm.induct) auto
(* monotony *)
lemma islintn_mon:
assumes lin: "islintn (n,t)"
and mgen: "m \<le> n"
shows "islintn(m,t)"
using lin mgen
by (induct t rule: islintn.induct) auto
lemma islintn_subt:
assumes lint: "islintn(n,Add (Mult (Cst i) (Var m)) r)"
shows "islintn (m+1,r)"
using lint
by auto
(* List indexin for n > 0 *)
lemma nth_pos: "0 < n \<longrightarrow> (x#xs) ! n = (y#xs) ! n"
using Nat.gr0_conv_Suc
by clarsimp
lemma nth_pos2: "0 < n \<Longrightarrow> (x#xs) ! n = xs ! (n - 1)"
using Nat.gr0_conv_Suc
by clarsimp
lemma intterm_novar0:
assumes lin: "islinintterm (Add (Mult (Cst i) (Var n)) r)"
shows "I_intterm (x#ats) r = I_intterm (y#ats) r"
using lin
by (induct r rule: islinintterm.induct) (simp_all add: nth_pos2)
(* a simple version of a general theorem: Interpretation doese not depend
on the first variable if it doese not occur in the term *)
lemma linterm_novar0:
assumes lin: "islintn (n,t)"
and npos: "0 < n"
shows "I_intterm (x#ats) t = I_intterm (y#ats) t"
using lin npos
by (induct n t rule: islintn.induct) (simp_all add: nth_pos2)
(* Periodicity of dvd *)
lemma dvd_period:
assumes advdd: "(a::int) dvd d"
shows "(a dvd (x + t)) = (a dvd ((x+ c*d) + t))"
using advdd
proof-
from advdd have "\<forall>x.\<forall>k. (((a::int) dvd (x + t)) = (a dvd
(x+k*d + t)))" by (rule dvd_modd_pinf)
then show ?thesis by simp
qed
(* lin_ad adds two linear terms*)
consts lin_add :: "intterm \<times> intterm \<Rightarrow> intterm"
recdef lin_add "measure (\<lambda>(x,y). ((size x) + (size y)))"
"lin_add (Add (Mult (Cst c1) (Var n1)) (r1),Add (Mult (Cst c2) (Var n2)) (r2)) =
(if n1=n2 then
(let c = Cst (c1 + c2)
in (if c1+c2=0 then lin_add(r1,r2) else Add (Mult c (Var n1)) (lin_add (r1,r2))))
else if n1 \<le> n2 then (Add (Mult (Cst c1) (Var n1)) (lin_add (r1,Add (Mult (Cst c2) (Var n2)) (r2))))
else (Add (Mult (Cst c2) (Var n2)) (lin_add (Add (Mult (Cst c1) (Var n1)) r1,r2))))"
"lin_add (Add (Mult (Cst c1) (Var n1)) (r1),Cst b) =
(Add (Mult (Cst c1) (Var n1)) (lin_add (r1, Cst b)))"
"lin_add (Cst x,Add (Mult (Cst c2) (Var n2)) (r2)) =
Add (Mult (Cst c2) (Var n2)) (lin_add (Cst x,r2))"
"lin_add (Cst b1, Cst b2) = Cst (b1+b2)"
lemma lin_add_cst_corr:
assumes blin : "islintn(n0,b)"
shows "I_intterm ats (lin_add (Cst a,b)) = (I_intterm ats (Add (Cst a) b))"
using blin
by (induct n0 b rule: islintn.induct) auto
lemma lin_add_cst_corr2:
assumes blin : "islintn(n0,b)"
shows "I_intterm ats (lin_add (b,Cst a)) = (I_intterm ats (Add b (Cst a)))"
using blin
by (induct n0 b rule: islintn.induct) auto
lemma lin_add_corrh: "\<And> n01 n02. \<lbrakk> islintn (n01,a) ; islintn (n02,b)\<rbrakk>
\<Longrightarrow> I_intterm ats (lin_add(a,b)) = I_intterm ats (Add a b)"
proof(induct a b rule: lin_add.induct)
case (58 i n r j m s)
have "(n = m \<and> i+j = 0) \<or> (n = m \<and> i+j \<noteq> 0) \<or> n < m \<or> m < n " by arith
moreover
{assume "n=m\<and>i+j=0" hence ?case using prems by (auto simp add: sym[OF zadd_zmult_distrib]) }
moreover
{assume "n=m\<and>i+j\<noteq>0" hence ?case using prems by (auto simp add: Let_def zadd_zmult_distrib)}
moreover
{assume "n < m" hence ?case using prems by auto }
moreover
{assume "n > m" hence ?case using prems by auto }
ultimately show ?case by blast
qed (auto simp add: lin_add_cst_corr lin_add_cst_corr2 Let_def)
(* lin_add has the semantics of Add*)
lemma lin_add_corr:
assumes lina: "islinintterm a"
and linb: "islinintterm b"
shows "I_intterm ats (lin_add (a,b)) = (I_intterm ats (Add a b))"
using lina linb islinintterm_eq_islint islint_def lin_add_corrh
by blast
lemma lin_add_cst_lint:
assumes lin: "islintn (n0,b)"
shows "islintn (n0, lin_add (Cst i, b))"
using lin
by (induct n0 b rule: islintn.induct) auto
lemma lin_add_cst_lint2:
assumes lin: "islintn (n0,b)"
shows "islintn (n0, lin_add (b,Cst i))"
using lin
by (induct n0 b rule: islintn.induct) auto
(* lin_add preserves linearity..*)
lemma lin_add_lint: "\<And> n0 n01 n02. \<lbrakk> islintn (n01,a) ; islintn (n02,b); n0 \<le> min n01 n02 \<rbrakk>
\<Longrightarrow> islintn (n0, lin_add (a,b))"
proof (induct a b rule: lin_add.induct)
case (58 i n r j m s)
have "(n =m \<and> i + j = 0) \<or> (n = m \<and> i+j \<noteq> 0) \<or> n <m \<or> m < n" by arith
moreover
{ assume "n = m"
and "i+j = 0"
hence ?case using "58" islintn_mon[where m = "n01" and n = "Suc m"]
islintn_mon[where m = "n02" and n = "Suc m"] by auto }
moreover
{ assume "n = m"
and "i+j \<noteq> 0"
hence ?case using "58" islintn_mon[where m = "n01" and n = "Suc m"]
islintn_mon[where m = "n02" and n = "Suc m"] by (auto simp add: Let_def) }
moreover
{ assume "n < m" hence ?case using 58 by force }
moreover
{ assume "m < n"
hence ?case using 58
apply (auto simp add: Let_def)
apply (erule allE[where x = "Suc m" ] )
by (erule allE[where x = "Suc m" ] ) simp }
ultimately show ?case by blast
qed(simp_all add: Let_def lin_add_cst_lint lin_add_cst_lint2)
lemma lin_add_lin:
assumes lina: "islinintterm a"
and linb: "islinintterm b"
shows "islinintterm (lin_add (a,b))"
using islinintterm_eq_islint islint_def lin_add_lint lina linb by auto
(* lin_mul multiplies a linear term by a constant *)
consts lin_mul :: "int \<times> intterm \<Rightarrow> intterm"
recdef lin_mul "measure (\<lambda>(c,t). size t)"
"lin_mul (c,Cst i) = (Cst (c*i))"
"lin_mul (c,Add (Mult (Cst c') (Var n)) r) =
(if c = 0 then (Cst 0) else
(Add (Mult (Cst (c*c')) (Var n)) (lin_mul (c,r))))"
lemma zmult_zadd_distrib[simp]: "(a::int) * (b+c) = a*b + a*c"
proof-
have "a*(b+c) = (b+c)*a" by simp
moreover have "(b+c)*a = b*a + c*a" by (simp add: zadd_zmult_distrib)
ultimately show ?thesis by simp
qed
(* lin_mul has the semantics of Mult *)
lemma lin_mul_corr:
assumes lint: "islinintterm t"
shows "I_intterm ats (lin_mul (c,t)) = I_intterm ats (Mult (Cst c) t)"
using lint
proof (induct c t rule: lin_mul.induct)
case (21 c c' n r)
have "islinintterm (Add (Mult (Cst c') (Var n)) r)" .
then have "islinintterm r"
by (rule islinintterm_subt[of "c'" "n" "r"])
then show ?case using "21.hyps" "21.prems" by simp
qed(auto)
(* lin_mul preserves linearity *)
lemma lin_mul_lin:
assumes lint: "islinintterm t"
shows "islinintterm (lin_mul(c,t))"
using lint
by (induct t rule: islinintterm.induct) auto
lemma lin_mul0:
assumes lint: "islinintterm t"
shows "lin_mul(0,t) = Cst 0"
using lint
by (induct t rule: islinintterm.induct) auto
lemma lin_mul_lintn:
"\<And> m. islintn(m,t) \<Longrightarrow> islintn(m,lin_mul(l,t))"
by (induct l t rule: lin_mul.induct) simp_all
(* lin_neg neagtes a linear term *)
constdefs lin_neg :: "intterm \<Rightarrow> intterm"
"lin_neg i == lin_mul ((-1::int),i)"
(* lin_neg has the semantics of Neg *)
lemma lin_neg_corr:
assumes lint: "islinintterm t"
shows "I_intterm ats (lin_neg t) = I_intterm ats (Neg t)"
using lint lin_mul_corr
by (simp add: lin_neg_def lin_mul_corr)
(* lin_neg preserves linearity *)
lemma lin_neg_lin:
assumes lint: "islinintterm t"
shows "islinintterm (lin_neg t)"
using lint
by (simp add: lin_mul_lin lin_neg_def)
(* Some properties about lin_add and lin-neg should be moved above *)
lemma lin_neg_idemp:
assumes lini: "islinintterm i"
shows "lin_neg (lin_neg i) = i"
using lini
by (induct i rule: islinintterm.induct) (auto simp add: lin_neg_def)
lemma lin_neg_lin_add_distrib:
assumes lina : "islinintterm a"
and linb :"islinintterm b"
shows "lin_neg (lin_add(a,b)) = lin_add (lin_neg a, lin_neg b)"
using lina linb
proof (induct a b rule: lin_add.induct)
case (58 c1 n1 r1 c2 n2 r2)
from prems have lincnr1:"islinintterm (Add (Mult (Cst c1) (Var n1)) r1)" by simp
have linr1: "islinintterm r1" by (rule islinintterm_subt[OF lincnr1])
from prems have lincnr2: "islinintterm (Add (Mult (Cst c2) (Var n2)) r2)" by simp
have linr2: "islinintterm r2" by (rule islinintterm_subt[OF lincnr2])
have "n1 = n2 \<or> n1 < n2 \<or> n1 > n2" by arith
show ?case using prems linr1 linr2 by (simp_all add: lin_neg_def Let_def)
next
case (59 c n r b)
from prems have lincnr: "islinintterm (Add (Mult (Cst c) (Var n)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
show ?case using prems linr by (simp add: lin_neg_def Let_def)
next
case (60 b c n r)
from prems have lincnr: "islinintterm (Add (Mult (Cst c) (Var n)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
show ?case using prems linr by (simp add: lin_neg_def Let_def)
qed (simp_all add: lin_neg_def)
(* linearize tries to linearize a term *)
consts linearize :: "intterm \<Rightarrow> intterm option"
recdef linearize "measure (\<lambda>t. size t)"
"linearize (Cst b) = Some (Cst b)"
"linearize (Var n) = Some (Add (Mult (Cst 1) (Var n)) (Cst 0))"
"linearize (Neg i) = lift_un lin_neg (linearize i)"
"linearize (Add i j) = lift_bin(\<lambda> x. \<lambda> y. lin_add(x,y), linearize i, linearize j)"
"linearize (Sub i j) =
lift_bin(\<lambda> x. \<lambda> y. lin_add(x,lin_neg y), linearize i, linearize j)"
"linearize (Mult i j) =
(case linearize i of
None \<Rightarrow> None
| Some li \<Rightarrow> (case li of
Cst b \<Rightarrow> (case linearize j of
None \<Rightarrow> None
| (Some lj) \<Rightarrow> Some (lin_mul(b,lj)))
| _ \<Rightarrow> (case linearize j of
None \<Rightarrow> None
| (Some lj) \<Rightarrow> (case lj of
Cst b \<Rightarrow> Some (lin_mul (b,li))
| _ \<Rightarrow> None))))"
lemma linearize_linear1:
assumes lin: "linearize t \<noteq> None"
shows "islinintterm (the (linearize t))"
using lin
proof (induct t rule: linearize.induct)
case (1 b) show ?case by simp
next
case (2 n) show ?case by simp
next
case (3 i) show ?case
proof-
have "(linearize i = None) \<or> (\<exists>li. linearize i = Some li)" by auto
moreover
{ assume "linearize i = None" with prems have ?thesis by auto}
moreover
{ assume lini: "\<exists>li. linearize i = Some li"
from lini obtain "li" where "linearize i = Some li" by blast
have linli: "islinintterm li" by (simp!)
moreover have "linearize (Neg i) = Some (lin_neg li)" using prems by simp
moreover from linli have "islinintterm(lin_neg li)" by (simp add: lin_neg_lin)
ultimately have ?thesis by simp
}
ultimately show ?thesis by blast
qed
next
case (4 i j) show ?case
proof-
have "(linearize i = None) \<or> ((\<exists> li. linearize i = Some li) \<and> linearize j = None) \<or> ((\<exists> li. linearize i = Some li) \<and> (\<exists> lj. linearize j = Some lj))" by auto
moreover
{
assume nlini: "linearize i = None"
from nlini have "linearize (Add i j) = None"
by (simp add: Let_def measure_def inv_image_def) then have ?thesis using prems by auto}
moreover
{ assume nlinj: "linearize j = None"
and lini: "\<exists> li. linearize i = Some li"
from nlinj lini have "linearize (Add i j) = None"
by (simp add: Let_def measure_def inv_image_def, auto) with prems have ?thesis by auto}
moreover
{ assume lini: "\<exists>li. linearize i = Some li"
and linj: "\<exists>lj. linearize j = Some lj"
from lini obtain "li" where "linearize i = Some li" by blast
have linli: "islinintterm li" by (simp!)
from linj obtain "lj" where "linearize j = Some lj" by blast
have linlj: "islinintterm lj" by (simp!)
moreover from lini linj have "linearize (Add i j) = Some (lin_add (li,lj))"
by (simp add: measure_def inv_image_def, auto!)
moreover from linli linlj have "islinintterm(lin_add (li,lj))" by (simp add: lin_add_lin)
ultimately have ?thesis by simp }
ultimately show ?thesis by blast
qed
next
case (5 i j)show ?case
proof-
have "(linearize i = None) \<or> ((\<exists> li. linearize i = Some li) \<and> linearize j = None) \<or> ((\<exists> li. linearize i = Some li) \<and> (\<exists> lj. linearize j = Some lj))" by auto
moreover
{
assume nlini: "linearize i = None"
from nlini have "linearize (Sub i j) = None" by (simp add: Let_def measure_def inv_image_def) then have ?thesis by (auto!)
}
moreover
{
assume lini: "\<exists> li. linearize i = Some li"
and nlinj: "linearize j = None"
from nlinj lini have "linearize (Sub i j) = None"
by (simp add: Let_def measure_def inv_image_def, auto) then have ?thesis by (auto!)
}
moreover
{
assume lini: "\<exists>li. linearize i = Some li"
and linj: "\<exists>lj. linearize j = Some lj"
from lini obtain "li" where "linearize i = Some li" by blast
have linli: "islinintterm li" by (simp!)
from linj obtain "lj" where "linearize j = Some lj" by blast
have linlj: "islinintterm lj" by (simp!)
moreover from lini linj have "linearize (Sub i j) = Some (lin_add (li,lin_neg lj))"
by (simp add: measure_def inv_image_def, auto!)
moreover from linli linlj have "islinintterm(lin_add (li,lin_neg lj))" by (simp add: lin_add_lin lin_neg_lin)
ultimately have ?thesis by simp
}
ultimately show ?thesis by blast
qed
next
case (6 i j)show ?case
proof-
have cses: "(linearize i = None) \<or>
((\<exists> li. linearize i = Some li) \<and> linearize j = None) \<or>
((\<exists> li. linearize i = Some li) \<and> (\<exists> bj. linearize j = Some (Cst bj)))
\<or> ((\<exists> bi. linearize i = Some (Cst bi)) \<and> (\<exists> lj. linearize j = Some lj))
\<or> ((\<exists> li. linearize i = Some li \<and> \<not> (\<exists> bi. li = Cst bi)) \<and> (\<exists> lj. linearize j = Some lj \<and> \<not> (\<exists> bj. lj = Cst bj)))" by auto
moreover
{
assume nlini: "linearize i = None"
from nlini have "linearize (Mult i j) = None"
by (simp add: Let_def measure_def inv_image_def)
with prems have ?thesis by auto }
moreover
{ assume lini: "\<exists> li. linearize i = Some li"
and nlinj: "linearize j = None"
from lini obtain "li" where "linearize i = Some li" by blast
moreover from nlinj lini have "linearize (Mult i j) = None"
using prems
by (cases li ) (auto simp add: Let_def measure_def inv_image_def)
with prems have ?thesis by auto}
moreover
{ assume lini: "\<exists>li. linearize i = Some li"
and linj: "\<exists>bj. linearize j = Some (Cst bj)"
from lini obtain "li" where li_def: "linearize i = Some li" by blast
from prems have linli: "islinintterm li" by simp
moreover
from linj obtain "bj" where bj_def: "linearize j = Some (Cst bj)" by blast
have linlj: "islinintterm (Cst bj)" by simp
moreover from lini linj prems
have "linearize (Mult i j) = Some (lin_mul (bj,li))"
by (cases li) (auto simp add: measure_def inv_image_def)
moreover from linli linlj have "islinintterm(lin_mul (bj,li))" by (simp add: lin_mul_lin)
ultimately have ?thesis by simp }
moreover
{ assume lini: "\<exists>bi. linearize i = Some (Cst bi)"
and linj: "\<exists>lj. linearize j = Some lj"
from lini obtain "bi" where "linearize i = Some (Cst bi)" by blast
from prems have linli: "islinintterm (Cst bi)" by simp
moreover
from linj obtain "lj" where "linearize j = Some lj" by blast
from prems have linlj: "islinintterm lj" by simp
moreover from lini linj prems have "linearize (Mult i j) = Some (lin_mul (bi,lj))"
by (simp add: measure_def inv_image_def)
moreover from linli linlj have "islinintterm(lin_mul (bi,lj))" by (simp add: lin_mul_lin)
ultimately have ?thesis by simp }
moreover
{ assume linc: "\<exists> li. linearize i = Some li \<and> \<not> (\<exists> bi. li = Cst bi)"
and ljnc: "\<exists> lj. linearize j = Some lj \<and> \<not> (\<exists> bj. lj = Cst bj)"
from linc obtain "li" where "linearize i = Some li \<and> \<not> (\<exists> bi. li = Cst bi)" by blast
moreover
from ljnc obtain "lj" where "linearize j = Some lj \<and> \<not> (\<exists> bj. lj = Cst bj)" by blast
ultimately have "linearize (Mult i j) = None"
by (cases li, auto simp add: measure_def inv_image_def) (cases lj, auto)+
with prems have ?thesis by simp }
ultimately show ?thesis by blast
qed
qed
(* the result of linearize, when successful, is a linear term*)
lemma linearize_linear: "\<And> t'. linearize t = Some t' \<Longrightarrow> islinintterm t'"
proof-
fix t'
assume lint: "linearize t = Some t'"
from lint have lt: "linearize t \<noteq> None" by auto
then have "islinintterm (the (linearize t))" by (rule_tac linearize_linear1[OF lt])
with lint show "islinintterm t'" by simp
qed
lemma linearize_corr1:
assumes lin: "linearize t \<noteq> None"
shows "I_intterm ats t = I_intterm ats (the (linearize t))"
using lin
proof (induct t rule: linearize.induct)
case (3 i) show ?case
proof-
have "(linearize i = None) \<or> (\<exists>li. linearize i = Some li)" by auto
moreover
{
assume "linearize i = None"
have ?thesis using prems by simp
}
moreover
{
assume lini: "\<exists>li. linearize i = Some li"
from lini have lini2: "linearize i \<noteq> None" by simp
from lini obtain "li" where "linearize i = Some li" by blast
from lini2 lini have "islinintterm (the (linearize i))"
by (simp add: linearize_linear1[OF lini2])
then have linli: "islinintterm li" using prems by simp
have ieqli: "I_intterm ats i = I_intterm ats li" using prems by simp
moreover have "linearize (Neg i) = Some (lin_neg li)" using prems by simp
moreover from ieqli linli have "I_intterm ats (Neg i) = I_intterm ats (lin_neg li)" by (simp add: lin_neg_corr[OF linli])
ultimately have ?thesis using prems by (simp add: lin_neg_corr)
}
ultimately show ?thesis by blast
qed
next
case (4 i j) show ?case
proof-
have "(linearize i = None) \<or> ((\<exists> li. linearize i = Some li) \<and> linearize j = None) \<or> ((\<exists> li. linearize i = Some li) \<and> (\<exists> lj. linearize j = Some lj))" by auto
moreover
{
assume nlini: "linearize i = None"
from nlini have "linearize (Add i j) = None" by (simp add: Let_def measure_def inv_image_def) then have ?thesis using prems by auto
}
moreover
{
assume nlinj: "linearize j = None"
and lini: "\<exists> li. linearize i = Some li"
from nlinj lini have "linearize (Add i j) = None"
by (simp add: Let_def measure_def inv_image_def, auto)
then have ?thesis using prems by auto
}
moreover
{
assume lini: "\<exists>li. linearize i = Some li"
and linj: "\<exists>lj. linearize j = Some lj"
from lini have lini2: "linearize i \<noteq> None" by simp
from linj have linj2: "linearize j \<noteq> None" by simp
from lini obtain "li" where "linearize i = Some li" by blast
from lini2 have "islinintterm (the (linearize i))" by (simp add: linearize_linear1)
then have linli: "islinintterm li" using prems by simp
from linj obtain "lj" where "linearize j = Some lj" by blast
from linj2 have "islinintterm (the (linearize j))" by (simp add: linearize_linear1)
then have linlj: "islinintterm lj" using prems by simp
moreover from lini linj have "linearize (Add i j) = Some (lin_add (li,lj))"
using prems by (simp add: measure_def inv_image_def)
moreover from linli linlj have "I_intterm ats (lin_add (li,lj)) = I_intterm ats (Add li lj)" by (simp add: lin_add_corr)
ultimately have ?thesis using prems by simp
}
ultimately show ?thesis by blast
qed
next
case (5 i j)show ?case
proof-
have "(linearize i = None) \<or> ((\<exists> li. linearize i = Some li) \<and> linearize j = None) \<or> ((\<exists> li. linearize i = Some li) \<and> (\<exists> lj. linearize j = Some lj))" by auto
moreover
{
assume nlini: "linearize i = None"
from nlini have "linearize (Sub i j) = None" by (simp add: Let_def measure_def inv_image_def) then have ?thesis using prems by auto
}
moreover
{
assume lini: "\<exists> li. linearize i = Some li"
and nlinj: "linearize j = None"
from nlinj lini have "linearize (Sub i j) = None"
by (simp add: Let_def measure_def inv_image_def, auto) with prems have ?thesis by auto
}
moreover
{
assume lini: "\<exists>li. linearize i = Some li"
and linj: "\<exists>lj. linearize j = Some lj"
from lini have lini2: "linearize i \<noteq> None" by simp
from linj have linj2: "linearize j \<noteq> None" by simp
from lini obtain "li" where "linearize i = Some li" by blast
from lini2 have "islinintterm (the (linearize i))" by (simp add: linearize_linear1)
with prems have linli: "islinintterm li" by simp
from linj obtain "lj" where "linearize j = Some lj" by blast
from linj2 have "islinintterm (the (linearize j))" by (simp add: linearize_linear1)
with prems have linlj: "islinintterm lj" by simp
moreover from prems have "linearize (Sub i j) = Some (lin_add (li,lin_neg lj))"
by (simp add: measure_def inv_image_def)
moreover from linlj have linnlj:"islinintterm (lin_neg lj)" by (simp add: lin_neg_lin)
moreover from linli linnlj have "I_intterm ats (lin_add (li,lin_neg lj)) = I_intterm ats (Add li (lin_neg lj))" by (simp only: lin_add_corr[OF linli linnlj])
moreover from linli linlj linnlj have "I_intterm ats (Add li (lin_neg lj)) = I_intterm ats (Sub li lj)"
by (simp add: lin_neg_corr)
ultimately have ?thesis using prems by simp
}
ultimately show ?thesis by blast
qed
next
case (6 i j)show ?case
proof-
have cses: "(linearize i = None) \<or>
((\<exists> li. linearize i = Some li) \<and> linearize j = None) \<or>
((\<exists> li. linearize i = Some li) \<and> (\<exists> bj. linearize j = Some (Cst bj)))
\<or> ((\<exists> bi. linearize i = Some (Cst bi)) \<and> (\<exists> lj. linearize j = Some lj))
\<or> ((\<exists> li. linearize i = Some li \<and> \<not> (\<exists> bi. li = Cst bi)) \<and> (\<exists> lj. linearize j = Some lj \<and> \<not> (\<exists> bj. lj = Cst bj)))" by auto
moreover
{
assume nlini: "linearize i = None"
from nlini have "linearize (Mult i j) = None" by (simp add: Let_def measure_def inv_image_def) with prems have ?thesis by auto
}
moreover
{
assume lini: "\<exists> li. linearize i = Some li"
and nlinj: "linearize j = None"
from lini obtain "li" where "linearize i = Some li" by blast
moreover from prems have "linearize (Mult i j) = None"
by (cases li) (simp_all add: Let_def measure_def inv_image_def)
with prems have ?thesis by auto
}
moreover
{
assume lini: "\<exists>li. linearize i = Some li"
and linj: "\<exists>bj. linearize j = Some (Cst bj)"
from lini have lini2: "linearize i \<noteq> None" by simp
from linj have linj2: "linearize j \<noteq> None" by auto
from lini obtain "li" where "linearize i = Some li" by blast
from lini2 have "islinintterm (the (linearize i))" by (simp add: linearize_linear1)
with prems have linli: "islinintterm li" by simp
moreover
from linj obtain "bj" where "linearize j = Some (Cst bj)" by blast
have linlj: "islinintterm (Cst bj)" by simp
moreover from prems have "linearize (Mult i j) = Some (lin_mul (bj,li))"
by (cases li) (auto simp add: measure_def inv_image_def)
then have lm1: "I_intterm ats (the(linearize (Mult i j))) = I_intterm ats (lin_mul (bj,li))" by simp
moreover from linli linlj have "I_intterm ats (lin_mul(bj,li)) = I_intterm ats (Mult li (Cst bj))" by (simp add: lin_mul_corr)
with prems
have "I_intterm ats (lin_mul(bj,li)) = I_intterm ats (Mult li (the (linearize j)))"
by auto
moreover have "I_intterm ats (Mult li (the (linearize j))) = I_intterm ats (Mult i (the (linearize j)))" using prems by simp
moreover have "I_intterm ats i = I_intterm ats (the (linearize i))"
using lini2 lini "6.hyps" by simp
moreover have "I_intterm ats j = I_intterm ats (the (linearize j))"
using prems by (cases li) (auto simp add: measure_def inv_image_def)
ultimately have ?thesis by auto }
moreover
{ assume lini: "\<exists>bi. linearize i = Some (Cst bi)"
and linj: "\<exists>lj. linearize j = Some lj"
from lini have lini2 : "linearize i \<noteq> None" by auto
from linj have linj2 : "linearize j \<noteq> None" by auto
from lini obtain "bi" where "linearize i = Some (Cst bi)" by blast
have linli: "islinintterm (Cst bi)" using prems by simp
moreover
from linj obtain "lj" where "linearize j = Some lj" by blast
from linj2 have "islinintterm (the (linearize j))" by (simp add: linearize_linear1)
then have linlj: "islinintterm lj" by (simp!)
moreover from linli lini linj have "linearize (Mult i j) = Some (lin_mul (bi,lj))" apply (simp add: measure_def inv_image_def)
apply auto by (case_tac "li::intterm",auto!)
then have lm1: "I_intterm ats (the(linearize (Mult i j))) = I_intterm ats (lin_mul (bi,lj))" by simp
moreover from linli linlj have "I_intterm ats (lin_mul(bi,lj)) = I_intterm ats (Mult (Cst bi) lj)" by (simp add: lin_mul_corr)
then have "I_intterm ats (lin_mul(bi,lj)) = I_intterm ats (Mult (the (linearize i)) lj)" by (auto!)
moreover have "I_intterm ats (Mult (the (linearize i)) lj) = I_intterm ats (Mult (the (linearize i)) j)" using lini lini2 by (simp!)
moreover have "I_intterm ats i = I_intterm ats (the (linearize i))"
using lini2 lini "6.hyps" by simp
moreover have "I_intterm ats j = I_intterm ats (the (linearize j))"
using linj linj2 lini lini2 linli linlj "6.hyps" by (auto!)
ultimately have ?thesis by auto }
moreover
{ assume linc: "\<exists> li. linearize i = Some li \<and> \<not> (\<exists> bi. li = Cst bi)"
and ljnc: "\<exists> lj. linearize j = Some lj \<and> \<not> (\<exists> bj. lj = Cst bj)"
from linc obtain "li" where "\<exists> li. linearize i = Some li \<and> \<not> (\<exists> bi. li = Cst bi)" by blast
moreover
from ljnc obtain "lj" where "\<exists> lj. linearize j = Some lj \<and> \<not> (\<exists> bj. lj = Cst bj)" by blast
ultimately have "linearize (Mult i j) = None"
apply (simp add: measure_def inv_image_def)
apply (case_tac "linearize i", auto)
apply (case_tac a)
apply (auto!)
by (case_tac "lj",auto)+
then have ?thesis by (simp!) }
ultimately show ?thesis by blast
qed
qed simp_all
(* linearize, when successfull, preserves semantics *)
lemma linearize_corr: "\<And> t'. linearize t = Some t' \<Longrightarrow> I_intterm ats t = I_intterm ats t' "
proof-
fix t'
assume lint: "linearize t = Some t'"
show "I_intterm ats t = I_intterm ats t'"
proof-
from lint have lt: "linearize t \<noteq> None" by simp
then have "I_intterm ats t = I_intterm ats (the (linearize t))"
by (rule_tac linearize_corr1[OF lt])
with lint show ?thesis by simp
qed
qed
(* tries to linearize a formula *)
consts linform :: "QF \<Rightarrow> QF option"
primrec
"linform (Le it1 it2) =
lift_bin(\<lambda>x. \<lambda>y. Le (lin_add(x,lin_neg y)) (Cst 0),linearize it1, linearize it2)"
"linform (Eq it1 it2) =
lift_bin(\<lambda>x. \<lambda>y. Eq (lin_add(x,lin_neg y)) (Cst 0),linearize it1, linearize it2)"
"linform (Divides d t) =
(case linearize d of
None \<Rightarrow> None
| Some ld \<Rightarrow> (case ld of
Cst b \<Rightarrow>
(if (b=0) then None
else
(case linearize t of
None \<Rightarrow> None
| Some lt \<Rightarrow> Some (Divides ld lt)))
| _ \<Rightarrow> None))"
"linform T = Some T"
"linform F = Some F"
"linform (NOT p) = lift_un NOT (linform p)"
"linform (And p q)= lift_bin(\<lambda>f. \<lambda>g. And f g, linform p, linform q)"
"linform (Or p q) = lift_bin(\<lambda>f. \<lambda>g. Or f g, linform p, linform q)"
(* linearity of formulae *)
consts islinform :: "QF \<Rightarrow> bool"
recdef islinform "measure size"
"islinform (Le it (Cst i)) = (i=0 \<and> islinintterm it )"
"islinform (Eq it (Cst i)) = (i=0 \<and> islinintterm it)"
"islinform (Divides (Cst d) t) = (d \<noteq> 0 \<and> islinintterm t)"
"islinform T = True"
"islinform F = True"
"islinform (NOT (Divides (Cst d) t)) = (d \<noteq> 0 \<and> islinintterm t)"
"islinform (NOT (Eq it (Cst i))) = (i=0 \<and> islinintterm it)"
"islinform (And p q)= ((islinform p) \<and> (islinform q))"
"islinform (Or p q) = ((islinform p) \<and> (islinform q))"
"islinform p = False"
(* linform preserves nnf, if successful *)
lemma linform_nnf:
assumes nnfp: "isnnf p"
shows "\<And> p'. \<lbrakk>linform p = Some p'\<rbrakk> \<Longrightarrow> isnnf p'"
using nnfp
proof (induct p rule: isnnf.induct, simp_all)
case (goal1 a b p')
show ?case
using prems
by (cases "linearize a", auto) (cases "linearize b", auto)
next
case (goal2 a b p')
show ?case
using prems
by (cases "linearize a", auto) (cases "linearize b", auto)
next
case (goal3 d t p')
show ?case
using prems
apply (cases "linearize d", auto)
apply (case_tac "a",auto)
apply (case_tac "int=0",auto)
by (cases "linearize t",auto)
next
case (goal4 f g p') show ?case
using prems
by (cases "linform f", auto) (cases "linform g", auto)
next
case (goal5 f g p') show ?case
using prems
by (cases "linform f", auto) (cases "linform g", auto)
next
case (goal6 d t p') show ?case
using prems
apply (cases "linearize d", auto)
apply (case_tac "a", auto)
apply (case_tac "int = 0",auto)
by (cases "linearize t", auto)
next
case (goal7 a b p')
show ?case
using prems
by (cases "linearize a", auto) (cases "linearize b", auto)
qed
lemma linform_corr: "\<And> lp. \<lbrakk> isnnf p ; linform p = Some lp \<rbrakk> \<Longrightarrow>
(qinterp ats p = qinterp ats lp)"
proof (induct p rule: linform.induct)
case (Le x y)
show ?case
using "Le.prems"
proof-
have "(\<exists> lx ly. linearize x = Some lx \<and> linearize y = Some ly) \<or>
(linearize x = None) \<or> (linearize y = None)"by auto
moreover
{
assume linxy: "\<exists> lx ly. linearize x = Some lx \<and> linearize y = Some ly"
from linxy obtain "lx" "ly"
where lxly:"linearize x = Some lx \<and> linearize y = Some ly" by blast
then
have lxeqx: "I_intterm ats x = I_intterm ats lx"
by (simp add: linearize_corr)
from lxly have lxlin: "islinintterm lx"
by (auto simp add: linearize_linear)
from lxly have lyeqy: "I_intterm ats y = I_intterm ats ly"
by (simp add: linearize_corr)
from lxly have lylin: "islinintterm ly"
by (auto simp add: linearize_linear)
from "prems"
have lpeqle: "lp = (Le (lin_add(lx,lin_neg ly)) (Cst 0))"
by auto
moreover
have lin1: "islinintterm (Cst 1)" by simp
then
have ?thesis
using lxlin lylin lin1 lin_add_lin lin_neg_lin "prems" lxly lpeqle
by (simp add: lin_add_corr lin_neg_corr lxeqx lyeqy)
}
moreover
{
assume "linearize x = None"
have ?thesis using "prems" by simp
}
moreover
{
assume "linearize y = None"
then have ?thesis using "prems"
by (case_tac "linearize x", auto)
}
ultimately show ?thesis by blast
qed
next
case (Eq x y)
show ?case
using "Eq.prems"
proof-
have "(\<exists> lx ly. linearize x = Some lx \<and> linearize y = Some ly) \<or>
(linearize x = None) \<or> (linearize y = None)"by auto
moreover
{
assume linxy: "\<exists> lx ly. linearize x = Some lx \<and> linearize y = Some ly"
from linxy obtain "lx" "ly"
where lxly:"linearize x = Some lx \<and> linearize y = Some ly" by blast
then
have lxeqx: "I_intterm ats x = I_intterm ats lx"
by (simp add: linearize_corr)
from lxly have lxlin: "islinintterm lx"
by (auto simp add: linearize_linear)
from lxly have lyeqy: "I_intterm ats y = I_intterm ats ly"
by (simp add: linearize_corr)
from lxly have lylin: "islinintterm ly"
by (auto simp add: linearize_linear)
from "prems"
have lpeqle: "lp = (Eq (lin_add(lx,lin_neg ly)) (Cst 0))"
by auto
moreover
have lin1: "islinintterm (Cst 1)" by simp
then
have ?thesis
using lxlin lylin lin1 lin_add_lin lin_neg_lin "prems" lxly lpeqle
by (simp add: lin_add_corr lin_neg_corr lxeqx lyeqy)
}
moreover
{
assume "linearize x = None"
have ?thesis using "prems" by simp
}
moreover
{
assume "linearize y = None"
then have ?thesis using "prems"
by (case_tac "linearize x", auto)
}
ultimately show ?thesis by blast
qed
next
case (Divides d t)
show ?case
using "Divides.prems"
apply (case_tac "linearize d",auto)
apply (case_tac a, auto)
apply (case_tac "int = 0", auto)
apply (case_tac "linearize t", auto)
apply (simp add: linearize_corr)
apply (case_tac a, auto)
apply (case_tac "int = 0", auto)
by (case_tac "linearize t", auto simp add: linearize_corr)
next
case (NOT f) show ?case
using "prems"
proof-
have "(\<exists> lf. linform f = Some lf) \<or> (linform f = None)" by auto
moreover
{
assume linf: "\<exists> lf. linform f = Some lf"
from prems have "isnnf (NOT f)" by simp
then have fnnf: "isnnf f" by (cases f) auto
from linf obtain "lf" where lf: "linform f = Some lf" by blast
then have "lp = NOT lf" using "prems" by auto
with "NOT.prems" "NOT.hyps" lf fnnf
have ?case by simp
}
moreover
{
assume "linform f = None"
then
have "linform (NOT f) = None" by simp
then
have ?thesis using "NOT.prems" by simp
}
ultimately show ?thesis by blast
qed
next
case (Or f g)
show ?case using "Or.hyps"
proof -
have "((\<exists> lf. linform f = Some lf ) \<and> (\<exists> lg. linform g = Some lg)) \<or>
(linform f = None) \<or> (linform g = None)" by auto
moreover
{
assume linf: "\<exists> lf. linform f = Some lf"
and ling: "\<exists> lg. linform g = Some lg"
from linf obtain "lf" where lf: "linform f = Some lf" by blast
from ling obtain "lg" where lg: "linform g = Some lg" by blast
from lf lg have "linform (Or f g) = Some (Or lf lg)" by simp
then have "lp = Or lf lg" using lf lg "prems" by simp
with lf lg "prems" have ?thesis by simp
}
moreover
{
assume "linform f = None"
then have ?thesis using "Or.prems" by auto
}
moreover
{
assume "linform g = None"
then have ?thesis using "Or.prems" by (case_tac "linform f", auto)
}
ultimately show ?thesis by blast
qed
next
case (And f g)
show ?case using "And.hyps"
proof -
have "((\<exists> lf. linform f = Some lf ) \<and> (\<exists> lg. linform g = Some lg)) \<or>
(linform f = None) \<or> (linform g = None)" by auto
moreover
{
assume linf: "\<exists> lf. linform f = Some lf"
and ling: "\<exists> lg. linform g = Some lg"
from linf obtain "lf" where lf: "linform f = Some lf" by blast
from ling obtain "lg" where lg: "linform g = Some lg" by blast
from lf lg have "linform (And f g) = Some (And lf lg)" by simp
then have "lp = And lf lg" using lf lg "prems" by simp
with lf lg "prems" have ?thesis by simp
}
moreover
{
assume "linform f = None"
then have ?thesis using "And.prems" by auto
}
moreover
{
assume "linform g = None"
then have ?thesis using "And.prems" by (case_tac "linform f", auto)
}
ultimately show ?thesis by blast
qed
qed simp_all
(* the result of linform is a linear formula *)
lemma linform_lin: "\<And> lp. \<lbrakk> isnnf p ; linform p = Some lp\<rbrakk> \<Longrightarrow> islinform lp"
proof (induct p rule: linform.induct)
case (Le x y)
have "((\<exists> lx. linearize x = Some lx) \<and> (\<exists> ly. linearize y = Some ly)) \<or>
(linearize x = None) \<or> (linearize y = None) " by clarsimp
moreover
{
assume linx: "\<exists> lx. linearize x = Some lx"
and liny: "\<exists> ly. linearize y = Some ly"
from linx obtain "lx" where lx: "linearize x = Some lx" by blast
from liny obtain "ly" where ly: "linearize y = Some ly" by blast
from lx have lxlin: "islinintterm lx" by (simp add: linearize_linear)
from ly have lylin: "islinintterm ly" by (simp add: linearize_linear)
have lin1:"islinintterm (Cst 1)" by simp
have lin0: "islinintterm (Cst 0)" by simp
from "prems" have "lp = Le (lin_add(lx,lin_neg ly)) (Cst 0)"
by auto
with lin0 lin1 lxlin lylin "prems"
have ?case by (simp add: lin_add_lin lin_neg_lin)
}
moreover
{
assume "linearize x = None"
then have ?case using "prems" by simp
}
moreover
{
assume "linearize y = None"
then have ?case using "prems" by (case_tac "linearize x",simp_all)
}
ultimately show ?case by blast
next
case (Eq x y)
have "((\<exists> lx. linearize x = Some lx) \<and> (\<exists> ly. linearize y = Some ly)) \<or>
(linearize x = None) \<or> (linearize y = None) " by clarsimp
moreover
{
assume linx: "\<exists> lx. linearize x = Some lx"
and liny: "\<exists> ly. linearize y = Some ly"
from linx obtain "lx" where lx: "linearize x = Some lx" by blast
from liny obtain "ly" where ly: "linearize y = Some ly" by blast
from lx have lxlin: "islinintterm lx" by (simp add: linearize_linear)
from ly have lylin: "islinintterm ly" by (simp add: linearize_linear)
have lin1:"islinintterm (Cst 1)" by simp
have lin0: "islinintterm (Cst 0)" by simp
from "prems" have "lp = Eq (lin_add(lx,lin_neg ly)) (Cst 0)"
by auto
with lin0 lin1 lxlin lylin "prems"
have ?case by (simp add: lin_add_lin lin_neg_lin)
}
moreover
{
assume "linearize x = None"
then have ?case using "prems" by simp
}
moreover
{
assume "linearize y = None"
then have ?case using "prems" by (case_tac "linearize x",simp_all)
}
ultimately show ?case by blast
next
case (Divides d t)
show ?case
using prems
apply (case_tac "linearize d", auto)
apply (case_tac a, auto)
apply (case_tac "int = 0", auto)
by (case_tac "linearize t",auto simp add: linearize_linear)
next
case (Or f g)
show ?case using "Or.hyps"
proof -
have "((\<exists> lf. linform f = Some lf ) \<and> (\<exists> lg. linform g = Some lg)) \<or>
(linform f = None) \<or> (linform g = None)" by auto
moreover
{
assume linf: "\<exists> lf. linform f = Some lf"
and ling: "\<exists> lg. linform g = Some lg"
from linf obtain "lf" where lf: "linform f = Some lf" by blast
from ling obtain "lg" where lg: "linform g = Some lg" by blast
from lf lg have "linform (Or f g) = Some (Or lf lg)" by simp
then have "lp = Or lf lg" using lf lg "prems" by simp
with lf lg "prems" have ?thesis by simp
}
moreover
{
assume "linform f = None"
then have ?thesis using "Or.prems" by auto
}
moreover
{
assume "linform g = None"
then have ?thesis using "Or.prems" by (case_tac "linform f", auto)
}
ultimately show ?thesis by blast
qed
next
case (And f g)
show ?case using "And.hyps"
proof -
have "((\<exists> lf. linform f = Some lf ) \<and> (\<exists> lg. linform g = Some lg)) \<or>
(linform f = None) \<or> (linform g = None)" by auto
moreover
{
assume linf: "\<exists> lf. linform f = Some lf"
and ling: "\<exists> lg. linform g = Some lg"
from linf obtain "lf" where lf: "linform f = Some lf" by blast
from ling obtain "lg" where lg: "linform g = Some lg" by blast
from lf lg have "linform (And f g) = Some (And lf lg)" by simp
then have "lp = And lf lg" using lf lg "prems" by simp
with lf lg "prems" have ?thesis by simp
}
moreover
{
assume "linform f = None"
then have ?thesis using "And.prems" by auto
}
moreover
{
assume "linform g = None"
then have ?thesis using "And.prems" by (case_tac "linform f", auto)
}
ultimately show ?thesis by blast
qed
next
case (NOT f) show ?case
using "prems"
proof-
have "(\<exists> lf. linform f = Some lf) \<or> (linform f = None)" by auto
moreover
{
assume linf: "\<exists> lf. linform f = Some lf"
from prems have "isnnf (NOT f)" by simp
then have fnnf: "isnnf f" by (cases f) auto
from linf obtain "lf" where lf: "linform f = Some lf" by blast
then have "lp = NOT lf" using "prems" by auto
with "NOT.prems" "NOT.hyps" lf fnnf
have ?thesis
using fnnf
apply (cases f, auto)
prefer 2
apply (case_tac "linearize intterm1",auto)
apply (case_tac a, auto)
apply (case_tac "int = 0", auto)
apply (case_tac "linearize intterm2")
apply (auto simp add: linearize_linear)
apply (case_tac "linearize intterm1",auto)
by (case_tac "linearize intterm2")
(auto simp add: linearize_linear lin_add_lin lin_neg_lin)
}
moreover
{
assume "linform f = None"
then
have "linform (NOT f) = None" by simp
then
have ?thesis using "NOT.prems" by simp
}
ultimately show ?thesis by blast
qed
qed (simp_all)
(* linform, if successfull, preserves quantifier freeness *)
lemma linform_isnnf: "islinform p \<Longrightarrow> isnnf p"
by (induct p rule: islinform.induct) auto
lemma linform_isqfree: "islinform p \<Longrightarrow> isqfree p"
using linform_isnnf nnf_isqfree by simp
lemma linform_qfree: "\<And> p'. \<lbrakk> isnnf p ; linform p = Some p'\<rbrakk> \<Longrightarrow> isqfree p'"
using linform_isqfree linform_lin
by simp
(* Definitions and lemmas about gcd and lcm *)
constdefs lcm :: "nat \<times> nat \<Rightarrow> nat"
"lcm \<equiv> (\<lambda>(m,n). m*n div gcd(m,n))"
constdefs ilcm :: "int \<Rightarrow> int \<Rightarrow> int"
"ilcm \<equiv> \<lambda>i.\<lambda>j. int (lcm(nat(abs i),nat(abs j)))"
(* ilcm_dvd12 are needed later *)
lemma lcm_dvd1:
assumes mpos: " m >0"
and npos: "n>0"
shows "m dvd (lcm(m,n))"
proof-
have "gcd(m,n) dvd n" by simp
then obtain "k" where "n = gcd(m,n) * k" using dvd_def by auto
then have "m*n div gcd(m,n) = m*(gcd(m,n)*k) div gcd(m,n)" by (simp add: mult_ac)
also have "\<dots> = m*k" using mpos npos gcd_zero by simp
finally show ?thesis by (simp add: lcm_def)
qed
lemma lcm_dvd2:
assumes mpos: " m >0"
and npos: "n>0"
shows "n dvd (lcm(m,n))"
proof-
have "gcd(m,n) dvd m" by simp
then obtain "k" where "m = gcd(m,n) * k" using dvd_def by auto
then have "m*n div gcd(m,n) = (gcd(m,n)*k)*n div gcd(m,n)" by (simp add: mult_ac)
also have "\<dots> = n*k" using mpos npos gcd_zero by simp
finally show ?thesis by (simp add: lcm_def)
qed
lemma ilcm_dvd1:
assumes anz: "a \<noteq> 0"
and bnz: "b \<noteq> 0"
shows "a dvd (ilcm a b)"
proof-
let ?na = "nat (abs a)"
let ?nb = "nat (abs b)"
have nap: "?na >0" using anz by simp
have nbp: "?nb >0" using bnz by simp
from nap nbp have "?na dvd lcm(?na,?nb)" using lcm_dvd1 by simp
thus ?thesis by (simp add: ilcm_def dvd_int_iff)
qed
lemma ilcm_dvd2:
assumes anz: "a \<noteq> 0"
and bnz: "b \<noteq> 0"
shows "b dvd (ilcm a b)"
proof-
let ?na = "nat (abs a)"
let ?nb = "nat (abs b)"
have nap: "?na >0" using anz by simp
have nbp: "?nb >0" using bnz by simp
from nap nbp have "?nb dvd lcm(?na,?nb)" using lcm_dvd2 by simp
thus ?thesis by (simp add: ilcm_def dvd_int_iff)
qed
lemma zdvd_self_abs1: "(d::int) dvd (abs d)"
by (case_tac "d <0", simp_all)
lemma zdvd_self_abs2: "(abs (d::int)) dvd d"
by (case_tac "d<0", simp_all)
(* lcm a b is positive for positive a and b *)
lemma lcm_pos:
assumes mpos: "m > 0"
and npos: "n>0"
shows "lcm (m,n) > 0"
proof(rule ccontr, simp add: lcm_def gcd_zero)
assume h:"m*n div gcd(m,n) = 0"
from mpos npos have "gcd (m,n) \<noteq> 0" using gcd_zero by simp
hence gcdp: "gcd(m,n) > 0" by simp
with h
have "m*n < gcd(m,n)"
by (cases "m * n < gcd (m, n)") (auto simp add: div_if[OF gcdp, where m="m*n"])
moreover
have "gcd(m,n) dvd m" by simp
with mpos dvd_imp_le have t1:"gcd(m,n) \<le> m" by simp
with npos have t1:"gcd(m,n)*n \<le> m*n" by simp
have "gcd(m,n) \<le> gcd(m,n)*n" using npos by simp
with t1 have "gcd(m,n) \<le> m*n" by arith
ultimately show "False" by simp
qed
lemma ilcm_pos:
assumes apos: " 0 < a"
and bpos: "0 < b"
shows "0 < ilcm a b"
proof-
let ?na = "nat (abs a)"
let ?nb = "nat (abs b)"
have nap: "?na >0" using apos by simp
have nbp: "?nb >0" using bpos by simp
have "0 < lcm (?na,?nb)" by (rule lcm_pos[OF nap nbp])
thus ?thesis by (simp add: ilcm_def)
qed
(* fomlcm computes the lcm of all c, where c is the coeffitient of Var 0 *)
consts formlcm :: "QF \<Rightarrow> int"
recdef formlcm "measure size"
"formlcm (Le (Add (Mult (Cst c) (Var 0)) r) (Cst i)) = abs c "
"formlcm (Eq (Add (Mult (Cst c) (Var 0)) r) (Cst i)) = abs c "
"formlcm (Divides (Cst d) (Add (Mult (Cst c) (Var 0)) r)) = abs c"
"formlcm (NOT p) = formlcm p"
"formlcm (And p q)= ilcm (formlcm p) (formlcm q)"
"formlcm (Or p q) = ilcm (formlcm p) (formlcm q)"
"formlcm p = 1"
(* the property that formlcm should fullfill *)
consts divideallc:: "int \<times> QF \<Rightarrow> bool"
recdef divideallc "measure (\<lambda>(i,p). size p)"
"divideallc (l,Le (Add (Mult (Cst c) (Var 0)) r) (Cst i)) = (c dvd l)"
"divideallc (l,Eq (Add (Mult (Cst c) (Var 0)) r) (Cst i)) = (c dvd l)"
"divideallc(l,Divides (Cst d) (Add (Mult (Cst c) (Var 0)) r)) = (c dvd l)"
"divideallc (l,NOT p) = divideallc(l,p)"
"divideallc (l,And p q) = (divideallc (l,p) \<and> divideallc (l,q))"
"divideallc (l,Or p q) = (divideallc (l,p) \<and> divideallc (l,q))"
"divideallc p = True"
(* formlcm retuns a positive integer *)
lemma formlcm_pos:
assumes linp: "islinform p"
shows "0 < formlcm p"
using linp
proof (induct p rule: formlcm.induct, simp_all add: ilcm_pos)
case (goal1 c r i)
have "i=0 \<or> i \<noteq> 0" by simp
moreover
{
assume "i \<noteq> 0" then have ?case using prems by simp
}
moreover
{
assume iz: "i = 0"
then have "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
then have "c\<noteq>0"
using prems
by (simp add: islininttermc0r[where c="c" and n="0" and r="r"])
then have ?case by simp
}
ultimately
show ?case by blast
next
case (goal2 c r i)
have "i=0 \<or> i \<noteq> 0" by simp
moreover
{
assume "i \<noteq> 0" then have ?case using prems by simp
}
moreover
{
assume iz: "i = 0"
then have "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
then have "c\<noteq>0"
using prems
by (simp add: islininttermc0r[where c="c" and n="0" and r="r"])
then have ?case by simp
}
ultimately
show ?case by blast
next
case (goal3 d c r)
show ?case using prems by (simp add: islininttermc0r[where c="c" and n="0" and r="r"])
next
case (goal4 f)
show ?case using prems
by (cases f,auto) (case_tac "intterm2", auto,case_tac "intterm1", auto)
qed
lemma divideallc_mono: "\<And> c. \<lbrakk> divideallc(c,p) ; c dvd d\<rbrakk> \<Longrightarrow> divideallc (d,p)"
proof (induct d p rule: divideallc.induct, simp_all)
case (goal1 l a b) show ?case by ( rule zdvd_trans [where m="a" and n="b" and k="l"])
next
case (goal2 l a b) show ?case by ( rule zdvd_trans [where m="a" and n="b" and k="l"])
next
case (goal3 l a b) show ?case by ( rule zdvd_trans [where m="a" and n="b" and k="l"])
next
case (goal4 l f g k)
have "divideallc (l,g)" using prems by clarsimp
moreover have "divideallc (l,f)" using prems by clarsimp
ultimately
show ?case by simp
next
case (goal5 l f g k)
have "divideallc (l,g)" using prems by clarsimp
moreover have "divideallc (l,f)" using prems by clarsimp
ultimately
show ?case by simp
qed
(* fomlcm retuns a number all coeffitients of Var 0 divide *)
lemma formlcm_divideallc:
assumes linp: "islinform p"
shows "divideallc(formlcm p, p)"
using linp
proof (induct p rule: formlcm.induct, simp_all add: zdvd_self_abs1)
case (goal1 f)
show ?case using prems
by (cases f,auto) (case_tac "intterm2", auto, case_tac "intterm1",auto)
next
case (goal2 f g)
have "formlcm f >0" using formlcm_pos prems by simp
hence "formlcm f \<noteq> 0" by simp
moreover have "formlcm g > 0" using formlcm_pos prems by simp
hence "formlcm g \<noteq> 0" by simp
ultimately
show ?case using prems formlcm_pos
by (simp add: ilcm_dvd1 ilcm_dvd2
divideallc_mono[where c="formlcm f" and d="ilcm (formlcm f) (formlcm g)"]
divideallc_mono[where c="formlcm g" and d="ilcm (formlcm f) (formlcm g)"])
next
case (goal3 f g)
have "formlcm f >0" using formlcm_pos prems by simp
hence "formlcm f \<noteq> 0" by simp
moreover have "formlcm g > 0" using formlcm_pos prems by simp
hence "formlcm g \<noteq> 0" by simp
ultimately
show ?case using prems
by (simp add: ilcm_dvd1 ilcm_dvd2
divideallc_mono[where c="formlcm f" and d="ilcm (formlcm f) (formlcm g)"]
divideallc_mono[where c="formlcm g" and d="ilcm (formlcm f) (formlcm g)"])
qed
(* adjustcoeff transforms the formula given an l , look at correctness thm*)
consts adjustcoeff :: "int \<times> QF \<Rightarrow> QF"
recdef adjustcoeff "measure (\<lambda>(l,p). size p)"
"adjustcoeff (l,(Le (Add (Mult (Cst c) (Var 0)) r) (Cst i))) =
(if c\<le>0 then
Le (Add (Mult (Cst -1) (Var 0)) (lin_mul (- (l div c), r))) (Cst (0::int))
else
Le (Add (Mult (Cst 1) (Var 0)) (lin_mul (l div c, r))) (Cst (0::int)))"
"adjustcoeff (l,(Eq (Add (Mult (Cst c) (Var 0)) r) (Cst i))) =
(Eq (Add (Mult (Cst 1) (Var 0)) (lin_mul (l div c, r))) (Cst (0::int)))"
"adjustcoeff (l,Divides (Cst d) (Add (Mult (Cst c) (Var 0)) r)) =
Divides (Cst ((l div c) * d))
(Add (Mult (Cst 1) (Var 0)) (lin_mul (l div c, r)))"
"adjustcoeff (l,NOT (Divides (Cst d) (Add (Mult (Cst c) (Var 0)) r))) = NOT (Divides (Cst ((l div c) * d))
(Add (Mult (Cst 1) (Var 0)) (lin_mul (l div c, r))))"
"adjustcoeff (l,(NOT(Eq (Add (Mult (Cst c) (Var 0)) r) (Cst i)))) =
(NOT(Eq (Add (Mult (Cst 1) (Var 0)) (lin_mul (l div c, r))) (Cst (0::int))))"
"adjustcoeff (l,And p q) = And (adjustcoeff (l,p)) (adjustcoeff(l,q))"
"adjustcoeff (l,Or p q) = Or (adjustcoeff (l,p)) (adjustcoeff(l,q))"
"adjustcoeff (l,p) = p"
(* unitycoeff expects a quantifier free formula an transforms it to an equivalent formula where the bound variable occurs only with coeffitient 1 or -1 *)
constdefs unitycoeff :: "QF \<Rightarrow> QF"
"unitycoeff p ==
(let l = formlcm p;
p' = adjustcoeff (l,p)
in (if l=1 then p' else
(And (Divides (Cst l) (Add (Mult (Cst 1) (Var 0)) (Cst 0))) p')))"
(* what is a unified formula *)
consts isunified :: "QF \<Rightarrow> bool"
recdef isunified "measure size"
"isunified (Le (Add (Mult (Cst i) (Var 0)) r) (Cst z)) =
((abs i) = 1 \<and> (islinform(Le (Add (Mult (Cst i) (Var 0)) r) (Cst z))))"
"isunified (Eq (Add (Mult (Cst i) (Var 0)) r) (Cst z)) =
((abs i) = 1 \<and> (islinform(Le (Add (Mult (Cst i) (Var 0)) r) (Cst z))))"
"isunified (NOT(Eq (Add (Mult (Cst i) (Var 0)) r) (Cst z))) =
((abs i) = 1 \<and> (islinform(Le (Add (Mult (Cst i) (Var 0)) r) (Cst z))))"
"isunified (Divides (Cst d) (Add (Mult (Cst i) (Var 0)) r)) =
((abs i) = 1 \<and> (islinform(Divides (Cst d) (Add (Mult (Cst i) (Var 0)) r))))"
"isunified (NOT(Divides (Cst d) (Add (Mult (Cst i) (Var 0)) r))) =
((abs i) = 1 \<and> (islinform(NOT(Divides (Cst d) (Add (Mult (Cst i) (Var 0)) r)))))"
"isunified (And p q) = (isunified p \<and> isunified q)"
"isunified (Or p q) = (isunified p \<and> isunified q)"
"isunified p = islinform p"
lemma unified_islinform: "isunified p \<Longrightarrow> islinform p"
by (induct p rule: isunified.induct) auto
lemma adjustcoeff_lenpos:
"0 < n \<Longrightarrow> adjustcoeff (l, Le (Add (Mult (Cst i) (Var n)) r) (Cst c)) =
Le (Add (Mult (Cst i) (Var n)) r) (Cst c)"
by (cases n, auto)
lemma adjustcoeff_eqnpos:
"0 < n \<Longrightarrow> adjustcoeff (l, Eq (Add (Mult (Cst i) (Var n)) r) (Cst c)) =
Eq (Add (Mult (Cst i) (Var n)) r) (Cst c)"
by (cases n, auto)
(* Properties of adjustcoeff and unitycoeff *)
(* Some simple lemmas used afterwards *)
lemma zmult_zle_mono: "(i::int) \<le> j \<Longrightarrow> 0 \<le> k \<Longrightarrow> k * i \<le> k * j"
apply (erule order_le_less [THEN iffD1, THEN disjE, of "0::int"])
apply (erule order_le_less [THEN iffD1, THEN disjE])
apply (rule order_less_imp_le)
apply (rule zmult_zless_mono2)
apply simp_all
done
lemma zmult_zle_mono_eq:
assumes kpos: "0 < k"
shows "((i::int) \<le> j) = (k*i \<le> k*j)" (is "?P = ?Q")
proof
assume P: ?P
from kpos have kge0: "0 \<le> k" by simp
show ?Q
by (rule zmult_zle_mono[OF P kge0])
next
assume ?Q
then have "k*i - k*j \<le> 0" by simp
then have le1: "k*(i-j) \<le> k*0"
by (simp add: zdiff_zmult_distrib2)
have "i -j \<le> 0"
by (rule mult_left_le_imp_le[OF le1 kpos])
then
show ?P by simp
qed
lemma adjustcoeff_le_corr:
assumes lpos: "0 < l"
and ipos: "0 < (i::int)"
and dvd: "i dvd l"
shows "(i*x + r \<le> 0) = (l*x + ((l div i)*r) \<le> 0)"
proof-
from lpos ipos have ilel: "i\<le>l" by (simp add: zdvd_imp_le [OF dvd lpos])
from ipos have inz: "i \<noteq> 0" by simp
have "i div i\<le> l div i"
by (simp add: zdiv_mono1[OF ilel ipos])
then have ldivipos:"0 < l div i"
by (simp add: zdiv_self[OF inz])
from dvd have "\<exists>i'. i*i' = l" by (auto simp add: dvd_def)
then obtain "i'" where ii'eql: "i*i' = l" by blast
have "(i * x + r \<le> 0) = (l div i * (i * x + r) \<le> l div i * 0)"
by (rule zmult_zle_mono_eq[OF ldivipos, where i="i*x + r" and j="0"])
also
have "(l div i * (i * x + r) \<le> l div i * 0) = ((l div i * i) * x + ((l div i)*r) \<le> 0)"
by (simp add: mult_ac)
also have "((l div i * i) * x + ((l div i)*r) \<le> 0) = (l*x + ((l div i)*r) \<le> 0)"
using sym[OF ii'eql] inz
by (simp add: zmult_ac)
finally
show ?thesis
by simp
qed
lemma adjustcoeff_le_corr2:
assumes lpos: "0 < l"
and ineg: "(i::int) < 0"
and dvd: "i dvd l"
shows "(i*x + r \<le> 0) = ((-l)*x + ((-(l div i))*r) \<le> 0)"
proof-
from dvd have midvdl: "-i dvd l" by simp
from ineg have mipos: "0 < -i" by simp
from lpos ineg have milel: "-i\<le>l" by (simp add: zdvd_imp_le [OF midvdl lpos])
from ineg have inz: "i \<noteq> 0" by simp
have "l div i\<le> -i div i"
by (simp add: zdiv_mono1_neg[OF milel ineg])
then have "l div i \<le> -1"
apply (simp add: zdiv_zminus1_eq_if[OF inz, where a="i"])
by (simp add: zdiv_self[OF inz])
then have ldivineg: "l div i < 0" by simp
then have mldivipos: "0 < - (l div i)" by simp
from dvd have "\<exists>i'. i*i' = l" by (auto simp add: dvd_def)
then obtain "i'" where ii'eql: "i*i' = l" by blast
have "(i * x + r \<le> 0) = (- (l div i) * (i * x + r) \<le> - (l div i) * 0)"
by (rule zmult_zle_mono_eq[OF mldivipos, where i="i*x + r" and j="0"])
also
have "(- (l div i) * (i * x + r) \<le> - (l div i) * 0) = (-((l div i) * i) * x \<le> (l div i)*r)"
by (simp add: mult_ac)
also have " (-((l div i) * i) * x \<le> (l div i)*r) = (- (l*x) \<le> (l div i)*r)"
using sym[OF ii'eql] inz
by (simp add: zmult_ac)
finally
show ?thesis
by simp
qed
(* FIXME : Move this theorem above, it simplifies the 2 theorems above : adjustcoeff_le_corr1,2 *)
lemma dvd_div_pos:
assumes bpos: "0 < (b::int)"
and anz: "a\<noteq>0"
and dvd: "a dvd b"
shows "(b div a)*a = b"
proof-
from anz have "0 < a \<or> a < 0" by arith
moreover
{
assume apos: "0 < a"
from bpos apos have aleb: "a\<le>b" by (simp add: zdvd_imp_le [OF dvd bpos])
have "a div a\<le> b div a"
by (simp add: zdiv_mono1[OF aleb apos])
then have bdivapos:"0 < b div a"
by (simp add: zdiv_self[OF anz])
from dvd have "\<exists>a'. a*a' = b" by (auto simp add: dvd_def)
then obtain "a'" where aa'eqb: "a*a' = b" by blast
then have ?thesis using anz sym[OF aa'eqb] by simp
}
moreover
{
assume aneg: "a < 0"
from dvd have midvdb: "-a dvd b" by simp
from aneg have mapos: "0 < -a" by simp
from bpos aneg have maleb: "-a\<le>b" by (simp add: zdvd_imp_le [OF midvdb bpos])
from aneg have anz: "a \<noteq> 0" by simp
have "b div a\<le> -a div a"
by (simp add: zdiv_mono1_neg[OF maleb aneg])
then have "b div a \<le> -1"
apply (simp add: zdiv_zminus1_eq_if[OF anz, where a="a"])
by (simp add: zdiv_self[OF anz])
then have bdivaneg: "b div a < 0" by simp
then have mbdivapos: "0 < - (b div a)" by simp
from dvd have "\<exists>a'. a*a' = b" by (auto simp add: dvd_def)
then obtain "a'" where aa'eqb: "a*a' = b" by blast
then have ?thesis using anz sym[OF aa'eqb] by (simp)
}
ultimately show ?thesis by blast
qed
lemma adjustcoeff_eq_corr:
assumes lpos: "(0::int) < l"
and inz: "i \<noteq> 0"
and dvd: "i dvd l"
shows "(i*x + r = 0) = (l*x + ((l div i)*r) = 0)"
proof-
have ldvdii: "(l div i)*i = l" by (rule dvd_div_pos[OF lpos inz dvd])
have ldivinz: "l div i \<noteq> 0" using inz ldvdii lpos by auto
have "(i*x + r = 0) = ((l div i)*(i*x + r) = (l div i)*0)"
using ldivinz by arith
also have "\<dots> = (((l div i)*i)*x + (l div i)*r = 0)"
by (simp add: zmult_ac)
finally show ?thesis using ldvdii by simp
qed
(* Correctness theorem for adjustcoeff *)
lemma adjustcoeff_corr:
assumes linp: "islinform p"
and alldvd: "divideallc (l,p)"
and lpos: "0 < l"
shows "qinterp (a#ats) p = qinterp ((a*l)#ats) (adjustcoeff(l, p))"
using linp alldvd
proof (induct p rule: islinform.induct,simp_all)
case (goal1 t c)
from prems have cz: "c=0" by simp
then have ?case
using prems
proof(induct t rule: islinintterm.induct)
case (2 i n i') show ?case using prems
proof-
from prems have "i\<noteq>0" by simp
then
have "(n=0 \<and> i < 0) \<or> (n=0 \<and> i > 0) \<or> n\<noteq>0" by arith
moreover
{
assume "n\<noteq>0" then have ?thesis
by (simp add: nth_pos2 adjustcoeff_lenpos)
}
moreover
{
assume nz: "n=0"
and ipos: "0 < i"
from prems nz have idvdl: "i dvd l" by simp
have "(i*a + i' \<le> 0) = (l*a+ ((l div i)*i') \<le> 0)"
by (rule adjustcoeff_le_corr[OF lpos ipos idvdl])
then
have ?thesis using prems by (simp add: mult_ac)
}
moreover
{
assume nz: "n=0"
and ineg: "i < 0"
from prems nz have idvdl: "i dvd l" by simp
have "(i*a+i' \<le> 0) = (-l*a + (-(l div i) * i') \<le> 0)"
by (rule adjustcoeff_le_corr2[OF lpos ineg idvdl])
then
have ?thesis using prems
by (simp add: zmult_ac)
}
ultimately show ?thesis by blast
qed
next
case (3 i n i' n' r) show ?case using prems
proof-
from prems
have lininrp: "islinintterm (Add (Mult (Cst i') (Var n')) r)"
by simp
then
have "islint (Add (Mult (Cst i') (Var n')) (r))"
by (simp add: islinintterm_eq_islint)
then have linr: "islintn(Suc n',r)"
by (simp add: islinintterm_subt[OF lininrp] islinintterm_eq_islint islint_def)
from lininrp have linr2: "islinintterm r"
by (simp add: islinintterm_subt[OF lininrp])
from prems have "n < n'" by simp
then have nppos: "0 < n'" by simp
from prems have "i\<noteq>0" by simp
then
have "(n=0 \<and> i < 0) \<or> (n=0 \<and> i > 0) \<or> n\<noteq>0" by arith
moreover
{
assume nnz: "n\<noteq>0"
from linr have ?thesis using nppos nnz intterm_novar0[OF lininrp] prems
apply (simp add: adjustcoeff_lenpos linterm_novar0[OF linr, where x="a" and y="a*l"])
by (simp add: nth_pos2)
}
moreover
{
assume nz: "n=0"
and ipos: "0 < i"
from prems nz have idvdl: "i dvd l" by simp
have "(i * a + (i' * (a # ats) ! n' + I_intterm (a # ats) r) \<le> 0) =
(l * a + l div i * (i' * (a # ats) ! n' + I_intterm (a # ats) r) \<le> 0)"
by (rule adjustcoeff_le_corr[OF lpos ipos idvdl])
then
have ?thesis using prems linr linr2
by (simp add: mult_ac nth_pos2 lin_mul_corr
linterm_novar0[OF linr, where x="a" and y="a*l"])
}
moreover
{
assume nz: "n=0"
and ineg: "i < 0"
from prems nz have idvdl: "i dvd l" by simp
have "(i * a + (i' * (a # ats) ! n' + I_intterm (a # ats) r) \<le> 0) =
(- l * a + - (l div i) * (i' * (a # ats) ! n' + I_intterm (a # ats) r) \<le> 0)"
by (rule adjustcoeff_le_corr2[OF lpos ineg idvdl, where x="a" and r="(i'* (a#ats) ! n' + I_intterm (a#ats) r )"])
then
have ?thesis using prems linr linr2
by (simp add: zmult_ac nth_pos2 lin_mul_corr
linterm_novar0[OF linr, where x="a" and y="a*l"] )
}
ultimately show ?thesis by blast
qed
qed simp_all
then show ?case by simp
next
case (goal2 t c)
from prems have cz: "c=0" by simp
then have ?case
using prems
proof(induct t rule: islinintterm.induct)
case (2 i n i') show ?case using prems
proof-
from prems have inz: "i\<noteq>0" by simp
then
have "n=0 \<or> n\<noteq>0" by arith
moreover
{
assume "n\<noteq>0" then have ?thesis
by (simp add: nth_pos2 adjustcoeff_eqnpos)
}
moreover
{
assume nz: "n=0"
from prems nz have idvdl: "i dvd l" by simp
have "(i*a + i' = 0) = (l*a+ ((l div i)*i') = 0)"
by (rule adjustcoeff_eq_corr[OF lpos inz idvdl])
then
have ?thesis using prems by (simp add: mult_ac)
}
ultimately show ?thesis by blast
qed
next
case (3 i n i' n' r) show ?case using prems
proof-
from prems
have lininrp: "islinintterm (Add (Mult (Cst i') (Var n')) r)"
by simp
then
have "islint (Add (Mult (Cst i') (Var n')) (r))"
by (simp add: islinintterm_eq_islint)
then have linr: "islintn(Suc n',r)"
by (simp add: islinintterm_subt[OF lininrp] islinintterm_eq_islint islint_def)
from lininrp have linr2: "islinintterm r"
by (simp add: islinintterm_subt[OF lininrp])
from prems have "n < n'" by simp
then have nppos: "0 < n'" by simp
from prems have "i\<noteq>0" by simp
then
have "n=0 \<or> n\<noteq>0" by arith
moreover
{
assume nnz: "n\<noteq>0"
from linr have ?thesis using nppos nnz intterm_novar0[OF lininrp] prems
apply (simp add: adjustcoeff_eqnpos linterm_novar0[OF linr, where x="a" and y="a*l"])
by (simp add: nth_pos2)
}
moreover
{
assume nz: "n=0"
from prems have inz: "i \<noteq> 0" by auto
from prems nz have idvdl: "i dvd l" by simp
have "(i * a + (i' * (a # ats) ! n' + I_intterm (a # ats) r) = 0) =
(l * a + l div i * (i' * (a # ats) ! n' + I_intterm (a # ats) r) = 0)"
by (rule adjustcoeff_eq_corr[OF lpos inz idvdl])
then
have ?thesis using prems linr linr2
by (simp add: mult_ac nth_pos2 lin_mul_corr
linterm_novar0[OF linr, where x="a" and y="a*l"])
}
ultimately show ?thesis by blast
qed
qed simp_all
then show ?case by simp
next
case (goal3 d t) show ?case
using prems
proof (induct t rule: islinintterm.induct)
case (2 i n i')
have "n=0 \<or> (\<exists>m. (n = Suc m))" by arith
moreover
{
assume "\<exists>m. n = Suc m"
then have ?case using prems by auto
}
moreover
{
assume nz: "n=0"
from prems have inz: "i\<noteq>0" by simp
from prems have idvdl: "i dvd l" by simp
have ldiviieql: "l div i * i = l" by (rule dvd_div_pos[OF lpos inz idvdl])
with lpos have ldivinz: "0 \<noteq> l div i" by auto
then have ?case using prems
apply simp
apply (simp add:
ac_dvd_eq[OF ldivinz, where m="d" and c="i" and n="a" and t="i'"]
ldiviieql)
by (simp add: zmult_commute)
}
ultimately show ?case by blast
next
case (3 i n i' n' r)
from prems
have lininrp: "islinintterm (Add (Mult (Cst i') (Var n')) r)"
by simp
then
have "islint (Add (Mult (Cst i') (Var n')) (r))"
by (simp add: islinintterm_eq_islint)
then have linr: "islintn(Suc n',r)"
by (simp add: islinintterm_subt[OF lininrp] islinintterm_eq_islint islint_def)
from lininrp have linr2: "islinintterm r"
by (simp add: islinintterm_subt[OF lininrp])
from prems have "n < n'" by simp
then have nppos: "0 < n'" by simp
from prems have inz: "i\<noteq>0" by simp
have "n=0 \<or> (\<exists>m. (n = Suc m))" by arith
moreover
{
assume "\<exists>m. n = Suc m"
then have npos: "0 < n" by arith
have ?case using nppos intterm_novar0[OF lininrp] prems
apply (auto simp add: linterm_novar0[OF linr, where x="a" and y="a*l"])
by (simp_all add: nth_pos2)
}
moreover
{
assume nz: "n=0"
from prems have idvdl: "i dvd l" by simp
have ldiviieql: "l div i * i = l" by (rule dvd_div_pos[OF lpos inz idvdl])
with lpos have ldivinz: "0 \<noteq> l div i" by auto
then have ?case using prems linr2 linr
apply (simp add: nth_pos2 lin_mul_corr linterm_novar0)
apply (simp add: ac_dvd_eq[OF ldivinz, where m="d" and c="i" and n="a" and t="(i' * ats ! (n' - Suc 0) + I_intterm (a # ats) r)"] ldiviieql)
by (simp add: zmult_ac linterm_novar0[OF linr, where x="a" and y="a*l"])
}
ultimately show ?case by blast
qed simp_all
next
case (goal4 d t) show ?case
using prems
proof (induct t rule: islinintterm.induct)
case (2 i n i')
have "n=0 \<or> (\<exists>m. (n = Suc m))" by arith
moreover
{
assume "\<exists>m. n = Suc m"
then have ?case using prems by auto
}
moreover
{
assume nz: "n=0"
from prems have inz: "i\<noteq>0" by simp
from prems have idvdl: "i dvd l" by simp
have ldiviieql: "l div i * i = l" by (rule dvd_div_pos[OF lpos inz idvdl])
with lpos have ldivinz: "0 \<noteq> l div i" by auto
then have ?case using prems
apply simp
apply (simp add:
ac_dvd_eq[OF ldivinz, where m="d" and c="i" and n="a" and t="i'"]
ldiviieql)
by (simp add: zmult_commute)
}
ultimately show ?case by blast
next
case (3 i n i' n' r)
from prems
have lininrp: "islinintterm (Add (Mult (Cst i') (Var n')) r)"
by simp
then
have "islint (Add (Mult (Cst i') (Var n')) (r))"
by (simp add: islinintterm_eq_islint)
then have linr: "islintn(Suc n',r)"
by (simp add: islinintterm_subt[OF lininrp] islinintterm_eq_islint islint_def)
from lininrp have linr2: "islinintterm r"
by (simp add: islinintterm_subt[OF lininrp])
from prems have "n < n'" by simp
then have nppos: "0 < n'" by simp
from prems have inz: "i\<noteq>0" by simp
have "n=0 \<or> (\<exists>m. (n = Suc m))" by arith
moreover
{
assume "\<exists>m. n = Suc m"
then have npos: "0 < n" by arith
have ?case using nppos intterm_novar0[OF lininrp] prems
apply (auto simp add: linterm_novar0[OF linr, where x="a" and y="a*l"])
by (simp_all add: nth_pos2)
}
moreover
{
assume nz: "n=0"
from prems have idvdl: "i dvd l" by simp
have ldiviieql: "l div i * i = l" by (rule dvd_div_pos[OF lpos inz idvdl])
with lpos have ldivinz: "0 \<noteq> l div i" by auto
then have ?case using prems linr2 linr
apply (simp add: nth_pos2 lin_mul_corr linterm_novar0)
apply (simp add: ac_dvd_eq[OF ldivinz, where m="d" and c="i" and n="a" and t="(i' * ats ! (n' - Suc 0) + I_intterm (a # ats) r)"] ldiviieql)
by (simp add: zmult_ac linterm_novar0[OF linr, where x="a" and y="a*l"])
}
ultimately show ?case by blast
qed simp_all
next
case (goal5 t c)
from prems have cz: "c=0" by simp
then have ?case
using prems
proof(induct t rule: islinintterm.induct)
case (2 i n i') show ?case using prems
proof-
from prems have inz: "i\<noteq>0" by simp
then
have "n=0 \<or> n\<noteq>0" by arith
moreover
{
assume "n\<noteq>0" then have ?thesis
using prems
by (cases n, simp_all)
}
moreover
{
assume nz: "n=0"
from prems nz have idvdl: "i dvd l" by simp
have "(i*a + i' = 0) = (l*a+ ((l div i)*i') = 0)"
by (rule adjustcoeff_eq_corr[OF lpos inz idvdl])
then
have ?thesis using prems by (simp add: mult_ac)
}
ultimately show ?thesis by blast
qed
next
case (3 i n i' n' r) show ?case using prems
proof-
from prems
have lininrp: "islinintterm (Add (Mult (Cst i') (Var n')) r)"
by simp
then
have "islint (Add (Mult (Cst i') (Var n')) (r))"
by (simp add: islinintterm_eq_islint)
then have linr: "islintn(Suc n',r)"
by (simp add: islinintterm_subt[OF lininrp] islinintterm_eq_islint islint_def)
from lininrp have linr2: "islinintterm r"
by (simp add: islinintterm_subt[OF lininrp])
from prems have "n < n'" by simp
then have nppos: "0 < n'" by simp
from prems have "i\<noteq>0" by simp
then
have "n=0 \<or> n\<noteq>0" by arith
moreover
{
assume nnz: "n\<noteq>0"
then have ?thesis using prems linr nppos nnz intterm_novar0[OF lininrp]
by (cases n, simp_all)
(simp add: nth_pos2 linterm_novar0[OF linr, where x="a" and y="a*l"])
}
moreover
{
assume nz: "n=0"
from prems have inz: "i \<noteq> 0" by auto
from prems nz have idvdl: "i dvd l" by simp
have "(i * a + (i' * (a # ats) ! n' + I_intterm (a # ats) r) = 0) =
(l * a + l div i * (i' * (a # ats) ! n' + I_intterm (a # ats) r) = 0)"
by (rule adjustcoeff_eq_corr[OF lpos inz idvdl])
then
have ?thesis using prems linr linr2
by (simp add: mult_ac nth_pos2 lin_mul_corr
linterm_novar0[OF linr, where x="a" and y="a*l"])
}
ultimately show ?thesis by blast
qed
qed simp_all
then show ?case by simp
qed
(* unitycoeff preserves semantics *)
lemma unitycoeff_corr:
assumes linp: "islinform p"
shows "qinterp ats (QEx p) = qinterp ats (QEx (unitycoeff p))"
proof-
have lpos: "0 < formlcm p" by (rule formlcm_pos[OF linp])
have dvd : "divideallc (formlcm p, p)" by (rule formlcm_divideallc[OF linp])
show ?thesis using prems lpos dvd
proof (simp add: unitycoeff_def Let_def,case_tac "formlcm p = 1",
simp_all add: adjustcoeff_corr)
show "(\<exists>x. qinterp (x * formlcm p # ats) (adjustcoeff (formlcm p, p))) =
(\<exists>x. formlcm p dvd x \<and>
qinterp (x # ats) (adjustcoeff (formlcm p, p)))"
(is "(\<exists>x. ?P(x* (formlcm p))) = (\<exists>x. formlcm p dvd x \<and> ?P x)")
proof-
have "(\<exists>x. ?P(x* (formlcm p))) = (\<exists>x. ?P((formlcm p)*x))"
by (simp add: mult_commute)
also have "(\<exists>x. ?P((formlcm p)*x)) = (\<exists>x. (formlcm p dvd x) \<and> ?P x)"
by (simp add: unity_coeff_ex[where P="?P"])
finally show ?thesis by simp
qed
qed
qed
(* the resul of adjustcoeff is unified for all l with divideallc (l,p) *)
lemma adjustcoeff_unified:
assumes linp: "islinform p"
and dvdc: "divideallc(l,p)"
and lpos: "l > 0"
shows "isunified (adjustcoeff(l, p))"
using linp dvdc lpos
proof(induct l p rule: adjustcoeff.induct,simp_all add: lin_mul_lintn islinintterm_eq_islint islint_def)
case (goal1 l d c r)
from prems have "c >0 \<or> c < 0" by auto
moreover {
assume cpos: "c > 0 "
from prems have lp: "l > 0" by simp
from prems have cdvdl: "c dvd l" by simp
have clel: "c \<le> l" by (rule zdvd_imp_le[OF cdvdl lp])
have "c div c \<le> l div c" by (rule zdiv_mono1[OF clel cpos])
then have ?case using cpos by (simp add: zdiv_self)
}
moreover {
assume cneg: "c < 0"
have mcpos: "-c > 0" by simp
then have mcnz: "-c \<noteq> 0" by simp
from prems have mcdvdl: "-c dvd l"
by simp
then have l1:"l mod -c = 0" by (simp add: zdvd_iff_zmod_eq_0)
from prems have lp: "l >0" by simp
have mclel: "-c \<le> l" by (rule zdvd_imp_le[OF mcdvdl lp])
have "l div c = (-l div -c)" by simp
also have "\<dots> = - (l div -c)" using l1
by (simp only: zdiv_zminus1_eq_if[OF mcnz, where a="l"]) simp
finally have diveq: "l div c = - (l div -c)" by simp
have "-c div -c \<le> l div -c" by (rule zdiv_mono1[OF mclel mcpos])
then have "0 < l div -c" using cneg
by (simp add: zdiv_self)
then have ?case using diveq by simp
}
ultimately show ?case by blast
next
case (goal2 l p) from prems have "c >0 \<or> c < 0" by auto
moreover {
assume cpos: "c > 0 "
from prems have lp: "l > 0" by simp
from prems have cdvdl: "c dvd l" by simp
have clel: "c \<le> l" by (rule zdvd_imp_le[OF cdvdl lp])
have "c div c \<le> l div c" by (rule zdiv_mono1[OF clel cpos])
then have ?case using cpos by (simp add: zdiv_self)
}
moreover {
assume cneg: "c < 0"
have mcpos: "-c > 0" by simp
then have mcnz: "-c \<noteq> 0" by simp
from prems have mcdvdl: "-c dvd l"
by simp
then have l1:"l mod -c = 0" by (simp add: zdvd_iff_zmod_eq_0)
from prems have lp: "l >0" by simp
have mclel: "-c \<le> l" by (rule zdvd_imp_le[OF mcdvdl lp])
have "l div c = (-l div -c)" by simp
also have "\<dots> = - (l div -c)" using l1
by (simp only: zdiv_zminus1_eq_if[OF mcnz, where a="l"]) simp
finally have diveq: "l div c = - (l div -c)" by simp
have "-c div -c \<le> l div -c" by (rule zdiv_mono1[OF mclel mcpos])
then have "0 < l div -c" using cneg
by (simp add: zdiv_self)
then have ?case using diveq by simp
}
ultimately show ?case by blast
qed
lemma adjustcoeff_lcm_unified:
assumes linp: "islinform p"
shows "isunified (adjustcoeff(formlcm p, p))"
using linp adjustcoeff_unified formlcm_pos formlcm_divideallc
by simp
(* the result of unitycoeff is unified *)
lemma unitycoeff_unified:
assumes linp: "islinform p"
shows "isunified (unitycoeff p)"
using linp formlcm_pos[OF linp]
proof (auto simp add: unitycoeff_def Let_def adjustcoeff_lcm_unified)
assume f1: "formlcm p = 1"
have "isunified (adjustcoeff(formlcm p, p))"
by (rule adjustcoeff_lcm_unified[OF linp])
with f1
show "isunified (adjustcoeff(1,p))" by simp
qed
lemma unified_isnnf:
assumes unifp: "isunified p"
shows "isnnf p"
using unified_islinform[OF unifp] linform_isnnf
by simp
lemma unified_isqfree: "isunified p\<Longrightarrow> isqfree p"
using unified_islinform linform_isqfree
by auto
(* Plus/Minus infinity , B and A set definitions *)
consts minusinf :: "QF \<Rightarrow> QF"
plusinf :: "QF \<Rightarrow> QF"
aset :: "QF \<Rightarrow> intterm list"
bset :: "QF \<Rightarrow> intterm list"
recdef minusinf "measure size"
"minusinf (Le (Add (Mult (Cst c) (Var 0)) r) z) =
(if c < 0 then F else T)"
"minusinf (Eq (Add (Mult (Cst c) (Var 0)) r) z) = F"
"minusinf (NOT(Eq (Add (Mult (Cst c) (Var 0)) r) z)) = T"
"minusinf (And p q) = And (minusinf p) (minusinf q)"
"minusinf (Or p q) = Or (minusinf p) (minusinf q)"
"minusinf p = p"
recdef plusinf "measure size"
"plusinf (Le (Add (Mult (Cst c) (Var 0)) r) z) =
(if c < 0 then T else F)"
"plusinf (Eq (Add (Mult (Cst c) (Var 0)) r) z) = F"
"plusinf (NOT (Eq (Add (Mult (Cst c) (Var 0)) r) z)) = T"
"plusinf (And p q) = And (plusinf p) (plusinf q)"
"plusinf (Or p q) = Or (plusinf p) (plusinf q)"
"plusinf p = p"
recdef bset "measure size"
"bset (Le (Add (Mult (Cst c) (Var 0)) r) z) =
(if c < 0 then [lin_add(r,(Cst -1)), r]
else [lin_add(lin_neg r,(Cst -1))])"
"bset (Eq (Add (Mult (Cst c) (Var 0)) r) z) =
(if c < 0 then [lin_add(r,(Cst -1))]
else [lin_add(lin_neg r,(Cst -1))])"
"bset (NOT(Eq (Add (Mult (Cst c) (Var 0)) r) z)) =
(if c < 0 then [r]
else [lin_neg r])"
"bset (And p q) = (bset p) @ (bset q)"
"bset (Or p q) = (bset p) @ (bset q)"
"bset p = []"
recdef aset "measure size"
"aset (Le (Add (Mult (Cst c) (Var 0)) r) z) =
(if c < 0 then [lin_add (r, Cst 1)]
else [lin_add (lin_neg r, Cst 1), lin_neg r])"
"aset (Eq (Add (Mult (Cst c) (Var 0)) r) z) =
(if c < 0 then [lin_add(r,(Cst 1))]
else [lin_add(lin_neg r,(Cst 1))])"
"aset (NOT(Eq (Add (Mult (Cst c) (Var 0)) r) z)) =
(if c < 0 then [r]
else [lin_neg r])"
"aset (And p q) = (aset p) @ (aset q)"
"aset (Or p q) = (aset p) @ (aset q)"
"aset p = []"
(* divlcm computes \<delta> = lcm d , where d | x +t occurs in p *)
consts divlcm :: "QF \<Rightarrow> int"
recdef divlcm "measure size"
"divlcm (Divides (Cst d) (Add (Mult (Cst c) (Var 0)) r)) = (abs d)"
"divlcm (NOT p) = divlcm p"
"divlcm (And p q)= ilcm (divlcm p) (divlcm q)"
"divlcm (Or p q) = ilcm (divlcm p) (divlcm q)"
"divlcm p = 1"
(* the preoperty of \<delta> *)
consts alldivide :: "int \<times> QF \<Rightarrow> bool"
recdef alldivide "measure (%(d,p). size p)"
"alldivide (d,(Divides (Cst d') (Add (Mult (Cst c) (Var 0)) r))) =
(d' dvd d)"
"alldivide (d,(NOT p)) = alldivide (d,p)"
"alldivide (d,(And p q)) = (alldivide (d,p) \<and> alldivide (d,q))"
"alldivide (d,(Or p q)) = ((alldivide (d,p)) \<and> (alldivide (d,q)))"
"alldivide (d,p) = True"
(* alldivide is monotone *)
lemma alldivide_mono: "\<And> d'. \<lbrakk> alldivide (d,p) ; d dvd d'\<rbrakk> \<Longrightarrow> alldivide (d',p)"
proof(induct d p rule: alldivide.induct, simp_all add: ilcm_dvd1 ilcm_dvd2)
fix "d1" "d2" "d3"
assume th1:"d2 dvd (d1::int)"
and th2: "d1 dvd d3"
show "d2 dvd d3" by (rule zdvd_trans[OF th1 th2])
qed
(* Some simple lemmas *)
lemma zdvd_eq_zdvd_abs: " (d::int) dvd d' = (d dvd (abs d')) "
proof-
have "d' < 0 \<or> d' \<ge> 0" by arith
moreover
{
assume dn': "d' < 0"
then have "abs d' = - d'" by simp
then
have ?thesis by (simp)
}
moreover
{
assume dp': "d' \<ge> 0"
then have "abs d' = d'" by simp
then have ?thesis by simp
}
ultimately show ?thesis by blast
qed
lemma zdvd_refl_abs: "(d::int) dvd (abs d)"
proof-
have "d dvd d" by simp
then show ?thesis by (simp add: iffD1 [OF zdvd_eq_zdvd_abs [where d = "d" and d'="d"]])
qed
(* \<delta> > 0*)
lemma divlcm_pos:
assumes
linp: "islinform p"
shows "0 < divlcm p"
using linp
proof (induct p rule: divlcm.induct,simp_all add: ilcm_pos)
case (goal1 f) show ?case
using prems
by (cases f, auto) (case_tac "intterm1", auto)
qed
lemma nz_le: "(x::int) > 0 \<Longrightarrow> x \<noteq> 0" by auto
(* divlcm is correct *)
lemma divlcm_corr:
assumes
linp: "islinform p"
shows "alldivide (divlcm p,p)"
using linp divlcm_pos
proof (induct p rule: divlcm.induct,simp_all add: zdvd_refl_abs,clarsimp simp add: Nat.gr0_conv_Suc)
case (goal1 f)
have "islinform f" using prems
by (cases f, auto) (case_tac "intterm2", auto,case_tac "intterm1", auto)
then have "alldivide (divlcm f, f)" using prems by simp
moreover have "divlcm (NOT f) = divlcm f" by simp
moreover have "alldivide (x,f) = alldivide (x,NOT f)" by simp
ultimately show ?case by simp
next
case (goal2 f g)
have dvd1: "(divlcm f) dvd (ilcm (divlcm f) (divlcm g))"
using prems by(simp add: ilcm_dvd1 nz_le)
have dvd2: "(divlcm g) dvd (ilcm (divlcm f) (divlcm g))"
using prems by (simp add: ilcm_dvd2 nz_le)
from dvd1 prems
have "alldivide (ilcm (divlcm f) (divlcm g), f)"
by (simp add: alldivide_mono[where d= "divlcm f" and p="f" and d' ="ilcm (divlcm f) (divlcm g)"])
moreover from dvd2 prems
have "alldivide (ilcm (divlcm f) (divlcm g), g)"
by (simp add: alldivide_mono[where d= "divlcm g" and p="g" and d' ="ilcm (divlcm f) (divlcm g)"])
ultimately show ?case by simp
next
case (goal3 f g)
have dvd1: "(divlcm f) dvd (ilcm (divlcm f) (divlcm g))"
using prems by (simp add: nz_le ilcm_dvd1)
have dvd2: "(divlcm g) dvd (ilcm (divlcm f) (divlcm g))"
using prems by (simp add: nz_le ilcm_dvd2)
from dvd1 prems
have "alldivide (ilcm (divlcm f) (divlcm g), f)"
by (simp add: alldivide_mono[where d= "divlcm f" and p="f" and d' ="ilcm (divlcm f) (divlcm g)"])
moreover from dvd2 prems
have "alldivide (ilcm (divlcm f) (divlcm g), g)"
by (simp add: alldivide_mono[where d= "divlcm g" and p="g" and d' ="ilcm (divlcm f) (divlcm g)"])
ultimately show ?case by simp
qed
(* Properties of minusinf and plusinf*)
(* minusinf p and p are the same for minusinfity \<dots> *)
lemma minusinf_eq:
assumes unifp: "isunified p"
shows "\<exists> z. \<forall> x. x < z \<longrightarrow> (qinterp (x#ats) p = qinterp (x#ats) (minusinf p))"
using unifp unified_islinform[OF unifp]
proof (induct p rule: minusinf.induct)
case (1 c r z)
have "c <0 \<or> 0 \<le> c" by arith
moreover
{
assume cneg: " c < 0"
from prems have z0: "z= Cst 0"
by (cases z,auto)
with prems have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)"
by simp
from prems z0 have ?case
proof-
show ?thesis
using prems z0
apply auto
apply (rule exI[where x="I_intterm (a # ats) r"])
apply (rule allI)
proof-
fix x
show "x < I_intterm (a # ats) r \<longrightarrow> \<not> - x + I_intterm (x # ats) r \<le> 0"
by (simp add: intterm_novar0[OF lincnr, where x="a" and y="x"])
qed
qed
}
moreover
{
assume cpos: "0 \<le> c"
from prems have z0: "z= Cst 0"
by (cases z) auto
with prems have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)"
by simp
from prems z0 have ?case
proof-
show ?thesis
using prems z0
apply auto
apply (rule exI[where x="-(I_intterm (a # ats) r)"])
apply (rule allI)
proof-
fix x
show "x < - I_intterm (a # ats) r \<longrightarrow> x + I_intterm (x # ats) r \<le> 0"
by (simp add: intterm_novar0[OF lincnr, where x="a" and y="x"])
qed
qed
}
ultimately show ?case by blast
next
case (2 c r z)
from prems have z0: "z= Cst 0"
by (cases z,auto)
with prems have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)"
by simp
have "c <0 \<or> 0 \<le> c" by arith
moreover
{
assume cneg: " c < 0"
from prems z0 have ?case
proof-
show ?thesis
using prems z0
apply auto
apply (rule exI[where x="I_intterm (a # ats) r"])
apply (rule allI)
proof-
fix x
show "x < I_intterm (a # ats) r \<longrightarrow> \<not> - x + I_intterm (x # ats) r = 0"
by (simp add: intterm_novar0[OF lincnr, where x="a" and y="x"])
qed
qed
}
moreover
{
assume cpos: "0 \<le> c"
from prems z0 have ?case
proof-
show ?thesis
using prems z0
apply auto
apply (rule exI[where x="-(I_intterm (a # ats) r)"])
apply (rule allI)
proof-
fix x
show "x < - I_intterm (a # ats) r \<longrightarrow> x + I_intterm (x # ats) r \<noteq> 0"
by (simp add: intterm_novar0[OF lincnr, where x="a" and y="x"])
qed
qed
}
ultimately show ?case by blast
next
case (3 c r z)
from prems have z0: "z= Cst 0"
by (cases z,auto)
with prems have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)"
by simp
have "c <0 \<or> 0 \<le> c" by arith
moreover
{
assume cneg: " c < 0"
from prems z0 have ?case
proof-
show ?thesis
using prems z0
apply auto
apply (rule exI[where x="I_intterm (a # ats) r"])
apply (rule allI)
proof-
fix x
show "x < I_intterm (a # ats) r \<longrightarrow> \<not> - x + I_intterm (x # ats) r = 0"
by (simp add: intterm_novar0[OF lincnr, where x="a" and y="x"])
qed
qed
}
moreover
{
assume cpos: "0 \<le> c"
from prems z0 have ?case
proof-
show ?thesis
using prems z0
apply auto
apply (rule exI[where x="-(I_intterm (a # ats) r)"])
apply (rule allI)
proof-
fix x
show "x < - I_intterm (a # ats) r \<longrightarrow> x + I_intterm (x # ats) r \<noteq> 0"
by (simp add: intterm_novar0[OF lincnr, where x="a" and y="x"])
qed
qed
}
ultimately show ?case by blast
next
case (4 f g)
from prems obtain "zf" where
zf:"\<forall>x<zf. qinterp (x # ats) f = qinterp (x # ats) (minusinf f)" by auto
from prems obtain "zg" where
zg:"\<forall>x<zg. qinterp (x # ats) g = qinterp (x # ats) (minusinf g)" by auto
from zf zg show ?case
apply auto
apply (rule exI[where x="min zf zg"])
by simp
next case (5 f g)
from prems obtain "zf" where
zf:"\<forall>x<zf. qinterp (x # ats) f = qinterp (x # ats) (minusinf f)" by auto
from prems obtain "zg" where
zg:"\<forall>x<zg. qinterp (x # ats) g = qinterp (x # ats) (minusinf g)" by auto
from zf zg show ?case
apply auto
apply (rule exI[where x="min zf zg"])
by simp
qed simp_all
(* miusinf p behaves periodically*)
lemma minusinf_repeats:
assumes alldvd: "alldivide (d,p)"
and unity: "isunified p"
shows "qinterp (x#ats) (minusinf p) = qinterp ((x + c*d)#ats) (minusinf p)"
using alldvd unity unified_islinform[OF unity]
proof(induct p rule: islinform.induct, simp_all)
case (goal1 t a)
show ?case
using prems
apply (cases t, simp_all add: nth_pos2)
apply (case_tac "intterm1", simp_all)
apply (case_tac "intterm1a",simp_all)
by (case_tac "intterm2a",simp_all)
(case_tac "nat",simp_all add: nth_pos2 intterm_novar0[where x="x" and y="x+c*d"])
next
case (goal2 t a)
show ?case
using prems
apply (cases t, simp_all add: nth_pos2)
apply (case_tac "intterm1", simp_all)
apply (case_tac "intterm1a",simp_all)
by (case_tac "intterm2a",simp_all)
(case_tac "nat",simp_all add: nth_pos2 intterm_novar0[where x="x" and y="x+c*d"])
next
case (goal3 a t)
show ?case using prems
proof(induct t rule: islinintterm.induct, simp_all add: nth_pos2)
case (goal1 i n i')
show ?case
using prems
proof(cases n, simp_all, case_tac "i=1", simp,
simp add: dvd_period[where a="a" and d="d" and x="x" and c="c"])
case goal1
from prems have "(abs i = 1) \<and> i \<noteq> 1" by auto
then have im1: "i=-1" by arith
then have "(a dvd i*x + i') = (a dvd x + (-i'))"
by (simp add: uminus_dvd_conv'[where d="a" and t="-x +i'"])
moreover
from im1 have "(a dvd i*x + (i*(c * d)) + i') = (a dvd (x + c*d - i'))"
apply simp
apply (simp add: uminus_dvd_conv'[where d="a" and t="-x - c * d + i'"])
by (simp add: zadd_ac)
ultimately
have eq1:"((a dvd i*x + i') = (a dvd i*x + (i*(c * d)) + i')) =
((a dvd x + (-i')) = (a dvd (x + c*d - i')))" by simp
moreover
have dvd2: "(a dvd x + (-i')) = (a dvd x + c * d + (-i'))"
by (rule dvd_period[where a="a" and d="d" and x="x" and c="c"], assumption)
ultimately show ?case by simp
qed
next
case (goal2 i n i' n' r)
have "n = 0 \<or> 0 < n" by arith
moreover
{
assume npos: "0 < n"
from prems have "n < n'" by simp then have "0 < n'" by simp
moreover from prems
have linr: "islinintterm (Add (Mult (Cst i') (Var n')) r)" by simp
ultimately have ?case
using prems npos
by (simp add: nth_pos2 intterm_novar0[OF linr,where x="x" and y="x + c*d"])
}
moreover
{
assume n0: "n=0"
from prems have lin2: "islinintterm (Add (Mult (Cst i') (Var n')) r)" by simp
from prems have "n < n'" by simp then have npos': "0 < n'" by simp
with prems have ?case
proof(simp add: intterm_novar0[OF lin2, where x="x" and y="x+c*d"]
nth_pos2 dvd_period,case_tac "i=1",
simp add: dvd_period[where a="a" and d="d" and x="x" and c="c"], simp)
case goal1
from prems have "abs i = 1 \<and> i\<noteq>1" by auto
then have mi: "i = -1" by arith
have "(a dvd -x + (i' * ats ! (n' - Suc 0) + I_intterm ((x + c * d) # ats) r)) =
(a dvd x + (-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r))"
by (simp add:
uminus_dvd_conv'[where d="a" and
t="-x + (i' * ats ! (n' - Suc 0) + I_intterm ((x + c * d) # ats) r)"])
also
have "(a dvd x + (-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)) =
(a dvd x +c*d + (-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r))"
by (rule dvd_period[where a="a" and d="d" and x="x" and c="c"], assumption)
also
have "(a dvd x +c*d +
(-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)) =
(a dvd -(x +c*d +
(-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)))"
by (rule uminus_dvd_conv'[where d="a" and
t="x +c*d + (-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)"])
also
have "(a dvd -(x +c*d +
(-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)))
= (a dvd
- x - c * d + (i' * ats ! (n' - Suc 0) + I_intterm ((x + c * d) # ats) r))"
by (auto,simp_all add: zadd_ac)
finally show ?case using mi by auto
qed
}
ultimately show ?case by blast
qed
next
case (goal4 a t)
show ?case using prems
proof(induct t rule: islinintterm.induct, simp_all,case_tac "n=0",
simp_all add: nth_pos2)
case (goal1 i n i')
show ?case
using prems
proof(case_tac "i=1", simp,
simp add: dvd_period[where a="a" and d="d" and x="x" and c="c"])
case goal1
from prems have "abs i = 1 \<and> i\<noteq>1" by auto
then have im1: "i=-1" by arith
then have "(a dvd i*x + i') = (a dvd x + (-i'))"
by (simp add: uminus_dvd_conv'[where d="a" and t="-x +i'"])
moreover
from im1 have "(a dvd i*x + (i*(c * d)) + i') = (a dvd (x + c*d - i'))"
apply simp
apply (simp add: uminus_dvd_conv'[where d="a" and t="-x - c * d + i'"])
by (simp add: zadd_ac)
ultimately
have eq1:"((a dvd i*x + i') = (a dvd i*x + (i*(c * d)) + i')) =
((a dvd x + (-i')) = (a dvd (x + c*d - i')))" by simp
moreover
have dvd2: "(a dvd x + (-i')) = (a dvd x + c * d + (-i'))"
by (rule dvd_period[where a="a" and d="d" and x="x" and c="c"], assumption)
ultimately show ?thesis by simp
qed
next
case (goal2 i n i' n' r)
have "n = 0 \<or> 0 < n" by arith
moreover
{
assume npos: "0 < n"
from prems have "n < n'" by simp then have "0 < n'" by simp
moreover from prems
have linr: "islinintterm (Add (Mult (Cst i') (Var n')) r)" by simp
ultimately have ?case
using prems npos
by (simp add: nth_pos2 intterm_novar0[OF linr,where x="x" and y="x + c*d"])
}
moreover
{
assume n0: "n=0"
from prems have lin2: "islinintterm (Add (Mult (Cst i') (Var n')) r)" by simp
from prems have "n < n'" by simp then have npos': "0 < n'" by simp
with prems have ?case
proof(simp add: intterm_novar0[OF lin2, where x="x" and y="x+c*d"]
nth_pos2 dvd_period,case_tac "i=1",
simp add: dvd_period[where a="a" and d="d" and x="x" and c="c"], simp)
case goal1
from prems have "abs i = 1 \<and> i\<noteq>1" by auto
then have mi: "i = -1" by arith
have "(a dvd -x + (i' * ats ! (n' - Suc 0) + I_intterm ((x + c * d) # ats) r)) =
(a dvd x + (-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r))"
by (simp add:
uminus_dvd_conv'[where d="a" and
t="-x + (i' * ats ! (n' - Suc 0) + I_intterm ((x + c * d) # ats) r)"])
also
have "(a dvd x + (-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)) =
(a dvd x +c*d + (-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r))"
by (rule dvd_period[where a="a" and d="d" and x="x" and c="c"], assumption)
also
have "(a dvd x +c*d +
(-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)) =
(a dvd -(x +c*d +
(-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)))"
by (rule uminus_dvd_conv'[where d="a" and
t="x +c*d + (-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)"])
also
have "(a dvd -(x +c*d +
(-i' * ats ! (n' - Suc 0) - I_intterm ((x + c * d) # ats) r)))
= (a dvd
- x - c * d + (i' * ats ! (n' - Suc 0) + I_intterm ((x + c * d) # ats) r))"
by (auto,simp_all add: zadd_ac)
finally show ?case using mi by auto
qed
}
ultimately show ?case by blast
qed
next
case (goal5 t a)
show ?case
using prems
apply (cases t, simp_all add: nth_pos2)
apply (case_tac "intterm1", simp_all)
apply (case_tac "intterm1a",simp_all)
by (case_tac "intterm2a",simp_all)
(case_tac "nat",simp_all add: nth_pos2 intterm_novar0[where x="x" and y="x+c*d"])
qed
lemma minusinf_repeats2:
assumes alldvd: "alldivide (d,p)"
and unity: "isunified p"
shows "\<forall> x k. (qinterp (x#ats) (minusinf p) = qinterp ((x - k*d)#ats) (minusinf p))"
(is "\<forall> x k. ?P x = ?P (x - k*d)")
proof(rule allI, rule allI)
fix x k
show "?P x = ?P (x - k*d)"
proof-
have "?P x = ?P (x + (-k)*d)" by (rule minusinf_repeats[OF alldvd unity])
then have "?P x = ?P (x - (k*d))" by simp
then show ?thesis by blast
qed
qed
(* existence for minusinf p is existence for p *)
lemma minusinf_lemma:
assumes unifp: "isunified p"
and exminf: "\<exists> j \<in> {1 ..d}. qinterp (j#ats) (minusinf p)" (is "\<exists> j \<in> {1 .. d}. ?P1 j")
shows "\<exists> x. qinterp (x#ats) p" (is "\<exists> x. ?P x")
proof-
from exminf obtain "j" where P1j: "?P1 j" by blast
have ePeqP1: "\<exists>z. \<forall> x. x < z \<longrightarrow> (?P x = ?P1 x)"
by (rule minusinf_eq[OF unifp])
then obtain "z" where P1eqP : "\<forall> x. x < z \<longrightarrow> (?P x = ?P1 x)" by blast
let ?d = "divlcm p"
have alldvd: "alldivide (?d,p)" using unified_islinform[OF unifp] divlcm_corr
by auto
have dpos: "0 < ?d" using unified_islinform[OF unifp] divlcm_pos
by simp
have P1eqP1 : "\<forall> x k. ?P1 x = ?P1 (x - k*(?d))"
by (rule minusinf_repeats2[OF alldvd unifp])
let ?w = "j - (abs (j-z) +1)* ?d"
show "\<exists> x. ?P x"
proof
have w: "?w < z"
by (rule decr_lemma[OF dpos])
have "?P1 j = ?P1 ?w" using P1eqP1 by blast
also have "\<dots> = ?P ?w" using w P1eqP by blast
finally show "?P ?w" using P1j by blast
qed
qed
(* limited search for the withness for minusinf p, due to peridicity *)
lemma minusinf_disj:
assumes unifp: "isunified p"
shows "(\<exists> x. qinterp (x#ats) (minusinf p)) =
(\<exists> j \<in> { 1.. divlcm p}. qinterp (j#ats) (minusinf p))"
(is "(\<exists> x. ?P x) = (\<exists> j \<in> { 1.. ?d}. ?P j)")
proof
have linp: "islinform p" by (rule unified_islinform[OF unifp])
have dpos: "0 < ?d" by (rule divlcm_pos[OF linp])
have alldvd: "alldivide(?d,p)" by (rule divlcm_corr[OF linp])
{
assume "\<exists> j\<in> {1 .. ?d}. ?P j"
then show "\<exists> x. ?P x" using dpos by auto
next
assume "\<exists> x. ?P x"
then obtain "x" where P: "?P x" by blast
have modd: "\<forall>x k. ?P x = ?P (x - k*?d)"
by (rule minusinf_repeats2[OF alldvd unifp])
have "x mod ?d = x - (x div ?d)*?d"
by(simp add:zmod_zdiv_equality mult_ac eq_diff_eq)
hence Pmod: "?P x = ?P (x mod ?d)" using modd by simp
show "\<exists> j\<in> {1 .. ?d}. ?P j"
proof (cases)
assume "x mod ?d = 0"
hence "?P 0" using P Pmod by simp
moreover have "?P 0 = ?P (0 - (-1)*?d)" using modd by blast
ultimately have "?P ?d" by simp
moreover have "?d \<in> {1 .. ?d}" using dpos
by (simp add:atLeastAtMost_iff)
ultimately show "\<exists> j\<in> {1 .. ?d}. ?P j" ..
next
assume not0: "x mod ?d \<noteq> 0"
have "?P(x mod ?d)" using dpos P Pmod by(simp add:pos_mod_sign pos_mod_bound)
moreover have "x mod ?d : {1 .. ?d}"
proof -
have "0 \<le> x mod ?d" by(rule pos_mod_sign[OF dpos])
moreover have "x mod ?d < ?d" by(rule pos_mod_bound[OF dpos])
ultimately show ?thesis using not0 by(simp add:atLeastAtMost_iff)
qed
ultimately show "\<exists> j\<in> {1 .. ?d}. ?P j" ..
qed
}
qed
lemma minusinf_qfree:
assumes linp : "islinform p"
shows "isqfree (minusinf p)"
using linp
by (induct p rule: minusinf.induct) auto
(* Properties of bset and a set *)
(* The elements of a bset are linear *)
lemma bset_lin:
assumes unifp: "isunified p"
shows "\<forall> b \<in> set (bset p). islinintterm b"
using unifp unified_islinform[OF unifp]
proof (induct p rule: bset.induct, auto)
case (goal1 c r z)
from prems have "z = Cst 0" by (cases z, simp_all)
then have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have "islinintterm (Cst -1)" by simp
then show ?case using linr lin_add_lin by simp
next
case (goal2 c r z)
from prems have "z = Cst 0" by (cases z, simp_all)
then have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
show ?case by (rule linr)
next
case (goal3 c r z)
from prems have "z = Cst 0" by (cases z, simp_all)
then have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have "islinintterm (Cst -1)" by simp
then show ?case using linr lin_add_lin lin_neg_lin by simp
next
case (goal4 c r z)
from prems have "z = Cst 0" by (cases z, simp_all)
then have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have "islinintterm (Cst -1)" by simp
then show ?case using linr lin_add_lin lin_neg_lin by simp
next
case (goal5 c r z)
from prems have "z = Cst 0" by (cases z, simp_all)
then have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have "islinintterm (Cst -1)" by simp
then show ?case using linr lin_add_lin lin_neg_lin by simp
next
case (goal6 c r z)
from prems have "z = Cst 0" by (cases z, simp_all)
then have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have "islinintterm (Cst -1)" by simp
then show ?case using linr lin_add_lin lin_neg_lin by simp
next
case (goal7 c r z)
from prems have "z = Cst 0" by (cases z, simp_all)
then have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" using prems by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have "islinintterm (Cst -1)" by simp
then show ?case using linr lin_add_lin lin_neg_lin by simp
qed
(* The third lemma in Norrisch's Paper *)
lemma bset_disj_repeat:
assumes unifp: "isunified p"
and alldvd: "alldivide (d,p)"
and dpos: "0 < d"
and nob: "(qinterp (x#ats) q) \<and> \<not>(\<exists>j\<in> {1 .. d}. \<exists> b \<in> set (bset p). (qinterp (((I_intterm (a#ats) b) + j)#ats) q)) \<and>(qinterp (x#ats) p)"
(is "?Q x \<and> \<not>(\<exists> j\<in> {1.. d}. \<exists> b\<in> ?B. ?Q (?I a b + j)) \<and> ?P x")
shows "?P (x -d)"
using unifp nob alldvd unified_islinform[OF unifp]
proof (induct p rule: islinform.induct,auto)
case (goal1 t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have "n=0 \<or> n>0" by arith
moreover {assume "n>0" then have ?case
using prems
by (simp add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="x-d"]) }
moreover
{assume nz: "n = 0"
from prems have "abs i = 1" by auto
then have "i = -1 \<or> i =1" by arith
moreover
{
assume i1: "i=1"
have ?case using dpos prems
by (auto simp add: intterm_novar0[OF lininr, where x="x" and y="x - d"])
}
moreover
{
assume im1: "i = -1"
have ?case
using prems
proof(auto simp add: intterm_novar0[OF lininr, where x="x - d" and y="x"], cases)
assume "- x + d + ?I x r \<le> 0"
then show "- x + d + ?I x r \<le> 0" .
next
assume np: "\<not> - x + d + ?I x r \<le> 0"
then have ltd:"x - ?I x r \<le> d - 1" by simp
from prems have "-x + ?I x r \<le> 0" by simp
then have ge0: "x - ?I x r \<ge> 0"
by simp
from ltd ge0 have "x - ?I x r = 0 \<or> (1 \<le> x - ?I x r \<and> x - ?I x r \<le> d - 1) " by arith
moreover
{
assume "x - ?I x r = 0"
then have xeqr: "x = ?I x r" by simp
from prems have "?Q x" by simp
with xeqr have qr:"?Q (?I x r)" by simp
from prems have lininr: "islinintterm (Add (Mult (Cst i) (Var 0)) r)" by simp
have "islinintterm r" by (rule islinintterm_subt[OF lininr])
from prems
have "\<forall>j\<in>{1..d}. \<not> ?Q (?I a r + -1 + j)"
using linr by (auto simp add: lin_add_corr)
moreover from dpos have "1 \<in> {1..d}" by simp
ultimately have " \<not> ?Q (?I a r + -1 + 1)" by blast
with dpos linr have "\<not> ?Q (?I x r)"
by (simp add: intterm_novar0[OF lininr, where x="x" and y="a"] lin_add_corr)
with qr have "- x + d + ?I x r \<le> 0" by simp
}
moreover
{
assume gt0: "1 \<le> x - ?I x r \<and> x - ?I x r \<le> d - 1"
then have "\<exists> j\<in> {1 .. d - 1}. x - ?I x r = j" by simp
then have "\<exists> j\<in> {1 .. d}. x - ?I x r = j" by auto
then obtain "j" where con: "1\<le>j \<and> j \<le> d \<and> x - ?I x r = j" by auto
then have xeqr: "x = ?I x r + j" by auto
with prems have "?Q (?I x r + j)" by simp
with con have qrpj: "\<exists> j\<in> {1 .. d}. ?Q (?I x r + j)" by auto
from prems have "\<forall>j\<in>{1..d}. \<not> ?Q (?I a r + j)" by auto
then have "\<not> (\<exists> j\<in>{1..d}. ?Q (?I x r + j))"
by (simp add: intterm_novar0[OF lininr, where x="x" and y="a"])
with qrpj prems have "- x + d + ?I x r \<le> 0" by simp
}
ultimately show "- x + d + ?I x r \<le> 0" by blast
qed
}
ultimately have ?case by blast
}
ultimately have ?case by blast
}
ultimately show ?case by blast
next
case (goal3 a t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have "n=0 \<or> n>0" by arith
moreover {assume "n>0" then have ?case using prems
by (simp add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="x-d"]) }
moreover {
assume nz: "n=0"
from prems have "abs i = 1" by auto
then have ipm: "i=1 \<or> i = -1" by arith
from nz prems have advdixr: "a dvd (i * x) + I_intterm (x # ats) r"
by simp
from prems have "a dvd d" by simp
then have advdid: "a dvd i*d" using ipm by auto
have ?case
using prems ipm
by (auto simp add: intterm_novar0[OF lininr, where x="x-d" and y="x"] dvd_period[OF advdid, where x="i*x" and c="-1"])
}
ultimately have ?case by blast
} ultimately show ?case by blast
next
case (goal4 a t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have "n=0 \<or> n>0" by arith
moreover {assume "n>0" then have ?case using prems
by (simp add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="x-d"]) }
moreover {
assume nz: "n=0"
from prems have "abs i = 1" by auto
then have ipm: "i =1 \<or> i = -1" by arith
from nz prems have advdixr: "\<not> (a dvd (i * x) + I_intterm (x # ats) r)"
by simp
from prems have "a dvd d" by simp
then have advdid: "a dvd i*d" using ipm by auto
have ?case
using prems ipm
by (auto simp add: intterm_novar0[OF lininr, where x="x-d" and y="x"] dvd_period[OF advdid, where x="i*x" and c="-1"])
}
ultimately have ?case by blast
} ultimately show ?case by blast
next
case (goal2 t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have "n=0 \<or> n>0" by arith
moreover {assume "n>0" then have ?case
using prems
by (simp add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="x-d"]) }
moreover
{assume nz: "n = 0"
from prems have "abs i = 1" by auto
then have "i = -1 \<or> i =1" by arith
moreover
{
assume i1: "i=1"
with prems have px: "x + ?I x r = 0" by simp
then have "x = (- ?I x r - 1) + 1" by simp
hence q1: "?Q ((- ?I x r - 1) + 1)" by simp
from prems have "\<not> (?Q ((?I a (lin_add(lin_neg r, Cst -1))) + 1))"
by auto
hence "\<not> (?Q ((- ?I a r - 1) + 1))"
using lin_add_corr lin_neg_corr linr lin_neg_lin
by simp
hence "\<not> (?Q ((- ?I x r - 1) + 1))"
using intterm_novar0[OF lininr, where x="x" and y="a"]
by simp
with q1 have ?case by simp
}
moreover
{
assume im1: "i = -1"
with prems have px: "-x + ?I x r = 0" by simp
then have "x = ?I x r" by simp
hence q1: "?Q (?I x r)" by simp
from prems have "\<not> (?Q ((?I a (lin_add(r, Cst -1))) + 1))"
by auto
hence "\<not> (?Q (?I a r))"
using lin_add_corr lin_neg_corr linr lin_neg_lin
by simp
hence "\<not> (?Q (?I x r ))"
using intterm_novar0[OF lininr, where x="x" and y="a"]
by simp
with q1 have ?case by simp
}
ultimately have ?case by blast
}
ultimately have ?case by blast
}
ultimately show ?case by blast
next
case (goal5 t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have "n=0 \<or> n>0" by arith
moreover {assume "n>0" then have ?case
using prems
by (simp add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="x-d"]) }
moreover
{assume nz: "n = 0"
from prems have "abs i = 1" by auto
then have "i = -1 \<or> i =1" by arith
moreover
{
assume i1: "i=1"
with prems have px: "x -d + ?I (x-d) r = 0" by simp
hence "x = (- ?I x r) + d"
using intterm_novar0[OF lininr, where x="x" and y="x-d"]
by simp
hence q1: "?Q (- ?I x r + d)" by simp
from prems have "\<not> (?Q ((?I a (lin_neg r)) + d))"
by auto
hence "\<not> (?Q (- ?I a r + d))"
using lin_neg_corr linr by simp
hence "\<not> (?Q ((- ?I x r + d)))"
using intterm_novar0[OF lininr, where x="x" and y="a"]
by simp
with q1 have ?case by simp
}
moreover
{
assume im1: "i = -1"
with prems have px: "- (x -d) + ?I (x - d) r = 0" by simp
then have "x = ?I x r + d "
using intterm_novar0[OF lininr, where x="x" and y="x-d"]
by simp
hence q1: "?Q (?I x r + d)" by simp
from prems have "\<not> (?Q ((?I a r) + d))"
by auto
hence "\<not> (?Q (?I x r + d))"
using intterm_novar0[OF lininr, where x="x" and y="a"]
by simp
with q1 have ?case by simp
}
ultimately have ?case by blast
}
ultimately have ?case by blast
}
ultimately show ?case by blast
qed
lemma bset_disj_repeat2:
assumes unifp: "isunified p"
shows "\<forall> x. \<not>(\<exists>j\<in> {1 .. (divlcm p)}. \<exists> b \<in> set (bset p).
(qinterp (((I_intterm (a#ats) b) + j)#ats) p))
\<longrightarrow> (qinterp (x#ats) p) \<longrightarrow> (qinterp ((x - (divlcm p))#ats) p)"
(is "\<forall> x. \<not>(\<exists> j\<in> {1 .. ?d}. \<exists> b\<in> ?B. ?P (?I a b + j)) \<longrightarrow> ?P x \<longrightarrow> ?P (x - ?d)")
proof
fix x
have linp: "islinform p" by (rule unified_islinform[OF unifp])
have dpos: "?d > 0" by (rule divlcm_pos[OF linp])
have alldvd: "alldivide(?d,p)" by (rule divlcm_corr[OF linp])
show "\<not>(\<exists> j\<in> {1 .. ?d}. \<exists> b\<in> ?B. ?P (?I a b + j)) \<longrightarrow> ?P x \<longrightarrow> ?P (x - ?d)"
using prems bset_disj_repeat[OF unifp alldvd dpos]
by blast
qed
(* Cooper's theorem in the minusinfinity version *)
lemma cooper_mi_eq:
assumes unifp : "isunified p"
shows "(\<exists> x. qinterp (x#ats) p) =
((\<exists> j \<in> {1 .. (divlcm p)}. qinterp (j#ats) (minusinf p)) \<or>
(\<exists> j \<in> {1 .. (divlcm p)}. \<exists> b \<in> set (bset p).
qinterp (((I_intterm (a#ats) b) + j)#ats) p))"
(is "(\<exists> x. ?P x) = ((\<exists> j\<in> {1 .. ?d}. ?MP j) \<or> (\<exists> j \<in> ?D. \<exists> b\<in> ?B. ?P (?I a b + j)))")
proof-
have linp :"islinform p" by (rule unified_islinform[OF unifp])
have dpos: "?d > 0" by (rule divlcm_pos[OF linp])
have alldvd: "alldivide(?d,p)" by (rule divlcm_corr[OF linp])
have eMPimpeP: "(\<exists>j \<in> ?D. ?MP j) \<longrightarrow> (\<exists>x. ?P x)"
by (simp add: minusinf_lemma[OF unifp, where d="?d" and ats="ats"])
have ePimpeP: "(\<exists> j \<in> ?D. \<exists> b\<in> ?B. ?P (?I a b + j)) \<longrightarrow> (\<exists> x. ?P x)"
by blast
have bst_rep: "\<forall> x. \<not> (\<exists> j \<in> ?D. \<exists> b \<in> ?B. ?P (?I a b + j)) \<longrightarrow> ?P x \<longrightarrow> ?P (x - ?d)"
by (rule bset_disj_repeat2[OF unifp])
have MPrep: "\<forall> x k. ?MP x = ?MP (x- k*?d)"
by (rule minusinf_repeats2[OF alldvd unifp])
have MPeqP: "\<exists> z. \<forall> x < z. ?P x = ?MP x"
by (rule minusinf_eq[OF unifp])
let ?B'= "{?I a b| b. b\<in> ?B}"
from bst_rep have bst_rep2: "\<forall>x. \<not> (\<exists>j\<in>?D. \<exists>b\<in> ?B'. ?P (b+j)) \<longrightarrow> ?P x \<longrightarrow> ?P (x - ?d)"
by auto
show ?thesis
using cpmi_eq[OF dpos MPeqP bst_rep2 MPrep]
by auto
qed
(* A formalized analogy between aset, bset, plusinfinity and minusinfinity *)
consts mirror:: "QF \<Rightarrow> QF"
recdef mirror "measure size"
"mirror (Le (Add (Mult (Cst c) (Var 0)) r) z) =
(Le (Add (Mult (Cst (- c)) (Var 0)) r) z)"
"mirror (Eq (Add (Mult (Cst c) (Var 0)) r) z) =
(Eq (Add (Mult (Cst (- c)) (Var 0)) r) z)"
"mirror (Divides (Cst d) (Add (Mult (Cst c) (Var 0)) r)) =
(Divides (Cst d) (Add (Mult (Cst (- c)) (Var 0)) r))"
"mirror (NOT(Divides (Cst d) (Add (Mult (Cst c) (Var 0)) r))) =
(NOT(Divides (Cst d) (Add (Mult (Cst (- c)) (Var 0)) r)))"
"mirror (NOT(Eq (Add (Mult (Cst c) (Var 0)) r) z)) =
(NOT(Eq (Add (Mult (Cst (- c)) (Var 0)) r) z))"
"mirror (And p q) = And (mirror p) (mirror q)"
"mirror (Or p q) = Or (mirror p) (mirror q)"
"mirror p = p"
(* mirror preserves unifiedness *)
lemma[simp]: "(abs (i::int) = 1) = (i =1 \<or> i = -1)" by arith
lemma mirror_unified:
assumes unif: "isunified p"
shows "isunified (mirror p)"
using unif
proof (induct p rule: mirror.induct, simp_all)
case (goal1 c r z)
from prems have zz: "z = Cst 0" by (cases z, simp_all)
then show ?case using prems
by (auto simp add: islinintterm_eq_islint islint_def)
next
case (goal2 c r z)
from prems have zz: "z = Cst 0" by (cases z, simp_all)
then show ?case using prems
by (auto simp add: islinintterm_eq_islint islint_def)
next
case (goal3 d c r) show ?case using prems by (auto simp add: islinintterm_eq_islint islint_def)
next
case (goal4 d c r) show ?case using prems by (auto simp add: islinintterm_eq_islint islint_def)
next
case (goal5 c r z)
from prems have zz: "z = Cst 0" by (cases z, simp_all)
then show ?case using prems
by (auto simp add: islinintterm_eq_islint islint_def)
qed
(* relationship between plusinf and minusinf *)
lemma plusinf_eq_minusinf_mirror:
assumes unifp: "isunified p"
shows "(qinterp (x#ats) (plusinf p)) = (qinterp ((- x)#ats) (minusinf (mirror p)))"
using unifp unified_islinform[OF unifp]
proof (induct p rule: islinform.induct, simp_all)
case (goal1 t z)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems
by (cases n, auto simp add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"] )}
ultimately show ?case by blast
next
case (goal2 t z)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems
by (cases n, auto simp add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"] )}
ultimately show ?case by blast
next
case (goal3 d t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems
by (cases n, simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"] )}
ultimately show ?case by blast
next
case (goal4 d t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems
by (cases n, simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"] )}
ultimately show ?case by blast
next
case (goal5 t z)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems
by (cases n, auto simp add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"] )}
ultimately show ?case by blast
qed
(* relationship between aset abd bset *)
lemma aset_eq_bset_mirror:
assumes unifp: "isunified p"
shows "set (aset p) = set (map lin_neg (bset (mirror p)))"
using unifp
proof(induct p rule: mirror.induct)
case (1 c r z)
from prems have zz: "z = Cst 0"
by (cases z, auto)
from prems zz have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have neg1eqm1: "Cst 1 = lin_neg (Cst -1)" by (simp add: lin_neg_def)
have negm1eq1: "Cst -1 = lin_neg (Cst 1)" by (simp add: lin_neg_def)
show ?case using prems linr zz apply (auto simp add: lin_neg_lin_add_distrib lin_neg_idemp neg1eqm1)
by (simp add: negm1eq1 lin_neg_idemp sym[OF lin_neg_lin_add_distrib] lin_add_lin)
next
case (2 c r z) from prems have zz: "z = Cst 0"
by (cases z, auto)
from prems zz have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have neg1eqm1: "Cst 1 = lin_neg (Cst -1)" by (simp add: lin_neg_def)
have negm1eq1: "Cst -1 = lin_neg (Cst 1)" by (simp add: lin_neg_def)
show ?case using prems linr zz
by (auto simp add: lin_neg_lin_add_distrib lin_neg_idemp neg1eqm1)
(simp add: negm1eq1 lin_neg_idemp sym[OF lin_neg_lin_add_distrib] lin_add_lin lin_neg_lin)
next
case (5 c r z) from prems have zz: "z = Cst 0"
by (cases z, auto)
from prems zz have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have neg1eqm1: "Cst 1 = lin_neg (Cst -1)" by (simp add: lin_neg_def)
have negm1eq1: "Cst -1 = lin_neg (Cst 1)" by (simp add: lin_neg_def)
show ?case using prems linr zz
by(auto simp add: lin_neg_lin_add_distrib lin_neg_idemp neg1eqm1)
qed simp_all
(* relationship between aset abd bset 2*)
lemma aset_eq_bset_mirror2:
assumes unifp: "isunified p"
shows "aset p = map lin_neg (bset (mirror p))"
using unifp
proof(induct p rule: mirror.induct)
case (1 c r z)
from prems have zz: "z = Cst 0"
by (cases z, auto)
from prems zz have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have neg1eqm1: "Cst 1 = lin_neg (Cst -1)" by (simp add: lin_neg_def)
have negm1eq1: "Cst -1 = lin_neg (Cst 1)" by (simp add: lin_neg_def)
show ?case using prems linr zz
apply (simp add: lin_neg_lin_add_distrib lin_neg_idemp neg1eqm1)
apply (simp add: negm1eq1 lin_neg_idemp sym[OF lin_neg_lin_add_distrib] lin_add_lin)
by arith
next
case (2 c r z) from prems have zz: "z = Cst 0"
by (cases z, auto)
from prems zz have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have neg1eqm1: "Cst 1 = lin_neg (Cst -1)" by (simp add: lin_neg_def)
have negm1eq1: "Cst -1 = lin_neg (Cst 1)" by (simp add: lin_neg_def)
show ?case using prems linr zz
by(auto simp add: lin_neg_lin_add_distrib lin_neg_idemp neg1eqm1)
(simp add: negm1eq1 lin_neg_idemp sym[OF lin_neg_lin_add_distrib] lin_add_lin lin_neg_lin)
next
case (5 c r z) from prems have zz: "z = Cst 0"
by (cases z, auto)
from prems zz have lincnr: "islinintterm (Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have neg1eqm1: "Cst 1 = lin_neg (Cst -1)" by (simp add: lin_neg_def)
have negm1eq1: "Cst -1 = lin_neg (Cst 1)" by (simp add: lin_neg_def)
show ?case using prems linr zz
by(auto simp add: lin_neg_lin_add_distrib lin_neg_idemp neg1eqm1)
qed simp_all
(* mirror preserves divlcm *)
lemma divlcm_mirror_eq:
assumes unifp: "isunified p"
shows "divlcm p = divlcm (mirror p)"
using unifp
by (induct p rule: mirror.induct) auto
(* mirror almost preserves semantics *)
lemma mirror_interp:
assumes unifp: "isunified p"
shows "(qinterp (x#ats) p) = (qinterp ((- x)#ats) (mirror p))" (is "?P x = ?MP (-x)")
using unifp unified_islinform[OF unifp]
proof (induct p rule: islinform.induct)
case (1 t z)
from prems have zz: "z = 0" by simp
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems zz
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
next
case (2 t z)
from prems have zz: "z = 0" by simp
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems zz
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
next
case (3 d t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case
using prems linr
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
next
case (6 d t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case
using prems linr
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
next
case (7 t z)
from prems have zz: "z = 0" by simp
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems zz
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
qed simp_all
lemma mirror_interp2:
assumes unifp: "islinform p"
shows "(qinterp (x#ats) p) = (qinterp ((- x)#ats) (mirror p))" (is "?P x = ?MP (-x)")
using unifp
proof (induct p rule: islinform.induct)
case (1 t z)
from prems have zz: "z = 0" by simp
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems zz
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
next
case (2 t z)
from prems have zz: "z = 0" by simp
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems zz
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
next
case (3 d t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case
using prems linr
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
next
case (6 d t)
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case
using prems linr
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
next
case (7 t z)
from prems have zz: "z = 0" by simp
from prems
have lint: "islinintterm t" by simp
then have "(\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r) \<or> (\<exists> i. t = Cst i)"
by (induct t rule: islinintterm.induct) auto
moreover{ assume "\<exists> i. t = Cst i" then have ?case using prems by auto }
moreover
{ assume "\<exists> i n r. t = Add (Mult (Cst i) (Var n) ) r"
then obtain "i" "n" "r" where
inr_def: "t = Add (Mult (Cst i) (Var n) ) r"
by blast
with lint have lininr: "islinintterm (Add (Mult (Cst i) (Var n) ) r)"
by simp
have linr: "islinintterm r"
by (rule islinintterm_subt[OF lininr])
have ?case using prems zz
by (cases n) (simp_all add: nth_pos2
intterm_novar0[OF lininr, where x="x" and y="-x"])
}
ultimately show ?case by blast
qed simp_all
(* mirror preserves existence *)
lemma mirror_ex:
assumes unifp: "isunified p"
shows "(\<exists> x. (qinterp (x#ats) p)) = (\<exists> y. (qinterp (y#ats) (mirror p)))"
(is "(\<exists> x. ?P x) = (\<exists> y. ?MP y)")
proof
assume "\<exists> x. ?P x"
then obtain "x" where px:"?P x" by blast
have "?MP (-x)"
using px
by(simp add: mirror_interp[OF unifp, where x="x"])
then show "\<exists> y. ?MP y" by blast
next
assume "\<exists> y. ?MP y"
then obtain "y" where mpy: "?MP y" by blast
have "?P (-y)"
using mpy
by (simp add: mirror_interp[OF unifp, where x="-y"])
then show "\<exists> x. ?P x" by blast
qed
lemma mirror_ex2:
assumes unifp: "isunified p"
shows "qinterp ats (QEx p) = qinterp ats (QEx (mirror p))"
using mirror_ex[OF unifp] by simp
(* Cooper's theorem in its plusinfinity version *)
lemma cooper_pi_eq:
assumes unifp : "isunified p"
shows "(\<exists> x. qinterp (x#ats) p) =
((\<exists> j \<in> {1 .. (divlcm p)}. qinterp (-j#ats) (plusinf p)) \<or>
(\<exists> j \<in> {1 .. (divlcm p)}. \<exists> b \<in> set (aset p).
qinterp (((I_intterm (a#ats) b) - j)#ats) p))"
(is "(\<exists> x. ?P x) = ((\<exists> j\<in> {1 .. ?d}. ?PP (-j)) \<or> (\<exists> j \<in> ?D. \<exists> b\<in> ?A. ?P (?I a b - j)))")
proof-
have unifmp: "isunified (mirror p)" by (rule mirror_unified[OF unifp])
have th1:
"(\<exists> j\<in> {1 .. ?d}. ?PP (-j)) = (\<exists> j\<in> {1..?d}. qinterp (j # ats) (minusinf (mirror p)))"
by (simp add: plusinf_eq_minusinf_mirror[OF unifp])
have dth: "?d = divlcm (mirror p)"
by (rule divlcm_mirror_eq[OF unifp])
have "(\<exists> j \<in> ?D. \<exists> b\<in> ?A. ?P (?I a b - j)) =
(\<exists> j\<in> ?D. \<exists> b \<in> set (map lin_neg (bset (mirror p))). ?P (?I a b - j))"
by (simp only: aset_eq_bset_mirror[OF unifp])
also have "\<dots> = (\<exists> j\<in> ?D. \<exists> b \<in> set (bset (mirror p)). ?P (?I a (lin_neg b) - j))"
by simp
also have "\<dots> = (\<exists> j\<in> ?D. \<exists> b \<in> set (bset (mirror p)). ?P (-(?I a b + j)))"
proof
assume "\<exists>j\<in>{1..divlcm p}.
\<exists>b\<in>set (bset (mirror p)). qinterp ((I_intterm (a # ats) (lin_neg b) - j) # ats) p"
then
obtain "j" and "b" where
pbmj: "j\<in> ?D \<and> b\<in> set (bset (mirror p)) \<and> ?P (?I a (lin_neg b) - j)" by blast
then have linb: "islinintterm b"
by (auto simp add:bset_lin[OF unifmp])
from linb pbmj have "?P (-(?I a b + j))" by (simp add: lin_neg_corr)
then show "\<exists> j\<in> ?D. \<exists> b \<in> set (bset (mirror p)). ?P (-(?I a b + j))"
using pbmj
by auto
next
assume "\<exists> j\<in> ?D. \<exists> b \<in> set (bset (mirror p)). ?P (-(?I a b + j))"
then obtain "j" and "b" where
pbmj: "j\<in> ?D \<and> b\<in> set (bset (mirror p)) \<and> ?P (-(?I a b + j))"
by blast
then have linb: "islinintterm b"
by (auto simp add:bset_lin[OF unifmp])
from linb pbmj have "?P (?I a (lin_neg b) - j)"
by (simp add: lin_neg_corr)
then show "\<exists> j\<in> ?D. \<exists> b \<in> set (bset (mirror p)). ?P (?I a (lin_neg b) - j)"
using pbmj by auto
qed
finally
have bth: "(\<exists> j\<in> ?D. \<exists> b\<in> ?A. ?P (?I a b - j)) =
(\<exists>j\<in> ?D. \<exists> b\<in>set (bset (mirror p)).
qinterp ((I_intterm (a # ats) b + j) # ats) (mirror p))"
by (simp add: mirror_interp[OF unifp] zadd_ac)
from bth dth th1
have "(\<exists> x. ?P x) = (\<exists> x. qinterp (x#ats) (mirror p))"
by (simp add: mirror_ex[OF unifp])
also have "\<dots> = ((\<exists>j\<in>{1..divlcm (mirror p)}. qinterp (j # ats) (minusinf (mirror p))) \<or>
(\<exists>j\<in>{1..divlcm (mirror p)}.
\<exists>b\<in>set (bset (mirror p)). qinterp ((I_intterm (a # ats) b + j) # ats) (mirror p)))"
(is "(\<exists> x. ?MP x) = ((\<exists> j\<in> ?DM. ?MPM j) \<or> (\<exists> j \<in> ?DM. \<exists> b\<in> ?BM. ?MP (?I a b + j)))")
by (rule cooper_mi_eq[OF unifmp])
also
have "\<dots> = ((\<exists> j\<in> ?D. ?PP (-j)) \<or> (\<exists> j \<in> ?D. \<exists> b\<in> ?BM. ?MP (?I a b + j)))"
using bth th1 dth by simp
finally show ?thesis using sym[OF bth] by simp
qed
(* substitution of a term into a Qfree formula, substitution of Bound 0 by i*)
consts subst_it:: "intterm \<Rightarrow> intterm \<Rightarrow> intterm"
primrec
"subst_it i (Cst b) = Cst b"
"subst_it i (Var n) = (if n = 0 then i else Var n)"
"subst_it i (Neg it) = Neg (subst_it i it)"
"subst_it i (Add it1 it2) = Add (subst_it i it1) (subst_it i it2)"
"subst_it i (Sub it1 it2) = Sub (subst_it i it1) (subst_it i it2)"
"subst_it i (Mult it1 it2) = Mult (subst_it i it1) (subst_it i it2)"
(* subst_it preserves semantics *)
lemma subst_it_corr:
"I_intterm (a#ats) (subst_it i t) = I_intterm ((I_intterm (a#ats) i)#ats) t"
by (induct t rule: subst_it.induct, simp_all add: nth_pos2)
consts subst_p:: "intterm \<Rightarrow> QF \<Rightarrow> QF"
primrec
"subst_p i (Le it1 it2) = Le (subst_it i it1) (subst_it i it2)"
"subst_p i (Lt it1 it2) = Lt (subst_it i it1) (subst_it i it2)"
"subst_p i (Ge it1 it2) = Ge (subst_it i it1) (subst_it i it2)"
"subst_p i (Gt it1 it2) = Gt (subst_it i it1) (subst_it i it2)"
"subst_p i (Eq it1 it2) = Eq (subst_it i it1) (subst_it i it2)"
"subst_p i (Divides d t) = Divides (subst_it i d) (subst_it i t)"
"subst_p i T = T"
"subst_p i F = F"
"subst_p i (And p q) = And (subst_p i p) (subst_p i q)"
"subst_p i (Or p q) = Or (subst_p i p) (subst_p i q)"
"subst_p i (Imp p q) = Imp (subst_p i p) (subst_p i q)"
"subst_p i (Equ p q) = Equ (subst_p i p) (subst_p i q)"
"subst_p i (NOT p) = (NOT (subst_p i p))"
(* subs_p preserves correctness *)
lemma subst_p_corr:
assumes qf: "isqfree p"
shows "qinterp (a # ats) (subst_p i p) = qinterp ((I_intterm (a#ats) i)#ats) p "
using qf
by (induct p rule: subst_p.induct) (simp_all add: subst_it_corr)
(* novar0 p is true if the fomula doese not depend on the quantified variable*)
consts novar0I:: "intterm \<Rightarrow> bool"
primrec
"novar0I (Cst i) = True"
"novar0I (Var n) = (n > 0)"
"novar0I (Neg a) = (novar0I a)"
"novar0I (Add a b) = (novar0I a \<and> novar0I b)"
"novar0I (Sub a b) = (novar0I a \<and> novar0I b)"
"novar0I (Mult a b) = (novar0I a \<and> novar0I b)"
consts novar0:: "QF \<Rightarrow> bool"
recdef novar0 "measure size"
"novar0 (Lt a b) = (novar0I a \<and> novar0I b)"
"novar0 (Gt a b) = (novar0I a \<and> novar0I b)"
"novar0 (Le a b) = (novar0I a \<and> novar0I b)"
"novar0 (Ge a b) = (novar0I a \<and> novar0I b)"
"novar0 (Eq a b) = (novar0I a \<and> novar0I b)"
"novar0 (Divides a b) = (novar0I a \<and> novar0I b)"
"novar0 T = True"
"novar0 F = True"
"novar0 (NOT p) = novar0 p"
"novar0 (And p q) = (novar0 p \<and> novar0 q)"
"novar0 (Or p q) = (novar0 p \<and> novar0 q)"
"novar0 (Imp p q) = (novar0 p \<and> novar0 q)"
"novar0 (Equ p q) = (novar0 p \<and> novar0 q)"
"novar0 p = False"
(* Interpretation of terms, that doese not depend on Var 0 *)
lemma I_intterm_novar0:
assumes nov0: "novar0I x"
shows "I_intterm (a#ats) x = I_intterm (b#ats) x"
using nov0
by (induct x) (auto simp add: nth_pos2)
(* substition is meaningless for term independent of Var 0*)
lemma subst_p_novar0_corr:
assumes qfp: "isqfree p"
and nov0: "novar0I i"
shows "qinterp (a#ats) (subst_p i p) = qinterp (I_intterm (b#ats) i#ats) p"
proof-
have "qinterp (a#ats) (subst_p i p) = qinterp (I_intterm (a#ats) i#ats) p"
by (rule subst_p_corr[OF qfp])
moreover have "I_intterm (a#ats) i#ats = I_intterm (b#ats) i#ats"
by (simp add: I_intterm_novar0[OF nov0, where a="a" and b="b"])
ultimately show ?thesis by simp
qed
(* linearity and independence on Var 0*)
lemma lin_novar0:
assumes linx: "islinintterm x"
and nov0: "novar0I x"
shows "\<exists> n > 0. islintn(n,x)"
using linx nov0
by (induct x rule: islinintterm.induct) auto
lemma lintnpos_novar0:
assumes npos: "n > 0"
and linx: "islintn(n,x)"
shows "novar0I x"
using npos linx
by (induct n x rule: islintn.induct) auto
(* lin_add preserves independence on Var 0*)
lemma lin_add_novar0:
assumes nov0a: "novar0I a"
and nov0b : "novar0I b"
and lina : "islinintterm a"
and linb: "islinintterm b"
shows "novar0I (lin_add (a,b))"
proof-
have "\<exists> na > 0. islintn(na, a)" by (rule lin_novar0[OF lina nov0a])
then obtain "na" where na: "na > 0 \<and> islintn(na,a)" by blast
have "\<exists> nb > 0. islintn(nb, b)" by (rule lin_novar0[OF linb nov0b])
then obtain "nb" where nb: "nb > 0 \<and> islintn(nb,b)" by blast
from na have napos: "na > 0" by simp
from na have linna: "islintn(na,a)" by simp
from nb have nbpos: "nb > 0" by simp
from nb have linnb: "islintn(nb,b)" by simp
have "min na nb \<le> min na nb" by simp
then have "islintn (min na nb, lin_add(a,b))" by (simp add: lin_add_lint[OF linna linnb])
moreover have "min na nb > 0" using napos nbpos by (simp add: min_def)
ultimately show ?thesis by (simp only: lintnpos_novar0)
qed
(* lin__mul preserves independence on Var 0*)
lemma lin_mul_novar0:
assumes linx: "islinintterm x"
and nov0: "novar0I x"
shows "novar0I (lin_mul(i,x))"
using linx nov0
proof (induct i x rule: lin_mul.induct, auto)
case (goal1 c c' n r)
from prems have lincnr: "islinintterm (Add (Mult (Cst c') (Var n)) r)" by simp
have "islinintterm r" by (rule islinintterm_subt[OF lincnr])
then show ?case using prems by simp
qed
(* lin_neg preserves indepenednce on Var 0*)
lemma lin_neg_novar0:
assumes linx: "islinintterm x"
and nov0: "novar0I x"
shows "novar0I (lin_neg x)"
by (auto simp add: lin_mul_novar0 linx nov0 lin_neg_def)
(* subterms of linear terms are independent on Var 0*)
lemma intterm_subt_novar0:
assumes lincnr: "islinintterm (Add (Mult (Cst c) (Var n)) r)"
shows "novar0I r"
proof-
have cnz: "c \<noteq> 0" by (rule islinintterm_cnz[OF lincnr])
have "islintn(0,Add (Mult (Cst c) (Var n)) r)" using lincnr
by (simp only: islinintterm_eq_islint islint_def)
then have "islintn (n+1,r)" by auto
moreover have "n+1 >0 " by arith
ultimately show ?thesis
using lintnpos_novar0
by auto
qed
(* decrease the De-Bruijn indices*)
consts decrvarsI:: "intterm \<Rightarrow> intterm"
primrec
"decrvarsI (Cst i) = (Cst i)"
"decrvarsI (Var n) = (Var (n - 1))"
"decrvarsI (Neg a) = (Neg (decrvarsI a))"
"decrvarsI (Add a b) = (Add (decrvarsI a) (decrvarsI b))"
"decrvarsI (Sub a b) = (Sub (decrvarsI a) (decrvarsI b))"
"decrvarsI (Mult a b) = (Mult (decrvarsI a) (decrvarsI b))"
(* One can decrease the indics for terms and formulae independent on Var 0*)
lemma intterm_decrvarsI:
assumes nov0: "novar0I t"
shows "I_intterm (a#ats) t = I_intterm ats (decrvarsI t)"
using nov0
by (induct t) (auto simp add: nth_pos2)
consts decrvars:: "QF \<Rightarrow> QF"
primrec
"decrvars (Lt a b) = (Lt (decrvarsI a) (decrvarsI b))"
"decrvars (Gt a b) = (Gt (decrvarsI a) (decrvarsI b))"
"decrvars (Le a b) = (Le (decrvarsI a) (decrvarsI b))"
"decrvars (Ge a b) = (Ge (decrvarsI a) (decrvarsI b))"
"decrvars (Eq a b) = (Eq (decrvarsI a) (decrvarsI b))"
"decrvars (Divides a b) = (Divides (decrvarsI a) (decrvarsI b))"
"decrvars T = T"
"decrvars F = F"
"decrvars (NOT p) = (NOT (decrvars p))"
"decrvars (And p q) = (And (decrvars p) (decrvars q))"
"decrvars (Or p q) = (Or (decrvars p) (decrvars q))"
"decrvars (Imp p q) = (Imp (decrvars p) (decrvars q))"
"decrvars (Equ p q) = (Equ (decrvars p) (decrvars q))"
(* decrvars preserves quantifier freeness*)
lemma decrvars_qfree: "isqfree p \<Longrightarrow> isqfree (decrvars p)"
by (induct p rule: isqfree.induct, auto)
lemma novar0_qfree: "novar0 p \<Longrightarrow> isqfree p"
by (induct p) auto
lemma qinterp_novar0:
assumes nov0: "novar0 p"
shows "qinterp (a#ats) p = qinterp ats (decrvars p)"
using nov0
by(induct p) (simp_all add: intterm_decrvarsI)
(* All elements of bset p doese not depend on Var 0*)
lemma bset_novar0:
assumes unifp: "isunified p"
shows "\<forall> b\<in> set (bset p). novar0I b "
using unifp
proof(induct p rule: bset.induct)
case (1 c r z)
from prems have zz: "z = Cst 0" by (cases "z", auto)
from prems zz have lincnr: "islinintterm(Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have novar0r: "novar0I r" by (rule intterm_subt_novar0[OF lincnr])
from prems zz have "c = 1 \<or> c = -1" by auto
moreover
{
assume c1: "c=1"
have lin1: "islinintterm (Cst 1)" by simp
have novar01: "novar0I (Cst 1)" by simp
then have ?case
using prems zz novar0r lin1 novar01
by (auto simp add: lin_add_novar0 lin_neg_novar0 linr lin_neg_lin)
}
moreover
{
assume c1: "c= -1"
have lin1: "islinintterm (Cst -1)" by simp
have novar01: "novar0I (Cst -1)" by simp
then have ?case
using prems zz novar0r lin1 novar01
by (auto simp add: lin_add_novar0 lin_neg_novar0 linr lin_neg_lin)
}
ultimately show ?case by blast
next
case (2 c r z)
from prems have zz: "z = Cst 0" by (cases "z", auto)
from prems zz have lincnr: "islinintterm(Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have novar0r: "novar0I r" by (rule intterm_subt_novar0[OF lincnr])
from prems zz have "c = 1 \<or> c = -1" by auto
moreover
{
assume c1: "c=1"
have lin1: "islinintterm (Cst 1)" by simp
have novar01: "novar0I (Cst 1)" by simp
then have ?case
using prems zz novar0r lin1 novar01
by (auto simp add: lin_add_novar0 lin_neg_novar0 linr lin_neg_lin)
}
moreover
{
assume c1: "c= -1"
have lin1: "islinintterm (Cst -1)" by simp
have novar01: "novar0I (Cst -1)" by simp
then have ?case
using prems zz novar0r lin1 novar01
by (auto simp add: lin_add_novar0 lin_neg_novar0 linr lin_neg_lin)
}
ultimately show ?case by blast
next
case (3 c r z)
from prems have zz: "z = Cst 0" by (cases "z", auto)
from prems zz have lincnr: "islinintterm(Add (Mult (Cst c) (Var 0)) r)" by simp
have linr: "islinintterm r" by (rule islinintterm_subt[OF lincnr])
have novar0r: "novar0I r" by (rule intterm_subt_novar0[OF lincnr])
from prems zz have "c = 1 \<or> c = -1" by auto
moreover
{
assume c1: "c=1"
have lin1: "islinintterm (Cst 1)" by simp
have novar01: "novar0I (Cst 1)" by simp
then have ?case
using prems zz novar0r lin1 novar01
by (auto simp add: lin_add_novar0 lin_neg_novar0 linr lin_neg_lin)
}
moreover
{
assume c1: "c= -1"
have lin1: "islinintterm (Cst -1)" by simp
have novar01: "novar0I (Cst -1)" by simp
then have ?case
using prems zz novar0r lin1 novar01
by (auto simp add: lin_add_novar0 lin_neg_novar0 linr lin_neg_lin)
}
ultimately show ?case by blast
qed auto
(* substitution preserves independence on Var 0*)
lemma subst_it_novar0:
assumes nov0x: "novar0I x"
shows "novar0I (subst_it x t)"
using nov0x
by (induct t) auto
lemma subst_p_novar0:
assumes nov0x:"novar0I x"
and qfp: "isqfree p"
shows "novar0 (subst_p x p)"
using nov0x qfp
by (induct p rule: novar0.induct) (simp_all add: subst_it_novar0)
(* linearize preserves independence on Var 0 *)
lemma linearize_novar0:
assumes nov0t: "novar0I t "
shows "\<And> t'. linearize t = Some t' \<Longrightarrow> novar0I t'"
using nov0t
proof(induct t rule: novar0I.induct)
case (Neg a)
let ?la = "linearize a"
from prems have "\<exists> a'. ?la = Some a'" by (cases ?la, auto)
then obtain "a'" where "?la = Some a'" by blast
with prems have nv0a':"novar0I a'" by simp
have "islinintterm a'" using prems by (simp add: linearize_linear)
with nv0a' have "novar0I (lin_neg a')"
by (simp add: lin_neg_novar0)
then
show ?case using prems by simp
next
case (Add a b)
let ?la = "linearize a"
let ?lb = "linearize b"
from prems have linab: "linearize (Add a b) = Some t'" by simp
then have "\<exists> a'. ?la = Some a'" by (cases ?la) auto
then obtain "a'" where "?la = Some a'" by blast
with prems have nv0a':"novar0I a'" by simp
have lina': "islinintterm a'" using prems by (simp add: linearize_linear)
from linab have "\<exists> b'. ?lb = Some b'"
by (cases ?la, auto simp add: measure_def inv_image_def) (cases ?lb, auto)
then obtain "b'" where "?lb = Some b'" by blast
with prems have nv0b':"novar0I b'" by simp
have linb': "islinintterm b'" using prems by (simp add: linearize_linear)
then show ?case using prems lina' linb' nv0a' nv0b'
by (auto simp add: measure_def inv_image_def lin_add_novar0)
next
case (Sub a b)
let ?la = "linearize a"
let ?lb = "linearize b"
from prems have linab: "linearize (Sub a b) = Some t'" by simp
then have "\<exists> a'. ?la = Some a'" by (cases ?la) auto
then obtain "a'" where "?la = Some a'" by blast
with prems have nv0a':"novar0I a'" by simp
have lina': "islinintterm a'" using prems by (simp add: linearize_linear)
from linab have "\<exists> b'. ?lb = Some b'"
by (cases ?la, auto simp add: measure_def inv_image_def) (cases ?lb, auto)
then obtain "b'" where "?lb = Some b'" by blast
with prems have nv0b':"novar0I b'" by simp
have linb': "islinintterm b'" using prems by (simp add: linearize_linear)
then show ?case using prems lina' linb' nv0a' nv0b'
by (auto simp add:
measure_def inv_image_def lin_add_novar0 lin_neg_novar0 lin_neg_lin)
next
case (Mult a b)
let ?la = "linearize a"
let ?lb = "linearize b"
from prems have linab: "linearize (Mult a b) = Some t'" by simp
then have "\<exists> a'. ?la = Some a'"
by (cases ?la, auto simp add: measure_def inv_image_def)
then obtain "a'" where "?la = Some a'" by blast
with prems have nv0a':"novar0I a'" by simp
have lina': "islinintterm a'" using prems by (simp add: linearize_linear)
from prems linab have "\<exists> b'. ?lb = Some b'"
apply (cases ?la, auto simp add: measure_def inv_image_def)
by (cases "a'",auto simp add: measure_def inv_image_def) (cases ?lb, auto)+
then obtain "b'" where "?lb = Some b'" by blast
with prems have nv0b':"novar0I b'" by simp
have linb': "islinintterm b'" using prems by (simp add: linearize_linear)
then show ?case using prems lina' linb' nv0a' nv0b'
by (cases "a'",auto simp add: measure_def inv_image_def lin_mul_novar0)
(cases "b'",auto simp add: measure_def inv_image_def lin_mul_novar0)
qed auto
(* simplification of formulae *)
consts psimpl :: "QF \<Rightarrow> QF"
recdef psimpl "measure size"
"psimpl (Le l r) =
(case (linearize (Sub l r)) of
None \<Rightarrow> Le l r
| Some x \<Rightarrow> (case x of
Cst i \<Rightarrow> (if i \<le> 0 then T else F)
| _ \<Rightarrow> (Le x (Cst 0))))"
"psimpl (Eq l r) =
(case (linearize (Sub l r)) of
None \<Rightarrow> Eq l r
| Some x \<Rightarrow> (case x of
Cst i \<Rightarrow> (if i = 0 then T else F)
| _ \<Rightarrow> (Eq x (Cst 0))))"
"psimpl (Divides (Cst d) t) =
(case (linearize t) of
None \<Rightarrow> (Divides (Cst d) t)
| Some c \<Rightarrow> (case c of
Cst i \<Rightarrow> (if d dvd i then T else F)
| _ \<Rightarrow> (Divides (Cst d) c)))"
"psimpl (And p q) =
(let p'= psimpl p
in (case p' of
F \<Rightarrow> F
|T \<Rightarrow> psimpl q
| _ \<Rightarrow> let q' = psimpl q
in (case q' of
F \<Rightarrow> F
| T \<Rightarrow> p'
| _ \<Rightarrow> (And p' q'))))"
"psimpl (Or p q) =
(let p'= psimpl p
in (case p' of
T \<Rightarrow> T
| F \<Rightarrow> psimpl q
| _ \<Rightarrow> let q' = psimpl q
in (case q' of
T \<Rightarrow> T
| F \<Rightarrow> p'
| _ \<Rightarrow> (Or p' q'))))"
"psimpl (Imp p q) =
(let p'= psimpl p
in (case p' of
F \<Rightarrow> T
|T \<Rightarrow> psimpl q
| NOT p1 \<Rightarrow> let q' = psimpl q
in (case q' of
F \<Rightarrow> p1
| T \<Rightarrow> T
| _ \<Rightarrow> (Or p1 q'))
| _ \<Rightarrow> let q' = psimpl q
in (case q' of
F \<Rightarrow> NOT p'
| T \<Rightarrow> T
| _ \<Rightarrow> (Imp p' q'))))"
"psimpl (Equ p q) =
(let p'= psimpl p ; q' = psimpl q
in (case p' of
T \<Rightarrow> q'
| F \<Rightarrow> (case q' of
T \<Rightarrow> F
| F \<Rightarrow> T
| NOT q1 \<Rightarrow> q1
| _ \<Rightarrow> NOT q')
| NOT p1 \<Rightarrow> (case q' of
T \<Rightarrow> p'
| F \<Rightarrow> p1
| NOT q1 \<Rightarrow> (Equ p1 q1)
| _ \<Rightarrow> (Equ p' q'))
| _ \<Rightarrow> (case q' of
T \<Rightarrow> p'
| F \<Rightarrow> NOT p'
| _ \<Rightarrow> (Equ p' q'))))"
"psimpl (NOT p) =
(let p' = psimpl p
in ( case p' of
F \<Rightarrow> T
| T \<Rightarrow> F
| NOT p1 \<Rightarrow> p1
| _ \<Rightarrow> (NOT p')))"
"psimpl p = p"
(* psimpl preserves semantics *)
lemma psimpl_corr: "qinterp ats p = qinterp ats (psimpl p)"
proof(induct p rule: psimpl.induct)
case (1 l r)
have "(\<exists> lx. linearize (Sub l r) = Some lx) \<or> (linearize (Sub l r) = None)" by auto
moreover
{
assume lin: "\<exists> lx. linearize (Sub l r) = Some lx"
from lin obtain "lx" where lx: "linearize (Sub l r) = Some lx" by blast
from lx have "I_intterm ats (Sub l r) = I_intterm ats lx"
by (rule linearize_corr[where t="Sub l r" and t'= "lx"])
then have feq: "qinterp ats (Le l r) = qinterp ats (Le lx (Cst 0))" by (simp , arith)
from lx have lxlin: "islinintterm lx" by (rule linearize_linear)
from lxlin feq have ?case
proof-
have "(\<exists> i. lx = Cst i) \<or> (\<not> (\<exists> i. lx = Cst i))" by blast
moreover
{
assume lxcst: "\<exists> i. lx = Cst i"
from lxcst obtain "i" where lxi: "lx = Cst i" by blast
with feq have "qinterp ats (Le l r) = (i \<le> 0)" by simp
then have ?case using prems by (simp add: measure_def inv_image_def)
}
moreover
{
assume "(\<not> (\<exists> i. lx = Cst i))"
then have "(case lx of
Cst i \<Rightarrow> (if i \<le> 0 then T else F)
| _ \<Rightarrow> (Le lx (Cst 0))) = (Le lx (Cst 0))"
by (case_tac "lx::intterm", auto)
with prems lxlin feq have ?case by (auto simp add: measure_def inv_image_def)
}
ultimately show ?thesis by blast
qed
}
moreover
{
assume "linearize (Sub l r) = None"
then have ?case using prems by simp
}
ultimately show ?case by blast
next
case (2 l r)
have "(\<exists> lx. linearize (Sub l r) = Some lx) \<or> (linearize (Sub l r) = None)" by auto
moreover
{
assume lin: "\<exists> lx. linearize (Sub l r) = Some lx"
from lin obtain "lx" where lx: "linearize (Sub l r) = Some lx" by blast
from lx have "I_intterm ats (Sub l r) = I_intterm ats lx"
by (rule linearize_corr[where t="Sub l r" and t'= "lx"])
then have feq: "qinterp ats (Eq l r) = qinterp ats (Eq lx (Cst 0))" by (simp , arith)
from lx have lxlin: "islinintterm lx" by (rule linearize_linear)
from lxlin feq have ?case
proof-
have "(\<exists> i. lx = Cst i) \<or> (\<not> (\<exists> i. lx = Cst i))" by blast
moreover
{
assume lxcst: "\<exists> i. lx = Cst i"
from lxcst obtain "i" where lxi: "lx = Cst i" by blast
with feq have "qinterp ats (Eq l r) = (i = 0)" by simp
then have ?case using prems by (simp add: measure_def inv_image_def)
}
moreover
{
assume "(\<not> (\<exists> i. lx = Cst i))"
then have "(case lx of
Cst i \<Rightarrow> (if i = 0 then T else F)
| _ \<Rightarrow> (Eq lx (Cst 0))) = (Eq lx (Cst 0))"
by (case_tac "lx::intterm", auto)
with prems lxlin feq have ?case by (auto simp add: measure_def inv_image_def)
}
ultimately show ?thesis by blast
qed
}
moreover
{
assume "linearize (Sub l r) = None"
then have ?case using prems by simp
}
ultimately show ?case by blast
next
case (3 d t)
have "(\<exists> lt. linearize t = Some lt) \<or> (linearize t = None)" by auto
moreover
{
assume lin: "\<exists> lt. linearize t = Some lt"
from lin obtain "lt" where lt: "linearize t = Some lt" by blast
from lt have "I_intterm ats t = I_intterm ats lt"
by (rule linearize_corr[where t="t" and t'= "lt"])
then have feq: "qinterp ats (Divides (Cst d) t) = qinterp ats (Divides (Cst d) lt)" by (simp)
from lt have ltlin: "islinintterm lt" by (rule linearize_linear)
from ltlin feq have ?case using prems apply simp by (case_tac "lt::intterm", simp_all)
}
moreover
{
assume "linearize t = None"
then have ?case using prems by simp
}
ultimately show ?case by blast
next
case (4 f g)
let ?sf = "psimpl f"
let ?sg = "psimpl g"
show ?case using prems
by (cases ?sf, simp_all add: Let_def measure_def inv_image_def)
(cases ?sg, simp_all)+
next
case (5 f g)
let ?sf = "psimpl f"
let ?sg = "psimpl g"
show ?case using prems
apply (cases ?sf, simp_all add: Let_def measure_def inv_image_def)
apply (cases ?sg, simp_all)
apply (cases ?sg, simp_all)
apply (cases ?sg, simp_all)
apply (cases ?sg, simp_all)
apply (cases ?sg, simp_all)
apply (cases ?sg, simp_all)
apply (cases ?sg, simp_all)
apply blast
apply (cases ?sg, simp_all)
apply (cases ?sg, simp_all)
apply (cases ?sg, simp_all)
apply blast
apply (cases ?sg, simp_all)
by (cases ?sg, simp_all) (cases ?sg, simp_all)
next
case (6 f g)
let ?sf = "psimpl f"
let ?sg = "psimpl g"
show ?case using prems
apply(simp add: Let_def measure_def inv_image_def)
apply(cases ?sf,simp_all)
apply (simp_all add: Let_def measure_def inv_image_def)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply blast
apply blast
apply blast
apply blast
apply blast
apply blast
apply blast
apply blast
apply blast
apply blast
apply blast
apply blast
apply blast
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
apply(cases ?sg, simp_all)
done
next
case (7 f g)
let ?sf = "psimpl f"
let ?sg = "psimpl g"
show ?case
using prems
by (cases ?sf, simp_all add: Let_def) (cases ?sg, simp_all)+
next
case (8 f) show ?case
using prems
apply (simp add: Let_def)
by (case_tac "psimpl f", simp_all)
qed simp_all
(* psimpl preserves independence on Var 0*)
lemma psimpl_novar0:
assumes nov0p: "novar0 p"
shows "novar0 (psimpl p)"
using nov0p
proof (induct p rule: psimpl.induct)
case (1 l r)
let ?ls = "linearize (Sub l r)"
have "?ls = None \<or> (\<exists> x. ?ls = Some x)" by auto
moreover
{
assume "?ls = None" then have ?case
using prems by (simp add: measure_def inv_image_def)
}
moreover {
assume "\<exists> x. ?ls = Some x"
then obtain "x" where ls_d: "?ls = Some x" by blast
from prems have "novar0I l" by simp
moreover from prems have "novar0I r" by simp
ultimately have nv0s: "novar0I (Sub l r)" by simp
from prems have "novar0I x"
by (simp add: linearize_novar0[OF nv0s, where t'="x"])
then have ?case
using prems
by (cases "x") (auto simp add: measure_def inv_image_def)
}
ultimately show ?case by blast
next
case (2 l r)
let ?ls = "linearize (Sub l r)"
have "?ls = None \<or> (\<exists> x. ?ls = Some x)" by auto
moreover
{
assume "?ls = None" then have ?case
using prems by (simp add: measure_def inv_image_def)
}
moreover {
assume "\<exists> x. ?ls = Some x"
then obtain "x" where ls_d: "?ls = Some x" by blast
from prems have "novar0I l" by simp
moreover from prems have "novar0I r" by simp
ultimately have nv0s: "novar0I (Sub l r)" by simp
from prems have "novar0I x"
by (simp add: linearize_novar0[OF nv0s, where t'="x"])
then have ?case
using prems
by (cases "x") (auto simp add: measure_def inv_image_def)
}
ultimately show ?case by blast
next
case (3 d t)
let ?lt = "linearize t"
have "?lt = None \<or> (\<exists> x. ?lt = Some x)" by auto
moreover
{ assume "?lt = None" then have ?case using prems by simp }
moreover {
assume "\<exists>x. ?lt = Some x"
then obtain "x" where x_d: "?lt = Some x" by blast
from prems have nv0t: "novar0I t" by simp
with x_d have "novar0I x"
by (simp add: linearize_novar0[OF nv0t])
with prems have ?case
by (cases "x") simp_all
}
ultimately show ?case by blast
next
case (4 f g)
let ?sf = "psimpl f"
let ?sg = "psimpl g"
show ?case
using prems
by (cases ?sf, simp_all add: Let_def measure_def inv_image_def)
(cases ?sg,simp_all)+
next
case (5 f g)
let ?sf = "psimpl f"
let ?sg = "psimpl g"
show ?case
using prems
by (cases ?sf, simp_all add: Let_def measure_def inv_image_def)
(cases ?sg,simp_all)+
next
case (6 f g)
let ?sf = "psimpl f"
let ?sg = "psimpl g"
show ?case
using prems
by (cases ?sf, simp_all add: Let_def measure_def inv_image_def)
(cases ?sg,simp_all)+
next
case (7 f g)
let ?sf = "psimpl f"
let ?sg = "psimpl g"
show ?case
using prems
by (cases ?sf, simp_all add: Let_def measure_def inv_image_def)
(cases ?sg,simp_all)+
next
case (8 f)
let ?sf = "psimpl f"
from prems have nv0sf:"novar0 ?sf" by simp
show ?case using prems nv0sf
by (cases ?sf, auto simp add: Let_def measure_def inv_image_def)
qed simp_all
(* implements a disj of p applied to all elements of the list*)
consts explode_disj :: "(intterm list \<times> QF) \<Rightarrow> QF"
recdef explode_disj "measure (\<lambda>(is,p). length is)"
"explode_disj ([],p) = F"
"explode_disj (i#is,p) =
(let pi = psimpl (subst_p i p)
in ( case pi of
T \<Rightarrow> T
| F \<Rightarrow> explode_disj (is,p)
| _ \<Rightarrow> (let r = explode_disj (is,p)
in (case r of
T \<Rightarrow> T
| F \<Rightarrow> pi
| _ \<Rightarrow> Or pi r))))"
(* correctness theorem for one iteration of explode_disj *)
lemma explode_disj_disj:
assumes qfp: "isqfree p"
shows "(qinterp (x#xs) (explode_disj(i#is,p))) =
(qinterp (x#xs) (subst_p i p) \<or> (qinterp (x#xs) (explode_disj(is,p))))"
using qfp
proof-
let ?pi = "psimpl (subst_p i p)"
have pi: "qinterp (x#xs) ?pi = qinterp (x#xs) (subst_p i p)"
by (simp add: psimpl_corr[where p="(subst_p i p)"])
let ?dp = "explode_disj(is,p)"
show ?thesis using pi
proof (cases)
assume "?pi= T \<or> ?pi = F"
then show ?thesis using pi by (case_tac "?pi::QF", auto)
next
assume notTF: "\<not> (?pi = T \<or> ?pi = F)"
let ?dp = "explode_disj(is,p)"
have dp_cases: "explode_disj(i#is,p) =
(case (explode_disj(is,p)) of
T \<Rightarrow> T
| F \<Rightarrow> psimpl (subst_p i p)
| _ \<Rightarrow> Or (psimpl (subst_p i p)) (explode_disj(is,p)))" using notTF
by (cases "?pi")
(simp_all add: Let_def cong del: QF.weak_case_cong)
show ?thesis using pi dp_cases notTF
proof(cases)
assume "?dp = T \<or> ?dp = F"
then show ?thesis
using pi dp_cases
by (cases "?dp") auto
next
assume "\<not> (?dp = T \<or> ?dp = F)"
then show ?thesis using pi dp_cases notTF
by (cases ?dp) auto
qed
qed
qed
(* correctness theorem for explode_disj *)
lemma explode_disj_corr:
assumes qfp: "isqfree p"
shows "(\<exists> x \<in> set xs. qinterp (a#ats) (subst_p x p)) =
(qinterp (a#ats) (explode_disj(xs,p)))" (is "(\<exists> x \<in> set xs. ?P x) = (?DP a xs )")
using qfp
proof (induct xs)
case Nil show ?case by simp
next
case (Cons y ys)
have "(\<exists> x \<in> set (y#ys). ?P x) = (?P y \<or> (\<exists> x\<in> set ys. ?P x))"
by auto
also have "\<dots> = (?P y \<or> ?DP a ys)" using "Cons.hyps" qfp by auto
also have "\<dots> = ?DP a (y#ys)" using explode_disj_disj[OF qfp] by auto
finally show ?case by simp
qed
(* explode_disj preserves independence on Var 0*)
lemma explode_disj_novar0:
assumes nov0xs: "\<forall>x \<in> set xs. novar0I x"
and qfp: "isqfree p"
shows "novar0 (explode_disj (xs,p))"
using nov0xs qfp
proof (induct xs, auto simp add: Let_def)
case (goal1 a as)
let ?q = "subst_p a p"
let ?qs = "psimpl ?q"
have "?qs = T \<or> ?qs = F \<or> (?qs \<noteq> T \<or> ?qs \<noteq> F)" by simp
moreover
{ assume "?qs = T" then have ?case by simp }
moreover
{ assume "?qs = F" then have ?case by simp }
moreover
{
assume qsnTF: "?qs \<noteq> T \<and> ?qs \<noteq> F"
let ?r = "explode_disj (as,p)"
have nov0qs: "novar0 ?qs"
using prems
by (auto simp add: psimpl_novar0 subst_p_novar0)
have "?r = T \<or> ?r = F \<or> (?r \<noteq> T \<or> ?r \<noteq> F)" by simp
moreover
{ assume "?r = T" then have ?case by (cases ?qs) auto }
moreover
{ assume "?r = F" then have ?case using nov0qs by (cases ?qs, auto) }
moreover
{ assume "?r \<noteq> T \<and> ?r \<noteq> F" then have ?case using nov0qs prems qsnTF
by (cases ?qs, auto simp add: Let_def) (cases ?r,auto)+
}
ultimately have ?case by blast
}
ultimately show ?case by blast
qed
(* Some simple lemmas used for technical reasons *)
lemma eval_Or_cases:
"qinterp (a#ats) (case f of
T \<Rightarrow> T
| F \<Rightarrow> g
| _ \<Rightarrow> (case g of
T \<Rightarrow> T
| F \<Rightarrow> f
| _ \<Rightarrow> Or f g)) = (qinterp (a#ats) f \<or> qinterp (a#ats) g)"
proof-
let ?result = "
(case f of
T \<Rightarrow> T
| F \<Rightarrow> g
| _ \<Rightarrow> (case g of
T \<Rightarrow> T
| F \<Rightarrow> f
| _ \<Rightarrow> Or f g))"
have "f = T \<or> f = F \<or> (f \<noteq> T \<and> f\<noteq> F)" by auto
moreover
{
assume fT: "f = T"
then have ?thesis by auto
}
moreover
{
assume "f=F"
then have ?thesis by auto
}
moreover
{
assume fnT: "f\<noteq>T"
and fnF: "f\<noteq>F"
have "g = T \<or> g = F \<or> (g \<noteq> T \<and> g\<noteq> F)" by auto
moreover
{
assume "g=T"
then have ?thesis using fnT fnF by (cases f, auto)
}
moreover
{
assume "g=F"
then have ?thesis using fnT fnF by (cases f, auto)
}
moreover
{
assume gnT: "g\<noteq>T"
and gnF: "g\<noteq>F"
then have "?result = (case g of
T \<Rightarrow> T
| F \<Rightarrow> f
| _ \<Rightarrow> Or f g)"
using fnT fnF
by (cases f, auto)
also have "\<dots> = Or f g"
using gnT gnF
by (cases g, auto)
finally have "?result = Or f g" by simp
then
have ?thesis by simp
}
ultimately have ?thesis by blast
}
ultimately show ?thesis by blast
qed
lemma or_case_novar0:
assumes fnTF: "f \<noteq> T \<and> f \<noteq> F"
and gnTF: "g \<noteq> T \<and> g \<noteq> F"
and f0: "novar0 f"
and g0: "novar0 g"
shows "novar0
(case f of T \<Rightarrow> T | F \<Rightarrow> g
| _ \<Rightarrow> (case g of T \<Rightarrow> T | F \<Rightarrow> f | _ \<Rightarrow> Or f g))"
using fnTF gnTF f0 g0
by (cases f, auto) (cases g, auto)+
(* An implementation of sets trough lists *)
constdefs list_insert :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list"
"list_insert x xs \<equiv> (if x mem xs then xs else x#xs)"
lemma list_insert_set: "set (list_insert x xs) = set (x#xs)"
by(induct xs) (auto simp add: list_insert_def)
consts list_union :: "('a list \<times> 'a list) \<Rightarrow> 'a list"
recdef list_union "measure (\<lambda>(xs,ys). length xs)"
"list_union ([], ys) = ys"
"list_union (xs, []) = xs"
"list_union (x#xs,ys) = list_insert x (list_union (xs,ys))"
lemma list_union_set: "set (list_union(xs,ys)) = set (xs@ys)"
by(induct xs ys rule: list_union.induct, auto simp add:list_insert_set)
consts list_set ::"'a list \<Rightarrow> 'a list"
primrec
"list_set [] = []"
"list_set (x#xs) = list_insert x (list_set xs)"
lemma list_set_set: "set xs = set (list_set xs)"
by (induct xs) (auto simp add: list_insert_set)
consts iupto :: "int \<times> int \<Rightarrow> int list"
recdef iupto "measure (\<lambda> (i,j). nat (j - i +1))"
"iupto(i,j) = (if j<i then [] else (i#(iupto(i+1,j))))"
(* correctness theorem for iupto *)
lemma iupto_set: "set (iupto(i,j)) = {i .. j}"
proof(induct rule: iupto.induct)
case (1 a b)
show ?case
using prems by (simp add: simp_from_to)
qed
consts all_sums :: "int \<times> intterm list \<Rightarrow> intterm list"
recdef all_sums "measure (\<lambda>(i,is). length is)"
"all_sums (j,[]) = []"
"all_sums (j,i#is) = (map (\<lambda>x. lin_add (i,(Cst x))) (iupto(1,j))@(all_sums (j,is)))"
(* all_sums preserves independence on Var 0*)
lemma all_sums_novar0:
assumes nov0xs: "\<forall> x\<in> set xs. novar0I x"
and linxs: "\<forall> x\<in> set xs. islinintterm x "
shows "\<forall> x\<in> set (all_sums (d,xs)). novar0I x"
using nov0xs linxs
proof(induct d xs rule: all_sums.induct)
case 1 show ?case by simp
next
case (2 j a as)
have lina: "islinintterm a" using "2.prems" by auto
have nov0a: "novar0I a" using "2.prems" by auto
let ?ys = "map (\<lambda>x. lin_add (a,(Cst x))) (iupto(1,j))"
have nov0ys: "\<forall> y\<in> set ?ys. novar0I y"
proof-
have linx: "\<forall> x \<in> set (iupto(1,j)). islinintterm (Cst x)" by simp
have nov0x: "\<forall> x \<in> set (iupto(1,j)). novar0I (Cst x)" by simp
with nov0a lina linx have "\<forall> x\<in> set (iupto(1,j)). novar0I (lin_add (a,Cst x))"
by (simp add: lin_add_novar0)
then show ?thesis by auto
qed
from "2.prems"
have linas: "\<forall>u\<in>set as. islinintterm u" by auto
from "2.prems" have nov0as: "\<forall>u\<in>set as. novar0I u" by auto
from "2.hyps" linas nov0as have nov0alls: "\<forall>u\<in>set (all_sums (j, as)). novar0I u" by simp
from nov0alls nov0ys have
cs: "(\<forall> u\<in> set (?ys@ (all_sums (j,as))). novar0I u)"
by (simp only: sym[OF list_all_iff]) auto
have "all_sums(j,a#as) = ?ys@(all_sums(j,as))"
by simp
then
have "?case = (\<forall> x\<in> set (?ys@ (all_sums (j,as))). novar0I x)"
by auto
with cs show ?case by blast
qed
(* correctness theorem for all_sums*)
lemma all_sums_ex:
"(\<exists> j\<in> {1..d}. \<exists> b\<in> (set xs). P (lin_add(b,Cst j))) =
(\<exists> x\<in> set (all_sums (d,xs)). P x)"
proof(induct d xs rule: all_sums.induct)
case (1 a) show ?case by simp
next
case (2 a y ys)
have "(\<exists> x\<in> set (map (\<lambda>x. lin_add (y,(Cst x))) (iupto(1,a))) . P x) =
(\<exists> j\<in> set (iupto(1,a)). P (lin_add(y,Cst j)))"
by auto
also have "\<dots> = (\<exists> j\<in> {1..a}. P (lin_add(y,Cst j)))"
by (simp only : iupto_set)
finally
have dsj1:"(\<exists>j\<in>{1..a}. P (lin_add (y, Cst j))) = (\<exists>x\<in>set (map (\<lambda>x. lin_add (y, Cst x)) (iupto (1, a))). P x)" by simp
from prems have "(\<exists> j\<in> {1..a}. \<exists> b\<in> (set (y#ys)). P (lin_add(b,Cst j))) =
((\<exists> j\<in> {1..a}. P (lin_add(y,Cst j))) \<or> (\<exists> j\<in> {1..a}. \<exists> b \<in> set ys. P (lin_add(b,Cst j))))" by auto
also
have " \<dots> = ((\<exists> j\<in> {1..a}. P (lin_add(y,Cst j))) \<or> (\<exists> x\<in> set (all_sums(a, ys)). P x))" using prems by simp
also have "\<dots> = ((\<exists>x\<in>set (map (\<lambda>x. lin_add (y, Cst x)) (iupto (1, a))). P x) \<or> (\<exists>x\<in>set (all_sums (a, ys)). P x))" using dsj1 by simp
also have "\<dots> = (\<exists> x\<in> (set (map (\<lambda>x. lin_add (y, Cst x)) (iupto (1, a)))) \<union> (set (all_sums(a, ys))). P x)" by blast
finally show ?case by simp
qed
(* explode_minf (p,B) assumes that p is unified and B = bset p, it computes the rhs of cooper_mi_eq*)
consts explode_minf :: "(QF \<times> intterm list) \<Rightarrow> QF"
recdef explode_minf "measure size"
"explode_minf (q,B) =
(let d = divlcm q;
pm = minusinf q;
dj1 = explode_disj ((map Cst (iupto (1, d))),pm)
in (case dj1 of
T \<Rightarrow> T
| F \<Rightarrow> explode_disj (all_sums (d,B),q)
| _ \<Rightarrow> (let dj2 = explode_disj (all_sums (d,B),q)
in ( case dj2 of
T \<Rightarrow> T
| F \<Rightarrow> dj1
| _ \<Rightarrow> Or dj1 dj2))))"
(* The result of the rhs of cooper's theorem doese not depend on Var 0*)
lemma explode_minf_novar0:
assumes unifp : "isunified p"
and bst: "set (bset p) = set B"
shows "novar0 (explode_minf (p,B))"
proof-
let ?d = "divlcm p"
let ?pm = "minusinf p"
let ?dj1 = "explode_disj (map Cst (iupto(1,?d)),?pm)"
have qfpm: "isqfree ?pm" using unified_islinform[OF unifp] minusinf_qfree by simp
have dpos: "?d >0" using unified_islinform[OF unifp] divlcm_pos by simp
have "\<forall> x\<in> set (map Cst (iupto(1,?d))). novar0I x" by auto
then have dj1_nov0: "novar0 ?dj1" using qfpm explode_disj_novar0 by simp
let ?dj2 = "explode_disj (all_sums (?d,B),p)"
have
bstlin: "\<forall>b\<in>set B. islinintterm b"
using bset_lin[OF unifp] bst
by simp
have bstnov0: "\<forall>b\<in>set B. novar0I b"
using bst bset_novar0[OF unifp] by simp
have allsnov0: "\<forall>x\<in>set (all_sums(?d,B)). novar0I x "
by (simp add:all_sums_novar0[OF bstnov0 bstlin] )
then have dj2_nov0: "novar0 ?dj2"
using explode_disj_novar0 unified_isqfree[OF unifp] bst by simp
have "?dj1 = T \<or> ?dj1 = F \<or> (?dj1 \<noteq> T \<and> ?dj1 \<noteq> F)" by auto
moreover
{ assume "?dj1 = T" then have ?thesis by simp }
moreover
{ assume "?dj1 = F" then have ?thesis using bst dj2_nov0 by (simp add: Let_def)}
moreover
{
assume dj1nFT:"?dj1 \<noteq> T \<and> ?dj1 \<noteq> F"
have "?dj2 = T \<or> ?dj2 = F \<or> (?dj2 \<noteq> T \<and> ?dj2 \<noteq> F)" by auto
moreover
{ assume "?dj2 = T" then have ?thesis by (cases ?dj1) simp_all }
moreover
{ assume "?dj2 = F" then have ?thesis using dj1_nov0 bst
by (cases ?dj1) (simp_all add: Let_def)}
moreover
{
assume dj2_nTF:"?dj2 \<noteq> T \<and> ?dj2 \<noteq> F"
let ?res = "\<lambda>f. \<lambda>g. (case f of T \<Rightarrow> T | F \<Rightarrow> g
| _ \<Rightarrow> (case g of T \<Rightarrow> T| F \<Rightarrow> f| _ \<Rightarrow> Or f g))"
have expth: "explode_minf (p,B) = ?res ?dj1 ?dj2"
by (simp add: Let_def del: iupto.simps split del: split_if
cong del: QF.weak_case_cong)
then have ?thesis
using prems or_case_novar0 [OF dj1nFT dj2_nTF dj1_nov0 dj2_nov0]
by (simp add: Let_def del: iupto.simps cong del: QF.weak_case_cong)
}
ultimately have ?thesis by blast
}
ultimately show ?thesis by blast
qed
(* explode_minf computes the rhs of cooper's thm*)
lemma explode_minf_corr:
assumes unifp : "isunified p"
and bst: "set (bset p) = set B"
shows "(\<exists> x . qinterp (x#ats) p) = (qinterp (a#ats) (explode_minf (p,B)))"
(is "(\<exists> x. ?P x) = (?EXP a p)")
proof-
let ?d = "divlcm p"
let ?pm = "minusinf p"
let ?dj1 = "explode_disj (map Cst (iupto(1,?d)),?pm)"
have qfpm: "isqfree ?pm" using unified_islinform[OF unifp] minusinf_qfree by simp
have nnfp: "isnnf p" by (rule unified_isnnf[OF unifp])
have "(\<exists>j\<in>{1..?d}. qinterp (j # ats) (minusinf p))
= (\<exists>j\<in> set (iupto(1,?d)). qinterp (j#ats) (minusinf p))"
(is "(\<exists> j\<in> {1..?d}. ?QM j) = \<dots>")
by (simp add: sym[OF iupto_set] )
also
have "\<dots> =(\<exists>j\<in> set (iupto(1,?d)). qinterp ((I_intterm (a#ats) (Cst j))#ats) (minusinf p))"
by simp
also have
"\<dots> = (\<exists>j\<in> set (map Cst (iupto(1,?d))). qinterp ((I_intterm (a#ats) j)#ats) (minusinf p))" by simp
also have
"\<dots> =
(\<exists>j\<in> set (map Cst (iupto(1,?d))). qinterp (a#ats) (subst_p j (minusinf p)))"
by (simp add: subst_p_corr[OF qfpm])
finally have dj1_thm:
"(\<exists> j\<in> {1..?d}. ?QM j) = (qinterp (a#ats) ?dj1)"
by (simp only: explode_disj_corr[OF qfpm])
let ?dj2 = "explode_disj (all_sums (?d,B),p)"
have
bstlin: "\<forall>b\<in>set B. islinintterm b"
using bst by (simp add: bset_lin[OF unifp])
have bstnov0: "\<forall>b\<in>set B. novar0I b"
using bst by (simp add: bset_novar0[OF unifp])
have allsnov0: "\<forall>x\<in>set (all_sums(?d,B)). novar0I x "
by (simp add:all_sums_novar0[OF bstnov0 bstlin] )
have "(\<exists> j\<in> {1..?d}. \<exists> b\<in> set B. ?P (I_intterm (a#ats) b + j)) =
(\<exists> j\<in> {1..?d}. \<exists> b\<in> set B. ?P (I_intterm (a#ats) (lin_add(b,Cst j))))"
using bst by (auto simp add: lin_add_corr bset_lin[OF unifp])
also have "\<dots> = (\<exists> x \<in> set (all_sums (?d, B)). ?P (I_intterm (a#ats) x))"
by (simp add: all_sums_ex[where P="\<lambda> t. ?P (I_intterm (a#ats) t)"])
finally
have "(\<exists> j\<in> {1..?d}. \<exists> b\<in> set B. ?P (I_intterm (a#ats) b + j)) =
(\<exists> x \<in> set (all_sums (?d, B)). qinterp (a#ats) (subst_p x p))"
using allsnov0 prems linform_isqfree unified_islinform[OF unifp]
by (simp add: all_sums_ex subst_p_corr)
also have "\<dots> = (qinterp (a#ats) ?dj2)"
using linform_isqfree unified_islinform[OF unifp]
by (simp add: explode_disj_corr)
finally have dj2th:
"(\<exists> j\<in> {1..?d}. \<exists> b\<in> set B. ?P (I_intterm (a#ats) b + j)) =
(qinterp (a#ats) ?dj2)" by simp
let ?result = "\<lambda>f. \<lambda>g.
(case f of
T \<Rightarrow> T
| F \<Rightarrow> g
| _ \<Rightarrow> (case g of
T \<Rightarrow> T
| F \<Rightarrow> f
| _ \<Rightarrow> Or f g))"
have "?EXP a p = qinterp (a#ats) (?result ?dj1 ?dj2)"
by (simp only: explode_minf.simps Let_def)
also
have "\<dots> = (qinterp (a#ats) ?dj1 \<or> qinterp (a#ats) ?dj2)"
by (rule eval_Or_cases[where f="?dj1" and g="?dj2" and a="a" and ats="ats"])
also
have "\<dots> = ((\<exists> j\<in> {1..?d}. ?QM j) \<or>
(\<exists> j\<in> {1..?d}. \<exists> b\<in> set B. ?P (I_intterm (a#ats) b + j)))"
by (simp add: dj1_thm dj2th)
also
have "\<dots> = (\<exists> x. ?P x)"
using bst sym[OF cooper_mi_eq[OF unifp]] by simp
finally show ?thesis by simp
qed
lemma explode_minf_corr2:
assumes unifp : "isunified p"
and bst: "set (bset p) = set B"
shows "(qinterp ats (QEx p)) = (qinterp ats (decrvars(explode_minf (p,B))))"
(is "?P = (?Qe p)")
proof-
have "?P = (\<exists>x. qinterp (x#ats) p)" by simp
also have "\<dots> = (qinterp (a # ats) (explode_minf (p,B)))"
using unifp bst explode_minf_corr by simp
finally have ex: "?P = (qinterp (a # ats) (explode_minf (p,B)))" .
have nv0: "novar0 (explode_minf (p,B))"
by (rule explode_minf_novar0[OF unifp])
show ?thesis
using qinterp_novar0[OF nv0] ex by simp
qed
(* An implementation of cooper's method for both plus/minus/infinity *)
(* unify the formula *)
constdefs unify:: "QF \<Rightarrow> (QF \<times> intterm list)"
"unify p \<equiv>
(let q = unitycoeff p;
B = list_set(bset q);
A = list_set (aset q)
in
if (length B \<le> length A)
then (q,B)
else (mirror q, map lin_neg A))"
(* unify behaves like unitycoeff *)
lemma unify_ex:
assumes linp: "islinform p"
shows "qinterp ats (QEx p) = qinterp ats (QEx (fst (unify p)))"
proof-
have "length (list_set(bset (unitycoeff p))) \<le> length (list_set (aset (unitycoeff p))) \<or> length (list_set(bset (unitycoeff p))) > length (list_set (aset (unitycoeff p)))" by arith
moreover
{
assume "length (list_set(bset (unitycoeff p))) \<le> length (list_set (aset (unitycoeff p)))"
then have "fst (unify p) = unitycoeff p" using unify_def by (simp add: Let_def)
then have ?thesis using unitycoeff_corr[OF linp]
by simp
}
moreover
{
assume "length (list_set(bset (unitycoeff p))) > length (list_set (aset (unitycoeff p)))"
then have unif: "fst(unify p) = mirror (unitycoeff p)"
using unify_def by (simp add: Let_def)
let ?q ="unitycoeff p"
have unifq: "isunified ?q" by(rule unitycoeff_unified[OF linp])
have linq: "islinform ?q" by (rule unified_islinform[OF unifq])
have "qinterp ats (QEx ?q) = qinterp ats (QEx (mirror ?q))"
by (rule mirror_ex2[OF unifq])
moreover have "qinterp ats (QEx p) = qinterp ats (QEx ?q)"
using unitycoeff_corr linp by simp
ultimately have ?thesis using prems unif by simp
}
ultimately show ?thesis by blast
qed
(* unify's result is a unified formula *)
lemma unify_unified:
assumes linp: "islinform p"
shows "isunified (fst (unify p))"
using linp unitycoeff_unified mirror_unified unify_def unified_islinform
by (auto simp add: Let_def)
(* unify preserves quantifier-freeness*)
lemma unify_qfree:
assumes linp: "islinform p"
shows "isqfree (fst(unify p))"
using linp unify_unified unified_isqfree by simp
lemma unify_bst:
assumes linp: " islinform p"
and unif: "unify p = (q,B)"
shows "set B = set (bset q)"
proof-
let ?q = "unitycoeff p"
let ?a = "aset ?q"
let ?b = "bset ?q"
let ?la = "list_set ?a"
let ?lb = "list_set ?b"
have " length ?lb \<le> length ?la \<or> length ?lb > length ?la" by arith
moreover
{
assume "length ?lb \<le> length ?la"
then
have "unify p = (?q,?lb)"using unify_def prems by (simp add: Let_def)
then
have ?thesis using prems by (simp add: sym[OF list_set_set])
}
moreover
{ assume "length ?lb > length ?la"
have r: "unify p = (mirror ?q,map lin_neg ?la)"using unify_def prems by (simp add: Let_def)
have lin: "\<forall> x\<in> set (bset (mirror ?q)). islinintterm x"
using bset_lin mirror_unified unitycoeff_unified[OF linp] by auto
with r prems aset_eq_bset_mirror lin_neg_idemp unitycoeff_unified linp
have "set B = set (map lin_neg (map lin_neg (bset (mirror (unitycoeff p)))))"
by (simp add: sym[OF list_set_set])
also have "\<dots> = set (map (\<lambda>x. lin_neg (lin_neg x)) (bset (mirror (unitycoeff p))))"
by auto
also have "\<dots> = set (bset (mirror (unitycoeff p)))"
using lin lin_neg_idemp by (auto simp add: map_idI)
finally
have ?thesis using r prems aset_eq_bset_mirror lin_neg_idemp unitycoeff_unified linp
by (simp add: sym[OF list_set_set])}
ultimately show ?thesis by blast
qed
lemma explode_minf_unify_novar0:
assumes linp: "islinform p"
shows "novar0 (explode_minf (unify p))"
proof-
have "\<exists> q B. unify p = (q,B)" by simp
then obtain "q" "B" where qB_def: "unify p = (q,B)" by blast
have unifq: "isunified q" using unify_unified[OF linp] qB_def by simp
have bst: "set B = set (bset q)" using unify_bst linp qB_def by simp
from unifq bst explode_minf_novar0 show ?thesis
using qB_def by simp
qed
lemma explode_minf_unify_corr2:
assumes linp: "islinform p"
shows "qinterp ats (QEx p) = qinterp ats (decrvars(explode_minf(unify p)))"
proof-
have "\<exists> q B. unify p = (q,B)" by simp
then obtain "q" "B" where qB_def: "unify p = (q,B)" by blast
have unifq: "isunified q" using unify_unified[OF linp] qB_def by simp
have bst: "set (bset q) = set B" using unify_bst linp qB_def by simp
from explode_minf_corr2[OF unifq bst] unify_ex[OF linp] show ?thesis
using qB_def by simp
qed
(* An implementation of cooper's method *)
constdefs cooper:: "QF \<Rightarrow> QF option"
"cooper p \<equiv> lift_un (\<lambda>q. decrvars(explode_minf (unify q))) (linform (nnf p))"
(* cooper eliminates quantifiers *)
lemma cooper_qfree: "(\<And> q q'. \<lbrakk>isqfree q ; cooper q = Some q'\<rbrakk> \<Longrightarrow> isqfree q')"
proof-
fix "q" "q'"
assume qfq: "isqfree q"
and qeq: "cooper q = Some q'"
from qeq have "\<exists>p. linform (nnf q) = Some p"
by (cases "linform (nnf q)") (simp_all add: cooper_def)
then obtain "p" where p_def: "linform (nnf q) = Some p" by blast
have linp: "islinform p" using p_def linform_lin nnf_isnnf qfq
by auto
have nnfq: "isnnf (nnf q)" using nnf_isnnf qfq by simp
then have nnfp: "isnnf p" using linform_nnf[OF nnfq] p_def by auto
have qfp: "isqfree p" using linp linform_isqfree by simp
have "cooper q = Some (decrvars(explode_minf (unify p)))" using p_def
by (simp add: cooper_def del: explode_minf.simps)
then have "q' = decrvars (explode_minf (unify p))" using qeq by simp
with linp qfp nnfp unify_unified unify_qfree unified_islinform
show "isqfree q'"
using novar0_qfree explode_minf_unify_novar0 decrvars_qfree
by simp
qed
(* cooper preserves semantics *)
lemma cooper_corr: "(\<And> q q' ats. \<lbrakk>isqfree q ; cooper q = Some q'\<rbrakk> \<Longrightarrow> (qinterp ats (QEx q)) = (qinterp ats q'))" (is "\<And> q q' ats. \<lbrakk> _ ; _ \<rbrakk> \<Longrightarrow> (?P ats (QEx q) = ?P ats q')")
proof-
fix "q" "q'" "ats"
assume qfq: "isqfree q"
and qeq: "cooper q = Some q'"
from qeq have "\<exists>p. linform (nnf q) = Some p"
by (cases "linform (nnf q)") (simp_all add: cooper_def)
then obtain "p" where p_def: "linform (nnf q) = Some p" by blast
have linp: "islinform p" using p_def linform_lin nnf_isnnf qfq by auto
have qfp: "isqfree p" using linp linform_isqfree by simp
have nnfq: "isnnf (nnf q)" using nnf_isnnf qfq by simp
then have nnfp: "isnnf p" using linform_nnf[OF nnfq] p_def by auto
have "\<forall> ats. ?P ats q = ?P ats (nnf q)" using nnf_corr qfq by auto
then have qeqp: "\<forall> ats. ?P ats q = ?P ats p"
using linform_corr p_def nnf_isnnf qfq
by auto
have "cooper q = Some (decrvars (explode_minf (unify p)))" using p_def
by (simp add: cooper_def del: explode_minf.simps)
then have decr: "q' = decrvars(explode_minf (unify p))" using qeq by simp
have eqq:"?P ats (QEx q) = ?P ats (QEx p)" using qeqp by auto
with decr explode_minf_unify_corr2 unified_islinform unify_unified linp
show "?P ats (QEx q) = ?P ats q'" by simp
qed
(* A decision procedure for Presburger Arithmetics *)
constdefs pa:: "QF \<Rightarrow> QF option"
"pa p \<equiv> lift_un psimpl (qelim(cooper, p))"
lemma psimpl_qfree: "isqfree p \<Longrightarrow> isqfree (psimpl p)"
apply(induct p rule: isqfree.induct)
apply(auto simp add: Let_def measure_def inv_image_def)
apply (simp_all cong del: QF.weak_case_cong add: Let_def)
apply (case_tac "psimpl p", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl p", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl p", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl p", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl q", auto)
apply (case_tac "psimpl p", auto)
apply (case_tac "lift_bin (\<lambda>x y. lin_add (x, lin_neg y), linearize y,
linearize z)", auto)
apply (case_tac "a",auto)
apply (case_tac "lift_bin (\<lambda>x y. lin_add (x, lin_neg y), linearize ac,
linearize ad)", auto)
apply (case_tac "a",auto)
apply (case_tac "ae", auto)
apply (case_tac "linearize af", auto)
by (case_tac "a", auto)
(* pa eliminates quantifiers *)
theorem pa_qfree: "\<And> p'. pa p = Some p' \<Longrightarrow> isqfree p'"
proof(simp only: pa_def)
fix "p'"
assume qep: "lift_un psimpl (qelim (cooper, p)) = Some p'"
then have "\<exists> q. qelim (cooper, p) = Some q"
by (cases "qelim(cooper, p)") auto
then obtain "q" where q_def: "qelim (cooper, p) = Some q" by blast
have "\<And>q q'. \<lbrakk>isqfree q; cooper q = Some q'\<rbrakk> \<Longrightarrow> isqfree q'" using cooper_qfree by blast
with q_def
have "isqfree q" using qelim_qfree by blast
then have "isqfree (psimpl q)" using psimpl_qfree
by auto
then show "isqfree p'"
using prems
by simp
qed
(* pa preserves semantics *)
theorem pa_corr:
"\<And> p'. pa p = Some p' \<Longrightarrow> (qinterp ats p = qinterp ats p')"
proof(simp only: pa_def)
fix "p'"
assume qep: "lift_un psimpl (qelim(cooper, p)) = Some p'"
then have "\<exists> q. qelim (cooper, p) = Some q"
by (cases "qelim(cooper, p)") auto
then obtain "q" where q_def: "qelim (cooper, p) = Some q" by blast
have cp1:"\<And>q q' ats.
\<lbrakk>isqfree q; cooper q = Some q'\<rbrakk> \<Longrightarrow> qinterp ats (QEx q) = qinterp ats q'"
using cooper_corr by blast
moreover have cp2: "\<And>q q'. \<lbrakk>isqfree q; cooper q = Some q'\<rbrakk> \<Longrightarrow> isqfree q'"
using cooper_qfree by blast
ultimately have "qinterp ats p = qinterp ats q" using qelim_corr qep psimpl_corr q_def
by blast
then have "qinterp ats p = qinterp ats (psimpl q)" using psimpl_corr q_def
by auto
then show "qinterp ats p = qinterp ats p'" using prems
by simp
qed
lemma [code]: "linearize (Mult i j) =
(case linearize i of
None \<Rightarrow> None
| Some li \<Rightarrow> (case li of
Cst b \<Rightarrow> (case linearize j of
None \<Rightarrow> None
| (Some lj) \<Rightarrow> Some (lin_mul(b,lj)))
| _ \<Rightarrow> (case linearize j of
None \<Rightarrow> None
| (Some lj) \<Rightarrow> (case lj of
Cst b \<Rightarrow> Some (lin_mul (b,li))
| _ \<Rightarrow> None))))"
by (simp add: measure_def inv_image_def)
lemma [code]: "psimpl (And p q) =
(let p'= psimpl p
in (case p' of
F \<Rightarrow> F
|T \<Rightarrow> psimpl q
| _ \<Rightarrow> let q' = psimpl q
in (case q' of
F \<Rightarrow> F
| T \<Rightarrow> p'
| _ \<Rightarrow> (And p' q'))))"
by (simp add: measure_def inv_image_def)
lemma [code]: "psimpl (Or p q) =
(let p'= psimpl p
in (case p' of
T \<Rightarrow> T
| F \<Rightarrow> psimpl q
| _ \<Rightarrow> let q' = psimpl q
in (case q' of
T \<Rightarrow> T
| F \<Rightarrow> p'
| _ \<Rightarrow> (Or p' q'))))"
by (simp add: measure_def inv_image_def)
lemma [code]: "psimpl (Imp p q) =
(let p'= psimpl p
in (case p' of
F \<Rightarrow> T
|T \<Rightarrow> psimpl q
| NOT p1 \<Rightarrow> let q' = psimpl q
in (case q' of
F \<Rightarrow> p1
| T \<Rightarrow> T
| _ \<Rightarrow> (Or p1 q'))
| _ \<Rightarrow> let q' = psimpl q
in (case q' of
F \<Rightarrow> NOT p'
| T \<Rightarrow> T
| _ \<Rightarrow> (Imp p' q'))))"
by (simp add: measure_def inv_image_def)
declare zdvd_iff_zmod_eq_0 [code]
(*
generate_code ("presburger.ML") test = "pa"
use "rcooper.ML"
oracle rpresburger_oracle ("term") = RCooper.rpresburger_oracle
use "rpresbtac.ML"
setup RPresburger.setup
*)
end