量子计算自学记录 - 详解

一、量子计算入门:像画箭头一样理解“量子比特”

想象一下你在纸上画一个箭头。

这个箭头有长度,有方向。在数学里,这叫做“向量”。你可能把两个箭头加起来,得到一个新的箭头,这叫做“叠加”

那么,量子计算和这个箭头有什么关系呢?

在神奇的量子世界里,一个最基础的单位(比如一个粒子)的状态,就可以被看作是这样一根“箭头”。科学家们给这种状态起了个酷酷的名字,叫“态矢量”,也叫量子态(State Vector)

关键点来了:

  • 我们电脑里最小的单位是“比特”,只能是0​ 或 1,就像一个开关,只有“开”和“关”两种静止的状态。(相当于箭头只能指向一个方向)

  • 而量子计算机最小的单位是“量子比特”。最神奇的是,一个量子比特能够同时是0的状态、1的状态、或者是它们俩的任意组合(叠加)状态!

这就像你画的那种箭头,它可以指向0的方向,也行指向1的方向,更许可指向0和1之间的任何一个方向。

这就像你画的那个箭头,它不是静止的。通过它可以旋转,可以指向0的方向,也可以指向1的方向,更能够飞快地扫过0和1之间的所有方向。

这种“动态”的、可以“旋转”的能力(也就是叠加),就是量子计算机如此强大的核心秘密!​ 它能让计算机同时进行海量的计算,就像一个有无数个指针的钟表在同时转动。

总结一下:

这篇教程用我们熟悉的“画箭头”来打比方,告诉我们:

  1. 量子比特是量子计算的基石。

  2. 量子比特的状态像一个可能旋转的箭头

  3. 它的魔力在于能够处于叠加状态(既是0又是1),这让量子计算机拥有了传统计算机无法比拟的潜力。

二、量子态和希尔伯特空间

量子态:量子世界的“状态快照”

你可以把量子态想象成「量子世界里某个东西(比如电子、光子)在某一时刻的“全部信息快照”」。

  • 向下,等等。就是在经典世界里,描述一个东西的状态很简单:比如小球的位置、速度;硬币是正面还是反面。但到了微观的量子世界(比如电子),它有很多“神奇”的特性,不能只用“位置”“速度”这类经典量完全描述。量子态要包含这个微观粒子所有可能的信息,比如它有多大概率出现在A位置、多大概率出现在B位置,它的自旋是向上还

  • 更形象地说,量子态就像一个“装满信息的容器”。要是把量子体系比作一个游戏角色,量子态就是这个角色的“属性面板”——上面写了它能做什么、有多大几率做这些事。而且量子态还分“纯态”(信息很确定的状态)和“混态”(信息有点模糊、不确定的状态),有点像你玩游戏时“明确选了某个职业” vs “职业还没完全确定、有点混合”的感觉。

希尔伯特空间:量子态的“大仓库+运算舞台”

