theory Demo03
imports Main
begin

section{* Propositional logic *}

subsection{* Basic rules *}

text{* \<and> *}
thm conjI conjE 

text{* \<or> *}
thm disjI1 disjI2 disjE

text{* \<longrightarrow> *}
thm impI impE


subsection{* Examples *}

text{* a simple backward step: *}
lemma "A \<and> B" thm conjI
  apply(rule conjI)
  oops

text{* a simple backward proof: *}
lemma "B \<and> A \<longrightarrow> A \<and> B"
  apply(rule impI)
  apply(erule conjE)
  apply(rule conjI)
   apply(assumption)
  apply(assumption)
  done

lemma "A \<or> B \<longrightarrow> B \<or> A"
  apply (rule impI)
  apply (erule disjE)
   apply (rule disjI2)
   apply assumption
  apply (rule disjI1)
  apply assumption
  done

lemma "\<lbrakk> A \<longrightarrow> B; B \<longrightarrow> C \<rbrakk> \<Longrightarrow> A \<longrightarrow> C"
  apply (rule impI)
  apply (erule impE)
   apply assumption
  apply (erule impE)
   apply assumption
  apply assumption
  done


thm notI notE 

lemma "\<not>A \<or> \<not>B \<Longrightarrow> \<not>(A \<and> B)"
  apply (rule notI)
  apply (erule disjE)
   apply (erule conjE)
   apply (erule notE) 
   apply assumption
  apply (erule conjE)
  apply (erule notE)
  apply assumption
  done


text{* Explicit backtracking: *}

lemma "\<lbrakk> P \<and> Q; A \<and> B \<rbrakk> \<Longrightarrow> A"
  apply(erule conjE)
  back
  apply(assumption)
  done
text{* Ugly!  Avoid in finished proofs. *}


text{* Implict backtracking: chaining with , *}

lemma "\<lbrakk> P \<and> Q; A \<and> B \<rbrakk> \<Longrightarrow> A"
  apply(erule conjE, assumption)
  done



text {* Case distinctions *}

lemma "P \<or> \<not>P"
  apply (case_tac "P")
  oops
  

thm FalseE

lemma "(\<not>P \<longrightarrow> False) \<longrightarrow> P"
  apply (rule impI)
  apply (case_tac "P")
   apply assumption
  apply (erule impE)
   apply assumption
  apply (erule FalseE)
  done
  
-- ---------------------------------------


subsection {* more rules *}

text{* \<and> *}
thm conjunct1 conjunct2

text{* \<or> *}
thm disjCI  

text{* \<longrightarrow> *}
thm mp

text{* = (iff) *}
thm iffI iffE iffD1 iffD2

text{* Equality *}
thm refl sym trans

text{* \<not> *}
thm notI notE

text{* Contradictions *}
thm FalseE ccontr classical excluded_middle


text{* = (iff) *}
thm iffI iffE iffD1 iffD2

text{* Equality *}
thm refl sym trans


text {* defer and prefer *}
lemma "(A \<or> A) = (A \<and> A)"
  apply (rule iffI)
  defer
  sorry


text{* A warming up exercise: classical propositional logic. *}
lemma Pierce: "((A \<longrightarrow> B) \<longrightarrow> A) \<longrightarrow> A"
  sorry


-- --------------------------------------

section {* Quantifier reasoning *}

text{* A successful proof: *}
lemma "\<forall>x. \<exists>y. x = y" 
apply(rule allI)
apply(rule exI)
apply(rule refl)
done


text{* An unsuccessful proof: *}
lemma "\<exists>y. \<forall>x. x = y"
apply(rule exI)
apply(rule allI)
(* Does not work:
apply(rule refl)
*)
oops

text{* Intro and elim resoning: *}
lemma "\<exists>y. \<forall>x. P x y \<Longrightarrow> \<forall>x. \<exists>y. P x y"
(* the safe rules first: *)
apply(rule allI)
apply(erule exE)
(* now the unsafe ones: *)
apply(rule_tac x=y in exI)
apply(erule_tac x=x in allE)
apply(assumption)
done

text{* What happens if an unsafe rule is tried too early: *}
lemma "\<exists>y. \<forall>x. P x y \<Longrightarrow> \<forall>x. \<exists>y. P x y"
apply(rule allI)
apply(rule exI)
apply(erule exE)
apply(erule allE)
(* doesn't work
apply(assumption)
*)
oops

