-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7795bbc
commit c52c4b5
Showing
8 changed files
with
380 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2018, 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. | ||
|
||
"""Test Recursive Min Eigen Optimizer with legacy MinimumEigensolver.""" | ||
|
||
import unittest | ||
from test import QiskitOptimizationTestCase | ||
|
||
import numpy as np | ||
|
||
from qiskit import BasicAer | ||
from qiskit.utils import algorithm_globals, QuantumInstance | ||
|
||
from qiskit.algorithms import NumPyMinimumEigensolver, QAOA | ||
|
||
import qiskit_optimization.optionals as _optionals | ||
from qiskit_optimization.algorithms import ( | ||
MinimumEigenOptimizer, | ||
CplexOptimizer, | ||
RecursiveMinimumEigenOptimizer, | ||
WarmStartQAOAOptimizer, | ||
SlsqpOptimizer, | ||
) | ||
from qiskit_optimization.algorithms.recursive_minimum_eigen_optimizer import ( | ||
IntermediateResult, | ||
) | ||
from qiskit_optimization.problems import QuadraticProgram | ||
from qiskit_optimization.converters import ( | ||
IntegerToBinary, | ||
InequalityToEquality, | ||
LinearEqualityToPenalty, | ||
QuadraticProgramToQubo, | ||
) | ||
|
||
|
||
class TestRecursiveMinEigenOptimizer(QiskitOptimizationTestCase): | ||
"""Recursive Min Eigen Optimizer Tests.""" | ||
|
||
@unittest.skipIf(not _optionals.HAS_CPLEX, "CPLEX not available.") | ||
def test_recursive_min_eigen_optimizer(self): | ||
"""Test the recursive minimum eigen optimizer.""" | ||
filename = "op_ip1.lp" | ||
# get minimum eigen solver | ||
min_eigen_solver = NumPyMinimumEigensolver() | ||
|
||
# construct minimum eigen optimizer | ||
min_eigen_optimizer = MinimumEigenOptimizer(min_eigen_solver) | ||
recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer( | ||
min_eigen_optimizer, min_num_vars=4 | ||
) | ||
|
||
# load optimization problem | ||
problem = QuadraticProgram() | ||
lp_file = self.get_resource_path(filename, "algorithms/resources") | ||
problem.read_from_lp_file(lp_file) | ||
|
||
# solve problem with cplex | ||
cplex = CplexOptimizer() | ||
cplex_result = cplex.solve(problem) | ||
|
||
# solve problem | ||
result = recursive_min_eigen_optimizer.solve(problem) | ||
|
||
# analyze results | ||
np.testing.assert_array_almost_equal(cplex_result.x, result.x, 4) | ||
self.assertAlmostEqual(cplex_result.fval, result.fval) | ||
|
||
@unittest.skipIf(not _optionals.HAS_CPLEX, "CPLEX not available.") | ||
def test_recursive_history(self): | ||
"""Tests different options for history.""" | ||
filename = "op_ip1.lp" | ||
# load optimization problem | ||
problem = QuadraticProgram() | ||
lp_file = self.get_resource_path(filename, "algorithms/resources") | ||
problem.read_from_lp_file(lp_file) | ||
|
||
# get minimum eigen solver | ||
min_eigen_solver = NumPyMinimumEigensolver() | ||
|
||
# construct minimum eigen optimizer | ||
min_eigen_optimizer = MinimumEigenOptimizer(min_eigen_solver) | ||
|
||
# no history | ||
recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer( | ||
min_eigen_optimizer, | ||
min_num_vars=4, | ||
history=IntermediateResult.NO_ITERATIONS, | ||
) | ||
result = recursive_min_eigen_optimizer.solve(problem) | ||
self.assertIsNotNone(result.replacements) | ||
self.assertIsNotNone(result.history) | ||
self.assertIsNotNone(result.history[0]) | ||
self.assertEqual(len(result.history[0]), 0) | ||
self.assertIsNone(result.history[1]) | ||
|
||
# only last iteration in the history | ||
recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer( | ||
min_eigen_optimizer, | ||
min_num_vars=4, | ||
history=IntermediateResult.LAST_ITERATION, | ||
) | ||
result = recursive_min_eigen_optimizer.solve(problem) | ||
self.assertIsNotNone(result.replacements) | ||
self.assertIsNotNone(result.history) | ||
self.assertIsNotNone(result.history[0]) | ||
self.assertEqual(len(result.history[0]), 0) | ||
self.assertIsNotNone(result.history[1]) | ||
|
||
# full history | ||
recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer( | ||
min_eigen_optimizer, | ||
min_num_vars=4, | ||
history=IntermediateResult.ALL_ITERATIONS, | ||
) | ||
result = recursive_min_eigen_optimizer.solve(problem) | ||
self.assertIsNotNone(result.replacements) | ||
self.assertIsNotNone(result.history) | ||
self.assertIsNotNone(result.history[0]) | ||
self.assertGreater(len(result.history[0]), 1) | ||
self.assertIsNotNone(result.history[1]) | ||
|
||
@unittest.skipIf(not _optionals.HAS_CPLEX, "CPLEX not available.") | ||
def test_recursive_warm_qaoa(self): | ||
"""Test the recursive optimizer with warm start qaoa.""" | ||
seed = 1234 | ||
algorithm_globals.random_seed = seed | ||
backend = BasicAer.get_backend("statevector_simulator") | ||
qaoa = QAOA( | ||
quantum_instance=QuantumInstance( | ||
backend=backend, seed_simulator=seed, seed_transpiler=seed | ||
), | ||
reps=1, | ||
) | ||
warm_qaoa = WarmStartQAOAOptimizer( | ||
pre_solver=SlsqpOptimizer(), relax_for_pre_solver=True, qaoa=qaoa | ||
) | ||
|
||
recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer(warm_qaoa, min_num_vars=4) | ||
|
||
# load optimization problem | ||
problem = QuadraticProgram() | ||
lp_file = self.get_resource_path("op_ip1.lp", "algorithms/resources") | ||
problem.read_from_lp_file(lp_file) | ||
|
||
# solve problem with cplex | ||
cplex = CplexOptimizer(cplex_parameters={"threads": 1, "randomseed": 1}) | ||
cplex_result = cplex.solve(problem) | ||
|
||
# solve problem | ||
result = recursive_min_eigen_optimizer.solve(problem) | ||
|
||
# analyze results | ||
np.testing.assert_array_almost_equal(cplex_result.x, result.x, 4) | ||
self.assertAlmostEqual(cplex_result.fval, result.fval) | ||
|
||
def test_converter_list(self): | ||
"""Test converter list""" | ||
op = QuadraticProgram() | ||
op.integer_var(0, 3, "x") | ||
op.binary_var("y") | ||
|
||
op.maximize(linear={"x": 1, "y": 2}) | ||
op.linear_constraint(linear={"y": 1, "x": 1}, sense="LE", rhs=3, name="xy_leq") | ||
|
||
# construct minimum eigen optimizer | ||
min_eigen_solver = NumPyMinimumEigensolver() | ||
min_eigen_optimizer = MinimumEigenOptimizer(min_eigen_solver) | ||
# a single converter | ||
qp2qubo = QuadraticProgramToQubo() | ||
recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer( | ||
min_eigen_optimizer, min_num_vars=2, converters=qp2qubo | ||
) | ||
result = recursive_min_eigen_optimizer.solve(op) | ||
self.assertEqual(result.fval, 4) | ||
# a list of converters | ||
ineq2eq = InequalityToEquality() | ||
int2bin = IntegerToBinary() | ||
penalize = LinearEqualityToPenalty() | ||
converters = [ineq2eq, int2bin, penalize] | ||
recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer( | ||
min_eigen_optimizer, min_num_vars=2, converters=converters | ||
) | ||
result = recursive_min_eigen_optimizer.solve(op) | ||
self.assertEqual(result.fval, 4) | ||
# invalid converters | ||
with self.assertRaises(TypeError): | ||
invalid = [qp2qubo, "invalid converter"] | ||
RecursiveMinimumEigenOptimizer(min_eigen_optimizer, min_num_vars=2, converters=invalid) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2021, 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. | ||
|
||
""" Test warm start QAOA optimizer with legacy MinimumEigensolver. """ | ||
|
||
import unittest | ||
from test import QiskitOptimizationTestCase | ||
|
||
import numpy as np | ||
|
||
from docplex.mp.model import Model | ||
from qiskit import BasicAer | ||
from qiskit.algorithms import QAOA | ||
|
||
import qiskit_optimization.optionals as _optionals | ||
from qiskit_optimization.algorithms import SlsqpOptimizer | ||
from qiskit_optimization.algorithms.goemans_williamson_optimizer import ( | ||
GoemansWilliamsonOptimizer, | ||
) | ||
from qiskit_optimization.algorithms.warm_start_qaoa_optimizer import ( | ||
MeanAggregator, | ||
WarmStartQAOAOptimizer, | ||
) | ||
from qiskit_optimization.applications.max_cut import Maxcut | ||
from qiskit_optimization.translators import from_docplex_mp | ||
|
||
|
||
class TestWarmStartQAOAOptimizer(QiskitOptimizationTestCase): | ||
"""Tests for the warm start QAOA optimizer.""" | ||
|
||
@unittest.skipIf(not _optionals.HAS_CVXPY, "CVXPY not available.") | ||
def test_max_cut(self): | ||
"""Basic test on the max cut problem.""" | ||
graph = np.array( | ||
[ | ||
[0.0, 1.0, 2.0, 0.0], | ||
[1.0, 0.0, 1.0, 0.0], | ||
[2.0, 1.0, 0.0, 1.0], | ||
[0.0, 0.0, 1.0, 0.0], | ||
] | ||
) | ||
|
||
presolver = GoemansWilliamsonOptimizer(num_cuts=10) | ||
problem = Maxcut(graph).to_quadratic_program() | ||
|
||
backend = BasicAer.get_backend("statevector_simulator") | ||
qaoa = QAOA(quantum_instance=backend, reps=1) | ||
aggregator = MeanAggregator() | ||
optimizer = WarmStartQAOAOptimizer( | ||
pre_solver=presolver, | ||
relax_for_pre_solver=False, | ||
qaoa=qaoa, | ||
epsilon=0.25, | ||
num_initial_solutions=10, | ||
aggregator=aggregator, | ||
) | ||
result_warm = optimizer.solve(problem) | ||
|
||
self.assertIsNotNone(result_warm) | ||
self.assertIsNotNone(result_warm.x) | ||
np.testing.assert_almost_equal([0, 0, 1, 0], result_warm.x, 3) | ||
self.assertIsNotNone(result_warm.fval) | ||
np.testing.assert_almost_equal(4, result_warm.fval, 3) | ||
|
||
def test_constrained_binary(self): | ||
"""Constrained binary optimization problem.""" | ||
model = Model() | ||
v = model.binary_var(name="v") | ||
w = model.binary_var(name="w") | ||
# pylint:disable=invalid-name | ||
t = model.binary_var(name="t") | ||
|
||
model.minimize(v + w + t) | ||
model.add_constraint(2 * v + 10 * w + t <= 3, "cons1") | ||
model.add_constraint(v + w + t >= 2, "cons2") | ||
|
||
problem = from_docplex_mp(model) | ||
|
||
backend = BasicAer.get_backend("statevector_simulator") | ||
qaoa = QAOA(quantum_instance=backend, reps=1) | ||
aggregator = MeanAggregator() | ||
optimizer = WarmStartQAOAOptimizer( | ||
pre_solver=SlsqpOptimizer(), | ||
relax_for_pre_solver=True, | ||
qaoa=qaoa, | ||
epsilon=0.25, | ||
aggregator=aggregator, | ||
) | ||
result_warm = optimizer.solve(problem) | ||
|
||
self.assertIsNotNone(result_warm) | ||
self.assertIsNotNone(result_warm.x) | ||
np.testing.assert_almost_equal([1, 0, 1], result_warm.x, 3) | ||
self.assertIsNotNone(result_warm.fval) | ||
np.testing.assert_almost_equal(2, result_warm.fval, 3) | ||
|
||
def test_simple_qubo(self): | ||
"""Test on a simple QUBO problem.""" | ||
model = Model() | ||
# pylint:disable=invalid-name | ||
u = model.binary_var(name="u") | ||
v = model.binary_var(name="v") | ||
|
||
model.minimize((u - v + 2) ** 2) | ||
problem = from_docplex_mp(model) | ||
|
||
backend = BasicAer.get_backend("statevector_simulator") | ||
qaoa = QAOA(quantum_instance=backend, reps=1) | ||
optimizer = WarmStartQAOAOptimizer( | ||
pre_solver=SlsqpOptimizer(), | ||
relax_for_pre_solver=True, | ||
qaoa=qaoa, | ||
epsilon=0.25, | ||
) | ||
result_warm = optimizer.solve(problem) | ||
|
||
self.assertIsNotNone(result_warm) | ||
self.assertIsNotNone(result_warm.x) | ||
np.testing.assert_almost_equal([0, 1], result_warm.x, 3) | ||
self.assertIsNotNone(result_warm.fval) | ||
np.testing.assert_almost_equal(1, result_warm.fval, 3) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
Oops, something went wrong.