theory Grover imports Partial_State Gates Quantum_Hoare begin
subsection‹Basic definitions›
locale grover_state = fixes n :: nat (* number of qubits *) and f :: "nat ==> bool"(* characteristic function, only need values in [0,N). *) assumes n: "n > 1" and dimM: "card {i. i < (2::nat) ^ n ∧ f i} > 0" "card {i. i < (2::nat) ^ n ∧ f i} < (2::nat) ^ n" begin
definition θ :: real where "θ = 2 * arccos (sqrt ((N - M) / N))"
lemma cos_theta_div_2: "cos (θ / 2) = sqrt ((N - M) / N)" proof - have"θ / 2 = arccos (sqrt ((N - M) / N))"using θ_defby simp thenshow"cos (θ / 2) = sqrt ((N - M) / N)" by (simp add: cos_arccos_abs) qed
lemma sin_theta_div_2: "sin (θ / 2) = sqrt (M / N)" proof - have a: "θ / 2 = arccos (sqrt ((N - M) / N))"using θ_defby simp have N: "N > 0"using N_def by auto have M: "M < N"using M_def dimM N_def by auto thenshow"sin (θ / 2) = sqrt (M / N)" unfolding a apply (simp add: sin_arccos_abs) proof - have eq: "real (N - M) = real N - real M"using N M using M_not_ge_N nat_le_linear of_nat_diff by blast have"1 - real (N - M) / real N = (real N - (real N - real M)) / real N" unfolding eq using N by (metis diff_divide_distrib divide_self_if eq gr_implies_not0 of_nat_0_eq_iff) thenshow"1 - real (N - M) / real N = real M / real N"by auto qed qed
lemma θ_neq_0: "θ ≠ 0" proof -
{ assume"θ = 0" thenhave"θ / 2 = 0"by auto thenhave"sin (θ / 2) = 0"by auto
} note z = this have"sin (θ / 2) = sqrt (M / N)"using sin_theta_div_2 by auto moreoverhave"M > 0"unfolding M_def N_def using dimM by auto ultimatelyhave"sin (θ / 2) > 0"by auto with z show ?thesis by auto qed
show ?thesis unfolding eq0 eq1 eq2 using alpha_l_beta_l_add_norm by auto qed
abbreviation proj :: "complex vec ==> complex mat"where "proj v ≡ outer_prod v v"
definition psi'_l where "psi'_l l = (alpha_l l) ⋅v α - (beta_l l) ⋅v β"
lemma psi'_l_dim: "psi'_l l ∈ carrier_vec N" unfolding psi'_l_def α_def β_defby auto
definition proj_psi'_l where "proj_psi'_l l = proj (psi'_l l)"
lemma proj_psi'_dim: "proj_psi'_l l ∈ carrier_mat N N" unfolding proj_psi'_l_def using psi'_l_dim by auto
lemma psi_inner_psi'_l: "inner_prod ψ (psi'_l l) = (alpha_l l * ccos (θ / 2) - beta_l l * csin (θ / 2))" proof - have"inner_prod ψ (psi'_l l) = inner_prod ψ (alpha_l l ⋅v α) - inner_prod ψ (beta_l l ⋅v β)" unfolding psi'_l_def apply (subst inner_prod_minus_distrib_right[of _ N]) by auto alsohave"… = alpha_l l * (inner_prod ψ α) - beta_l l * (inner_prod ψ β)" using ψ_dim α_dim β_dim by auto alsohave"… = alpha_l l * (ccos (θ / 2)) - beta_l l * (csin (θ / 2))" using psi_inner_alpha psi_inner_beta by auto finallyshow ?thesis by auto qed
lemma double_ccos_square: "2 * ccos (a::real) * ccos a = ccos (2 * a) + 1" proof - have eq: "ccos (2 * a) = ccos a * ccos a - csin a * csin a" using cos_add[of a a] by auto have"csin a * csin a = 1 - ccos a * ccos a" using csin_ccos_squared_add[of a] by (metis add_diff_cancel_left') thenhave"ccos a * ccos a - csin a * csin a = 2 * ccos a * ccos a - 1" by simp with eq show ?thesis by simp qed
lemma double_csin_square: "2 * csin (a::real) * csin a = 1 - ccos (2 * a)" proof - have eq: "ccos (2 * a) = ccos a * ccos a - csin a * csin a" using cos_add[of a a] by auto have"ccos a * ccos a = 1 - csin a * csin a" using csin_ccos_squared_add[of a] by (auto intro: add_implies_diff) thenhave"ccos a * ccos a - csin a * csin a = 1 - 2 * csin (a::real) * csin a" by simp with eq show ?thesis by simp qed
lemma csin_double: "2 * csin (a::real) * ccos a = csin(2 * a)" using sin_add[of a a] by simp
lemma ccos_add: "ccos (x + y) = ccos x * ccos y - csin x * csin y" using cos_add[of x y] by simp
lemma unitary_mat_O: "unitary mat_O" proof - have"mat_O ∈ carrier_mat N N"unfolding mat_O_def by auto moreoverhave"mat_O * adjoint mat_O = mat_O * mat_O"using hermitian_mat_O unfoldinghermitian_def by auto moreoverhave"mat_O * mat_O = 1m N" apply (rule eq_matI) unfolding mat_O_def apply (simp add: scalar_prod_def)
subgoal for i j apply (rule)
subgoal apply (subst sum_only_one_neq_0[of "{0..<N}""j"]) by auto apply (subst sum_only_one_neq_0[of "{0..<N}""j"]) by auto by auto ultimatelyshow ?thesis unfolding unitary_def inverts_mat_def by auto qed
definition mat_Ph :: "complex mat"where "mat_Ph = mat N N (λ(i,j). if i = j then if i = 0 then 1 else -1 else 0)"
lemma unitary_mat_Ph: "unitary mat_Ph" proof - have"mat_Ph ∈ carrier_mat N N"unfolding mat_Ph_def by auto moreoverhave"mat_Ph * adjoint mat_Ph = mat_Ph * mat_Ph"using hermitian_mat_Ph unfolding hermitian_def by auto moreoverhave"mat_Ph * mat_Ph = 1m N" apply (rule eq_matI) unfolding mat_Ph_def apply (simp add: scalar_prod_def)
subgoal for i j apply (rule)
subgoal apply (subst sum_only_one_neq_0[of "{0..<N}""0"]) by auto apply (subst sum_only_one_neq_0[of "{0..<N}""j"]) by auto by auto ultimatelyshow ?thesis unfolding unitary_def inverts_mat_def by auto qed
definition mat_G' :: "complex mat"where "mat_G' = mat N N (λ(i,j). if i = j then 2 / N - 1 else 2 / N)"
text‹Geometrically, the Grover operator G is a rotation› definition mat_G :: "complex mat"where "mat_G = mat_G' * mat_O"
end
subsection‹State of Grover's algorithm›
text‹The dimensions are [2, 2, ..., 2, n]. We work with a very special
case as in the paper› locale grover_state_sig = grover_state + state_sig + fixes R :: nat fixes K :: nat assumes dims_def: "dims = replicate n 2 @ [K]" assumes R: "R = pi / (2 * θ) - 1 / 2" assumes K: "K > R"
abbreviation tensor_P where "tensor_P A B ≡ ps2_P.ptensor_mat A B"
lemma tensor_P_dim: "tensor_P A B ∈ carrier_mat d d" proof - have"ps2_P.d0 = prod_list (nths dims ({0..<n} ∪ {n}))"unfolding ps2_P.d0_def ps2_P.dims0_def ps2_P.vars0_def by (simp add: vars1_def vars2_def) alsohave"… = prod_list (nths dims ({0..<Suc n}))" apply (subgoal_tac "{0..<n} ∪ {n} = {0..<(Suc n)}") by auto alsohave"… = prod_list dims"using nths_Suc_n_dims by auto alsohave"… = d"unfolding d_def by auto finallyshow ?thesis using ps2_P.ptensor_mat_carrier by auto qed
lemma dims_nths_le_n: assumes"l ≤ n" shows"nths dims {0..<l} = replicate l 2" proof (rule nth_equalityI, auto) have"l ≤ n ==> (i < Suc n ∧ i < l) = (i < l)"for i using less_trans by fastforce thenshow l: "length (nths dims {0..<l}) = l"using assms by (auto simp add: length_nths length_dims)
have llt: "l < length dims"using length_dims assms by auto have v1: "∧i. i < l ==> {a. a < i ∧ a ∈ {0..<l}} = {0..<i}"unfolding vars1_def by auto thenhave"∧i. i < l ==> card {j. j < i ∧ j ∈ {0..<l}} = i"by auto thenhave"nths dims {0..<l} ! i = dims ! i"if"i < l"for i using nth_nths_card[of i dims "{0..<l}"] that llt by auto moreoverhave"dims ! i = replicate n 2 ! i"if"i < n"for i unfolding dims_def by (auto simp add: nth_append that) moreoverhave"replicate n 2 ! i = replicate l 2 ! i"if"i < l"for i using assms that by auto ultimatelyshow"nths dims {0..<l} ! i = replicate l 2 ! i"if"i < length (nths dims {0..<l})"for i using l that assms by auto qed
lemma dims_nths_one_lt_n: assumes"l < n" shows"nths dims {l} = [2]" proof - have"{i. i < length dims ∧ i ∈ {l}} = {l}"using assms length_dims by auto thenhave"nths dims {l} = [dims ! l]"using nths_only_one[of dims "{l}" l] by auto moreoverhave"dims ! l = 2"unfolding dims_def using assms by (simp add: nth_append) ultimatelyshow ?thesis by auto qed
have v1: "∧i. i < n ==> {a. a < i ∧ a ∈ vars1} = {0..<i}"unfolding vars1_def by auto thenhave"∧i. i < n ==> card {j. j < i ∧ j ∈ vars1} = i"by auto thenhave"nths dims vars1 ! i = dims ! i"if"i < n"for i using nth_nths_card[of i dims vars1] that length_dims vars1_def by auto moreoverhave"dims ! i = replicate n 2 ! i"if"i < n"for i unfolding dims_def by (simp add: nth_append that) ultimatelyshow"nths dims vars1 ! i = replicate n 2 ! i"if"i < length (nths dims vars1)"for i using l that by auto qed
lemma d_vars1: "prod_list (nths dims vars1) = N" proof - have eq: "{0..<n} = {..<n}"by auto have"nths (replicate n 2 @ [K]) {0..<n} = (replicate n 2)" apply (subst eq) using nths_upt_eq_take by simp thenshow ?thesis unfolding dims_def vars1_def N_def by auto qed
lemma ps2_P_dims0: "ps2_P.dims0 = dims" proof - have"vars1 ∪ vars2 = {0..<Suc n}"unfolding vars1_def vars2_def by auto thenhave dims: "nths dims (vars1 ∪ vars2) = dims"unfolding vars1_def vars2_def using nths_Suc_n_dims by auto thenshow ?thesis unfolding ps2_P.dims0_def ps2_P.vars0_def apply (subst dims) by auto qed
lemma ps2_P_vars1': "ps2_P.vars1' = vars1" unfolding ps2_P.vars1'_def ps2_P.vars0_def proof - have eq: "vars1 ∪ vars2 = {0..<(Suc n)}"unfolding vars1_def vars2_def by auto have"x < Suc n ==> {i ∈ {0..<Suc n}. i < x} = {i. i < x}"for x by auto thenhave"x < Suc n ==> ind_in_set {0..<(Suc n)} x = x"for x unfolding ind_in_set_def by auto thenhave"x ∈ vars1 ==> ind_in_set {0..<(Suc n)} x = x"for x unfolding vars1_def by auto thenhave"ind_in_set {0..<(Suc n)} ` vars1 = vars1"by force with eq show"ind_in_set (vars1 ∪ vars2) ` vars1 = vars1"by auto qed
lemma ps2_P_d0: "ps2_P.d0 = d" unfolding ps2_P.d0_def using ps2_P_dims0 d_def by auto
lemma ps_P_d: "ps_P.d = d" unfolding ps_P.d_def ps2_P_dims0 by auto
lemma ps_P_d1: "ps_P.d1 = N" unfolding ps_P.d1_def ps_P.dims1_def ps2_P.nths_vars1' using ps2_P_d1 unfolding ps2_P.d1_def by auto
lemma ps_P_d2: "ps_P.d2 = K" unfolding ps_P.d2_def ps_P.dims2_def ps2_P.nths_vars2' using ps2_P_d2 unfolding ps2_P.d2_def by auto
lemma nths_uminus_vars1: "nths dims (- vars1) = nths dims vars2" using ps2_P.nths_vars2' unfolding ps2_P_dims0 ps2_P_vars1' ps2_P.dims2_def by auto
lemma tensor_P_mult: assumes"m1 ∈ carrier_mat (2^n) (2^n)" and"m2 ∈ carrier_mat (2^n) (2^n)" and"m3 ∈ carrier_mat K K" and"m4 ∈ carrier_mat K K" shows"(tensor_P m1 m3) * (tensor_P m2 m4) = tensor_P (m1 * m2) (m3 * m4)" proof - have eq:"{0..<n} = {..<n}"by auto have"(nths dims vars1) = replicate n 2" unfolding dims_def vars1_def apply (subst eq) by (simp add: nths_upt_eq_take[of "(replicate n 2 @ [K])" n])
have"ps2_P.d1 = 2^n"unfolding ps2_P.d1_def ps2_P.dims1_def using d_vars1 N_def by auto moreoverhave"ps2_P.d2 = K"unfolding ps2_P.d2_def ps2_P.dims2_def using dims_vars2 by auto
ultimatelyshow ?thesis apply (subst ps2_P.ptensor_mat_mult) using assms by auto qed
lemma mat_ext_vars1: shows"mat_extension dims vars1 A = tensor_P A (1m K)" unfolding Utrans_P_def ps2_P.ptensor_mat_def partial_state.mat_extension_def
partial_state.d2_def partial_state.dims2_def ps2_P.nths_vars2'[simplified ps2_P_dims0 ps2_P_vars1'] using ps2_P_d2 unfolding ps2_P.d2_def using ps2_P_dims0 ps2_P_vars1' by auto
lemma Utrans_P_is_tensor_P1: "Utrans_P vars1 A = Utrans (tensor_P A (1m K))" unfolding Utrans_P_def ps2_P.ptensor_mat_def partial_state.mat_extension_def
partial_state.d2_def partial_state.dims2_def ps2_P.nths_vars2'[simplified ps2_P_dims0 ps2_P_vars1'] using ps2_P_d2 unfolding ps2_P.d2_def using ps2_P_dims0 ps2_P_vars1' by auto
lemma nths_dims_uminus_vars2: "nths dims (-vars2) = nths dims vars1" proof - have"nths dims (-vars2) = nths dims ({0..<length dims} - vars2)" using nths_minus_eq by auto alsohave"… = nths dims vars1"unfolding vars1_def vars2_def length_dims apply (subgoal_tac "{0..<n + 1} - {n} = {0..<n}") by auto finallyshow ?thesis by auto qed
lemma mat_ext_vars2: assumes"A ∈ carrier_mat K K" shows"mat_extension dims vars2 A = tensor_P (1m N) A" proof - have"mat_extension dims vars2 A = tensor_mat dims vars2 A (1m N)" unfolding Utrans_P_def partial_state.mat_extension_def
partial_state.d2_def partial_state.dims2_def
nths_dims_uminus_vars2 dims_vars1 N_def by auto alsohave"… = tensor_mat dims vars1 (1m N) A" apply (subst tensor_mat_comm[of vars1 vars2])
subgoal unfolding vars1_def vars2_def by auto
subgoal unfolding length_dims vars1_def vars2_def by auto
subgoal unfolding dims_vars1 N_def by auto unfolding dims_vars2 using assms by auto finallyshow"mat_extension dims vars2 A = tensor_P (1m N) A" unfolding ps2_P.ptensor_mat_def ps2_P_dims0 ps2_P_vars1' by auto qed
lemma Utrans_P_is_tensor_P2: assumes"A ∈ carrier_mat K K" shows"Utrans_P vars2 A = Utrans (tensor_P (1m N) A)" unfolding Utrans_P_def using mat_ext_vars2 assms by auto
subsection‹Grover's algorithm›
text‹Apply hadamard operator to first n variables› definition hadamard_on_i :: "nat ==> complex mat"where "hadamard_on_i i = pmat_extension dims {i} (vars1 - {i}) hadamard" declare hadamard_on_i_def [simp]
text‹Body of the loop› definition D :: com where "D = Utrans_P vars1 mat_O ;; hadamard_n n ;; Utrans_P vars1 mat_Ph ;; hadamard_n n ;; Utrans_P vars2 (mat_incr K)"
lemma unitary_ex_mat_O: "unitary (tensor_P mat_O (1m K))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_unitary)
subgoal using ps_P_d1 mat_O_def by auto
subgoal using ps_P_d2 by auto
subgoal using unitary_mat_O by auto using unitary_one by auto
lemma unitary_ex_mat_Ph: "unitary (tensor_P mat_Ph (1m K))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_unitary)
subgoal using ps_P_d1 mat_Ph_def by auto
subgoal using ps_P_d2 by auto
subgoal using unitary_mat_Ph by auto using unitary_one by auto
lemma unitary_hadamard_on_i: assumes"k < n" shows"unitary (hadamard_on_i k)" proof - interpret st2: partial_state2 dims "{k}""vars1 - {k}" apply unfold_locales by auto show ?thesis unfolding hadamard_on_i_def st2.pmat_extension_def st2.ptensor_mat_def apply (rule partial_state.tensor_mat_unitary)
subgoal unfolding partial_state.d1_def partial_state.dims1_def st2.nths_vars1' st2.dims1_def using dims_nths_one_lt_n assms hadamard_dim by auto
subgoal unfolding st2.d2_def st2.dims2_def partial_state.d2_def partial_state.dims2_def st2.nths_vars2' st2.dims1_def by auto
subgoal using unitary_hadamard by auto
subgoal using unitary_one by auto done qed
lemma unitary_exhadamard_on_i: assumes"k < n" shows"unitary (tensor_P (hadamard_on_i k) (1m K))" proof - interpret st2: partial_state2 dims "{k}""vars1 - {k}" apply unfold_locales by auto have d1: "st2.d0 = partial_state.d1 ps2_P.dims0 ps2_P.vars1'" unfolding partial_state.d1_def partial_state.dims1_def ps2_P.nths_vars1' ps2_P.dims1_def
st2.d0_def st2.dims0_def st2.vars0_def using assms apply (subgoal_tac "{k} ∪ (vars1 - {k}) = vars1") apply simp unfolding vars1_def by auto show ?thesis unfolding ps2_P.ptensor_mat_def apply (rule partial_state.tensor_mat_unitary)
subgoal unfolding hadamard_on_i_def st2.pmat_extension_def using st2.ptensor_mat_carrier[of hadamard "1m st2.d2"] using d1 by auto
subgoal unfolding partial_state.d2_def partial_state.dims2_def ps2_P.nths_vars2' ps2_P.dims2_def dims_vars2 by auto using unitary_hadamard_on_i unitary_one assms by auto qed
lemma hadamard_on_i_dim: assumes"k < n" shows"hadamard_on_i k ∈ carrier_mat N N" proof - interpret st: partial_state2 dims "{k}""(vars1 - {k})" apply unfold_locales by auto have vars1: "{k} ∪ (vars1 - {k}) = vars1"unfolding vars1_def using assms by auto show ?thesis unfolding hadamard_on_i_def N_def using st.pmat_extension_carrier unfolding st.d0_def st.dims0_def st.vars0_def using vars1 dims_vars1 by auto qed
lemma well_com_hadamard_k: "k ≤ n ==> well_com (hadamard_n k)" proof (induct k) case0 thenshow ?caseby auto next case (Suc n) thenhave"well_com (hadamard_n n)"by auto thenshow ?caseunfolding hadamard_n.simps well_com.simps using tensor_P_dim unitary_exhadamard_on_i Suc by auto qed
lemma well_com_hadamard_n: "well_com (hadamard_n n)" using well_com_hadamard_k by auto
lemma well_com_mat_O: "well_com (Utrans_P vars1 mat_O)" apply (subst Utrans_P_is_tensor_P1) apply simp using tensor_P_dim unitary_ex_mat_O by auto
lemma well_com_mat_Ph: "well_com (Utrans_P vars1 mat_Ph)" apply (subst Utrans_P_is_tensor_P1) apply simp using tensor_P_dim unitary_ex_mat_Ph by auto
lemma unitary_exmat_incr: "unitary (tensor_P (1m N) (mat_incr K))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_unitary) using unitary_mat_incr K unitary_one by (auto simp add: ps_P_d1 ps_P_d2 mat_incr_def)
lemma well_com_mat_incr: "well_com (Utrans_P vars2 (mat_incr K))" apply (subst Utrans_P_is_tensor_P2) apply (simp add: mat_incr_def) using tensor_P_dim unitary_exmat_incr by auto
lemma well_com_D: "well_com D" unfolding D_def apply auto using well_com_hadamard_n well_com_mat_incr well_com_mat_O well_com_mat_Ph by auto
text‹Test at while loop›
definition M0 :: "complex mat"where "M0 = mat K K (λ(i,j). if i = j ∧ i ≥ R then 1 else 0)"
lemma testN_mult_testN: "testN k * testN k = testN k" unfolding testN_def by (auto simp add: scalar_prod_def sum_only_one_neq_0)
lemma testN_dim: "testN k ∈ carrier_mat N N" unfolding testN_def by auto
definition test_fst_k :: "nat ==> complex mat"where "test_fst_k k = mat N N (λ(i, j). if (i = j ∧ i < k) then 1 else 0)"
lemma sum_test_k: assumes"m ≤ N" shows"matrix_sum N (λk. testN k) m = test_fst_k m" proof - have"m ≤ N ==> matrix_sum N (λk. testN k) m = mat N N (λ(i, j). if (i = j ∧ i < m) then 1 else 0)"for m proof (induct m) case0 thenshow ?caseapply simp apply (rule eq_matI) by auto next case (Suc m) thenhave m: "m < N"by auto thenhave m': "m ≤ N"by auto have"matrix_sum N testN (Suc m) = testN m + matrix_sum N testN m"by simp alsohave"… = mat N N (λ(i, j). if (i = j ∧ i < (Suc m)) then 1 else 0)" unfolding testN_def Suc(1)[OF m'] apply (rule eq_matI) by auto finallyshow ?caseby auto qed thenshow ?thesis unfolding test_fst_k_def using assms by auto qed
lemma test_fst_kN: "test_fst_k N = 1m N" apply (rule eq_matI) unfolding test_fst_k_def by auto
lemma matrix_sum_tensor_P1: "(∧k. k < m ==> g k ∈ carrier_mat N N) ==> (A ∈ carrier_mat K K) ==> matrix_sum d (λk. tensor_P (g k) A) m = tensor_P (matrix_sum N g m) A" proof (induct m) case0 show ?caseapply (simp) unfolding ps2_P.ptensor_mat_def using ps_P.tensor_mat_zero1[simplified ps_P_d ps_P_d1, of A] by auto next case (Suc m) thenhave ind: "matrix_sum d (λk. tensor_P (g k) A) m = tensor_P (matrix_sum N g m) A" and dk: "∧k. k < m ==> g k ∈ carrier_mat N N"and"A ∈ carrier_mat K K"by auto have ds: "matrix_sum N g m ∈ carrier_mat N N"apply (subst matrix_sum_dim) using dk by auto show ?caseapply simp apply (subst ind) unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_add1) unfolding ps_P_d1 ps_P_d2 using Suc ds by auto qed
text‹Grover's algorithm. Assume we start in the zero state› definition Grover :: com where "Grover = hadamard_n n ;; While_P vars2 M0 M1 D ;; Measure_P vars1 N testN (replicate N SKIP)"
lemma well_com_if: "well_com (Measure_P vars1 N testN (replicate N SKIP))" unfolding Measure_P_def apply auto proof - have eq0: "∧n. mat_extension dims vars1 (testN n) = tensor_P (testN n) (1m K)" unfolding mat_ext_vars1 by auto have eq1: "adjoint (tensor_P (testN j) (1m K)) * tensor_P (testN j) (1m K) = tensor_P (testN j) (1m K)"for j unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) apply (auto simp add: ps_P_d1 ps_P_d2 testN_dim hermitian_testN[unfolded hermitian_def] hermitian_one[unfolded hermitian_def]) apply (subst ps_P.tensor_mat_mult[symmetric]) by (auto simp add: ps_P_d1 ps_P_d2 testN_dim testN_mult_testN) have"measurement d N (λn. tensor_P (testN n) (1m K))" unfolding measurement_def apply (simp add: tensor_P_dim) apply (subst eq1) apply (subst matrix_sum_tensor_P1) apply (auto simp add: testN_dim) apply (subst sum_test_k, simp) apply (subst test_fst_kN) unfolding ps2_P.ptensor_mat_def using ps_P.tensor_mat_id ps_P_d ps_P_d1 ps_P_d2 by auto thenshow"measurement d N (λn. mat_extension dims vars1 (testN n))"using eq0 by auto
show"list_all well_com (replicate N SKIP)" apply (subst list_all_length) by simp qed
lemma well_com_while: "well_com (While_P vars2 M0 M1 D)" unfolding While_P_def apply auto apply (subst (12) mat_ext_vars2) apply (auto simp add: M1_dim M0_dim) proof - have2: "2 = Suc (Suc 0)"by auto have ad0: "adjoint (tensor_P (1m N) M0) = (tensor_P (1m N) M0)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) unfolding ps_P_d1 ps_P_d2 by (auto simp add: M0_dim adjoint_one hermitian_M0[unfolded hermitian_def]) have ad1: "adjoint (tensor_P (1m N) M1) = (tensor_P (1m N) M1)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) unfolding ps_P_d1 ps_P_d2 by (auto simp add: M1_dim adjoint_one hermitian_M1[unfolded hermitian_def]) have m0: "tensor_P (1m N) M0 * tensor_P (1m N) M0 = tensor_P (1m N) M0" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_mult[symmetric]) unfolding ps_P_d1 ps_P_d2 using M0_dim M0_mult_M0 by auto have m1: "tensor_P (1m N) M1 * tensor_P (1m N) M1 = tensor_P (1m N) M1" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_mult[symmetric]) unfolding ps_P_d1 ps_P_d2 using M1_dim M1_mult_M1 by auto have s: "tensor_P (1m N) M1 + tensor_P (1m N) M0 = 1m d" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_add2[symmetric]) unfolding ps_P_d1 ps_P_d2 by (auto simp add: M1_dim M0_dim M1_add_M0 ps_P.tensor_mat_id[simplified ps_P_d1 ps_P_d2 ps_P_d]) show"measurement d 2 (λn. if n = 0 then tensor_P (1m N) M0 else if n = 1 then tensor_P (1m N) M1 else undefined)" unfolding measurement_def apply (auto simp add: tensor_P_dim) apply (subst 2) apply (simp add: ad0 ad1 m0 m1) apply (subst assoc_add_mat[symmetric, of _ d d]) using tensor_P_dim s by auto show"well_com D"using well_com_D by auto qed
lemma well_com_Grover: "well_com Grover" unfolding Grover_def apply auto using well_com_hadamard_n well_com_if well_com_while by auto
subsection‹Correctness›
text‹Pre-condition: assume in the zero state›
definition ket_pre :: "complex vec"where "ket_pre = Matrix.vec N (λk. if k = 0 then 1 else 0)"
lemma ket_pre_dim: "ket_pre ∈ carrier_vec N"using ket_pre_def by auto
lemma pre_dim: "pre ∈ carrier_mat N N" using pre_def ket_pre_def by auto
lemma norm_pre: "inner_prod ket_pre ket_pre = 1" unfolding ket_pre_def scalar_prod_def using sum_only_one_neq_0[of "{0..<N}"0"λi. (if i = 0 then 1 else 0) * cnj (if i = 0 then 1 else 0)"] by auto
lemma pre_trace: "trace pre = 1" unfolding pre_def apply (subst trace_outer_prod[of _ N])
subgoal unfolding ket_pre_def by auto using norm_pre by auto
lemma positive_pre: "positive pre" using positive_same_outer_prod unfolding pre_def ket_pre_def by auto
lemma pre_le_one: "pre ≤L 1m N" unfolding pre_def using outer_prod_le_one norm_pre ket_pre_def by auto
text‹Post-condition: should be in a state i with f i = 1›
definitionpost :: "complex mat"where "post = mat N N (λ(i, j). if (i = j ∧ f i) then 1 else 0)"
lemma post_dim: "post ∈ carrier_mat N N" unfolding post_def by auto
lemma H_k_dim: "k < n ==> H_k k ∈ carrier_mat (2^(Suc k)) (2^(Suc k))" proof (induct k) case0 thenshow ?caseusing hadamard_dim by auto next case (Suc k) interpret st: partial_state2 dims "{0..<(Suc k)}""{Suc k}" apply unfold_locales by auto have"Suc (Suc k) ≤ n"using Suc by auto thenhave"nths dims ({0..<Suc (Suc k)}) = replicate (Suc (Suc k)) 2"using dims_nths_le_n by auto moreoverhave"prod_list (replicate l 2) = 2^l"for l by simp moreoverhave"{0..<Suc k} ∪ {Suc k} = {0..<(Suc (Suc k))}"by auto ultimatelyhave plssk: "prod_list (nths dims ({0..<Suc k} ∪ {Suc k})) = 2^(Suc (Suc k))"by auto have"dim_col (H_k (Suc k)) = 2^(Suc (Suc k))"using st.ptensor_mat_dim_col unfolding st.d0_def st.dims0_def st.vars0_def using plssk by auto moreoverhave"dim_row (H_k (Suc k)) = 2^(Suc (Suc k))"using st.ptensor_mat_dim_row unfolding st.d0_def st.dims0_def st.vars0_def using plssk by auto ultimatelyshow ?caseby auto qed
lemma exH_k_eq_H_k: "k < n ==> exH_k k = pmat_extension dims {0..<(Suc k)} {(Suc k)..<n} (H_k k)" proof(induct k) case0 have"{(Suc 0)..<n} = vars1 - {0..<(Suc 0)}"using vars1_def by fastforce thenshow ?caseunfolding exH_k.simps using vars1_def by auto next case (Suc k) interpret st: partial_state2 dims "{0..<Suc k}""{(Suc k)..<n}" apply unfold_locales by auto interpret st1: partial_state2 dims "{Suc k}""{(Suc (Suc k))..<n}" apply unfold_locales by auto interpret st2: partial_state2 dims "{Suc k}""vars1 - {Suc k}" apply unfold_locales by auto interpret st3: partial_state2 dims "{0..<Suc k}""{Suc (Suc k)..<n}" apply unfold_locales by auto interpret st4: partial_state2 dims "{0..<Suc (Suc k)}""{Suc (Suc k)..<n}" apply unfold_locales by auto
from Suc have eq0: "exH_k (Suc k) = (st.pmat_extension (H_k k)) * (st2.pmat_extension hadamard)"by auto have"vars1 - {0..<Suc k} = {(Suc k)..<n}"using vars1_def by auto
thenhave eql1: "st.pmat_extension (H_k k) = st.ptensor_mat (H_k k) (1m st.d2)" using st.pmat_extension_def by auto
from dims_nths_one_lt_n[OF Suc(2)] have st1d1: "st1.d1 = 2"unfolding st1.d1_def st1.dims1_def by fastforce have"{Suc k} ∪ {Suc (Suc k)..<n} = {Suc k..<n}"using Suc by auto thenhave"st1.d0 = st.d2"unfolding st1.d0_def st1.dims0_def st1.vars0_def st.d2_def st.dims2_def by fastforce thenhave eql2: "st1.ptensor_mat (1m 2) (1m st1.d2) = 1m st.d2" using st1.ptensor_mat_id st1d1 by auto have eql3: "st.ptensor_mat (H_k k) (1m st.d2) = st.ptensor_mat (H_k k) (st1.ptensor_mat (1m 2) (1m st1.d2))" apply (subst eql2[symmetric]) by auto
have eqr1: "(st2.pmat_extension hadamard) = st2.ptensor_mat hadamard (1m st2.d2)"using st2.pmat_extension_def by auto have splitset: "{0..<Suc k} ∪ {Suc (Suc k)..<n} = vars1 - {Suc k}"unfolding vars1_def using Suc(2) by auto
have Sksplit: "{Suc k} ∪ {Suc (Suc k)..<n} = {Suc k..<n}"using Suc(2) by auto have Sksplit1: "{0..<Suc k}∪{Suc k} = {0..<Suc (Suc k)}"by auto have"st.ptensor_mat (H_k k) (st1.ptensor_mat (1m 2) (1m st1.d2)) = ptensor_mat dims ({0..<Suc k}∪{Suc k}) {Suc (Suc k)..<n} (ptensor_mat dims {0..<Suc k} {Suc k} (H_k k) (1m 2)) (1m st1.d2)" apply (subst ptensor_mat_assoc[symmetric, of "{0..<Suc k}""{Suc k}""{Suc (Suc k)..<n}""H_k k""1m 2""1m st1.d2", simplified Sksplit]) using Suc length_dims by auto alsohave"… = ptensor_mat dims ({0..<Suc k}∪{Suc k}) {Suc (Suc k)..<n} (ptensor_mat dims {Suc k} {0..<Suc k} (1m 2) (H_k k)) (1m st1.d2)" using ptensor_mat_comm[of "{0..<Suc k}""{Suc k}"] by auto alsohave"… = ptensor_mat dims {Suc k} ({0..<Suc k} ∪ {Suc (Suc k)..<n}) (1m 2) (ptensor_mat dims {0..<Suc k} {Suc (Suc k)..<n} (H_k k) (1m st1.d2))" apply (subst sup_commute) apply (subst ptensor_mat_assoc[of "{Suc k}""{0..<Suc k}""{Suc (Suc k)..<n}""(1m 2)""H_k k""1m st1.d2"]) using Suc length_dims by auto finallyhave eql4: "st.pmat_extension (H_k k) = st2.ptensor_mat (1m 2) (st3.ptensor_mat (H_k k) (1m st3.d2))"using eql1 eql3 splitset by auto
have"st2.ptensor_mat (1m 2) (st3.ptensor_mat (H_k k) (1m st3.d2)) * st2.ptensor_mat hadamard (1m st2.d2) = st2.ptensor_mat ((1m 2)*hadamard) ((st3.ptensor_mat (H_k k) (1m st3.d2))*(1m st2.d2))" apply (rule st2.ptensor_mat_mult[symmetric, of "1m 2""hadamard""(st3.ptensor_mat (H_k k) (1m st3.d2))""(1m st2.d2)"])
subgoal unfolding st2.d1_def st2.dims1_def by (simp add: dims_nths_one_lt_n Suc(2))
subgoal unfolding st2.d1_def st2.dims1_def apply (simp add: dims_nths_one_lt_n Suc(2)) using hadamard_dim by auto
subgoal unfolding st2.d2_def[unfolded st2.dims2_def] using st3.ptensor_mat_dim_col[unfolded st3.d0_def st3.dims0_def st3.vars0_def, simplified splitset]
st3.ptensor_mat_dim_row[unfolded st3.d0_def st3.dims0_def st3.vars0_def, simplified splitset] by auto by auto alsohave"… = st2.ptensor_mat (hadamard) (st3.ptensor_mat (H_k k) (1m st3.d2))" unfolding st2.d2_def[unfolded st2.dims2_def] using hadamard_dim st3.ptensor_mat_dim_col[unfolded st3.d0_def st3.dims0_def st3.vars0_def, simplified splitset]
st3.ptensor_mat_dim_row[unfolded st3.d0_def st3.dims0_def st3.vars0_def, simplified splitset] by auto alsohave"… = ptensor_mat dims ({0..<Suc k}∪{Suc k}) {Suc (Suc k)..<n} (ptensor_mat dims {Suc k} {0..<Suc k} hadamard (H_k k)) (1m st3.d2)" apply (subst ptensor_mat_assoc[symmetric, of "{Suc k}""{0..<Suc k}""{Suc (Suc k)..<n}""hadamard""H_k k""1m st3.d2", simplified splitset]) using Suc length_dims by auto alsohave"… = ptensor_mat dims ({0..<Suc k}∪{Suc k}) {Suc (Suc k)..<n} (H_k (Suc k)) (1m st3.d2)" using ptensor_mat_comm[of "{Suc k}"] Sksplit1 by auto alsohave"… = ptensor_mat dims ({0..<Suc (Suc k)}) {Suc (Suc k)..<n} (H_k (Suc k)) (1m st3.d2)"using Sksplit1 by auto alsohave"… = pmat_extension dims {0..<Suc (Suc k)} {Suc (Suc k)..<n} (H_k (Suc k))" unfolding st4.pmat_extension_def by auto finallyshow ?caseusing eq0 eql4 eqr1 by auto qed
lemma mult_exH_k_left: assumes"Suc k < n" shows"hadamard_on_i (Suc k) * exH_k k = exH_k (Suc k)" proof - interpret st: partial_state2 dims "{0..<Suc k}""{(Suc k)..<n}" apply unfold_locales by auto interpret st1: partial_state2 dims "{Suc k}""{(Suc (Suc k))..<n}" apply unfold_locales by auto interpret st2: partial_state2 dims "{Suc k}""vars1 - {Suc k}" apply unfold_locales by auto interpret st3: partial_state2 dims "{0..<Suc k}""{Suc (Suc k)..<n}" apply unfold_locales by auto interpret st4: partial_state2 dims "{0..<Suc (Suc k)}""{Suc (Suc k)..<n}" apply unfold_locales by auto
from exH_k_eq_H_k assms have eq0: "exH_k (Suc k) = (st.pmat_extension (H_k k)) * (st2.pmat_extension hadamard)"by auto have"vars1 - {0..<Suc k} = {(Suc k)..<n}"using vars1_def by auto
thenhave eql1: "st.pmat_extension (H_k k) = st.ptensor_mat (H_k k) (1m st.d2)" using st.pmat_extension_def by auto
from dims_nths_one_lt_n[OF assms] have st1d1: "st1.d1 = 2"unfolding st1.d1_def st1.dims1_def by fastforce have"{Suc k} ∪ {Suc (Suc k)..<n} = {Suc k..<n}"using assms by auto thenhave"st1.d0 = st.d2"unfolding st1.d0_def st1.dims0_def st1.vars0_def st.d2_def st.dims2_def by fastforce thenhave eql2: "st1.ptensor_mat (1m 2) (1m st1.d2) = 1m st.d2" using st1.ptensor_mat_id st1d1 by auto have eql3: "st.ptensor_mat (H_k k) (1m st.d2) = st.ptensor_mat (H_k k) (st1.ptensor_mat (1m 2) (1m st1.d2))" apply (subst eql2[symmetric]) by auto
have eqr1: "(st2.pmat_extension hadamard) = st2.ptensor_mat hadamard (1m st2.d2)"using st2.pmat_extension_def by auto have splitset: "{0..<Suc k} ∪ {Suc (Suc k)..<n} = vars1 - {Suc k}"unfolding vars1_def using assms by auto
have Sksplit: "{Suc k} ∪ {Suc (Suc k)..<n} = {Suc k..<n}"using assms by auto have Sksplit1: "{0..<Suc k}∪{Suc k} = {0..<Suc (Suc k)}"by auto have"st.ptensor_mat (H_k k) (st1.ptensor_mat (1m 2) (1m st1.d2)) = ptensor_mat dims ({0..<Suc k}∪{Suc k}) {Suc (Suc k)..<n} (ptensor_mat dims {0..<Suc k} {Suc k} (H_k k) (1m 2)) (1m st1.d2)" apply (subst ptensor_mat_assoc[symmetric, of "{0..<Suc k}""{Suc k}""{Suc (Suc k)..<n}""H_k k""1m 2""1m st1.d2", simplified Sksplit]) using assms length_dims by auto alsohave"… = ptensor_mat dims ({0..<Suc k}∪{Suc k}) {Suc (Suc k)..<n} (ptensor_mat dims {Suc k} {0..<Suc k} (1m 2) (H_k k)) (1m st1.d2)" using ptensor_mat_comm[of "{0..<Suc k}""{Suc k}"] by auto alsohave"… = ptensor_mat dims {Suc k} ({0..<Suc k} ∪ {Suc (Suc k)..<n}) (1m 2) (ptensor_mat dims {0..<Suc k} {Suc (Suc k)..<n} (H_k k) (1m st1.d2))" apply (subst sup_commute) apply (subst ptensor_mat_assoc[of "{Suc k}""{0..<Suc k}""{Suc (Suc k)..<n}""(1m 2)""H_k k""1m st1.d2"]) using assms length_dims by auto finallyhave"st.pmat_extension (H_k k) = st2.ptensor_mat (1m 2) (st3.ptensor_mat (H_k k) (1m st3.d2))"using eql1 eql3 splitset by auto moreoverhave"st.pmat_extension (H_k k) = exH_k k"using exH_k_eq_H_k assms by auto ultimatelyhave eql4: "exH_k k = st2.ptensor_mat (1m 2) (st3.ptensor_mat (H_k k) (1m st3.d2))"by auto
have"st2.ptensor_mat hadamard (1m st2.d2) * st2.ptensor_mat (1m 2) (st3.ptensor_mat (H_k k) (1m st3.d2)) = st2.ptensor_mat (hadamard*(1m 2)) ((1m st2.d2)* (st3.ptensor_mat (H_k k) (1m st3.d2)))" apply (rule st2.ptensor_mat_mult[symmetric, of "hadamard""1m 2""(1m st2.d2)""(st3.ptensor_mat (H_k k) (1m st3.d2))"])
subgoal unfolding st2.d1_def st2.dims1_def apply (simp add: dims_nths_one_lt_n assms) using hadamard_dim by auto
subgoal unfolding st2.d1_def st2.dims1_def by (simp add: dims_nths_one_lt_n assms)
subgoal by auto
subgoal unfolding st2.d2_def[unfolded st2.dims2_def] using st3.ptensor_mat_dim_col[unfolded st3.d0_def st3.dims0_def st3.vars0_def, simplified splitset]
st3.ptensor_mat_dim_row[unfolded st3.d0_def st3.dims0_def st3.vars0_def, simplified splitset] by auto done alsohave"… = st2.ptensor_mat (hadamard) (st3.ptensor_mat (H_k k) (1m st3.d2))" unfolding st2.d2_def[unfolded st2.dims2_def] using hadamard_dim st3.ptensor_mat_dim_col[unfolded st3.d0_def st3.dims0_def st3.vars0_def, simplified splitset]
st3.ptensor_mat_dim_row[unfolded st3.d0_def st3.dims0_def st3.vars0_def, simplified splitset] by auto alsohave"… = ptensor_mat dims ({0..<Suc k}∪{Suc k}) {Suc (Suc k)..<n} (ptensor_mat dims {Suc k} {0..<Suc k} hadamard (H_k k)) (1m st3.d2)" apply (subst ptensor_mat_assoc[symmetric, of "{Suc k}""{0..<Suc k}""{Suc (Suc k)..<n}""hadamard""H_k k""1m st3.d2", simplified splitset]) using assms length_dims by auto alsohave"… = ptensor_mat dims ({0..<Suc k}∪{Suc k}) {Suc (Suc k)..<n} (H_k (Suc k)) (1m st3.d2)" using ptensor_mat_comm[of "{Suc k}"] Sksplit1 by auto alsohave"… = ptensor_mat dims ({0..<Suc (Suc k)}) {Suc (Suc k)..<n} (H_k (Suc k)) (1m st3.d2)"using Sksplit1 by auto alsohave"… = pmat_extension dims {0..<Suc (Suc k)} {Suc (Suc k)..<n} (H_k (Suc k))" unfolding st4.pmat_extension_def by auto alsohave"… = exH_k (Suc k)"using exH_k_eq_H_k[of "Suc k"] assms by auto finallyhave"st2.ptensor_mat hadamard (1m st2.d2) * st2.ptensor_mat (1m 2) (st3.ptensor_mat (H_k k) (1m st3.d2)) =exH_k (Suc k)". thenshow ?thesis unfolding hadamard_on_i_def using eql4 eqr1 by auto qed
lemma exH_eq_H: "exH_k (n - 1) = H_k (n - 1)" proof - have"∃m. n = Suc (Suc m)"using n by presburger thenobtain m where m: "n = Suc (Suc m)"using n by auto thenhave"exH_k m = pmat_extension dims {0..<(Suc m)} {(Suc m)..<n} (H_k m)"using exH_k_eq_H_k by auto thenhave"exH_k (Suc m) = pmat_extension dims {0..<(Suc m)} {(Suc m)..<n} (H_k m) * (pmat_extension dims {Suc m} (vars1 - {Suc m}) hadamard)"by auto moreoverhave"{(Suc m)..<n} = {Suc m}"using m by auto moreoverhave"vars1 - {Suc m} = {0..<Suc m}"unfolding vars1_def using m by auto ultimatelyhave eqSm: "exH_k (Suc m) = pmat_extension dims {0..<(Suc m)} {Suc m} (H_k m) * (pmat_extension dims {Suc m} {0..<Suc m} hadamard)"by auto
interpret stm1: partial_state2 dims "{Suc m}""{0..<Suc m}" apply unfold_locales by auto interpret stm2: partial_state2 dims "{0..<Suc m}""{Suc m}" apply unfold_locales by auto have"nths dims {0..<Suc m} = replicate (Suc m) 2"using dims_nths_le_n m by auto thenhave stm2d1: "stm2.d1 = 2^(Suc m)"unfolding stm2.d1_def stm2.dims1_def by auto have stm2d2: "stm2.d2 = 2"unfolding stm2.d2_def stm2.dims2_def using dims_nths_one_lt_n m by auto
have"m < n"using m by auto thenhave"H_k m ∈ carrier_mat (2^(Suc m)) (2^(Suc m))"using H_k_dim by auto thenhave Hkm1: "(H_k m) * (1m stm2.d1) = (H_k m)"unfolding stm2d1 by auto
have eqd12: "stm1.d2 = stm2.d1"unfolding stm1.d2_def stm1.dims2_def stm2.d1_def stm2.dims1_def by auto have"pmat_extension dims {Suc m} {0..<Suc m} hadamard = stm1.ptensor_mat hadamard (1m stm1.d2)"using stm1.pmat_extension_def by auto alsohave"… = stm2.ptensor_mat (1m stm2.d1) hadamard"using ptensor_mat_comm eqd12 byauto finallyhave eqr: "(pmat_extension dims {Suc m} {0..<Suc m} hadamard) = stm2.ptensor_mat (1m stm2.d1) hadamard". thenhave"exH_k (Suc m) = stm2.ptensor_mat (H_k m) (1m stm2.d2) * stm2.ptensor_mat (1m stm2.d1) hadamard" using eqSm unfolding stm2.pmat_extension_def by auto alsohave"… = stm2.ptensor_mat ((H_k m) * (1m stm2.d1)) (1m stm2.d2 * hadamard)" apply (rule stm2.ptensor_mat_mult[symmetric, of "H_k m""1m stm2.d1""1m stm2.d2""hadamard"]) unfolding stm2d1 stm2d2 using H_k_dim m hadamard_dim by auto alsohave"… = stm2.ptensor_mat (H_k m) (hadamard)"using H_k_dim hadamard_dim stm2d1 stm2d2 Hkm1 by auto alsohave"… = H_k (Suc m)"unfolding stm2.ptensor_mat_def H_k.simps by auto finallyhave"exH_k (Suc m) = H_k (Suc m)"by auto moreoverhave"Suc m = n - 1"using m by auto ultimatelyshow ?thesis by auto qed
lemma ket_plus_k_dim: assumes"k < n" shows"ket_plus_k k ∈ carrier_vec (2^(Suc k))" proof (cases k) case0 show ?thesis using ket_plus_dim 0by auto next case (Suc k) interpret st: partial_state2 dims "{0..<(Suc k)}""{Suc k}" apply unfold_locales by auto have"Suc (Suc k) ≤ n"using assms Suc by auto thenhave"nths dims ({0..<Suc (Suc k)}) = replicate (Suc (Suc k)) 2"using dims_nths_le_n by auto moreoverhave"prod_list (replicate l 2) = 2^l"for l by simp moreoverhave"{0..<Suc k} ∪ {Suc k} = {0..<(Suc (Suc k))}"by auto ultimatelyhave plssk: "prod_list (nths dims ({0..<Suc k} ∪ {Suc k})) = 2^(Suc (Suc k))"by auto show ?thesis apply (rule carrier_vecI) unfolding ket_zero_k.simps Suc using st.ptensor_vec_dim plssk unfolding st.d0_def st.dims0_def st.vars0_def by auto qed
lemma H_k_ket_zero_k: "k < n ==> (H_k k) *v (ket_zero_k k) = (ket_plus_k k)" proof (induct k) case0 show ?caseusing hadamard_on_zero unfolding H_k.simps ket_zero_k.simps ket_plus_k.simps by auto next case (Suc k) thenhave k: "k < n"by auto interpret st: partial_state2 dims "{0..<(Suc k)}""{Suc k}" apply unfold_locales by auto have"nths dims {0..<Suc k} = replicate (Suc k) 2"using dims_nths_le_n Suc by auto thenhave std1: "st.d1 = 2^(Suc k)"unfolding st.d1_def st.dims1_def by auto have std2: "st.d2 = 2"unfolding st.d2_def st.dims2_def using dims_nths_one_lt_n Suc by auto have"H_k (Suc k) *v ket_zero_k (Suc k) = st.ptensor_mat (H_k k) hadamard *v st.ptensor_vec (ket_zero_k k) ket_zero"by auto alsohave"… = st.ptensor_vec ((H_k k) *v (ket_zero_k k)) (hadamard *v ket_zero)" using st.ptensor_mat_mult_vec[unfolded std1 std2, OF H_k_dim[OF k] ket_zero_k_dim[OF k] hadamard_dim ket_zero_dim] by auto alsohave"… = st.ptensor_vec (ket_plus_k k) ket_plus"using Suc hadamard_on_zero by auto finallyshow ?caseby auto qed
lemma encode1_replicate_2: "partial_state.encode1 (replicate (Suc k) 2) {0..<k} i = i mod (2 ^ k)" proof - have take_Suc: "take k (replicate (Suc k) 2) = replicate k 2" apply (subst take_replicate) by auto have take_encode: "take k (digit_encode (replicate (Suc k) 2) i) = digit_encode (replicate k 2) i" apply (subst digit_encode_take) using take_Suc by metis show ?thesis unfolding partial_state.encode1_def partial_state.dims1_def
nths_upt_eq_take[simplified lessThan_atLeast0] take_Suc take_encode
digit_decode_encode prod_list_replicate .. qed
lemma encode2_replicate_2: assumes"i < 2 ^ Suc k" shows"partial_state.encode2 (replicate (Suc k) 2) {0..<k} i = i div (2 ^ k)" proof - have drop_Suc: "drop k (replicate (Suc k) 2) = [2]" apply (subst drop_replicate) by auto have drop_encode: "drop k (digit_encode (replicate (Suc k) 2) i) = digit_encode [2] (i div (2 ^ k))" unfolding digit_encode_drop drop_Suc take_replicate prod_list_replicate by (metis lessI min.strict_order_iff) have le2: "i div 2 ^ k < 2" using assms by (auto simp add: less_mult_imp_div_less) have prod_list_2: "prod_list [2] = 2"by simp show ?thesis unfolding partial_state.encode2_def partial_state.dims2_def
nths_minus_upt_eq_drop[simplified lessThan_atLeast0] drop_Suc drop_encode
digit_decode_encode prod_list_2 using le2 by auto qed
lemma ket_zero_k_decode: "k < n ==> ket_zero_k k = Matrix.vec (2^(Suc k)) (λk. if k = 0 then 1 else 0)" proof (induct k) case0 show ?caseapply (rule eq_vecI) by (auto simp add: ket_zero_def) next case (Suc k) thenhave k: "k < n"by auto have kzkk: "ket_zero_k k = Matrix.vec (2 ^ Suc k) (λk. if (k = 0) then 1 else 0)"using Suc(1)[OF k] by auto
have dSk: "ket_zero_k (Suc k) ∈ carrier_vec (2^(Suc (Suc k)))"using ket_zero_k_dim[OF Suc(2)] by auto
have splitset: "({0..<Suc k} ∪ {Suc k}) = {0..<Suc (Suc k)}"by auto thenhave st2dims0: "st2.dims0 = replicate (Suc (Suc k)) 2"unfolding st2.dims0_def st2.vars0_def using dims_nths_le_n[of "Suc (Suc k)"] Suc by auto have"∧x. (x ∈ {0..<Suc k} ==> {y ∈ {0..<Suc (Suc k)}. y < x} = {0..<x})"by auto thenhave cardeq: "∧x. (x ∈ {0..<Suc k} ==> card {y ∈ {0..<Suc (Suc k)}. y < x} = card {0..<x})"by auto have setcong: "∧g h I. (∧x. (x ∈ I ==> g x = h x)) ==> {g x | x. x ∈ I} = {h x | x. x ∈ I}"by metis have"{card {y ∈ {0..<Suc (Suc k)}. y < x} |x. x ∈ {0..<Suc k}} = {card {0..<x} |x. x∈ {0..<Suc k}} " using setcong[OF cardeq, of "{0..<Suc k}"] by auto alsohave"… = {0..<Suc k}"by auto finallyhave st2vars1': "st2.vars1' = {0..<Suc k}"unfolding st2.vars1'_def st2.vars0_def splitset ind_in_set_def by fastforce have st2pvsttv: "st2.ptensor_vec = st.tensor_vec"unfolding st2.ptensor_vec_def usingst2dims0 st2vars1' by auto have"st.encode1 0 = 0"using encode1_replicate_2[of "Suc k"0] by auto moreoverhave"st.encode2 0 = 0"using encode2_replicate_2[of 0"Suc k"] by auto moreoverhave std: "st.d = 2^(Suc (Suc k))"unfolding st.d_def by auto ultimatelyhave kzkk0: "ket_zero_k (Suc k) $ 0 = 1" unfolding ket_zero_k.simps st2pvsttv st.tensor_vec_def ket_zero_def using kzkk by auto
have kzkki: "ket_zero_k (Suc k) $ i = 0"if ine0: "i ≠ 0"and ile: "i < 2^(Suc (Suc k))"for i proof (cases "i mod (2 ^ Suc k) ≠ 0") case True thenhave"ket_zero_k k $ st.encode1 i = 0"unfolding kzkk using encode1_replicate_2[of "Suc k" i] ile by auto thenshow ?thesis unfolding ket_zero_k.simps st2pvsttv st.tensor_vec_def ket_zero_def std using ile by auto next case False have"i div (2 ^ Suc k) ≠ 0 ∨ i mod (2 ^ Suc k) ≠ 0"using ine0 by fastforce thenhave"i div (2 ^ Suc k) ≠ 0"using False by auto moreoverhave"i div (2 ^ Suc k) < 2"using ile less_mult_imp_div_less by auto ultimatelyhave"i div (2 ^ Suc k) = 1"by auto thenhave"st.encode2 i = 1"using encode2_replicate_2[of i "Suc k"] ile by auto thenhave"Matrix.vec 2 (λk. if k = 0 then 1 else 0) $ st.encode2 i = 0" unfolding kzkk by fastforce thenshow ?thesis unfolding ket_zero_k.simps st2pvsttv st.tensor_vec_def ket_zero_def std using ile by auto qed
show ?caseapply (rule eq_vecI)
subgoal for i using kzkk0 kzkki by auto using carrier_vecD[OF dSk] by auto qed
lemma ket_plus_k_decode: "k < n ==> ket_plus_k k = Matrix.vec (2^(Suc k)) (λl. 1 / csqrt (2^(Suc k)))" proof (induct k) case0 thenshow ?caseunfolding ket_plus_k.simps ket_plus_def by auto next case (Suc k) thenhave kpkk: "ket_plus_k k = Matrix.vec (2 ^ Suc k) (λl. 1 / csqrt (2 ^ Suc k))"by auto
have dSk: "ket_plus_k (Suc k) ∈ carrier_vec (2^(Suc (Suc k)))"using ket_plus_k_dim[OF Suc(2)] by auto
have std: "st.d = 2^(Suc (Suc k))"unfolding st.d_def by auto
have nthsSSk2: "nths (replicate (Suc (Suc k)) 2) {0..<Suc k} = replicate (Suc k) 2" unfolding nths_replicate[of "Suc (Suc k)"2"{0..<Suc k}"] by (smt (verit) Collect_cong ‹{card {0..<x} |x. x ∈ {0..<Suc k}} = {0..<Suc k}› atLeastLessThan_iff card_atLeastLessThan diff_zero less_SucI) thenhave std1: "st.d1 = 2^(Suc k)"unfolding st.d1_def st.dims1_def nthsSSk2 by auto have"{i. i < Suc (Suc k) ∧ i ∈ {Suc k..}} = {Suc k}"by auto thenhave"nths (replicate (Suc (Suc k)) 2) ({Suc k..}) = replicate 1 2"unfolding nths_replicate by auto moreoverhave"(- {0..<Suc k}) = {Suc k..}"by auto ultimatelyhave nthsSSk2c: "nths (replicate (Suc (Suc k)) 2) (- {0..<Suc k}) = replicate 1 2"by auto have std2: "st.d2 = 2"unfolding st.d2_def st.dims2_def apply (subst nthsSSk2c) by auto
have"st.encode1 i < st.d1"if"i < st.d"for i using that st.encode1_lt[OF that] by auto thenhave kpkki: "ket_plus_k k $ st.encode1 i = 1 / csqrt (2^(Suc k))"if"i < st.d"for i unfolding kpkk std1 using that by auto have"st.encode2 i < st.d2"if"i < st.d"for i using that st.encode2_lt[OF that] by auto thenhave kpi: "ket_plus $ st.encode2 i = 1 / csqrt 2"if"i < st.d"for i unfolding ket_plus_def std2 using that by auto have kzkki: "ket_plus_k (Suc k) $ i = 1 / (csqrt (2 ^ (Suc (Suc k))))"if"i < st.d"for i unfolding ket_plus_k.simps st2pvsttv st.tensor_vec_def using csqrt2p kpkki kpi that by auto show ?caseapply (rule eq_vecI)
subgoal for i using kzkki unfolding std by auto using carrier_vecD[OF dSk] by auto qed
lemma exH_k_mult_pre_is_psi: "exH_k (n - 1) *v ket_pre = ψ" proof - have"exH_k (n - 1) = H_k (n - 1)"using exH_eq_H by auto moreoverhave"ket_zero_k (n - 1) = ket_pre"using ket_zero_k_decode[of "n - 1"] ket_pre_def N_def n by auto moreoverhave"ket_plus_k (n - 1) = ψ"using ket_plus_k_decode[of "n - 1"] ψ_def N_def n byauto moreoverhave"H_k (n - 1) *v ket_zero_k (n - 1) = ket_plus_k (n - 1)"using H_k_ket_zero_k n by auto ultimatelyshow ?thesis by auto qed
definition ket_k :: "nat ==> complex vec"where "ket_k x = Matrix.vec K (λk. if k = x then 1 else 0)"
lemma ket_k_dim: "ket_k k ∈ carrier_vec K" unfolding ket_k_def by auto
lemma mat_incr_mult_ket_k: "k < K ==> (mat_incr K) *v (ket_k k) = (ket_k ((k + 1) mod K))" apply (rule eq_vecI) unfolding mat_incr_def ket_k_def apply (simp add: scalar_prod_def) apply (case_tac "k = K - 1")
subgoal for i apply auto by (simp add: sum_only_one_neq_0[of _ "K - 1"])
subgoal for i apply auto by (simp add: sum_only_one_neq_0[of _ "i - 1"]) by auto
definition proj_k where "proj_k x = proj (ket_k x)"
lemma proj_k_dim: "proj_k k ∈ carrier_mat K K" unfolding proj_k_def using ket_k_dim by auto
lemma norm_ket_k_lt_K: "k < K ==> inner_prod (ket_k k) (ket_k k) = 1" unfolding ket_k_def apply (simp add: scalar_prod_def) using sum_only_one_neq_0[of "{0..<K}" k "λi. (if i = k then 1 else 0) * cnj (if i = k then 1 else 0)"] by auto
lemma norm_ket_k_ge_K: "k ≥ K ==> inner_prod (ket_k k) (ket_k k) = 0" unfolding ket_k_def by (simp add: scalar_prod_def)
lemma proj_k_mat: assumes"k < K" shows"proj_k k = mat K K (λ(i, j). if (i = j ∧ i = k) then 1 else 0)" apply (rule eq_matI) apply (simp add: proj_k_def ket_k_def index_outer_prod) using proj_k_dim by auto
lemma positive_proj_k: "positive (proj_k k)" using positive_same_outer_prod unfolding proj_k_def ket_k_def by auto
lemma proj_k_le_one: "(proj_k k) ≤L 1m K" unfolding proj_k_def using outer_prod_le_one norm_ket_k ket_k_def by auto
definition proj_psi where "proj_psi = proj ψ"
lemma proj_psi_dim: "proj_psi ∈ carrier_mat N N" unfolding proj_psi_def ψ_defby auto
lemma hermitian_exproj_psi: "hermitian (tensor_P proj_psi (1m K))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_hermitian) using proj_psi_dim ps_P_d1 ps_P_d2 hermitian_proj_psi hermitian_one by auto
lemma proj_psi_is_projection: "proj_psi * proj_psi = proj_psi" proof - have"proj_psi * proj_psi = inner_prod ψ ψ ⋅m proj_psi" unfolding proj_psi_def apply (subst outer_prod_mult_outer_prod) using ψ_defby auto alsohave"… = proj_psi" using ψ_inner by auto finallyshow ?thesis. qed
lemma proj_psi_trace: "trace (proj_psi) = 1" unfolding proj_psi_def apply (subst trace_outer_prod[of _ N])
subgoal unfolding ψ_defby auto using norm_psi by auto
lemma positive_proj_psi: "positive (proj_psi)" using positive_same_outer_prod unfolding proj_psi_def ψ_defby auto
lemma proj_psi_le_one: "(proj_psi) ≤L 1m N" unfolding proj_psi_def using outer_prod_le_one norm_psi ψ_defby auto
lemma hermitian_hadamard_on_k: assumes"k < n" shows"hermitian (hadamard_on_i k)" proof - interpret st2: partial_state2 dims "{k}""(vars1 - {k})" apply unfold_locales by auto have st2d1: "st2.dims1 = [2]"unfolding st2.dims1_def dims_def using assms dims_nths_one_lt_n local.dims_def st2.dims1_def by auto show"hermitian (hadamard_on_i k)"unfolding hadamard_on_i_def st2.pmat_extension_def st2.ptensor_mat_def apply (rule partial_state.tensor_mat_hermitian)
subgoal unfolding partial_state.d1_def partial_state.dims1_def st2.nths_vars1' hadamard_def by (simp add: st2d1)
subgoal unfolding partial_state.d2_def partial_state.dims2_def st2.nths_vars2' st2.d2_def by auto
subgoal unfolding hermitian_def hadamard_def apply (rule eq_matI) by (auto simp add: adjoint_dim adjoint_eval) using hermitian_one by auto qed
lemma hermitian_H_k: "k < n ==> hermitian (H_k k)" proof (induct k) case0 show ?caseunfolding H_k.simps hermitian_def hadamard_def apply (rule eq_matI) by (auto simp add: adjoint_dim adjoint_eval) next case (Suc k) interpret st2: partial_state2 dims "{0..<Suc k}""{Suc k}" apply unfold_locales by auto have st2d1: "prod_list st2.dims1 = (2^(Suc k))"unfolding st2.dims1_def dims_def usingSuc(2) using dims_nths_le_n local.dims_def st2.dims1_def by auto have st2d2: "st2.dims2 = [2]"unfolding st2.dims2_def dims_def using Suc(2) using dims_nths_one_lt_n local.dims_def st2.dims2_def by auto show ?caseunfolding H_k.simps st2.ptensor_mat_def apply (rule partial_state.tensor_mat_hermitian)
subgoal unfolding partial_state.d1_def partial_state.dims1_def st2.nths_vars1' using st2d1 H_k_dim Suc by auto
subgoal unfolding partial_state.d2_def partial_state.dims2_def st2.nths_vars2' st2.d2_def using st2d2 by (simp add: hadamard_def)
subgoal using Suc by auto using hermitian_hadamard by auto qed
lemma unitary_H_k: "k < n ==> unitary (H_k k)" proof (induct k) case0 show ?caseusing unitary_hadamard by auto next case (Suc k) thenhave k: "k < n"by auto interpret st2: partial_state2 dims "{0..<Suc k}""{Suc k}"by (unfold_locales, auto)
have st2d1: "prod_list st2.dims1 = (2^(Suc k))"unfolding st2.dims1_def dims_def usingSuc(2) using dims_nths_le_n local.dims_def st2.dims1_def by auto have st2d2: "st2.dims2 = [2]"unfolding st2.dims2_def dims_def using Suc(2) using dims_nths_one_lt_n local.dims_def st2.dims2_def by auto show ?caseunfolding H_k.simps st2.ptensor_mat_def apply (rule partial_state.tensor_mat_unitary[of "H_k k" st2.dims0 st2.vars1' hadamard] ) unfolding partial_state.d1_def partial_state.dims1_def st2.nths_vars1' partial_state.d2_def partial_state.dims2_def
st2.nths_vars2' apply (auto simp add: st2d1 st2d2 )
subgoal using H_k_dim[OF k] by auto
subgoal using hadamard_dim by auto
subgoal using Suc by auto using unitary_hadamard by auto qed
lemma exH_k_dim: shows"k < n ==> exH_k k ∈ carrier_mat N N" apply (induct k) using hadamard_on_i_dim by auto
lemma exH_n_dim: shows"exH_k (n - 1) ∈ carrier_mat N N" using exH_k_dim n by auto
lemma unitary_exH_k: shows"k < n ==> unitary (exH_k k)" proof (induct k) case0 thenshow ?caseunfolding exH_k.simps using unitary_hadamard_on_i 0by auto next case (Suc k) show ?caseunfolding exH_k.simps apply (subst unitary_times_unitary[of _ N])
subgoal using exH_k_dim Suc by auto
subgoal using hadamard_on_i_dim Suc by auto
subgoal using Suc by auto using unitary_hadamard_on_i Suc by auto qed
lemma hermitian_exH_n: "hermitian (exH_k (n - 1))" using hermitian_H_k exH_eq_H n by auto
lemma exH_k_mult_psi_is_pre: "exH_k (n - 1) *v ψ = ket_pre" proof - let ?H = "exH_k (n - 1)" have"hermitian ?H"using hermitian_H_k exH_eq_H n by auto thenhave eqad: "adjoint ?H = ?H"unfolding hermitian_def by auto have d: "?H ∈ carrier_mat N N"using exH_k_dim n by auto have"unitary ?H"using unitary_exH_k n by auto thenhave id: "?H * ?H = 1m N" unfolding unitary_def inverts_mat_def using d apply (subst (2) eqad[symmetric]) by auto have"?H *v ψ = ?H *v (?H *v ket_pre)" using exH_k_mult_pre_is_psi by auto alsohave"… = (?H * ?H) *v ket_pre" using d ket_pre_def by auto alsohave"… = ket_pre" using id ket_pre_def by auto finallyshow ?thesis by auto qed
fun exexH_k :: "nat ==> complex mat"where "exexH_k k = tensor_P (exH_k k) (1m K)"
lemma unitary_exexH_k: "k < n ==> unitary (exexH_k k)" unfolding exexH_k.simps ps2_P.ptensor_mat_def apply (subst partial_state.tensor_mat_unitary)
subgoal using exH_k_dim unfolding partial_state.d1_def partial_state.dims1_def ps2_P.nths_vars1' ps2_P.dims1_def dims_vars1 N_def by auto
subgoal unfolding partial_state.d2_def partial_state.dims2_def ps2_P.nths_vars2' ps2_P.dims2_def dims_vars2 by auto using unitary_exH_k unitary_one by auto
lemma exexH_k_dim: "k < n ==> exexH_k k ∈ carrier_mat d d" unfolding exexH_k.simps using ps2_P.ptensor_mat_carrier ps2_P_d0 by auto
lemma hoare_seq_utrans: fixes P :: "complex mat" assumes"unitary U1"and"unitary U2"and"is_quantum_predicate P" and dU1: "U1 ∈ carrier_mat d d"and dU2: "U2 ∈ carrier_mat d d" shows" ⊨p {adjoint (U2 * U1) * P * (U2 * U1)} Utrans U1;; Utrans U2 {P}" proof - have hp0: "⊨p {adjoint (U2) * P * (U2)} Utrans U2 {P}" using assms hoare_partial.introsby auto have qp: "is_quantum_predicate (adjoint (U2) * P * (U2))" using qp_close_under_unitary_operator assms by auto thenhave hp1: "⊨p {adjoint U1 * (adjoint (U2) * P * (U2)) * U1} Utrans U1 {adjoint (U2) * P * (U2)}" using hoare_partial.introsby auto have dP: "P ∈ carrier_mat d d"using assms is_quantum_predicate_def by auto have eq: "adjoint U1 * (adjoint U2 * P * U2) * U1 = adjoint (U2 * U1) * P * (U2 * U1)" using dU1 dU2 dP by (mat_assoc d) with hp1 have hp2: "⊨p {adjoint (U2 * U1) * P * (U2 * U1)} Utrans U1 {adjoint (U2) * P * (U2)}"by auto
have"is_quantum_predicate (adjoint U1 * (adjoint U2 * P * U2) * U1)"using qp qp_close_under_unitary_operator assms by auto thenhave"is_quantum_predicate (adjoint (U2 * U1) * P * (U2 * U1))"using eq by auto thenshow ?thesis using hoare_partial.intros(3)[OF _ qp assms(3)] hp0 hp2 by auto qed
lemma qp_close_after_exexH_k: fixes P :: "complex mat" assumes"is_quantum_predicate P" shows"k < n ==> is_quantum_predicate (adjoint (exexH_k k) * P * exexH_k k)" apply (subst qp_close_under_unitary_operator)
subgoal using exexH_k_dim by auto
subgoal using unitary_exexH_k by auto using assms by auto
lemma hoare_hadamard_n: fixes P :: "complex mat" shows"is_quantum_predicate P ==> k < n ==> ⊨p {adjoint (exexH_k k) * P * exexH_k k} hadamard_n (Suc k) {P}" proof (induct k arbitrary: P) case0 have qp: "is_quantum_predicate (adjoint (exexH_k 0) * P * exexH_k 0)" using qp_close_under_unitary_operator[OF _ unitary_exhadamard_on_i[of 0]] tensor_P_dim 0by auto thenhave"⊨p {adjoint (exexH_k 0) * P * exexH_k 0} SKIP {adjoint (exexH_k 0) * P * exexH_k 0}" using hoare_partial.intros(1) by auto moreoverhave"⊨p {adjoint (exexH_k 0) * P * exexH_k 0} Utrans (tensor_P (hadamard_on_i 0) (1m K)) {P}" using hoare_partial.intros(2) 0by auto ultimatelyhave"⊨p {adjoint (exexH_k 0) * P * exexH_k 0} SKIP;; Utrans (tensor_P (hadamard_on_i 0) (1m K)) {P}" using hoare_partial.intros(3) qp 0by auto thenshow ?caseusing qp by auto next case (Suc k) have h1: "⊨p {adjoint (tensor_P (hadamard_on_i (Suc k)) (1m K)) * P * (tensor_P (hadamard_on_i (Suc k)) (1m K))} Utrans (tensor_P (hadamard_on_i (Suc k)) (1m K)) {P}" using hoare_partial.intros Suc by auto have qp: "is_quantum_predicate (adjoint (tensor_P (hadamard_on_i (Suc k)) (1m K)) * P * (tensor_P (hadamard_on_i (Suc k)) (1m K)))" apply (subst qp_close_under_unitary_operator)
subgoal using ps2_P.ptensor_mat_carrier ps2_P_d0 by auto
subgoal unfolding ps2_P.ptensor_mat_def apply (subst partial_state.tensor_mat_unitary )
subgoal unfolding partial_state.d1_def partial_state.dims1_def ps2_P.nths_vars1' ps2_P.dims1_def d_vars1 using hadamard_on_i_dim Suc by auto
subgoal unfolding partial_state.d2_def partial_state.dims2_def ps2_P.nths_vars2' ps2_P.dims2_def using dims_vars2 by auto using unitary_hadamard_on_i unitary_one Suc by auto using Suc by auto thenhave h2: "⊨p {adjoint (exexH_k k) * (adjoint (tensor_P (hadamard_on_i (Suc k)) (1m K)) * P * (tensor_P (hadamard_on_i (Suc k)) (1m K))) * exexH_k k} hadamard_n (Suc k) {adjoint (tensor_P (hadamard_on_i (Suc k)) (1m K)) * P * (tensor_P (hadamard_on_i (Suc k)) (1m K))}" using Suc by auto have"(tensor_P (hadamard_on_i (Suc k)) (1m K)) * exexH_k k = (tensor_P (hadamard_on_i (Suc k) * (exH_k k)) (1m K * (1m K)))" apply (subst ps2_P.ptensor_mat_mult)
subgoal using hadamard_on_i_dim ps2_P_d1 Suc by auto
subgoal using exH_k_dim ps2_P_d1 Suc by auto using ps2_P_d2 by auto alsohave"… = exexH_k (Suc k)"using mult_exH_k_left Suc by auto finallyhave eq1: "(tensor_P (hadamard_on_i (Suc k)) (1m K)) * exexH_k k = exexH_k (Suc k)". thenhave eq2: "adjoint (exexH_k k) * adjoint (tensor_P (hadamard_on_i (Suc k)) (1m K)) = adjoint (exexH_k (Suc k))" apply (subst adjoint_mult[symmetric, of _ d d _ d])
subgoal using tensor_P_dim by auto using exexH_k_dim Suc by auto have dP: "P ∈ carrier_mat d d"using is_quantum_predicate_def Suc by auto moreoverhave dH: "exexH_k k ∈ carrier_mat d d"using exexH_k_dim Suc by auto moreoverhave dHi: "tensor_P (hadamard_on_i (Suc k)) (1m K) ∈ carrier_mat d d"usingtensor_P_dim by auto ultimatelyhave eq3: "adjoint (exexH_k k) * (adjoint (tensor_P (hadamard_on_i (Suc k)) (1m K)) * P * tensor_P (hadamard_on_i (Suc k)) (1m K)) * exexH_k k = (adjoint (exexH_k k) * adjoint (tensor_P (hadamard_on_i (Suc k)) (1m K))) * P * (tensor_P (hadamard_on_i (Suc k)) (1m K) * exexH_k k)" by (mat_assoc d) show ?caseapply (subst hadamard_n.simps) apply (subst hoare_partial.intros(3)[of _ "adjoint (tensor_P (hadamard_on_i (Suc k)) (1m K)) * P * (tensor_P (hadamard_on_i (Suc k)) (1m K))"])
subgoal using qp_close_after_exexH_k[of P "Suc k"] Suc by auto
subgoal using qp by auto
subgoal using Suc by auto
subgoal using h2[simplified eq3 eq1 eq2] by auto using h1 by auto qed
lemma qp_pre: "is_quantum_predicate (tensor_P pre (proj_k 0))" unfolding is_quantum_predicate_def proof (intro conjI) show"tensor_P pre (proj_k 0) ∈ carrier_mat d d"using tensor_P_dim by auto interpret st: partial_state dims vars1 . have d1: "st.d1 = N"unfolding st.d1_def st.dims1_def using d_vars1 by auto have d2: "st.d2 = K"unfolding st.d2_def st.dims2_def nths_uminus_vars1 dims_vars2 by auto show"positive (tensor_P pre (proj_k 0))" unfolding ps2_P.ptensor_mat_def ps2_P_dims0 ps2_P_vars1' apply (subst st.tensor_mat_positive)
subgoal unfolding pre_def using outer_prod_dim ket_pre_def d1 by auto
subgoal unfolding proj_k_def using outer_prod_dim ket_k_def d2 by auto
subgoal using positive_pre by auto using positive_proj_k[of 0] K_gt_0 by auto show"tensor_P pre (proj_k 0) ≤L 1m d" unfolding ps2_P.ptensor_mat_def ps2_P_dims0 ps2_P_vars1' apply (subst st.tensor_mat_le_one)
subgoal using pre_def ket_pre_def outer_prod_dim d1 by auto
subgoal using proj_k_def K_gt_0 ket_k_def outer_prod_dim d2 by auto using d1 d2 K_gt_0 outer_prod_dim positive_pre positive_proj_k pre_le_one proj_k_le_one by auto qed
lemma qp_init_post: "is_quantum_predicate (tensor_P proj_psi (proj_k 0))" unfolding is_quantum_predicate_def proof (intro conjI) show"tensor_P proj_psi (proj_k 0) ∈ carrier_mat d d"using tensor_P_dim by auto interpret st: partial_state dims vars1 . have d1: "st.d1 = N"unfolding st.d1_def st.dims1_def using d_vars1 by auto have d2: "st.d2 = K"unfolding st.d2_def st.dims2_def nths_uminus_vars1 dims_vars2 by auto show"positive (tensor_P proj_psi (proj_k 0))" unfolding ps2_P.ptensor_mat_def ps2_P_dims0 ps2_P_vars1' apply (subst st.tensor_mat_positive)
subgoal unfolding proj_psi_def using outer_prod_dim ψ_def d1 by auto
subgoal unfolding proj_k_def using outer_prod_dim ket_k_def d2 by auto
subgoal using positive_proj_psi by auto using positive_proj_k[of 0] K_gt_0 by auto show"tensor_P proj_psi (proj_k 0) ≤L 1m d" unfolding ps2_P.ptensor_mat_def ps2_P_dims0 ps2_P_vars1' apply (subst st.tensor_mat_le_one)
subgoal using proj_psi_def outer_prod_dim d1 by auto
subgoal using proj_k_def K_gt_0 ket_k_def outer_prod_dim d2 by auto using d1 d2 K_gt_0 outer_prod_dim positive_proj_psi positive_proj_k proj_psi_le_one proj_k_le_one by auto qed
lemma tensor_P_adjoint_left_right: assumes"m1 ∈ carrier_mat N N"and"m2 ∈ carrier_mat K K"and"m3 ∈ carrier_mat N N"and"m4 ∈ carrier_mat K K" shows"adjoint (tensor_P m1 m2) * tensor_P m3 m4 * tensor_P m1 m2 = tensor_P (adjoint m1 * m3 * m1) (adjoint m2 * m4 * m2)" proof - have eq1: "adjoint (tensor_P m1 m2) = tensor_P (adjoint m1) (adjoint m2)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) using ps_P_d1 ps_P_d2 assms by auto have eq2: "adjoint (tensor_P m1 m2) * tensor_P m3 m4 = tensor_P (adjoint m1 * m3) (adjoint m2 * m4)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_mult) using ps_P_d1 ps_P_d2 assms eq1 unfolding ps2_P.ptensor_mat_def by (auto simp add: adjoint_dim) have eq3: "tensor_P (adjoint m1 * m3) (adjoint m2 * m4) * (tensor_P m1 m2) = tensor_P (adjoint m1 * m3 * m1) (adjoint m2 * m4 * m2)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_mult[of "adjoint m1 * m3"]) using ps_P_d1 ps_P_d2 assms by (auto simp add: adjoint_dim) show ?thesis using eq1 eq2 eq3 by auto qed
abbreviation exH_n where "exH_n ≡ exH_k (n - 1)"
lemma hoare_triple_init: "⊨p {tensor_P pre (proj_k 0)} hadamard_n n {tensor_P proj_psi (proj_k 0)}" proof - have h: "⊨p {adjoint (exexH_k (n - 1)) * (tensor_P proj_psi (proj_k 0)) * (exexH_k (n - 1))} hadamard_n n {tensor_P proj_psi (proj_k 0)}" using hoare_hadamard_n[OF qp_init_post, of "n - 1"] qp_init_post n by auto have"adjoint (exexH_k (n - 1)) * tensor_P proj_psi (proj_k 0) * exexH_k (n - 1) = tensor_P (adjoint exH_n * proj_psi * exH_n) (adjoint (1m K) * proj_k 0 * 1m K)" unfolding exexH_k.simps apply (subst tensor_P_adjoint_left_right) using exH_k_dim proj_psi_def ψ_def proj_k_def ket_k_def n by (auto) moreoverhave"adjoint exH_n * proj_psi * exH_n = pre" unfolding proj_psi_def pre_def apply (subst outer_prod_left_right_mat[of _ N _ N _ N _ N])
subgoal using ψ_defby auto
subgoal using exH_k_dim n by (simp add: adjoint_dim)
subgoal using exH_k_dim n by simp apply (subst (12) hermitian_exH_n[simplified hermitian_def]) apply (subst (12) exH_k_mult_psi_is_pre) by auto moreoverhave"adjoint (1m K) * (proj_k 0) * (1m K) = proj_k 0" apply (subst adjoint_one) using proj_k_dim[of 0] K_gt_0 by auto ultimatelyhave"adjoint (exexH_k (n - 1)) * tensor_P proj_psi (proj_k 0) * exexH_k (n - 1) = tensor_P pre (proj_k 0)" by auto with h show ?thesis by auto qed
text‹Hoare triples of while loop›
definition proj_psi_l where "proj_psi_l l = proj (psi_l l)"
lemma positive_psi_l: "k < K ==> positive (proj_psi_l k)" unfolding proj_psi_l_def apply (subst positive_same_outer_prod) using psi_l_dim by auto
lemma hermitian_proj_psi_l: "k < K ==> hermitian (proj_psi_l k)" using positive_psi_l positive_is_hermitian by auto
definition P' where "P' = tensor_P (proj_psi_l R) (proj_k R)"
lemma proj_psi_l_dim: "proj_psi_l l ∈ carrier_mat N N" unfolding proj_psi_l_def using psi_l_def by auto
lemma psi_l_le_id: shows"proj_psi_l l ≤L 1m N" proof - have"inner_prod (psi_l l) (psi_l l) = 1" using inner_psi_l by auto thenshow ?thesis using outer_prod_le_one psi_l_def proj_psi_l_def by auto qed
lemma positive_proj_psi_l: shows"positive (proj_psi_l l)" using positive_same_outer_prod proj_psi_l_def psi_l_dim by auto
definition proj_fst_k :: "nat ==> complex mat"where "proj_fst_k k = mat K K (λ(i, j). if (i = j ∧ i < k) then 1 else 0)"
lemma proj_fst_k_is_projection: "proj_fst_k k * proj_fst_k k = proj_fst_k k" by (auto simp add: proj_fst_k_def scalar_prod_def sum_only_one_neq_0)
lemma positive_proj_fst_k: "positive (proj_fst_k k)" proof - have"(proj_fst_k k) * adjoint (proj_fst_k k) = (proj_fst_k k)" using hermitian_proj_fst_k proj_fst_k_is_projection by auto thenhave"∃M. M * adjoint M = (proj_fst_k k)"by auto thenshow ?thesis apply (subst positive_if_decomp) using proj_fst_k_def by auto qed
lemma proj_fst_k_le_one: "proj_fst_k k ≤L 1m K" proof -
define M where"M l = mat K K (λ(i, j). if (i = j ∧ i ≥ l) then (1::complex) else 0)"for l have eq: "1m K - proj_fst_k k = M k"unfolding M_def proj_fst_k_def apply (rule eq_matI) by auto have"M k * M k = M k"unfolding M_def apply (rule eq_matI) apply (simp add: scalar_prod_def) apply (subst sum_only_one_neq_0[of _ j]) by auto moreoverhave"adjoint (M k) = M k"unfolding M_def apply (rule eq_matI) by (auto simp add: adjoint_eval) ultimatelyhave"M k * adjoint (M k) = M k"by auto thenhave"∃M. M * adjoint M = 1m K - proj_fst_k k"using eq by auto thenhave"positive (1m K - proj_fst_k k)" apply (subst positive_if_decomp) using proj_fst_k_def by auto thenshow ?thesis unfolding lowner_le_def using proj_fst_k_def by auto qed
lemma sum_proj_k: assumes"m ≤ K" shows"matrix_sum K (λk. proj_k k) m = proj_fst_k m" proof - have"m ≤ K ==> matrix_sum K (λk. proj_k k) m = mat K K (λ(i, j). if (i = j ∧ i < m) then 1 else 0)"for m proof (induct m) case0 thenshow ?caseapply simp apply (rule eq_matI) by auto next case (Suc m) thenhave m: "m < K"by auto thenhave m': "m ≤ K"by auto have"matrix_sum K proj_k (Suc m) = proj_k m + matrix_sum K proj_k m"by simp alsohave"… = mat K K (λ(i, j). if (i = j ∧ i < (Suc m)) then 1 else 0)" unfolding proj_k_mat[OF m] Suc(1)[OF m'] apply (rule eq_matI) by auto finallyshow ?caseby auto qed thenshow ?thesis unfolding proj_fst_k_def using assms by auto qed
lemma proj_psi_proj_k_le_exproj_k: shows"tensor_P (proj_psi_l k) (proj_k l) ≤L tensor_P (1m N) (proj_k l)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive_le)
subgoal using proj_psi_l_def psi_l_dim ps_P_d1 by auto
subgoal using proj_k_def ket_k_def ps_P_d2 by auto
subgoal using positive_proj_psi_l by auto
subgoal using positive_same_outer_prod proj_k_def ket_k_def by auto
subgoal using psi_l_le_id by auto apply (subst lowner_le_refl[of _ K]) by (auto simp add: proj_k_def ket_k_def)
lemma tensor_P_left_right_partial1: assumes"m1 ∈ carrier_mat N N"and"m2 ∈ carrier_mat N N"and"m3 ∈ carrier_mat K K"and"m4 ∈ carrier_mat N N" shows"tensor_P m1 (1m K) * tensor_P m2 m3 * tensor_P m4 (1m K) = tensor_P (m1 * m2 * m4) m3" proof - have"tensor_P m1 (1m K) * tensor_P m2 m3 = tensor_P (m1 * m2) m3" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_mult[symmetric]) using assms ps_P_d1 ps_P_d2 by auto moreoverhave"tensor_P (m1 * m2) m3 * tensor_P m4 (1m K) = tensor_P (m1 * m2 * m4) m3" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_mult[symmetric]) using assms ps_P_d1 ps_P_d2 by auto ultimatelyshow ?thesis by auto qed
lemma tensor_P_left_right_partial2: assumes"m1 ∈ carrier_mat K K"and"m2 ∈ carrier_mat K K"and"m3 ∈ carrier_mat N N"and"m4 ∈ carrier_mat K K" shows"tensor_P (1m N) m1 * tensor_P m3 m2 * tensor_P (1m N) m4 = tensor_P m3 (m1 * m2 * m4)" proof - have"tensor_P (1m N) m1 * tensor_P m3 m2 = tensor_P m3 (m1 * m2)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_mult[symmetric]) using assms ps_P_d1 ps_P_d2 by auto moreoverhave"tensor_P m3 (m1 * m2) * tensor_P (1m N) m4 = tensor_P m3 (m1 * m2 * m4)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_mult[symmetric]) using assms ps_P_d1 ps_P_d2 by auto ultimatelyshow ?thesis by auto qed
lemma matrix_sum_mult_left_right: fixes A B :: "complex mat" assumes dg: "(∧k. k < l ==> g k ∈ carrier_mat m m) " and dA: "A ∈ carrier_mat m m"and dB: "B ∈ carrier_mat m m" shows"matrix_sum m (λk. A * g k * B) l = A * matrix_sum m g l * B" proof - have eq: "A * matrix_sum m g l = matrix_sum m (λk. A * g k) l" using matrix_sum_distrib_left assms by auto have"A * matrix_sum m g l * B = matrix_sum m (λk. A * g k * B) l" apply (subst eq) using matrix_sum_mult_right[of l "λk. A * g k"] assms by auto thenshow ?thesis by auto qed
lemma mat_O_split: "mat_O = 1m N - 2 ⋅m proj_O" apply (rule eq_matI) unfolding mat_O_def proj_O_def by auto
lemma mat_O_mult_psi'_l: "mat_O *v (psi'_l l) = psi_l l" proof - have"mat_O *v (psi'_l l) = mat_O *v ((alpha_l l) ⋅v α) - mat_O *v ((beta_l l) ⋅v β)" unfolding psi'_l_def apply (subst mult_minus_distrib_mat_vec) using mat_O_dim α_dim β_dim by auto alsohave"… = (alpha_l l) ⋅v (mat_O *v α) - (beta_l l) ⋅v (mat_O *v β)" using mult_mat_vec_smult_vec_assoc[of mat_O N N] mat_O_dim α_dim β_dim by auto alsohave"… = (alpha_l l) ⋅v α - (beta_l l) ⋅v (- β)" using mat_O_mult_alpha mat_O_mult_beta by auto alsohave"… = (alpha_l l) ⋅v α + (beta_l l) ⋅v β" by auto finallyshow ?thesis unfolding psi_l_def by auto qed
lemma mat_O_times_Q1: "adjoint (tensor_P mat_O (1m K)) * Q1 * (tensor_P mat_O (1m K)) = Q" proof - let ?m1 = "tensor_P mat_O (1m K)" have eq:"adjoint ?m1 = ?m1" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) apply (auto simp add: mat_O_dim ps_P_d1 ps_P_d2) by (simp add: hermitian_mat_O[unfolded hermitian_def] hermitian_one[unfolded hermitian_def])
{ fix l let ?m2 = "tensor_P (proj_psi'_l l) (proj_k l)" have"?m1 * ?m2 * ?m1 = tensor_P (mat_O * (proj_psi'_l l) * mat_O) (proj_k l)" apply (subst tensor_P_left_right_partial1) using mat_O_dim proj_psi'_dim proj_k_dim by auto moreoverhave"mat_O * (proj_psi'_l l) * mat_O = outer_prod (psi_l l) (psi_l l)" unfolding proj_psi'_l_def apply (subst outer_prod_left_right_mat[of _ N _ N _ N _ N]) using psi'_l_dim mat_O_dim mat_O_mult_psi'_l hermitian_mat_O[unfolded hermitian_def] by auto ultimatelyhave"?m1 * ?m2 * ?m1 = tensor_P (proj_psi_l l) (proj_k l)"unfolding proj_psi_l_def by auto
} note p1 = this have"adjoint (tensor_P mat_O (1m K)) * Q1 * (tensor_P mat_O (1m K)) = ?m1 * Q1 * ?m1" using eq by auto alsohave"… = matrix_sum d (λl. ?m1 * (tensor_P (proj_psi'_l l) (proj_k l)) * ?m1) R" unfolding Q1_def apply (subst matrix_sum_mult_left_right) using tensor_P_dim by auto alsohave"… = Q" unfolding Q_def using p1 by auto finallyshow ?thesis by auto qed
definition Q2 where "Q2 = matrix_sum d (λl. tensor_P (proj_psi_l (l + 1)) (proj_k l)) R"
lemma Q2_dim: "Q2 ∈ carrier_mat d d" unfolding Q2_def apply (subst matrix_sum_dim) using tensor_P_dim by auto
lemma Q2_le_one: "Q2 ≤L 1m d" proof - have leq: "Q2 ≤L matrix_sum d (λk. tensor_P (1m N) (proj_k k)) R" unfolding Q2_def apply (subst lowner_le_matrix_sum)
subgoal using tensor_P_dim by auto
subgoal using tensor_P_dim by auto using proj_psi_proj_k_le_exproj_k by auto have"matrix_sum d (λk. tensor_P (1m N) (proj_k k)) R = tensor_P (1m N) (matrix_sum K proj_k R)" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_matrix_sum2[simplified ps_P_d ps_P_d2])
subgoal using ps_P_d1 by auto using proj_k_dim by auto alsohave"… = tensor_P (1m N) (proj_fst_k R)"using sum_proj_k K by auto alsohave"…≤L tensor_P (1m N) (1m K)"unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive_le)
subgoal using ps_P_d1 by auto
subgoal using ps_P_d2 proj_fst_k_def by auto
subgoal using positive_one by auto
subgoal using positive_proj_fst_k by auto
subgoal using lowner_le_refl[of "1m N" N] by auto using proj_fst_k_le_one by auto alsohave"… = 1m d"unfolding ps2_P.ptensor_mat_def using ps_P.tensor_mat_id ps_P_d1 ps_P_d2 ps_P_d by auto finallyhave leq2: "matrix_sum d (λk. tensor_P (1m N) (proj_k k)) R ≤L 1m d"by auto have ds: "matrix_sum d (λk. tensor_P (1m N) (proj_k k)) R ∈ carrier_mat d d" apply (subst matrix_sum_dim) using tensor_P_dim by auto thenshow ?thesis using leq leq2 lowner_le_trans[OF Q2_dim ds, of "1m d"] by auto qed
lemma qp_Q2: "is_quantum_predicate Q2" unfolding is_quantum_predicate_def proof (intro conjI) show"Q2 ∈ carrier_mat d d"unfolding Q2_def apply (subst matrix_sum_dim) using tensor_P_dim by auto next show"positive Q2"unfolding Q2_def apply (subst matrix_sum_positive)
subgoal using tensor_P_dim by auto
subgoal for k unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive)
subgoal using proj_psi_l_def psi_l_dim ps_P_d1 by auto
subgoal using proj_k_dim ps_P_d2 K by auto
subgoal using positive_proj_psi_l by auto using positive_proj_k K by auto by auto next show"Q2 ≤L 1m d"using Q2_le_one by auto qed
lemma pre_mat: "pre = mat N N (λ(i, j). if i = j ∧ i = 0 then 1 else 0)" apply (rule eq_matI)
subgoal for i j unfolding pre_def apply (subst index_outer_prod[OF ket_pre_dim ket_pre_dim]) apply simp_all unfolding ket_pre_def by auto using outer_prod_dim[OF ket_pre_dim ket_pre_dim, folded pre_def] by auto
lemma mat_Ph_split: "mat_Ph = 2 ⋅m pre - 1m N" unfolding mat_Ph_def pre_mat apply (rule eq_matI) by auto
lemma H_Ph_H: "exexH_k (n-1) * tensor_P mat_Ph (1m K) * exexH_k (n - 1) = 2 ⋅m tensor_P proj_psi (1m K) - 1m d" unfolding mat_Ph_split exexH_k.simps apply (subst tensor_P_left_right_partial1)
subgoal using exH_k_dim[of "n - 1"] n by auto
subgoal using pre_dim by auto
subgoal by auto proof - have eq1: "exH_n * exH_n = 1m N" using unitary_exH_k[of "n - 1"] unfolding unitary_def inverts_mat_def using n hermitian_exH_n[simplified hermitian_def] exH_n_dim by auto have eq2: "exH_n * pre * exH_n = proj_psi" unfolding pre_def proj_psi_def apply (subst outer_prod_left_right_mat[of _ N _ N _ N _ N])
subgoal using ket_pre_dim by auto
subgoal using exH_n_dim by auto apply (subst hermitian_exH_n[simplified hermitian_def]) using exH_k_mult_pre_is_psi by auto have eq3: "exH_n * (2 ⋅m pre) * exH_n = 2 ⋅m (exH_n * pre * exH_n)" using pre_dim exH_n_dim by (mat_assoc N) have"exH_n * (2 ⋅m pre - 1m N) * exH_n = exH_n * (2 ⋅m pre) * exH_n - exH_n * exH_n" using pre_dim exH_n_dim apply (mat_assoc N) by auto alsohave"… = 2 ⋅m (exH_n * pre * exH_n) - 1m N" using eq1 eq3 by auto finallyhave eq4: "exH_n * (2 ⋅m pre - 1m N) * exH_n = 2 ⋅m proj_psi - 1m N"using eq2 by auto show"tensor_P (exH_n * (2 ⋅m pre - 1m N) * exH_n) (1m K) = 2 ⋅m tensor_P proj_psi (1m K) - 1m d" unfolding eq4 unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_minus1) unfolding ps_P_d1 ps_P_d2 apply (auto simp add: proj_psi_dim) apply (subst ps_P.tensor_mat_scale1) unfolding ps_P_d1 ps_P_d2 apply (auto simp add: proj_psi_dim) apply (subst ps_P.tensor_mat_id[simplified ps_P_d1 ps_P_d2 ps_P_d]) by auto qed
lemma hermitian_proj_psi_minus_1: "hermitian (2 ⋅m proj_psi - 1m N)" unfolding hermitian_def apply (subst adjoint_minus[of _ N N]) apply (auto simp add: proj_psi_dim) apply (subst adjoint_scale) using hermitian_proj_psi[simplified hermitian_def] hermitian_def adjoint_one by auto
lemma unitary_proj_psi_minus_1: "unitary (2 ⋅m proj_psi - 1m N)" proof - have a: "adjoint (2 ⋅m proj_psi) = 2 ⋅m proj_psi" apply (subst adjoint_scale) using hermitian_proj_psi[simplified hermitian_def] by simp have eq: "adjoint (2 ⋅m proj_psi - 1m N) = 2 ⋅m proj_psi - 1m N" apply (subst adjoint_minus) using proj_psi_dim a adjoint_one by auto have"(2 ⋅m proj_psi) * (2 ⋅m proj_psi) = 4 ⋅m (proj_psi * proj_psi)" using proj_psi_dim by auto alsohave"… = 4 ⋅m proj_psi"using proj_psi_is_projection by auto finallyhave sq: "(2 ⋅m proj_psi) * (2 ⋅m proj_psi) = 4 ⋅m proj_psi". have l: "(2 ⋅m proj_psi) * (2 ⋅m proj_psi - 1m N) = 4 ⋅m proj_psi - (2 ⋅m proj_psi)" apply (subst mult_minus_distrib_mat) using proj_psi_dim sq by auto
have"(2 ⋅m proj_psi - 1m N) * adjoint (2 ⋅m proj_psi - 1m N) = (2 ⋅m proj_psi - 1m N) * (2 ⋅m proj_psi - 1m N)"using eq by auto alsohave"… = (2 ⋅m proj_psi) * (2 ⋅m proj_psi - 1m N) - 2 ⋅m proj_psi + 1m N" apply (subst minus_mult_distrib_mat[of _ N N]) using proj_psi_dim by auto alsohave"… = 4 ⋅m proj_psi - (2 ⋅m proj_psi) - 2 ⋅m proj_psi + 1m N" using l by auto alsohave"… = 1m N"using proj_psi_dim by auto finallyhave"(2 ⋅m proj_psi - 1m N) * adjoint (2 ⋅m proj_psi - 1m N) = 1m N". thenshow ?thesis unfolding unitary_def inverts_mat_def using proj_psi_dim by auto qed
lemma proj_psi_minus_1_mult_psi'_l: "(2 ⋅m proj_psi - 1m N) *v psi'_l l = psi_l (l + 1)" proof - have eq1: "(2 ⋅m proj_psi - 1m N) *v psi'_l l = 2 ⋅m proj_psi *v psi'_l l - psi'_l l" apply (subst minus_mult_distrib_mat_vec) using psi'_l_dim proj_psi'_dim proj_psi_dim by auto have eq2: "2 ⋅m proj_psi *v (psi'_l l) = 2 ⋅v (proj_psi *v (psi'_l l))" apply (subst smult_mat_mult_mat_vec_assoc) using proj_psi_dim psi'_l_dim by auto have"proj_psi *v (psi'_l l) = inner_prod ψ (psi'_l l) ⋅v ψ" unfolding proj_psi_def apply (subst outer_prod_mult_vec[of _ N _ N]) using ψ_dim psi'_l_dim by auto alsohave"… = ((alpha_l l) * ccos (θ / 2) - (beta_l l) * csin (θ / 2)) ⋅v ψ" using psi_inner_psi'_l by auto finallyhave"proj_psi *v (psi'_l l) = ((alpha_l l) * ccos (θ / 2) - (beta_l l) * csin (θ / 2)) ⋅v ψ"by auto thenhave eq3: "2 ⋅v (proj_psi *v (psi'_l l)) = 2 * ((alpha_l l) * ccos (θ / 2) - (beta_l l) * csin (θ / 2)) ⋅v ψ"by auto thenshow"(2 ⋅m proj_psi - (1m N)) *v (psi'_l l) = psi_l (l + 1)" using eq1 eq2 eq3 psi_l_Suc_l_derive by simp qed
lemma proj_psi_minus_1_mult_psi_Suc_l: "(2 ⋅m proj_psi - 1m N) *v psi_l (l + 1) = psi'_l l" proof - have id: "(2 ⋅m proj_psi - 1m N) * (2 ⋅m proj_psi - 1m N) = 1m N" using unitary_proj_psi_minus_1 unfolding unitary_def hermitian_proj_psi_minus_1[simplified hermitian_def] unfolding inverts_mat_def by auto have"(2 ⋅m proj_psi - 1m N) *v psi_l (l + 1) = (2 ⋅m proj_psi - 1m N) *v ((2 ⋅mproj_psi - 1m N) *v psi'_l l)" using proj_psi_minus_1_mult_psi'_l by auto alsohave"… = ((2 ⋅m proj_psi - 1m N) * (2 ⋅m proj_psi - 1m N) *v psi'_l l)" apply (subst assoc_mult_mat_vec) using proj_psi_dim psi'_l_dim by auto alsohave"… = psi'_l l"using psi'_l_dim id by auto finallyshow ?thesis by auto qed
lemma unitary_exproj_psi_minus_1: "unitary (2 ⋅m tensor_P proj_psi (1m K) - 1m d)" unfolding exproj_psi_minus_1_tensor unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_unitary) using ps_P_d1 ps_P_d2 unitary_proj_psi_minus_1 unitary_one by auto
lemma proj_psi_minus_1_Q2: "adjoint (2 ⋅m tensor_P proj_psi (1m K) - 1m d) * Q2 * (2 ⋅m tensor_P proj_psi (1m K) - 1m d) = Q1" proof - have eq1: "adjoint (2 ⋅m tensor_P proj_psi (1m K) - 1m d) = 2 ⋅m tensor_P proj_psi (1m K) - 1m d" apply (subst adjoint_minus[of _ d d])
subgoal using tensor_P_dim[of proj_psi] by auto
subgoal by auto apply (subst adjoint_one) apply (subst adjoint_scale) using hermitian_exproj_psi[simplified hermitian_def] by auto let ?m1 = "tensor_P (2 ⋅m proj_psi - (1m N)) (1m K)"
{ fix l let ?m2 = "tensor_P (proj_psi_l (l + 1)) (proj_k l)" have121: "?m1 * ?m2 * ?m1 = tensor_P ((2 ⋅m proj_psi - (1m N)) * (proj_psi_l (l + 1)) * (2 ⋅m proj_psi - (1m N))) (proj_k l)" apply (subst tensor_P_left_right_partial1) using proj_psi_dim proj_psi_l_dim proj_k_dim by auto have"(2 ⋅m proj_psi - (1m N)) * (proj_psi_l (l + 1)) * (2 ⋅m proj_psi - (1m N)) = outer_prod ((2 ⋅m proj_psi - (1m N)) *v (psi_l (l + 1))) ((2 ⋅m proj_psi - (1m N)) *v (psi_l (l + 1)))" unfolding proj_psi_l_def apply (subst outer_prod_left_right_mat[of _ N _ N _ N _ N]) using proj_psi_dim psi_l_dim hermitian_proj_psi_minus_1[simplified hermitian_def] by auto alsohave"… = outer_prod (psi'_l l) (psi'_l l)" using proj_psi_minus_1_mult_psi_Suc_l by auto finallyhave"(2 ⋅m proj_psi - (1m N)) * (proj_psi_l (l + 1)) * (2 ⋅m proj_psi - (1m N)) = outer_prod (psi'_l l) (psi'_l l)". thenhave"?m1 * ?m2 * ?m1 = tensor_P (proj_psi'_l l) (proj_k l)" using121 proj_psi'_l_def by auto
} note p1 = this have"adjoint (2 ⋅m tensor_P proj_psi (1m K) - 1m d) * Q2 * (2 ⋅m tensor_P proj_psi (1m K) - 1m d) = (2 ⋅m tensor_P proj_psi (1m K) - 1m d) * Q2 * (2 ⋅m tensor_P proj_psi (1m K) - 1m d)" using eq1 by auto alsohave"… = matrix_sum d (λl. (2 ⋅m tensor_P proj_psi (1m K) - 1m d) * tensor_P (proj_psi_l (l + 1)) (proj_k l) * (2 ⋅m tensor_P proj_psi (1m K) - 1m d)) R"unfolding Q2_def apply (subst matrix_sum_mult_left_right) using tensor_P_dim by auto alsohave"… = matrix_sum d (λl. tensor_P (proj_psi'_l l) (proj_k l)) R" using p1 exproj_psi_minus_1_tensor by auto alsohave"… = Q1"unfolding Q1_def by auto finallyshow ?thesis using eq1 by auto qed
lemma qp_Q1: "is_quantum_predicate Q1" unfolding proj_psi_minus_1_Q2[symmetric] apply (subst qp_close_under_unitary_operator) using tensor_P_dim unitary_exproj_psi_minus_1 qp_Q2 by auto
lemma qp_Q: "is_quantum_predicate Q" proof - have u: "unitary (tensor_P mat_O (1m K))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_unitary)
subgoal unfolding ps_P_d1 mat_O_def by auto
subgoal unfolding ps_P_d2 by auto
subgoal using unitary_mat_O by auto using unitary_one by auto thenshow ?thesis using tensor_P_dim qp_Q1 using qp_close_under_unitary_operator[OF tensor_P_dim u qp_Q1] by (simp add: mat_O_times_Q1 ) qed
lemma hoare_triple_D1: "⊨p {Q} Utrans_P vars1 mat_O {Q1}" unfolding Utrans_P_is_tensor_P1
mat_O_times_Q1[symmetric] apply (subst hoare_partial.intros(2)) using qp_Q1 by auto
lemma hoare_triple_D2: "⊨p {Q1} hadamard_n n ;; Utrans_P vars1 mat_Ph ;; hadamard_n n {Q2}" proof - let ?H = "exexH_k (n - 1)" let ?Ph = "tensor_P mat_Ph (1m K)" let ?O = "tensor_P mat_O (1m K)" have h1: "⊨p {adjoint ?H * Q2 * ?H} hadamard_n n {Q2}" using hoare_hadamard_n[OF qp_Q2, of "n - 1"] n by auto have qp1: "is_quantum_predicate ((adjoint ?H) * Q2 * ?H)" using qp_close_under_unitary_operator unitary_exexH_k n exexH_k_dim qp_Q2 by auto thenhave h2: "⊨p {adjoint ?Ph * (adjoint ?H * Q2 * ?H) * ?Ph} Utrans_P vars1 mat_Ph {adjoint ?H * Q2 * ?H}" using qp1 Utrans_P_is_tensor_P1 hoare_partial.introsby auto have qp2: "is_quantum_predicate (adjoint ?Ph * (adjoint ?H * Q2 * ?H) * ?Ph)" using qp_close_under_unitary_operator[of "tensor_P mat_Ph (1m K)"] ps2_P.ptensor_mat_carrier ps2_P_d0 unitary_ex_mat_Ph qp1 by auto thenhave h3: "⊨p {adjoint ?H * (adjoint ?Ph * (adjoint ?H * Q2 * ?H) * ?Ph) * ?H} hadamard_n n {adjoint ?Ph * (adjoint ?H * Q2 * ?H) * ?Ph}" using hoare_hadamard_n[OF qp2, of "n - 1"] n by auto have qp3: "is_quantum_predicate (adjoint ?H * (adjoint ?Ph * (adjoint ?H * Q2 * ?H) * ?Ph) * ?H)" using qp_close_under_unitary_operator[of "?H"] exexH_k_dim unitary_exexH_k qp2 n by auto have h4: "⊨p {adjoint ?H * (adjoint ?Ph * (adjoint ?H * Q2 * ?H) * ?Ph) * ?H} hadamard_n n ;; Utrans_P vars1 mat_Ph {adjoint ?H * Q2 * ?H}" using h2 h3 qp1 qp2 qp3 hoare_partial.introsby auto thenhave h5: "⊨p {adjoint ?H * (adjoint ?Ph * (adjoint ?H * Q2 * ?H) * ?Ph) * ?H} hadamard_n n ;; Utrans_P vars1 mat_Ph ;; hadamard_n n {Q2}" using h1 qp_Q2 qp3 qp1 hoare_partial.intros(3)[OF qp3 qp1 qp_Q2 h4 h1] by auto
have"adjoint ?H * (adjoint ?Ph * (adjoint ?H * Q2 * ?H) * ?Ph) * ?H = adjoint (?H * ?Ph * ?H) * Q2 * (?H * ?Ph * ?H)" apply (mat_assoc d) using exexH_k_dim n tensor_P_dim Q2_dim by auto alsohave"… = Q1"using H_Ph_H proj_psi_minus_1_Q2 by auto finallyshow ?thesis using h5 by auto qed
lemma exP0_P': "adjoint exM0 * P' * exM0 = P'" proof - have eq: "adjoint exM0 = exM0" unfolding exM0_def ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) unfolding ps_P_d1 ps_P_d2 using M0_dim adjoint_one hermitian_M0[unfolded hermitian_def] by auto have eq2: "M0 * (proj_k R) * M0 = (proj_k R)" unfolding proj_k_def apply (subst outer_prod_left_right_mat[of _ K _ K _ K _ K]) unfolding hermitian_M0[unfolded hermitian_def] M0_mult_ket_k_R using ket_k_dim M0_dim by auto show ?thesis unfolding eq unfolding exM0_def P'_def apply (subst tensor_P_left_right_partial2) using M0_dim proj_k_dim eq2 proj_psi_l_dim by auto qed
definition exM1 where "exM1 = tensor_P (1m N) M1"
lemma M1_mult_ket_k: assumes"k < R" shows"M1 *v ket_k k = ket_k k" apply (rule eq_vecI) unfolding M1_def ket_k_def by (auto simp add: scalar_prod_def assms R sum_only_one_neq_0)
lemma exP1_Q: "adjoint exM1 * Q * exM1 = Q" proof - have eq: "adjoint exM1 = exM1" unfolding exM1_def ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) unfolding ps_P_d1 ps_P_d2 using M1_dim adjoint_one hermitian_M1[unfolded hermitian_def] by auto
{ fix k assume k: "k < R" let ?m = "tensor_P (proj_psi_l k) (proj_k k)" have"exM1 * ?m * exM1 = tensor_P (proj_psi_l k) (M1 * (proj_k k) * M1)" unfolding exM1_def apply (subst tensor_P_left_right_partial2) using M1_dim proj_k_dim proj_psi_l_dim by auto alsohave"… = tensor_P (proj_psi_l k) (outer_prod (M1 *v ket_k k) (M1 *v ket_k k))" unfolding proj_k_def apply (subst outer_prod_left_right_mat[of _ K _ K _ K _ K]) unfolding hermitian_M1[unfolded hermitian_def] using ket_k_dim M1_dim by auto finallyhave"exM1 * ?m * exM1 = ?m"unfolding proj_k_def using k M1_mult_ket_k by auto
} note p1 = this have"adjoint exM1 * Q * exM1 = exM1 * Q * exM1"using eq by auto alsohave"… = matrix_sum d (λk. exM1 * (tensor_P (proj_psi_l k) (proj_k k)) * exM1) R" unfolding Q_def apply (subst matrix_sum_mult_left_right) using tensor_P_dim exM1_def by auto alsohave"… = matrix_sum d (λk. tensor_P (proj_psi_l k) (proj_k k)) R" apply (subst matrix_sum_cong) using p1 by auto finallyshow ?thesis using Q_def by auto qed
lemma qp_P': "is_quantum_predicate P'" unfolding is_quantum_predicate_def proof (intro conjI) show"P' ∈ carrier_mat d d"unfolding P'_defusing tensor_P_dim by auto show"positive P'"unfolding P'_def ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive) apply (auto simp add: ps_P_d1 ps_P_d2 proj_O_dim proj_k_dim) using proj_psi_l_dim positive_proj_psi_l positive_proj_k K by auto show"P' ≤L 1m d"unfolding P'_def ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_le_one[simplified ps_P_d]) by (auto simp add: ps_P_d1 ps_P_d2 proj_psi_l_dim K proj_k_dim positive_proj_psi_l positive_proj_k proj_k_le_one psi_l_le_id) qed
lemma P'_add_Q: "P' + Q = matrix_sum d (λl. tensor_P (proj_psi_l l) (proj_k l)) (R + 1)" apply simp unfolding P'_def Q_def by auto
lemma positive_Qk: "positive (tensor_P (proj_psi_l l) (proj_k l))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive) unfolding ps_P_d1 ps_P_d2 using proj_psi_l_dim proj_k_dim positive_proj_psi_l positive_proj_k by auto
lemma P'_Q_dim: "P' + Q ∈ carrier_mat d d" unfolding P'_add_Q apply (subst matrix_sum_dim) using tensor_P_dim by auto
lemma P'_add_Q_le_one: "P' + Q ≤L 1m d" proof - have leq: "matrix_sum d (λl. tensor_P (proj_psi_l l) (proj_k l)) (R + 1) ≤L matrix_sum d (λk. tensor_P (1m N) (proj_k k)) (R + 1)" unfolding Q2_def apply (subst lowner_le_matrix_sum)
subgoal using tensor_P_dim by auto
subgoal using tensor_P_dim by auto using proj_psi_proj_k_le_exproj_k by auto have"matrix_sum d (λk. tensor_P (1m N) (proj_k k)) (R + 1) = tensor_P (1m N) (matrix_sum K proj_k (R + 1))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_matrix_sum2[simplified ps_P_d ps_P_d2])
subgoal using ps_P_d1 by auto using proj_k_dim by auto alsohave"… = tensor_P (1m N) (proj_fst_k (R + 1))"using sum_proj_k[of "R + 1"] K by auto alsohave"…≤L tensor_P (1m N) (1m K)"unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive_le)
subgoal using ps_P_d1 by auto
subgoal using ps_P_d2 proj_fst_k_def by auto
subgoal using positive_one by auto
subgoal using positive_proj_fst_k by auto
subgoal using lowner_le_refl[of "1m N" N] by auto using proj_fst_k_le_one by auto alsohave"… = 1m d"unfolding ps2_P.ptensor_mat_def using ps_P.tensor_mat_id ps_P_d1 ps_P_d2 ps_P_d by auto finallyhave leq2: "matrix_sum d (λk. tensor_P (1m N) (proj_k k)) (R + 1) ≤L 1m d"byauto have ds: "matrix_sum d (λk. tensor_P (1m N) (proj_k k)) (R + 1) ∈ carrier_mat d d" apply (subst matrix_sum_dim) using tensor_P_dim by auto thenshow ?thesis using leq leq2 lowner_le_trans[OF P'_Q_dim ds, of "1m d"] unfolding P'_add_Q by auto qed
lemma qp_P'_Q: "is_quantum_predicate (P' + Q)" unfolding is_quantum_predicate_def proof (intro conjI) show"P' + Q ∈ carrier_mat d d" unfolding P'_add_Q apply (subst matrix_sum_dim) using tensor_P_dim by auto show"positive (P' + Q)"unfolding P'_add_Q apply (subst matrix_sum_positive) using tensor_P_dim positive_Qk by auto show" P' + Q ≤L 1m d"using P'_add_Q_le_one by auto qed
lemma Q2_leq_lemma: "tensor_P (1m N) (mat_incr K) * Q2 * adjoint (tensor_P (1m N) (mat_incr K)) ≤L P' + Q" proof - have ad: "adjoint (tensor_P (1m N) (mat_incr K)) = tensor_P (1m N) (adjoint (mat_incr K))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) using ps_P_d1 ps_P_d2 mat_incr_dim adjoint_one by auto let ?m1 = "tensor_P (1m N) (mat_incr K)" let ?m3 = "tensor_P (1m N) (adjoint (mat_incr K))"
{ fix l assume"l < R" thenhave"l < K - 1"using K by auto thenhave m: "(mat_incr K) *v (ket_k l) = (ket_k (l + 1))" using mat_incr_mult_ket_k by auto let ?m2 = "tensor_P (proj_psi_l (l + 1)) (proj_k l)" have eq: "?m1 * ?m2 * ?m3 = tensor_P (proj_psi_l (l + 1)) ((mat_incr K) * (proj_k l) * adjoint (mat_incr K))" apply (subst tensor_P_left_right_partial2) using proj_k_dim proj_psi_l_dim mat_incr_dim adjoint_dim[OF mat_incr_dim] by auto have"(mat_incr K) * (proj_k l) * adjoint (mat_incr K) = outer_prod ((mat_incr K) *v (ket_k l)) ((mat_incr K) *v (ket_k l))" unfolding proj_k_def apply (subst outer_prod_left_right_mat[of _ K _ K _ K _ K]) using ket_k_dim mat_incr_dim adjoint_dim[OF mat_incr_dim] adjoint_adjoint[of "mat_incr K"] by auto alsohave"… = proj_k (l + 1)"unfolding proj_k_def using m by auto finallyhave"?m1 * ?m2 * ?m3 = tensor_P (proj_psi_l (l + 1)) (proj_k (l + 1))"using eq by auto
} note p1 = this have"?m1 * Q2 * ?m3 = matrix_sum d (λl. ?m1 * (tensor_P (proj_psi_l (l + 1)) (proj_k l)) * ?m3) R" unfolding Q2_def apply(subst matrix_sum_mult_left_right) using tensor_P_dim by auto alsohave"… = matrix_sum d (λl. tensor_P (proj_psi_l (l + 1)) (proj_k (l + 1))) R" apply (subst matrix_sum_cong) using p1 by auto finallyhave eq1: "?m1 * Q2 * ?m3 = matrix_sum d (λl. tensor_P (proj_psi_l (l + 1)) (proj_k (l + 1))) R" (is"_=?r") . have eq2: "P' + Q = tensor_P (proj_psi_l 0) (proj_k 0) + ?r" unfolding P'_add_Q apply (subst matrix_sum_Suc_remove_head) using tensor_P_dim by auto have"tensor_P (proj_psi_l 0) (proj_k 0) + ?r ≤L P' + Q" unfolding eq2[symmetric] apply (subst lowner_le_refl) using P'_Q_dim by auto moreoverhave"positive (tensor_P (proj_psi_l 0) (proj_k 0))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive) unfolding ps_P_d1 ps_P_d2 using proj_psi_l_dim proj_k_dim positive_proj_psi_l positive_proj_k by auto moreoverhave"matrix_sum d (λl. tensor_P (proj_psi_l (l + 1)) (proj_k (l + 1))) R ∈ carrier_mat d d" apply (subst matrix_sum_dim) using tensor_P_dim by auto ultimatelyhave"?r ≤L P' + Q" apply (subst add_positive_le_reduce2[of ?r d "tensor_P (proj_psi_l 0) (proj_k 0)""P' + Q"]) using tensor_P_dim P'_Q_dim by auto thenshow ?thesis using eq1 ad by auto qed
lemma Q2_leq: "Q2 ≤L adjoint (tensor_P (1m N) (mat_incr K)) * (P' + Q) * tensor_P (1m N) (mat_incr K)" proof - let ?m1 = "tensor_P (1m N) (mat_incr K)" let ?m2 = "adjoint (tensor_P (1m N) (mat_incr K))" have"?m1 * ?m2 = 1m d" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_adjoint) unfolding ps_P_d1 ps_P_d2 apply (auto simp add: mat_incr_dim adjoint_one) apply (subst ps_P.tensor_mat_mult[symmetric]) unfolding ps_P_d1 ps_P_d2 apply (auto simp add: mat_incr_dim adjoint_dim mat_incr_mult_adjoint_mat_incr) using ps_P.tensor_mat_id ps_P_d ps_P_d1 ps_P_d2 by auto thenhave inv: "?m2 * ?m1 = 1m d" using mat_mult_left_right_inverse[of ?m1 d ?m2]
tensor_P_dim adjoint_dim by auto have d: "?m1 * Q2 * ?m2 ∈ carrier_mat d d"using tensor_P_dim adjoint_dim[OF tensor_P_dim] Q2_dim by fastforce have le: "?m2 * (?m1 * Q2 * ?m2) * ?m1 ≤L ?m2 * (P' + Q) * ?m1" (is"lowner_le ?l ?r") apply (subst lowner_le_keep_under_measurement[of _ d]) using Q2_leq_lemma tensor_P_dim P'_Q_dim d by auto have"?l = (?m2 * ?m1) * Q2 * (?m2 * ?m1)" apply (mat_assoc d) using tensor_P_dim Q2_dim by auto alsohave"… = 1m d * Q2 * 1m d"using inv by auto alsohave"… = Q2"using Q2_dim by auto finallyhave eq: "?l = Q2". show ?thesis using eq le by auto qed
lemma hoare_triple_D3: "⊨p {Q2} Utrans_P vars2 (mat_incr K) {adjoint exM0 * P' * exM0 + adjoint exM1 * Q * exM1}" unfolding exP0_P' exP1_Q proof - let ?m = "tensor_P (1m N) (mat_incr K)" have h1: "⊨p {adjoint ?m * (P' + Q) * ?m} Utrans ?m {P' + Q}" using qp_P'_Q hoare_partial.introsby auto have qp: "is_quantum_predicate (adjoint ?m * (P' + Q) * ?m)" using qp_close_under_unitary_operator tensor_P_dim qp_P'_Q unitary_exmat_incr by auto thenhave"⊨p {Q2} Utrans ?m {P' + Q}" using hoare_partial.intros(6)[OF qp_Q2 qp_P'_Q qp qp_P'_Q] Q2_leq h1 lowner_le_refl[OF P'_Q_dim] by auto moreoverhave"Utrans ?m = Utrans_P vars2 (mat_incr K)" apply (subst Utrans_P_is_tensor_P2) unfolding mat_incr_def by auto ultimatelyshow"⊨p {Q2} Utrans_P vars2 (mat_incr K) {P' + Q}"by auto qed
lemma qp_D3_post: "is_quantum_predicate (adjoint exM0 * P' * exM0 + adjoint exM1 * Q * exM1)" unfolding exP0_P' exP1_Q using qp_P'_Q by auto
lemma hoare_triple_D: "⊨p {Q} D {adjoint exM0 * P' * exM0 + adjoint exM1 * Q * exM1}" proof - have"⊨p {Q1} hadamard_n n;; (Utrans_P vars1 mat_Ph;; hadamard_n n) {Q2}" using well_com_hadamard_n well_com_mat_Ph hoare_triple_D2 qp_Q1 qp_Q2 by (auto simp add: hoare_patial_seq_assoc) thenhave"⊨p {Q} Utrans_P vars1 mat_O;; (hadamard_n n;; (Utrans_P vars1 mat_Ph;; hadamard_n n)) {Q2}" using hoare_triple_D1 qp_Q qp_Q1 qp_Q2 hoare_partial.intros(3) by auto moreoverhave"well_com (Utrans_P vars1 mat_Ph;; hadamard_n n)"using well_com_hadamard_n well_com_mat_Ph by auto ultimatelyhave"⊨p {Q} (Utrans_P vars1 mat_O;; hadamard_n n);; (Utrans_P vars1 mat_Ph;; hadamard_n n) {Q2}" using well_com_hadamard_n well_com_mat_O qp_Q qp_Q2 by (auto simp add: hoare_patial_seq_assoc) moreoverhave"well_com (Utrans_P vars1 mat_O;; hadamard_n n)" using well_com_mat_O well_com_hadamard_n by auto ultimatelyhave"⊨p {Q} Utrans_P vars1 mat_O;; hadamard_n n;; Utrans_P vars1 mat_Ph;; hadamard_n n {Q2}" using well_com_hadamard_n well_com_mat_Ph qp_Q qp_Q2 by (auto simp add: hoare_patial_seq_assoc) with qp_Q qp_Q2 qp_D3_post hoare_triple_D3 show"⊨p {Q} D {adjoint exM0 * P' * exM0 + adjoint exM1 * Q * exM1}" unfolding D_def using hoare_partial.intros(3) by auto qed
lemma psi_is_psi_l0: "ψ = psi_l 0" unfolding ψ_eq psi_l_def alpha_l_def beta_l_def by auto
lemma proj_psi_is_proj_psi_l0: "proj_psi = proj_psi_l 0" unfolding proj_psi_def psi_is_psi_l0 proj_psi_l_def by auto
lemma lowner_le_Q: "tensor_P proj_psi (proj_k 0) ≤L adjoint exM0 * P' * exM0 + adjoint exM1 * Q * exM1" proof - let ?r = "matrix_sum d (λl. tensor_P (proj_psi_l l) (proj_k l)) (R + 1)" let ?l = "tensor_P (proj_psi_l 0) (proj_k 0)" have eq: "?r = ?l + matrix_sum d (λl. tensor_P (proj_psi_l (l + 1)) (proj_k (l + 1))) R" (is"_ = _ + ?s") apply (subst matrix_sum_Suc_remove_head) using tensor_P_dim by auto have d: "?s ∈ carrier_mat d d" apply (subst matrix_sum_dim) using tensor_P_dim by auto have pt: "positive (tensor_P (proj_psi_l l) (proj_k l))"for l unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive) unfolding ps_P_d1 ps_P_d2 using proj_psi_l_dim proj_k_dim positive_proj_psi_l positive_proj_k by auto have ps: "positive ?s" apply (subst matrix_sum_positive)
subgoal using tensor_P_dim by auto using pt by auto have"?l ≤L ?r" unfolding eq apply (subst add_positive_le_reduce1[of ?l d ?s])
subgoal using tensor_P_dim by auto
subgoal using d by auto
subgoal using tensor_P_dim d by auto
subgoal using ps by auto apply (subst lowner_le_refl[of _ d]) using tensor_P_dim d by auto thenshow ?thesis unfolding exP0_P' exP1_Q P'_add_Q proj_psi_is_proj_psi_l0 by auto qed
lemma hoare_triple_while: "⊨p {adjoint exM0 * P' * exM0 + adjoint exM1 * Q * exM1} While_P vars2 M0 M1 D {P'}" proof - let ?m = "λ(n::nat). if n = 0 then mat_extension dims vars2 M0 else if n = 1 then mat_extension dims vars2 M1 else undefined" have dM0: "M0 ∈ carrier_mat K K"unfolding M0_def by auto have dM1: "M1 ∈ carrier_mat K K"unfolding M1_def by auto have m0: "?m 0 = exM0"apply (simp) unfolding exM0_def ps2_P.ptensor_mat_def mat_ext_vars2[OF dM0] by auto have m1: "?m 1 = exM1"unfolding exM1_def ps2_P.ptensor_mat_def mat_ext_vars2[OF dM1] byauto have"⊨p {Q} D {adjoint (?m 0) * P' * (?m 0) + adjoint (?m 1) * Q * (?m 1)}" using hoare_triple_D m0 m1 by auto thenshow ?thesis unfolding While_P_def using qp_D3_post qp_P' hoare_partial.intros(5)[OF qp_P' qp_Q, of D ?m] m0 m1 by auto qed
lemma R_and_a_half_θ: "(R + 1/2) * θ = pi / 2" using R θ_neq_0 by auto
lemma psi_lR_is_beta: "psi_l R = β" unfolding psi_l_def alpha_l_def beta_l_def R_and_a_half_θ by auto
lemma post_mult_post: "post * post = post" by (auto simp add: post_def scalar_prod_def sum_only_one_neq_0)
lemma post_mult_proj_psi_lR: "post * proj_psi_l R = proj_psi_l R" proof - let ?R = "proj_psi_l R" have"post * ?R = post * ?R * 1m N" using post_dim proj_psi_l_dim[of R] by auto alsohave"… = outer_prod (post *v psi_l R) ((1m N) *v psi_l R)" unfolding proj_psi_l_def apply (subst outer_prod_left_right_mat[of _ N _ N _ N _ N]) by (auto simp add: psi_l_dim post_dim adjoint_one) alsohave"… = ?R"unfolding proj_psi_l_def unfolding psi_lR_is_beta unfolding post_mult_beta using β_dim by auto finallyshow"post * ?R = ?R". qed
lemma proj_psi_lR_mult_post: "proj_psi_l R * post = proj_psi_l R" proof - let ?R = "proj_psi_l R" have"?R * post = 1m N * ?R * post" using post_dim proj_psi_l_dim[of R] by auto alsohave"… = outer_prod ((1m N) *v psi_l R) (post *v psi_l R)" unfolding proj_psi_l_def apply (subst outer_prod_left_right_mat[of _ N _ N _ N _ N]) by (auto simp add: psi_l_dim post_dim hermitian_post[unfolded hermitian_def]) alsohave"… = ?R"unfolding proj_psi_l_def unfolding psi_lR_is_beta unfolding post_mult_beta using β_dim by auto finallyshow"?R * post = ?R". qed
lemma proj_psi_lR_mult_proj_psi_lR: "proj_psi_l R * proj_psi_l R = proj_psi_l R" unfolding proj_psi_l_def psi_lR_is_beta apply (subst outer_prod_mult_outer_prod[of _ N _ N _ _ N]) by (auto simp add: β_inner)
lemma proj_psi_lR_le_post: "proj_psi_l R ≤L post" proof - let ?R = "proj_psi_l R" let ?s = "post - ?R" have eq1: "post * (post - ?R) = post - ?R" apply (subst mult_minus_distrib_mat[of _ N N _ N]) apply (auto simp add: post_dim proj_psi_l_dim[of R]) using post_mult_post post_mult_proj_psi_lR by auto have eq2: "?R * (post - ?R) = 0m N N" apply (subst mult_minus_distrib_mat[of _ N N _ N]) apply (auto simp add: post_dim proj_psi_l_dim[of R]) unfolding proj_psi_lR_mult_post proj_psi_lR_mult_proj_psi_lR using proj_psi_l_dim[of R] by auto have"adjoint ?s = ?s" apply (subst adjoint_minus[of _ N N]) using post_dim proj_psi_l_dim hermitian_post hermitian_proj_psi_l K by (auto simp add: hermitian_def) thenhave"?s * adjoint ?s = ?s * ?s"by auto alsohave"… = post * (post - ?R) - ?R * (post - ?R)" using post_dim proj_psi_l_dim[of R] by (mat_assoc N) alsohave"… = post - ?R" unfolding eq1 eq2 using post_dim proj_psi_l_dim[of R] by auto finallyhave"?s * adjoint ?s = ?s". thenhave"∃M. M * adjoint M = ?s"by auto thenhave"positive ?s"apply (subst positive_if_decomp[of ?s N]) using post_dim proj_psi_l_dim[of R] by auto thenshow ?thesis unfolding lowner_le_def using post_dim proj_psi_l_dim[of R] by auto qed
lemma P'_le_post_R: "P' ≤L (tensor_P post (proj_k R))" proof - let ?r = "tensor_P post (proj_k R)" have"?r - P' = tensor_P (post - proj_psi_l R) (proj_k R)" unfolding P'_def ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_minus1) unfolding ps_P_d1 ps_P_d2 using post_dim proj_psi_l_dim proj_k_dim by auto moreoverhave"positive (tensor_P (post - proj_psi_l R) (proj_k R))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive) unfolding ps_P_d1 ps_P_d2 using proj_psi_lR_le_post[unfolded lowner_le_def]
post_dim proj_psi_l_dim[of R] proj_k_dim positive_proj_k by auto ultimatelyshow"P' ≤L ?r" unfolding lowner_le_def P'_def using tensor_P_dim by auto qed
lemma positive_post: "positive post" proof - have ad: "adjoint post = post"using hermitian_post[unfolded hermitian_def] by auto thenhave"post * adjoint post = post" unfolding ad post_mult_post by auto thenhave"∃M. M * adjoint M = post"by auto thenshow ?thesis using positive_if_decomp post_dim by auto qed
lemma lowner_le_P': "P' ≤L tensor_P post (1m K)" proof - let ?r = "tensor_P post (1m K)" let ?m = "tensor_P post (proj_k R)" have"?m ≤L ?r" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive_le) unfolding ps_P_d1 ps_P_d2 using post_dim proj_k_dim positive_post positive_proj_k
lowner_le_refl[of post] proj_k_le_one by auto thenshow"P' ≤L ?r" using lowner_le_trans[of P' d ?m ?r] P'_le_post_R unfolding P'_defusing tensor_P_dim by auto qed
lemma post_mult_testNk_neg: assumes"¬ f k" shows"post * testN k = 0m N N" using assms by (auto simp add: post_def testN_def scalar_prod_def sum_only_one_neq_0)
lemma testN_post1: "f k ==> adjoint (testN k) * post * testN k = testN k" apply (subst assoc_mult_mat[of _ N N _ N _ N]) apply (auto simp add: adjoint_dim testN_dim post_dim) apply (subst post_mult_testNk, simp) unfolding hermitian_testN[unfolded hermitian_def] using testN_mult_testN by auto
lemma testN_post2: "¬ f k ==> adjoint (testN k) * post * testN k = 0m N N" apply (subst assoc_mult_mat[of _ N N _ N _ N]) apply (auto simp add: adjoint_dim testN_dim post_dim) apply (subst post_mult_testNk_neg, simp) unfolding hermitian_testN[unfolded hermitian_def] using testN_dim[of k] by auto
definition post_fst_k :: "nat ==> complex mat"where "post_fst_k k = mat N N (λ(i, j). if (i = j ∧ f i ∧ i < k) then 1 else 0)"
lemma post_fst_kN: "post_fst_k N = post" unfolding post_fst_k_def post_def by auto
lemma post_fst_k_Suc: "f i ==> post_fst_k (Suc i) = testN i + post_fst_k i" apply (rule eq_matI) unfolding post_fst_k_def testN_def by auto
lemma post_fst_k_Suc_neg: "¬ f i ==> post_fst_k (Suc i) = post_fst_k i" apply (rule eq_matI) unfolding post_fst_k_def apply auto using less_antisym by fastforce
lemma testN_sum: "matrix_sum N (λk. adjoint (testN k) * post * testN k) N = post" proof - have"m ≤ N ==> matrix_sum N (λk. adjoint (testN k) * post * testN k) m = post_fst_k m"for m proof (induct m) case0 thenshow ?caseapply simp unfolding post_fst_k_def by auto next case (Suc m) thenhave m: "m ≤ N"by auto show ?case proof (cases "f m") case True show ?thesis apply simp apply (subst testN_post1[OF True]) apply (subst Suc(1)[OF m]) using post_fst_k_Suc True by auto next case False show ?thesis apply simp apply (subst testN_post2[OF False]) apply (subst Suc(1)[OF m]) using post_fst_k_Suc_neg False post_fst_k_def by auto qed qed thenshow ?thesis using post_fst_kN by auto qed
lemma tensor_P_testN_sum: "matrix_sum d (λk. adjoint (tensor_P (testN k) (1m K)) * tensor_P post (1m K) * tensor_P (testN k) (1m K)) N = tensor_P post (1m K)" proof - have eq: "adjoint (tensor_P (testN k) (1m K)) * tensor_P post (1m K) * tensor_P (testN k) (1m K) = tensor_P (adjoint (testN k) * post * (testN k)) (1m K)"for k apply (subst tensor_P_adjoint_left_right)
subgoal unfolding testN_def by auto
subgoal by auto
subgoal using post_dim by auto using adjoint_one by auto moreoverhave"matrix_sum N (λk. adjoint (testN k) * post * testN k) N = post" using testN_sum by auto show ?thesis unfolding eq apply (subst matrix_sum_tensor_P1)
subgoal unfolding testN_def by auto
subgoal by auto using testN_sum by auto qed
lemma post_le_one: "post ≤L 1m N" proof - let ?s = "1m N - post" have eq1: "1m N * (1m N - post) = 1m N - post" apply (mat_assoc N) using post_dim by auto have eq2: "post * (1m N - post) = 0m N N" apply (subst mult_minus_distrib_mat[of _ N N]) using post_dim by (auto simp add: post_mult_post)
have"adjoint ?s = ?s" apply (subst adjoint_minus) apply (auto simp add: post_dim adjoint_dim) using adjoint_one hermitian_post[unfolded hermitian_def] by auto thenhave"?s * adjoint ?s = ?s * ?s"by auto alsohave"… = 1m N * (1m N - post) - post * (1m N - post)" apply (mat_assoc N) using post_dim by auto alsohave"… = ?s"unfolding eq1 eq2 using post_dim by auto finallyhave"?s * adjoint ?s = ?s". thenhave"∃M. M * adjoint M = ?s"by auto thenhave"positive ?s"apply (subst positive_if_decomp[of ?s N]) using post_dim by auto thenshow ?thesis unfolding lowner_le_def using post_dim by auto qed
lemma qp_post: "is_quantum_predicate (tensor_P post (1m K))" unfolding is_quantum_predicate_def proof (intro conjI) show"tensor_P post (1m K) ∈ carrier_mat d d" using tensor_P_dim by auto show"positive (tensor_P post (1m K))" unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive) by (auto simp add: ps_P_d1 ps_P_d2 post_dim positive_post positive_one) show"tensor_P post (1m K) ≤L 1m d" unfolding ps_P.tensor_mat_id[symmetric, unfolded ps_P_d ps_P_d1 ps_P_d2] unfolding ps2_P.ptensor_mat_def apply (subst ps_P.tensor_mat_positive_le) unfolding ps_P_d1 ps_P_d2 using post_dim positive_post positive_one post_le_one lowner_le_refl[of "1m K" K] by auto qed
lemma hoare_triple_if: "⊨p {tensor_P post (1m K)} Measure_P vars1 N testN (replicate N SKIP) {tensor_P post (1m K)}" proof-
define M where"M = (λ)) define Post where "and(∀i j. i<j ∧ j<length l ⟶ l!i ∩* = {}) )" have M: "M = (lambdatNm K))" unfolding _df usgm_x_var1at have skip: "∧==> (replicate N SKIP) ! k = SKIP" by simp have h: "java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 unfoldingusingrtial moreoverhave"∧==> is_quantum_predicate (Post k)"unfolding Post_def using qp_post byauto ultimatelyshow ?thesis unfolding using hoare_partial.intros(4) Postsub K)" "replicate N SKIP" M] unfolding M Post_def using tensor_P_testN_sum qp_post by auto qed
theorem grover_partial_deduct: "er_invarItronvar
{sor_Pproj_k
Grover
nsor_Pm K)}" unfolding Grover_def proof - have "⊨p
{nsor_P )
hadamard_n n
{adjoint exM0 * P' * exM0 + adjoint exM1 *xM1 using hoare_partial.intros(6)[OF_postost
hoare_triple_init lowner_le_refl[OF tensor_P_dim] lowner_le_Qu ∈ l ! (j - Suc 0)› A have"u∈(set l)" thenv∈0h<><>ast#)i<close> have"v∈ {tensor_P pre (proj_k 0)} hadamard_n n;; ile_P vars2 M0s2 M0 1 D {P'}" using_es thenhave"⊨p {tensor_P pre (proj_k 0)} hadamard_n n;; While_P vars2 M0 M1 D {tensor_P post (1* `` V0" usingp_prejava.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
lowner_le_P_c_def thencompute_SCC_spec" {tensor_P pre (proj_k 0)} hadamard_n n;; While_P vars2 M0 M1 D;; Measure_P vars1 N testN (replicate N SK {tensor_P post (1do { let x = S!l; qed
theorem grover_partial_correct: "⊨SPEC (λ!i)" {tensor_P pre (proj_k 0)} Grover {tensor_P post (1_ using grover_partial_deductasNE: "p<noteq[Id (RETURNlast ))" end
end
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.117Bemerkung:
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.