Origin HHL

在 HHL 算法中,我们需要计算一个参数 δ\delta,该参数用于确定酉矩阵 UU 中旋转角度的大小,进而影响量子相位估计过程中测量结果的精度。

具体而言,在 HHL 算法中,我们需要构造一个酉矩阵 U=eiAtU=e^{iAt},其中 AA 是待求解的厄米矩阵,tt 是待确定的时间参数。通过量子相位估计技术,我们可以将 tt 的取值范围缩小到 [0,2π)[0,2\pi),并且使得相位估计结果精度达到 O(1δ)\mathcal{O}\left(\frac{1}{\delta}\right)。因此,我们希望选择一个合适的 δ\delta 值,使得相位估计结果的精度可以满足我们的要求。

具体而言,HHL 算法中 δ\delta 的计算公式为:

δ=polylog(n)λminλmax\delta=\frac{\text{polylog}(n)}{\sqrt{\lambda_{\min}\lambda_{\max}}}

其中 nn 是矩阵 AA 的维数,λmin\lambda_{\text{min}}λmax\lambda_{\text{max}} 分别是 AA 的最小和最大特征值,polylog(n)\text{polylog}(n) 表示多重对数函数。这个公式中,分母部分可以看做是矩阵的谱范数,也就是矩阵所有特征值绝对值的最大值。因此,δ\delta 的值越小,矩阵的谱范数越大,量子相位估计的精度也就越高。

在代码中,计算 δ\delta 的过程包含了以下几个步骤:

  1. λmin\lambda_{\text{min}} 缩放到 [0,2nl1][0,2^{n_l}-1] 的区间内,这里的 nln_l 是指用于表示二进制小数时使用的比特数。
  2. λmin\lambda_{\text{min}} 的二进制表示转换为十进制表示,并将小数点前的所有位数相加,得到 δ\delta 的近似值。

需要注意的是,这里计算得到的是 δ\delta 的近似值,而非精确值。因此,在实际使用中,可能需要根据具体的需求和精度要求,对 δ\delta 进行进一步的调整和优化。

Qiskit Linear Solver源码解析

matrices

LinearSystemMatrix

线性问题矩阵的基类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def __init__(
self,
num_state_qubits: int,
tolerance: float,
evolution_time: float,
name: str = "ls_matrix",
) -> None:
super().__init__(name=name)

# 存储参数
self._num_state_qubits = num_state_qubits
self._reset_registers(num_state_qubits)
self.tolerance = tolerance
self.evolution_time = evolution_time
参数 含义
num_state_qubits x|x\rangle比特数
tolerance 精度
evolution_time 哈密顿模拟时间
name 名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@abstractmethod
def eigs_bounds(self) -> Tuple[float, float]:
"""返回矩阵最小和最大特征值。"""
raise NotImplementedError

@abstractmethod
def condition_bounds(self) -> Tuple[float, float]:
"""返回矩阵最小和最大条件数。"""
raise NotImplementedError

@abstractmethod
def _reset_registers(self, num_state_qubits: int) -> None:
"""依据新的比特数重置量子寄存器。

参数:
num_state_qubits: 新的比特数。
"""
raise NotImplementedError

@abstractmethod
def power(self, power: int, matrix_power: bool = False) -> QuantumCircuit:
"""构建电路的“幂”。

Args:
power: 幂。
matrix_power: 如果为True,电路会被转为矩阵并计算矩阵的幂。否则,若power为正,会重复相应次数的电路。 the implementation defaults to ``repeat``.

Returns:
酉幂的量子电路。
"""
raise NotImplementedError

NumpyMatrix

接收一个NumPy数组进行初始化。

检查矩阵合法性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def _check_configuration(self, raise_on_failure: bool = True) -> bool:
valid = True

if self.matrix.shape[0] != self.matrix.shape[1]:
if raise_on_failure:
raise AttributeError("Input matrix must be square!")
return False
if np.log2(self.matrix.shape[0]) % 1 != 0:
if raise_on_failure:
raise AttributeError("Input matrix dimension must be 2^n!")
return False
if not np.allclose(self.matrix, self.matrix.conj().T):
if raise_on_failure:
raise AttributeError("Input matrix must be hermitian!")
return False

return valid

重复电路,用 UA=eiAtU_A=e^{iAt} 生成酉变换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def power(self, power: int, matrix_power: bool = False) -> QuantumCircuit:
"""构建电路的“幂”。

Args:
power: 幂。
matrix_power: 如果为True,电路会被转为矩阵并计算矩阵的幂。否则,若power为正,会重复相应次数的电路。 the implementation defaults to ``repeat``.

Returns:
酉幂的量子电路。
"""
qc = QuantumCircuit(self.num_state_qubits)
evolved = sp.linalg.expm(1j * self.matrix * self.evolution_time)
# 构造酉电路
qc.unitary(evolved, qc.qubits)
return qc.power(power)

Solver

LinearSolver

仅包含一个solve方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class LinearSolver(ABC):
"""线性求解器的抽象类。"""

