theory Find
  imports Main
begin

section \<open>Find theorems with @{command find_theorems}\<close>
text \<open>
  Theorems can be searched by name where \<open>*\<close> wildcards are allowed.
  One of the theorems found with the query below is @{thm gauss_sum_nat}.
\<close>
find_theorems name: "gau*"

text \<open>
  You can also search theorems by specifying an arbitrary number of patterns.
  Patterns are allowed to contain wildcards (\<open>*\<close>) constants, schematic variables, and types.
  It is also possible to negate a pattern by prefixing it with a \<open>-\<close>.
  If a negated pattern occurs in a theorem, it will not be considered by the search.
\<close>
find_theorems "finite (?A::'a rel)"
find_theorems "finite _ \<Longrightarrow> _" "insert _ _" -"card _"
find_theorems "finite ?A \<Longrightarrow> finite ?B \<Longrightarrow> _ (?A \<union> ?B)"

text \<open>
  In addition to patterns, we can take the goal state into account to search for theorems.
  The example below uses \<open>intro\<close> to search for introduction rules that solve the current goal.
  For the given goal, @{command find_theorems} finds the lemma @{thm bij_betw_byWitness} which we
  instantiate accordingly.
  Then, we solve the the first two subgoals with @{method simp_all}.
  This leaves us with two subgoals: @{prop \<open>(\<lambda>x. x + 1) ` \<int> \<subseteq> \<int>\<close>} and
  @{prop \<open>(\<lambda>x. x - 1) ` \<int> \<subseteq> \<int>\<close>}.
  Searching with intro returns a lot of theorems since @{verbatim \<open>\<subseteq>\<close>} often occurs in the
  conclusion of theorems.
  To filter out irrelevant theorems, we pass the goal as a pattern with the appropriate wildcards.
  Then, @{command find_theorems} gives us the lemma @{thm image_subsetI} with which we can solve the
  remaining goals.
  In addition to \<open>intro\<close>, there are also \<open>elim\<close>, \<open>dest\<close>, and \<open>solves\<close> which work analogously.
