IBM Qiskit量子计算-操作-操作流
admin
2023-07-24 02:41:05
0

简介

Qiskit提供了表示状态、操作、求和、张量积和组成等。

这些代数结构允许我们构建表示运算符的表达式。

我们我们介绍通过从Pauli操作符创建表达数。在随后的小结中,我们会更加详细的探索操作符和状态,如何表达他们,和我们如何使用他们。在最后一部分,我们创建一个状态,用Hamiltonian演化它,计算可观测的期望值。

Pauli操作,求和,组成,张量积

最重要的基础操作是Pauli操作。Pauli操作表示成这样:

from qiskit.opflow import I, X, Y, Z
print(I, X, Y, Z)

# 结果
I X Y Z

这些操作也可以使用系数。

print(1.5 * I)
print(2.5 * X)

# 结果
1.5 * I
2.5 * X

系数也可以在求和中使用操作符。

print(X + 2.0 * Y)

# 结果
1.0 * X
+ 2.0 * Y

张量积用^表示

print(X^Y^Z)

# 结果
XYZ

组合用@符号表示

print(X @ Y @ Z)

# 结果
iI

在之前的两个例子中,张量积和Pauli操作的组合会马上减少到相当的Pauli操作(可能多个量子比特)。如果,我们用张量或组合构成更复杂的对象,结果就能只能表示不想当的操作。这就是代数表达式。

例如,组合两个和。

print((X + Y) @ (Y + Z))
1j * Z
+ -1j * Y
+ 1.0 * I
+ 1j * X

和两个和的张量积

print((X + Y) ^ (Y + Z))
1.0 * XY
+ 1.0 * XZ
+ 1.0 * YY
+ 1.0 * YZ

让我们更加仔细的查看上述表达。首先,Pauli操作。

(I, X)
(PauliOp(Pauli('I'), coeff=1.0), PauliOp(Pauli('X'), coeff=1.0))

每个Pauli操作都是PauliOp的实例,包含了qiskit.quantum_info.Pauli实例,然后加上了系数coeff。一般情况下,PauliOp表示带有权重的Pauli操作的张量积。

2.0 * X^Y^Z
PauliOp(Pauli('XYZ'), coeff=2.0)

对于Pauli操作的编码成一对布尔值,可以查看qiskit.quantum_info.Pauli文档。

所有的对象都表示操作符,不管是不是作为PauliOp的原始对象,或者代数表达式带有系数。

print(1.1 * ((1.2 * X)^(Y + (1.3 * Z))))
1.2 * (
1.1 * XY
+ 1.4300000000000002 * XZ
)

在后面,我们会更加深入的介绍Qiskit的操作符,状态和创建量子算法块。

部分一:状态函数和测量

量子状态都被表示为StateFn类的子类。有四种表示量子状态的方法:

  • DictStateFn:是在计算基础上的一种稀疏表达,以dict为基础。
  • VectorStateFn:是在计算基础上的一种紧密表达,以numpy向量为基础。
  • CircuitStateFn:是一种基于电路的,表示通过执行在所有零为计算基础状态的电路获得的状态。
  • OperatorStateFn:表示通过密度矩阵的混合状态。

我们后文可以看到,OperatorStateFn可以被观察参数。

一些StateFn实例,提供了方便的办法。例如,Zero,One,Plus,Minus。

from qiskit.opflow import (StateFn, Zero, One, Plus, Minus, H, DictStateFn, VectorStateFn, CircuitStateFn, OperatorStateFn)

Zero和One表示量子状态 和 。通过DictStateFn表示。

print(Zero, One)
DictStateFn({'0': 1}) DictStateFn({'1': 1})

Plus和Minus,表示电路的状态 和 。H与Plus表示同一个意思。

print(Plus, Minus)

# 结果
CircuitStateFn(
┌───┐
q: ┤ H ├
└───┘
) CircuitStateFn(
┌───┐┌───┐
q: ┤ X ├┤ H ├
└───┘└───┘
)

使用 eval 方法对量子态进行索引。这些例子都反悔0和1为基础状态的系数。(以下,我们能看到eval方法用于其他计算。)

print(Zero.eval('0'))
print(Zero.eval('1'))
print(One.eval('1'))
print(Plus.eval('0'))
print(Minus.eval('1'))