text {* Instantiation in more detail: *}

text{* Instantiating allE: *}
lemma "\<forall>x. P x \<Longrightarrow> P 37"
thm allE
apply (erule_tac x = "37" in allE)
apply assumption
done

text{* Instantiating exI: *}
lemma "\<exists>n. P (f n) \<Longrightarrow> \<exists>m. P m"
apply(erule exE)
thm exI
apply(rule_tac x = "f n" in exI)
apply assumption
done

text{* Instantiation removes ambiguity: *}
lemma "\<lbrakk> A \<and> B; C \<and> D \<rbrakk> \<Longrightarrow> D"
thm conjE
apply(erule_tac P = "C" in conjE)
(* without instantiation, the wrong one is chosen (first) *)
apply assumption
done


text {* Instantiation with "where" and "of" *}
text {* May not refer to parameters of the goal. *}

thm conjI
thm conjI [of A B]
thm conjI [where Q = "f x"]

lemma "\<forall>x. x = x"
apply (rule allI)
thm refl [where t = x]
(* doesn't work
apply (rule refl [where t = x])
*)
oops

text {* Exercises *}

lemma "\<exists>x. \<forall>y. P x y \<Longrightarrow> \<forall>y. \<exists>x. P x y"
oops

lemma "(\<exists>x. P x) \<longrightarrow> Q \<Longrightarrow> \<forall>x. P x \<longrightarrow> Q" 
oops

lemma "\<exists>x. (P x \<longrightarrow> (\<forall>x. P x))"
oops

-- ----------------------------------------------

text{* Renaming parameters: *}

lemma "\<And>x y z. P x y z"
apply(rename_tac a b)
oops

lemma "\<forall>x. P x \<Longrightarrow> \<forall>x. \<forall>x. P x"
apply(rule allI)
apply(rule allI)
apply(rename_tac X)
apply(erule_tac x=X in allE)
apply assumption
done




text {* Forward reasoning: drule/frule/OF/THEN*}

lemma "A \<and> B \<Longrightarrow> \<not> \<not> A"
thm conjunct1
apply (drule conjunct1)
apply (rule notI)
apply (erule notE)
apply assumption
done


lemma "\<forall>x. P x \<Longrightarrow> P t"
  thm spec
  apply (frule spec)
  apply assumption
  done


thm dvd_add dvd_refl
thm dvd_add [OF dvd_refl]
thm dvd_add [OF dvd_refl dvd_refl]


-- ---------------------------------------------

text {* Epsilon *}

lemma "(\<exists>x. P x) = P (SOME x. P x)"
  apply (rule iffI)
   apply (erule exE)
   apply (rule someI)
   apply assumption
  apply (rule exI)
  apply assumption
  done


text {* Automation *}

lemma "\<forall>x y. P x y \<and> Q x y \<and> R x y"
apply (intro allI conjI)
oops

lemma "\<forall>x y. P x y \<and> Q x y \<and> R x y"
apply clarify
oops

lemma "\<forall>x y. P x y \<and> Q x y \<and> R x y"
apply safe
oops

lemma "\<exists>y. \<forall>x. P x y \<Longrightarrow> \<forall>x. \<exists>y. P x y"
apply blast
done

lemma "\<exists>y. \<forall>x. P x y \<Longrightarrow> \<forall>x. \<exists>y. P x y"
apply fast
done


-- ---------------------------------------------

text {* Attributes *}

definition 
  xor :: "bool \<Rightarrow> bool \<Rightarrow> bool"
  where "xor A B \<equiv> (A \<and> \<not>B) \<or> (\<not>A \<and> B)"

lemma xorI [intro!]:
  "\<lbrakk> \<lbrakk>A; B\<rbrakk> \<Longrightarrow> False; \<not>B \<Longrightarrow> A \<rbrakk> \<Longrightarrow> xor A B"
  apply (unfold xor_def)
  apply blast
  done

lemma xorE:
  "\<lbrakk> xor A B; \<lbrakk>A; \<not>B\<rbrakk> \<Longrightarrow> R; \<lbrakk>\<not>A; B\<rbrakk> \<Longrightarrow> R \<rbrakk> \<Longrightarrow> R"
  apply (unfold xor_def)
  apply blast
  done

lemma "xor A A = False" by (blast elim!: xorE)

declare xorE [elim!]

lemma "xor A B = xor B A" by blast


end