Skip to content

Commit f08001a

Browse files
Parrondos 1d game
1 parent 3f411fb commit f08001a

20 files changed

+2091
-0
lines changed

parrondos_qwalk_1D.py

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# %%
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
from quantumwalks import run_quantum_walk_simulation
5+
from quantumwalks.discrete_walk import QuantumWalk
6+
from quantumwalks.utils.operators import create_shift_operators
7+
8+
def create_custom_coin(alpha: float, beta: float, gamma: float) -> np.ndarray:
9+
"""
10+
Create a custom coin operator U(α,β,γ) using vectorized operations.
11+
"""
12+
return np.array([
13+
[np.exp(1j * alpha) * np.cos(beta), -np.exp(-1j * gamma) * np.sin(beta)],
14+
[np.exp(1j * gamma) * np.sin(beta), np.exp(-1j * alpha) * np.cos(beta)]
15+
], dtype=np.complex128)
16+
17+
def calculate_lr_difference_alternating_coins(qw: QuantumWalk, coin_A: np.ndarray, coin_B: np.ndarray) -> np.ndarray:
18+
"""
19+
Calculate P_L - P_R for each step of the walk using alternating coins A and B.
20+
"""
21+
# Initialize state
22+
posn0 = np.zeros(qw.P)
23+
posn0[qw.N] = 1
24+
psi = np.kron(posn0, qw.initial_coin_state)
25+
26+
# Pre-allocate arrays
27+
differences = np.zeros(qw.N + 1)
28+
positions = np.arange(-qw.N, qw.N + 1)
29+
30+
# Create measurement operators matrix once
31+
measurement_ops = np.array([
32+
np.kron(np.outer(np.eye(qw.P)[i], np.eye(qw.P)[i]), np.eye(2))
33+
for i in range(qw.P)
34+
])
35+
36+
# Create shift operators using the utility function
37+
shift_plus, shift_minus = create_shift_operators(qw.P)
38+
shift_op = (np.kron(shift_plus, np.outer(qw.coin0, qw.coin0)) +
39+
np.kron(shift_minus, np.outer(qw.coin1, qw.coin1)))
40+
41+
# Calculate evolution operators for both coins
42+
U_A = shift_op @ np.kron(np.eye(qw.P), coin_A)
43+
U_B = shift_op @ np.kron(np.eye(qw.P), coin_B)
44+
45+
# Calculate for each step
46+
for step in range(qw.N + 1):
47+
# Vectorized probability calculation
48+
projections = measurement_ops @ psi
49+
prob = np.real(np.sum(projections * np.conjugate(projections), axis=1))
50+
51+
# Vectorized P_L and P_R calculation
52+
P_L = np.sum(prob[positions < 0])
53+
P_R = np.sum(prob[positions >= 0])
54+
differences[step] = P_L - P_R
55+
56+
# Evolve state with alternating coin operators
57+
if step < qw.N:
58+
if step % 2 == 0:
59+
psi = U_A @ psi # Apply coin A
60+
else:
61+
psi = U_B @ psi # Apply coin B
62+
63+
return differences, prob # Return both differences and final probability distribution
64+
65+
def run_simulation_alternating_coins(steps: int,
66+
alpha_A: float, beta_A: float, gamma_A: float,
67+
alpha_B: float, beta_B: float, gamma_B: float):
68+
"""
69+
Run simulation with alternating coins A and B.
70+
"""
71+
# Create both coin operators
72+
coin_A = create_custom_coin(alpha_A, beta_A, gamma_A)
73+
coin_B = create_custom_coin(alpha_B, beta_B, gamma_B)
74+
initial_state = np.array([1, -1], dtype=np.complex128) / np.sqrt(2)
75+
76+
print(f"Running quantum walk simulation with alternating coins:")
77+
print(f"Coin A parameters: α={alpha_A:.2f}, β={beta_A:.2f}, γ={gamma_A:.2f}")
78+
print(f"Coin B parameters: α={alpha_B:.2f}, β={beta_B:.2f}, γ={gamma_B:.2f}")
79+
80+
# Create quantum walk object (using coin_A as default)
81+
qw = QuantumWalk(steps, initial_state, coin_A)
82+
83+
# Calculate differences and probabilities using alternating coins
84+
differences, prob = calculate_lr_difference_alternating_coins(qw, coin_A, coin_B)
85+
86+
# Plot results
87+
plot_results(qw, prob, 0.0, differences, steps) # Using 0.0 as execution time placeholder
88+
89+
return qw, differences, prob
90+
91+
def plot_results(qw: QuantumWalk, prob: np.ndarray,
92+
exec_time: float, differences: np.ndarray, steps: int):
93+
"""
94+
Plot both probability distribution and P_L - P_R differences.
95+
"""
96+
# Plot probability distribution
97+
positions = np.arange(-qw.N, qw.N + 1)
98+
99+
plt.figure(figsize=(12, 8))
100+
plt.plot(positions, prob, 'b-', label='Probability', linewidth=1.5)
101+
plt.plot(positions, prob, 'ro', markersize=4)
102+
plt.fill_between(positions, prob, alpha=0.3)
103+
plt.grid(True, alpha=0.3)
104+
plt.xlabel('Position', fontsize=12)
105+
plt.ylabel('Probability', fontsize=12)
106+
plt.title(f'Quantum Walk Distribution after {steps} steps\n(Alternating Coins)', fontsize=14)
107+
plt.legend()
108+
plt.tight_layout()
109+
plt.show()
110+
111+
# Plot P_L - P_R differences
112+
plt.figure(figsize=(12, 8))
113+
x = np.arange(steps + 1)
114+
plt.plot(x, differences, 'b-', label='P_L - P_R', linewidth=1.5)
115+
plt.plot(x, differences, 'ro', markersize=4)
116+
117+
# Set y-axis range from -1 to 1
118+
plt.ylim(-1, 1)
119+
120+
plt.grid(True, alpha=0.3)
121+
plt.xlabel('Step', fontsize=12)
122+
plt.ylabel('P_L - P_R', fontsize=12)
123+
plt.title('Difference between Left and Right Probabilities\n(Alternating Coins)', fontsize=14)
124+
plt.legend()
125+
plt.tight_layout()
126+
plt.show()
127+
128+
129+
# %%
130+
131+
if __name__ == "__main__":
132+
# Set parameters
133+
steps = 800
134+
135+
# Parameters for Coin A
136+
alpha_A = -51.0/180 * np.pi # Converting to radians
137+
beta_A = 45.0/180 * np.pi
138+
gamma_A = 0.0/180 * np.pi
139+
140+
# Parameters for Coin B
141+
alpha_B = 0.0/180 * np.pi
142+
beta_B = 88.0/180 * np.pi
143+
gamma_B = -16.0/180 * np.pi
144+
145+
# Run simulation with alternating coins
146+
qw, differences, prob = run_simulation_alternating_coins(
147+
steps,
148+
alpha_A, beta_A, gamma_A,
149+
alpha_B, beta_B, gamma_B
150+
)
151+
152+
# Print some statistics
153+
positions = np.arange(-qw.N, qw.N + 1)
154+
mean_pos = np.average(positions, weights=prob)
155+
std_dev = np.sqrt(np.average((positions - mean_pos)**2, weights=prob))
156+
157+
print("\nFinal Statistics:")
158+
print(f"Mean Position: {mean_pos:.4f}")
159+
print(f"Standard Deviation: {std_dev:.4f}")
160+
print(f"Max Probability: {np.max(prob):.4f}")
161+
162+
# %%
163+
164+
165+

0 commit comments

Comments
 (0)