Theory Gelfand_Naimark_Segal

section ‹The Gelfand--Naimark--Segal Construction›

theory Gelfand_Naimark_Segal
imports
  Inner_Completion
  Cstar_Algebra_On
  Complex_Bounded_Operators.Complex_Bounded_Linear_Function
  Smooth_Manifolds.Analysis_More
begin

unbundle lifting_syntax

subsection ‹Strengthen lifting lemmas›

subsubsection ‹Lifting to the metric completion›

lemma inj_to_metric_completion: "inj to_metric_completion"
  using isometry_on_injective to_metric_completion_isometry by blast

definition "from_metric_completion ≡ the_inv to_metric_completion"

lemma lift_to_metric_completion2:
  fixes f::"('a::metric_space) ⇒ ('b::complete_space)"
  assumes "uniformly_continuous_on UNIV f"
  shows "∃g. (uniformly_continuous_on UNIV g)
            ∧ (f = g o to_metric_completion)
            ∧ (∀x ∈ range to_metric_completion. g x = f (from_metric_completion x))"
  unfolding from_metric_completion_def
  using lift_to_metric_completion[OF assms]
  by (simp add: inj_to_metric_completion the_inv_f_f)

lemma lift_to_metric_completion_isometry2:
  fixes f::"('a::metric_space) ⇒ ('b::complete_space)"
  assumes "isometry_on UNIV f"
  shows "∃g. isometry_on UNIV g
          ∧ range g = closure(range f)
          ∧ f = g o to_metric_completion
          ∧ (∀x ∈ range to_metric_completion. g x = f (from_metric_completion x))"
  unfolding from_metric_completion_def
  using lift_to_metric_completion_isometry[OF assms]
  by (simp add: inj_to_metric_completion the_inv_f_f)

lemma dense_imp_conv_seq:
  assumes "closure S = U" "x∈U"
  shows "∃s. (s n) ∈ S ∧ s ⇢ x"
  using LIMSEQ_if_less
  by (metis (full_types, lifting) ext all_not_in_conv
      assms closed_empty closure_closed order.strict_iff_order)

