GroverOperator
class qiskit.circuit.library.GroverOperator(oracle, state_preparation=None, zero_reflection=None, reflection_qubits=None, insert_barriers=False, mcx_mode='noancilla', name='Q')
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, , consta del oráculo de fase, , el desplazamiento de fase cero o reflexión cero, , y una preparación de estado de entrada :
En la búsqueda estándar de Grover tenemos :
La operació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 ) y luego se refleja todo el estado alrededor de la media (con ).
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); podría no ser una capa de puertas de Hadamard [3].
La acción del oráculo de fase se define como
donde si 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 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 . Antes de aplicar el operador Grover en el algoritmo de Grover, los qubits se preparan primero con una aplicación del operador (o puertas Hadamard en la formulación estándar). Así, siempre tenemos una operación de la forma . Por lo tanto, es posible trasladar la lógica de cambio de bits 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 suele definirse como
donde es la identidad en qubits. Por defecto, esta clase implementa la versión negativa , 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 ├
« └─────────────────┘└───────────────┘└────────────┘└───┘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.
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 .
- zero_reflection (QuantumCircuit |DensityMatrix |Operator | None) – Reflexión sobre el estado cero, .
- 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