希尔伯特空间许可理解成「专门给量子态准备的“超级大仓库 + 运算操场”」。

  1. 仓库:装下所有可能的量子态

    无穷的,但先这么类比)。就是量子系统有多少种可能的状态,希尔伯特空间就有多少个“维度”来容纳它们。打个比方:如果一个量子系统只有两种可能状态(比如电子自旋“上”或“下”),那希尔伯特空间就像一个二维的平面,每个点代表一种自旋状态的组合;如果系统更复杂,有N种可能状态,希尔伯特空间就会有N个维度(当然现实中维度可能

  2. 运算操场:量子态之间怎么变化、怎么相互作用

    希尔伯特空间不光是存量子态,还能让量子态在里面“做运算”。量子力学里有很多操作(比如测量、幺正演化),这些操作都可以看成在希尔伯特空间里“移动”量子态——从一个点变到另一个点。你可以把它想成:量子态是操场上的运动员,希尔伯特空间是操场本身;运动员在操场上跑来跑去(对应量子态的变化),而操场的规则(比如长度、角度怎么算)决定了运动员能怎么跑。

  3. 为什么要叫“希尔伯特”?

    数学家大卫·希尔伯特(David Hilbert)研究过这种“无穷维、能做内积运算(用来计算概率等)”的抽象空间,后来物理学家发现,量子态特定适合放在这样的空间里描述,所以就借用该名字,叫“希尔伯特空间”啦~

  4. 布洛赫球,可以极其有效地表示一个量子比特(qubit)所处的纯态在二维希尔伯特空间中的状态纯态指量子框架处于一个就是,就确定的、单一的量子态,这个态可以用一个复向量空间中的单位向量(归一化的态矢量)来精确描述。纯态是量子系统可能处于的最“纯粹”、最确定的状态,没有任何经典意义上的随机混合。

画布洛赫球的代码:

from qutip import Qobj, basis, Bloch
import numpy as np
import matplotlib.pyplot as plt
import argparse
import time
def make_bloch():
	b = Bloch()
	state_0 = Qobj([[1], [0]])
	state_1 = Qobj([[0], [1]])
	state_plus = Qobj([[1], [1]]) / np.sqrt(2)
	state_minus = Qobj([[1], [-1]]) / np.sqrt(2)
	state_i = Qobj([[1], [1j]]) / np.sqrt(2)
	state_minus_i = Qobj([[1], [-1j]]) / np.sqrt(2)
	b.add_states([state_0, state_1, state_plus, state_minus, state_i, state_minus_i])
	return b
def show_bloch(bloch_obj, timeout: float | None = None):
	"""Display the Bloch sphere.
	If timeout is None (default) the function will wait for manual close: it
	will call the blocking show when available, or keep the process alive so
	you can close the window manually. If timeout is a number (seconds), the
	plot will be shown and automatically closed after that delay.
	"""
	try:
		# Try the simple call first. In many setups this blocks until the
		# window is closed by the user (desired manual mode).
		bloch_obj.show()
	except Exception:
		# If Bloch.show() raises or returns immediately, continue; we'll
		# control matplotlib directly below.
		pass
	if timeout is None:
		# Keep the process alive so the GUI window stays open until user closes it.
		# If bloch_obj.show() already blocked and the window was closed, this
		# input won't be reached which is fine. Otherwise this prevents the
		# script from exiting and letting you close the window manually.
		try:
			print("Plot displayed. Close the plot window to exit, or press Enter here to exit now.")
			input()
		except KeyboardInterrupt:
			# allow Ctrl-C to exit
			pass
	else:
		# Non-blocking show and auto-close after timeout seconds.
		try:
			plt.show(block=False)
		except TypeError:
			# Older matplotlib versions may not accept block kwarg; try a non-blocking approach
			plt.ion()
			plt.show()
		# Use pause so the GUI event loop runs and window remains responsive
		plt.pause(timeout)
		# Close all figure windows
		plt.close('all')
if __name__ == "__main__":
	parser = argparse.ArgumentParser(description="Display a sample Bloch sphere.")
	parser.add_argument("--timeout", "-t", type=float, default=None,
						help="Auto-close the plot after this many seconds. If omitted, wait for manual close.")
	args = parser.parse_args()
	b = make_bloch()
	show_bloch(b, timeout=args.timeout)

总结一下

  • 量子态:微观粒子在某一时刻的“全部信息包”,包含它所有可能的行为概率。

  • 希尔伯特空间:专门给量子态住的“大仓库”,同时也是量子态“变化、互动”的“运算舞台”——量子力学里的各种操作,本质上都是在这个空间里对量子态做“移动/变换”。

允许把量子态想象成手机里的“APP数据包”,希尔伯特空间就是手机内存+运行程序的“平台环境”——APP(量子态)要在系统(希尔伯特空间)里才能运行、变化~

三、机器学习中经典的核函数

一、现实问题:数据太复杂,分不开

想象你在纸上画两个颜色的点,理想情况下,用一条直线就能把两种颜色的点分开 —— 这就是线性可分

但现实往往不是这样,比如:

  • 红点在中间,蓝点围了一圈;

  • 或者数据像“螺旋”一样交错。

这时候,直线分不开,必须画曲线,甚至很复杂的边界。


二、解决思路:把数据“变个空间”

既然在平面上分不开,那我们就把资料“升维”,比如:

把二维的数据“投射”到三维空间里,可能一下子就变得“线性可分”了。

举个例子:

  • 在平面上,红点和蓝点交错;

  • 但我们给每个点加一个“高度”,比如离中心越远越高;

  • 结果在三维空间里,红点可能都在“上层”,蓝点在“下层”,

  • 这时候,用一个平面就能分开!

这个“变空间”的过程,叫做:

特征映射(feature mapping)
把原来的内容 x 变成更高维的 ϕ(x)


三、新问题:计算太贵,怎么办?

虽然升维有用,但直接算该高维空间里的信息,太慢、太耗内存,甚至维度可能是无限维的!


四、聪明办法:用“核函数”偷懒

我们发现:很多算法(比如SVM)其实不需要知道具体的高维数据
它们只需要知道:

它们的就是两个点在高维空间里“有多像” —— 也就内积

于是,我们发明了一个“魔法函数”:

核函数k(xi​,xj​)

不直接算高维数据,但能直接告诉你这两个点在高维空间里有多像

这就是著名的:

核技巧(kernel trick)


五、总结一句话

现实信息太复杂,分不开?
→ 我们就把它“升维”到更高维空间,让它变得能分开。
→ 但升维计算太贵?
→ 就用“核函数”偷懒,不算高维内容,却能得到高维效果


举个生活例子

想象你在看一张皱巴巴的纸,上面红蓝点混在一起,直线分不开。

你把纸揉成一个球,红点和蓝点就在球的不同“层”上了,
这时候,用一个平面就能分开!

但你不需要真的去揉纸,你只要知道:

“这两个点,如果揉成团后,会在球的同一边吗?”

核函数就是那个告诉你答案的“魔法”,而不用你真的去揉纸


✅ 总结口诀

材料太乱分不开?
升维映射把它拆!
计算太贵怎么办?
核函数来偷个懒!

举例:

超容易例子 二维到三维的多项式核

  • 取二维向量 x = (x1, x2),定义映射:

    ϕ(x) = (x1², √2 x1x2, x2²)。

  • 两个样本的内积为:

    ⟨ϕ(x), ϕ(z)⟩ = x1² z1² + 2 x1 x2 z1 z2 + x2² z2² = (x1 z1 + x2 z2)² = (x·z)²。

  • 于是我们可以直接定义核函数:k(x, z) = (x·z)²

  • 这意味着:不需要真的去算三维的ϕ(x),只需在原空间做一个数乘再平方,就得到了高维空间的内积。这个k(x, z)​ 就是多项式核在 d=2​ 时的特例。

这里就是用k(x, z) = (x·z)²该函数替代了两个样本的内积的计算⟨ϕ(x), ϕ(z)⟩, 不用再去计算ϕ(x)和 ϕ(z)再做内积了,直接算(x·z)²就是ϕ(x)和 ϕ(z)的内积。

posted @ 2025-12-10 11:56  clnchanpin  阅读(4)  评论(0)    收藏  举报