Skip to content

Commit

Permalink
Fix grover optimizer (qiskit-community/qiskit-aqua#966)
Browse files Browse the repository at this point in the history
* fix grover optimizer

grover optimizer didn't handle maximization correctly.

* Update test_grover_optimizer.py

* use aqua_globals as RNG

* fix seed for tests

Co-authored-by: Cryoris <jules.gacon@googlemail.com>
  • Loading branch information
stefan-woerner and Cryoris authored May 11, 2020
1 parent 7dcbd84 commit 9734a69
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 13 deletions.
22 changes: 17 additions & 5 deletions qiskit/optimization/algorithms/grover_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
import logging
from typing import Optional, Dict, Union, Tuple
import math
import random
import numpy as np
from qiskit import QuantumCircuit
from qiskit.providers import BaseBackend
from qiskit.aqua import QuantumInstance
from qiskit.aqua import QuantumInstance, aqua_globals
from qiskit.aqua.algorithms.amplitude_amplifiers.grover import Grover
from ..exceptions import QiskitOptimizationError
from .optimization_algorithm import OptimizationAlgorithm, OptimizationResult
Expand Down Expand Up @@ -116,6 +115,16 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
qubo_converter = QuadraticProgramToQubo()
problem_ = qubo_converter.encode(problem)

# convert to minimization problem
sense = problem_.objective.sense
if sense == problem_.objective.Sense.MAXIMIZE:
problem_.objective.sense = problem_.objective.Sense.MINIMIZE
problem_.objective.constant = -problem_.objective.constant
for i, v in problem_.objective.linear.to_dict().items():
problem_.objective.linear[i] = -v
for (i, j), v in problem_.objective.quadratic.to_dict().items():
problem_.objective.quadratic[i, j] = -v

# Variables for tracking the optimum.
optimum_found = False
optimum_key = math.inf
Expand Down Expand Up @@ -156,7 +165,7 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
while not improvement_found:
# Determine the number of rotations.
loops_with_no_improvement += 1
rotation_count = int(np.ceil(random.uniform(0, m-1)))
rotation_count = int(np.ceil(aqua_globals.random.uniform(0, m-1)))
rotations += rotation_count

# Apply Grover's Algorithm to find values below the threshold.
Expand Down Expand Up @@ -218,7 +227,10 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:

# Build the results object.
grover_results = GroverOptimizationResults(operation_count, n_key, n_value, func_dict)
result = OptimizationResult(x=opt_x, fval=solutions[optimum_key],
fval = solutions[optimum_key]
if sense == problem_.objective.Sense.MAXIMIZE:
fval = -fval
result = OptimizationResult(x=opt_x, fval=fval,
results={"grover_results": grover_results,
"qubo_converter": qubo_converter})

Expand All @@ -234,7 +246,7 @@ def _measure(self, circuit: QuantumCircuit, n_key: int, n_value: int) -> str:

# Pick a random outcome.
freq[len(freq)-1] = (freq[len(freq)-1][0], 1 - sum([x[1] for x in freq[0:len(freq)-1]]))
idx = np.random.choice(len(freq), 1, p=[x[1] for x in freq])[0]
idx = aqua_globals.random.choice(len(freq), 1, p=[x[1] for x in freq])[0]
logger.info('Frequencies: %s', freq)

return freq[idx][0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ class QuadraticProgramToNegativeValueOracle:
arxiv:1912.04088.
"""

def __init__(self, num_output_qubits: int, measurement: bool = False) -> None:
def __init__(self, num_value_qubits: int, measurement: bool = False) -> None:
"""
Args:
num_output_qubits: The number of qubits required to represent the output.
num_value_qubits: The number of qubits required to represent the output.
measurement: Whether the A operator contains measurements.
"""
self._num_key = 0
self._num_value = num_output_qubits
self._num_value = num_value_qubits
self._measurement = measurement

def encode(self, problem: QuadraticProgram) -> \
Expand Down
23 changes: 18 additions & 5 deletions test/optimization/test_grover_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

import unittest
from test.optimization import QiskitOptimizationTestCase
import random
import numpy
from docplex.mp.model import Model
from qiskit import Aer
from qiskit.aqua import aqua_globals, QuantumInstance
Expand All @@ -31,9 +29,7 @@ class TestGroverOptimizer(QiskitOptimizationTestCase):

def setUp(self):
super().setUp()
random.seed = 2
numpy.random.seed = 42
aqua_globals.seed = 42
aqua_globals.random_seed = 1
self.q_instance = QuantumInstance(Aer.get_backend('statevector_simulator'),
seed_simulator=921, seed_transpiler=200)

Expand Down Expand Up @@ -81,6 +77,23 @@ def test_qubo_gas_int_simple(self):
results = gmf.solve(op)
self.validate_results(op, results)

def test_qubo_gas_int_simple_maximize(self):
"""Test for simple case, but with maximization."""

# Input.
model = Model()
x_0 = model.binary_var(name='x0')
x_1 = model.binary_var(name='x1')
model.maximize(-x_0+2*x_1)
op = QuadraticProgram()
op.from_docplex(model)

# Get the optimum key and value.
n_iter = 8
gmf = GroverOptimizer(4, num_iterations=n_iter, quantum_instance=self.q_instance)
results = gmf.solve(op)
self.validate_results(op, results)

def test_qubo_gas_int_paper_example(self):
"""Test the example from https://arxiv.org/abs/1912.04088."""

Expand Down

0 comments on commit 9734a69

Please sign in to comment.