\<close>
lemma "bij_betw (\<lambda>x. x + 1) \<int> \<int>"
  find_theorems intro
  apply(intro bij_betw_byWitness[where ?f'="\<lambda>x. x - 1"])
     apply(simp_all)
  find_theorems intro
  find_theorems intro "_ ` _ \<subseteq> _"
   apply(simp_all add: image_subsetI)
  done

text \<open>
  To search for theorems that simplify a given term, one can pass \<open>simp\<close> and a term to
  @{command find_theorems}.
  In the example below, @{command find_theorems} returns the lemma @{thm rev_rev_ident} with which
  we can rewrite @{term \<open>rev (rev xs)\<close>} to @{term \<open>xs\<close>}.
\<close>

find_theorems simp: "rev (rev _)"

section \<open>Find constants with @{command find_consts}\<close>
text \<open>
  Finding constants (e.g. functions or definitions) can be done with the @{command find_consts}.
  As with @{command find_theorems}, you can search for constants by name as seen below.
\<close>
find_consts name: metric

text \<open>
  Perhaps more useful than searching for constants by name, it is possible to search for them by
  type.
  The default search returns all constants which contain the given type pattern.
  If you are only interested in exact matches, then you can use the \<open>strict\<close> annotation.
  The example below illustrates this behaviour: the first search returns functions
  @{term_type List.replicate} while the second only returns @{term_type List.subseqs}
  (and some functions from @{theory HOL.Quickcheck_Narrowing}).
\<close>
find_consts "'a \<Rightarrow> 'a list"
find_consts strict: "'a \<Rightarrow> 'a list"

text \<open>
  We can also use wildcards and negated patterns.
\<close>
find_consts strict: "_ \<Rightarrow> 'a list \<Rightarrow> _ list"
find_consts strict: "_ \<Rightarrow> 'a list \<Rightarrow> _ list" -"('a \<times> 'b) list"

text \<open>
  Finally, type variables can also have class constraints.
\<close>
find_consts "('a::ord) list \<Rightarrow> ('a::ord) list"

end


(*  Title:      FOL/ex/Quantifiers_Int.thy
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
    Copyright   1991  University of Cambridge
*)

section \<open>First-Order Logic: quantifier examples (intuitionistic version)\<close>

theory Quantifiers_Int
imports IFOL
begin

lemma "(\<forall>x y. P(x,y)) \<longrightarrow> (\<forall>y x. P(x,y))"
  by (tactic "IntPr.fast_tac @{context} 1")

lemma "(\<exists>x y. P(x,y)) \<longrightarrow> (\<exists>y x. P(x,y))"
  by (tactic "IntPr.fast_tac @{context} 1")

\<comment> \<open>Converse is false\<close>
lemma "(\<forall>x. P(x)) \<or> (\<forall>x. Q(x)) \<longrightarrow> (\<forall>x. P(x) \<or> Q(x))"
  by (tactic "IntPr.fast_tac @{context} 1")

lemma "(\<forall>x. P \<longrightarrow> Q(x)) \<longleftrightarrow> (P \<longrightarrow> (\<forall>x. Q(x)))"
  by (tactic "IntPr.fast_tac @{context} 1")

lemma "(\<forall>x. P(x) \<longrightarrow> Q) \<longleftrightarrow> ((\<exists>x. P(x)) \<longrightarrow> Q)"
  by (tactic "IntPr.fast_tac @{context} 1")

text \<open>Some harder ones\<close>

lemma "(\<exists>x. P(x) \<or> Q(x)) \<longleftrightarrow> (\<exists>x. P(x)) \<or> (\<exists>x. Q(x))"
  by (tactic "IntPr.fast_tac @{context} 1")

\<comment> \<open>Converse is false\<close>
lemma "(\<exists>x. P(x) \<and> Q(x)) \<longrightarrow> (\<exists>x. P(x)) \<and> (\<exists>x. Q(x))"
  by (tactic "IntPr.fast_tac @{context} 1")

text \<open>Basic test of quantifier reasoning\<close>

\<comment> \<open>TRUE\<close>
lemma "(\<exists>y. \<forall>x. Q(x,y)) \<longrightarrow> (\<forall>x. \<exists>y. Q(x,y))"
  by (tactic "IntPr.fast_tac @{context} 1")

lemma "(\<forall>x. Q(x)) \<longrightarrow> (\<exists>x. Q(x))"
  by (tactic "IntPr.fast_tac @{context} 1")

text \<open>The following should fail, as they are false!\<close>

lemma "(\<forall>x. \<exists>y. Q(x,y)) \<longrightarrow> (\<exists>y. \<forall>x. Q(x,y))"
  apply (tactic "IntPr.fast_tac @{context} 1")?
  oops

lemma "(\<exists>x. Q(x)) \<longrightarrow> (\<forall>x. Q(x))"
  apply (tactic "IntPr.fast_tac @{context} 1")?
  oops

schematic_goal "P(?a) \<longrightarrow> (\<forall>x. P(x))"
  apply (tactic "IntPr.fast_tac @{context} 1")?
  oops

schematic_goal "(P(?a) \<longrightarrow> (\<forall>x. Q(x))) \<longrightarrow> (\<forall>x. P(x) \<longrightarrow> Q(x))"
  apply (tactic "IntPr.fast_tac @{context} 1")?
  oops

text \<open>Back to things that are provable \dots\<close>

lemma "(\<forall>x. P(x) \<longrightarrow> Q(x)) \<and> (\<exists>x. P(x)) \<longrightarrow> (\<exists>x. Q(x))"
  by (tactic "IntPr.fast_tac @{context} 1")

\<comment> \<open>An example of why exI should be delayed as long as possible\<close>
lemma "(P \<longrightarrow> (\<exists>x. Q(x))) \<and> P \<longrightarrow> (\<exists>x. Q(x))"
  by (tactic "IntPr.fast_tac @{context} 1")

schematic_goal "(\<forall>x. P(x) \<longrightarrow> Q(f(x))) \<and> (\<forall>x. Q(x) \<longrightarrow> R(g(x))) \<and> P(d) \<longrightarrow> R(?a)"
  by (tactic "IntPr.fast_tac @{context} 1")

lemma "(\<forall>x. Q(x)) \<longrightarrow> (\<exists>x. Q(x))"
  by (tactic "IntPr.fast_tac @{context} 1")

text \<open>Some slow ones\<close>

\<comment> \<open>Principia Mathematica *11.53\<close>
lemma "(\<forall>x y. P(x) \<longrightarrow> Q(y)) \<longleftrightarrow> ((\<exists>x. P(x)) \<longrightarrow> (\<forall>y. Q(y)))"
  by (tactic "IntPr.fast_tac @{context} 1")

(*Principia Mathematica *11.55  *)
lemma "(\<exists>x y. P(x) \<and> Q(x,y)) \<longleftrightarrow> (\<exists>x. P(x) \<and> (\<exists>y. Q(x,y)))"
  by (tactic "IntPr.fast_tac @{context} 1")

(*Principia Mathematica *11.61  *)
lemma "(\<exists>y. \<forall>x. P(x) \<longrightarrow> Q(x,y)) \<longrightarrow> (\<forall>x. P(x) \<longrightarrow> (\<exists>y. Q(x,y)))"
  by (tactic "IntPr.fast_tac @{context} 1")

end


(* This Isabelle theory is produced using the TIP tool offered at the following website:
     https://github.com/tip-org/tools
   This file was originally provided as part of TIP benchmark at the following website:
     https://github.com/tip-org/benchmarks
   Yutaka Nagashima at CIIRC, CTU changed the TIP output theory file slightly
   to make it compatible with Isabelle2017.
\:w
   Some proofs were added by Yutaka Nagashima.*)
  theory TIP_regexp_RecAtom
imports "../../Test_Base"
begin

datatype 'a list = nil2 | cons2 "'a" "'a list"

datatype A = X | Y

datatype R
         = Nil | Eps | Atom "A" | Plus "R" "R" | Seq "R" "R" | Star "R"

fun seq :: "R => R => R" where
"seq x y =
   (case x of
      Nil => Nil
      | other =>
          (case y of
             Nil => Nil
             | other =>
                 (case x of
                    Eps => y
                    | other =>
                        (case y of
                           Eps => x
                           | other => Seq x y))))"

fun plus :: "R => R => R" where
"plus x y =
   (case x of
      Nil => y
      | other =>
          (case y of
             Nil => x
             | other => Plus x y))"

fun eqA :: "A => A => bool" where
"eqA (X) (X) = True"
| "eqA (X) (Y) = False"
| "eqA (Y) (X) = False"
| "eqA (Y) (Y) = True"

fun eqList :: "A list => A list => bool" where
"eqList (nil2) (nil2) = True"
| "eqList (nil2) (cons2 z x2) = False"
| "eqList (cons2 x3 xs) (nil2) = False"
| "eqList (cons2 x3 xs) (cons2 y2 ys) =
     ((eqA x3 y2) & (eqList xs ys))"

fun eps :: "R => bool" where
"eps x =
   (case x of
      Eps => True
      | Plus p q => ((eps p) | (eps q))
      | Seq r q2 => ((eps r) & (eps q2))
      | Star y => True
      | other => False)"

fun epsR :: "R => R" where
"epsR x = (if eps x then Eps else Nil)"

fun step :: "R => A => R" where
"step x y =
   (case x of
      Atom a => (if eqA a y then Eps else Nil)
      | Plus p q => plus (step p y) (step q y)
      | Seq r q2 => plus (seq (step r y) q2) (seq (epsR r) (step q2 y))
      | Star p2 => seq (step p2 y) x
      | other => Nil)"

fun recognise :: "R => A list => bool" where
"recognise x (nil2) = eps x"
| "recognise x (cons2 z xs) = recognise (step x z) xs"

theorem property0 :
  "((recognise (Atom a) s) = (eqList s (cons2 a (nil2))))"
  oops

end


theory ZadatakBiH
  imports Complex_Main
begin
(*Pravimo funkcije koje izracunavaju vrednost izraza sa nekim izabranim brojevima*)
fun racunanjeIzrazaA::"real \<Rightarrow> real \<Rightarrow> real \<Rightarrow> real" where
"racunanjeIzrazaA a b c = ((1+a*b) / (a-b)) * ((1+b*c)/(b-c)) + ((1+b*c) / (b-c)) * ((1+c*a)/(c-a)) + ((1+c*a) / (c-a)) * ((1+a*b)/(a-b))"

fun racunanjeIzrazaB::"real \<Rightarrow> real \<Rightarrow> real \<Rightarrow> real" where
"racunanjeIzrazaB a b c = ((1-a*b) / (a-b)) * ((1-b*c)/(b-c)) + ((1-b*c) / (b-c)) * ((1-c*a)/(c-a)) + ((1-c*a) / (c-a)) * ((1-a*b)/(a-b))"

(*Proveravamo koja je vrednost koji vracaju i dobijamo za razlicite brojeve 1 (-1) a za iste brojeve 0*)
value "racunanjeIzrazaA 1 2 3"

value "racunanjeIzrazaB 1 2 3"

(*sledece dve teoreme pokazuju da za svako a b c koji su medjusobno razliciti funkcije vracaju 1 odnosno -1*)
lemma shows "\<forall> a::real.\<forall> b::real.\<forall> c::real. a\<noteq>b \<and> a\<noteq>c \<and> b\<noteq>c \<longrightarrow> racunanjeIzrazaA a b c = 1"
  sorry

lemma shows "\<forall> a::real.\<forall> b::real.\<forall> c::real. a\<noteq>b \<and> a\<noteq>c \<and> b\<noteq>c \<longrightarrow> racunanjeIzrazaB a b c = -1"
  sorry

(*zadatak pod b). Postoje neki brojevi a b c za koje ce ova jednakost biti tacna*)
lemma
  shows "\<exists> a::real. \<exists> b::real. \<exists> c::real. a\<noteq>b \<and> a\<noteq>c \<and> b\<noteq>c \<longrightarrow> (1+a\<^sup>2*b\<^sup>2)/(a-b)\<^sup>2 + (1+b\<^sup>2*c\<^sup>2)/(b-c)\<^sup>2 +  (1+c\<^sup>2*a\<^sup>2)/(c-a)\<^sup>2 \<ge> (3::real) / (2::real)"
  by blast
(*postavlja se pitanje da li se moze umesto znaka \<ge> staviti znak jednakosti? Isabelle je mogao ovo da dokaze te je odgovor da.*)
lemma
  shows "\<exists> a::real. \<exists> b::real. \<exists> c::real. a\<noteq>b \<and> a\<noteq>c \<and> b\<noteq>c \<longrightarrow> (1+a\<^sup>2*b\<^sup>2)/(a-b)\<^sup>2 + (1+b\<^sup>2*c\<^sup>2)/(b-c)\<^sup>2 +  (1+c\<^sup>2*a\<^sup>2)/(c-a)\<^sup>2 =(3::real) / (2::real)"
  by blast

end