lemma to_metric_completion_sequence_ex:
  shows "∃s. (to_metric_completion o s) ⇢ x"
  using dense_imp_conv_seq[of "range to_metric_completion" UNIV]
  by (smt (verit, best) UNIV_I closure_sequential function_factors_right image_iff
      to_metric_completion_dense')

lemma cinner_extensionality_dense:
  assumes dense_S: "closure S = UNIV"
    and inner_on_S: "∀z∈S. cinner z x = cinner z y"
  shows "x = y"
proof (rule cinner_extensionality)
  fix z :: "'a::complex_inner"
  obtain s where s: "s ⇢ z" "⋀n::nat. (s n) ∙C x = (s n) ∙C y"
    by (metis UNIV_I closure_sequential dense_S inner_on_S)
  ― ‹We could obtain term‹∀n. s n ∈ S› at the same time,
      but this is not needed here.›
  have "(λn. s n ∙C x) ⇢ z ∙C x"
    and"(λn. s n ∙C x) ⇢ z ∙C y"
    apply (simp add: s(1) tendsto_cinner)
    unfolding s(2) by (simp add: s(1) tendsto_cinner)
  thus "z ∙C x = z ∙C y"
    using LIMSEQ_unique by blast
qed

lemma cinner_extensionality_metric_completion:
  assumes "∀z. cinner (to_metric_completion z) x = cinner (to_metric_completion z) y"
  shows "x = y"
  using cinner_extensionality_dense[OF to_metric_completion_dense'] assms
  by blast

lemma completion_ext_simp1:
  fixes f::"('m::metric_space) ⇒ ('c::complete_space)" and g
  defines "D ≡ range to_metric_completion"
  shows "(f = g o to_metric_completion) ⟷
      (∀x ∈ D. g x = f (from_metric_completion x))"
  unfolding assms o_def from_metric_completion_def
  using f_the_inv_into_f the_inv_f_f inj_to_metric_completion
  by (metis rangeI)

lemma lift_to_metric_completion4:
  fixes f::"('m::metric_space) ⇒ ('c::complete_space)"
  assumes "uniformly_continuous_on UNIV f"
  shows "∃!g. (uniformly_continuous_on UNIV g)
            ∧ (f = g ∘ to_metric_completion)"
proof -
  { fix x y and v :: "'m metric_completion"
    assume x: "isUCont x" "f = x ∘ to_metric_completion"
      and y: "isUCont y" "f = y ∘ to_metric_completion"
    have x3: "∀b∈range to_metric_completion. x b = f (from_metric_completion b)"
      and y3: "∀b∈range to_metric_completion. y b = f (from_metric_completion b)"
      using completion_ext_simp1 x(2) y(2) by blast+
    have "∃s. (to_metric_completion o s) ⇢ v"
      using to_metric_completion_sequence_ex .
    then obtain s :: "nat⇒'m" where s: "(to_metric_completion ∘ s) ⇢ v"
      by blast
    let ?s = "to_metric_completion o s"
    have x_to_x: "(x ∘ ?s) ⇢ x v"
      and y_to_y: "(y ∘ ?s) ⇢ y v"
      using continuous_at_sequentially isUCont_isCont s x(1) y(1) by blast+
    moreover have "∀b∈range to_metric_completion. x b = y b"
      using x3 y3 by presburger
    ultimately have x_to_y: "(x ∘ ?s) ⇢ y v"
      by (metis fun.map_comp x(2) y(2))
    have "x v = y v"
      using LIMSEQ_unique x_to_x x_to_y by blast
  } note 1 = this
  have "∃!x. isUCont x ∧
       f = x ∘ to_metric_completion ∧
       (∀xa∈range to_metric_completion.
           x xa = f (from_metric_completion xa))"
    by (metis (no_types, lifting) ext "1" assms lift_to_metric_completion2)
  thus ?thesis
    using completion_ext_simp1
    by (metis (no_types, lifting))
qed


lemma lift_to_metric_completion3:
  fixes f::"('m::metric_space) ⇒ ('c::complete_space)"
  assumes "uniformly_continuous_on UNIV f"
  shows "∃!g. (uniformly_continuous_on UNIV g)
            ∧ (f = g o to_metric_completion)
            ∧ (∀x ∈ range to_metric_completion. g x = f (from_metric_completion x))"
  by (metis assms lift_to_metric_completion2 lift_to_metric_completion4)


subsubsection ‹Lifting a bounded operator from an inner product space to a Hilbert space›

lemma to_metric_completion_cblinfun_exists:
  fixes f :: ‹'a::complex_normed_vector ⇒ 'b::cbanach›
  assumes f_add: ‹⋀x y. f (x + y) = f x + f y›
  assumes f_scale: ‹⋀c x y. f (c *C x) = c *C f x›
  assumes bounded: ‹⋀x. norm (f x) ≤ B * norm x›
  shows "cblinfun_extension_exists (range to_metric_completion)
      (map_fun (from_metric_completion) id f)"
    (is ‹cblinfun_extension_exists ?D ?f›)
proof -
  interpret f: bounded_clinear f
    by unfold_locales (use f_add f_scale bounded in ‹auto simp: mult.commute›)
  obtain K where K: "⋀x. norm (f x) ≤ norm x * K"
    using f.real.bounded by blast
  interpret m: bounded_clinear to_metric_completion
    using to_metric_completion_bounded_clinear .

  show ?thesis
  proof (rule cblinfun_extension_exists_bounded_dense)
    fix c x y 
    assume x: "x ∈ ?D"
    show "?f (c *C x) = c *C ?f x"
      unfolding map_fun_def from_metric_completion_def apply simp
      using the_inv_f_f[OF inj_to_metric_completion]
      by (metis x assms(2) m.scale rangeE)
     show "norm (?f x) ≤ K * norm x"
      unfolding map_fun_def from_metric_completion_def apply simp
      using the_inv_f_f[OF inj_to_metric_completion]
      using to_metric_completion_norm
      by (metis Extra_Ordered_Fields.sign_simps(5) K rangeE x)
    assume y: "y ∈ ?D"
    show "?f (x + y) = ?f x + ?f y"
      unfolding map_fun_def from_metric_completion_def apply simp
      using the_inv_f_f[OF inj_to_metric_completion] f_the_inv_into_f[OF inj_to_metric_completion]
      using m.add f.add
      by (metis (no_types, lifting) x y)
  qed (use range_is_csubspace to_metric_completion_clinear in blast,
    use to_metric_completion_dense' in blast)
qed

lemma to_metric_completion_cblinfun_exists':
  fixes f :: ‹('a::complex_normed_vector, 'b::cbanach) cblinfun›
  shows "cblinfun_extension_exists (range to_metric_completion)
      (map_fun (from_metric_completion) id f)"
  using to_metric_completion_cblinfun_exists
        cblinfun.add_right cblinfun.scaleC_right norm_cblinfun
  by meson


subsection ‹The $C^*$-algebra of bounded operators on a Hilbert space›

text ‹The assumption on the next lemma is a nondegeneracy condition found as the defining
  assumption of locale‹assoc_algebra_1_on›. It's similar also to the class class‹zero_neq_one›,
  which enters for example into class‹ring_1›, class‹field›, and class‹one_dim›.›

lemma Cstar_cblinfun:
  includes cblinfun_syntax
  assumes "(id_cblinfun :: ('b ⇒CL ('b::chilbert_space))) ≠ 0"
  shows "Cstar_algebra UNIV (UNIV :: ('b ⇒CL ('b::chilbert_space)) set) (*C) (oCL) norm id_cblinfun adj"
  (is "Cstar_algebra ?C ?B _ _ _ _ _")
proof -
  interpret normed_vector_space_on ?C cmod ?B "(*C)" norm
    by (unfold_locales,
      auto simp: norm_triangle_ineq norm_mult_ineq norm_mult complex_vector.vector_space_assms(1,2))

  interpret Group_Theory.monoid ?B "(+)" 0
    by unfold_locales auto
  interpret involutive_complex_algebra ?B "(*C)" "(oCL)" id_cblinfun adj
    by (unfold_locales,
      auto simp: assms cblinfun_compose_add_left cblinfun_compose_add_right lift_cblinfun_comp(2)
        add_eq_0_iff adj_plus)

  have "complete ?B"
    by (simp add: complete_UNIV)
  then have "mcomplete"
    unfolding mcomplete_iff_complete[symmetric] dist_cblinfun_def totalized_induced_metric_def
    by (simp add: norm_minus_commute)
  show ?thesis
    apply unfold_locales
    using ‹mcomplete› by (auto simp:
        norm_is_Proj_nonzero norm_cblinfun_compose power2_eq_square)
qed
text ‹The above can be used e.g. as
  @{thm Cstar_cblinfun[OF id_cblinfun_not_0]}, or using class‹zero_neq_one›.›


subsection ‹Type class of $C^*$-algebras›

text ‹Make a bundle to (de)activate dagger notation for adjoints of functions
  between types in the class of complex inner product spaces.›
bundle cadjoint_syntax begin
  notation Complex_Inner_Product.cadjoint ("_†" [99] 100)
end
unbundle no cadjoint_syntax


class cstar = complex_normed_algebra_1 + cbanach +
  fixes involution::"'a⇒'a" ("_†" [99] 100)
  assumes ivl_scaleC: "(c *C s)† = cnj c *C s†" ― ‹@{thm involutive_complex_algebra.ivl_scale}›
    and ivl_plus [simp]: "(x+y)† = x† + y†" ― ‹@{thm involutive_ring.ivl_ring}›
    and involution[simp]: "(x†)† = x" ― ‹@{thm involutive_semigroup.involution}›
    and ivl_times [simp]: "(x * y)† = y† * x†" ― ‹@{thm involutive_semigroup.antiautomorphism}›
    and ivl_isometric: "norm (A†) = norm A" ― ‹@{thm Cstar_algebra.involution_isometric}›
    and Cstar: "norm (A† * A) = (norm (A†)) * (norm A)" ― ‹@{thm Cstar_algebra.Cstar}›
begin

text ‹
A class analogue of locale‹Cstar_algebra›,
reproducing the axioms @{thm Cstar_algebra_axioms_def} one-by-one.
Some assumptions of locale‹Cstar_algebra› are in class‹real_normed_algebra›, compare:
\begin{itemize}
  \item @{thm Cstar_algebra.normed_algebra} with @{thm norm_mult_ineq},
  \item @{thm Cstar_algebra.normed_unital} with @{thm norm_one}.
\end{itemize}
›

end

bundle cstar_syntax begin
  notation involution ("_†" [99] 100)
end

unbundle cstar_syntax


lemma cstar_locale: "Cstar_algebra UNIV (UNIV::'a::cstar set)
    scaleC times norm 1 involution"
proof -
  have 0: "Metric_space.mcomplete (UNIV::'a set)
      (normed_vector_space_on.totalized_induced_metric UNIV norm)"
    by (simp add: complete_UNIV totalized_induced_metric_eq_dist)
  have 1: "monoid.invertible UNIV (+) 0 u"
    for u :: 'a
  proof -
    interpret Group_Theory.monoid UNIV "(+)" "0::'a"
      by unfold_locales simp_all
    show ?thesis
      unfolding invertible_def[simplified]
      by (intro exI[of _ "-u"]) simp
  qed
  have 2: "involution u * involution (of_complex c) =
      of_complex (cnj c) * involution u"
    for u :: 'a and c::complex
    using ivl_scaleC by auto
  have 3: "norm (of_complex c * u) = cmod c * norm u"
    for u :: 'a and c::complex
    by (metis norm_scaleC scaleC_conv_of_complex)
  have 4: "v * (of_complex c * u) = of_complex c * (v * u)"
    for u v :: 'a and c::complex
    by (metis mult_scaleC_right scaleC_conv_of_complex)
  show ?thesis
    apply unfold_locales
    apply (simp_all add: ivl_isometric Cstar
        norm_triangle_ineq norm_mult Groups.mult_ac(1)
        nat_distrib(2) cross3_simps(23) norm_mult_ineq)
    using 0 1 2 3 4 by simp_all
qed

text ‹We \emph{have to} interpret class‹cstar› as a locale‹Cstar_algebra›
  in stages, and name the interpretation of the locale‹involutive_complex_algebra›,
  otherwise there is a naming conflict between
  @{thm algebra_on.lie_algebraI} and @{thm vector_space_on.lie_algebraI}.›
interpretation cstar1: involutive_complex_algebra
    "UNIV::'a::cstar set" scaleC times 1 involution
  using cstar_locale unfolding Cstar_algebra_def by blast

interpretation Cstar_algebra
    UNIV "UNIV::'a::cstar set" scaleC times norm 1 involution
  using cstar_locale .

text ‹Some simp set adjustments.›
declare cstar1.involution_uminus'[simp del]
declare cstar1.ivl_minus'[simp del]

context cstar begin
named_theorems cstar_simps
lemmas cross3_simps(10,11,23,24,27,28)[cstar_simps]
lemmas
  cstar1.involution_uminus'[OF UNIV_I, cstar_simps]
  cstar1.ivl_minus'[OF UNIV_I UNIV_I, cstar_simps]
end


subsection ‹GNS construction›

context
  fixes ω :: "'a::cstar ⇒ complex"
  assumes omega_nonneg: "⋀A::'a. ω (A† * A) ≥ 0"
    and one [simp]: "ω 1 = 1"
    and "clinear ω"
begin

subsubsection ‹Interpretation of existing locales›

thm linear_def clinear_def linear_on_def

interpretation ω: clinear ω
  using ‹clinear ω› .

lemma cstar_state: "Cstar_state UNIV UNIV scaleC times norm 1 involution ω"
  apply unfold_locales
  using ω.add ω.scaleC omega_nonneg
  by (simp_all add: nat_distrib(2) cross3_simps(52))

interpretation Cstar_state UNIV UNIV scaleC times norm 1 involution ω
  using cstar_state .

subsubsection ‹Some identities for class‹cstar› and its left ideal.›

text ‹Show the kernel of our intended inner product is a (left) ideal.›
definition zero_inner_set: "ℑ = {A::'a. ω (A† * A) = 0}"

lemma is_zero_inner: "ω (A† * A) = 0" if "A∈ℑ"
  using that unfolding zero_inner_set by simp

lemma zero_inner_zero: "ω i = 0" if "i∈ℑ"
  using state_zero_if_inner_zero that unfolding zero_inner_set
  by blast

lemma zero_inner_times: "a*i ∈ ℑ" if "i∈ℑ" for a i :: 'a
proof -
  let ?b = "a†*a*i"
  from cauchy_schwarz_square[of ?b i]
  have "¦ω ((a*i)† * (a*i))¦2 ≤ ω (?b† * ?b) * ω (i† * i)"
    by (simp add: cstar_simps functional_inner_def)
  then show ?thesis
    unfolding is_zero_inner[OF that] zero_inner_set apply simp
    using cnj_x_x_geq0 cnj_x_x
    by (metis abs_eq_0_iff le_less less_le_not_le zero_eq_power2)
qed

lemma zero_inner_zero2: "ω (a*i) = 0" if "i∈ℑ"
  apply (rule zero_inner_zero)
  apply (rule zero_inner_times)
  using that .

end


class cstar_state = cstar +
  fixes state :: "'a ⇒ complex" (‹ω›)
  assumes omega_nonneg: "⋀A::'a. ω (A† * A) ≥ 0"
    and omega_one [simp]: "ω 1 = 1"
    and omega_linear[simp]: "ω (u + v) = ω u + ω v"
      "ω (c *C u) = c * ω u"
    and extra_assm[no_atp]:
      ‹ω ((B*A)† * B*A) ≤ (norm B)2 * ω (A† * A)›


lemma omega_clinear: "clinear ω"
  apply unfold_locales using omega_linear by auto

interpretation omega_linear: Vector_Spaces.linear scaleC times ω
  apply unfold_locales using omega_linear(2)
  by auto

― ‹Top-level interpretation of locale‹Cstar_state› for any type in class‹cstar_state›.›
interpretation cstar_state: Cstar_state UNIV UNIV scaleC times norm 1 involution ω
proof -
  interpret Cstar_algebra UNIV UNIV scaleC times norm 1 involution
    using cstar_locale .
  show "Cstar_state UNIV UNIV (*C) (*) norm 1 involution ω"
    apply unfold_locales
    using omega_linear(2) omega_nonneg by (auto simp: cstar_simps)
qed


lemma zero_inner_zero': "ω A = 0" if "ω (A† * A) = 0"
  using zero_inner_zero zero_inner_set that
  using omega_nonneg omega_one omega_clinear
  by (metis (full_types,lifting) ctr_simps_mem_Collect_eq)

lemma zero_inner_zero2': "ω (B*A) = 0" if "ω (A† * A) = 0"
  using zero_inner_zero2 zero_inner_set that
  using omega_nonneg omega_one omega_clinear
  by (metis (full_types,lifting) ctr_simps_mem_Collect_eq)


text ‹Some identities, restated for class‹cstar_state›.›
lemma state_ivl_cnj: "ω (A†) = cnj (ω A)"
  using positive_normalised_linear_functional.involution_conjugate
  using cstar_state[of ω, OF omega_nonneg omega_one omega_clinear]
  unfolding Cstar_state_def by blast

lemma state_cnj_ivl [cstar_simps]: "cnj (ω (A†)) = ω A"
  using positive_normalised_linear_functional.cnj_ivl
  using cstar_state[of ω, OF omega_nonneg omega_one omega_clinear]
  unfolding Cstar_state_def by blast

lemma state_norm_leq_inner: "¦ω A¦2 ≤ ω (A† * A)"
  using positive_normalised_linear_functional.state_norm_leq_inner
  using cstar_state[of ω, OF omega_nonneg omega_one omega_clinear]
  unfolding Cstar_state_def
  by (metis UNIV_I complex_of_real_cmod of_real_power
      positive_normalised_linear_functional.functional_inner_def)


lemma zero_inner_equivp: "equivp (λu v. ∃A. ω (A† * A) = 0 ∧ u = v + A)"
proof -
  have 1: "∃B. ω (B† * B) = 0 ∧ A + B = 0"
      if "ω (A† * A) = 0" for A :: 'a
    apply (intro exI[of _ "-A"])
    by (simp add: cstar1.involution_uminus' that)
  have 2: "ω ((B† + A†) * (B + A)) = 0"
    if "ω (A† * A) = 0" "ω (B† * B) = 0"
    for A B :: 'a
    by (simp add: ordered_field_class.sign_simps(18) that zero_inner_zero2')
  show ?thesis
    apply (intro equivpI reflpI sympI transpI)
    by (auto simp: 1 2)
qed


subsubsection ‹Quotient construction for the inner product›

quotient_type (overloaded) 'a gns_precomplete =
  "'a::cstar_state" / "λu v. ∃A. (ω (A† * A) = 0 ∧ u = v + A)"
  using zero_inner_equivp .

instantiation gns_precomplete :: (cstar_state) scaleC
begin

lift_definition scaleC_gns_precomplete ::
    "complex ⇒ 'a gns_precomplete ⇒ 'a gns_precomplete"
  is scaleC
  apply (simp add: cstar_simps)
  by (metis cross3_simps(10) nat_distrib(2) zero_inner_zero2')

lift_definition scaleR_gns_precomplete ::
    "real ⇒ 'a gns_precomplete ⇒ 'a gns_precomplete"
  is scaleR
proof -
  { fix r :: real and u i :: 'a
    assume asm: "ω (i† * i) = 0"
    have "∃i'. ω (i'† * i') = 0 ∧ r *R (u + i) = r *R u + i'"
      apply (rule exI[of _ "scaleR r i"], intro conjI)
      apply (metis scaleC_gns_precomplete.abs_eq asm arithmetic_simps(49)
          gns_precomplete.abs_eq_iff pth_4(2) scaleR_scaleC)
      using cross3_simps(30) by blast }
  thus "∃A. ω (A† * A) = 0 ∧ r *R a1 = r *R a2 + A"
    if "∃A. ω (A† * A) = 0 ∧ a1 = a2 + A"
    for r and a1 a2 :: 'a
    using that by blast
qed

instance
  by (intro_classes) (simp add: scaleC_gns_precomplete_def
      scaleR_gns_precomplete_def scaleR_scaleC)

end


text ‹The lifting of the vector space structure is almost entirely a
  transfer+sledgehammer affair: identities proven earlier are enough
  to let sledgehammer find respectfulness proofs.›

instantiation gns_precomplete :: (cstar_state) complex_vector
begin

lift_definition zero_gns_precomplete :: "'a gns_precomplete"
  is 0 .

lemma "(a+b)* c = a* c + b* (c::'a)"
  using cross3_simps(23) by blast

lift_definition minus_gns_precomplete ::
    "'a gns_precomplete ⇒ 'a gns_precomplete ⇒ 'a gns_precomplete"
  is minus
proof -
  { fix u v :: 'a
    assume u: "ω (u† * u) = 0" and v: "ω (v† * v) = 0"
    have "ω ((u† - v†) * (u - v)) = ω (u† * u) - ω (v† * u) - ω (u† * v) + ω (v† * v)"
      by (simp add: omega_linear.diff cstar_simps)
    also have "… = 0"
      using zero_inner_zero2'[OF u] zero_inner_zero2'[OF v] by simp
    finally have "ω ((u† - v†) * (u - v)) = 0" . }
  thus "⋀a1 a2 a3 a4.
      ∃A. ω (A† * A) = 0 ∧ a1 = a2 + A ⟹
      ∃A. ω (A† * A) = 0 ∧ a3 = a4 + A ⟹
      ∃A. ω (A† * A) = 0 ∧ a1 - a3 = a2 - a4 + A"
    apply (auto simp add: cstar1.involution_uminus' cstar1.ivl_minus')
    apply (metis arith_simps(57) cross3_simps(27) omega_linear.diff zero_inner_zero2')
    done
qed

lift_definition uminus_gns_precomplete ::
    "'a gns_precomplete ⇒ 'a gns_precomplete"
  is uminus by (auto simp: cstar_simps)

lift_definition plus_gns_precomplete ::
    "'a gns_precomplete ⇒ 'a gns_precomplete ⇒ 'a gns_precomplete"
  is plus
  by (auto simp: cstar_simps) (metis add_0_iff zero_inner_zero2')

instance
  apply (intro_classes; transfer)
  by (auto simp add: cstar_simps)

end


instantiation gns_precomplete :: (cstar_state) complex_inner
begin

text ‹The interesting definition is for the inner product,
  which implies that of the norm.›

lift_definition cinner_gns_precomplete ::
    "'a gns_precomplete ⇒ 'a gns_precomplete ⇒ complex"
  is "λu v. ω (u† * v)"
proof clarify
  fix u v i1 i2 :: 'a
  assume i_in_ideal: "ω (i1† * i1) = 0" "ω (i2† * i2) = 0"
  have 1: "ω ((v+i2)† * (u+i1)) =
      ω (v†*u) + ω (v†*i1) + cnj (ω (u†*i2)) + ω (i2†*i1)"
    apply (simp add: ring_distribs)
    using involution ivl_times omega_clinear omega_nonneg omega_one
    by (metis (no_types, lifting) Cstar_state_def UNIV_I cstar_state
        positive_normalised_linear_functional.involution_conjugate)
  also have "… = ω (v†*u)"
    using i_in_ideal by (simp add: cstar_simps zero_inner_zero2')
  finally show "ω ((v + i2)† * (u + i1)) = ω (v† * u)"
    by (simp add: cstar_simps)
qed

― ‹This could be defined in terms of term‹λu. cinner u u›, which
  will be a proof obligation later on anyway, but I think this
  is easier (since we can leverage identities to prove the necessary
  anyway) in the long term: we keep a concrete construction.›
lift_definition norm_gns_precomplete :: "'a gns_precomplete ⇒ real"
  is "λu. Re (csqrt (ω (u† * u)))"
  by clarsimp (metis (no_types, lifting) cinner_gns_precomplete.abs_eq
      gns_precomplete.abs_eq_iff ivl_plus)


text ‹The distance is given by the norm (and vector subtraction),
  as is standard.›

definition dist_gns_precomplete ::
    "'a gns_precomplete ⇒ 'a gns_precomplete ⇒ real"
    where "dist_gns_precomplete x y = norm (y-x)"


text ‹The uniform and topological structures are prescribed,
  in turn, by the metric structure.›

definition uniformity_gns_precomplete::"(('a gns_precomplete) × ('a gns_precomplete)) filter"
  where "uniformity_gns_precomplete = (INF e∈{0 <..}. principal {(x, y). dist x y < e})"

definition open_gns_precomplete :: "'a gns_precomplete set ⇒ bool"
  where "open_gns_precomplete U = (∀x∈U. eventually (λ(x', y). x' = x ⟶ y ∈ U) uniformity)"

definition sgn_gns_precomplete ::
    "'a gns_precomplete ⇒ 'a gns_precomplete"
  where "sgn_gns_precomplete x ≡ x /R norm x"

lemma norm_sym_gns_precomplete:
  fixes x y :: "'a gns_precomplete"
  shows "norm (y - x) = norm (x - y)"
proof transfer
  fix x y :: 'a
  have "ω ((y - x)† * (y - x)) = ω ((x - y)† * (x - y))"
    by (simp add: cstar_simps omega_linear.diff)
  thus "Re (csqrt (ω ((y-x)† * (y-x)))) = Re (csqrt (ω ((x-y)† * (x-y))))"
    by simp
qed

instance
  apply intro_classes
  subgoal unfolding dist_gns_precomplete_def using norm_sym_gns_precomplete .
  subgoal unfolding sgn_gns_precomplete_def by blast
  subgoal unfolding uniformity_gns_precomplete_def by blast
  subgoal unfolding open_gns_precomplete_def by blast
  subgoal apply transfer
    using state_ivl_cnj by (metis involution ivl_times)
  subgoal apply transfer
    by (simp add: cstar_simps)
  subgoal by transfer (simp only: ivl_scaleC mult_scaleC_left omega_linear.scale)
  subgoal by transfer (simp add: omega_nonneg)
  subgoal by transfer simp
  subgoal by transfer (simp add: cmod_Re omega_nonneg)
  done

end


type_synonym ('a) gns = "'a gns_precomplete metric_completion"


subsubsection ‹Representation of typ‹'a› on the Hilbert space typ‹'a gns›.›

text ‹The action on the dense subspace term‹to_gns ` UNIV› is given
  by lifted multiplication. Notice this isn't quite the dense
  subspace -- this is the action on the precomplete quotient,
  a type, not a set on typ‹'a gns›.›
lift_definition action_gns_precomplete ::
    "'a::cstar_state ⇒ 'a gns_precomplete ⇒ 'a gns_precomplete"
  is "(*)"
  by (metis Extra_Ordered_Fields.sign_simps(4) nat_distrib(2) zero_inner_zero2')

lemma action_gns_precomplete_alt: "action_gns_precomplete u ≡
    λv. abs_gns_precomplete (u * (rep_gns_precomplete v))"
  unfolding action_gns_precomplete_def map_fun_def o_def id_def .


― ‹We can't use lift-definition for the action on the completion,
  because ‹from_gns› (below) isn't total (since term‹from_metric_completion› isn't).›

definition to_gns :: "'a::cstar_state ⇒ 'a gns"
  where "to_gns ≡ to_metric_completion ∘ abs_gns_precomplete"

definition from_gns :: "'a::cstar_state gns ⇒ 'a"
  where "from_gns ≡ rep_gns_precomplete ∘ from_metric_completion"

definition action_gns_precomplete' ::
    "'a::cstar_state ⇒ 'a gns_precomplete ⇒ 'a gns"
  where "action_gns_precomplete' u ≡
    to_metric_completion ∘ (action_gns_precomplete u)"

lemma action_gns_precomplete'_alt: "action_gns_precomplete' ≡
    (id ---> id ---> to_metric_completion) action_gns_precomplete"
  unfolding action_gns_precomplete'_def map_fun_def o_def by simp

lemma action_gns_precomplete'_alt2: "action_gns_precomplete' ≡
    (id ---> rep_gns_precomplete ---> (to_gns)) (*)"
  unfolding action_gns_precomplete'_def action_gns_precomplete_def
    to_gns_def map_fun_def o_def id_def by argo


subsubsection ‹The action is bounded.›
text ‹This is where @{thm extra_assm} is first used.› 

lemma state_norm_sandwich_leq: ‹¦ω (A† * B * A)¦ ≤ ω (A† * A) * norm B›
proof-
  from cstar_state.mult_inner_norm_bound extra_assm
  show ?thesis
    unfolding cstar_state.functional_inner_def
    by (metis (no_types, lifting) UNIV_I involution ivl_isometric ivl_times mult.assoc)
qed

lemma action_gns_bounded_norm_square:
  "(norm ((action_gns_precomplete u) v))2 ≤ (norm u)2 * (norm v)2"
proof -
  { fix u v :: 'a
    have "¦ω (v† * u† * u * v)¦ ≤ ω (v† * v) * (norm (u† * u))"
      using state_norm_sandwich_leq[of v "u† * u"] by (simp add: cstar_simps)
    then have "∥ω ((u * v)† * (u * v))∥ ≤ (norm u)2 * ∥ω (v† * v)∥"
      apply (simp add: cstar_simps)
      using Bstar[simplified]
      by (smt (verit) Extra_Ordered_Fields.sign_simps(5) UNIV_I complex_of_real_cmod
          complex_of_real_mono_iff cstar_state.finner_cmod_eq cstar_state.functional_inner_def
          of_real_mult) }
  thus ?thesis
    unfolding norm_eq_sqrt_cinner[of "(action_gns_precomplete u) v"]
    unfolding norm_eq_sqrt_cinner[of v]
    apply transfer
    by (simp only: abs_norm_cancel real_sqrt_power[of _ 2, symmetric, unfolded real_sqrt_abs])
qed

lemma action_gns_bounded_norm_square':
  shows "(norm ((action_gns_precomplete' u) v))2 ≤ (norm u)2 * (norm v)2"
  using to_metric_completion_norm[of "action_gns_precomplete u v"]
  by (simp add: action_gns_precomplete'_def action_gns_bounded_norm_square)

lemma action_gns_bounded_norm:
  shows "(norm ((action_gns_precomplete u) v)) ≤ (norm u) * (norm v)"
  using action_gns_bounded_norm_square norm_ge_zero
  by (metis power2_le_imp_le power_mult_distrib zero_compare_simps(4))

lemma action_gns_bounded_norm':
  shows "(norm ((action_gns_precomplete' u) v)) ≤ (norm u) * (norm v)"
  using to_metric_completion_norm[of "action_gns_precomplete u v"]
  by (simp add: action_gns_precomplete'_def action_gns_bounded_norm)

lemma action_gns_blin: "bounded_linear (action_gns_precomplete u)"
proof -
  interpret linear "action_gns_precomplete u"
    by unfold_locales (transfer, simp add: cstar_simps)+
  have "∀x. norm (action_gns_precomplete u x) ≤ norm x * norm u"
    by (simp add: action_gns_bounded_norm[of u] cstar_simps) 
  then show ?thesis
    by unfold_locales blast
qed

lemma action_gns_blin': "bounded_linear (action_gns_precomplete' u)"
  unfolding action_gns_precomplete'_def o_def
  apply (rule bounded_linear_compose[OF _ action_gns_blin])
  using to_metric_completion_linear to_metric_completion_norm
  by (metis Groups.mult_ac(2) bounded_linear.intro
      bounded_linear_axioms_def more_arith_simps(5) order.refl)


lemma action_gns_unif_cts': "uniformly_continuous_on UNIV (action_gns_precomplete' u)"
  using bounded_linear.isUCont[OF action_gns_blin'] .



― ‹Never unfold this. Use the lemma below instead.›
definition action_gns_closure:: "'a::cstar_state ⇒ 'a gns⇒'a gns"
  where "action_gns_closure u ≡ THE g.
    (uniformly_continuous_on UNIV g) ∧
    (action_gns_precomplete' u = g ∘ to_metric_completion)"

lemma action_gns_closure:
  "uniformly_continuous_on UNIV (action_gns_closure u)"
  "action_gns_precomplete' u =
    (action_gns_closure u) ∘ to_metric_completion"
  "⋀x. x∈range to_metric_completion ⟹
    (action_gns_closure u) x = action_gns_precomplete' u (from_metric_completion x)"
  using theI'[OF lift_to_metric_completion3[OF action_gns_unif_cts'], of u]
  by (auto simp add: completion_ext_simp1 from_metric_completion_def action_gns_closure_def)


lemma action_gns_cblin: "bounded_clinear (action_gns_precomplete u)"
proof -
  interpret clinear "action_gns_precomplete u"
    apply unfold_locales 
    apply transfer
     apply (simp add: cstar_simps; fail)
    apply transfer
    using mult_scaleC_right mult_zero_right omega_linear.zero (* TODO simp set? *)
    by (metis nat_arith.rule0)
  have "∀x. norm (action_gns_precomplete u x) ≤ norm x * norm u"
    by (simp add: action_gns_bounded_norm[of u] cstar_simps) 
  then show ?thesis
    by unfold_locales blast
qed

lemma action_gns_cblin': "bounded_clinear (action_gns_precomplete' u)"
  unfolding action_gns_precomplete'_def o_def
  apply (rule bounded_clinear_compose[OF _ action_gns_cblin])
  using to_metric_completion_clinear to_metric_completion_norm
  by (metis Groups.mult_ac(2) bounded_clinear.intro
      bounded_clinear_axioms_def more_arith_simps(5) order.refl)

― ‹See \url{https://proofwiki.org/wiki/Bounded_Linear_Transformation_to_Banach_Space_has_Unique_Extension_to_Closure_of_Domain}
and \url{https://en.wikipedia.org/wiki/Continuous_linear_extension}›
lemma linear_continuous_imp_bounded:
  assumes "linear f" "continuous_on UNIV f"
  shows "bounded_linear f"
proof -
  interpret linear f using assms(1) .
  find_theorems name: continuous_on norm
  thm continuous_on_closure_norm_le continuous_on_compact_bound
  thm assms(2)[unfolded continuous_on_def tendsto_def]
  have "continuous (at 0) f"
    using assms(2) by (simp add: continuous_on_interior)
  then obtain d where "d>0" "∀x. norm (x-0) < d ⟶ norm (f x - f 0) < 1"
    unfolding dist_norm[symmetric]
    using continuous_at_eps_delta rel_simps(68) by blast
  hence d: "d>0" "⋀x. norm (x) < d ⟹ norm (f x) < 1"
    by auto
  { fix x :: 'a
    let ?dx = "d /R (2 * norm x)"
    let ?y = "?dx *R x"
    have 1: "norm ?y < d"
    proof -
      have "norm x * inverse (norm x) < 2 ∧ 0 ≤ d"
        by (metis d(1) less_le linorder_not_le mult_zero_left
            numeral_One numeral_less_iff right_inverse semiring_norm(83)
            verit_comp_simplify(21) zero_less_numeral)
      thus ?thesis
        by (simp add: Groups.mult_ac(2) d(1))
    qed
    have 2: "norm (f ?y) = ?dx * norm (f x)"
      using d(1) scaleR by fastforce
    then have 3: "?dx * norm (f x) < 1"
      using d(2)[OF 1] by presburger
    then have "norm (f x) ≤ (2 / d) * norm x"
      using norm_ge_zero zero_less_norm_iff d(1)
    proof -
      have "∀r::real. 1 * r = r"
        by simp
      moreover have "∀r ra. (r::real) * (1 / ra) = r / ra"
        by auto
      moreover have "norm (f x) < 1 / (d / (norm x * 2)) ∨ ¬ 0 < d / (norm x * 2)"
        by (metis Extra_Ordered_Fields.sign_simps(5) 3 divide_inverse linordered_field_class.pos_less_divide_eq real_scaleR_def)
      ultimately have "norm (f x) ≤ norm x * (2 / d)"
        by (metis (no_types) arith_extra_simps(18) d(1) divide_divide_eq_right less_le
            linordered_field_class.pos_less_divide_eq local.zero norm_ge_zero zero_less_norm_iff zero_less_numeral)
      then show ?thesis
        by (simp add: Extra_Ordered_Fields.sign_simps(5))
    qed
  } then
  show ?thesis
    by unfold_locales (metis Extra_Ordered_Fields.sign_simps(5))
qed

lemma linear_continuous_iff_bounded:
  assumes "linear f"
  shows "continuous_on UNIV f ⟷ bounded_linear f"
  using assms linear_continuous_imp_bounded linear_continuous_on
  by blast

lemma clinear_continuous_iff_bounded:
  assumes "clinear f"
  shows "continuous_on UNIV f ⟷ bounded_clinear f"
  using assms linear_continuous_iff_bounded
  by (metis bounded_clinear.bounded_linear
      bounded_linear_bounded_clinear clinear.linear clinear.scaleC)

lemma linear_UCont_iff_bounded:
  assumes "linear f"
  shows "uniformly_continuous_on UNIV f ⟷ bounded_linear f"
  using linear_continuous_iff_bounded[OF assms]
  using bounded_linear.isUCont uniformly_continuous_imp_continuous by blast

lemma clinear_UCont_iff_bounded:
  assumes "clinear f"
  shows "uniformly_continuous_on UNIV f ⟷ bounded_clinear f"
  using clinear_continuous_iff_bounded[OF assms]
    bounded_linear.isUCont[OF bounded_clinear.bounded_linear]
    uniformly_continuous_imp_continuous by blast

definition action_cblinfun ::
    "'a::cstar_state ⇒ ('a gns, 'a gns) cblinfun" (‹πω›)
  where "action_cblinfun u ≡ cblinfun_extension
    (range to_metric_completion)
    (map_fun from_metric_completion id (action_gns_precomplete' u))"
                                         
lemma action_cblinfun: "cblinfun_extension_exists
    (range to_metric_completion)
    (map_fun from_metric_completion id (action_gns_precomplete' u))"
  for u :: "'a::cstar_state"
proof -
  interpret bounded_clinear "action_gns_precomplete' u"
    using action_gns_cblin' .
  obtain K where K: "⋀x. norm (action_gns_precomplete' u x) ≤ norm x * K"
    using real.bounded by blast
  show ?thesis
    by (meson action_gns_bounded_norm' real.add scaleC to_metric_completion_cblinfun_exists)
qed

lemma action_cblinfun_apply:
  shows "action_cblinfun u (to_metric_completion x) = action_gns_precomplete' u x"
  using cblinfun_extension_apply[OF action_cblinfun]
  using the_inv_f_f[OF inj_to_metric_completion]
  unfolding action_cblinfun_def from_metric_completion_def
  by (smt (verit) eq_id_iff map_fun_apply rangeI)

lemma action_cblinfun_cong:
  assumes "cspan (range to_metric_completion) = cspan (to_metric_completion ` B')"
    "⋀x. x ∈ B' ⟹ action_cblinfun u (to_metric_completion x) = g (to_metric_completion x)"
  shows "cblinfun_extension (to_metric_completion ` B') g = action_cblinfun u"
  using assms
  using cblinfun_extension_cong[OF _ _ _ action_cblinfun]
  using the_inv_f_f[OF inj_to_metric_completion]
  by (smt (verit, ccfv_threshold) action_cblinfun_apply action_cblinfun_def eq_id_iff
      from_metric_completion_def image_iff image_mono map_fun_apply subset_UNIV)

lemmas action_cblinfun_apply' = cblinfun_extension_apply[OF action_cblinfun, folded action_cblinfun_def]
  and action_cblinfun_cong' = cblinfun_extension_cong[OF _ _ _ action_cblinfun, folded action_cblinfun_def]
  and action_cblinfun_restrict' = cblinfun_extension_exists_restrict[OF _ _ action_cblinfun, folded action_cblinfun_def]

lemma action_UCont: "isUCont (action_cblinfun u)"
  using clinear_UCont_iff_bounded bounded_cbilinear_apply_bounded_clinear
    bounded_cbilinear_cblinfun_apply cblinfun_apply_clinear by blast

lemma action_closure_cblinfun:
    "action_gns_closure u = (action_cblinfun u)"
proof-
  have action_cblinfun_to_completion:
    "action_gns_precomplete' u = action_cblinfun u ∘ to_metric_completion"
    "x ∈ range to_metric_completion ⟹
      action_cblinfun u x = action_gns_precomplete' u (from_metric_completion x)" for x
    by (simp_all add: action_cblinfun_apply' action_cblinfun_apply o_def)
  show ?thesis
    using action_UCont action_cblinfun_to_completion(1) action_gns_closure(1,2) action_gns_unif_cts'
      lift_to_metric_completion4 by blast
qed


text ‹The cyclic vector is the abstraction of the unit›
definition gns_1 (‹Ω›)
  where "gns_1 ≡ to_gns 1"

lemma gns_1': "Ω ∙C (action_gns_closure u Ω) = ω u"
proof -
  have "(abs_gns_precomplete 1) ∙C action_gns_precomplete u (abs_gns_precomplete 1) = ω u"
    by transfer (simp add: cstar1.unit_self_adjoint)
  then have "to_metric_completion (abs_gns_precomplete 1) ∙C
      action_gns_precomplete' u (abs_gns_precomplete 1) =
      ω u"
    unfolding action_gns_precomplete'_def
    by (simp add: to_metric_completion_cinner)
  thus ?thesis
    using action_gns_closure(2) by (metis comp_def gns_1_def to_gns_def)
qed
 
― ‹Basically an Isabelle phrasing of Bratteli and Robinson's
  last sentence on page 55 \cite{bratteli1979}.›
lemma cyclic_set:
  shows "{πω u Ω | u. True} = {to_gns u | u. True}"
    and "{action_gns_closure u Ω | u. True} = {to_gns u | u. True}"
proof -
  have "∃u. action_gns_closure v Ω = to_gns u" for v :: "'c::cstar_state"
    unfolding gns_1_def to_gns_def
    by (metis action_gns_closure(2) action_gns_precomplete'_def action_gns_precomplete_alt o_def)
  moreover have "∃v. to_gns u = action_gns_closure v Ω" for u :: "'c::cstar_state"
    unfolding gns_1_def to_gns_def
    by (metis UNIV_I action_gns_closure(2) action_gns_precomplete'_def
        action_gns_precomplete.abs_eq comp_eq_dest_lhs cstar1.multiplicative.right_unit)
  ultimately show "{action_gns_closure u Ω | u. True} = {to_gns u | u. True}"
    by (auto simp add: gns_1_def to_gns_def)
  thus "{πω u Ω | u. True} = {to_gns u | u. True}"
    by (simp add: action_closure_cblinfun)
qed

lemma gns_cyclic': "Elementary_Topology.closure {action_gns_closure u Ω | u :: 'a::cstar_state. True} = UNIV"
proof -
  have "∃u. to_metric_completion x = to_metric_completion (abs_gns_precomplete u)"
    for x :: "'b::cstar_state gns_precomplete"
    by (metis add.inverse_inverse map_fun_apply uminus_gns_precomplete_def)
  hence "{to_gns u | u. True} = range to_metric_completion"
    by (auto simp add: to_gns_def)
  thus ?thesis
    using cyclic_set(2) to_metric_completion_dense'
    by (metis (lifting) ext)
qed


subsubsection ‹The action is a homomorphism›

hide_const (open) closure

text ‹Following theory‹Smooth_Manifolds.Analysis_More›
  to instantiate the vector space on functions.›
instantiation "fun" :: (type,scaleC) scaleC
begin
definition scaleC_fun :: "complex ⇒ ('a ⇒ 'b) ⇒ 'a ⇒ 'b"
  where "scaleC_fun r f = (λx. r *C f x)"
instance
  apply intro_classes unfolding scaleC_fun_def scaleR_fun_def
  by (simp add: scaleR_scaleC)
end

instance "fun" :: (type, complex_vector) complex_vector
  by standard (auto simp: scaleC_fun_def algebra_simps)


― ‹The action is (by design) not injective.
  The norm is defined through the inner product, not as a lifting
  of the norm -- it may not be preserved exactly.›
lemma action_injective_on_quotient: "∃I. ω (I† * I) = 0 ∧ a = b + I"
  if "∀x. action_gns_precomplete a x = action_gns_precomplete b x"
  for a b :: "'a::cstar_state" and x :: "'a gns_precomplete"
    using that apply transfer
    by (metis verit_prod_simplify(2))

― ‹We already know this action outputs term‹bounded_clinear› maps.
  We don't yet know it is linear itself.›
lemma action_precomplete_morphism:
  shows "action_gns_precomplete (a+b) = action_gns_precomplete a + action_gns_precomplete b"
    and "action_gns_precomplete (a*b) = action_gns_precomplete a ∘ action_gns_precomplete b"
    and "action_gns_precomplete (c*Ca) = c *C (action_gns_precomplete a)"
    and "action_gns_precomplete 1 = id"
    and "action_gns_precomplete (involution a) = cadjoint (action_gns_precomplete a)"
proof -
  let ?pi = action_gns_precomplete
  show "?pi (a+b) = ?pi a + ?pi b"
    unfolding plus_fun_def apply (intro ext) apply transfer
    by (simp add: cross3_simps(23))
  show "?pi (a*b) = ?pi a ∘ ?pi b"
    unfolding o_def apply (intro ext) apply transfer
    by (simp add: ordered_field_class.sign_simps(4))
  show "?pi (c*Ca) = c *C (?pi a)"
    unfolding o_def scaleC_fun_def apply (intro ext) apply transfer
    by (metis arith_simps(50) mult_scaleC_left mult_zero_right omega_linear.zero)
  show "?pi 1 = id"
    unfolding id_def apply (intro ext)
    by transfer fastforce
  show "?pi (a†) = cadjoint (?pi a)"
  proof -
    have "(?pi (a†) x) ∙C y = x ∙C (?pi a y)" for x y
      apply transfer by (simp add: Groups.mult_ac(1))
    thus ?thesis
      by (metis cadjoint_eqI)
  qed
qed

lemma action_precomplete_morphism':
  shows "action_gns_precomplete' (a+b) = action_gns_precomplete' a + action_gns_precomplete' b"
    and "action_gns_precomplete' (c*Ca) = c *C (action_gns_precomplete' a)"
    and "action_gns_precomplete' 1 = to_metric_completion"
    and "action_gns_precomplete' (a*b) = action_gns_precomplete' a ∘
        from_metric_completion ∘ action_gns_precomplete' b"
    and "action_gns_precomplete' (a†) = to_metric_completion ∘
      cadjoint (from_metric_completion ∘ action_gns_precomplete' a)"
proof -
  let ?pi = action_gns_precomplete'
  show "?pi 1 = to_metric_completion"
    unfolding action_gns_precomplete'_def o_def
    by (simp add: action_precomplete_morphism(4))

  interpret clinear to_metric_completion
    using to_metric_completion_clinear .
  show "?pi (a+b) = ?pi a + ?pi b"
    unfolding action_gns_precomplete'_def o_def
    by (auto simp add: action_precomplete_morphism(1) add)
  show "?pi (c*Ca) = c *C (?pi a)"
    unfolding action_gns_precomplete'_def o_def
    by (simp only: action_precomplete_morphism(3) scaleC_fun_def scaleC)
  show "?pi (a*b) = (?pi a) ∘ from_metric_completion ∘ (?pi b)"
    unfolding action_gns_precomplete'_def
    by (metis (mono_tags) action_precomplete_morphism(2) completion_ext_simp1 o_apply)
  show "?pi (a†) = to_metric_completion ∘ (cadjoint (from_metric_completion ∘ action_gns_precomplete' a))"
    unfolding action_gns_precomplete'_def action_precomplete_morphism(5) o_def
    by (simp add: from_metric_completion_def inj_to_metric_completion the_inv_f_f)
qed

method action_uniq_eqI =
  (unfold action_gns_closure_def,
    intro the1_equality[OF lift_to_metric_completion4[OF action_gns_unif_cts']] conjI,
    fold action_gns_closure_def)

lemma
  shows action_closure_morphism:
    "action_gns_closure (a+b) = action_gns_closure a + action_gns_closure b"
    "action_gns_closure (a*b) = comp (action_gns_closure a) (action_gns_closure b)"
    "action_gns_closure (c*Ca) = c *C (action_gns_closure a)"
    "action_gns_closure 1 = id_cblinfun"
    "action_gns_closure (involution a) = cadjoint (action_gns_closure a)"
  and action_cblinfun_morphism:
    "πω (a+b) = πω a + πω b"
    "πω (a*b) = cblinfun_compose (πω a) (πω b)"
    "πω (c*Ca) = c *C (πω a)"
    "πω 1 = id_cblinfun"
    "πω (involution a) = adj (πω a)"
proof -
  show "action_gns_closure (a+b) = action_gns_closure a + action_gns_closure b"
  proof action_uniq_eqI
    show "isUCont (action_gns_closure a + action_gns_closure b)"
      unfolding plus_fun_def
      using action_gns_closure(1) uniformly_continuous_on_add by blast
    show "action_gns_precomplete' (a + b) =
        (action_gns_closure a + action_gns_closure b) ∘ to_metric_completion"
      unfolding plus_compose
      using action_gns_closure(2) action_precomplete_morphism'(1)
      by metis
  qed
  thus "πω (a+b) = πω a + πω b"
    unfolding action_closure_cblinfun
    by (intro cblinfun_eqI) (simp add: cblinfun.add_left)

  show "action_gns_closure (a*b) = action_gns_closure a ∘ action_gns_closure b"
  proof action_uniq_eqI
    show "isUCont (action_gns_closure a ∘ action_gns_closure b)"
      unfolding action_closure_cblinfun o_def
      apply (rule bounded_linear.isUCont)
      apply (rule bounded_linear_compose[of "cblinfun_apply (πω a)"])
      by (simp_all add: cblinfun.real.bounded_linear_right)
    show "action_gns_precomplete' (a * b) =
        (action_gns_closure a ∘ action_gns_closure b) ∘ to_metric_completion"
      using action_gns_closure(2) action_precomplete_morphism(2)
      by (metis (no_types, lifting) action_gns_precomplete'_def fun.map_comp)
  qed
  thus "πω (a*b) = cblinfun_compose (πω a) (πω b)"
    unfolding action_closure_cblinfun
    by (intro cblinfun_eqI) (simp)

  show "action_gns_closure (c*Ca) = c *C (action_gns_closure a)"
  proof action_uniq_eqI
    show "isUCont (c *C (action_gns_closure a))"
      unfolding action_closure_cblinfun scaleC_fun_def
      by (auto intro: bounded_linear.isUCont simp add: bounded_clinear.bounded_linear 
          bounded_clinear_scaleC_right bounded_linear_compose cblinfun.real.bounded_linear_right)
    show "action_gns_precomplete' (c*Ca) =
        (c *C (action_gns_closure a)) ∘ to_metric_completion"
      using action_gns_closure(2) action_precomplete_morphism'(2)
      unfolding o_def scaleC_fun_def by metis
  qed
  thus "πω (c*Ca) = c *C (πω a)"
    unfolding action_closure_cblinfun
    by (intro cblinfun_eqI) (simp add: scaleC_fun_def)

  show "action_gns_closure 1 = id_cblinfun"
    by (metis action_gns_closure(1,2) action_gns_unif_cts' action_precomplete_morphism'(3) apply_id_cblinfun
        bounded_linear.isUCont cblinfun.real.bounded_linear_right fun.map_id lift_to_metric_completion4)
  thus "πω 1 = id_cblinfun"
    by (smt (verit, best) action_closure_cblinfun cblinfun_eqI)

  show "action_gns_closure (a†) = cadjoint (action_gns_closure a)"
  proof action_uniq_eqI
    have cblin_action: "bounded_clinear (action_gns_closure a)"
      unfolding action_closure_cblinfun
      by (metis (no_types) bounded_clinear_intro cblinfun.add_right
          cblinfun.scaleC_right norm_cblinfun ordered_field_class.sign_simps(5))

    show "isUCont (cadjoint (action_gns_closure a))"
      by (auto intro!: bounded_linear.isUCont bounded_clinear.bounded_linear 
               simp add: cblin_action cadjoint_bounded_clinear)
    have to_metric_completion_cadjoint:
        "cadjoint (action_gns_closure a) (to_metric_completion x) ∙C
          (to_metric_completion y) =
        cadjoint (action_gns_precomplete a) x ∙C y"
      for x y :: "'a gns_precomplete"
    proof -
      let ?x = "to_metric_completion x"
      let ?y = "to_metric_completion y"
      have "cadjoint (action_gns_closure a) ?x ∙C ?y = ?x ∙C ((action_gns_closure a) ?y)"
        using cadjoint_univ_prop[OF cblin_action] by presburger
      also have "… = ?x ∙C (to_metric_completion ((action_gns_precomplete a) y))"
        using action_gns_closure(2)[unfolded action_gns_precomplete'_def o_def]
        by metis
      also have "… = x ∙C ((action_gns_precomplete a) y)"
        by (rule to_metric_completion_cinner)
      also have "… = (cadjoint (action_gns_precomplete a) x) ∙C y"
        using cadjoint_univ_prop[OF cblin_action]
        by (metis (no_types, lifting) Groups.mult_ac(1) action_gns_precomplete'_def action_gns_precomplete_alt
            action_precomplete_morphism'(3) action_precomplete_morphism(5) cinner_gns_precomplete.abs_eq involution
            ivl_times more_arith_simps(5) o_def to_metric_completion_cinner)
      finally show "cadjoint (action_gns_closure a) ?x ∙C ?y =
          cadjoint (action_gns_precomplete a) x ∙C y"
        by -
    qed

    show "action_gns_precomplete' (a†) =
        cadjoint (action_gns_closure a) ∘ to_metric_completion"
      unfolding action_gns_closure(2)
      unfolding o_def apply (intro ext)
      apply (intro cinner_extensionality_metric_completion allI)
      by (metis (mono_tags, opaque_lifting) action_cblinfun_apply action_closure_cblinfun action_gns_precomplete'_def
          action_precomplete_morphism(5) cinner_eq_flip o_def to_metric_completion_cadjoint
          to_metric_completion_cinner)
  qed
  thus "πω (involution a) = adj (πω a)"
    unfolding action_closure_cblinfun
    by (intro cblinfun_eqI) (simp add: adj.rep_eq)
qed


subsection ‹GNS theorem for term‹πω››
text ‹It's a little sparser than in textbooks: the existence of the
  Hilbert space and a representation in terms of bounded operators
  is implicit in the construction of typ‹'a::cstar_state gns›
  and term‹πω›.›

― ‹Uniqueness up to unitary equivalence is missing as of yet.›
theorem GNS_construction:
  shows gns_1: "∀u. Ω ∙C (πω u Ω) = ω u"
    and gns_cyclic: "closure {πω u Ω | u. True} = UNIV"
    and gns_hom: "πω (a+b) = πω a + πω b"
      "πω (a*b) = cblinfun_compose (πω a) (πω b)"
      "πω (c*Ca) = c *C (πω a)"
      "πω 1 = id_cblinfun"
      "πω (involution a) = adj (πω a)"
proof -
  show "∀u. Ω ∙C cblinfun_apply (πω u) Ω = ω u"
    using gns_1'[unfolded action_closure_cblinfun] by blast
  show "closure {cblinfun_apply (πω u) Ω |u. True} = UNIV"
    using gns_cyclic'[unfolded action_closure_cblinfun] .
qed (use action_cblinfun_morphism in simp_all)


unbundle cblinfun_syntax
no_notation gns_1 (‹Ω›)
no_notation action_cblinfun (‹πω›)
text ‹For presentation only, we give the existential form of the GNS construction.
  There's no disadvantage to using explicit constructions and @{thm GNS_construction}.›
theorem GNS_construction':
  obtains πω :: "'a::cstar_state ⇒ ('a gns ⇒CL 'a gns)"
    and Ω :: "'a gns"
  where ― ‹properties of ‹Ω››
        "∀u. Ω ∙C (πω u Ω) = ω u"
    and "closure {πω u Ω | u. True} = UNIV"
        ― ‹‹π› is a $^*$-homomorphism›
    and "πω (a+b) = πω a + πω b"
    and "πω (a*b) = cblinfun_compose (πω a) (πω b)"
    and "πω (c*Ca) = c *C (πω a)"
    and "πω 1 = id_cblinfun"
    and "πω (involution a) = adj (πω a)"
  using GNS_construction by blast
unbundle no cblinfun_syntax
notation gns_1 (‹Ω›)
notation action_cblinfun (‹πω›)

unbundle no lifting_syntax
unbundle no cstar_syntax
unbundle scaleC_syntax (* to undo changes from this entry *)

end