(*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: BSD-2-Clause
 *)

theory word_abs_options imports "AutoCorres.AutoCorres" begin

external_file "word_abs_options.c"
install_C_file "word_abs_options.c"

autocorres [
  ts_rules = nondet,
  unsigned_word_abs = usum2, no_signed_word_abs = isum1
  ] "word_abs_options.c"

context word_abs_options begin

lemma "\<lbrace> \<top> \<rbrace> isum1' (a :: sword32) (b :: sword32) \<lbrace> \<lambda>r _. r = a + b \<rbrace>"
  unfolding isum1'_def
  apply (wp refl)
  done

lemma "\<lbrace> \<top> \<rbrace> isum2' (a :: int) (b :: int) \<lbrace> \<lambda>r _. r = a + b \<rbrace>"
  unfolding isum2'_def
  apply (wp refl)
  done

lemma "\<lbrace> \<top> \<rbrace> usum1' (a :: word32) (b :: word32) \<lbrace> \<lambda>r _. r = a + b \<rbrace>"
  unfolding usum1'_def
  apply (wp refl)
  done

lemma "\<lbrace> \<top> \<rbrace> usum2' (a :: nat) (b :: nat) \<lbrace> \<lambda>r _. r = a + b \<rbrace>"
  unfolding usum2'_def
  apply (wp refl)
  done

end

end


theory Theorem611
  imports Complex_Main LearningTheory
begin

text "This document contains a collection of (mostly failed) attempts at gathering subproofs and
  important lemmata for theorem 6.11. It may help proving the theorem in the future and serves
  no other purpose."

 (*measure_pmf.jensens_inequality*)

lemma "AE x in measure_pmf M. X' x \<in> UNIV"
  by simp

lemma "convex_on UNIV abs"
unfolding convex_on_def
  apply (simp)
  by (metis (mono_tags, hide_lams) abs_mult abs_of_nonneg abs_triangle_ineq add.commute mult.commute)

lemma "integrable (measure_pmf M) abs"
  oops

(*for lemma A.3*)
lemma "measure_pmf.expectation p (abs \<circ> f)
   \<le> infsetsum (\<lambda>i. (a::real) * (Suc i) * (measure_pmf.prob p {x. (abs \<circ> f) x > a * i})) UNIV"
  oops

lemma "abs (infsetsum f A) \<le> infsetsum (abs \<circ> f) A"
  oops

lemma "\<forall>x. f x \<in> {-1<..<1::real} \<Longrightarrow> f \<in> borel_measurable borel"
  oops

lemma "\<forall>x. f x \<in> {-1<..<1::real} \<Longrightarrow> simple_function (measure_pmf M) f"
  oops

lemma "\<forall>x. f x \<in> {-1<..<1} \<Longrightarrow> integrable (measure_pmf M) f"
  oops

lemma "emeasure (measure_pmf M) {(y::real) \<in> space M. id y \<noteq> 0} \<noteq> \<infinity>"
  by simp

lemma "integrable (measure_pmf M) (id::(real\<Rightarrow>real))"
  oops

lemma if_summable: "f abs_summable_on A \<Longrightarrow> (\<lambda>x. if P x then f x else 0) abs_summable_on A"
  by (simp add: abs_summable_on_comparison_test)

lemma "(\<lambda>x. if h x \<noteq> f x then pmf D x else 0) abs_summable_on A"
  using pmf_abs_summable[of "D"] if_summable[of "pmf D"] by auto

lemma exp_to_prob: "measure_pmf.expectation pr (\<lambda>x. if P x then 1::real else 0)
     = measure_pmf.prob pr {x. P x}"
proof -
  have "measure_pmf.expectation pr (\<lambda>x. if P x then 1::real else 0)
      = infsetsum (\<lambda>x. if P x then pmf pr x else 0) UNIV"
    by (smt infsetsum_cong mult_cancel_left2 mult_not_zero pmf_expectation_eq_infsetsum)
  also have "... = ... - infsetsum (\<lambda>x. if P x then pmf pr x else 0) {x. \<not> P x}"
    by (smt infsetsum_all_0 mem_Collect_eq)
  also have "... = infsetsum (\<lambda>x. if P x then pmf pr x else 0) (UNIV - {x. \<not> P x})"
    by (simp add: if_summable infsetsum_Diff pmf_abs_summable)
  also have "... = infsetsum (\<lambda>x. if P x then pmf pr x else 0) {x. P x}"
  proof -
    have "UNIV - {x. \<not> P x} = {x. P x}"
      by blast
    then show ?thesis by auto
  qed
  also have "... = infsetsum (pmf pr) {x. P x}"
    by (smt infsetsum_cong mem_Collect_eq)
  finally show ?thesis
    by (simp add: measure_pmf_conv_infsetsum)
