别再死记硬背了!用Python+NumPy手把手模拟量子叠加态与纠缠态(附代码)
用Python+NumPy零基础玩转量子叠加态与纠缠态:从代码到可视化
量子力学常被贴上"高深莫测"的标签,但今天我们要用Python和NumPy这把钥匙,打开量子世界的大门。想象一下,在Jupyter Notebook里亲手创建量子叠加态,观察测量时的坍缩现象,甚至模拟两个量子比特的纠缠——这一切都不需要复杂的数学推导,只需基础的Python语法和一颗好奇心。
1. 量子编程环境搭建与基础概念
在开始量子模拟之前,让我们先准备好Python环境。推荐使用Google Colab或本地安装的Jupyter Notebook,它们能完美支持我们后续的可视化需求。以下是需要安装的库:
pip install numpy matplotlib ipywidgets量子计算中最基础的单位是量子比特(qubit),与经典比特不同,它可以同时处于0和1的叠加状态。在数学上,我们用向量表示量子态:
- |0⟩ = [1, 0]ᵀ
- |1⟩ = [0, 1]ᵀ
而叠加态则是这两个基态的线性组合:ψ = α|0⟩ + β|1⟩,其中|α|² + |β|² = 1。这个归一化条件保证了测量概率的总和为1。
import numpy as np # 定义基态 zero_state = np.array([1, 0]) one_state = np.array([0, 1]) # 创建叠加态 def create_superposition(alpha, beta): return alpha * zero_state + beta * one_state # 示例:创建等概率叠加态 equal_superposition = create_superposition(1/np.sqrt(2), 1/np.sqrt(2)) print("等概率叠加态:", equal_superposition)2. 模拟量子叠加态与测量坍缩
叠加态最神奇的特性在于测量时的坍缩。当我们对一个叠加态进行测量时,它会以一定概率坍缩到其中一个基态。让我们用NumPy模拟这个过程:
def measure_qubit(state): probabilities = np.abs(state)**2 outcome = np.random.choice([0, 1], p=probabilities) return zero_state if outcome == 0 else one_state # 模拟测量过程 initial_state = create_superposition(0.6, 0.8) # 需要归一化 normalized_state = initial_state / np.linalg.norm(initial_state) print("测量前状态:", normalized_state) for _ in range(5): print("测量结果:", measure_qubit(normalized_state))为了更直观地理解,我们可以绘制量子态的概率分布:
import matplotlib.pyplot as plt def plot_probabilities(state): labels = ['|0⟩', '|1⟩'] probs = np.abs(state)**2 plt.bar(labels, probs) plt.ylabel('Probability') plt.title('Quantum State Probabilities') plt.show() plot_probabilities(normalized_state)量子与经典概率的关键区别:
- 经典概率:系统"已经"处于某个状态,只是我们不知道
- 量子概率:系统"真正"同时处于多个状态,直到测量才确定
3. 构建双量子比特系统与纠缠态
当我们将两个量子比特组合在一起时,最有趣的现象——量子纠缠就出现了。纠缠态是指两个量子比特的状态无法单独描述,必须作为一个整体来看待。
首先,我们需要了解双量子比特系统的基态:
- |00⟩ = [1, 0, 0, 0]ᵀ
- |01⟩ = [0, 1, 0, 0]ᵀ
- |10⟩ = [0, 0, 1, 0]ᵀ
- |11⟩ = [0, 0, 0, 1]ᵀ
著名的贝尔态就是最大纠缠态的一个例子:
# 创建贝尔态 (|00⟩ + |11⟩)/√2 bell_state = np.array([1, 0, 0, 1]) / np.sqrt(2)我们可以模拟对其中一个量子比特的测量如何影响另一个:
def measure_bell_state(state): # 测量第一个量子比特 prob_0 = np.abs(state[0])**2 + np.abs(state[1])**2 first_outcome = np.random.choice([0, 1], p=[prob_0, 1-prob_0]) if first_outcome == 0: # 坍缩到|00⟩或|01⟩ second_state = state[:2] / np.sqrt(np.sum(np.abs(state[:2])**2)) else: # 坍缩到|10⟩或|11⟩ second_state = state[2:] / np.sqrt(np.sum(np.abs(state[2:])**2)) second_outcome = np.random.choice([0, 1], p=np.abs(second_state)**2) return first_outcome, second_outcome # 进行多次测量实验 results = [measure_bell_state(bell_state) for _ in range(100)] first_outcomes = [r[0] for r in results] second_outcomes = [r[1] for r in results] print("第一个量子比特测量结果为0的比例:", sum(first_outcomes)/100) print("当第一个为0时第二个为0的比例:", sum(1 for r in results if r[0]==0 and r[1]==0)/sum(1 for r in results if r[0]==0))4. 可视化量子门操作与状态演化
量子门是操作量子态的基本工具,类似于经典逻辑门。让我们实现几个基本的量子门并观察它们对量子态的影响。
Hadamard门:创建叠加态
def hadamard(state): H = np.array([[1, 1], [1, -1]]) / np.sqrt(2) return np.dot(H, state) # 应用Hadamard门 new_state = hadamard(zero_state) print("Hadamard门应用后的状态:", new_state) plot_probabilities(new_state)CNOT门:创建纠缠态
def cnot(state): # state应为4维向量 CNOT = np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0] ]) return np.dot(CNOT, state) # 创建纠缠态 entangled_state = cnot(np.kron(hadamard(zero_state), zero_state)) print("纠缠态:", entangled_state)为了更直观地展示量子门的作用,我们可以使用布洛赫球表示:
from mpl_toolkits.mplot3d import Axes3D def plot_bloch_vector(state): # 将状态转换为布洛赫向量 alpha, beta = state x = 2 * np.real(alpha * np.conj(beta)) y = 2 * np.imag(alpha * np.conj(beta)) z = np.abs(alpha)**2 - np.abs(beta)**2 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 绘制球体 u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j] x_sphere = np.cos(u)*np.sin(v) y_sphere = np.sin(u)*np.sin(v) z_sphere = np.cos(v) ax.plot_wireframe(x_sphere, y_sphere, z_sphere, color="gray", alpha=0.2) # 绘制向量 ax.quiver(0, 0, 0, x, y, z, color='red', arrow_length_ratio=0.1) ax.set_xlim([-1,1]) ax.set_ylim([-1,1]) ax.set_zlim([-1,1]) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.title('Bloch Sphere Representation') plt.show() plot_bloch_vector(hadamard(zero_state))5. 量子算法初探:Deutsch-Jozsa算法
作为量子计算优势的简单示例,让我们实现Deutsch-Jozsa算法。这个算法可以仅用一次查询就确定一个函数是常函数还是平衡函数,而经典算法在最坏情况下需要2ⁿ⁻¹ +1次查询。
def deutsch_jozsa(f): # 初始化两个量子比特 |01⟩ state = np.kron(zero_state, one_state) # 应用Hadamard门到两个量子比特 H = hadamard(np.eye(2)) # 扩展Hadamard到2-qubit state = np.kron(H, H) @ state # 应用Oracle(函数f) # 这里我们实现一个平衡函数f(x) = x Uf = np.array([ [0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) state = Uf @ state # 再次应用Hadamard到第一个量子比特 state = np.kron(H, np.eye(2)) @ state # 测量第一个量子比特 prob_0 = np.abs(state[0])**2 + np.abs(state[1])**2 return 0 if np.random.random() < prob_0 else 1 # 测试算法 result = deutsch_jozsa(lambda x: x) # 平衡函数 print("算法结果为:", result) if result == 1: print("函数是平衡的") else: print("函数是常数的")这个简单的例子展示了量子并行性的威力——我们能够同时评估函数在多个输入上的值。
