简介:这份资源是《量子计算和量子信息》教材的配套课后答案,面向正在学习量子计算与量子信息理论的高年级本科生、研究生及自学者,帮助读者在啃读尼尔森与丘的经典教材时核对习题思路、验证推导结论。内容由goropikari在GitHub发布的非官方解题手册整理而成,覆盖量子力学基础、量子噪音与量子操作、量子信息的距离度量、熵与信息等核心章节,并附有勘误清单,指出如第101页式2.150、第408页式9.49、第409页习题9.12及第411页习题9.16等处可能存在的错误,提醒读者自行验证。资源包为单个PDF文件,约466KB,轻量便于随时查阅。目前已有1355人学习下载,适合需要对照习题、排查推导细节并培养独立思考能力的读者参考使用。
1. 从一道课后题卡壳说起:量子计算和量子信息课后答案到底该怎么用
很多人第一次翻开《量子计算和量子信息》这本书,翻到第二章就卡住了。线性代数那套狄拉克符号还没消化完,紧接着就是量子门、纠缠态、密度算符,课后题更是让人怀疑自己是不是选错了方向。我见过不少同学,书看了三遍,题一道做不出来,最后只能去网上搜答案,搜到的还多半是零散截图或者语焉不详的几行字。
这个标题指向的需求非常明确:你手上有这本书,你正在啃课后习题,你需要一份能让你看懂“为什么这么解”的参考,而不是一份让你抄完就忘的答案。尼尔森和赵千川这个组合,在量子信息领域是绕不开的经典教材,它的课后题覆盖了从基础线性代数到量子纠错码的完整链条。但答案本身不是目的,答案是你验证自己理解是否到位的工具。如果你只是把答案抄一遍交上去,那这门课你等于没学。
我写这篇东西,是想把“怎么用课后答案真正学会量子计算”这件事拆开讲清楚。适合谁看?正在上这门课的高年级本科生、刚进实验室要补量子信息基础的研究生,以及想自学但被习题卡住的开发者。如果你指望找到一份万能答案库,那可能会失望;但如果你想搞清楚每道题背后的算符逻辑、测量假设和推导路径,接下来的内容应该能帮到你。
2. 先搞清楚这本书的习题体系:从线性代数到量子纠错码
2.1 课后题到底在考什么:四层能力递进
这本书的习题不是随便凑数的。我把它大致分成四层。第一层是线性代数的量子语言化,比如把矩阵运算翻译成狄拉克符号,把张量积写成直积态的形式。第二层是量子门和电路的基本操作,比如验证某个门是酉矩阵、推导控制门的分解。第三层是量子信息论的核心概念,比如纠缠熵、密度算符的偏迹、贝尔不等式的推导。第四层是量子纠错和容错,比如稳定子码的生成元、错误综合征的测量。
很多同学卡在第二层就放弃了,原因是第一层的符号没练熟。我一般建议,拿到一道题先判断它属于哪一层。如果是第一层,直接回到书后附录的线性代数复习;如果是第三层,先确认自己是否理解了密度算符的物理意义。答案里如果只给结果不给中间步骤,那这份答案对你来说价值有限。
2.2 答案的三种来源和各自的坑
目前能见到的课后答案大致有三种。第一种是网上流传的手写扫描版,优点是步骤详细,缺点是字迹模糊、符号不统一,有时候还会跳步。第二种是某些课程网站上的官方解答,质量最高,但往往只覆盖部分习题,而且不对外公开。第三种是各种论坛里的讨论帖,碎片化严重,一道题可能有好几种解法,但没人告诉你哪种是标准路径。
我踩过的坑是:拿手写版对答案,结果发现自己的符号体系和它不一样,比如它用 (|0\rangle) 表示自旋向上,我用 (|+\rangle),对完之后反而更糊涂了。后来我养成一个习惯,不管看哪份答案,先看它的符号约定是否和教材一致。如果不一致,要么换算,要么直接放弃这份答案。另外,手写版里经常出现把偏迹写成迹、把张量积顺序搞反的情况,如果你不自己推一遍,根本发现不了。
2.3 用答案反推知识漏洞的检查清单
答案不是用来抄的,是用来做诊断的。我一般会按下面这个清单走一遍。第一,看答案的第一步用了什么定理或定义,如果这个定理我记不清,立刻回去翻书。第二,看答案的中间步骤有没有跳步,如果跳了,我自己补上,补不上的地方就是漏洞。第三,看答案的最终结果和我的是否一致,如果不一致,先检查符号约定,再检查计算过程。第四,看答案有没有用到教材里没提但习题里暗示的技巧,比如用施密特分解判断纠缠。
这个清单看起来简单,但坚持做下来,你会发现自己的薄弱环节非常集中。比如很多人卡在偏迹的计算上,其实就是没理解“对某个子系统求迹”这个操作在矩阵元层面怎么实现。一旦你通过答案反推出这个漏洞,再去找对应的章节补,效率比从头看书高得多。
3. 用Python把抽象算符变成可验证的矩阵:最小复现环境搭建
3.1 为什么建议用NumPy而不是手算
这本书的习题里,很多操作手算容易出错,比如计算两个量子门的张量积、求密度矩阵的偏迹、验证贝尔态的纠缠熵。手算当然能练基本功,但当你需要验证自己的推导是否正确时,用NumPy写几行代码跑一下,比反复检查草稿纸快得多。而且量子计算的本质就是线性代数,NumPy的数组操作天然适合表达量子态和算符。
我一般会建议初学者先手算一遍,再用代码验证。如果两者结果一致,说明你掌握了;如果不一致,代码会告诉你哪一步的矩阵元算错了。这不是偷懒,是把精力从繁琐的算术转移到概念理解上。
3.2 搭建最小验证环境:安装与基础约定
环境很简单,Python 3.8以上,装好NumPy就行。如果你还想画布洛赫球或者做可视化,可以加Matplotlib,但验证习题不需要。我习惯在脚本开头统一符号约定:用列向量表示量子态,用二维数组表示算符,张量积用np.kron,偏迹自己写一个函数。
import numpy as np # 基础态定义:|0> = [1,0]^T, |1> = [0,1]^T ket0 = np.array([[1], [0]], dtype=complex) ket1 = np.array([[0], [1]], dtype=complex) # 常用门 I = np.eye(2, dtype=complex) X = np.array([[0, 1], [1, 0]], dtype=complex) H = np.array([[1, 1], [1, -1]], dtype=complex) / np.sqrt(2) # 张量积:两个算符的直积 def tensor(op_list): result = op_list[0] for op in op_list[1:]: result = np.kron(result, op) return result # 偏迹:对多体系统的某个子系统求迹 def partial_trace(rho, dims, keep): """ rho: 密度矩阵 dims: 各子系统维度列表,如[2,2] keep: 要保留的子系统索引,如0表示保留第一个 """ n = len(dims) reshaped = rho.reshape(dims + dims) # 对要丢弃的子系统求迹 trace_over = [i for i in range(n) if i != keep] for idx in sorted(trace_over, reverse=True): reshaped = np.trace(reshaped, axis1=idx, axis2=idx + n) n -= 1 return reshaped.reshape(dims[keep], dims[keep])这段代码里,tensor函数用来构造多量子比特系统的算符,比如tensor([H, I])就是H作用在第一个比特上、第二个比特不变。partial_trace函数是习题里出现频率最高的操作之一,比如从贝尔态(|\Phi^+\rangle = (|00\rangle + |11\rangle)/\sqrt{2})的密度矩阵中求出第一个比特的约化密度矩阵。注意dims参数要按子系统顺序写,keep是你要保留的那个子系统的索引。
3.3 用代码验证一道典型习题:贝尔态的约化密度矩阵
教材里有一道经典题:求贝尔态(|\Phi^+\rangle)的约化密度矩阵,并验证它是否是最大混合态。手算的过程是:先写出密度矩阵(\rho = |\Phi^+\rangle\langle\Phi^+|),然后对第二个比特求偏迹。用上面的代码可以这样验证:
# 构造贝尔态 |Phi+> = (|00> + |11>) / sqrt(2) phi_plus = (tensor([ket0, ket0]) + tensor([ket1, ket1])) / np.sqrt(2) rho = phi_plus @ phi_plus.conj().T # 对第二个比特求偏迹,保留第一个比特 rho_A = partial_trace(rho, dims=[2, 2], keep=0) print("约化密度矩阵 rho_A:") print(rho_A) print("是否为最大混合态:", np.allclose(rho_A, I / 2))运行结果是rho_A等于单位矩阵的一半,也就是最大混合态。这个结果说明贝尔态的两个子系统各自都是完全混合的,但整体是纯态,这就是纠缠的典型特征。如果你手算的结果不是这个,那大概率是在偏迹的矩阵元求和时漏了项。代码的好处是,你可以把中间步骤打印出来,逐项对照。
参数说明:dims=[2,2]表示两个量子比特,每个维度是2。keep=0表示保留第一个比特。如果你要保留第二个比特,改成keep=1即可。np.allclose用来判断两个矩阵是否在数值误差范围内相等,因为浮点运算会有微小偏差。
4. 避坑:课后答案使用中的五个血泪教训
4.1 符号约定不一致导致全盘对不上
现象:你算出的结果和答案差一个负号或者差一个转置,反复检查计算过程也没发现错误。原因:不同来源的答案可能采用不同的符号约定,比如有的把泡利矩阵(\sigma_y)定义为(\begin{pmatrix}0 & -i \ i & 0\end{pmatrix}),有的定义为(\begin{pmatrix}0 & i \ -i & 0\end{pmatrix})。解决:在看任何答案之前,先确认它的泡利矩阵、量子门矩阵、基矢顺序是否和教材一致。如果不一致,要么换算,要么换一份答案。
4.2 跳步太多导致中间逻辑断裂
现象:答案从第一步直接跳到第三步,中间那步“显然”的推导你死活想不出来。原因:手写答案或者论坛讨论往往省略了“简单”的代数运算,但这些运算对初学者来说并不简单。解决:遇到跳步,不要硬看,自己拿纸推一遍。如果推不出来,去教材里找对应的定理或例题。推出来之后,把这一步补在答案旁边,这份答案才真正属于你。
4.3 把偏迹当成普通求迹
现象:计算约化密度矩阵时,你直接对整个密度矩阵求迹,得到一个数,而不是一个矩阵。原因:偏迹是对某个子系统求迹,保留另一个子系统的矩阵结构。普通求迹是对整个系统求迹,得到标量。解决:记住偏迹的矩阵元公式((\rho_A){ij} = \sum_k \rho{ik,jk}),其中(i,j)是保留子系统的指标,(k)是丢弃子系统的指标。用代码验证时,检查partial_trace函数的keep参数是否指向正确的子系统。
4.4 忽略测量假设导致概率算错
现象:题目要求计算某个测量结果出现的概率,你算出的概率大于1或者为负数。原因:量子测量必须用一组完备的测量算符来描述,比如投影测量要求(\sum_m M_m^\dagger M_m = I)。如果你用的算符不满足这个条件,概率自然不对。解决:先检查测量算符是否完备,再计算(p(m) = \langle\psi|M_m^\dagger M_m|\psi\rangle)。如果题目给的是投影测量,确认投影算符是否正交且完备。
4.5 把答案当唯一标准,不敢质疑
现象:你发现答案的某个结果和教材里的定理矛盾,但不敢怀疑答案,反而怀疑自己。原因:网上流传的答案质量参差不齐,有些是学生作业,本身就有错误。解决:用教材里的定理和代码验证双重确认。如果代码跑出来和答案不一致,而你的推导又和教材一致,那大概率是答案错了。这时候相信自己的推导,但也要把答案的错误记下来,避免下次再被误导。
5. 从课后题到真实计算:用稳定子码习题打通量子纠错的理解
5.1 稳定子码习题为什么让人头疼
稳定子码是这本书后半部分的重点,也是课后题里最容易让人放弃的部分。题目通常给你几个生成元,让你求码空间、错误综合征、逻辑算符。手算的话,你需要处理多个泡利算符的对易关系,还要在(2^n)维希尔伯特空间里找同时本征态。很多人在这里翻车,不是因为概念不懂,而是因为算符太多、符号太乱。
我一般会建议用代码把生成元矩阵化,然后通过求解本征方程来找到码空间。这样你不需要手动推导所有对易关系,代码会帮你算。但前提是你得理解稳定子码的定义:码空间是所有生成元同时本征值为+1的本征态张成的空间。
5.2 用代码求稳定子码的码空间和错误综合征
假设题目给出三个生成元(g_1 = X_1X_2X_3),(g_2 = Z_1Z_2Z_3),(g_3 = X_1X_2),要求码空间和错误(E = Z_1)的综合征。先构造这些算符的矩阵表示:
# 定义单比特泡利矩阵 X = np.array([[0, 1], [1, 0]], dtype=complex) Z = np.array([[1, 0], [0, -1]], dtype=complex) I2 = np.eye(2, dtype=complex) # 构造三比特算符 g1 = tensor([X, X, X]) g2 = tensor([Z, Z, Z]) g3 = tensor([X, X, I2]) # 验证生成元之间的对易关系 def commutator(A, B): return A @ B - B @ A print("g1和g2的对易子是否为零:", np.allclose(commutator(g1, g2), 0)) print("g1和g3的对易子是否为零:", np.allclose(commutator(g1, g3), 0)) print("g2和g3的对易子是否为零:", np.allclose(commutator(g2, g3), 0))运行结果会告诉你哪些生成元对易、哪些反对易。稳定子码要求所有生成元两两对易,如果出现反对易,说明这组生成元不构成稳定子群。接下来求码空间,也就是找同时满足(g_i|\psi\rangle = |\psi\rangle)的态。这可以通过构造投影算符(P = \prod_i (I + g_i)/2)来实现:
# 构造投影算符到码空间 P = (np.eye(8) + g1) @ (np.eye(8) + g2) @ (np.eye(8) + g3) / 8 # 求投影算符的秩,即码空间的维度 rank = np.linalg.matrix_rank(P) print("码空间维度:", rank) # 求码空间的一组基 eigenvalues, eigenvectors = np.linalg.eigh(P) # 取本征值接近1的本征向量 code_states = eigenvectors[:, eigenvalues > 0.5] print("码空间基向量数量:", code_states.shape[1])参数说明:np.eye(8)是三比特系统的单位矩阵,维度是(2^3=8)。投影算符的秩告诉你码空间有几个正交基。如果秩是2,说明这个码编码了1个逻辑量子比特。错误综合征的计算是看错误算符和生成元的对易关系:如果(E)和(g_i)对易,综合征为0;如果反对易,综合征为1。
# 计算错误E = Z1的综合征 E = tensor([Z, I2, I2]) syndrome = [] for g in [g1, g2, g3]: if np.allclose(E @ g - g @ E, 0): syndrome.append(0) else: syndrome.append(1) print("错误Z1的综合征:", syndrome)这个综合征向量告诉你错误发生在哪个位置,然后你可以根据稳定子码的译码表来纠正。代码的好处是,你可以快速尝试不同的错误算符,观察综合征的变化,从而理解稳定子码的纠错机制。
5.3 从习题到真实量子纠错:边界在哪里
课后题里的稳定子码通常是简化版,比如只给几个生成元,让你求码空间。真实量子纠错系统要考虑的问题更多:错误模型不是简单的泡利错误,而是连续的旋转错误;测量本身也会引入错误;容错阈值要求每个门操作的错误率低于某个值。但课后题的价值在于,它让你理解稳定子码的代数结构,这是后续学习表面码、颜色码的基础。
我一般会建议,做完课后题之后,尝试用代码模拟一个简单的纠错循环:随机生成一个错误,计算综合征,根据综合征查表纠正,然后验证纠正后的态是否回到码空间。这个循环能帮你把习题里的静态计算变成动态过程,理解会更深刻。
6. 把答案变成自己的:一套可复用的习题复盘流程
6.1 三遍做题法:从看懂到讲清楚
我自己的习惯是,每道题至少做三遍。第一遍,不看答案,自己硬推,推不出来就标记卡点。第二遍,看答案,重点看卡点处的推导,然后合上答案,自己重新推一遍。第三遍,假装给别人讲这道题,用白板或者纸把每一步的逻辑写出来,如果讲不下去,说明还有漏洞。这三遍下来,这道题才算真正吃透。
三遍做题法的时间分配大概是1:2:1。第一遍不要超过20分钟,卡住就停。第二遍可以花40分钟,把答案的每一步都搞清楚。第三遍花20分钟,重点是逻辑连贯性。很多人只做第一遍和第二遍,忽略了第三遍,结果考试时遇到类似的题还是不会。
6.2 建立自己的符号表和定理卡片
量子信息的符号非常多,狄拉克符号、泡利矩阵、张量积、偏迹、施密特分解,每个都有自己的约定。我建议建一个符号表,把教材里出现的符号和对应的矩阵表示、物理意义列出来。每次做题前先看一遍符号表,避免因为符号混淆而算错。
定理卡片是另一个好习惯。把常用的定理写在卡片上,比如“偏迹的矩阵元公式”“贝尔不等式的CHSH形式”“稳定子码的投影算符构造”。做题时如果用到某个定理,先看卡片,确认自己用的是对的。卡片不用多,20张左右就能覆盖这本书的核心内容。
6.3 用代码验证手算结果:一个可复用的检查脚本
最后分享一个我常用的检查脚本框架。每次手算完一道题,把关键步骤用代码跑一遍,对比结果。脚本不需要很复杂,能算张量积、偏迹、本征值、对易关系就够了。
def check_result(manual_result, code_result, tol=1e-8): """ 对比手算结果和代码结果 manual_result: 手算得到的矩阵或标量 code_result: 代码计算得到的矩阵或标量 tol: 容差 """ if np.allclose(manual_result, code_result, atol=tol): print("结果一致,推导正确") else: print("结果不一致,检查以下可能:") print("1. 符号约定是否一致") print("2. 矩阵乘法顺序是否写反") print("3. 偏迹的子系统索引是否正确") print("4. 是否漏掉了复数共轭") diff = np.abs(manual_result - code_result) print("最大偏差:", np.max(diff))这个脚本的用法很简单:把你手算的结果和代码算的结果传进去,如果一致就放心,不一致就按提示逐项检查。我用了好几年,帮我抓出了不少隐蔽的错误,比如把(XZ)的顺序写成了(ZX),或者偏迹时保留错了子系统。
希望帮到你。
本文还有配套的精品资源,点击获取