Nota
Esta página fue generada a partir de docs/tutorials/04_grover_optimizer.ipynb.
Optimizador de Grover#
Introducción#
La Búsqueda Adaptativa de Grover (Grover Adaptive Search, GAS) ha sido explorada como una posible solución para problemas de optimización combinatoria, junto con los algoritmos variacionales tal como el Solucionador Propio Cuántico Variacional (Variational Quantum Eigensolver, VQE) y el Algoritmo Cuántico de Optimización Aproximada (Quantum Approximate Optimization Algorithm, QAOA). El algoritmo aplica la Búsqueda de Grover iterativamente para encontrar el valor óptimo de una función objetivo, al usar el mejor valor conocido de la ejecución anterior como umbral. El oráculo adaptativo utilizado en GAS reconoce todos los valores arriba o debajo del umbral actual (para máximos y mínimos, respectivamente), disminuyendo el tamaño del espacio de búsqueda, en cada iteración se actualiza el umbral, hasta que se encuentra un óptimo.
En este cuaderno exploraremos cada componente del GroverOptimizer
, el cual utiliza las técnicas descritas en GAS, minimizando un problema de Optimización Binaria Cuadrática sin Restricciones (Quadratic Unconstrained Binary Optimization, QUBO), como se describe en [1]
Referencias#
Búsqueda Adaptativa de Grover#
La Búsqueda de Grover, el elemento central de GAS, necesita de tres ingredientes:
Un operador de preparación de estado
para construir una superposición de todos los estados en el espacio de búsqueda.Un operador oráculo
, que reconoce a los estados de interés y multiplica sus amplitudes por -1.El operador de difusión de Grover
, que multiplica la amplitud del estado por -1.
Si bien las implementaciones de GAS varían según el caso de uso específico, el framework general aún sigue vagamente los pasos que se describen a continuación.
GroverOptimizer
utiliza QuadraticProgramToNegativeValueOracle
para construir
Dicho formalmente, QuadraticProgramToNegativeValueOracle
construye un
donde
En cada iteración en la que se actualiza el umbral
Encontrar el Mínimo de un Problema QUBO utilizando GroverOptimizer#
El siguiente es un ejemplo de juguete de un problema de minimización.
Para nuestros pasos iniciales, creamos un modelo docplex que define el problema anterior, y luego usamos la función from_docplex_mp()
para convertir el modelo en un QuadraticProgram
, que se puede usar para representar un QUBO en Qiskit Optimization.
[1]:
from qiskit_algorithms import NumPyMinimumEigensolver
from qiskit.primitives import Sampler
from qiskit_optimization.algorithms import GroverOptimizer, MinimumEigenOptimizer
from qiskit_optimization.translators import from_docplex_mp
from docplex.mp.model import Model
[2]:
model = Model()
x0 = model.binary_var(name="x0")
x1 = model.binary_var(name="x1")
x2 = model.binary_var(name="x2")
model.minimize(-x0 + 2 * x1 - 3 * x2 - 2 * x0 * x2 - 1 * x1 * x2)
qp = from_docplex_mp(model)
print(qp.prettyprint())
Problem name: docplex_model1
Minimize
-2*x0*x2 - x1*x2 - x0 + 2*x1 - 3*x2
Subject to
No constraints
Binary variables (3)
x0 x1 x2
A continuación, creamos un GroverOptimizer
que usa 6 qubits para codificar el valor y terminará después de que haya habido 10 iteraciones de GAS sin progreso (es decir, el valor de solve()
toma el QuadraticProgram
que creamos anteriormente y devuelve un objeto de resultados que contiene información sobre la ejecución.
[3]:
grover_optimizer = GroverOptimizer(6, num_iterations=10, sampler=Sampler())
results = grover_optimizer.solve(qp)
print(results.prettyprint())
objective function value: -6.0
variable values: x0=1.0, x1=0.0, x2=1.0
status: SUCCESS
Esto resulta en la solución óptima GroverOptimizer
aplicada a este QUBO.
Cada gráfica muestra una sola iteración de GAS, con los valores actuales de
Comprobar que GroverOptimizer encuentra el valor correcto#
Podemos verificar que el algoritmo está funcionando correctamente usando el MinimumEigenOptimizer
en Qiskit Optimization.
[4]:
exact_solver = MinimumEigenOptimizer(NumPyMinimumEigensolver())
exact_result = exact_solver.solve(qp)
print(exact_result.prettyprint())
objective function value: -6.0
variable values: x0=1.0, x1=0.0, x2=1.0
status: SUCCESS
[5]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
qiskit-terra | 0.23.0 |
qiskit-aer | 0.11.1 |
qiskit-optimization | 0.5.0 |
qiskit-machine-learning | 0.6.0 |
System information | |
Python version | 3.9.15 |
Python compiler | Clang 14.0.0 (clang-1400.0.29.102) |
Python build | main, Oct 11 2022 22:27:25 |
OS | Darwin |
CPUs | 4 |
Memory (Gb) | 16.0 |
Tue Dec 06 21:47:01 2022 JST |
This code is a part of Qiskit
© Copyright IBM 2017, 2022.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.
[ ]: