theory LiveDemo02
  imports 
    Main
begin

section \<open>Eigenvariable Condition\<close>

lemma "\<forall> y. y = x"
proof (rule allI)
  fix y
  show "y = x" 
    oops

lemma "\<forall> y. y = x"
proof (rule allI)
  fix z
  show "z = x" (* we can choose a different name than y *)
    oops

    text \<open>The upcoming examples just show that it is not possible to cheat.
  They are definitely not good style!\<close>

lemma "\<forall> y. y = x"
proof (rule allI)
  fix x
  show "x = x" (* it is not allowed to choose x *)
    oops

lemma "\<forall> y. y = x"
proof (rule allI)
  let ?blue_x = x (* let can be used to abbreviate terms within proofs *)
  fix x 
  show "x = ?blue_x" (* orange x \<noteq> blue x *)
    using refl[of x] refl[of ?blue_x]
    oops

lemma "\<forall> x y. x = y"
proof (rule allI)
  fix x :: 'a
  let ?orange_x = x
  show "\<forall>y. x = y" 
  proof (rule allI)
    fix x  
    show "?orange_x = x" (* automatic renaming *)
      oops



      section \<open>The rule method (in introduction mode)\<close>

lemma "x < 5 \<Longrightarrow> x < 3 \<and> x < 2" 
proof (rule conjI)
  oops

lemma "\<exists> y. 5 < y"  
proof (rule exI)
  show "5 < 7" 
    oops




    section \<open>Equality of Terms\<close>

    thm refl (* reflexivity of equality: t = t *)

    text \<open>\<alpha>-conversion is implicitly done\<close>

lemma alpha: "(\<forall> x. P x) = (\<forall> y. P y)" by (rule refl)
thm alpha[of "Q x"]
text \<open>\<beta>-reduction "(\<lambda> x. t) s \<longrightarrow>\<beta>  t [ x / s]" is implicitly done\<close>
lemma beta: "(\<lambda> x. P (x + x)) y = P (y + y)" by (rule refl)

text \<open>\<eta>-expansion "f = (\<lambda> x. f x)" if f has function-type 
  is implicitly invoked\<close>
lemma eta: "(\<lambda> x. f x) = f" by (rule refl)


section \<open>Drinker's paradox\<close>

find_theorems (5) "?x + ?y = ?y + ?x" 

lemma drinkers_paradox: "\<exists> p. drinks p \<longrightarrow> (\<forall> x. drinks x)" 
proof - 
  have "\<not> (\<exists> p. \<not> drinks p) \<or> (\<exists> p. \<not> drinks p)" 
    by (rule excluded_middle)
  from this show ?thesis
  proof 
    {
      assume "\<nexists>p. \<not> drinks p "
      from this show ?thesis by auto
    }
    {
      assume *: "\<exists>p. \<not> drinks p" 
      from *
      show ?thesis
      proof 
        fix p
        assume "\<not> drinks p" 
        show ?thesis
        proof 
          show "drinks p \<longrightarrow> (\<forall>x. drinks x)" 
          proof 
            assume "drinks p" 
            from \<open>\<not> drinks p\<close> this
            show "\<forall>x. drinks x" 
              by (rule notE)
          qed
        qed
      qed
    }
  qed
qed

lemma drinkers_paradox_v2: "\<exists> p. drinks p \<longrightarrow> (\<forall> x. drinks x)" 
proof -
  {
    assume "\<nexists>p. \<not> drinks p"
    from this have "\<forall> p. drinks p" by auto
    from this have ?thesis by auto
  }
  from this have case1: "\<nexists>p. \<not> drinks p \<Longrightarrow> ?thesis" by auto
  {
    fix p
    assume "\<not> drinks p" 
    have ?thesis
    proof (intro exI impI allI)
      fix x
      assume "drinks p" 
      from \<open>\<not> drinks p\<close> this
      show "drinks x" 
        by (rule notE)
    qed
  }
  from this have case2: "\<exists>p. \<not> drinks p \<Longrightarrow> ?thesis" by auto
  from case1 case2 show ?thesis by auto
qed


text \<open>Actually the drinker's paradox is so simple, that automation
  can do it on its own.\<close>

lemma drinkers_paradox_v3: "\<exists> p. drinks p \<longrightarrow> (\<forall> x. drinks x)" 
  by auto

end