# 结果
1.0
0.0
1.0
(0.7071067811865475+0j)
(-0.7071067811865475+8.7e-17j)

量子态的对偶向量,即ket对应的bra是通过伴adjoint方法得到。 StateFn 带有一个标志 is_measurement,如果对象是 ket,则为 False,如果是bra,则为 True。

然后,我们创建

One.adjoint()

# 结果
DictStateFn({'1': 1}, coeff=1.0, is_measurement=True)

为了方便起见,用波浪线符号可以获得对偶像量,如

~One

# 结果
DictStateFn({'1': 1}, coeff=1.0, is_measurement=True)

代数操作和断言

在StateFn之间,许多代数操作和断言都是支持的,包括:

  • +:加
  • -:减,负号(标量的乘以-1)
  • *:标量相乘
  • /:标量相除
  • @:组合
  • ^:张量积货张量幂(张量自身相乘n次)
  • **:组合幂(把自己组合n次)
  • ==:相等
  • ~:伴随,在State Function和测量之间替代。

很清楚的认识到,这些操作都优先遵守Python的操作规则,可能不是你想要的数学操作。例如I^X+X^I可能会被解析为I^(X+X)^I==2*(I^X^I),因为Python中在^之前执行+。这种情况下,你可以使用方法.tensor()等,或者圆括号。

StateFn带有系数。这允许我们用标量乘以一个状态,然后就能创建和。

这里,我们创建

(2.0 + 3.0j) * Zero

# 结果
DictStateFn({'0': 1}, coeff=(2+3j), is_measurement=False)

这里,我们相加两个DictStateFn,返回相同的对象。我们创建 。

print(Zero + One)

# 结果
DictStateFn({'0': 1.0, '1': 1.0})

注意,你必须手动的正则化状态,例如,创建 ,我们就会写

import math

v_zero_one = (Zero + One) / math.sqrt(2)
print(v_zero_one)

# 结果
DictStateFn({'0': 1.0, '1': 1.0}) * 0.7071067811865475

在其他情况下,结果就是求和符号表达式的结果。例如, 的表达式。

print(Plus + Minus)

# 结果
SummedOp([
CircuitStateFn(
┌───┐
q: ┤ H ├
└───┘
),
CircuitStateFn(
┌───┐┌───┐
q: ┤ X ├┤ H ├
└───┘└───┘
)
])

组合操作一般用于执行内积,默认情况下,用于非评估形式。这里有表示

print(~One @ One)

# 结果
ComposedOp([
DictMeasurement({'1': 1}),
DictStateFn({'1': 1})
])

注意,is_measurement标识会引起(bra)状态,~One会被打印成DictMeasurement。

符号表达式可以用eval方法解释

(~One @ One).eval()

# 结果
1.0

(~v_zero_one @ v_zero_one).eval()

# 结果
0.9999999999999998

这里有

(~Minus @ One).eval()

# 结果
(-0.7071067811865475-8.7e-17j)

组合操作符@等价于调用compose方法

print((~One).compose(One))

# 结果
ComposedOp([
DictMeasurement({'1': 1}),
DictStateFn({'1': 1})
])

内积可以直接使用eval方法,而不用创建ComposedOp。

(~One).eval(One)

# 结果
1.0

符号化的张量积可以像这样构建。有 。

print(Zero^Plus)

# 结果
TensoredOp([
DictStateFn({'0': 1}),
CircuitStateFn(
┌───┐
q: ┤ H ├
└───┘
)
])

可以简单表示为CircuitStateFn。

print((Zero^Plus).to_circuit_op())

# 结果
CircuitStateFn(
┌───┐
q_0: ┤ H ├
└───┘
q_1: ─────

)

张量幂可以使用^创建。有 和 。

print(600 * ((One^5) + (Zero^5)))
print((One^Zero)^3)

# 结果
DictStateFn({'11111': 1.0, '00000': 1.0}) * 600.0
DictStateFn({'101010': 1})

这个方法to_matrix_op转变为VectorStateFn。

print(((Plus^Minus)^2).to_matrix_op())
print(((Plus^One)^2).to_circuit_op())
print(((Plus^One)^2).to_matrix_op().sample())