qed

lemma "((g:: 'c \<Rightarrow> real) y) * measure_pmf.expectation D f = measure_pmf.expectation D (\<lambda>x. (g y) * f x)"
   by simp

lemma "measure_pmf.expectation D f - (a::real) = measure_pmf.expectation D (\<lambda>x. f x - a)"
proof -
  have "measure_pmf.expectation D f - (a::real) = (\<Sum>\<^sub>ax. pmf D x * f x) - (\<Sum>\<^sub>ax. pmf D x * a)"
    using pmf_expectation_eq_infsetsum infsetsum_pmf_eq_1
  proof -
    have "\<forall>p. integral\<^sup>L (count_space (UNIV::'c set)) (pmf p) = 1"
      by (metis (no_types) infsetsum_def measure_pmf_UNIV measure_pmf_conv_infsetsum)
    then show ?thesis sorry
  qed
  show ?thesis sorry
qed

lemma assumes "card I > 0"
          and "(\<lambda>x. pmf D x * f x) abs_summable_on UNIV"
  shows stichprobenmittel: "measure_pmf.expectation (Pi_pmf I undefined (\<lambda>_. D)) (\<lambda>S. sum (f \<circ> S) I / card I)
     = measure_pmf.expectation D f"
proof -
(*
  have "measure_pmf.expectation (Pi_pmf I undefined (\<lambda>_. D)) (\<lambda>S. sum (f \<circ> S) I / card I)
      = sum (\<lambda>_.(measure_pmf.expectation D f)) I / card I"
    *)
  have "i\<notin>I \<Longrightarrow> sum (f \<circ> S) (insert i I) / (card I + 1)
      = sum (f \<circ> S) I / (card I + 1) + (f \<circ> S) i / (card I + 1)"
    sorry
   (* by (metis add.commute add_divide_distrib assms card.infinite not_less0 sum.insert_if) *)

  have "measure_pmf.expectation (Pi_pmf (insert i I) undefined (\<lambda>_. D)) (\<lambda>S. sum (f \<circ> S) (insert i I) / (card I + 1))
      = measure_pmf.expectation (Pi_pmf (insert i I) undefined (\<lambda>_. D)) (\<lambda>S. sum (f \<circ> S) I / (card I + 1) + f (S i) / (card I + 1))"

    sorry
    show ?thesis sorry
qed

lemma assumes "card I > 0"
  shows "measure_pmf.expectation (Pi_pmf I undefined (\<lambda>_. D)) (\<lambda>S. sum (\<lambda>i. if h (S i) \<noteq> f (S i) then 1::real else 0) I / card I)
     = measure_pmf.expectation D (\<lambda>x. if h x \<noteq> f x then 1::real else 0)"
  sorry

(*for Jensens*)
lemma "abs (measure_pmf.expectation p f) \<le> measure_pmf.expectation p (abs \<circ> f)"
  using pmf_expectation_eq_infsetsum abs_triangle_ineq sorry

(*Theorem 6.11*)
lemma assumes "set_pmf D \<subseteq> X"
      and "f ` X = Y"
      and "\<delta>\<in>{x.0<x\<and>x<1}"
    shows theorem611: "measure_pmf.prob (Samples m D f) {S. \<forall>h\<in>H. abs(PredErr D f h - TrainErr S {0..<m} h)
                   \<le> (4+sqrt(ln(real(growth (2*m)))))/(\<delta> * sqrt(2*m))} \<ge> 1 - \<delta>"
