Skip to content

Commit 39d4855

Browse files
committed
more codes
1 parent cf1e46d commit 39d4855

File tree

3 files changed

+220
-2
lines changed

3 files changed

+220
-2
lines changed

doc/src/FuturePlans/programs/pcodes/qft5.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ def update(i):
130130
step_label.set_text(self.animation_labels[i])
131131
return bar
132132

133-
ani = FuncAnimation(fig, update, frames=len(self.animation_frames),
134-
interval=interval, blit=False, repeat=False)
133+
ani = FuncAnimation(fig, update, frames=len(self.animation_frames),interval=interval, blit=False, repeat=False)
135134

136135
if save_path.endswith(".gif"):
137136
ani.save(save_path, writer='pillow')
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from matplotlib.animation import FuncAnimation
4+
from matplotlib import cm
5+
6+
class QuantumPhaseEstimation:
7+
def __init__(self, n_qubits, unitary, eigenstate, inverse=False):
8+
self.n_qubits = n_qubits
9+
self.N = 2 ** n_qubits
10+
self.unitary = unitary # Unitary operator U
11+
self.eigenstate = eigenstate # Eigenstate |ψ⟩
12+
self.inverse = inverse # Whether to reverse the QFT
13+
self.state = np.zeros(self.N, dtype=complex)
14+
self.state[0] = 1.0 # Initialize ancillary qubits to |0...0⟩
15+
16+
def apply_single_qubit_gate(self, gate, target):
17+
I = np.eye(2)
18+
ops = [I] * self.n_qubits
19+
ops[target] = gate
20+
U = ops[0]
21+
for op in ops[1:]:
22+
U = np.kron(U, op)
23+
self.state = U @ self.state
24+
25+
def hadamard(self):
26+
return np.array([[1, 1], [1, -1]]) / np.sqrt(2)
27+
28+
def apply_controlled_unitary(self, control, target, exp_power):
29+
"""Apply controlled unitary operation U^(2^j)."""
30+
U = np.eye(self.N, dtype=complex)
31+
for i in range(self.N):
32+
b = format(i, f'0{self.n_qubits}b')
33+
if b[self.n_qubits - 1 - control] == '1':
34+
U[i, i] = np.exp(1j * (np.pi / (2 ** exp_power)))
35+
self.state = U @ self.state
36+
37+
def apply_qft(self, inverse=False):
38+
"""Apply Quantum Fourier Transform on ancillary qubits."""
39+
for target in range(self.n_qubits):
40+
idx = self.n_qubits - 1 - target
41+
for offset in range(1, self.n_qubits - target):
42+
control = self.n_qubits - 1 - (target + offset)
43+
angle = np.pi / (2 ** offset)
44+
if inverse:
45+
angle *= -1
46+
self.apply_controlled_unitary(control, idx, angle)
47+
self.apply_single_qubit_gate(self.hadamard(), idx)
48+
49+
self.swap_registers()
50+
51+
def swap_registers(self):
52+
perm = [int(format(i, f'0{self.n_qubits}b')[::-1], 2) for i in range(self.N)]
53+
self.state = self.state[perm]
54+
55+
def measure(self):
56+
"""Measure the ancillary qubits."""
57+
probs = np.abs(self.state) ** 2
58+
outcomes = np.random.choice(self.N, size=1024, p=probs)
59+
counts = {}
60+
for o in outcomes:
61+
bitstring = format(o, f'0{self.n_qubits}b')
62+
counts[bitstring] = counts.get(bitstring, 0) + 1
63+
return counts
64+
65+
def plot_probability_distribution(self, results):
66+
bitstrings = sorted(results.keys())
67+
counts = [results[b] for b in bitstrings]
68+
plt.bar(bitstrings, counts)
69+
plt.xlabel("Bitstring")
70+
plt.ylabel("Counts")
71+
plt.title("QPE Measurement Results")
72+
plt.xticks(rotation=45)
73+
plt.tight_layout()
74+
plt.show()
75+
76+
def apply_phase_estimation(self):
77+
"""Perform Quantum Phase Estimation (QPE)."""
78+
# Apply Hadamard to all ancillary qubits
79+
for target in range(self.n_qubits):
80+
self.apply_single_qubit_gate(self.hadamard(), target)
81+
82+
# Apply controlled unitaries (U^(2^j))
83+
for j in range(self.n_qubits):
84+
self.apply_controlled_unitary(j, self.n_qubits, j)
85+
86+
# Apply QFT
87+
self.apply_qft(inverse=True)
88+
89+
# Measure the ancillary qubits
90+
results = self.measure()
91+
self.plot_probability_distribution(results)
92+
93+
# Example Unit and Eigenstate
94+
def unitary_operator():
95+
# Simple controlled-phase gate (for example)
96+
return np.array([[1, 0], [0, np.exp(1j * np.pi / 4)]], dtype=complex)
97+
98+
def eigenstate():
99+
return np.array([1, 0], dtype=complex) # eigenstate |1⟩
100+
101+
# ---------------------------
102+
# Example usage
103+
# ---------------------------
104+
if __name__ == "__main__":
105+
n_qubits = 3
106+
qpe = QuantumPhaseEstimation(n_qubits, unitary_operator(), eigenstate())
107+
qpe.apply_phase_estimation()
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from matplotlib.animation import FuncAnimation
4+
from matplotlib import cm
5+
6+
7+
8+
def unitary_operator():
9+
# Controlled Phase Gate (CP) with a phase of pi/4
10+
return np.array([[1, 0, 0, 0],
11+
[0, 1, 0, 0],
12+
[0, 0, np.exp(1j * np.pi / 4), 0],
13+
[0, 0, 0, np.exp(1j * np.pi / 4)]], dtype=complex)
14+
15+
def eigenstate():
16+
# Superposition state |ψ⟩ = (|0⟩ + |1⟩)/√2
17+
return np.array([1/np.sqrt(2), 1/np.sqrt(2)], dtype=complex)
18+
19+
class QuantumPhaseEstimation:
20+
def __init__(self, n_qubits, unitary, eigenstate, inverse=False):
21+
self.n_qubits = n_qubits
22+
self.N = 2 ** n_qubits
23+
self.unitary = unitary # Unitary operator U
24+
self.eigenstate = eigenstate # Eigenstate |ψ⟩
25+
self.inverse = inverse # Whether to reverse the QFT
26+
self.state = np.zeros(self.N, dtype=complex)
27+
self.state[0] = 1.0 # Initialize ancillary qubits to |0...0⟩
28+
29+
def apply_single_qubit_gate(self, gate, target):
30+
I = np.eye(2)
31+
ops = [I] * self.n_qubits
32+
ops[target] = gate
33+
U = ops[0]
34+
for op in ops[1:]:
35+
U = np.kron(U, op)
36+
self.state = U @ self.state
37+
38+
def hadamard(self):
39+
return np.array([[1, 1], [1, -1]]) / np.sqrt(2)
40+
41+
def apply_controlled_unitary(self, control, target, exp_power):
42+
"""Apply controlled unitary operation U^(2^j)."""
43+
U = np.eye(self.N, dtype=complex)
44+
for i in range(self.N):
45+
b = format(i, f'0{self.n_qubits}b')
46+
if b[self.n_qubits - 1 - control] == '1':
47+
U[i, i] = np.exp(1j * (np.pi / (2 ** exp_power)))
48+
self.state = U @ self.state
49+
50+
def apply_qft(self, inverse=False):
51+
"""Apply Quantum Fourier Transform on ancillary qubits."""
52+
for target in range(self.n_qubits):
53+
idx = self.n_qubits - 1 - target
54+
for offset in range(1, self.n_qubits - target):
55+
control = self.n_qubits - 1 - (target + offset)
56+
angle = np.pi / (2 ** offset)
57+
if inverse:
58+
angle *= -1
59+
self.apply_controlled_unitary(control, idx, angle)
60+
self.apply_single_qubit_gate(self.hadamard(), idx)
61+
62+
self.swap_registers()
63+
64+
def swap_registers(self):
65+
perm = [int(format(i, f'0{self.n_qubits}b')[::-1], 2) for i in range(self.N)]
66+
self.state = self.state[perm]
67+
68+
def measure(self):
69+
"""Measure the ancillary qubits."""
70+
probs = np.abs(self.state) ** 2
71+
outcomes = np.random.choice(self.N, size=1024, p=probs)
72+
counts = {}
73+
for o in outcomes:
74+
bitstring = format(o, f'0{self.n_qubits}b')
75+
counts[bitstring] = counts.get(bitstring, 0) + 1
76+
return counts
77+
78+
def plot_probability_distribution(self, results):
79+
bitstrings = sorted(results.keys())
80+
counts = [results[b] for b in bitstrings]
81+
plt.bar(bitstrings, counts)
82+
plt.xlabel("Bitstring")
83+
plt.ylabel("Counts")
84+
plt.title("QPE Measurement Results")
85+
plt.xticks(rotation=45)
86+
plt.tight_layout()
87+
plt.show()
88+
89+
def apply_phase_estimation(self):
90+
"""Perform Quantum Phase Estimation (QPE)."""
91+
# Apply Hadamard to all ancillary qubits
92+
for target in range(self.n_qubits):
93+
self.apply_single_qubit_gate(self.hadamard(), target)
94+
95+
# Apply controlled unitaries (U^(2^j))
96+
for j in range(self.n_qubits):
97+
self.apply_controlled_unitary(j, self.n_qubits, j)
98+
99+
# Apply QFT
100+
self.apply_qft(inverse=True)
101+
102+
# Measure the ancillary qubits
103+
results = self.measure()
104+
self.plot_probability_distribution(results)
105+
106+
# ---------------------------
107+
# Example usage
108+
# ---------------------------
109+
if __name__ == "__main__":
110+
n_qubits = 3 # Number of ancillary qubits
111+
qpe = QuantumPhaseEstimation(n_qubits, unitary_operator(), eigenstate())
112+
qpe.apply_phase_estimation()

0 commit comments

Comments
 (0)