【问题标题】:How to create unitary gate from np.array in qiskit?如何在 qiskit 中从 np.array 创建单一门?
【发布时间】:2020-04-15 18:20:31
【问题描述】:

大家好:Cirq 提供了一种从数组创建单一门的方法。我尝试在 Qiskit 中做同样的事情,但没能完全做到。这是一个示例代码,到目前为止我可以放在一起。另外,有没有办法用这个单一的从 q[0] 到 q[1] 应用受控操作?或者为此目的创建一个特定的标记门以在电路中使用?如果是这样,怎么做?非常感谢!

from qiskit.extensions import *
U2x2 = np.array([[0.998762, -0.049745], [-0.049745, -0.998762]])
# Still not sure how to use this, though it compiles
gate2x2 = UnitaryGate(U2x2)

# The best I could do so far was this:
# Create the quantum circuit
q = QuantumRegister(2)
c = ClassicalRegister(2)
qc = QuantumCircuit(q, c)

qc.unitary(U2x2, range(1))
qc.measure(q[0], c[0])

【问题讨论】:

  • 所以你的主要问题是是否有可能/如何制作一个从 q[0] 到 q[1] 的受控统一门?或者它与您发布的代码有关的问题。因为您发布的代码对我来说编译和运行良好
  • 对,代码确实编译并运行。但是你如何得到同一个矩阵的受控门呢?以及如何扩展到 4x4 矩阵,比如说?那可能吗?另外,我发布的内容是唯一的方法吗?我似乎明白可以给这个门起个名字,以后再用这个名字,但不知道怎么做。

标签: python quantum-computing qiskit


【解决方案1】:

如果您只想从数组中获得常规的单一门,我相信您使用 qc.unitary(U2x2, range(1)) 的实现是正确的。实例化 UnitaryGate 似乎已经在 qc.unitary() 调用中完成,所以只需调用 qc.unitary() 就可以了。

但是,如果您想要这个单一门的受控版本,我发现手动实例化 UnitaryGate 然后向该门添加控件可以正常工作。类似的东西应该可以工作:

from qiskit.circuit.add_control import add_control

gate2x2 = UnitaryGate(U2x2)
gate2x2_ctrl = add_control(gate2x2, 1)

qc.append(gate2x2_ctrl, [q[0], q[1]])

Hereadd_control() 的源代码,如果您想了解更多信息。

【讨论】:

  • 这非常有用。非常感谢!
  • 再问一个问题,有没有办法从大于 2x2 的矩阵中定义门?例如,作用于两个量子位的 4x4 矩阵?有了你向我展示的内容,我已经可以对两个 2x2 矩阵的 Kronecker 积进行此操作,但是如果不知道 Kronecker 积分解怎么办?
  • 我认为应该可以使用 4x4 矩阵,但您将使用第一种添加酉门的方法。因此,您将创建 U4x4 来存储一个 4x4 numpy 数组,然后调用 qc.unitary(U4x4, [q[0], q[1]]) 如果您想将其附加到 qubits 0 和 1
  • 有趣的是,我刚刚更新了我的 Qiskit 代码,虽然 add_control() 文档说第三个参数是可选的,但我的代码不会运行,除非我传递一个字符串,门的名称,作为第三个论据,像这样:add_control(gate2x2, 1,'CU2x2').
  • 4x4 也可以工作,但至少绘图很奇怪,当查看电路时,下面显示了两个控件(0 和 1),而不仅仅是一个控件:q = QuantumRegister(3, 'q') qc = QuantumCircuit(q) gate4x4 = UnitaryGate(U4x4) gate4x4_ctrl = add_control(gate4x4, 1,'CU4x4') qc.append(gate4x4, [q[0], q[1]] ) qc.append(gate4x4_ctrl, [ q[0], q[1], q[2] ] )跨度>
【解决方案2】:

事实证明,以下是可行的,但门的应用方式与直觉相反。这可能是 Qiskit 中位排序的结果,这似乎导致了非常不标准的实现,所以要小心!具体来说,测试以下代码(您可以使用注释掉的x() 门将量子位转换为|1>):

q = QuantumRegister(2, 'q')
c = ClassicalRegister(2, 'c')

U4x4 = np.array( [[0, 1, 0, 0], [1, 0, 0, 0], 
                  [0, 0, 0, 1], [0, 0, 1, 0]] )

qc = QuantumCircuit(q,c)
qc.x(q[0])
#qc.x(q[1])

gate4x4 = UnitaryGate(U4x4)
qc.append(gate4x4, [q[0], q[1]] )
qc.measure(q[0],c[0])
qc.measure(q[1],c[1])
qc.draw()

仅通过查看矩阵,您可以看到它应该具有以下输出:|00> -> |01>, |01> -> |00>, |10> -> |11>|11> -> |10>,其中第一位,即|ab> 中的a 表示在q[0] 上测量的值。换句话说,如果输入是q[0]=|1>q[1]=|0>,人们会期望标准基础中的输入状态是(列向量)(0;0;1;0),所以输出是(0;0;0;1)。但是通过在 Aer 上进行模拟来尝试一下,您会发现情况并非如此。如图所示,使用qc.x(q[0]),输出为(0;0;0;0)。要获得预期的输出,您需要在 [q[1], q[0]] 上使用 append。虽然这肯定可以由知道的人处理,但我认为这完全令人困惑。

这是此门的受控版本。同样,请注意 append 指令中所需的(非常不直观的)量子比特的逆序,以便第一个量子比特 q[0] 充当控制。

q = QuantumRegister(3, 'q')
c = ClassicalRegister(3, 'c')

U4x4 = np.array( [[0, 1, 0, 0], [1, 0, 0, 0], 
                  [0, 0, 0, 1], [0, 0, 1, 0]] )
k = 4
# This makes a controlled variant of the matrix
C_U = np.vstack([np.hstack([np.eye(k),       np.zeros((k,k))]), 
                 np.hstack([np.zeros((k,k)), U4x4])])

qc = QuantumCircuit(q,c)
#qc.x(q[0])

gate3Q = UnitaryGate(C_U)
qc.x(q[0])
qc.append(gate3Q, [q[2], q[1], q[0]] )
qc.measure(q[0],c[0])
qc.measure(q[1],c[1])
qc.measure(q[2],c[2])
qc.draw()

通过运行此代码(并打开和关闭x(q[0]) 等),您可以轻松地自己确认发生了什么

backend = BasicAer.get_backend('qasm_simulator')
shots = 2048
results = execute(qc, backend=backend, shots=shots).result()
answer = results.get_counts()
print(answer)
plot_histogram(answer)

通过查看C_Uappend 的定义,似乎第一个量子位q[2] 应该是控制。但不,是q[0]。为了进一步参考,这是我正在运行的 Qiskit 版本:

{'qiskit-terra': '0.11.0',
 'qiskit-aer': '0.3.4',
 'qiskit-ignis': '0.2.0',
 'qiskit-ibmq-provider': '0.4.4',
 'qiskit-aqua': '0.6.1',
 'qiskit': '0.14.0'}

【讨论】:

    猜你喜欢
    • 2021-07-02
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 2017-01-18
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多