proof -
  (* replace max with sup? *)
  have "measure_pmf.expectation (Samples m D f) (\<lambda>S. (Max(image (\<lambda>h. abs(PredErr D f h - TrainErr S {0..<m} h)) H)))
        \<le> (4+sqrt(ln(real(growth (2*m)))))/(\<delta> * sqrt(2*m))" sorry
 (* have "\<forall>h\<in>H. measure_pmf.expectation D (\<lambda>x. if h x \<noteq> f x then 1::real else 0) = (\<Sum>\<^sub>ax. pmf D x * (\<lambda>x. if h x \<noteq> f x then 1::real else 0) x)"
    using pmf_expectation_eq_infsetsum by auto
  have "\<forall>h\<in>H. (\<Sum>\<^sub>ax. pmf D x * (\<lambda>x. if h x \<noteq> f x then 1::real else 0) x) = (\<Sum>\<^sub>ax. (if h x \<noteq> f x then pmf D x else 0))"
    by (smt infsetsum_cong mult_cancel_left1 mult_cancel_right1)
  have "\<forall>h A.(\<lambda>x. if h x \<noteq> f x then pmf D x else 0) abs_summable_on A"
    using pmf_abs_summable[of "D"] if_summable[of "pmf D"] by auto
  then have "\<forall>h\<in>H. infsetsum (\<lambda>x. if h x \<noteq> f x then pmf D x else 0) (UNIV - {x. h x = f x})
        = (\<Sum>\<^sub>ax. (if h x \<noteq> f x then pmf D x else 0)) - infsetsum (\<lambda>x. if h x \<noteq> f x then pmf D x else 0) {x. h x = f x}"
    by (simp add: infsetsum_Diff)
  have "\<forall>h\<in>H. infsetsum (\<lambda>x. if h x \<noteq> f x then pmf D x else 0) {x. h x = f x} = 0"
    by (smt infsetsum_all_0 mem_Collect_eq)
  have "\<forall>h\<in>H. infsetsum (\<lambda>x. if h x \<noteq> f x then pmf D x else 0) (UNIV - {x. h x = f x}) = infsetsum (pmf D) {x. h x \<noteq> f x}"
    by (smt Diff_iff UNIV_I infsetsum_Diff infsetsum_all_0 infsetsum_cong infsetsum_def mem_Collect_eq pmf_abs_summable subsetI)

*)fix h I
  have "PredErr D f h = measure_pmf.expectation D (\<lambda>x. if h x \<noteq> f x then 1::real else 0)"
    unfolding PredErr_def using exp_to_prob[of D "(\<lambda>x. h x \<noteq> f x)"]
    by (smt Collect_cong)
  moreover assume "card I > 0"
  moreover have "(\<lambda>x. pmf D x * (\<lambda>x. if h x \<noteq> f x then 1::real else 0) x) abs_summable_on UNIV"
    using pmf_abs_summable[of "D"] if_summable[of "pmf D"]
    by (smt abs_summable_on_comparison_test mult_cancel_left1 mult_not_zero zero_less_norm_iff)
  ultimately have "measure_pmf.expectation (Pi_pmf I undefined (\<lambda>_. D))
              (\<lambda>S. sum (\<lambda>i. if h (S i) \<noteq> f (S i) then 1::real else 0) I / card I)
               = PredErr D f h"
    using stichprobenmittel by auto
  have "\<forall>h\<in>H. (PredErr D f h) = measure_pmf.expectation (Samples m D f) (\<lambda>S. TrainErr S {0..m} h)"
    unfolding PredErr_def TrainErr_def Samples_def
    sorry
  show ?thesis sorry
qed


           (*-------------------------------------------*
            |        CSP-Prover on Isabelle2004         |
            |                  April 2005               |
            |                   June 2005  (modified)   |
            |              September 2005  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2005         |
            |               November 2005  (modified)   |
            |                  April 2006  (modified)   |
            |                  March 2007  (modified)   |
            |                                           |
            |        Yoshinao Isobe (AIST JAPAN)        |
            *-------------------------------------------*)

theory CSP_F_op_alpha_par
imports CSP_F_domain CSP_T_op_alpha_par
begin

(*  The following simplification rules are deleted in this theory file *)
(*  because they unexpectly rewrite (notick | t = <>)                  *)
(*                                                                     *)
(*                  disj_not1: (~ P | Q) = (P --> Q)                   *)

declare disj_not1 [simp del]

(*********************************************************
             Alphabetized Parallel eval
 *********************************************************)

