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

Bases: QuantumCircuit

El operador Grover.

El algoritmo de búsqueda de Grover [1, 2] consiste en aplicaciones repetidas del llamado operador de Grover utilizado para amplificar las amplitudes de los estados de salida deseados. Este operador, Q\mathcal{Q}, consta del oráculo de fase, Sf\mathcal{S}_f, el desplazamiento de fase cero o reflexión cero, S0\mathcal{S}_0, y una preparación de estado de entrada A\mathcal{A} :

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

En la búsqueda estándar de Grover tenemos 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}

La operación D=HnS0HnD = H^{\otimes n} \mathcal{S}_0 H^{\otimes n} también se denomina operador de difusión. En esta formulación podemos ver que el operador de Grover consta de dos pasos: primero, el oráculo de fase multiplica los estados buenos por -1 (con Sf\mathcal{S}_f ) y luego se refleja todo el estado alrededor de la media (con DD ).

Esta clase permite establecer una preparación de estado diferente, como en la amplificación de amplitudes cuánticas (una generalización del algoritmo de Grover); A\mathcal{A} podría no ser una capa de puertas de Hadamard [3].

La acción del oráculo de fase Sf\mathcal{S}_f se define como

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

donde f(x)=1f(x) = 1 si xx es un buen estado y 0 en caso contrario. Para destacar el hecho de que este oráculo invierte la fase de los estados buenos y no invierte el estado de un qubit resultante, llamamos a Sf\mathcal{S}_f oráculo de fase.

Nótese que se puede construir fácilmente un oráculo de fase a partir de un oráculo de cambio de bit intercalando la puerta X controlada en el qubit resultado por una puerta X y H. Por ejemplo

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

Existe cierta flexibilidad a la hora de definir el oráculo y el operador A\mathcal{A}. Antes de aplicar el operador Grover en el algoritmo de Grover, los qubits se preparan primero con una aplicación del operador A\mathcal{A} (o puertas Hadamard en la formulación estándar). Así, siempre tenemos una operación de la forma ASfA\mathcal{A} \mathcal{S}_f \mathcal{A}^\dagger. Por lo tanto, es posible trasladar la lógica de cambio de bits a A\mathcal{A} y dejar el oráculo sólo para hacer cambios de fase a través de puertas Z basadas en los cambios de bits. Un posible caso de uso para esto son los oráculos que no descomputan los qubits de estado.

La reflexión cero S0\mathcal{S}_0 suele definirse como

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

donde In\mathbb{I}_n es la identidad en nn qubits. Por defecto, esta clase implementa la versión negativa 20n0nIn2 |0\rangle^{\otimes n} \langle 0|^{\otimes n} - \mathbb{I}_n, ya que ésta puede implementarse simplemente con una Z multicontrolada intercalada por puertas X en el qubit objetivo y la fase global introducida no importa para el algoritmo de Grover.

Ejemplos

>>> 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 ├
«         └─────────────────┘└───────────────┘└────────────┘└───┘
Consulte también

El sitio grover_operator() implementa la misma funcionalidad pero manteniendo la MCXGate abstracto, de forma que el compilador pueda elegir la descomposición óptima. Recomendamos utilizar grover_operator() por razones de rendimiento, que no envuelve el circuito en una puerta opaca.

Referencias:

[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. Capítulo 6.1.2.

[3] Brassard, G., Hoyer, P., Mosca, M., y Tapp, A. (2000). Amplificación y estimación de la amplitud cuántica. arXiv:quant-ph/0005055.

Obsoleto desde la versión 2.1

La clase qiskit.circuit.library.grover_operator.GroverOperator está obsoleta a partir de Qiskit 2.1. Se eliminará en Qiskit 3.0. Utilice qiskit.circuit.library.grover_operator en su lugar.

Parámetros

  • oracle (QuantumCircuit |Statevector) – El oráculo de fase que implementa una reflexión sobre el estado incorrecto. Ten en cuenta que no se trata de un oráculo de inversión de bits; consulta la cadena de documentación para obtener más información.
  • state_preparation (QuantumCircuit | None) – El operador que prepara el estado bueno y el malo. En el caso del algoritmo de Grover, se trata de una puerta de Hadamard de n qubits, y para la amplificación o estimación de la amplitud, el operador A\mathcal{A}.
  • zero_reflection (QuantumCircuit |DensityMatrix |Operator | None) – Reflexión sobre el estado cero, S0\mathcal{S}_0.
  • reflection_qubits (list[int] | None) – Qubits sobre los que actúa la reflexión cero.
  • insert_barriers (bool) – Si deben intercalarse barreras entre los reflejos y A.
  • mcx_mode (str) – El modo a utilizar para construir la reflexión cero por defecto.
  • name (str) – El nombre del circuito.

Atributos

oracle

El oráculo implementando una reflexión sobre el mal estado.

reflection_qubits

Qubits de reflexión sobre los que se aplica S0 (si el usuario no especifica S0 ).

state_preparation

El subcircuito que implementa el operador A o Hadamards.

zero_reflection

El subcircuito que implementa la reflexión sobre 0.

name

Tipo: str

Un nombre legible para el circuito.

Ejemplo

from qiskit import QuantumCircuit

qc = QuantumCircuit(2, 2, name="my_circuit")
print(qc.name)
my_circuit
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.