Skip to main content
IBM Quantum Platform

qiskit.circuit.library.grover_operator

qiskit.circuit.library.grover_operator(oracle, state_preparation=None, zero_reflection=None, reflection_qubits=None, insert_barriers=False, name='Q')

GitHub

グローバー演算子を構築する。

グローバーの探索アルゴリズム [1、2は]、所望の出力状態の振幅を増幅するために使用される、いわゆるグローバー演算子の繰り返し適用で構成される。 この演算子( Q\mathcal{Q} )は、位相オラクル( Sf\mathcal{S}_f )、ゼロ位相シフトまたはゼロ反射( S0\mathcal{S}_0 )、および入力状態準備( A\mathcal{A} )から構成される:

Q=AS0ASf\mathcal{Q} = \mathcal{A} \mathcal{S}_0 \mathcal{A}^\dagger \mathcal{S}_f

標準的なグローバー・サーチでは、 A=Hn\mathcal{A} = H^{\otimes n}

Q=HnS0HnSf=DSf\mathcal{Q} = H^{\otimes n} \mathcal{S}_0 H^{\otimes n} \mathcal{S}_f = D \mathcal{S_f}

D=HnS0HnD = H^{\otimes n} \mathcal{S}_0 H^{\otimes n}、拡散演算子とも呼ばれる。 この定式化では、グローバーの演算子は2つのステップで構成されていることがわかる。まず、位相オラクルは良い状態に -1 ( Sf\mathcal{S}_f )を掛け合わせ、次に状態全体を平均値の周りに反映させる( DD )。

このクラスでは、量子振幅増幅(グローバーのアルゴリズムの一般化)のように、異なる状態の準備を設定することができます。 A\mathcal{A} は、ハダマールゲートの層ではない可能性があります [3].

相オラクル Sf\mathcal{S}_f の作用は次のように定義される

Sf:x(1)f(x)x\mathcal{S}_f: |x\rangle \mapsto (-1)^{f(x)}|x\rangle

ここで、 xx が良い状態であれば f(x)=1f(x) = 1、そうでなければ0。 このオラクルが良い状態の位相を反転させ、結果の量子ビットの状態を反転させないという事実を強調するために、 Sf\mathcal{S}_f を位相オラクルと呼ぶ。

結果量子ビットをXゲートとHゲートで挟むことで、ビットフリップオラクルから位相オラクルを簡単に構築できることに注意してください。 例えば

Bitflip oracle     Phaseflip oracle
q_0: ──■──         q_0: ────────────■────────────
     ┌─┴─┐              ┌───┐┌───┐┌─┴─┐┌───┐┌───┐
out: ┤ X ├         out: ┤ X ├┤ H ├┤ X ├┤ H ├┤ X ├
     └───┘              └───┘└───┘└───┘└───┘└───┘

オラクルと A\mathcal{A} 演算子の定義には柔軟性がある。 GroverのアルゴリズムでGrover演算子を適用する前に、量子ビットはまず A\mathcal{A} (標準的な定式化ではハダマードゲート)演算子を1回適用して準備される。 従って、 ASfA\mathcal{A} \mathcal{S}_f \mathcal{A}^\dagger という形の演算が常に存在することになる。したがって、ビットフリップロジックを A\mathcal{A} に移し、オラクルはビットフリップに基づくZゲートを介した位相反転を行うためだけに残すことが可能である。 この使用例として考えられるのは、状態量子ビットを計算しないオラクルである。

ゼロ反射 S0\mathcal{S}_0 は通常次のように定義される

S0=20n0nIn\mathcal{S}_0 = 2 |0\rangle^{\otimes n} \langle 0|^{\otimes n} - \mathbb{I}_n

ここで、 In\mathbb{I}_n は、 nn クビット上の恒等式である。 デフォルトでは、このクラスは負のバージョン 20n0nIn2 |0\rangle^{\otimes n} \langle 0|^{\otimes n} - \mathbb{I}_n を実装しています。これは、ターゲット量子ビットのXゲートで挟まれたマルチ制御Zで単純に実装することができ、導入されたグローバル位相はGroverのアルゴリズムには関係ないからです。