lemma in_failures_Parallel_SKIP_lm1:
  "[| Y - insert Tick (Ev ` X) = Z - insert Tick (Ev ` X) ;
     (Tick ~: Z | Z <= Evset) |]
   ==> Z - Y <= Ev ` X"
by (auto simp add: Evset_def)

lemma in_failures_Parallel_SKIP_lm2:
  "Y - insert Tick (Ev ` X) = Z - insert Tick (Ev ` X)
   ==> Z - insert Tick Y <= Ev ` X"
by (auto)

(* Para SKIP *)

lemma in_failures_Parallel_SKIP:
  "(f :f failures(P |[X]| SKIP) M) =
   (EX u Y Z. f = (u, Y Un Z) & (u, Y) :f failures(P) M &
              sett(u) Int (Ev ` X) = {} & Z <= Ev ` X)"
apply (simp add: in_failures)
apply (rule iffI)

(* => *)
 apply (elim conjE exE)
 apply (erule disjE)

 (* t = <> *)
  apply (simp add: par_tr_nil)
  apply (elim conjE, simp)
  apply (rule_tac x="Y" in exI)
  apply (rule_tac x="Z - Y" in exI)
  apply (simp add: in_failures_Parallel_SKIP_lm1)

 (* t = <Tick> *)
  apply (simp add: par_tr_Tick)
  apply (elim conjE, simp)
  apply (case_tac "Tick ~: Z")

   apply (rule_tac x="Y" in exI)
   apply (rule_tac x="Z - Y" in exI)
   apply (simp add: in_failures_Parallel_SKIP_lm1)

   (* Tick : Z *)
   apply (rule_tac x="insert Tick Y" in exI)
   apply (rule_tac x="(Z - insert Tick Y)" in exI)
   apply (rule conjI, force)
   apply (simp add: Tick_in_sett)
   apply (erule exE)
   apply (rule conjI)
   apply (simp)
   apply (rule proc_T2_T3)
   apply (simp)
   apply (simp)
   apply (simp add: in_failures_Parallel_SKIP_lm2)

(* <= *)
 apply (elim conjE exE)
 apply (case_tac "Tick ~: sett u")

 (* t = <> *)
  apply (rule_tac x="u" in exI)
  apply (rule_tac x="Y" in exI)
  apply (rule_tac x="Z Un (Y - {Tick})" in exI)
  apply (simp)
  apply (rule conjI)
  apply (fast)
  apply (rule conjI)
  apply (fast)
  apply (rule_tac x="u" in exI)
  apply (rule_tac x="<>" in exI)
  apply (simp add: par_tr_nil)
  apply (simp add: Evset_def)
  apply (force)

 (* t = <Tick> *)
  apply (rule_tac x="u" in exI)
  apply (rule_tac x="Y" in exI)
  apply (rule_tac x="Z Un Y" in exI)
  apply (simp)
  apply (rule conjI)
  apply (fast)
  apply (rule conjI)
  apply (fast)
  apply (rule_tac x="u" in exI)
  apply (rule_tac x="<Tick>" in exI)
  apply (simp add: par_tr_Tick)
done

(*** complement ***)

lemma in_failures_Parallel_SKIP_comp:
  "(f :f failures(P |[- X]| SKIP) M) =
   (EX u Y Z. f = (u, Y Un Z) & (u, Y) :f failures(P) M &
              sett(u) <= insert Tick (Ev ` X) & Z Int insert Tick (Ev ` X) = {})"
apply (simp add: in_failures_Parallel_SKIP)
apply (auto)
apply (rule_tac x="Y" in exI)
apply (rule_tac x="Z" in exI)
apply (simp)
apply (rule conjI)
 apply (rule subsetI)
 apply (case_tac "x : Ev ` (- X)")
 apply (fast)
 apply (simp add: notin_Ev_set)
 apply (erule disjE, simp)
 apply (force)
apply (force)

apply (rule_tac x="Y" in exI)
apply (rule_tac x="Z" in exI)
apply (auto)
apply (case_tac "x = Tick", simp)
apply (simp add: not_Tick_to_Ev)
apply (auto)
done

(*** Alpha_parallel_evalF ***)

lemma in_failures_Alpha_parallel_lm1:
  "[| Tick ~: Za ; Za Int Ev ` X1 = {};
      Tick ~: Zb ; Zb Int Ev ` X2 = {};
      Ya Un Za - insert Tick (Ev ` (X1 Int X2)) =
      Yb Un Zb - insert Tick (Ev ` (X1 Int X2)) |]
       ==>
       (Ya Un Za Un (Yb Un Zb)) Int insert Tick (Ev ` (X1 Un X2)) =
         (Ya Int insert Tick (Ev ` X1)) Un
         (Yb Int insert Tick (Ev ` X2))"
by (auto)

lemma in_failures_Alpha_parallel_lm2:
  "X Int insert Tick (Ev ` (X1 Un X2)) <= Y Un Z
   ==> X = X Int Ev ` (X1 - X2) Un X Int Y Int insert Tick (Ev ` (X1 Int X2)) Un
               (X - insert Tick (Ev ` X1)) Un
               (X Int Ev ` (X2 - X1) Un X Int Z Int insert Tick (Ev ` (X1 Int X2)) Un
                (X - insert Tick (Ev ` X2)))"
