section ‹Kraus maps›
theory Kraus_Maps
imports Kraus_Families
begin
subsection ‹Kraus maps›
unbundle kraus_map_syntax
unbundle cblinfun_syntax
definition kraus_map :: ‹(('a::chilbert_space,'a) trace_class → ('b::chilbert_space,'b) trace_class) → bool› where
kraus_map_def_raw: ‹kraus_map E ⟷ (∃EE :: ('a,'b,unit) kraus_family. E = kf_apply EE)›
lemma kraus_map_def: ‹kraus_map E ⟷ (∃EE :: ('a::chilbert_space,'b::chilbert_space,'x) kraus_family. E = kf_apply EE)›
― ‹Has a more general type than the original definition›
proof (rule iffI)
assume ‹kraus_map E›
then obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
define EE' :: ‹('a,'b,'x) kraus_family› where ‹EE' = kf_map (λ_. undefined) EE›
have ‹kf_apply EE' = kf_apply EE›
by (simp add: EE'_def kf_apply_map)
with EE show ‹∃EE :: ('a,'b,'x) kraus_family. E = kf_apply EE›
by metis
next
assume ‹∃EE :: ('a,'b,'x) kraus_family. E = kf_apply EE›
then obtain EE :: ‹('a,'b,'x) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
define EE' :: ‹('a,'b,unit) kraus_family› where ‹EE' = kf_map (λ_. ()) EE›
have ‹kf_apply EE' = kf_apply EE›
by (simp add: EE'_def kf_apply_map)
with EE show ‹kraus_map E›
apply (simp add: kraus_map_def_raw)
by metis
qed
lemma kraus_mapI:
assumes ‹E = kf_apply E'›
shows ‹kraus_map E›
using assms kraus_map_def by blast
lemma kraus_map_bounded_clinear:
‹bounded_clinear E› if ‹kraus_map E›
by (metis kf_apply_bounded_clinear kraus_map_def that)
lemma kraus_map_pos:
assumes ‹kraus_map E› and ‹ρ ≥ 0›
shows ‹E ρ ≥ 0›
proof -
from assms obtain E' :: ‹('a, 'b, unit) kraus_family› where E': ‹E = kf_apply E'›
using kraus_map_def by blast
show ?thesis
by (simp add: E' assms(2) kf_apply_pos)
qed
lemma kraus_map_mono:
assumes ‹kraus_map E› and ‹ρ ≥ τ›
shows ‹E ρ ≥ E τ›
by (metis assms kf_apply_mono_right kraus_map_def_raw)
lemma kraus_map_kf_apply[iff]: ‹kraus_map (kf_apply E)›
using kraus_map_def by blast
definition km_some_kraus_family :: ‹(('a::chilbert_space, 'a) trace_class → ('b::chilbert_space, 'b) trace_class) → ('a, 'b, unit) kraus_family› where
‹km_some_kraus_family E = (if kraus_map E then SOME F. E = kf_apply F else 0)›
lemma kf_apply_km_some_kraus_family[simp]:
assumes ‹kraus_map E›
shows ‹kf_apply (km_some_kraus_family E) = E›
unfolding km_some_kraus_family_def
apply (rule someI2_ex)
using assms kraus_map_def by auto
lemma km_some_kraus_family_invalid:
assumes ‹¬ kraus_map E›
shows ‹km_some_kraus_family E = 0›
by (simp add: assms km_some_kraus_family_def)
definition km_operators_in :: ‹(('a::chilbert_space,'a) trace_class → ('b::chilbert_space,'b) trace_class) → ('a →CL 'b) set → bool› where
‹km_operators_in E S ⟷ (∃F :: ('a,'b,unit) kraus_family. kf_apply F = E ∧ kf_operators F ⊆ S)›
lemma km_operators_in_mono: ‹S ⊆ T ==> km_operators_in E S ==> km_operators_in E T›
by (metis basic_trans_rules(23) km_operators_in_def)
lemma km_operators_in_kf_apply:
assumes ‹span (kf_operators E) ⊆ S›
shows ‹km_operators_in (kf_apply E) S›
proof (unfold km_operators_in_def, intro conjI exI[where x=‹kf_flatten E›])
show ‹(*\<^sub>k\<^sub>r) (kf_flatten \) = (*\<^sub>k\<^sub>r) \\
by simp
from assms show ‹kf_operators (kf_flatten E) ⊆ S›
using kf_operators_kf_map by fastforce
km_operators_in_kf_apply_flattened:
fixes E :: ‹('a::chilbert_space,'b::chilbert_space,'x::CARD_1) kraus_family›
assumes ‹kf_operators E ⊆ S›
shows ‹km_operators_in (kf_apply E) S›
(unfold km_operators_in_def, intro conjI exI[where x=‹kf_map_inj (λx.()) E›])
show ‹(*\<^sub>k\<^sub>r) (kf_map_inj (\\. ()) \) = (*\<^sub>k\<^sub>r) \\
by (auto intro!: ext kf_apply_map_inj inj_onI)
have ‹kf_operators (kf_map_inj (λF. ()) E) = kf_operators E›
by simp
with assms show ‹kf_operators (kf_map_inj (λF. ()) E) ⊆ S›
by blast
km_commute:
assumes ‹km_operators_in E S›
assumes ‹km_operators_in F T›
assumes ‹S ⊆ commutant T›
shows ‹F o E = E o F›
-
from assms obtain E' :: ‹(_,_,unit) kraus_family› where E': ‹E = kf_apply E'› and E'S: ‹kf_operators E' ⊆ S›
by (metis km_operators_in_def)
from assms obtain F' :: ‹(_,_,unit) kraus_family› where F': ‹F = kf_apply F'› and F'T: ‹kf_operators F' ⊆ T›
by (metis km_operators_in_def)
have ‹kf_operators E' ⊆ S›
by (rule E'S)
also have ‹S ⊆ commutant T›
by (rule assms)
also have ‹commutant T ⊆ commutant (kf_operators F')›
apply (rule commutant_antimono)
by (rule F'T)
finally show ?thesis
unfolding E' F'
by (rule kf_apply_commute[symmetric])
km_operators_in_UNIV:
assumes ‹kraus_map E›
shows ‹km_operators_in E UNIV›
by (metis assms kf_apply_km_some_kraus_family km_operators_in_def top.extremum)
separating_kraus_map_bounded_clinear:
fixes S :: ‹('a::chilbert_space,'a) trace_class set›
assumes ‹separating_set (bounded_clinear :: (_ → ('b::chilbert_space,'b) trace_class) → _) S›
shows ‹separating_set (kraus_map :: (_ → ('b::chilbert_space,'b) trace_class) → _) S›
by (metis (mono_tags, lifting) assms kraus_map_bounded_clinear separating_set_def)
‹Bound and norm›
km_bound :: ‹(('a::chilbert_space, 'a) trace_class → ('b::chilbert_space, 'b) trace_class) → ('a, 'a) cblinfun› where
‹km_bound E = (if ∃E' :: (_, _, unit) kraus_family. E = kf_apply E' then kf_bound (SOME E' :: (_, _, unit) kraus_family. E = kf_apply E') else 0)›
km_bound_kf_bound:
assumes ‹E = kf_apply F›
shows ‹km_bound E = kf_bound F›
-
wlog ex: ‹∃E' :: (_, _, unit) kraus_family. E = kf_apply E'›
using assms kraus_map_def_raw negation by blast
define E' where ‹E' = (SOME E' :: (_, _, unit) kraus_family. E = kf_apply E')›
have ‹E = kf_apply (kf_flatten F)›
by (simp add: assms)
then have ‹E = kf_apply E'›
by (metis (mono_tags, lifting) E'_def someI_ex)
then have ‹E' =kr F›
using assms kf_eq_weak_def by force
then have ‹kf_bound E' = kf_bound F›
using kf_bound_cong by blast
then show ?thesis
by (metis E'_def km_bound_def ex)
km_norm :: ‹(('a::chilbert_space, 'a) trace_class → ('b::chilbert_space, 'b) trace_class) → real› where
‹km_norm E = norm (km_bound E)›
km_norm_kf_norm:
assumes ‹E = kf_apply F›
shows ‹km_norm E = kf_norm F›
by (simp add: assms kf_norm_def km_bound_kf_bound km_norm_def)
km_bound_invalid:
assumes ‹¬ kraus_map E›
shows ‹km_bound E = 0›
by (metis assms km_bound_def kraus_map_def_raw)
km_norm_invalid:
assumes ‹¬ kraus_map E›
shows ‹km_norm E = 0›
by (simp add: assms km_bound_invalid km_norm_def)
km_norm_geq0[iff]: ‹km_norm E ≥ 0›
by (simp add: km_norm_def)
kf_bound_pos[iff]: ‹km_bound E ≥ 0›
apply (cases ‹kraus_map E›)
apply (simp add: km_bound_def)
by (simp add: km_bound_invalid)
km_bounded_pos:
assumes ‹kraus_map E› and ‹ρ ≥ 0›
shows ‹norm (E ρ) ≤ km_norm E * norm ρ›
-
from assms obtain E' :: ‹('a, 'b, unit) kraus_family› where E': ‹E = kf_apply E'›
using kraus_map_def by blast
show ?thesis
by (simp add: E' assms(2) kf_apply_bounded_pos km_norm_kf_norm)
km_bounded:
assumes ‹kraus_map E›
shows ‹norm (E ρ) ≤ 4 * km_norm E * norm ρ›
-
from assms obtain E' :: ‹('a, 'b, unit) kraus_family› where E': ‹E = kf_apply E'›
using kraus_map_def by blast
show ?thesis
by (simp add: E' kf_apply_bounded km_norm_kf_norm)
km_bound_from_map:
assumes ‹kraus_map E›
shows ‹ψ ∙C km_bound E φ = trace_tc (E (tc_butterfly φ ψ))›
by (metis assms kf_bound_from_map km_bound_kf_bound kraus_map_def_raw)
trace_from_km_bound:
assumes ‹kraus_map E›
shows ‹trace_tc (E ρ) = trace_tc (compose_tcr (km_bound E) ρ)›
by (metis assms km_bound_kf_bound kraus_map_def_raw trace_from_kf_bound)
km_bound_selfadjoint[iff]: ‹selfadjoint (km_bound E)›
by (simp add: pos_selfadjoint)
km_bound_leq_km_norm_id: ‹km_bound E ≤ km_norm E *R id_cblinfun›
by (simp add: km_norm_def less_eq_scaled_id_norm)
kf_norm_km_some_kraus_family[simp]: ‹kf_norm (km_some_kraus_family E) = km_norm E›
apply (cases ‹kraus_map E›)
by (auto intro!: km_norm_kf_norm[symmetric] simp: km_some_kraus_family_invalid km_norm_invalid)
‹Basic Kraus maps›
‹Zero map and constant maps. Addition and rescaling and composition of maps.›
kraus_map_0[iff]: ‹kraus_map 0›
by (metis kf_apply_0 kraus_mapI)
kraus_map_0'[iff]: ‹kraus_map (λ_. 0)›
using kraus_map_0 unfolding func_zero by simp
km_bound_0[simp]: ‹km_bound 0 = 0›
using km_bound_kf_bound[of 0 0]
by simp
km_norm_0[simp]: ‹km_norm 0 = 0›
by (simp add: km_norm_def)
km_some_kraus_family_0[simp]: ‹km_some_kraus_family 0 = 0›
apply (rule kf_eq_0_iff_eq_0[THEN iffD1])
by (simp add: kf_eq_weak_def)
kraus_map_id[iff]: ‹kraus_map id›
by (auto intro!: ext kraus_mapI[of _ kf_id])
km_bound_id[simp]: ‹km_bound id = id_cblinfun›
using km_bound_kf_bound[of id kf_id]
by (simp add: kf_id_apply[abs_def] id_def)
km_norm_id_leq1[iff]: ‹km_norm id ≤ 1›
by (simp add: km_norm_def norm_cblinfun_id_le)
km_norm_id_eq1[simp]: ‹km_norm (id :: ('a :: {chilbert_space, not_singleton}, 'a) trace_class → _) = 1›
by (simp add: km_norm_def)
km_operators_in_id[iff]: ‹km_operators_in id {id_cblinfun}›
apply (subst asm_rl[of ‹id = kf_apply kf_id›])
by (auto simp: km_operators_in_kf_apply_flattened)
kraus_map_add[iff]:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹kraus_map (λρ. E ρ + F ρ)›
-
from assms obtain E' :: ‹('a, 'b, unit) kraus_family› where E': ‹E = kf_apply E'›
using kraus_map_def by blast
from assms obtain F' :: ‹('a, 'b, unit) kraus_family› where F': ‹F = kf_apply F'›
using kraus_map_def by blast
show ?thesis
apply (rule kraus_mapI[of _ ‹E' + F'›])
by (auto intro!: ext simp: E' F' kf_plus_apply')
kraus_map_plus'[iff]:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹kraus_map (E + F)›
using assms by (simp add: plus_fun_def)
km_bound_plus:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹km_bound (E + F) = km_bound E + km_bound F›
-
from assms obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from assms obtain FF :: ‹('a,'b,unit) kraus_family› where FF: ‹F = kf_apply FF›
using kraus_map_def_raw by blast
show ?thesis
apply (rule km_bound_kf_bound[where F=‹EE + FF›, THEN trans])
by (auto intro!: ext simp: EE FF kf_plus_apply' kf_plus_bound' km_bound_kf_bound)
km_norm_triangle:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹km_norm (E + F) ≤ km_norm E + km_norm F›
by (simp add: km_norm_def km_bound_plus assms norm_triangle_ineq)
kraus_map_constant[iff]: ‹kraus_map (λσ. trace_tc σ *C ρ)› if ‹ρ ≥ 0›
apply (rule kraus_mapI[where E'=‹kf_constant ρ›])
by (simp add: kf_constant_apply[OF that, abs_def])
kraus_map_constant_invalid:
‹¬ kraus_map (λσ :: ('a::{chilbert_space,not_singleton},'a) trace_class. trace_tc σ *C ρ)› if ‹~ ρ ≥ 0›
(rule ccontr)
assume ‹¬ ¬ kraus_map (λσ :: ('a,'a) trace_class. trace_tc σ *C ρ)›
then have km: ‹kraus_map (λσ :: ('a,'a) trace_class. trace_tc σ *C ρ)›
by simp
obtain h :: 'a where ‹norm h = 1›
using ex_norm1_not_singleton by blast
from km have ‹trace_tc (tc_butterfly h h) *C ρ ≥ 0›
using kraus_map_pos by fastforce
with ‹norm h = 1›
have ‹ρ ≥ 0›
by (metis mult_cancel_left2 norm_tc_butterfly norm_tc_pos of_real_1 scaleC_one tc_butterfly_pos)
with that show False
by simp
kraus_map_scale:
assumes ‹kraus_map E› and ‹c ≥ 0›
shows ‹kraus_map (λρ. c *R E ρ)›
-
from assms obtain E' :: ‹('a, 'b, unit) kraus_family› where E': ‹E = kf_apply E'›
using kraus_map_def by blast
then show ?thesis
apply (rule_tac kraus_mapI[where E'=‹c *R E'›])
by (auto intro!: ext simp add: E' kf_scale_apply assms)
km_bound_scale[simp]: ‹km_bound (λρ. c *R E ρ) = c *R km_bound E› if ‹c ≥ 0›
-
consider (km) ‹kraus_map E› | (c0) ‹c = 0› | (not_km) ‹¬ kraus_map E› ‹c > 0›
using ‹0 ≤ c› by argo
then show ?thesis
proof cases
case km
then obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
with ‹c ≥ 0 ›have ‹kf_bound (c *R EE) = c *R kf_bound EE›
by simp
then show ?thesis
using km_bound_kf_bound[of ‹λρ. c *R E ρ› ‹c *R EE›, symmetric]
using kf_scale_apply[OF ‹c ≥ 0›, of EE, abs_def]
by (simp add: EE km_bound_kf_bound)
next
case c0
then show ?thesis
by (simp flip: func_zero)
next
case not_km
have ‹¬ kraus_map (λρ. c *R E ρ)›
proof (rule ccontr)
assume ‹¬ ¬ kraus_map (λρ. c *R E ρ)›
then have ‹kraus_map (λρ. inverse c *R (c *R E ρ))›
apply (rule_tac kraus_map_scale)
using not_km by auto
then have ‹kraus_map E›
using not_km by (simp add: scaleR_scaleR field.field_inverse)
with not_km show False
by simp
qed
with not_km show ?thesis
by (simp add: km_bound_invalid)
qed
km_norm_scale[simp]: ‹km_norm (λρ. c *R E ρ) = c * km_norm E› if ‹c ≥ 0›
using that by (simp add: km_norm_def)
kraus_map_sandwich[iff]: ‹kraus_map (sandwich_tc A)›
apply (rule kraus_mapI[of _ ‹kf_of_op A›])
using kf_of_op_apply[of A, abs_def]
by simp
km_bound_sandwich[simp]: ‹km_bound (sandwich_tc A) = A* oCL A›
using km_bound_kf_bound[of ‹sandwich_tc A› ‹kf_of_op A›, symmetric]
using kf_bound_of_op[of A]
using kf_of_op_apply[of A]
by fastforce
km_norm_sandwich[simp]: ‹km_norm (sandwich_tc A) = (norm A)2›
by (simp add: km_norm_def)
km_operators_in_sandwich: ‹km_operators_in (sandwich_tc U) {U}›
apply (subst kf_of_op_apply[abs_def, symmetric])
apply (rule km_operators_in_kf_apply_flattened)
by simp
km_constant_bound[simp]: ‹km_bound (λσ. trace_tc σ *C ρ) = norm ρ *R id_cblinfun› if ‹ρ ≥ 0›
apply (rule km_bound_kf_bound[THEN trans])
using that apply (rule kf_constant_apply[symmetric, THEN ext])
using that by (rule kf_bound_constant)
km_constant_norm[simp]: ‹km_norm (λσ::('a::{chilbert_space,not_singleton},'a) trace_class. trace_tc σ *C ρ) = norm ρ› if ‹ρ ≥ 0›
apply (subst km_norm_kf_norm[of ‹(λσ::('a,'a) trace_class. trace_tc σ *C ρ)› ‹kf_constant ρ›])
apply (subst kf_constant_apply[OF that, abs_def], rule refl)
apply (rule kf_norm_constant)
by (fact that)
km_constant_norm_leq[simp]: ‹km_norm (λσ::('a::chilbert_space,'a) trace_class. trace_tc σ *C ρ) ≤ norm ρ›
-
consider (pos) ‹ρ ≥ 0› | (singleton) ‹¬ class.not_singleton TYPE('a)› | (nonpos) ‹¬ ρ ≥ 0› ‹class.not_singleton TYPE('a)›
by blast
then show ?thesis
proof cases
case pos
show ?thesis
apply (subst km_norm_kf_norm[of ‹(λσ::('a,'a) trace_class. trace_tc σ *C ρ)› ‹kf_constant ρ›])
apply (subst kf_constant_apply[OF pos, abs_def], rule refl)
by (rule kf_norm_constant_leq)
next
case nonpos
have ‹¬ kraus_map (λσ::('a,'a) trace_class. trace_tc σ *C ρ)›
apply (rule kraus_map_constant_invalid[internalize_sort' 'a])
apply (rule chilbert_space_axioms)
using nonpos by -
then have ‹km_norm (λσ::('a,'a) trace_class. trace_tc σ *C ρ) = 0›
using km_norm_invalid by blast
then show ?thesis
by (metis norm_ge_zero)
next
case singleton
then have ‹(λσ::('a,'a) trace_class. trace_tc σ *C ρ) = 0›
apply (subst not_not_singleton_tc_zero)
by auto
then show ?thesis
by simp
qed
kraus_map_comp:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹kraus_map (E o F)›
-
from assms obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from assms obtain FF :: ‹('c,'a,unit) kraus_family› where FF: ‹F = kf_apply FF›
using kraus_map_def_raw by blast
show ?thesis
apply (rule kraus_mapI[where E'=‹kf_comp EE FF›])
by (simp add: EE FF kf_comp_apply)
km_comp_norm_leq:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹km_norm (E o F) ≤ km_norm E * km_norm F›
-
from assms obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from assms obtain FF :: ‹('c,'a,unit) kraus_family› where FF: ‹F = kf_apply FF›
using kraus_map_def_raw by blast
have ‹km_norm (E o F) = kf_norm (kf_comp EE FF)›
by (simp add: EE FF kf_comp_apply km_norm_kf_norm)
also have ‹… ≤ kf_norm EE * kf_norm FF›
by (simp add: kf_comp_norm_leq)
also have ‹… = km_norm E * km_norm F›
by (simp add: EE FF km_norm_kf_norm)
finally show ?thesis
by -
km_bound_comp_sandwich:
assumes ‹kraus_map E›
shows \<open>km_bound (\<lambda>\<rho>. \<EE> (sandwich_tc U \<rho>)) = sandwich (U*) (km_bound E)›
proof -
from assms obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
have \<open>km_bound (\<lambda>\<rho>. \<EE> (sandwich_tc U \<rho>)) = kf_bound (kf_comp EE (kf_of_op U))\<close>
apply (rule km_bound_kf_bound)
by (simp add: kf_comp_apply o_def EE kf_of_op_apply)
also have \<open>\<dots> = sandwich (U*) *V kf_bound EE›
by (simp add: kf_bound_comp_of_op)
also have ‹… = sandwich (U*) (km_bound E)›
by (simp add: EE km_bound_kf_bound)
finally show ?thesis
by -
qed
(* lemma sandwich_tc_compose: \<open>sandwich_tc A (sandwich_tc B \<rho>) = sandwich_tc (A o\<^sub>C\<^sub>L B) \<rho>\<close>
apply transfer'
by (simp add: sandwich_compose) *)
lemma km_norm_comp_sandwich_coiso:
assumes ‹isometry (U*)›
shows ‹km_norm (λρ. E (sandwich_tc U ρ)) = km_norm E›
proof (cases ‹kraus_map E›)
case True
then obtain EE :: ‹(_,_,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
have ‹km_norm (λρ. E (sandwich_tc U ρ)) = kf_norm (kf_comp EE (kf_of_op U))›
apply (rule km_norm_kf_norm)
by (auto intro!: simp: kf_comp_apply o_def EE kf_of_op_apply)
also have ‹… = kf_norm EE›
by (simp add: assms kf_norm_comp_of_op_coiso)
also have ‹… = km_norm E›
by (simp add: EE km_norm_kf_norm)
finally show ?thesis
by -
next
case False
have ‹¬ kraus_map (λρ. E (sandwich_tc U ρ))›
proof (rule ccontr)
assume ‹¬ ¬ kraus_map (λρ. E (sandwich_tc U ρ))›
then have ‹kraus_map (λρ. E (sandwich_tc U ρ))›
by blast
then have ‹kraus_map (λρ. E (sandwich_tc U (sandwich_tc (U*) ρ)))›
apply (rule kraus_map_comp[unfolded o_def])
by fastforce
then have ‹kraus_map E›
using isometryD[OF assms]
by (simp flip: sandwich_tc_compose[unfolded o_def, THEN fun_cong])
then show False
using False by blast
qed
with False show ?thesis
by (simp add: km_norm_invalid)
qed
lemma km_bound_comp_sandwich_iso:
assumes ‹isometry U›
shows ‹km_bound (λρ. sandwich_tc U (E ρ)) = km_bound E›
proof (cases ‹kraus_map E›)
case True
then obtain EE :: ‹(_,_,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
have ‹km_bound (λρ. sandwich_tc U (E ρ)) = kf_bound (kf_comp (kf_of_op U) EE)›
apply (rule km_bound_kf_bound)
by (auto intro!: simp: kf_comp_apply o_def EE kf_of_op_apply)
also have ‹… = kf_bound EE›
by (simp add: assms kf_bound_comp_iso)
also have ‹… = km_bound E›
by (simp add: EE km_bound_kf_bound)
finally show ?thesis
by -
next
case False
have ‹¬ kraus_map (λρ. sandwich_tc U (E ρ))›
proof (rule ccontr)
assume ‹¬ ¬ kraus_map (λρ. sandwich_tc U (E ρ))›
then have ‹kraus_map (λρ. sandwich_tc U (E ρ))›
by blast
then have ‹kraus_map (λρ. sandwich_tc (U*) (sandwich_tc U (E ρ)))›
apply (rule kraus_map_comp[unfolded o_def, rotated])
by fastforce
then have ‹kraus_map E›
using isometryD[OF assms]
by (simp flip: sandwich_tc_compose[unfolded o_def, THEN fun_cong])
then show False
using False by blast
qed
with False show ?thesis
by (simp add: km_bound_invalid)
qed
lemma km_norm_comp_sandwich_iso:
assumes ‹isometry U›
shows ‹km_norm (λρ. sandwich_tc U (E ρ)) = km_norm E›
proof (cases ‹kraus_map E›)
case True
then obtain EE :: ‹(_,_,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
have ‹km_norm (λρ. sandwich_tc U (E ρ)) = kf_norm (kf_comp (kf_of_op U) EE)›
apply (rule km_norm_kf_norm)
by (auto intro!: simp: kf_comp_apply o_def EE kf_of_op_apply)
also have ‹… = kf_norm EE›
by (simp add: assms kf_norm_comp_iso)
also have ‹… = km_norm E›
by (simp add: EE km_norm_kf_norm)
finally show ?thesis
by -
next
case False
have ‹¬ kraus_map (λρ. sandwich_tc U (E ρ))›
proof (rule ccontr)
assume ‹¬ ¬ kraus_map (λρ. sandwich_tc U (E ρ))›
then have ‹kraus_map (λρ. sandwich_tc U (E ρ))›
by blast
then have ‹kraus_map (λρ. sandwich_tc (U*) (sandwich_tc U (E ρ)))›
apply (rule kraus_map_comp[unfolded o_def, rotated])
by fastforce
then have ‹kraus_map E›
using isometryD[OF assms]
by (simp flip: sandwich_tc_compose[unfolded o_def, THEN fun_cong])
then show False
using False by blast
qed
with False show ?thesis
by (simp add: km_norm_invalid)
qed
lemma kraus_map_sum:
assumes ‹∧x. x∈A ==> kraus_map (E x)›
shows ‹kraus_map (∑x∈A. E x)›
apply (insert assms, induction A rule:infinite_finite_induct)
by auto
lemma km_bound_sum:
assumes ‹∧x. x∈A ==> kraus_map (E x)›
shows ‹km_bound (∑x∈A. E x) = (∑x∈A. km_bound (E x))›
proof (insert assms, induction A rule:infinite_finite_induct)
case (infinite A)
then show ?case
by (metis km_bound_0 sum.infinite)
next
case empty
then show ?case
by (metis km_bound_0 sum.empty)
next
case (insert x F)
have ‹km_bound (∑x∈insert x F. E x) = km_bound (E x + (∑x∈F. E x))›
by (simp add: insert.hyps)
also have ‹… = km_bound (E x) + km_bound (∑x∈F. E x)›
by (simp add: km_bound_plus kraus_map_sum insert.prems)
also have ‹… = km_bound (E x) + (∑x∈F. km_bound (E x))›
by (simp add: insert)
also have ‹… = (∑x∈insert x F. km_bound (E x))›
using insert.hyps by fastforce
finally show ?case
by -
qed
subsection ‹Infinite sums›
lemma
assumes ‹∧ρ. ((λa. sandwich_tc (f a) ρ) has_sum E ρ) A›
defines ‹EE ≡ Set.filter (λ(E,_). E≠0) ((λa. (f a, a)) ` A)›
shows kraus_mapI_sum: ‹kraus_map E›
and kraus_map_sum_kraus_family: ‹kraus_family EE›
and kraus_map_sum_kf_apply: ‹E = kf_apply (Abs_kraus_family EE)›
proof -
show ‹kraus_family EE›
unfolding EE_def
apply (rule kf_reconstruction_is_kraus_family)
by (fact assms(1))
show ‹E = kf_apply (Abs_kraus_family EE)›
unfolding EE_def
apply (rule kf_reconstruction[symmetric])
by (fact assms(1))
then show ‹kraus_map E›
by (rule kraus_mapI)
qed
lemma kraus_map_infsum_sandwich:
assumes ‹∧ρ. (λa. sandwich_tc (f a) ρ) summable_on A›
shows ‹kraus_map (λρ. ∑\∞a∈A. sandwich_tc (f a) ρ)›
apply (rule kraus_mapI_sum)
using assms by (rule has_sum_infsum)
lemma kraus_map_sum_sandwich: ‹kraus_map (λρ. ∑a∈A. sandwich_tc (f a) ρ)›
apply (cases ‹finite A›)
apply (simp add: kraus_map_infsum_sandwich flip: infsum_finite)
by simp
lemma kraus_map_as_infsum:
assumes ‹kraus_map E›
shows ‹∃M. ∀ρ. ((λE. sandwich_tc E ρ) has_sum E ρ) M›
proof -
from assms obtain E' :: ‹('a, 'b, unit) kraus_family› where E': ‹E = kf_apply E'›
using kraus_map_def by blast
define M where ‹M = fst ` Rep_kraus_family E'›
have ‹((λE. sandwich_tc E ρ) has_sum E ρ) M› for ρ
proof -
have [simp]: ‹inj_on fst (Rep_kraus_family E')›
by (auto intro!: inj_onI)
from kf_apply_has_sum[of ρ E']
have ‹((λ(E, x). sandwich_tc E ρ) has_sum kf_apply E' ρ) (Rep_kraus_family E')›
by -
then show ?thesis
by (simp add: M_def has_sum_reindex o_def case_prod_unfold E')
qed
then show ?thesis
by auto
qed
definition km_summable :: ‹('a → ('b::chilbert_space,'b) trace_class → ('c::chilbert_space,'c) trace_class) → 'a set → bool› where
‹km_summable E A ⟷ summable_on_in cweak_operator_topology (λa. km_bound (E a)) A›
lemma km_summable_kf_summable:
assumes ‹∧a ρ. a ∈ A ==> E a ρ = F a *kr ρ›
shows ‹km_summable E A ⟷ kf_summable F A›
proof -
have ‹km_summable E A ⟷ summable_on_in cweak_operator_topology (λa. km_bound (E a)) A›
using km_summable_def by blast
also have ‹… ⟷ summable_on_in cweak_operator_topology (λa. kf_bound (F a)) A›
apply (rule summable_on_in_cong)
apply (rule km_bound_kf_bound)
using assms by fastforce
also have ‹… ⟷ kf_summable F A›
using kf_summable_def by blast
finally show ?thesis
by -
qed
lemma km_summable_summable:
assumes km: ‹∧a. a∈A ==> kraus_map (E a)›
assumes sum: ‹km_summable E A›
shows ‹(λa. E a ρ) summable_on A›
proof -
from km
obtain EE :: ‹_ → (_,_,unit) kraus_family› where EE: ‹E a = kf_apply (EE a)› if ‹a ∈ A› for a
apply atomize_elim
apply (rule_tac choice)
by (simp add: kraus_map_def_raw)
from sum
have ‹kf_summable EE A›
by (simp add: EE km_summable_kf_summable)
then have ‹(λa. EE a *kr ρ) summable_on A›
by (rule kf_infsum_apply_summable)
then show ?thesis
by (metis (mono_tags, lifting) EE summable_on_cong)
qed
lemma kraus_map_infsum:
assumes km: ‹∧a. a∈A ==> kraus_map (E a)›
assumes sum: ‹km_summable E A›
shows ‹kraus_map (λρ. ∑\∞a∈A. E a ρ)›
proof -
from km
obtain EE :: ‹_ → (_,_,unit) kraus_family› where EE: ‹E a = kf_apply (EE a)› if ‹a ∈ A› for a
apply atomize_elim
apply (rule_tac choice)
by (simp add: kraus_map_def_raw)
from sum
have ‹kf_summable EE A›
by (simp add: EE km_summable_kf_summable)
then have ‹kf_infsum EE A *kr ρ = (∑\∞a∈A. EE a *kr ρ)› for ρ
by (metis kf_infsum_apply)
also have ‹… ρ = (∑\∞a∈A. E a ρ)› for ρ
by (metis (mono_tags, lifting) EE infsum_cong)
finally show ?thesis
apply (rule_tac kraus_mapI[of _ ‹kf_infsum EE A›])
by auto
qed
lemma km_bound_infsum:
assumes km: ‹∧a. a∈A ==> kraus_map (E a)›
assumes sum: ‹km_summable E A›
shows ‹km_bound (λρ. ∑\∞a∈A. E a ρ) = infsum_in cweak_operator_topology (λa. km_bound (E a)) A›
proof -
from km
obtain EE :: ‹_ → (_,_,unit) kraus_family› where EE: ‹E a = kf_apply (EE a)› if ‹a ∈ A› for a
apply atomize_elim
apply (rule_tac choice)
by (simp add: kraus_map_def_raw)
from sum have ‹kf_summable EE A›
by (simp add: EE km_summable_kf_summable)
have ‹km_bound (λρ. ∑\∞a∈A. E a ρ) = km_bound (λρ. ∑\∞a∈A. EE a *kr ρ)›
apply (rule arg_cong[where f=km_bound])
by (auto intro!: infsum_cong simp add: EE)
also have ‹… = kf_bound (kf_infsum EE A)›
apply (rule km_bound_kf_bound)
using kf_infsum_apply[OF ‹kf_summable EE A›]
by auto
also have ‹… = infsum_in cweak_operator_topology (λa. kf_bound (EE a)) A›
using ‹kf_summable EE A› kf_bound_infsum by fastforce
also have ‹… = infsum_in cweak_operator_topology (λa. km_bound (E a)) A›
by (metis (mono_tags, lifting) EE infsum_in_cong km_bound_kf_bound)
finally show ?thesis
by -
qed
lemma km_norm_infsum:
assumes km: ‹∧a. a∈A ==> kraus_map (E a)›
assumes sum: ‹(λa. km_norm (E a)) summable_on A›
shows ‹km_norm (λρ. ∑\∞a∈A. E a ρ) ≤ (∑\∞a∈A. km_norm (E a))›
proof -
from km
obtain EE :: ‹_ → (_,_,unit) kraus_family› where EE: ‹E a = kf_apply (EE a)› if ‹a ∈ A› for a
apply atomize_elim
apply (rule_tac choice)
by (simp add: kraus_map_def_raw)
from sum have sum1: ‹(λa. kf_norm (EE a)) summable_on A›
by (metis (mono_tags, lifting) EE km_norm_kf_norm summable_on_cong)
then have sum2: ‹kf_summable EE A›
using kf_summable_from_abs_summable by blast
have ‹km_norm (λρ. ∑\∞a∈A. E a ρ) = km_norm (λρ. ∑\∞a∈A. EE a *kr ρ)›
apply (rule arg_cong[where f=km_norm])
apply (rule ext)
apply (rule infsum_cong)
by (simp add: EE)
also have ‹… = kf_norm (kf_infsum EE A)›
apply (subst kf_infsum_apply[OF sum2, abs_def, symmetric])
using km_norm_kf_norm by blast
also have ‹… ≤ (∑\∞a∈A. kf_norm (EE a))›
by (metis kf_norm_infsum sum1)
also have ‹… = (∑\∞a∈A. km_norm (E a))›
by (metis (mono_tags, lifting) EE infsum_cong km_norm_kf_norm)
finally show ?thesis
by -
qed
lemma kraus_map_has_sum:
assumes ‹∧x. x ∈ A ==> kraus_map (E x)›
assumes ‹km_summable E A›
assumes ‹(E has_sum F) A›
shows ‹kraus_map F›
proof -
from ‹(E has_sum F) A›
have ‹((λx. E x t) has_sum F t) A› for t
by (simp add: has_sum_coordinatewise)
then have ‹F t = (∑\∞a∈A. E a t)› for t
by (metis infsumI)
with kraus_map_infsum[OF assms(1,2)]
show ‹kraus_map F›
by presburger
qed
lemma km_summable_iff_sums_to_kraus_map:
assumes ‹∧a. a∈A ==> kraus_map (E a)›
shows ‹km_summable E A ⟷ (∃F. (∀t. ((λx. E x t) has_sum F t) A) ∧ kraus_map F)›
proof (rule iffI)
assume asm: ‹km_summable E A›
define F where ‹F t = (∑\∞a∈A. E a t)› for t
from km_summable_summable[OF assms asm]
have ‹((λx. E x t) has_sum F t) A› for t
using F_def by fastforce
moreover from kraus_map_infsum[OF assms asm]
have ‹kraus_map F›
by (simp add: F_def[abs_def])
ultimately show ‹(∃F. (∀t. ((λx. E x t) has_sum F t) A) ∧ kraus_map F)›
by auto
next
assume ‹∃F. (∀t. ((λx. E x t) has_sum F t) A) ∧ kraus_map F›
then obtain F where ‹kraus_map F› and ‹((λx. E x t) has_sum F t) A› for t
by auto
then have ‹((λx. trace_tc (E x (tc_butterfly k h))) has_sum trace_tc (F (tc_butterfly k h))) A› for h k
using bounded_clinear.bounded_linear bounded_clinear_trace_tc has_sum_bounded_linear by blast
then have ‹((λx. trace_tc (E x (tc_butterfly k h))) has_sum h ∙C (km_bound F *V k)) A› for h k
by (simp add: km_bound_from_map ‹kraus_map F›)
then have ‹((λx. h ∙C (km_bound (E x) *V k)) has_sum h ∙C (km_bound F *V k)) A› for h k
apply (rule has_sum_cong[THEN iffD1, rotated 1])
by (simp add: km_bound_from_map assms)
then have ‹has_sum_in cweak_operator_topology (λa. km_bound (E a)) A (km_bound F)›
by (simp add: has_sum_in_cweak_operator_topology_pointwise)
then show ‹km_summable E A›
using summable_on_in_def km_summable_def by blast
qed
subsection ‹Tensor products›
definition km_tensor_exists :: ‹(('a ell2, 'b ell2) trace_class → ('c ell2, 'd ell2) trace_class)
→ (('e ell2, 'f ell2) trace_class → ('g ell2, 'h ell2) trace_class) → bool› where
‹km_tensor_exists E F ⟷ (∃EF. bounded_clinear EF ∧ (∀ρ σ. EF (tc_tensor ρ σ) = tc_tensor (E ρ) (F σ)))›
definition km_tensor :: ‹(('a ell2, 'c ell2) trace_class → ('e ell2, 'g ell2) trace_class)
→ (('b ell2, 'd ell2) trace_class → ('f ell2, 'h ell2) trace_class)
→ (('a × 'b) ell2, ('c × 'd) ell2) trace_class → (('e × 'f) ell2, ('g × 'h) ell2) trace_class› where
‹km_tensor E F = (if km_tensor_exists E F
then SOME EF. bounded_clinear EF ∧ (∀ρ σ. EF (tc_tensor ρ σ) = tc_tensor (E ρ) (F σ))
else 0)›
lemma km_tensor_invalid:
assumes ‹¬ km_tensor_exists E F›
shows ‹km_tensor E F = 0›
by (simp add: assms km_tensor_def)
lemma km_tensor_exists_bounded_clinear[iff]:
assumes ‹km_tensor_exists E F›
shows ‹bounded_clinear (km_tensor E F)›
unfolding km_tensor_def
apply (rule someI2_ex[where P=‹λEF. bounded_clinear EF ∧ (∀ρ σ. EF (tc_tensor ρ σ) = tc_tensor (E ρ) (F σ))›])
using assms
by (simp_all add: km_tensor_exists_def)
lemma km_tensor_apply[simp]:
assumes ‹km_tensor_exists E F›
shows ‹km_tensor E F (tc_tensor ρ σ) = tc_tensor (E ρ) (F σ)›
unfolding km_tensor_def
apply (rule someI2_ex[where P=‹λEF. bounded_clinear EF ∧ (∀ρ σ. EF (tc_tensor ρ σ) = tc_tensor (E ρ) (F σ))›])
using assms
by (simp_all add: km_tensor_exists_def)
lemma km_tensor_unique:
assumes ‹bounded_clinear EF›
assumes ‹∧ρ σ. EF (tc_tensor ρ σ) = tc_tensor (E ρ) (F σ)›
shows ‹EF = km_tensor E F›
proof -
define P where ‹P EF ⟷ bounded_clinear EF ∧ (∀ρ σ. EF (tc_tensor ρ σ) = tc_tensor (E ρ) (F σ))› for EF
have ‹P EF›
using P_def assms by presburger
then have ‹km_tensor_exists E F›
using P_def km_tensor_exists_def by blast
with ‹P EF› have Ptensor: ‹P (km_tensor E F)›
by (simp add: P_def)
show ?thesis
apply (rule eq_from_separatingI2)
apply (rule separating_set_bounded_clinear_tc_tensor)
using assms Ptensor by (simp_all add: P_def)
qed
lemma km_tensor_kf_tensor: ‹km_tensor (kf_apply E) (kf_apply F) = kf_apply (kf_tensor E F)›
by (metis kf_apply_bounded_clinear kf_apply_tensor km_tensor_unique)
lemma km_tensor_kraus_map:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹kraus_map (km_tensor E F)›
proof -
from assms obtain EE :: ‹(_,_,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from assms obtain FF :: ‹(_,_,unit) kraus_family› where FF: ‹F = kf_apply FF›
using kraus_map_def_raw by blast
show ?thesis
by (simp add: EE FF km_tensor_kf_tensor)
qed
lemma km_tensor_kraus_map_exists:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹km_tensor_exists E F›
proof -
from assms obtain EE :: ‹(_,_,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from assms obtain FF :: ‹(_,_,unit) kraus_family› where FF: ‹F = kf_apply FF›
using kraus_map_def_raw by blast
show ?thesis
using EE FF kf_apply_bounded_clinear kf_apply_tensor km_tensor_exists_def by blast
qed
lemma km_tensor_as_infsum:
assumes ‹∧ρ. ((λi. sandwich_tc (E i) ρ) has_sum E ρ) I›
assumes ‹∧ρ. ((λj. sandwich_tc (F j) ρ) has_sum F ρ) J›
shows ‹km_tensor E F ρ = (∑\∞(i,j)∈I×J. sandwich_tc (E i ⊗o F j) ρ)›
proof -
define EE FF where ‹EE = Set.filter (λ(E,_). E≠0) ((λa. (E a, a)) ` I)› and ‹FF = Set.filter (λ(E,_). E≠0) ((λa. (F a, a)) ` J)›
then have [simp]: ‹kraus_family EE› ‹kraus_family FF›
using assms kraus_map_sum_kraus_family
by blast+
have ‹E = kf_apply (Abs_kraus_family EE)› and ‹F = kf_apply (Abs_kraus_family FF)›
using assms kraus_map_sum_kf_apply EE_def FF_def
by blast+
then have ‹km_tensor E F ρ = kf_apply (kf_tensor (Abs_kraus_family EE) (Abs_kraus_family FF)) ρ›
by (simp add: km_tensor_kf_tensor)
also have ‹… = (∑\∞((E, x), (F, y))∈EE × FF. sandwich_tc (E ⊗o F) ρ)›
by (simp add: kf_apply_tensor_as_infsum Abs_kraus_family_inverse)
also have ‹… = (∑\∞((E, x), (F, y))∈(λ(i,j). ((E i, i), (F j, j)))`(I×J). sandwich_tc (E ⊗o F) ρ)›
apply (rule infsum_cong_neutral)
by (auto simp: EE_def FF_def)
also have ‹… = (∑\∞(i,j)∈I×J. sandwich_tc (E i ⊗o F j) ρ)›
by (simp add: infsum_reindex inj_on_def o_def case_prod_unfold)
finally show ?thesis
by -
qed
lemma km_bound_tensor:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹km_bound (km_tensor E F) = km_bound E ⊗o km_bound F›
proof -
from assms obtain EE :: ‹(_,_,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from assms obtain FF :: ‹(_,_,unit) kraus_family› where FF: ‹F = kf_apply FF›
using kraus_map_def_raw by blast
show ?thesis
by (simp add: EE FF km_tensor_kf_tensor kf_bound_tensor km_bound_kf_bound)
qed
lemma km_norm_tensor:
assumes ‹kraus_map E› and ‹kraus_map F›
shows ‹km_norm (km_tensor E F) = km_norm E * km_norm F›
proof -
from assms obtain EE :: ‹(_,_,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from assms obtain FF :: ‹(_,_,unit) kraus_family› where FF: ‹F = kf_apply FF›
using kraus_map_def_raw by blast
show ?thesis
by (simp add: EE FF km_tensor_kf_tensor kf_norm_tensor km_norm_kf_norm)
qed
lemma km_tensor_compose_distrib:
assumes ‹km_tensor_exists E G› and ‹km_tensor_exists F H›
shows ‹km_tensor (E o F) (G o H) = km_tensor E G o km_tensor F H›
by (smt (verit, del_insts) assms(1,2) comp_bounded_clinear km_tensor_exists_def km_tensor_unique o_apply)
lemma kraus_map_tensor_right[simp]:
assumes ‹ρ ≥ 0›
shows ‹kraus_map (λσ. tc_tensor σ ρ)›
apply (rule kraus_mapI[of _ ‹kf_tensor_right ρ›])
by (auto intro!: ext simp: kf_apply_tensor_right assms)
lemma kraus_map_tensor_left[simp]:
assumes ‹ρ ≥ 0›
shows ‹kraus_map (λσ. tc_tensor ρ σ)›
apply (rule kraus_mapI[of _ ‹kf_tensor_left ρ›])
by (auto intro!: ext simp: kf_apply_tensor_left assms)
lemma km_bound_tensor_right[simp]:
assumes ‹ρ ≥ 0›
shows ‹km_bound (λσ. tc_tensor σ ρ) = norm ρ *C id_cblinfun›
apply (subst km_bound_kf_bound)
apply (rule ext)
apply (subst kf_apply_tensor_right[OF assms])
by (auto intro!: simp: kf_bound_tensor_right assms)
lemma km_bound_tensor_left[simp]:
assumes ‹ρ ≥ 0›
shows ‹km_bound (λσ. tc_tensor ρ σ) = norm ρ *C id_cblinfun›
apply (subst km_bound_kf_bound)
apply (rule ext)
apply (subst kf_apply_tensor_left[OF assms])
by (auto intro!: simp: kf_bound_tensor_left assms)
lemma kf_norm_tensor_right[simp]:
assumes ‹ρ ≥ 0›
shows ‹km_norm (λσ. tc_tensor σ ρ) = norm ρ›
by (simp add: km_norm_def km_bound_tensor_right assms)
lemma kf_norm_tensor_left[simp]:
assumes ‹ρ ≥ 0›
shows ‹km_norm (λσ. tc_tensor ρ σ) = norm ρ›
by (simp add: km_norm_def km_bound_tensor_left assms)
lemma km_operators_in_tensor:
assumes ‹km_operators_in E S›
assumes ‹km_operators_in F T›
shows ‹km_operators_in (km_tensor E F) (span {s ⊗o t | s t. s∈S ∧ t∈T})›
proof -
have [iff]: ‹inj_on (λ((),()). ()) X› for X
by (simp add: inj_on_def)
from assms obtain E' :: ‹(_,_,unit) kraus_family› where E_def: ‹E = kf_apply E'› and E'S: ‹kf_operators E' ⊆ S›
by (metis km_operators_in_def)
from assms obtain F' :: ‹(_,_,unit) kraus_family› where F_def: ‹F = kf_apply F'› and F'T: ‹kf_operators F' ⊆ T›
by (metis km_operators_in_def)
define EF where ‹EF = kf_map_inj (λ((),()). ()) (kf_tensor E' F')›
then have ‹kf_operators EF = kf_operators (kf_tensor E' F')›
by (simp add: EF_def)
also have ‹kf_operators (kf_tensor E' F') ⊆ span {E ⊗o F | E F. E ∈ kf_operators E' ∧ F ∈ kf_operators F'}›
using kf_operators_tensor by force
also have ‹… ⊆ span {E ⊗o F | E F. E ∈ S ∧ F ∈ T}›
by (smt (verit) Collect_mono_iff E'S F'T span_mono subset_iff)
finally have ‹kf_operators EF ⊆ span {s ⊗o t |s t. s ∈ S ∧ t ∈ T}›
using EF_def by blast
moreover have ‹kf_apply EF = km_tensor E F›
by (simp add: EF_def E_def F_def kf_apply_bounded_clinear kf_apply_tensor km_tensor_unique)
ultimately show ?thesis
by (auto intro!: exI[of _ EF] simp add: km_operators_in_def)
qed
lemma km_tensor_sandwich_tc:
‹km_tensor (sandwich_tc A) (sandwich_tc B) = sandwich_tc (A ⊗o B)›
by (metis bounded_clinear_sandwich_tc km_tensor_unique sandwich_tc_tensor)
subsection ‹Trace and partial trace›
definition ‹km_trace_preserving E ⟷ (∃F::(_,_,unit) kraus_family. E = kf_apply F ∧ kf_trace_preserving F)›
lemma km_trace_preserving_def': ‹km_trace_preserving E ⟷ (∃F::(_, _, 'c) kraus_family. E = kf_apply F ∧ kf_trace_preserving F)›
― ‹Has a more general type than @{thm [source] km_trace_preserving_def}›
proof (rule iffI)
assume ‹km_trace_preserving E›
then obtain F :: ‹(_,_,unit) kraus_family› where EF: ‹E = kf_apply F› and tpF: ‹kf_trace_preserving F›
using km_trace_preserving_def by blast
from EF have ‹E = kf_apply (kf_map (λ_. undefined :: 'c) F)›
by simp
moreover from tpF have ‹kf_trace_preserving (kf_map (λ_. undefined :: 'c) F)›
by (metis EF calculation kf_trace_preserving_iff_bound_id km_bound_kf_bound)
ultimately show ‹∃F::(_, _, 'c) kraus_family. E = (*kr) F ∧ kf_trace_preserving F›
by blast
next
assume ‹∃F::(_, _, 'c) kraus_family. E = (*kr) F ∧ kf_trace_preserving F›
then obtain F :: ‹(_,_,'c) kraus_family› where EF: ‹E = kf_apply F› and tpF: ‹kf_trace_preserving F›
by blast
from EF have ‹E = kf_apply (kf_flatten F)›
by simp
moreover from tpF have ‹kf_trace_preserving (kf_flatten F)›
by (metis EF calculation kf_trace_preserving_iff_bound_id km_bound_kf_bound)
ultimately show ‹km_trace_preserving E›
using km_trace_preserving_def by blast
qed
definition km_trace_reducing_def: ‹km_trace_reducing E ⟷ (∃F::(_,_,unit) kraus_family. E = kf_apply F ∧ kf_trace_reducing F)›
lemma km_trace_reducing_def': ‹km_trace_reducing E ⟷ (∃F::(_, _, 'c) kraus_family. E = kf_apply F ∧ kf_trace_reducing F)›
proof (rule iffI)
assume ‹km_trace_reducing E›
then obtain F :: ‹(_,_,unit) kraus_family› where EF: ‹E = kf_apply F› and tpF: ‹kf_trace_reducing F›
using km_trace_reducing_def by blast
from EF have ‹E = kf_apply (kf_map (λ_. undefined :: 'c) F)›
by simp
moreover from tpF have ‹kf_trace_reducing (kf_map (λ_. undefined :: 'c) F)›
by (simp add: kf_trace_reducing_iff_norm_leq1)
ultimately show ‹∃F::(_, _, 'c) kraus_family. E = (*kr) F ∧ kf_trace_reducing F›
by blast
next
assume ‹∃F::(_, _, 'c) kraus_family. E = (*kr) F ∧ kf_trace_reducing F›
then obtain F :: ‹(_,_,'c) kraus_family› where EF: ‹E = kf_apply F› and tpF: ‹kf_trace_reducing F›
by blast
from EF have ‹E = kf_apply (kf_flatten F)›
by simp
moreover from tpF have ‹kf_trace_reducing (kf_flatten F)›
by (simp add: kf_trace_reducing_iff_norm_leq1)
ultimately show ‹km_trace_reducing E›
using km_trace_reducing_def by blast
qed
lemma km_trace_preserving_apply[simp]: ‹km_trace_preserving (kf_apply E) = kf_trace_preserving E›
using kf_trace_preserving_def km_trace_preserving_def' by auto
lemma km_trace_reducing_apply[simp]: ‹km_trace_reducing (kf_apply E) = kf_trace_reducing E›
by (metis kf_trace_reducing_iff_norm_leq1 km_norm_kf_norm km_trace_reducing_def')
lemma km_trace_preserving_iff: ‹km_trace_preserving E ⟷ kraus_map E ∧ (∀ρ. trace_tc (E ρ) = trace_tc ρ)›
proof (intro iffI conjI allI)
assume tp: ‹km_trace_preserving E›
then obtain F :: ‹(_,_,unit) kraus_family› where EF: ‹E = kf_apply F› and tpF: ‹kf_trace_preserving F›
by (metis kf_trace_preserving_def kf_trace_reducing_def km_trace_preserving_def order.refl)
then show ‹kraus_map E›
by blast
from tpF show ‹trace_tc (E ρ) = trace_tc ρ› for ρ
by (simp add: EF kf_trace_preserving_def)
next
assume asm: ‹kraus_map E ∧ (∀ρ. trace_tc (E ρ) = trace_tc ρ)›
then obtain F :: ‹(_,_,unit) kraus_family› where EF: ‹E = kf_apply F›
using kraus_map_def_raw by blast
from asm EF have ‹trace_tc (kf_apply F ρ) = trace_tc ρ› for ρ
by blast
then have ‹kf_trace_preserving F›
using kf_trace_preserving_def by blast
with EF show ‹km_trace_preserving E›
using km_trace_preserving_def by blast
qed
lemma km_trace_reducing_iff: ‹km_trace_reducing E ⟷ kraus_map E ∧ (∀ρ≥0. trace_tc (E ρ) ≤ trace_tc ρ)›
proof (intro iffI conjI allI impI)
assume tp: ‹km_trace_reducing E›
then obtain F :: ‹(_,_,unit) kraus_family› where EF: ‹E = kf_apply F› and tpF: ‹kf_trace_reducing F›
by (metis kf_trace_reducing_def kf_trace_reducing_def km_trace_reducing_def order.refl)
then show ‹kraus_map E›
by blast
from tpF EF show ‹trace_tc (E ρ) ≤ trace_tc ρ› if ‹ρ ≥ 0› for ρ
using kf_trace_reducing_def that by blast
next
assume asm: ‹kraus_map E ∧ (∀ρ≥0. trace_tc (E ρ) ≤ trace_tc ρ)›
then obtain F :: ‹(_,_,unit) kraus_family› where EF: ‹E = kf_apply F›
using kraus_map_def_raw by blast
from asm EF have ‹trace_tc (kf_apply F ρ) ≤ trace_tc ρ› if ‹ρ ≥ 0› for ρ
using that by blast
then have ‹kf_trace_reducing F›
using kf_trace_reducing_def by blast
with EF show ‹km_trace_reducing E›
using km_trace_reducing_def by blast
qed
lemma km_trace_preserving_imp_reducing:
assumes ‹km_trace_preserving E›
shows ‹km_trace_reducing E›
using assms km_trace_preserving_iff km_trace_reducing_iff by fastforce
lemma km_trace_preserving_id[iff]: ‹km_trace_preserving id›
by (simp add: km_trace_preserving_iff)
lemma km_trace_reducing_iff_norm_leq1: ‹km_trace_reducing E ⟷ kraus_map E ∧ km_norm E ≤ 1›
proof (intro iffI conjI)
assume ‹km_trace_reducing E›
then show ‹kraus_map E›
using km_trace_reducing_iff by blast
then obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
with ‹km_trace_reducing E›
have ‹kf_trace_reducing EE›
using kf_trace_reducing_def km_trace_reducing_iff by blast
then have ‹kf_norm EE ≤ 1›
using kf_trace_reducing_iff_norm_leq1 by blast
then show ‹km_norm E ≤ 1›
by (simp add: EE km_norm_kf_norm)
next
assume asm: ‹kraus_map E ∧ km_norm E ≤ 1›
then obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from asm have ‹km_norm E ≤ 1›
by blast
then have ‹kf_norm EE ≤ 1›
by (simp add: EE km_norm_kf_norm)
then have ‹kf_trace_reducing EE›
by (simp add: kf_trace_reducing_iff_norm_leq1)
then show ‹km_trace_reducing E›
using EE km_trace_reducing_def by blast
qed
lemma km_trace_preserving_iff_bound_id: ‹km_trace_preserving E ⟷ kraus_map E ∧ km_bound E = id_cblinfun›
proof (intro iffI conjI)
assume ‹km_trace_preserving E›
then show ‹kraus_map E›
using km_trace_preserving_iff by blast
then obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
with ‹km_trace_preserving E›
have ‹kf_trace_preserving EE›
using kf_trace_preserving_def km_trace_preserving_iff by blast
then have ‹kf_bound EE = id_cblinfun›
by (simp add: kf_trace_preserving_iff_bound_id)
then show ‹km_bound E = id_cblinfun›
by (simp add: EE km_bound_kf_bound)
next
assume asm: ‹kraus_map E ∧ km_bound E = id_cblinfun›
then have ‹kraus_map E›
by simp
then obtain EE :: ‹('a,'b,unit) kraus_family› where EE: ‹E = kf_apply EE›
using kraus_map_def_raw by blast
from asm have ‹kf_bound EE = id_cblinfun›
by (simp add: EE km_bound_kf_bound)
then have ‹kf_trace_preserving EE›
by (simp add: kf_trace_preserving_iff_bound_id)
then show ‹km_trace_preserving E›
using EE km_trace_preserving_def by blast
qed
lemma km_trace_preserving_iff_bound_id':
fixes E :: ‹('a::{chilbert_space, not_singleton}, 'a) trace_class → _›
shows ‹km_trace_preserving E ⟷ km_bound E = id_cblinfun›
using km_bound_invalid km_trace_preserving_iff_bound_id by fastforce
lemma km_trace_norm_preserving: ‹km_norm E ≤ 1› if ‹km_trace_preserving E›
using km_trace_preserving_imp_reducing km_trace_reducing_iff_norm_leq1 that by blast
lemma km_trace_norm_preserving_eq:
fixes E :: ‹('a::{chilbert_space,not_singleton},'a) trace_class → ('b::chilbert_space,'b) trace_class›
assumes ‹km_trace_preserving E›
shows ‹km_norm E = 1›
using assms
by (simp add: km_trace_preserving_iff_bound_id' km_norm_def)
lemma kraus_map_trace: ‹kraus_map (one_dim_iso o trace_tc)›
by (auto intro!: ext kraus_mapI[of _ ‹kf_trace some_chilbert_basis›]
simp: kf_trace_is_trace)
lemma trace_preserving_trace_kraus_map[iff]: ‹km_trace_preserving (one_dim_iso o trace_tc)›
using km_trace_preserving_iff kraus_map_trace by fastforce
lemma km_trace_bound[simp]: ‹km_bound (one_dim_iso o trace_tc) = id_cblinfun›
using km_trace_preserving_iff_bound_id by blast
lemma km_trace_norm_eq1[simp]: ‹km_norm (one_dim_iso o trace_tc :: ('a::{chilbert_space,not_singleton},'a) trace_class → _) = 1›
using km_trace_norm_preserving_eq by blast
lemma km_trace_norm_leq1[simp]: ‹km_norm (one_dim_iso o trace_tc) ≤ 1›
using km_trace_norm_preserving by blast
lemma kraus_map_partial_trace[iff]: ‹kraus_map partial_trace›
by (auto intro!: ext kraus_mapI[of _ ‹kf_partial_trace_right›] simp flip: partial_trace_is_kf_partial_trace)
lemma partial_trace_ignores_kraus_map:
assumes ‹km_trace_preserving E›
assumes ‹kraus_map F›
shows ‹partial_trace (km_tensor F E ρ) = F (partial_trace ρ)›
proof -
from assms
obtain EE :: ‹(_,_,unit) kraus_family› where EE_def: ‹E = kf_apply EE› and tpEE: ‹kf_trace_preserving EE›
using km_trace_preserving_def by blast
obtain FF :: ‹(_,_,unit) kraus_family› where FF_def: ‹F = kf_apply FF›
using assms(2) kraus_map_def_raw by blast
have ‹partial_trace (km_tensor F E ρ) = partial_trace (kf_tensor FF EE *kr ρ)›
using assms
by (simp add: km_trace_preserving_def partial_trace_ignores_kraus_family
km_tensor_kf_tensor EE_def kf_id_apply[abs_def] id_def FF_def
flip: km_tensor_kf_tensor)
also have ‹… = FF *kr partial_trace ρ›
by (simp add: partial_trace_ignores_kraus_family tpEE)
also have ‹… = F (partial_trace ρ)›
using FF_def by presburger
finally show ?thesis
by -
qed
lemma km_partial_trace_bound[simp]: ‹km_bound partial_trace = id_cblinfun›
apply (subst km_bound_kf_bound[of _ kf_partial_trace_right])
using partial_trace_is_kf_partial_trace by auto
lemma km_partial_trace_norm[simp]:
shows ‹km_norm partial_trace = 1›
by (simp add: km_norm_def)
lemma km_trace_preserving_tensor:
assumes ‹km_trace_preserving E› and ‹km_trace_preserving F›
shows ‹km_trace_preserving (km_tensor E F)›
proof -
from assms obtain EE :: ‹('a ell2, 'b ell2, unit) kraus_family› where EE: ‹E = kf_apply EE› and tE: ‹kf_trace_preserving EE›
using km_trace_preserving_def by blast
from assms obtain FF :: ‹('c ell2, 'd ell2, unit) kraus_family› where FF: ‹F = kf_apply FF› and tF: ‹kf_trace_preserving FF›
using km_trace_preserving_def by blast
show ?thesis
by (auto intro!: kf_trace_preserving_tensor simp: EE FF km_tensor_kf_tensor tE tF)
qed
lemma km_trace_reducing_tensor:
assumes ‹km_trace_reducing E› and ‹km_trace_reducing F›
shows ‹km_trace_reducing (km_tensor E F)›
by (smt (z3) assms(1,2) km_norm_geq0 km_norm_tensor km_tensor_kraus_map km_trace_reducing_iff_norm_leq1
mult_left_le_one_le)
subsection ‹Complete measurements›
definition ‹km_complete_measurement B ρ = (∑\∞x∈B. sandwich_tc (selfbutter (sgn x)) ρ)›
abbreviation ‹km_complete_measurement_ket ≡ km_complete_measurement (range ket)›
lemma km_complete_measurement_kf_complete_measurement: ‹km_complete_measurement B = kf_apply (kf_complete_measurement B)› if ‹is_ortho_set B›
by (simp add: kf_complete_measurement_apply[OF that, abs_def] km_complete_measurement_def[abs_def])
lemma km_complete_measurement_ket_kf_complete_measurement_ket: ‹km_complete_measurement_ket = kf_apply kf_complete_measurement_ket›
by (metis Complex_L2.is_ortho_set_ket kf_apply_map kf_complete_measurement_ket_kf_map kf_eq_imp_eq_weak kf_eq_weak_def
km_complete_measurement_kf_complete_measurement)
lemma km_complete_measurement_has_sum:
assumes ‹is_ortho_set B›
shows ‹((λx. sandwich_tc (selfbutter (sgn x)) ρ) has_sum km_complete_measurement B ρ) B›
using kf_complete_measurement_has_sum[OF assms] and assms
by (simp add: kf_complete_measurement_apply km_complete_measurement_def)
lemma km_complete_measurement_ket_has_sum:
‹((λx. sandwich_tc (selfbutter (ket x)) ρ) has_sum km_complete_measurement_ket ρ) UNIV›
by (smt (verit) has_sum_cong has_sum_reindex inj_ket is_onb_ket is_ortho_set_ket kf_complete_measurement_apply
kf_complete_measurement_has_sum_onb km_complete_measurement_def o_def)
lemma km_bound_complete_measurement:
assumes ‹is_ortho_set B›
shows ‹km_bound (km_complete_measurement B) ≤ id_cblinfun›
apply (subst km_bound_kf_bound[of _ ‹kf_complete_measurement B›])
using assms kf_complete_measurement_apply km_complete_measurement_def apply fastforce
by (simp add: assms kf_bound_complete_measurement)
lemma km_norm_complete_measurement:
assumes ‹is_ortho_set B›
shows ‹km_norm (km_complete_measurement B) ≤ 1›
apply (subst km_norm_kf_norm[of _ ‹kf_complete_measurement B›])
apply (simp add: assms km_complete_measurement_kf_complete_measurement)
by (simp_all add: assms kf_norm_complete_measurement)
lemma km_bound_complete_measurement_onb[simp]:
assumes ‹is_onb B›
shows ‹km_bound (km_complete_measurement B) = id_cblinfun›
apply (subst km_bound_kf_bound[of _ ‹kf_complete_measurement B›])
using assms
by (auto intro!: ext simp: kf_complete_measurement_apply is_onb_def km_complete_measurement_def)
lemma km_bound_complete_measurement_ket[simp]: ‹km_bound km_complete_measurement_ket = id_cblinfun›
by fastforce
lemma km_norm_complete_measurement_onb[simp]:
fixes B :: ‹'a::{not_singleton, chilbert_space} set›
assumes ‹is_onb B›
shows ‹km_norm (km_complete_measurement B) = 1›
apply (subst km_norm_kf_norm[of _ ‹kf_complete_measurement B›])
using assms
by (auto intro!: ext simp: kf_complete_measurement_apply is_onb_def km_complete_measurement_def)
lemma km_norm_complete_measurement_ket[simp]:
shows ‹km_norm km_complete_measurement_ket = 1›
by fastforce
lemma kraus_map_complete_measurement:
assumes ‹is_ortho_set B›
shows ‹kraus_map (km_complete_measurement B)›
apply (rule kraus_mapI[of _ ‹kf_complete_measurement B›])
by (auto intro!: ext simp add: assms kf_complete_measurement_apply km_complete_measurement_def)
lemma kraus_map_complete_measurement_ket[iff]:
shows ‹kraus_map km_complete_measurement_ket›
by (simp add: kraus_map_complete_measurement)
lemma km_complete_measurement_idem[simp]:
assumes ‹is_ortho_set B›
shows ‹km_complete_measurement B (km_complete_measurement B ρ) = km_complete_measurement B ρ›
using kf_complete_measurement_idem[of B]
kf_complete_measurement_apply[OF assms] km_complete_measurement_def
by (metis (no_types, lifting) ext kf_comp_apply kf_complete_measurement_idem_weak kf_eq_weak_def o_def)
lemma km_complete_measurement_ket_idem[simp]:
‹km_complete_measurement_ket (km_complete_measurement_ket ρ) = km_complete_measurement_ket ρ›
by fastforce
lemma km_complete_measurement_has_sum_onb:
assumes ‹is_onb B›
shows ‹((λx. sandwich_tc (selfbutter x) ρ) has_sum km_complete_measurement B ρ) B›
using kf_complete_measurement_has_sum_onb[OF assms] and assms
by (simp add: kf_complete_measurement_apply km_complete_measurement_def is_onb_def)
lemma km_complete_measurement_ket_diagonal_operator[simp]:
‹km_complete_measurement_ket (diagonal_operator_tc f) = diagonal_operator_tc f›
using kf_complete_measurement_ket_diagonal_operator[of f]
by (metis (no_types, lifting) is_ortho_set_ket kf_apply_map kf_apply_on_UNIV kf_apply_on_eqI kf_complete_measurement_apply
kf_complete_measurement_ket_kf_map km_complete_measurement_def)
lemma km_operators_complete_measurement:
assumes ‹is_ortho_set B›
shows ‹km_operators_in (km_complete_measurement B) (span (selfbutter ` B))›
proof -
have ‹span ((selfbutter ∘ sgn) ` B) ⊆ span (selfbutter ` B)›
proof (intro real_vector.span_minimal[OF _ real_vector.subspace_span] subsetI)
fix a
assume ‹a ∈ (selfbutter ∘ sgn) ` B›
then obtain h where ‹a = selfbutter (sgn h)› and ‹h ∈ B›
by force
then have ‹a = (inverse (norm h))2 *R selfbutter h›
by (simp add: sgn_div_norm scaleR_scaleC power2_eq_square)
with ‹h ∈ B›
show ‹a ∈ span (selfbutter ` B)›
by (simp add: span_clauses(1) span_mul)
qed
then show ?thesis
by (simp add: km_complete_measurement_kf_complete_measurement assms km_operators_in_kf_apply
kf_operators_complete_measurement)
qed
lemma km_operators_complete_measurement_ket:
shows ‹km_operators_in km_complete_measurement_ket (span (range (λc. (selfbutter (ket c)))))›
by (metis (no_types, lifting) image_cong is_ortho_set_ket km_operators_complete_measurement range_composition)
lemma km_complete_measurement_ket_butterket[simp]:
‹km_complete_measurement_ket (tc_butterfly (ket c) (ket c)) = tc_butterfly (ket c) (ket c)›
by (simp add: km_complete_measurement_ket_kf_complete_measurement_ket kf_complete_measurement_ket_apply_butterfly)
lemma km_complete_measurement_tensor:
assumes ‹is_ortho_set B› and ‹is_ortho_set C›
shows ‹km_tensor (km_complete_measurement B) (km_complete_measurement C)
= km_complete_measurement ((λ(b,c). b ⊗s c) ` (B × C))›
by (simp add: km_complete_measurement_kf_complete_measurement assms is_ortho_set_tensor km_tensor_kf_tensor
flip: kf_complete_measurement_tensor)
lemma km_complete_measurement_ket_tensor:
shows ‹km_tensor (km_complete_measurement_ket :: ('a ell2, _) trace_class → _) (km_complete_measurement_ket :: ('b ell2, _) trace_class → _)
= km_complete_measurement_ket›
by (simp add: km_complete_measurement_ket_kf_complete_measurement_ket km_tensor_kf_tensor kf_complete_measurement_ket_tensor)
lemma km_tensor_0_left[simp]: ‹km_tensor (0 :: ('a ell2, 'b ell2) trace_class → ('c ell2, 'd ell2) trace_class) E = 0›
proof (cases ‹km_tensor_exists (0 :: ('a ell2, 'b ell2) trace_class → ('c ell2, 'd ell2) trace_class) E›)
case True
then show ?thesis
apply (rule_tac eq_from_separatingI2[OF separating_set_bounded_clinear_tc_tensor])
by (simp_all add: km_tensor_apply)
next
case False
then show ?thesis
using km_tensor_invalid by blast
qed
lemma km_tensor_0_right[simp]: ‹km_tensor E (0 :: ('a ell2, 'b ell2) trace_class → ('c ell2, 'd ell2) trace_class) = 0›
proof (cases ‹km_tensor_exists E (0 :: ('a ell2, 'b ell2) trace_class → ('c ell2, 'd ell2) trace_class)›)
case True
then show ?thesis
apply (rule_tac eq_from_separatingI2[OF separating_set_bounded_clinear_tc_tensor])
by (simp_all add: km_tensor_apply)
next
case False
then show ?thesis
using km_tensor_invalid by blast
qed
unbundle no kraus_map_syntax
unbundle no cblinfun_syntax
end
¤ Dauer der Verarbeitung: 0.33 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland
|
|