@abstractmethod
def solve(
self,
matrix: Union[np.ndarray, QuantumCircuit],
vector: Union[np.ndarray, QuantumCircuit],
observable: Optional[
Union[
LinearSystemObservable,
List[LinearSystemObservable],
]
] = None,
observable_circuit: Optional[
Union[QuantumCircuit, List[QuantumCircuit]]
] = None,
post_processing: Optional[
Callable[[Union[float, List[float]], int, float], float]
] = None,
) -> LinearSolverResult:
参数 含义
matrix Ax=bA\vec{x}=\vec{b} 中的 AA
vector Ax=bA\vec{x}=\vec{b} 中的 bb
observable 观测量,默认为HHL成功的概率。
observable_circuit 用于测量的电路,默认为None。
post_processing 对观测量的进一步处理,默认输出观测量原始值。

NumpyLinearSolver

这是一个经典求解器,能帮助我们理解HHL求解器的代码逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def solve(
self,
matrix: Union[np.ndarray, QuantumCircuit],
vector: Union[np.ndarray, QuantumCircuit],
observable: Optional[
Union[
LinearSystemObservable,
List[LinearSystemObservable],
]
] = None,
observable_circuit: Optional[
Union[QuantumCircuit, List[QuantumCircuit]]
] = None,
post_processing: Optional[
Callable[[Union[float, List[float]], int, float], float]
] = None,
) -> LinearSolverResult:

# 检查实例所属类(获取A和x)。
if isinstance(vector, QuantumCircuit):
vector = Statevector(vector).data
if isinstance(matrix, QuantumCircuit):
if hasattr(matrix, "matrix"):
matrix = matrix.matrix
else:
matrix = Operator(matrix).data

# 求解
solution_vector = np.linalg.solve(matrix, vector)
solution = LinearSolverResult()
solution.state = solution_vector

# 计算观测量
if observable is not None:
if isinstance(observable, list):
solution.observable = []
for obs in observable:
solution.observable.append(
# 调用经典计算的测量
obs.evaluate_classically(solution_vector)
)
else:
# 调用经典计算的测量
solution.observable = observable.evaluate_classically(solution_vector)
# 计算二范数
solution.euclidean_norm = float(np.linalg.norm(solution_vector))
return solution

HHL

利用HHL求解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def __init__(
self,
epsilon: float = 1e-2,
expectation: Optional[ExpectationBase] = None,
quantum_instance: Optional[Union[Backend, QuantumInstance]] = None,
) -> None:

super().__init__()

self._epsilon = epsilon
# Tolerance for the different parts of the algorithm as per [1]
self._epsilon_r = epsilon / 3 # conditioned rotation
self._epsilon_s = epsilon / 3 # state preparation
self._epsilon_a = epsilon / 6 # hamiltonian simulation

self._scaling = None # scaling of the solution

self._sampler = None
self.quantum_instance = quantum_instance

self._expectation = expectation

# For now the default reciprocal implementation is exact
self._exact_reciprocal = True
# Set the default scaling to 1
self.scaling = 1
  • epsilon:要求精确解 x\vec{x} 与近似解 x~\tilde{x} 之间的误差 xx~ϵ\|x-\tilde{x}\|\le \epsilon

  • expectation:应用于期望值的期望转换器。如果为None,则使用PauliExpectation

  • QuantumInstance:量子计算环境的实例或后端,如果为None,就用Statevector

可以看到HHLsolve函数逻辑和NumpyLinearSolver类似,都是给出解(NumpyLinearSolver是解向量,HHL是解电路),接着计算观测量。

构造电路

第一步,将向量 b\vec{b} 编码为 b|b\rangle,注意这里 b\vec{b} 被标准化。我们直接调用isoisometry函数

0nbi=02nb1bii|0\rangle_{n_b}\to\sum_{i=0}^{2^{n_b}-1}b_i|i\rangle

第二步,构造矩阵 AA 的电路,已经有类NumpyMatrix;接着计算了受控旋转的参数 CC,即代码中的 delta,还有估计特征值所需的量子比特数 nln_l,并更新了哈密顿模拟的时间evolution_time和缩放比scaling

第三步,构造受控旋转电路,已经有类ExactReciprocal,参数 CC 已经计算得到。

第四步,构造相位估计电路,已经有类PhaseEstimation

第五步,拼接电路。

先构造一个空电路。

1
qc = QuantumCircuit(qb, ql, qf)
1
2
3
4
5
6
7
8
9
  q4: 

q5_0:

q5_1:

q5_2:

q6:

拼上vector_circuit后,在 q4q_4 上有一个模块。

1
qc.append(vector_circuit, qb[:])
1
2
3
4
5
6
7
8
9
10
      ┌──────────┐
q4: ┤ Isometry ├
└──────────┘
q5_0: ────────────

q5_1: ────────────

q5_2: ────────────

q6: ────────────

接着拼上QPE电路。

