Theory Unitary_S
theory Unitary_S
imports Definition_O2H
begin
unbundle cblinfun_syntax
unbundle lattice_syntax
context o2h_setting
begin
subsection ‹Linear operator ‹US››
definition Ub :: "nat ⇒ 'l update" where
"Ub i = classical_operator (Some o (flip i))"
lemma Ub_exists: "classical_operator_exists (Some ∘ flip i)"
by (intro classical_operator_exists_inj, subst inj_map_total)
(simp add: inj_flip)
lemma isometry_Ub:
"isometry (Ub k)"
unfolding Ub_def by (auto simp add: inj_flip)
lemma Ub_ket_range: "(Ub i *⇩V ket y) ∈ range ket" unfolding Ub_def
by (simp add: classical_operator_ket[OF Ub_exists])
lemma Ub_ket:
"Ub k *⇩V (ket x) = ket (flip k x)"
unfolding Ub_def by (simp add: classical_operator_ket[OF Ub_exists])
text ‹Using the operator ‹Ub›, we define the unitary $U_{S}$. Whenever we queried an element
in the set $S$, we add a bit-flip in the register ‹'l›, otherwise not.
The linear operator ‹Ub› works only on the second register part (the counting register).
This is the operator between the oracle queries while running ‹B›.›
definition US :: ‹('x ⇒ bool) ⇒ nat ⇒ ('mem × 'l) update› where
‹US S k = S_embed S ⊗⇩o Ub k + not_S_embed S ⊗⇩o id_cblinfun›
lemma isometry_US:
"isometry (US S k)"
proof -
have "S_embed S ⊗⇩o id_cblinfun + not_S_embed S ⊗⇩o id_cblinfun = id_cblinfun"
by (auto simp add: tensor_op_left_add[symmetric])
then have "((S_embed S)* ⊗⇩o (Ub k)* + (not_S_embed S)* ⊗⇩o id_cblinfun) o⇩C⇩L
(S_embed S ⊗⇩o (Ub k) + not_S_embed S ⊗⇩o id_cblinfun) = id_cblinfun"
by (auto simp add: cblinfun_compose_add_right cblinfun_compose_add_left
comp_tensor_op S_embed_adj tensor_op_ell2 isometry_Ub not_S_embed_adj not_S_embed_idem)
then show ?thesis unfolding US_def isometry_def
by (auto simp add: cblinfun.add_left cblinfun.add_right
tensor_ell2_ket[symmetric] adj_plus tensor_op_adjoint)
qed
lemma US_ket_split:
"(US S k) *⇩V ket (x,y) = (S_embed S *⇩V ket x) ⊗⇩s ((Ub k) *⇩V ket y) + (not_S_embed S *⇩V ket x) ⊗⇩s ket y"
unfolding US_def
by (auto simp add: plus_cblinfun.rep_eq tensor_ell2_ket[symmetric] tensor_op_ell2)
lemma US_ket_only01:
"US S k (v ⊗⇩s ket n) = (not_S_embed S *⇩V v) ⊗⇩s ket n + (S_embed S *⇩V v) ⊗⇩s ket (flip k n)"
unfolding US_def by (auto simp add: cblinfun.add_left tensor_op_ell2 Ub_ket)
lemma norm_US:
assumes "i < Suc d" shows "norm (US S i) = 1"
by (simp add: isometry_US norm_isometry)
text ‹Projection upto bit i›
text ‹How the counting unitary ‹Ub› behaves with respect to projections on the counting register.›
lemma proj_classical_set_not_blog_Ub:
assumes "n<d"
shows "proj_classical_set (- Collect blog) o⇩C⇩L Ub n =
Ub n o⇩C⇩L proj_classical_set (- Collect blog)"
proof (intro equal_ket, goal_cases)
case (1 x)
show ?case proof (cases "blog x")
case True
then show ?thesis by (simp add: blog_flip[OF ‹n<d›] True Ub_ket proj_classical_set_not_elem)
next
case False
then show ?thesis by (simp add: Ub_ket not_blog_flip[OF ‹n<d›] proj_classical_set_elem)
qed
qed
lemma proj_classical_set_over_Ub:
assumes "n≤d" "m<d"
shows "proj_classical_set (list_to_l ` has_bits {n..<d}) o⇩C⇩L Ub m =
Ub m o⇩C⇩L proj_classical_set (flip m ` list_to_l ` has_bits {n..<d})"
proof (intro equal_ket, goal_cases)
case (1 x)
show ?case proof (cases "blog x")
case True
obtain j where "j∈len_d_lists" and x: "x = list_to_l j"
by (metis True image_iff mem_Collect_eq surj_list_to_l)
consider (elem) "flip m x ∈ list_to_l ` has_bits {n..<d}" |
(not_elem) "¬ flip m x ∈ list_to_l ` has_bits {n..<d}" by auto
then have ?thesis if "n<d" proof (cases)
case elem
then have x_in: "x ∈ flip m ` list_to_l ` has_bits {n..<d}"
using True assms(2) flip_flip by fastforce
have "(proj_classical_set (list_to_l ` has_bits {n..<d}) o⇩C⇩L Ub m) *⇩V ket x = ket (flip m x)"
by (simp add: Ub_ket local.elem proj_classical_set_elem)
moreover have "(Ub m o⇩C⇩L proj_classical_set (flip m ` list_to_l ` has_bits {n..<d})) *⇩V ket x =
ket (flip m x)"
using proj_classical_set_elem[OF x_in] by (auto simp add: Ub_ket)
ultimately show ?thesis by metis
next
case not_elem
then have x_in: "x ∉ flip m ` list_to_l ` has_bits {n..<d}" using flip_flip[OF ‹m<d›]
by (metis True imageE inj_def inj_flip)
have "(proj_classical_set (list_to_l ` has_bits {n..<d}) o⇩C⇩L Ub m) *⇩V ket x = 0"
by (simp add: Ub_ket not_elem proj_classical_set_not_elem)
moreover have "(Ub m o⇩C⇩L proj_classical_set (flip m ` list_to_l ` has_bits {n..<d})) *⇩V ket x = 0"
using proj_classical_set_not_elem[OF x_in] by (auto simp add: Ub_ket)
ultimately show ?thesis by metis
qed
moreover have ?thesis if "n=d" unfolding that using True
by (auto simp add: Ub_ket proj_classical_set_not_elem)
ultimately show ?thesis using assms by linarith
next
case False
have "proj_classical_set (list_to_l ` has_bits {n..<d}) *⇩V ket (flip m x) = 0"
by (intro proj_classical_set_not_elem)(metis (no_types, lifting) False
image_iff mem_Collect_eq not_blog_flip[OF ‹m<d›] has_bits_def surj_list_to_l)
then have left: "(proj_classical_set (list_to_l ` has_bits {n..<d}) o⇩C⇩L Ub m) *⇩V ket x = 0"
by (auto simp add: Ub_ket)
have right: "proj_classical_set (flip m ` list_to_l ` has_bits {n..<d}) *⇩V ket x = 0"
by (intro proj_classical_set_not_elem) (smt (verit, del_insts) False assms(2) blog.simps
imageE image_eqI mem_Collect_eq has_bits_def surj_list_to_l)
show ?thesis unfolding left using right by auto
qed
qed
lemma Ψs_US_Proj_ket_upto:
assumes "i<d"
shows "tensor_ell2_right (ket empty)* o⇩C⇩L ((US S i) o⇩C⇩L Proj_ket_upto (has_bits_upto i)) =
not_S_embed S o⇩C⇩L tensor_ell2_right (ket empty)*"
proof (intro equal_ket, safe, goal_cases)
case (1 a b)
have split_a: "ket a = S_embed S (ket a) + not_S_embed S (ket a)"
using S_embed_not_S_embed_add by auto
have ?case (is "?left = ?right") if "b ∈ list_to_l ` has_bits_upto i"
proof -
have "Proj (ccspan (ket ` list_to_l ` has_bits_upto i)) *⇩V ket b = ket b"
using that by (simp add: Proj_fixes_image ccspan_superset')
then have proj: "proj_classical_set (list_to_l ` has_bits_upto i) *⇩V ket b = ket b"
unfolding proj_classical_set_def by auto
have "?left = (tensor_ell2_right (ket empty)* o⇩C⇩L (US S i)) *⇩V ket (a, b)"
using proj by (auto simp add: Proj_ket_upto_def Proj_ket_set_def tensor_ell2_ket[symmetric]
tensor_op_ell2)
also have "… = tensor_ell2_right (ket empty)* *⇩V
((S_embed S *⇩V ket a) ⊗⇩s (Ub i) *⇩V ket b + ((not_S_embed S *⇩V ket a) ⊗⇩s ket b))"
using US_ket_split by auto
also have "… = tensor_ell2_right (ket empty)* *⇩V ((not_S_embed S *⇩V ket a) ⊗⇩s ket b)"
proof -
obtain bs where b: "bs∈ has_bits_upto i" "b = list_to_l bs"
using ‹b ∈ list_to_l ` has_bits_upto i› by auto
then have bs: "length bs = d" "¬ (bs!(d-i-1))" unfolding has_bits_upto_def len_d_lists_def
using assms b(1) has_bits_upto_elem by auto
then have "bit b i = bit empty i" unfolding b(2)
by (subst bit_list_to_l) (auto simp add: ‹i<d›)
then have "flip i b ≠ empty" using assms bit_flip_same blog.intros(1) not_blog_flip by blast
then have "tensor_ell2_right (ket empty)* *⇩V ((S_embed S *⇩V ket a) ⊗⇩s (Ub i) *⇩V ket b) = 0"
by (simp add: Ub_def classical_operator_ket[OF Ub_exists])
then show ?thesis by (simp add: cblinfun.real.add_right)
qed
also have "… = ?right"
by (auto simp add: tensor_ell2_ket[symmetric] cinner_ket)
finally show ?thesis by blast
qed
moreover have ?case (is "?left = ?right") if "¬ (b ∈ list_to_l ` has_bits_upto i)" "blog b"
proof -
have "b ≠ empty" using that empty_list_to_l_has_bits_upto by force
have "b ∉ list_to_l ` has_bits_upto i" using that by auto
then have proj: "proj_classical_set (list_to_l ` has_bits_upto i) *⇩V ket b = 0"
unfolding proj_classical_set_def by (intro Proj_0_compl, intro mem_ortho_ccspanI) auto
then have "?left = 0"
by (auto simp add: Proj_ket_upto_def Proj_ket_set_def tensor_ell2_ket[symmetric]
tensor_op_ell2)
moreover have "?right = 0" using ‹b ≠ empty›
by (auto simp add: tensor_ell2_ket[symmetric] cinner_ket)
ultimately show ?thesis by auto
qed
moreover have ?case (is "?left = ?right") if "¬ blog b"
proof -
have "b ≠ empty" using that blog.intros(1) by auto
have "b ∉ list_to_l ` has_bits_upto i"
using has_bits_upto_def surj_list_to_l that by fastforce
then have proj: "proj_classical_set (list_to_l ` has_bits_upto i) *⇩V ket b = 0"
unfolding proj_classical_set_def by (intro Proj_0_compl, intro mem_ortho_ccspanI) auto
then have "?left = 0"
by (auto simp add: Proj_ket_upto_def Proj_ket_set_def tensor_ell2_ket[symmetric]
tensor_op_ell2)
moreover have "?right = 0" using ‹b ≠ empty›
by (auto simp add: tensor_ell2_ket[symmetric] cinner_ket)
ultimately show ?thesis by auto
qed
ultimately show ?case by (cases "b ∈ list_to_l ` has_bits_upto i", auto)
qed
end
unbundle no cblinfun_syntax
unbundle no lattice_syntax
end