例:

位相オラクルだけでグローバー演算子を構成できる:

from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import grover_operator

oracle = QuantumCircuit(2)
oracle.z(0)  # good state = first qubit is |1>
grover_op = grover_operator(oracle, insert_barriers=True)
grover_op.draw("mpl")
先のコードで出力された回路図。

また、状態の準備を変更することもできる:

oracle = QuantumCircuit(1)
oracle.z(0)  # the qubit state |1> is the good state
state_preparation = QuantumCircuit(1)
state_preparation.ry(0.2, 0)  # non-uniform state preparation
grover_op = grover_operator(oracle, state_preparation)
grover_op.draw("mpl")
先のコードで出力された回路図。

さらに、ゼロ反射がどの量子ビットに作用するかをマークすることもできる。 これは、いくつかの量子ビットがスクラッチスペースとして使われる場合に便利だが、オラクルには影響しないはずである:

oracle = QuantumCircuit(4)
oracle.z(3)
reflection_qubits = [0, 3]
state_preparation = QuantumCircuit(4)
state_preparation.cry(0.1, 0, 3)
state_preparation.ry(0.5, 3)
grover_op = grover_operator(oracle, state_preparation, reflection_qubits=reflection_qubits)
grover_op.draw("mpl")
先のコードで出力された回路図。

オラクルとゼロ反射は、次のように渡すこともできる。 qiskit.quantum_info オブジェクトとして渡すこともできる:

from qiskit.quantum_info import Statevector, DensityMatrix, Operator

mark_state = Statevector.from_label("011")
reflection = 2 * DensityMatrix.from_label("000") - Operator.from_label("III")
grover_op = grover_operator(oracle=mark_state, zero_reflection=reflection)
grover_op.draw("mpl")
先のコードで出力された回路図。

多数の量子ビットの場合、ゼロ反射に使用されるマルチ制御Xゲートは、さまざまな方法で合成することができる。 利用可能な量子ビットの数によって、コンパイラーは異なる実装を選択する:

from qiskit import transpile, Qubit
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import grover_operator

oracle = QuantumCircuit(10)
oracle.z(oracle.qubits)
grover_op = grover_operator(oracle)

# without extra qubit space, the MCX synthesis is expensive
basis_gates = ["u", "cx"]
tqc = transpile(grover_op, basis_gates=basis_gates)
is_2q = lambda inst: len(inst.qubits) == 2
print("2q depth w/o scratch qubits:", tqc.depth(filter_function=is_2q))  # > 350

# add extra bits that can be used as scratch space
grover_op.add_bits([Qubit() for _ in range(num_qubits)])
tqc = transpile(grover_op, basis_gates=basis_gates)
print("2q depth w/ scratch qubits:", tqc.depth(filter_function=is_2q)) # < 100

パラメーター

  • oracle (QuantumCircuit |Statevector) – フェイズオラクルは、バッドステートに関するリフレクションを実行する。 これはビットフリップ・オラクルではないことに注意。詳細はdocstringを参照のこと。
  • state_preparation (QuantumCircuit | None) – オペレーターは良い状態と悪い状態を準備する。 Groverのアルゴリズムでは、これはn量子ビットのハダマードゲートであり、振幅増幅または推定のための演算子 A\mathcal{A}
  • zero_reflection (QuantumCircuit |DensityMatrix |Operator | None) – ゼロの状態についての反射、 S0\mathcal{S}_0
  • reflection_qubits (list[int] | None) – ゼロ反射が作用するキュービット。
  • insert_barriers (bool) – 反射とAの間にバリアを挿入すべきかどうか。
  • name (str) – 回路の名前。

参照資料:

[1] L. K. Grover (1996), A fast quantum mechanical algorithm for database search、 arXiv:quant-ph/9605043.

[2] I. チュアンとM. Nielsen, Quantum Computation and Quantum Information, Cambridge:Cambridge University Press, 2000. 6.1.2。

[3] ブラサール, G., ホイヤー, P., Mosca, M. および Tapp, A. (2000). 量子振幅の増幅と推定。 arXiv:quant-ph/0005055.

このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。