简介《量子计算和量子信息》尼尔森和丘昂著赵千川译是一本量子计算领域的经典教材这份课后答案由 GitHub 用户 goropikari 整理发布属于非官方解题手册适合修读相关课程、自学量子计算或备考复习的读者使用。压缩包内文件总数 1 个为 PDF 格式大小仅 466KB目前已有 1359 人浏览/下载学习轻量但实用。内容覆盖量子力学基础、量子噪声与量子操作、距离度量、熵与信息等章节并包含勘误清单例如指出第 101 页密度矩阵符号应为 ρ′、第 408 页迹距离公式中的系数问题以及第 411 页矩阵转置关系式等这些细致标注能帮助读者避免被教材旧版印刷错误误导更准确理解量子比特、纠缠、保真度和冯诺依曼熵等核心概念。作者也提醒这份非官方手册并非严格学术保证鼓励读者独立推导验证因而更适合作为对照学习、引发思考的辅助材料。1. 这本量子信息教材的课后答案与其抄不如自己算《量子计算和量子信息》的课后习题覆盖面极广从线性代数复习题一路排到量子纠错、量子信息论不等式几乎是每个进入量子计算领域的人都要过一遍的关。可这本书只在少量章节末尾给出零星参考答案绝大多数题要靠读者自己推导。网上流传的课后答案多半是早期读者自制的扫描件或手写笔记版本各异、错漏不少直接照抄等于把错误批量复制进自己的知识体系。我习惯把找答案换成验答案题目照做但每一步推导都用数值工具验算能跑通才算过。这篇笔记就是我用 Python 验算这本书习题的完整框架、符号约定与踩坑记录适合正在刷题、准备考试、或做量子算法复现的从业者和同学。你会发现掌握验算方法之后课后答案就从一份来路不明的文件变成了自己手里可复现、可扩展的东西。2. 动手前先立框架Dirac记号、张量积与习题符号约定这本书的习题把符号负担拉得很满。看起来是量子物理题本质上是线性代数题bra、ket、算符、张积全部都能翻译成矩阵与向量。我每轮刷题之前会先花半小时把翻译表写一遍后面所有验算都建立在这张表上。跳过这一步直接做数值验证十有八九会栽在符号与矩阵的对应关系上。2.1 从算符到矩阵符号翻成线代语言是第一步先把最重要的映射写死。下面这张表我每次都会抄在草稿纸最上方它把量子信息习题里出现频率最高的记号全部对应到 numpy 里的数据对象。Dirac 记号含义数值表示|ψ⟩态列向量psi np.array([...])⟨φ||φ⟩的共轭转置phi.conj()得到行向量⟨φ|ψ⟩内积复数np.vdot(phi, psi)|ψ⟩⟨φ|外积/投影算符np.outer(psi, phi)A算符一方阵A np.array([...])这里第一个坑是谁取共轭。np.vdot(phi, psi)默认对第一个参数取共轭做的事情正好是⟨φ|ψ⟩。如果你写np.vdot(ZERO, ONE)得到的答案是 0这没问题但如果你写np.vdot(ONE, ZERO)结果会变成 1因为括号顺序反了等于在算⟨1|0⟩的共轭。数值上它恰好等于 1跟手算习惯完全相反。我一般在代码里给变量名加上明确前缀比如ket_psi和bra_phi避免调用时记错顺序。外积与点积是第二个高频混淆点。|ψ⟩⟨φ|的矩阵形状是 N×N而⟨φ|ψ⟩是一个数。有人写⟨ψ|M|ψ⟩期望得到标量却把代码写成ket M bra最后得到一个矩阵而且跑起来不报错。我的检查顺序固定为先看形状再谈数值。组件形状不对这句话几乎能解决一半的答案对不上问题。做题时通常还会遇到算符的谱分解。任何 Hermitian 算符都能写成A Σ λ_i |i⟩⟨i|的形式λ_i 是实数。量子信息习题里碰到的测量算符、哈密顿量、密度算符都是 Hermitian 的而量子门是幺正的定义是U†U I。拿到一道题先判断手上的算符属于哪一类再去套性质后面推导会顺手很多。2.2 张量积与量子位排序一页纸说清两个约定多比特体系里张量积的顺序是整个数值验算的根基。|01⟩到底对应四个列向量里的哪一个完全取决于你选择的位序约定。我建议固定使用第一个 qubit 写在最左边二进制从左往右读这一套因为它和教材正文的写法最一致。两比特态列向量第一个 qubit 在最高位00⟩01⟩10⟩11⟩这个约定下|01⟩的列向量就是|0⟩ ⊗ |1⟩也就是第一个 qubit 取|0⟩第二个 qubit 取|1⟩。对应的 numpy 实现要特别注意np.kron(A, B)的顺序它的结果是A ⊗ B不是B ⊗ A。构建|0⟩ ⊗ |1⟩时应该写np.kron(ZERO, ONE)写反了会得到|10⟩的向量而且这个错误在单步输出里很难用肉眼发现。import numpy as np ZERO np.array([1, 0], dtypecomplex) ONE np.array([0, 1], dtypecomplex) # 约定: 第一个 qubit 在左, 二进制从高位往低位排 psi01 np.kron(ZERO, ONE) # 对应 |01 print(psi01) # [0.0.j 1.0.j 0.0.j 0.0.j] # 反例: kron 参数写反, 得到的是 |10 psi10_wrong np.kron(ONE, ZERO) print(psi10_wrong) # [0.0.j 0.0.j 1.0.j 0.0.j]我在代码里把所有构建态的 kron 调用都用注释标明哪个参数对应题目里的第几个 qubit因为量子线路的教科书式写法是多比特态从左到右排列而某些仿真库默认最右是 qubit 0两套体系在写 CNOT、SWAP 这类多比特门时会产生完全不同的矩阵。多比特门的构建同样依赖这个约定。CNOT (H ⊗ I)表示第一个 qubit 过 H 门再作为控制位第二个 qubit 是目标位。如果你先np.kron(I, H_e)再乘 CNOT物理含义就变成了第二个 qubit 过 H 门结果完全不同。验算过程中只要发现输出态的分量与手算对不上第一件事就是检查 kron 方向而不是怀疑物理推导。2.3 最小验算环境用 numpy 把推导变成数值检查验算环境不需要量子计算框架一个 numpy 就够了。Python 3.8 以上版本安装numpy之后所有纯态、算符、测量的基础验证都能做。这个环境最关键的价值是把书里的算符代数恒等式变成输出全零矩阵或输出 True的硬性检查。X np.array([[0, 1], [1, 0]], dtypecomplex) Y np.array([[0, -1j], [1j, 0]], dtypecomplex) Z np.array([[1, 0], [0, -1]], dtypecomplex) I np.eye(2, dtypecomplex) # 验证对易关系 [X, Y] XY - YX 2iZ comm X Y - Y X print(np.round(comm - 2j * Z, 12)) # 输出全零矩阵则恒等式成立这段代码说明三件事。第一定义泡利矩阵时必须指定dtypecomplex否则 Y 矩阵里的-1j会被强制转成整数而报错或丢失虚部。第二是矩阵乘法必须用它而不是*后者在 numpy 里是逐元素乘法。第三手算恒等式得到代数式之后代入具体矩阵算差结果应该全零由于浮点数尾差需要用np.round(..., 12)或np.allclose(..., atol1e-10)来判断。这个最小环境可以扩展到几乎任何习题推导。比如你证明了某个算符恒等式直接把左右两边的矩阵相减看是不是零矩阵你算出了某个态直接和数值构建的列向量比较。所有推导是否正确的问题最终都能变成两个矩阵/两个向量是否相等的问题。3. 把答案从手算变成可验证三类高频题的 Python 验算套路刷过一遍习题就会发现高频题型其实只有几类证明某个门满足某某性质、求算符的本征值与本征态、计算测量概率与投影后的态。这三类题恰好都适合用同一个套路——把题目翻译成矩阵运算跑一遍跟手算结果对比。3.1 验证门的幺正性与自逆性不变量先行第一章习题里充斥着证明 XX 门是幺正的证明 H 门的平方等于单位矩阵这类题。手算时通常会用到U†U I的定义而数值验证只需要几行代码。我一般会把幺正性检查封装成一个小函数后续每一道涉及量子门的题都会先跑它。def is_unitary(U: np.ndarray, tol: float 1e-10) - bool: rows U.shape[0] return np.allclose(U U.conj().T, np.eye(rows), atoltol) # Hadamard 门 H_e 1 / np.sqrt(2) * np.array([[1, 1], [1, -1]], dtypecomplex) print(H is unitary:, is_unitary(H_e)) print(H^2 is unitary:, is_unitary(H_e H_e)) # 检查 H^2 I print(H^2 I:, np.allclose(H_e H_e, np.eye(2), atol1e-10))这里的关键点有两个。一是U.conj().T对应共轭转置U†不要漏掉.conj()否则验证的不是幺正性而是对称性。二是tol参数数值计算里浮点误差会带来1e-16量级的噪声atol给到1e-10既能容忍噪声又不会把真正不满足条件的矩阵放过。做完数值验证再回头写证明思路会清晰很多。比如你已经从数值上确认 H^2 I再试着用代数方法推导等于提前知道了结论推导过程自然有方向。遇到复杂的多比特门幺正性检查还能帮你发现矩阵写错、张量积顺序反了这类低级错误。3.2 本征值与本征态量子算法习题的主战场求本征值是后面量子算法章节的常客。相位估计算法要求算某个幺正算符的本征相位Shor 算法里涉及模指数算符的周期性所有这些都是本征值问题。numpy 对 Hermitian 矩阵提供了专门的特征分解函数np.linalg.eigh它假设输入是 Hermitian返回的实特征值按升序排列特征向量按列存放。# SWAP 门: 交换两个 qubit 的状态 SWAP np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtypecomplex) vals, vecs np.linalg.eigh(SWAP) print(eigenvalues:, np.round(vals, 10)) print(eigenvector for -1:, vecs[:, 0])SWAP 门的本征值集合是{-1, 1}其中-1对应反对称态(|01⟩ - |10⟩)/√2这个手算结论在程序里表现为vals[0] -1对应第一列特征向量分量之比正好是1, -1。我特别强调用eigh而不是eig原因有两个。第一量子信息习题中的算符绝大多数可以写成 Hermitian 形式eigh能保证特征值为实数不会出现10j这种需要手动去虚部的输出。第二eigh的数值稳定性更好当特征值接近简并时eig给出的特征向量可能发生混叠而eigh能保持正交性。在简并情况下特征向量不唯一我一般直接打印整个特征向量矩阵对照题目要求的对称性来判断。3.3 测量概率与投影后状态别让归一化毁掉后续结果测量是量子信息习题里最不容易手算出错、却最容易在数值验证时翻车的一类题。概率公式p ⟨ψ|M†M|ψ⟩和投影后态M|ψ⟩ / ‖M|ψ⟩‖看起来简单落到代码里有三个细节必须处理干净。def project_measure(state, projector): # 1. 确保输入纯态归一化 norm np.linalg.norm(state) if abs(norm - 1.0) 1e-10: state state / norm # 2. 测量概率: psi|P|psi prob np.real(np.vdot(state, projector state)) # 3. 投影后的态, 必须重新归一化才能用于后续计算 collapsed projector state collapsed_norm np.linalg.norm(collapsed) if collapsed_norm 1e-12: collapsed collapsed / collapsed_norm return prob, collapsed P0 np.outer(ZERO, ZERO) # 投影到 |0 psi H_e ZERO # H|0 prob0, psi0 project_measure(psi, P0) print(p(0) , prob0) # 0.5 print(collapsed:, psi0) # |0np.vdot(state, projector state)这一步同时处理了共轭和矩阵乘法得到的是实部为主的一个复数用np.real提出来就是概率。如果期望值里出现不可忽略的虚部说明某个矩阵写错了。投影后的态必须除以范数这一点是血泪教训。忘记归一化时psi0的模是1/√2直接拿它去算第二次测量的概率所有结果都会偏小一半而且不容易察觉。函数里对collapsed的归一化处理是我每次写测量代码都会保留的标准动作。4. 刷题避坑量子信息习题最常错的 5 类问题数值验算做得多了会发现大部分错误集中在几个固定模式上。这一章列出的 5 类问题我几乎每刷一轮习题都会遇到至少一个。每条按现象、原因、解决的顺序写方便你对照排查。4.1 张量积顺序翻车qubit 排序与 kron 的参数方向现象手算的态向量分量排列和自己代码构建的结果对不上比如题里算|01⟩的输出程序却给出|10⟩的向量。原因np.kron(A, B)计算的是A ⊗ B参数顺序一旦写反物理含义就变成第一个 qubit 取 B 的态、第二个取 A 的态。再加上题目里的多比特态默认从左到右是第一个到最后一个 qubit很多人没有先写下排序约定就直接写代码。解决在草稿纸和代码注释里同时写清第一个 qubit 在最高位二进制从左往右读。构建态和门之前先问自己一句kron 的第一个参数对应哪个 qubit。我还会在代码里加一条断言比如要得到|01⟩就断言np.argmax(psi) 1让程序自己在运行时报错不用肉眼比对。4.2 全局相位不等于相对相位别把对判成错现象自己算出来的答案和参考答案差一个负号或者差一个虚数单位i于是认定自己做错了。原因对单个态矢整体乘一个模长为 1 的复数e^{iθ}不改变任何测量结果这就是全局相位。习题答案里-|0⟩和|0⟩物理上完全等价但很多读者把它当成不同答案。解决比较两个态是否等价不要直接看分量要用内积模|⟨ψ|φ⟩|。它等于 1 就说明两个态只差全局相位。def same_state(psi, phi) - bool: return abs(np.vdot(psi, phi)) 1 - 1e-12 print(same_state(H_e ZERO, -H_e ZERO)) # True print(same_state(H_e ZERO, 1j * H_e ZERO)) # True相对相位是另一回事。(|0⟩ |1⟩)/√2和(|0⟩ - |1⟩)/√2只差一个负号但这两个态在X基下的测量结果完全不同。全局相位随便乘相对相位动不得这个区分在纠缠态验证里尤其重要。4.3 密度算符忘归一化施密特系数乱序现象构造密度矩阵ρ |ψ⟩⟨ψ|之后np.trace(rho)不等于 1或者做施密特分解时奇异值的个数和手算的对不上。原因纯态密度算符的 trace 等于 1前提是|ψ⟩本身已归一化。混合态ρ Σ p_i |i⟩⟨i|的 trace 是Σ p_i如果 p_i 没有归一化trace 就会偏离 1。施密特分解的问题则出在奇异值排序上有些教材按降序排有些代码默认升序排直接取第一个奇异值会取错。解决每构造一个密度算符立刻检查 trace每做一次施密特分解使用np.linalg.svd的compute_uvFalse先看奇异值列表再约定按降序解释。rho np.outer(ZERO, ZERO) print(trace(rho) , np.trace(rho)) # 1.0 # 施密特分解: 把两比特态按 2x2 矩阵做 SVD phi (np.kron(ZERO, ZERO) np.kron(ONE, ONE)) / np.sqrt(2) mat phi.reshape(2, 2) sv np.linalg.svd(mat, compute_uvFalse) print(Schmidt coefficients:, sv) # [0.70710678, 0.70710678]判断一个两比特态是否纠缠就看施密特系数里大于零的个数。系数[0.7071, 0.7071]对应最大纠缠态[1, 0]对应可分离态。这个做法比手算约化密度矩阵再求本征值快得多也省去大量中间推导。4.4 测量后的态没重新归一化现象测量概率单独算是对的但把投影后的态代入下一步计算时概率总和不为 1。原因投影算符作用到态上之后向量的模变成√p这一步在物理上对应测量后的态需要重新归一化。很多初学者投影完直接拿着未归一化的向量继续算结果所有后续概率整体变小。解决把投影后的向量除以它的模再进入下一步计算。我上面project_measure函数里的第三段就是专门处理这个问题的。哪怕是中间步骤只要这个向量要被当作物理态使用就必须归一化。4.5 左矢右矢作用顺序反了期望值算出了虚数现象计算⟨ψ|A|ψ⟩手算结果是实数但代码输出带一个明显不为零的虚部比如0.70.3j。原因算符作用顺序写反了。正确的数值写法是行向量 矩阵 列向量即bra A ket。有人写成ket A bra得到的是矩阵而不是数有人把矩阵的共轭转置漏掉把A†写成了A结果也会偏离。解决统一采用np.vdot(state, A state)这个写法它等价于⟨ψ|A|ψ⟩并且自动处理了左侧向量的共轭。更关键的是检查输出虚部物理可观测量的期望值必须是实数虚部只要超过1e-12就说明某个矩阵或顺序有误。expect np.vdot(ZERO, Z ZERO) # 0|Z|0 1 print(real:, np.real(expect), imag:, np.imag(expect))这个虚部检查是极其好用的排错手段。量子信息习题里的期望值、概率、保真度全是实数一旦代码算出虚部不要怀疑物理先怀疑自己矩阵写错了。5. 把验算沉淀成自己的答案库从一道例题到全书习题的自洽闭环前面几章解决的是怎么验证一道题最后一章把视角拉远如何用这些方法给自己建一套可持续维护的答案库。我用一个具体的例子说明完整流程再讲组织习惯。以验证 Bell 态生成线路为例。线路是第一个 qubit 过 H 门再以第一个 qubit 为控制位对第二个 qubit 做 CNOT输入|00⟩。整条线路的矩阵是CNOT (H ⊗ I)这一步把 2.2 节的张量积约定、3.1 节的幺正性检查、3.2 节的特征分解全串起来了。# 构建线路矩阵 U_bell CNOT np.kron(H_e, I) psi_in np.kron(ZERO, ZERO) psi_out U_bell psi_in # 检查输出态 print(output:, np.round(psi_out, 10)) # 期望: [0.707, 0, 0, 0.707], 即 (|00 |11)/sqrt(2) # 用 Schmidt 分解验证纠缠 mat psi_out.reshape(2, 2) sv np.linalg.svd(mat, compute_uvFalse) print(Schmidt coefficients:, np.round(sv, 10)) # [0.707, 0.707]这一步跑通答案库里的Bell 态生成题就有了三重保险线路矩阵和手算一致、输出态分量正确、施密特系数确认它是最大纠缠态。任何一处不满足都能立刻定位是门矩阵错了、kron 顺序反了、还是纠缠判据本身用错。我现在的习惯是每道习题建一个独立文件夹包含三样东西题目原文、手写推导的扫描或 Markdown 笔记、一个可以独立运行的verify.py。verify 脚本里只放断言和关键输出跑一次就知道这道题当前是否通过。题目答案不是一次性算出来就结束后面复习时重新跑一遍脚本任何回归都能当场发现。这个习惯帮我挡掉了大量荒唐错误。某次推导量子傅里叶变换的矩阵形式手算两页纸觉得稳了verify 脚本一跑特征值和书上对不上最终定位到是位序约定在推导中途换了。从那以后我再也不信手算很顺这种错觉。把验算做进流程这本书的课后题才真正从参考答案变成自己验证过的知识。希望帮到你。本文还有配套的精品资源点击获取