1
qc.append(phase_estimation, ql[:] + qb[:])
1
2
3
4
5
6
7
8
9
10
      ┌──────────┐┌──────┐
q4: ┤ Isometry ├┤3 ├
└──────────┘│ │
q5_0: ────────────┤0 ├
│ QPE │
q5_1: ────────────┤1 ├
│ │
q5_2: ────────────┤2 ├
└──────┘
q6: ────────────────────

然后是受控旋转电路。

x0cossxx0+sinsxx1|x\rangle |0\rangle \mapsto \cos\frac{s}{x}|x\rangle|0\rangle + \sin\frac{s}{x}|x\rangle |1\rangle

1
qc.append(reciprocal_circuit, ql[::-1] + [qf[0]])
1
2
3
4
5
6
7
8
9
10
11
      ┌──────────┐┌──────┐        
q4: ┤ Isometry ├┤3 ├────────
└──────────┘│ │┌──────┐
q5_0: ────────────┤0 ├┤2 ├
│ QPE ││ │
q5_1: ────────────┤1 ├┤1 ├
│ ││ 1/x │
q5_2: ────────────┤2 ├┤0 ├
└──────┘│ │
q6: ────────────────────┤3 ├
└──────┘

最后是 QPE\text{QPE}^{\dagger}

1
qc.append(phase_estimation.inverse(), ql[:] + qb[:])
1
2
3
4
5
6
7
8
9
10
11
      ┌──────────┐┌──────┐        ┌─────────┐
q4: ┤ Isometry ├┤3 ├────────┤3 ├
└──────────┘│ │┌──────┐│ │
q5_0: ────────────┤0 ├┤2 ├┤0 ├
│ QPE ││ ││ QPE_dg │
q5_1: ────────────┤1 ├┤1 ├┤1 ├
│ ││ 1/x ││ │
q5_2: ────────────┤2 ├┤0 ├┤2 ├
└──────┘│ │└─────────┘
q6: ────────────────────┤3 ├───────────
└──────┘

observables

observables是关于测量的组件。

LinearSystemObservable

这是线性观测的抽象类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class LinearSystemObservable(ABC):

@abstractmethod
def observable(self, num_qubits: int) -> Union[TensoredOp, List[TensoredOp]]:
"""The observable operator.

Args:
num_qubits: The number of qubits on which the observable will be applied.

Returns:
The observable as a sum of Pauli strings.
"""
raise NotImplementedError

@abstractmethod
def observable_circuit(
self, num_qubits: int
) -> Union[QuantumCircuit, List[QuantumCircuit]]:
"""The circuit implementing the observable.

Args:
num_qubits: The number of qubits on which the observable will be applied.

Returns:
The observable as a QuantumCircuit.
"""
raise NotImplementedError

@abstractmethod
def post_processing(
self, solution: Union[float, List[float]], num_qubits: int, scaling: float = 1
) -> float:
"""Evaluates the given observable on the solution to the linear system.

Args:
solution: The probability calculated from the circuit and the observable.
num_qubits: The number of qubits where the observable was applied.
scaling: Scaling of the solution.

Returns:
The value of the observable.
"""
raise NotImplementedError

@abstractmethod
def evaluate_classically(
self, solution: Union[np.ndarray, QuantumCircuit]
) -> float:
"""Calculates the analytical value of the given observable from the solution vector to the
linear system.

Args:
solution: The solution to the system as a numpy array or the circuit that prepares it.

Returns:
The value of the observable.
"""
raise NotImplementedError

Hybrid HHL

定义

特征值编码

已知实数 λ(0,1)\lambda\in (0,1) 为哈密顿矩阵 AA 的特征值,其二进制编码为

λ=0.b1b2\lambda=0.b_1b_2\cdots

其中 bk{0,1}b_k\in\{0,1\} 是二进制编码的第 kk 位。nN\forall n\in\mathbb{N}nn 比特估计为

λ(n)=b1b2bn2nλ\lambda(n)=b_1b_2\cdots b_n\approx 2^n \lambda

kk 特征均值

{λj}j=1l\left\{\lambda_j\right\}_{j=1}^l 为哈密顿矩阵 AA 的非零特征值,可对 kNk\in\mathbb{N} 定义第 kk 特征均值

mˉk=1lj=1lbkj\bar{m}_k=\frac{1}{l}\sum_{j=1}^{l} b_k^j

其中 bkjb_k^jλj\lambda_j 的第 kk 位比特。如果 mˉk=0,1\bar{m}_k=0,1,则称其为固定的;在这种情况下, 1j1,j2l\forall 1\leqslant j_1,j_2\leqslant l 显然有 bkj1=bkj2b_k^{j_1}=b_k^{j_2}

nn 完美估计

λ\lambda 是哈密顿矩阵 AA 的特征值,且 nNn\in\mathbb{N}

  1. 2nλ=λ(n)2^n\lambda=\lambda(n),则称 λ\lambdann 完美估计。

  2. 若所有 AA 的特征值都是 nn 完美估计,则称 AAnn 完美估计。

Improved HHL