Skip to main content
IBM Quantum Platform

GroverOperator

class qiskit.circuit.library.GroverOperator(oracle, state_preparation=None, zero_reflection=None, reflection_qubits=None, insert_barriers=False, mcx_mode='noancilla', name='Q')

GitHub

Basi: QuantumCircuit

L'operatore Grover.

L'algoritmo di ricerca di Grover [1, 2] consiste in applicazioni ripetute del cosiddetto operatore di Grover, utilizzato per amplificare le ampiezze degli stati di uscita desiderati. Questo operatore, Q\mathcal{Q}, è costituito dall'oracolo di fase, Sf\mathcal{S}_f, dallo sfasamento zero o dalla riflessione zero, S0\mathcal{S}_0, e da una preparazione dello stato di ingresso A\mathcal{A} :

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

Nella ricerca standard di Grover abbiamo 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}

L'operazione D=HnS0HnD = H^{\otimes n} \mathcal{S}_0 H^{\otimes n} viene anche chiamata operatore di diffusione. In questa formulazione possiamo vedere che l'operatore di Grover consiste in due passaggi: prima l'oracolo di fase moltiplica gli stati buoni per -1 (con Sf\mathcal{S}_f ) e poi l'intero stato viene riflesso intorno alla media (con DD ).

Questa classe consente di impostare una preparazione di stato diversa, come nell'amplificazione dell'ampiezza quantistica (una generalizzazione dell'algoritmo di Grover); A\mathcal{A} potrebbe non trattarsi di una sequenza di porte di Hadamard [3].

L'azione dell'oracolo di fase Sf\mathcal{S}_f è definita come

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

dove f(x)=1f(x) = 1 se xx è uno stato buono e 0 altrimenti. Per sottolineare il fatto che questo oracolo capovolge la fase degli stati buoni e non capovolge lo stato di un qubit risultato, chiamiamo Sf\mathcal{S}_f oracolo di fase.

Si noti che si può facilmente costruire un oracolo di fase a partire da un oracolo bitflip, inserendo il gate X controllato sul qubit risultato con un gate X e H. Per esempio

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

Esiste una certa flessibilità nel definire l'operatore oracolo e A\mathcal{A}. Prima di applicare l'operatore di Grover nell'algoritmo di Grover, i qubit vengono preparati con un'applicazione dell'operatore A\mathcal{A} (o delle porte di Hadamard nella formulazione standard). Quindi, abbiamo sempre operazioni della forma ASfA\mathcal{A} \mathcal{S}_f \mathcal{A}^\dagger. È quindi possibile spostare la logica dei bitflip in A\mathcal{A} e lasciare all'oracolo solo il compito di effettuare i capovolgimenti di fase tramite porte Z basate sui bitflip. Un possibile caso d'uso sono gli oracoli che non decompongono i qubit di stato.

La riflessione zero S0\mathcal{S}_0 è solitamente definita come

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

dove In\mathbb{I}_n è l'identità su nn qubit. Per impostazione predefinita, questa classe implementa la versione negativa 20n0nIn2 |0\rangle^{\otimes n} \langle 0|^{\otimes n} - \mathbb{I}_n, poiché questa può essere semplicemente implementata con una Z multicontrollata e con porte X sul qubit di destinazione e la fase globale introdotta non ha importanza per l'algoritmo di Grover.

Esempi

>>> from qiskit.circuit import QuantumCircuit
>>> from qiskit.circuit.library import GroverOperator
>>> oracle = QuantumCircuit(2)
>>> oracle.z(0)  # good state = first qubit is |1>
>>> grover_op = GroverOperator(oracle, insert_barriers=True)
>>> grover_op.decompose().draw()
         ┌───┐ ░ ┌───┐ ░ ┌───┐          ┌───┐      ░ ┌───┐
state_0: ┤ Z ├─░─┤ H ├─░─┤ X ├───────■──┤ X ├──────░─┤ H ├
         └───┘ ░ ├───┤ ░ ├───┤┌───┐┌─┴─┐├───┤┌───┐ ░ ├───┤
state_1: ──────░─┤ H ├─░─┤ X ├┤ H ├┤ X ├┤ H ├┤ X ├─░─┤ H ├
               ░ └───┘ ░ └───┘└───┘└───┘└───┘└───┘ ░ └───┘
>>> 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 = GroverOperator(oracle, state_preparation)
>>> grover_op.decompose().draw()
         ┌───┐┌──────────┐┌───┐┌───┐┌───┐┌─────────┐
state_0: ┤ Z ├┤ RY(-0.2) ├┤ X ├┤ Z ├┤ X ├┤ RY(0.2)
         └───┘└──────────┘└───┘└───┘└───┘└─────────┘
>>> 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 = GroverOperator(oracle, state_preparation,
... reflection_qubits=reflection_qubits)
>>> grover_op.decompose().draw()
                                      ┌───┐          ┌───┐
state_0: ──────────────────────■──────┤ X ├───────■──┤ X ├──────────■────────────────
                               │      └───┘       │  └───┘          │
state_1: ──────────────────────┼──────────────────┼─────────────────┼────────────────
                               │                  │                 │
state_2: ──────────────────────┼──────────────────┼─────────────────┼────────────────
         ┌───┐┌──────────┐┌────┴─────┐┌───┐┌───┐┌─┴─┐┌───┐┌───┐┌────┴────┐┌─────────┐
state_3: ┤ Z ├┤ RY(-0.5) ├┤ RY(-0.1) ├┤ X ├┤ H ├┤ X ├┤ H ├┤ X ├┤ RY(0.1) ├┤ RY(0.5)
         └───┘└──────────┘└──────────┘└───┘└───┘└───┘└───┘└───┘└─────────┘└─────────┘
>>> mark_state = Statevector.from_label('011')
>>> diffuse_operator = 2 * DensityMatrix.from_label('000') - Operator.from_label('III')
>>> grover_op = GroverOperator(oracle=mark_state, zero_reflection=diffuse_operator)
>>> grover_op.decompose().draw(fold=70)
         ┌─────────────────┐      ┌───┐                          »
state_0:0                ├──────┤ H ├──────────────────────────»
         │                 │┌─────┴───┴─────┐     ┌───┐          »
state_1:1 UCRZ(0,pi,0,0) ├┤0              ├─────┤ H ├──────────»
         │                 ││  UCRZ(pi/2,0) │┌────┴───┴────┐┌───┐»
state_2:2                ô1              ô UCRZ(-pi/4) ô H ï
         └─────────────────┘└───────────────┘└─────────────┘└───┘»
«         ┌─────────────────┐      ┌───┐
«state_0:0                ├──────┤ H ├─────────────────────────
«         │                 │┌─────┴───┴─────┐    ┌───┐
«state_1:1 UCRZ(pi,0,0,0) ├┤0              ├────┤ H ├──────────
«         │                 ││  UCRZ(pi/2,0) │┌───┴───┴────┐┌───┐
«state_2:2                ├┤1              ├┤ UCRZ(pi/4) ├┤ H ├
«         └─────────────────┘└───────────────┘└────────────┘└───┘
Vedi anche

Il grover_operator() implementa la stessa funzionalità, mantenendo però la parte MCXGate astratto, in modo che il compilatore possa scegliere la decomposizione ottimale. Si consiglia di utilizzare grover_operator() per motivi di prestazioni, che non avvolge il circuito in un gate opaco.

Riferimenti:

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

[2] I. Chuang & M. Nielsen, Quantum Computation and Quantum Information, Cambridge: Cambridge University Press, 2000. Capitolo 6.1.2.

[3] Brassard, G., Hoyer, P., Mosca, M., & Tapp, A. (2000). Amplificazione e stima dell'ampiezza quantistica. arXiv:quant-ph/0005055.

Deprecato dalla versione 2.1

La classe qiskit.circuit.library.grover_operator.GroverOperator è deprecata a partire da Qiskit 2.1. Verrà rimosso in Qiskit 3.0. Utilizzare invece qiskit.circuit.library.grover_operator.

Parametri

  • oracle (QuantumCircuit |Statevector) – L'oracolo di fase che mette in atto una riflessione sullo stato anomalo. Si noti che non si tratta di un oracolo di tipo “bitflip”; per ulteriori informazioni, consultare la stringa di documentazione.
  • state_preparation (QuantumCircuit | None) – L'operatore che prepara lo stato "buono" e quello "cattivo". Per l'algoritmo di Grover, si tratta di una porta di Hadamard a n qubit, mentre per l'amplificazione o la stima dell'ampiezza l'operatore è A\mathcal{A}.
  • zero_reflection (QuantumCircuit |DensityMatrix |Operator | None) – La riflessione sullo stato zero, S0\mathcal{S}_0.
  • reflection_qubits (list[int] | None) – Qubit su cui agisce la riflessione zero.
  • insert_barriers (bool) – Se è necessario inserire delle barriere tra le riflessioni e A.
  • mcx_mode (str) – La modalità da utilizzare per costruire la riflessione zero predefinita.
  • name (str) – Il nome del circuito.

Attributi

oracle

L'oracolo implementa una riflessione sullo stato negativo.

reflection_qubits

Qubit di riflessione, su cui si applica S0 (se S0 non è specificato dall'utente).

state_preparation

Il sottocircuito che implementa l'operatore A o Hadamards.

zero_reflection

Il sottocircuito che implementa la riflessione a circa 0.

name

Tipo: str

Un nome leggibile per il circuito.

Esempio

from qiskit import QuantumCircuit

qc = QuantumCircuit(2, 2, name="my_circuit")
print(qc.name)
my_circuit
Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.