# 结果
VectorStateFn(Statevector([ 0.25-6.1e-17j, -0.25+6.1e-17j, 0.25-6.1e-17j,
-0.25+6.1e-17j, -0.25+6.1e-17j, 0.25-6.1e-17j,
-0.25+6.1e-17j, 0.25-6.1e-17j, 0.25-6.1e-17j,
-0.25+6.1e-17j, 0.25-6.1e-17j, -0.25+6.1e-17j,
-0.25+6.1e-17j, 0.25-6.1e-17j, -0.25+6.1e-17j,
0.25-6.1e-17j],
dims=(2, 2, 2, 2)))
CircuitStateFn(
┌───┐
q_0: ┤ X ├
├───┤
q_1: ┤ H ├
├───┤
q_2: ┤ X ├
├───┤
q_3: ┤ H ├
└───┘
)
{'1111': 0.291015625, '0101': 0.248046875, '1101': 0.232421875, '0111': 0.228515625}

创建StateFn非常简单。StateFn类可以用做工厂类,在创建时进行合适的初始化,并返回正确的StateFn子类。目前,如下初始化能够用于构建,能提供StateFn子类:

  • str (equal to some basis bitstring) -> DictStateFn
  • dict -> DictStateFn
  • Qiskit Result object -> DictStateFn
  • list -> VectorStateFn
  • np.ndarray -> VectorStateFn
  • Statevector -> VectorStateFn
  • QuantumCircuit -> CircuitStateFn
  • Instruction -> CircuitStateFn
  • OperatorBase -> OperatorStateFn
print(StateFn({'0':1}))
print(StateFn({'0':1}) == Zero)

print(StateFn([0,1,1,0]))

from qiskit.circuit.library import RealAmplitudes
print(StateFn(RealAmplitudes(2)))

# 结果
DictStateFn({'0': 1})
True
VectorStateFn(Statevector([0.+0.j, 1.+0.j, 1.+0.j, 0.+0.j],
dims=(2, 2)))
CircuitStateFn(
┌──────────────────────────────────────────────────────────┐
q_0: ┤0 ├
│ RealAmplitudes(θ[0],θ[1],θ[2],θ[3],θ[4],θ[5],θ[6],θ[7]) │
q_1: ┤1 ├
└──────────────────────────────────────────────────────────┘
)

部分二:初始化操作PrimitiveOps

基础操作都是初始化操作PrimitiveOp的子类。例如StateFn,PrimitiveOp是一个工厂类,用于创建正确的PrimitiveOp类型。目前,如下初始化操作能够用于创建,同时列举了提供的PrimitiveOp的子类:

  • Terra’s Pauli -> PauliOp
  • Instruction -> CircuitOp
  • QuantumCircuit -> CircuitOp
  • 2d List -> MatrixOp
  • np.ndarray -> MatrixOp
  • spmatrix -> MatrixOp
  • Terra’s quantum_info.Operator -> MatrixOp
from qiskit.opflow import X, Y, Z, I, CX, T, H, S, PrimitiveOp

矩阵元素

eval 方法从运算符返回一列。例如,Pauli 运算符由 PauliOp 表示。请求列会返回稀疏表示的一个实例,即 DictStateFn。

X

# 结果
PauliOp(Pauli('X'), coeff=1.0)

print(X.eval('0'))

# 结果
DictStateFn({'1': (1+0j)})

因此,通过两次调用 eval 方法执行对运算符的索引,即获取矩阵元素。我们有 。矩阵元素 是

X.eval('0').eval('1')

# 结果
(1+0j)

有例子,使用两个量子比特操作符cx,控制的x,用电路表示。

print(CX)
print(CX.to_matrix().real) # The imaginary part vanishes.

# 结果
q_0: ──■──
┌─┴─┐
q_1: ┤ X ├
└───┘
[[1. 0. 0. 0.]
[0. 0. 0. 1.]
[0. 0. 1. 0.]
[0. 1. 0. 0.]]

CX.eval('01') # 01 is the one in decimal. We get the first column.

# 结果
VectorStateFn(Statevector([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
dims=(2, 2)), coeff=1.0, is_measurement=False)

CX.eval('01').eval('11') # This returns element with (zero-based) index (1, 3)

# 结果
(1+0j)

原文链接

相关内容