资讯动态

用Python和NumPy从零实现量子计算模拟器:量子比特到Bell态

发布时间:2026/10/8 20:47:36 来源:尧图企业网站定制
这两年量子计算的热度大家都看到了但真正动手写过量子程序的人其实没那么多。我一直觉得要理解量子算法最好的方式不是直接调Qiskit或Cirq这种框架的API而是自己从零写一个能在经典计算机上运行的量子计算模拟器。这个想法在去年终于落地了我把教学用的模拟器开源了出来项目代号就叫DREAMVFIA整个实现只依赖NumPy目标是让任何有Python基础的人都能看懂量子电路在底层到底是怎么算的。这篇是上篇先把地基打牢量子比特的数学表示、单比特门、双比特门、测量机制最后用不到五十行代码跑通一个真正的Bell态电路——也就是那个著名的“纠缠态”。如果你之前对量子计算的理解只停留在“叠加”“坍缩”这些名词上这篇文章就是来把这些名词变成你能摸到的数据结构和矩阵运算的。1. 为什么要在Python里写一个量子模拟器以及DREAMVFIA的起点1.1 模拟器补上的认知断层说实话现在的量子计算学习路径有点尴尬。直接上真机吧排队几小时是家常便饭而且真机的噪声、退相干、校准问题会把一个刚入门的初学者劝退。直接学算法吧市面上大多数教程又默认你已经理解了量子门的物理意义。我当初就是卡在这个位置知道X门是比特翻转知道H门产生叠加但这些门组合起来为什么能加速搜索为什么纠缠态是“纠缠”的没人告诉我。模拟器恰好补上了这块认知断层。只要把量子态当成一个复数向量把量子门当成矩阵把测量当成概率采样所有抽象概念都会变成屏幕上实实在在的数字。这一点是真实量子硬件做不到的——真机你只能拿到测量结果但模拟器可以把每一步运算结束后的中间状态完整打印出来这对于理解算法内部的运作机制简直是降维帮助。DREAMVFIA这个项目的定位就是教学型模拟器。它刻意不做成黑盒所有门的矩阵、所有采样逻辑、所有张量积的顺序都摊开放在源码里。你甚至可以给它加调试打印看看每个门作用前后量子态发生了什么样的变化。这种“全透明”的体验是Qiskit这类工业级框架给不了的。1.2 为什么是Python而不是C/Rust这是个好问题。C或Rust在性能上远超Python真要模拟大规模量子电路Python确实不是对手。但DREAMVFIA的首要目标不是性能而是教学和正确性。Python配上NumPy底层是BLAS/LAPACK这些经过几十年优化的线性代数库矩阵乘法效率并不差而且代码可读性非常高。另一个现实的理由是NumPy的np.kron张量积、np.dot、复数数组这些特性天然和量子计算的数学语言对齐。你不需要处理指针、内存管理、模板元编程就能把量子态的演化写得和教科书公式一一对应。这一点在项目早期尤其重要因为量子计算里最容易犯错的就是索引顺序和符号约定问题Python的交互式环境让你可以随时验证中间结果减少了很多无谓的debug时间。如果你之后对性能有刚需可以把核心的矩阵乘法部分切到numba或用C扩展。但DREAMVFIA设计上就把这两层拆开了你完全可以在保持API不变的前提下替换底层实现。先跑对再跑快这是我做开源项目一贯的顺序。1.3 模拟器的天花板2^N维度内存爆炸在进入代码之前必须先搞清楚一个物理现实经典计算机模拟量子计算的代价是指数级的。一个n量子比特的系统其量子态是一个包含2^n个复数的向量。每个复数如果按两个float64存储就是16字节那么30个量子比特的状态向量大约是16GB32个比特直接飚到64GB普通笔记本电脑已经扛不住了。这个内存上限也是推动真实量子计算机发展的核心理由之一——因为真机不存在这种指数级的内存膨胀。DREAMVFIA在项目文档里明确写了适用边界算法演示、教学验证、中小规模电路基本在20个量子比特以内可以跑得很舒服超过这个规模就该去考虑真实硬件或者更高级的张量网络模拟方法了。理解这个边界很重要。它不是缺陷而是模拟器这种工具的天然属性。你用它学原理、跑算法、验证想法而不是拿它挑战世界纪录。后面我所有代码示例都控制在几个比特的规模就是为了让你在笔记本上也能立刻跑起来。2. 量子比特的数学底座状态向量与叠加态2.1 经典比特到量子比特不只是一个0/1开关经典比特很简单要么是0要么是1一根电线缆要么通电要么不通电。但量子比特没法用这种“开关”直觉去套。一个量子比特的状态可以写成|ψ⟩ α|0⟩ β|1⟩这里的希腊字母α和β是复数描述的是量子比特处于|0⟩和|1⟩的“概率幅”。注意这里不是经典概率混合不是说有65%概率是0、35%概率是1。叠加态是一种更微妙的属性量子比特“同时”处于两种计算基态上而这个“同时”只有在测量时才会被打破。我一开始也老犯迷糊后来用一句话提醒自己经典是“要么/要么”量子是“既/又”。你在计算机里存储的是α和β这两个复数它们本身才是量子比特状态的真实表示。2.2 Dirac记号与基底向量Dirac记号狄拉克记号是量子计算的语言基础。|0⟩读作“ket 0”它就是一个列向量[1, 0]的转置|1⟩是列向量[0, 1]。在n量子比特系统里计算基态的数量是2^n每个基态都可以用一串0和1来表示比如|00⟩、|01⟩、|10⟩、|11⟩。代码里我直接用NumPy的复数数组来表示这些向量。初始化一个n比特系统就是创建一个长度为2^n的全零复数数组然后把第0号元素设为1。为什么是第0号因为数组下标0对应二进制全零的基态也就是所有比特都处于|0⟩的状态。这是整个模拟器的最初始状态后续所有门的操作都从这个基准出发。2.3 叠加态的归一化条件与Born规则既然α和β是概率幅那么它们和概率之间的关系由Born规则给出测量得到|0⟩的概率是|α|²测量得到|1⟩的概率是|β|²。这两项加起来必须等于1也就是归一化条件|α|² |β|² 1为什么要归一化因为量子门在数学上是幺正矩阵unitary matrix它作用在量子态上会保持向量的长度不变。如果初始状态是归一化的经过任何合法量子门演化后依然归一化这样测量概率永远是合法的概率分布。构建模拟器时我一直保持着两个习惯。第一每次应用门之后检查np.sum(np.abs(state) ** 2)是否约等于1一旦偏差超过1e-10说明某个门的矩阵构造有问题。第二测量采样时我会把概率向量再除以总和做一次软归一化因为浮点计算累积的小误差可能让np.random.choice的p参数总和差一点点。2.4 用NumPy把状态向量落地说了这么多抽象概念是时候看实际代码了。初始化一个单比特系统和多比特系统的代码非常直接import numpy as np # 单比特基态 state_0 np.array([1, 0], dtypecomplex) state_1 np.array([0, 1], dtypecomplex) # n比特系统初始化为 |00...0 def zero_state(n_qubits): dim 2 ** n_qubits state np.zeros(dim, dtypecomplex) state[0] 1 return state state zero_state(2) print(state) # [1.0.j 0.0.j 0.0.j 0.0.j]这段代码虽然简单但它定义了整个模拟器的核心数据结构。往后每一步量子门操作本质上都是对这样一个长度为2^n的复数数组做线性变换。QuantumCircuit类到时候就是围绕这个数组做封装提供更友好的门调用接口。3. 量子门就是矩阵单比特门的核心实现3.1 幺正矩阵为什么量子门必须是它现在到了理解量子计算最关键的一步量子门在数学上是一个幺正矩阵。所谓幺正就是满足U†U UU† I其中U†是U的共轭转置。这个性质保证了量子门的可逆性也保证了归一化条件永远成立。为什么必须可逆因为量子演化在理想情况下是信息无损的。经典计算机里的AND门是信息丢失的两个输入比特变成一个输出比特丢失的信息永远消失了所以没有逆运算。但量子门不能这样它必须把输入的量子态一一映射到输出量子态而且这个映射必须是双射否则概率无法保持。开发DREAMVFIA时我写了一个单元测试函数专门检查每个门的矩阵是不是幺正的计算U的共轭转置乘以U看看结果是否接近单位矩阵。这个测试看起来多余但它帮我抓过不少低级错误比如矩阵元素抄错正负号或者忘记除以√2。3.2 常用单比特门的矩阵DREAMVFIA里首先要实现五个基础单比特门。它们的矩阵形式如下门矩阵作用I[[1, 0], [0, 1]]什么都不做X[[0, 1], [1, 0]]比特翻转Y[[0, -i], [i, 0]]比特翻转相位Z[[1, 0], [0, -1]]相位翻转H(1/√2)[[1, 1], [1, -1]]产生叠加其中H门也叫Hadamard门它是整个量子算法里出场频率最高的角色。在代码里定义这些门非常直观I np.array([[1, 0], [0, 1]], dtypecomplex) X np.array([[0, 1], [1, 0]], dtypecomplex) Y np.array([[0, -1j], [1j, 0]], dtypecomplex) Z np.array([[1, 0], [0, -1]], dtypecomplex) H np.array([[1, 1], [1, -1]], dtypecomplex) / np.sqrt(2)你可能会问为什么X门就是经典非门因为把X矩阵作用到|0⟩上得到[0, 1]也就是|1⟩作用到|1⟩上得到[1, 0]也就是|0⟩。确实翻转了。但X门比经典非门强的地方在于它还能作用于叠加态α|0⟩ β|1⟩经过X门会变成β|0⟩ α|1⟩两个概率幅对调这是经典逻辑门做不到的。3.3 应用单比特门kron构造完整矩阵在单比特系统上应用门很简单直接做矩阵乘法就行。但量子电路通常有多个比特每个门只会作用在其中某一个比特上。比如有两个量子比特我想在第一个比特上做H门第二个比特保持不动那么实际作用的矩阵是H与I的张量积H⊗I。DREAMVFIA里的apply_single_qubit_gate函数就是这样构造完整矩阵的。这里要特别强调量子比特顺序约定。我采用大端序big-endian数组下标的二进制表示最左边是第0号量子比特最右边是第n-1号量子比特。也就是说对于2个比特下标2的二进制是10代表|10⟩也就是第0号比特为1、第1号比特为0。def apply_single_qubit_gate(state, gate, target_qubit, n_qubits): 在target_qubit上应用单比特门。 约定q0是最高位大端序。 full_matrix np.array([[1]], dtypecomplex) for q in range(n_qubits): if q target_qubit: full_matrix np.kron(full_matrix, gate) else: full_matrix np.kron(full_matrix, I) return full_matrix state这个实现方式不是性能最优但对于教学目的来说它的每一步都对应了张量积的概念非常直观。如果以后要模拟20个以上的量子比特这种构造完整矩阵再点乘的方法会非常慢因为需要构造一个4^n大小的矩阵。到时候可以改用reshape操作直接对状态向量做张量收缩性能会有质的飞跃。3.4 H门的直觉量子版公平硬币H门在量子计算里作用太大了值得单独聊一聊。把它作用在|0⟩上结果是(|0⟩ |1⟩)/√2。这个状态测量后得到0和1的概率各是50%看起来就像抛一枚公平硬币。但H门和公平硬币有一个根本区别把两个H门连续作用在|0⟩上结果是|0⟩概率是100%。如果它是公平硬币两次抛掷的结果应该会出现“正反组合”的概率分布而不是确定回到起点。这个特性叫干涉interference是量子计算能超越经典计算的秘密武器之一。记住这个特性后面在Deutsch-Jozsa算法、Grover搜索算法里会反复见到它。3.5 浮点精度和归一化的坑写模拟器绕不开浮点误差这里分享一个我踩过好几次的坑。H门的矩阵含有1/√2这个无理数连续作用两次H门后理想结果应该精确等于单位矩阵但浮点运算会得到类似0.9999999999999的对角线元素。如果你直接拿它和单位矩阵比较结果会是False。解决办法很简单用np.allclose而不是来判断矩阵相等另外在测量前对概率做一次归一化。我还在DREAMVFIA里封装了一个is_normalized函数每次门操作后检查归一化误差一旦超限就抛警告。这个习惯帮我避开了好几个因为矩阵构造错误导致概率分布完全乱掉的情况。4. 从单比特到双比特张量积、CNOT门与纠缠4.1 复合系统为什么用张量积单比特系统的状态是二维复数向量那两个比特的组合空间是几维答案是4维而不是224这么简单。更准确地说是2×24维。三个比特就是2³8维n个比特就是2ⁿ维。这个指数增长的维度正是量子计算能力的来源也是经典模拟器的噩梦。张量积是组合量子系统的数学工具。在NumPy里np.kron就是做这个的。两个单比特门组合时比如第一个比特做H、第二个比特做X那么完整门矩阵就是np.kron(H, X)。如果你构造的矩阵维度不对大概率是张量积的顺序写反了导致控制比特和目标比特被调换。4.2 从kron到多比特量子门DREAMVFIA里构建多比特门的基础就是kron但它有个更灵活的需求CNOT门这种双比特门的两个控制目标比特并不总是相邻的。处理这种情况我用了一个比较朴素但非常清晰的方法——遍历所有2ⁿ个基态对每个基态判断如果控制位是1就把目标位翻转。然后构造出对应的置换矩阵。以CNOT矩阵为例。用咱的大端序约定控制位是0号比特、目标位是1号比特时量子电路的行为是|00⟩→|00⟩|01⟩→|01⟩|10⟩→|11⟩|11⟩→|10⟩。对应的4×4矩阵是# CNOT矩阵 (ctrl0, targ1, 大端序) cnot_0_1 np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0] ], dtypecomplex)当然写模拟器不可能每个门都从查矩阵开始那太不工程了。所以我用循环构造了一种通用做法def cnot_matrix(ctrl, targ, n_qubits): dim 2 ** n_qubits U np.zeros((dim, dim), dtypecomplex) for i in range(dim): # 将下标转成比特列表大端序 bits [(i (n_qubits - 1 - k)) 1 for k in range(n_qubits)] if bits[ctrl] 1: bits[targ] ^ 1 # 翻转目标比特 j 0 for b in bits: j (j 1) | b U[j, i] 1 return U这个函数的时间复杂度是O(2ⁿ)每次调用都全量重算矩阵效率不高但代码和数学定义完全对标调试时可以直接对照你手算的基态映射。性能优化的事后面再说教学代码优先保证正确性。4.3 CNOT门量子世界的if语句CNOT受控非门是量子计算里非常重要的双比特门因为它能制造纠缠。它的逻辑很直白如果控制比特是|1⟩就对目标比特做X翻转如果控制比特是|0⟩目标比特保持不变。这不就是if语句吗对它就是量子世界的if语句。但它的强悍之处在于如果控制比特处于叠加态CNOT门会把这个叠加“传染”到目标比特上从而创造出两个比特都处于叠加相关态的情况——这就是纠缠。经典if语句做不了这件事因为经典程序的条件必须是确定的0或1。4.4 Bell态纠缠从哪冒出来现在到了这篇文章最激动人心的部分。我们用现有的模拟器组件搭建第一个真正的量子电路制造Bell态。Bell态是最简单也是最典型的纠缠态它的形式是(|00⟩ |11⟩)/√2。搭建这个电路只需要两步# 初始化两个比特 state zero_state(2) # 第一步在第0号比特上施加H门 state apply_single_qubit_gate(state, H, 0, 2) # 此时状态变为 (|00 |10) / √2 # 第二步以第0号比特为控制位第1号比特为目标位施加CNOT门 state cnot_matrix(0, 1, 2) state print(state) # 输出: [0.707106780.j, 0.0.j, 0.0.j, 0.707106780.j]输出里的第0号元素是0.707第3号元素也是0.707。按照大端序映射第0号下标对应|00⟩第3号下标对应|11⟩中间两个下标对应的|01⟩和|10⟩是零。也就是说这个双比特系统的量子态确实变成了(|00⟩ |11⟩)/√2。为什么说它纠缠因为如果你测量第0号比特得到的结果有50%是0、50%是1但一旦你知道了第0号比特的结果第1号比特的结果就完全确定了。它们像一个不可分割的整体各自的“个体状态”在纠缠面前失去了意义。用经典概率来描述这种相关性是不可能的——经典的“两个比特要么是00要么是11”和这里的叠加态有本质区别区别就在于叠加态下还存在干涉的可能性而经典概率没有。4.5 测量的实现按Born规则抽样模拟器的最后一块拼图是测量。量子力学告诉我们测量会让量子态坍缩到某个计算基态结果带有概率性概率由Born规则给出。在经典模拟器里“测量”这个动作其实分两步走第一步根据当前量子态计算每个基态的概率probs np.abs(state) ** 2。第二步根据这个概率分布做随机抽样得到最终的经典结果。下面是我在DREAMVFIA里使用的测量函数核心部分def measure_state(state, shots1024): probs np.abs(state) ** 2 probs probs / np.sum(probs) # 浮点误差的软归一化 dim len(state) outcomes np.random.choice(dim, sizeshots, pprobs) return outcomes注意这里有个重要的细节真正的量子硬件上测量之后量子态就坍缩了你无法再看到坍缩前的完整信息。但模拟器可以提前访问整个概率分布甚至可以在不“坍缩”的情况下把量子态原样保留下来。这是一个只有模拟器才有的温柔待遇我经常利用它来观察中间态的振幅而不是傻傻地只盯着采样结果。5. 电路级封装QuantumCircuit类与测量逻辑5.1 最小API设计散装的矩阵乘法函数演示原理很合适但真要写算法试验需要更友好的接口。DREAMVFIA从设计之初就决定模仿主流框架的写电路风格但把依赖降到最低。它提供的核心方法只有四个构造一个n比特电路初始状态为|0...0⟩在指定比特上施加单比特门h、x、z等在指定比特对上施加CNOT门cx对整个电路进行多次测量并返回统计结果这看起来很简单但恰恰是这套简单API可以跑通几乎所有经典量子算法包括Deutsch-Jozsa、Grover搜索这些教科书级别的例子。少即是多在这个项目里尤其明显。5.2 即时执行与延迟执行的选择市面上的主流模拟器通常会先把所有门保存成一个电路图再统一编译执行。这种方式叫延迟执行优点是能做门融合、线路优化真实硬件上也必须这么做。但DREAMVFIA选择了更朴素的即时执行每调用一个门方法立刻在状态向量上进行矩阵乘法。即时执行的好处是调试直观。你在每个门之后打印状态向量立刻能看到这个门对量子态的影响不用去解析复杂的数据结构。代价是少了线路优化的可能性但对于教学场景这不是问题。当你理解了量子计算的本质之后再去看Qiskit那套编译管线会觉得豁然开朗但对初学者来说延迟执行的多层抽象反而会掩盖量子原理。5.3 QuantumCircuit核心代码这是我写这个模拟器时最满意的一部分因为代码可以足够短但功能足够全class QuantumCircuit: def __init__(self, n_qubits): self.n n_qubits self.state np.zeros(2 ** n_qubits, dtypecomplex) self.state[0] 1 def _apply_single(self, gate, target): self.state apply_single_qubit_gate(self.state, gate, target, self.n) def h(self, target): self._apply_single(H, target) return self def x(self, target): self._apply_single(X, target) return self def z(self, target): self._apply_single(Z, target) return self def cx(self, ctrl, targ): self.state cnot_matrix(ctrl, targ, self.n) self.state return self def measure(self, shots1024): probs np.abs(self.state) ** 2 probs probs / np.sum(probs) return np.random.choice(2 ** self.n, sizeshots, pprobs)每个门的return self让电路构建可以链式调用写起来很顺手。你也可以看到measure函数没有修改self.state这意味着同一个量子电路可以反复测量很多次每次都得到新的采样结果。这对于调试算法特别有用——你可以先把电路构建好反复采样看统计规律而不用每次重头搭建。5.4 用已知结果做回归测试作为一个正经的开源项目DREAMVFIA里必须有测试不然代码改着改着就会出幺蛾子。我总结了三类最基本的回归测试第一类X门作用在|0⟩上必须得到|1⟩。这验证了最基本的比特翻转逻辑正确。第二类连续两次H门作用在任何基态上结果必须回到原始状态在浮点误差范围内。这验证了H门的矩阵归一化没有问题。第三类Bell态电路的测量结果中00和11的出现次数大致相等01和10几乎不出现。这验证了张量积顺序和CNOT逻辑都正确。这些测试看起来简单但任何一个失败都意味着你之前写的某个门矩阵有问题。我把它们写成了一个脚本每次提交代码时自动跑一遍。维护这个测试集花不了多少功夫却能让后续迭代安心很多。6. 上篇验收跑通Bell态电路看到“量子”真的坍缩成经典结果6.1 完整代码一览到这里我们已经把所有零件都准备好了。把散落的函数和类拼在一起一个完整的Bell态制备与测量程序就长这样import numpy as np from collections import Counter # ---- 基础门 ---- I np.array([[1, 0], [0, 1]], dtypecomplex) X np.array([[0, 1], [1, 0]], dtypecomplex) H np.array([[1, 1], [1, -1]], dtypecomplex) / np.sqrt(2) # ---- 单比特门应用 ---- def apply_single_qubit_gate(state, gate, target, n_qubits): full np.array([[1]], dtypecomplex) for q in range(n_qubits): full np.kron(full, gate if q target else I) return full state # ---- CNOT矩阵 ---- def cnot_matrix(ctrl, targ, n_qubits): dim 2 ** n_qubits U np.zeros((dim, dim), dtypecomplex) for i in range(dim): bits [(i (n_qubits - 1 - k)) 1 for k in range(n_qubits)] if bits[ctrl] 1: bits[targ] ^ 1 j 0 for b in bits: j (j 1) | b U[j, i] 1 return U # ---- 量子电路类 ---- class QuantumCircuit: def __init__(self, n_qubits): self.n n_qubits self.state np.zeros(2 ** n_qubits, dtypecomplex) self.state[0] 1 def h(self, target): self.state apply_single_qubit_gate(self.state, H, target, self.n) return self def cx(self, ctrl, targ): self.state cnot_matrix(ctrl, targ, self.n) self.state return self def measure(self, shots1024): probs np.abs(self.state) ** 2 probs probs / np.sum(probs) return np.random.choice(2 ** self.n, sizeshots, pprobs) # ---- 构建Bell态 ---- qc QuantumCircuit(2) qc.h(0) qc.cx(0, 1) outcomes qc.measure(shots2048) # ---- 统计结果 ---- counts Counter(outcomes) for key in sorted(counts.keys()): binary format(key, 02b) # 大端序下下标0对应|00 print(f|{binary}: {counts[key]})这段代码完全可以用在课堂演示里。把它保存成bell.py在终端执行你会看到类似下面的输出|00: 1041 |11: 100701和10完全消失了。这就是纠缠的直接证据两个量子比特的测量结果要么都是0要么都是1永远不会出现一个0一个1的独立情况。6.2 输出结果解读为什么结果不是严格的各50%因为2048次采样是有限样本会有统计涨落。你可以试着把shots调到100000会发现00和11的比例越来越接近50:50这正是大数定律在起作用。有些读者可能会疑惑这个输出看起来就像两个经典比特被初始化为相等的0或1然后同时输出有什么神奇的呢神奇之处在于在测量之前这个量子系统处于(|00⟩ |11⟩)/√2的叠加态它不是“有50%概率是00、50%概率是11”的经典混合态。虽然单次测量的统计结果相同但如果你在这个Bell态上再做某些干涉操作比如再给第0号比特施加一次H门经典混合态和量子纠缠态会给出完全不同的结果。这个实验以后在中篇里我会仔细讲这里先留个引子。6.3 常见问题排查表写模拟器的过程中我积累了一些高频问题。按我的经验90%的错误都出在下面几个地方症状可能原因解决方案测量概率和不为1门矩阵不幺正或复数输入错检查矩阵元素用U†UI做验证测量结果全是00忘了加H门或CNOT控制目标配反检查电路门顺序和比特索引结果出现01和10CNOT方向配反或索引顺序理解错误先手写一个2比特基态映射再对照矩阵矩阵维度不匹配张量积kron的顺序或次数不对打印每一步的中时期望矩阵尺寸H门两次后不还原浮点误差用np.allclose判断别用这里特别提一下量子比特顺序约定不同会导致完全不同的结果。Qiskit默认使用小端序而DREAMVFIA使用大端序。如果你在两个框架之间切换务必要先搞清楚下标和比特的映射关系这是新手最容易掉进去的坑。6.4 下篇预告到这上篇的骨架已经搭起来了状态向量、单比特门、CNOT门、测量这些东西已经能支撑你去捣鼓很多有趣的实验了。但模拟器还缺很多实用功能可视化的布洛赫球、更多受控门比如受控Z门、受控相位门以及直接在模拟器上跑通一个完整算法。下篇我会把重点放在算法层面在DREAMVFIA上实现Deutsch-Jozsa算法和Grover搜索算法这两者会彻底改变你对量子计算“不过是概率模型”的错觉——干涉效应会让你看到叠加态的真正威力。我会继续本着“一切从零手写”的原则连Oracle电路都用基础门搭出来。到时候这套模拟器就不再只是玩具而是一个能真正帮你理解量子算法精髓的教学工具。我自己在实际做这个项目的过程中最大的体会是写量子模拟器这件事本身比结果更有价值。每实现一个门、每跑通一个电路你对“叠加”“纠缠”“干涉”的理解就会深一层。建议你下一步也动手把代码敲一遍尤其是那个用于构造CNOT的循环一句话一句话地读用笔在纸上画两遍how the bits mapping works。等这些基础都扎实了下篇的算法解读你看起来会轻松很多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