GroverOperator
class qiskit.circuit.library.GroverOperator(oracle, state_preparation=None, zero_reflection=None, reflection_qubits=None, insert_barriers=False, mcx_mode='noancilla', name='Q')
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, , è costituito dall'oracolo di fase, , dallo sfasamento zero o dalla riflessione zero, , e da una preparazione dello stato di ingresso :
Nella ricerca standard di Grover abbiamo :
L'operazione 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 ) e poi l'intero stato viene riflesso intorno alla media (con ).
Questa classe consente di impostare una preparazione di stato diversa, come nell'amplificazione dell'ampiezza quantistica (una generalizzazione dell'algoritmo di Grover); potrebbe non trattarsi di una sequenza di porte di Hadamard [3].
L'azione dell'oracolo di fase è definita come
dove se è 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 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 . Prima di applicare l'operatore di Grover nell'algoritmo di Grover, i qubit vengono preparati con un'applicazione dell'operatore (o delle porte di Hadamard nella formulazione standard). Quindi, abbiamo sempre operazioni della forma . È quindi possibile spostare la logica dei bitflip in 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 è solitamente definita come
dove è l'identità su qubit. Per impostazione predefinita, questa classe implementa la versione negativa , 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 ├
« └─────────────────┘└───────────────┘└────────────┘└───┘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.
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 è .
- zero_reflection (QuantumCircuit |DensityMatrix |Operator | None) – La riflessione sullo stato zero, .
- 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