QuantumLib.VectorStates
Require Export Pad.
Notation "∣ + ⟩" := (/√2 .* ∣ 0 ⟩ .+ /√2 .* ∣ 1 ⟩).
Notation "∣ - ⟩" := (/√2 .* ∣ 0 ⟩ .+ (-/√2) .* ∣ 1 ⟩).
Lemma bra0_equiv : ⟨0∣ = bra 0.
Lemma bra1_equiv : ⟨1∣ = bra 1.
Lemma ket0_equiv : ∣0⟩ = ket 0.
Lemma ket1_equiv : ∣1⟩ = ket 1.
Lemma bra0ket0 : bra 0 × ket 0 = I 1.
Lemma bra0ket1 : bra 0 × ket 1 = Zero.
Lemma bra1ket0 : bra 1 × ket 0 = Zero.
Lemma bra1ket1 : bra 1 × ket 1 = I 1.
Lemma H0_spec : hadamard × ∣ 0 ⟩ = ∣ + ⟩.
Lemma H1_spec : hadamard × ∣ 1 ⟩ = ∣ - ⟩.
Lemma Hplus_spec : hadamard × ∣ + ⟩ = ∣ 0 ⟩.
Lemma Hminus_spec : hadamard × ∣ - ⟩ = ∣ 1 ⟩.
Local Open Scope nat_scope.
Lemma H0_kron_n_spec : ∀ n,
n ⨂ hadamard × n ⨂ ∣0⟩ = n ⨂ ∣+⟩.
Local Close Scope nat_scope.
Lemma X0_spec : σx × ∣ 0 ⟩ = ∣ 1 ⟩.
Lemma X1_spec : σx × ∣ 1 ⟩ = ∣ 0 ⟩.
Lemma Y0_spec : σy × ∣ 0 ⟩ = Ci .* ∣ 1 ⟩.
Lemma Y1_spec : σy × ∣ 1 ⟩ = -Ci .* ∣ 0 ⟩.
Lemma Z0_spec : σz × ∣ 0 ⟩ = ∣ 0 ⟩.
Lemma Z1_spec : σz × ∣ 1 ⟩ = -1 .* ∣ 1 ⟩.
Lemma phase0_spec : ∀ ϕ, phase_shift ϕ × ket 0 = ket 0.
Lemma phase1_spec : ∀ ϕ, phase_shift ϕ × ket 1 = Cexp ϕ .* ket 1.
Definition b2R (b : bool) : R := if b then 1%R else 0%R.
Lemma phase_shift_on_ket : ∀ (θ : R) (b : bool),
phase_shift θ × ∣ b ⟩ = (Cexp (b × θ)) .* ∣ b ⟩.
Lemma hadamard_on_ket : ∀ (b : bool),
hadamard × ∣ b ⟩ = /√2 .* (∣ 0 ⟩ .+ (-1)^b .* ∣ 1 ⟩).
Lemma CNOT_spec : ∀ (x y : nat), (x < 2)%nat → (y < 2)%nat → cnot × ∣ x,y ⟩ = ∣ x, (x + y) mod 2 ⟩.
Lemma CNOT00_spec : cnot × ∣ 0,0 ⟩ = ∣ 0,0 ⟩.
Lemma CNOT01_spec : cnot × ∣ 0,1 ⟩ = ∣ 0,1 ⟩.
Lemma CNOT10_spec : cnot × ∣ 1,0 ⟩ = ∣ 1,1 ⟩.
Lemma CNOT11_spec : cnot × ∣ 1,1 ⟩ = ∣ 1,0 ⟩.
Lemma SWAP_spec : ∀ x y, swap × ∣ x,y ⟩ = ∣ y,x ⟩.
Hint Rewrite bra0_equiv bra1_equiv ket0_equiv ket1_equiv : ket_db.
Hint Rewrite bra0ket0 bra0ket1 bra1ket0 bra1ket1 : ket_db.
Hint Rewrite Mmult_plus_distr_l Mmult_plus_distr_r kron_plus_distr_l kron_plus_distr_r Mscale_plus_distr_r : ket_db.
Hint Rewrite Mscale_mult_dist_l Mscale_mult_dist_r Mscale_kron_dist_l Mscale_kron_dist_r : ket_db.
Hint Rewrite Mscale_assoc @Mmult_assoc : ket_db.
Hint Rewrite Mmult_1_l Mmult_1_r kron_1_l kron_1_r Mscale_0_l Mscale_0_r Mscale_1_l Mplus_0_l Mplus_0_r using (auto with wf_db) : ket_db.
Hint Rewrite kron_0_l kron_0_r Mmult_0_l Mmult_0_r : ket_db.
Hint Rewrite @kron_mixed_product : ket_db.
Hint Rewrite H0_spec H1_spec Hplus_spec Hminus_spec X0_spec X1_spec Y0_spec Y1_spec
Z0_spec Z1_spec phase0_spec phase1_spec : ket_db.
Hint Rewrite CNOT00_spec CNOT01_spec CNOT10_spec CNOT11_spec SWAP_spec : ket_db.
Lemma ket2bra : ∀ n, (ket n) † = bra n.
Hint Rewrite ket2bra : ket_db.
Lemma ket0_transpose_bra0 : (ket 0) ⊤ = bra 0.
Lemma ket1_transpose_bra1 : (ket 1) ⊤ = bra 1.
Lemma bra0_transpose_ket0 : (bra 0) ⊤ = ket 0.
Lemma bra1_transpose_ket1 : (bra 1) ⊤ = ket 1.
Lemma bra1_adjoint_ket1 : (bra 1) † = ket 1.
Lemma ket1_adjoint_bra1 : (ket 1) † = bra 1.
Lemma bra0_adjoint_ket0 : (bra 0) † = ket 0.
Lemma ket0_adjoint_bra0 : (ket 0) † = bra 0.
Lemma XYZ0 : -Ci .* σx × σy × σz × ∣ 0 ⟩ = ∣ 0 ⟩.
Lemma XYZ1 : -Ci .* σx × σy × σz × ∣ 1 ⟩ = ∣ 1 ⟩.
Notation "∣ + ⟩" := (/√2 .* ∣ 0 ⟩ .+ /√2 .* ∣ 1 ⟩).
Notation "∣ - ⟩" := (/√2 .* ∣ 0 ⟩ .+ (-/√2) .* ∣ 1 ⟩).
Lemma bra0_equiv : ⟨0∣ = bra 0.
Lemma bra1_equiv : ⟨1∣ = bra 1.
Lemma ket0_equiv : ∣0⟩ = ket 0.
Lemma ket1_equiv : ∣1⟩ = ket 1.
Lemma bra0ket0 : bra 0 × ket 0 = I 1.
Lemma bra0ket1 : bra 0 × ket 1 = Zero.
Lemma bra1ket0 : bra 1 × ket 0 = Zero.
Lemma bra1ket1 : bra 1 × ket 1 = I 1.
Lemma H0_spec : hadamard × ∣ 0 ⟩ = ∣ + ⟩.
Lemma H1_spec : hadamard × ∣ 1 ⟩ = ∣ - ⟩.
Lemma Hplus_spec : hadamard × ∣ + ⟩ = ∣ 0 ⟩.
Lemma Hminus_spec : hadamard × ∣ - ⟩ = ∣ 1 ⟩.
Local Open Scope nat_scope.
Lemma H0_kron_n_spec : ∀ n,
n ⨂ hadamard × n ⨂ ∣0⟩ = n ⨂ ∣+⟩.
Local Close Scope nat_scope.
Lemma X0_spec : σx × ∣ 0 ⟩ = ∣ 1 ⟩.
Lemma X1_spec : σx × ∣ 1 ⟩ = ∣ 0 ⟩.
Lemma Y0_spec : σy × ∣ 0 ⟩ = Ci .* ∣ 1 ⟩.
Lemma Y1_spec : σy × ∣ 1 ⟩ = -Ci .* ∣ 0 ⟩.
Lemma Z0_spec : σz × ∣ 0 ⟩ = ∣ 0 ⟩.
Lemma Z1_spec : σz × ∣ 1 ⟩ = -1 .* ∣ 1 ⟩.
Lemma phase0_spec : ∀ ϕ, phase_shift ϕ × ket 0 = ket 0.
Lemma phase1_spec : ∀ ϕ, phase_shift ϕ × ket 1 = Cexp ϕ .* ket 1.
Definition b2R (b : bool) : R := if b then 1%R else 0%R.
Lemma phase_shift_on_ket : ∀ (θ : R) (b : bool),
phase_shift θ × ∣ b ⟩ = (Cexp (b × θ)) .* ∣ b ⟩.
Lemma hadamard_on_ket : ∀ (b : bool),
hadamard × ∣ b ⟩ = /√2 .* (∣ 0 ⟩ .+ (-1)^b .* ∣ 1 ⟩).
Lemma CNOT_spec : ∀ (x y : nat), (x < 2)%nat → (y < 2)%nat → cnot × ∣ x,y ⟩ = ∣ x, (x + y) mod 2 ⟩.
Lemma CNOT00_spec : cnot × ∣ 0,0 ⟩ = ∣ 0,0 ⟩.
Lemma CNOT01_spec : cnot × ∣ 0,1 ⟩ = ∣ 0,1 ⟩.
Lemma CNOT10_spec : cnot × ∣ 1,0 ⟩ = ∣ 1,1 ⟩.
Lemma CNOT11_spec : cnot × ∣ 1,1 ⟩ = ∣ 1,0 ⟩.
Lemma SWAP_spec : ∀ x y, swap × ∣ x,y ⟩ = ∣ y,x ⟩.
Hint Rewrite bra0_equiv bra1_equiv ket0_equiv ket1_equiv : ket_db.
Hint Rewrite bra0ket0 bra0ket1 bra1ket0 bra1ket1 : ket_db.
Hint Rewrite Mmult_plus_distr_l Mmult_plus_distr_r kron_plus_distr_l kron_plus_distr_r Mscale_plus_distr_r : ket_db.
Hint Rewrite Mscale_mult_dist_l Mscale_mult_dist_r Mscale_kron_dist_l Mscale_kron_dist_r : ket_db.
Hint Rewrite Mscale_assoc @Mmult_assoc : ket_db.
Hint Rewrite Mmult_1_l Mmult_1_r kron_1_l kron_1_r Mscale_0_l Mscale_0_r Mscale_1_l Mplus_0_l Mplus_0_r using (auto with wf_db) : ket_db.
Hint Rewrite kron_0_l kron_0_r Mmult_0_l Mmult_0_r : ket_db.
Hint Rewrite @kron_mixed_product : ket_db.
Hint Rewrite H0_spec H1_spec Hplus_spec Hminus_spec X0_spec X1_spec Y0_spec Y1_spec
Z0_spec Z1_spec phase0_spec phase1_spec : ket_db.
Hint Rewrite CNOT00_spec CNOT01_spec CNOT10_spec CNOT11_spec SWAP_spec : ket_db.
Lemma ket2bra : ∀ n, (ket n) † = bra n.
Hint Rewrite ket2bra : ket_db.
Lemma ket0_transpose_bra0 : (ket 0) ⊤ = bra 0.
Lemma ket1_transpose_bra1 : (ket 1) ⊤ = bra 1.
Lemma bra0_transpose_ket0 : (bra 0) ⊤ = ket 0.
Lemma bra1_transpose_ket1 : (bra 1) ⊤ = ket 1.
Lemma bra1_adjoint_ket1 : (bra 1) † = ket 1.
Lemma ket1_adjoint_bra1 : (ket 1) † = bra 1.
Lemma bra0_adjoint_ket0 : (bra 0) † = ket 0.
Lemma ket0_adjoint_bra0 : (ket 0) † = bra 0.
Lemma XYZ0 : -Ci .* σx × σy × σz × ∣ 0 ⟩ = ∣ 0 ⟩.
Lemma XYZ1 : -Ci .* σx × σy × σz × ∣ 1 ⟩ = ∣ 1 ⟩.
Classical States
Local Close Scope C_scope.
Local Close Scope R_scope.
Local Open Scope nat_scope.
Definition update {A} (f : nat → A) (i : nat) (x : A) :=
fun j ⇒ if j =? i then x else f j.
Lemma update_index_eq : ∀ {A} (f : nat → A) i b, (update f i b) i = b.
Lemma update_index_neq : ∀ {A} (f : nat → A) i j b, i ≠ j → (update f i b) j = f j.
Lemma update_same : ∀ {A} (f : nat → A) i b,
b = f i → update f i b = f.
Lemma update_twice_eq : ∀ {A} (f : nat → A) i b b',
update (update f i b) i b' = update f i b'.
Lemma update_twice_neq : ∀ {A} (f : nat → A) i j b b',
i ≠ j → update (update f i b) j b' = update (update f j b') i b.
Definition shift {A} (f : nat → A) k := fun i ⇒ f (i + k).
Lemma shift_0 : ∀ {A} (f : nat → A), shift f 0 = f.
Lemma shift_plus : ∀ {A} (f : nat → A) i j, shift (shift f j) i = shift f (i + j).
Lemma shift_simplify : ∀ {A} (f : nat → A) i j ,
shift f i j = f (j + i).
Definition fswap {A} (f : nat → A) x y :=
fun i ⇒ if i =? x then f y else if i =? y then f x else f i.
Lemma fswap_simpl1 : ∀ A f x y, @fswap A f x y x = f y.
Lemma fswap_simpl2 : ∀ A f x y, @fswap A f x y y = f x.
Lemma fswap_same : ∀ A f x, @fswap A f x x = f.
Lemma fswap_neq : ∀ {A} (f : nat → A) a b x, a ≠ x → b ≠ x → fswap f a b x = f x.
Lemma fswap_rewrite : ∀ {A} (f : nat → A) a b,
fswap f a b = update (update f b (f a)) a (f b).
Fixpoint f_to_vec (n : nat) (f : nat → bool) : Vector (2^n) :=
match n with
| 0 ⇒ I 1
| S n' ⇒ (f_to_vec n' f) ⊗ ∣ f n' ⟩
end.
Lemma f_to_vec_WF : ∀ (n : nat) (f : nat → bool),
WF_Matrix (f_to_vec n f).
#[export] Hint Resolve f_to_vec_WF : wf_db.
Lemma f_to_vec_eq : ∀ n f f',
(∀ i, i < n → f i = f' i) →
f_to_vec n f = f_to_vec n f'.
Definition basis_vector (n k : nat) : Vector n :=
fun i j ⇒ if (i =? k) && (j =? 0) then C1 else C0.
Lemma basis_vector_WF : ∀ n i, (i < n)%nat → WF_Matrix (basis_vector n i).
#[export] Hint Resolve basis_vector_WF : wf_db.
Lemma basis_vector_product_eq : ∀ d n,
n < d → (basis_vector d n)† × basis_vector d n = I 1.
Lemma basis_vector_pure_state : ∀ n i,
(i < n)%nat → Pure_State_Vector (basis_vector n i).
Lemma basis_vector_product_neq : ∀ d m n,
(m < d)%nat → (n < d)%nat → (m ≠ n)%nat → (basis_vector d m)† × basis_vector d n = Zero.
Lemma matrix_times_basis_eq : ∀ m n (A : Matrix m n) i j,
WF_Matrix A →
(A × basis_vector n j) i 0 = A i j.
Lemma equal_on_basis_vectors_implies_equal : ∀ m n (A B : Matrix m n),
WF_Matrix A →
WF_Matrix B →
(∀ k, k < n → A × (basis_vector n k) = B × (basis_vector n k)) →
A = B.
Lemma divmod_decomp : ∀ x y z r,
(r > 0)%nat →
(z < r)%nat →
(x = y × r + z ↔ x / r = y ∧ x mod r = z)%nat.
Lemma split_basis_vector : ∀ m n x y,
(x < 2 ^ m)%nat →
(y < 2 ^ n)%nat →
basis_vector (2 ^ (m + n)) (x × 2 ^ n + y)
= basis_vector (2 ^ m) x ⊗ basis_vector (2 ^ n) y.
Fixpoint binlist_to_nat (l : list bool) : nat :=
match l with
| [] ⇒ 0
| b :: l' ⇒ b + 2 × binlist_to_nat l'
end.
Fixpoint funbool_to_list (len : nat) (f : nat → bool) :=
match len with
| O ⇒ []
| S len' ⇒ f len' :: funbool_to_list len' f
end.
Definition funbool_to_nat (len : nat) (f : nat → bool) :=
binlist_to_nat (funbool_to_list len f).
Lemma funbool_to_nat_bound : ∀ n f, (funbool_to_nat n f < 2 ^ n)%nat.
Lemma funbool_to_nat_eq : ∀ n f f',
(∀ x, x < n → f x = f' x)%nat →
funbool_to_nat n f = funbool_to_nat n f'.
Local Opaque Nat.mul.
Lemma funbool_to_nat_shift : ∀ n f k, (k < n)%nat →
funbool_to_nat n f = (2 ^ (n - k) × funbool_to_nat k f + funbool_to_nat (n - k) (shift f k))%nat.
Local Transparent Nat.mul.
Lemma basis_f_to_vec : ∀ n f,
f_to_vec n f = basis_vector (2^n) (funbool_to_nat n f).
Fixpoint incr_bin (l : list bool) :=
match l with
| [] ⇒ [true]
| false :: t ⇒ true :: t
| true :: t ⇒ false :: (incr_bin t)
end.
Fixpoint nat_to_binlist' n :=
match n with
| O ⇒ []
| S n' ⇒ incr_bin (nat_to_binlist' n')
end.
Definition nat_to_binlist len n :=
let l := nat_to_binlist' n in
l ++ (repeat false (len - length l)).
Fixpoint list_to_funbool len (l : list bool) : nat → bool :=
match l with
| [] ⇒ fun _ ⇒ false
| h :: t ⇒ update (list_to_funbool (len - 1)%nat t) (len - 1) h
end.
Definition nat_to_funbool len n : nat → bool :=
list_to_funbool len (nat_to_binlist len n).
Lemma binlist_to_nat_append : ∀ l1 l2,
binlist_to_nat (l1 ++ l2) =
(binlist_to_nat l1 + 2 ^ (length l1) × binlist_to_nat l2)%nat.
Lemma binlist_to_nat_false : ∀ n, binlist_to_nat (repeat false n) = O.
Lemma binlist_to_nat_true : ∀ n, binlist_to_nat (repeat true n) = 2^n - 1.
Lemma nat_to_binlist_eq_nat_to_binlist' : ∀ len n,
binlist_to_nat (nat_to_binlist len n) = binlist_to_nat (nat_to_binlist' n).
Lemma nat_to_binlist_inverse : ∀ len n,
binlist_to_nat (nat_to_binlist len n) = n.
Lemma nat_to_binlist_corr : ∀ l n,
nat_to_binlist' n = l →
binlist_to_nat l = n.
Lemma incr_bin_true_length : ∀ l,
Forall (fun b ⇒ b = true) l →
length (incr_bin l) = S (length l).
Lemma incr_bin_false_length : ∀ l,
Exists (fun b ⇒ b ≠ true) l →
length (incr_bin l) = length l.
Lemma all_true_repeat : ∀ l,
Forall (fun b : bool ⇒ b = true) l →
l = repeat true (length l).
Lemma nat_to_binlist_length' : ∀ k n,
n < 2 ^ k → length (nat_to_binlist' n) ≤ k.
Lemma nat_to_binlist_length : ∀ len n,
(n < 2 ^ len)%nat → length (nat_to_binlist len n) = len.
Lemma funbool_to_list_update_oob : ∀ f dim b n, (dim ≤ n)%nat →
funbool_to_list dim (update f n b) = funbool_to_list dim f.
Lemma list_to_funbool_inverse : ∀ len l,
length l = len →
funbool_to_list len (list_to_funbool len l) = l.
Lemma nat_to_funbool_inverse : ∀ len n,
(n < 2 ^ len)%nat → funbool_to_nat len (nat_to_funbool len n) = n.
Local Opaque Nat.mul.
Lemma nat_to_binlist'_even : ∀ n, (n > 0)%nat →
nat_to_binlist' (2 × n) = false :: nat_to_binlist' n.
Lemma nat_to_binlist'_odd : ∀ n,
nat_to_binlist' (2 × n + 1) = true :: nat_to_binlist' n.
Lemma binlist_to_nat_inverse : ∀ l n i,
list_to_funbool n (nat_to_binlist' (binlist_to_nat l)) i = list_to_funbool n l i.
Lemma list_to_funbool_repeat_false : ∀ n i,
list_to_funbool n (repeat false n) i = false.
Lemma funbool_to_nat_0 : ∀ n f,
funbool_to_nat n f = O → ∀ i, (i < n)%nat → f i = false.
Lemma funbool_to_nat_inverse : ∀ len f i, (i < len)%nat →
nat_to_funbool len (funbool_to_nat len f) i = f i.
Local Transparent Nat.mul.
Lemma basis_f_to_vec_alt : ∀ len n, (n < 2 ^ len)%nat →
basis_vector (2 ^ len) n = f_to_vec len (nat_to_funbool len n).
Lemma equal_on_basis_states_implies_equal : ∀ {dim} (A B : Square (2 ^ dim)),
WF_Matrix A →
WF_Matrix B →
(∀ f, A × (f_to_vec dim f) = B × (f_to_vec dim f)) →
A = B.
Lemma f_to_vec_update_oob : ∀ (n : nat) (f : nat → bool) (i : nat) (b : bool),
n ≤ i → f_to_vec n (update f i b) = f_to_vec n f.
Lemma f_to_vec_shift_update_oob : ∀ (n : nat) (f : nat → bool) (i j : nat) (b : bool),
j + n ≤ i ∨ i < j →
f_to_vec n (shift (update f i b) j) = f_to_vec n (shift f j).
Lemma f_to_vec_split : ∀ (base n i : nat) (f : nat → bool),
i < n →
f_to_vec n f = (f_to_vec i f) ⊗ ∣ f i ⟩ ⊗ (f_to_vec (n - 1 - i) (shift f (i + 1))).
Lemma f_to_vec_merge : ∀ f1 f2 m n,
f_to_vec m f1 ⊗ f_to_vec n f2 =
f_to_vec (m + n) (fun x ⇒ if x <? m then f1 x else f2 (x - m)%nat).
Lemma f_to_vec_σx : ∀ (n i : nat) (f : nat → bool),
i < n →
(pad_u n i σx) × (f_to_vec n f) = f_to_vec n (update f i (¬ (f i))).
Lemma f_to_vec_cnot : ∀ (n i j : nat) (f : nat → bool),
i < n → j < n → i ≠ j →
(pad_ctrl n i j σx) × (f_to_vec n f) = f_to_vec n (update f j (f j ⊕ f i)).
Lemma f_to_vec_swap : ∀ (n i j : nat) (f : nat → bool),
i < n → j < n → i ≠ j →
(pad_swap n i j) × (f_to_vec n f) = f_to_vec n (fswap f i j).
Lemma f_to_vec_phase_shift : ∀ (n i : nat) (θ : R) (f : nat → bool),
(i < n)%nat →
(pad_u n i (phase_shift θ)) × (f_to_vec n f) =
(Cexp ((f i) × θ)) .* f_to_vec n f.
Local Open Scope R_scope.
Lemma f_to_vec_hadamard : ∀ (n i : nat) (f : nat → bool),
(i < n)%nat →
(pad_u n i hadamard) × (f_to_vec n f)
= /√2 .* ((f_to_vec n (update f i false)) .+
(Cexp ((f i) × PI)) .* f_to_vec n (update f i true)).
Local Close Scope R_scope.
Hint Rewrite f_to_vec_cnot f_to_vec_σx f_to_vec_phase_shift using lia : f_to_vec_db.
Hint Rewrite (@update_index_eq bool) (@update_index_neq bool) (@update_twice_eq bool) (@update_same bool) using lia : f_to_vec_db.
Indexed Vector Sum
Lemma basis_vector_decomp : ∀ {d} (ψ : Vector d),
WF_Matrix ψ →
ψ = big_sum (fun i ⇒ (ψ i O) .* basis_vector d i) d.
Local Opaque Nat.mul.
Lemma vsum_sum : ∀ d n (f : nat → Vector d),
big_sum f (2 × n) =
big_sum (fun i ⇒ f (2 × i)%nat) n .+ big_sum (fun i ⇒ f (2 × i + 1)%nat) n.
Local Transparent Nat.mul.
Lemma vsum_split : ∀ {d} (n i : nat) (v : nat → Vector d),
(i < n)%nat →
big_sum v n = (big_sum v i) .+ v i .+ (big_sum (shift v (i + 1)) (n - 1 - i)).
Lemma vsum_eq_up_to_fswap : ∀ {d} n f (v : nat → Vector d) x y,
(x < n)%nat → (y < n)%nat →
big_sum (fun i ⇒ v (f i)) n = big_sum (fun i ⇒ v (fswap f x y i)) n.
Indexed Kronecker Product
Fixpoint vkron n (f : nat → Vector 2) : Vector (2 ^ n) :=
match n with
| 0 ⇒ I 1
| S n' ⇒ vkron n' f ⊗ f n'
end.
Lemma WF_vkron : ∀ n (f : nat → Vector 2),
(∀ i, (i < n)%nat → WF_Matrix (f i)) →
WF_Matrix (vkron n f).
#[export] Hint Resolve WF_vkron: wf_db.
Lemma WF_shift : ∀ m n j k (f : nat → Matrix m n),
(∀ i, WF_Matrix (f i)) →
WF_Matrix (shift f j k).
#[export] Hint Resolve WF_shift: wf_db.
Lemma vkron_extend_r : ∀ n f,
vkron n f ⊗ f n = vkron (S n) f.
Lemma vkron_extend_l : ∀ n (f : nat → Vector 2),
(∀ i, WF_Matrix (f i)) →
(f O) ⊗ vkron n (shift f 1) = vkron (S n) f.
Lemma kron_n_f_to_vec : ∀ n (A : Square 2) f,
n ⨂ A × f_to_vec n f = vkron n (fun k ⇒ A × ∣ f k ⟩ ).
Lemma Mscale_vkron_distr_r : ∀ n x (f : nat → Vector 2),
vkron n (fun i ⇒ x .* f i) = x ^ n .* vkron n f.
Lemma vkron_split : ∀ n i (f : nat → Vector 2),
(∀ j, WF_Matrix (f j)) →
i < n →
vkron n f = (vkron i f) ⊗ f i ⊗ (vkron (n - 1 - i) (shift f (i + 1))).
Lemma vkron_eq : ∀ n (f f' : nat → Vector 2),
(∀ i, i < n → f i = f' i) → vkron n f = vkron n f'.
Lemma basis_vector_prepend_0 : ∀ n k,
n ≠ 0 → k < n →
∣0⟩ ⊗ basis_vector n k = basis_vector (2 × n) k.
Lemma basis_vector_prepend_1 : ∀ n k,
n ≠ 0 → k < n →
∣1⟩ ⊗ basis_vector n k = basis_vector (2 × n) (k + n).
Local Opaque Nat.mul Nat.div Nat.modulo.
Lemma basis_vector_append_0 : ∀ n k,
n ≠ 0 → k < n →
basis_vector n k ⊗ ∣0⟩ = basis_vector (2 × n) (2 × k).
Lemma basis_vector_append_1 : ∀ n k,
n ≠ 0 → k < n →
basis_vector n k ⊗ ∣1⟩ = basis_vector (2 × n) (2 × k + 1).
Local Transparent Nat.mul Nat.div Nat.modulo.
Lemma kron_n_0_is_0_vector : ∀ (n:nat), n ⨂ ∣0⟩ = basis_vector (2 ^ n) O.
Lemma vkron_to_vsum1 : ∀ n (c : R),
n > 0 →
vkron n (fun k ⇒ ∣0⟩ .+ Cexp (c × 2 ^ (n - k - 1)) .* ∣1⟩) =
big_sum (fun k ⇒ Cexp (c × INR k) .* basis_vector (2 ^ n) k) (2 ^ n).
Fixpoint product (x y : nat → bool) n :=
match n with
| O ⇒ false
| S n' ⇒ xorb ((x n') && (y n')) (product x y n')
end.
Lemma product_comm : ∀ f1 f2 n, product f1 f2 n = product f2 f1 n.
Lemma product_update_oob : ∀ f1 f2 n b dim, (dim ≤ n)%nat →
product f1 (update f2 n b) dim = product f1 f2 dim.
Lemma product_0 : ∀ f n, product (fun _ : nat ⇒ false) f n = false.
Lemma nat_to_funbool_0 : ∀ n, nat_to_funbool n 0 = (fun _ ⇒ false).
Lemma nat_to_funbool_1 : ∀ n, nat_to_funbool n 1 = (fun x ⇒ x =? n - 1).
Local Open Scope R_scope.
Local Open Scope C_scope.
Local Opaque Nat.mul.
Lemma vkron_to_vsum2 : ∀ n (f : nat → bool),
(n > 0)%nat →
vkron n (fun k ⇒ ∣0⟩ .+ (-1) ^ f k .* ∣1⟩) =
big_sum
(fun k ⇒ (-1) ^ (product f (nat_to_funbool n k) n) .* basis_vector (2 ^ n) k) (2^n).
Local Transparent Nat.mul.
Lemma H_spec :
∀ b : bool, hadamard × ∣ b ⟩ = / √ 2 .* (∣ 0 ⟩ .+ (-1)^b .* ∣ 1 ⟩).
Lemma H_kron_n_spec : ∀ n x, (n > 0)%nat →
n ⨂ hadamard × f_to_vec n x =
/√(2 ^ n) .* big_sum (fun k ⇒ (-1) ^ (product x (nat_to_funbool n k) n) .* basis_vector (2 ^ n) k) (2 ^ n).
Lemma H0_kron_n_spec_alt : ∀ n, (n > 0)%nat →
n ⨂ hadamard × n ⨂ ∣0⟩ =
/√(2 ^ n) .* big_sum (fun k ⇒ basis_vector (2 ^ n) k) (2 ^ n).