by (auto)

lemma in_failures_Alpha_parallel_lm3:
  "X Int Ev ` (X1 - X2) Un X Int Y Int insert Tick (Ev ` (X1 Int X2)) Un
           (X - insert Tick (Ev ` X1)) -
           insert Tick (Ev ` (X1 Int X2)) =
           X Int Ev ` (X2 - X1) Un X Int Z Int insert Tick (Ev ` (X1 Int X2)) Un
           (X - insert Tick (Ev ` X2)) -
           insert Tick (Ev ` (X1 Int X2))"
by (auto)

(* F *)

lemma in_failures_Alpha_parallel:
  "(f :f failures(P |[X1,X2]| Q) M) =
   (EX u X.
     f = (u, X) &
     (EX Y Z.
         X Int insert Tick (Ev ` (X1 Un X2)) =
         Y Int insert Tick (Ev ` X1) Un Z Int insert Tick (Ev ` X2) &
         (u rest-tr X1, Y) :f failures(P) M &
         (u rest-tr X2, Z) :f failures(Q) M &
          sett u <= insert Tick (Ev ` (X1 Un X2))))"
apply (simp add: Alpha_parallel_def)
apply (simp add: in_failures_Parallel[of _ _ "X1 Int X2"])
apply (simp add: in_failures_Parallel_SKIP_comp)
apply (rule iffI)

(* => *)
 apply (elim conjE exE)
 apply (simp add: par_tr_rest_tr)
 apply (rule_tac x="Ya" in exI, simp)
 apply (rule_tac x="Yb" in exI, simp)
 apply (simp add: in_failures_Alpha_parallel_lm1)

(* <= *)
 apply (elim conjE exE)
 apply (simp)
 apply (rule_tac x=
   "(X Int (Ev ` (X1 - X2))) Un
    (X Int Y Int insert Tick (Ev ` (X1 Int X2))) Un
    (X - insert Tick (Ev ` X1))" in exI)
 apply (rule_tac x=
   "(X Int (Ev ` (X2 - X1))) Un
    (X Int Z Int insert Tick (Ev ` (X1 Int X2))) Un
    (X - insert Tick (Ev ` X2))" in exI)

(* X = Y' Un Z' *)
  apply (rule conjI)
  apply (rule in_failures_Alpha_parallel_lm2)
  apply (fast)

(* Parallel condition *)
  apply (rule conjI)
  apply (simp add: in_failures_Alpha_parallel_lm3)

(* failures *)
  apply (rule_tac x="u rest-tr X1" in exI)
  apply (rule_tac x="u rest-tr X2" in exI)
  apply (simp add: par_tr_rest_tr_if)

  apply (rule conjI)
   apply (rule_tac x=
     "(X Int (Ev ` (X1 - X2))) Un
      (X Int Y Int insert Tick (Ev ` (X1 Int X2)))" in exI)
   apply (rule_tac x= "(X - insert Tick (Ev ` X1))" in exI)
   apply (simp)
   apply (rule conjI)
   apply (rule memF_F2)
   apply (simp)
   apply (force)
   apply (force)

   apply (rule_tac x=
     "(X Int (Ev ` (X2 - X1))) Un
      (X Int Z Int insert Tick (Ev ` (X1 Int X2)))" in exI)
   apply (rule_tac x= "(X - insert Tick (Ev ` X2))" in exI)
   apply (simp)
   apply (rule conjI)
   apply (rule memF_F2)
   apply (simp)
   apply (force)
   apply (force)
done

(*** Semantics for alphabetized parallel on F ***)

lemma failures_Alpha_parallel:
  "failures(P |[X1,X2]| Q) = (%M.
   {f. (EX u X. f = (u, X) &
     (EX Y Z.
         X Int insert Tick (Ev ` (X1 Un X2)) =
         Y Int insert Tick (Ev ` X1) Un Z Int insert Tick (Ev ` X2) &
         (u rest-tr X1, Y) :f failures(P) M &
         (u rest-tr X2, Z) :f failures(Q) M &
          sett u <= insert Tick (Ev ` (X1 Un X2))))}f)"
apply (simp only: in_failures_Alpha_parallel[THEN sym])
apply (simp)
done

(****************** to add it again ******************)

declare disj_not1   [simp]

end