Skip to content

Commit

Permalink
Merge bbb8c8e into f3a4df4
Browse files Browse the repository at this point in the history
  • Loading branch information
RichardOberdieck committed May 26, 2021
2 parents f3a4df4 + bbb8c8e commit 26a2581
Show file tree
Hide file tree
Showing 9 changed files with 538 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,11 @@ jobs:
with:
name: optimization${{ matrix.python-version }}
path: ./o${{ matrix.python-version }}/*
- name: Optimization Unit Tests without cplex/cvxpy/matplotlib under Python ${{ matrix.python-version }}
- name: Optimization Unit Tests without cplex/cvxpy/matplotlib/gurobipy under Python ${{ matrix.python-version }}
env:
PYTHONWARNINGS: default
run: |
pip uninstall -y cplex cvxpy matplotlib
pip uninstall -y cplex cvxpy matplotlib gurobipy
if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ contains(github.event.pull_request.labels.*.name, 'run_slow') }}" == "true" ]; then
export QISKIT_TESTS="run_slow"
fi
Expand Down
6 changes: 6 additions & 0 deletions .pylintdict
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ goldstone
grover
groveroptimizer
gset
gurobi
gurobipy
gutmann
hamilton
hamiltonian
Expand Down Expand Up @@ -100,6 +102,7 @@ minimumeigenoptimizer
multiset
ndarray
ndarrays
noop
networkx
neven
nosignatures
Expand Down Expand Up @@ -159,6 +162,7 @@ str
subcollection
subgraph
submodules
sys
subproblem
summands
terra
Expand All @@ -176,6 +180,8 @@ upperbound
variational
vartype
vqe
writelines
xixj
wavefunction
wecker
williamson
Expand Down
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ ignored-classes=optparse.Values,thread._local,_thread._local,QuantumCircuit
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
generated-members=gurobipy.*,gp.*

# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
Expand Down
3 changes: 3 additions & 0 deletions qiskit_optimization/algorithms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
GoemansWilliamsonOptimizationResult
GroverOptimizationResult
GroverOptimizer
GurobiOptimizer
IntermediateResult
MeanAggregator
MinimumEigenOptimizationResult
Expand Down Expand Up @@ -75,6 +76,7 @@
GoemansWilliamsonOptimizationResult,
)
from .grover_optimizer import GroverOptimizer, GroverOptimizationResult
from .gurobi_optimizer import GurobiOptimizer
from .minimum_eigen_optimizer import (
MinimumEigenOptimizer,
MinimumEigenOptimizationResult,
Expand Down Expand Up @@ -111,6 +113,7 @@
"GoemansWilliamsonOptimizationResult",
"GroverOptimizer",
"GroverOptimizationResult",
"GurobiOptimizer",
"MeanAggregator",
"MinimumEigenOptimizer",
"MinimumEigenOptimizationResult",
Expand Down
151 changes: 151 additions & 0 deletions qiskit_optimization/algorithms/gurobi_optimizer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2020, 2021.
#
# 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.

"""The Gurobi optimizer wrapped to be used within Qiskit's optimization module."""

import logging

from qiskit.exceptions import MissingOptionalLibraryError
from .optimization_algorithm import OptimizationAlgorithm, OptimizationResult
from ..exceptions import QiskitOptimizationError
from ..problems.quadratic_program import QuadraticProgram

logger = logging.getLogger(__name__)

try:
import gurobipy as gp

_HAS_GUROBI = True
except ImportError:
_HAS_GUROBI = False


class GurobiOptimizer(OptimizationAlgorithm):
"""The Gurobi optimizer wrapped as an Qiskit :class:`OptimizationAlgorithm`.
This class provides a wrapper for ``gurobipy`` (https://pypi.gurobi.com)
to be used within the optimization module.
Examples:
>>> from qiskit_optimization.problems import QuadraticProgram
>>> from qiskit_optimization.algorithms import GurobiOptimizer
>>> problem = QuadraticProgram()
>>> # specify problem here, if gurobi is installed
>>> optimizer = GurobiOptimizer() if GurobiOptimizer.is_gurobi_installed() else None
>>> # Suppress gurobipy print info to stdout
>>> import sys
>>> class DevNull:
... def noop(*args, **kwargs): pass
... close = write = flush = writelines = noop
>>> sys.stdout = DevNull()
>>> result = optimizer.solve(problem)
"""

def __init__(self, disp: bool = False) -> None:
"""Initializes the GurobiOptimizer.
Args:
disp: Whether to print Gurobi output or not.
Raises:
MissingOptionalLibraryError: Gurobi is not installed.
"""
if not _HAS_GUROBI:
raise MissingOptionalLibraryError(
libname="GUROBI",
name="GurobiOptimizer",
pip_install="pip install -i https://pypi.gurobi.com gurobipy",
)

self._disp = disp

@staticmethod
def is_gurobi_installed():
"""Returns True if gurobi is installed"""
return _HAS_GUROBI

@property
def disp(self) -> bool:
"""Returns the display setting.
Returns:
Whether to print Gurobi information or not.
"""
return self._disp

@disp.setter
def disp(self, disp: bool):
"""Set the display setting.
Args:
disp: The display setting.
"""
self._disp = disp

# pylint:disable=unused-argument
def get_compatibility_msg(self, problem: QuadraticProgram) -> str:
"""Checks whether a given problem can be solved with this optimizer.
Returns ``''`` since Gurobi accepts all problems that can be modeled using the
``QuadraticProgram``. Gurobi will also solve non-convex problems.
Args:
problem: The optimization problem to check compatibility.
Returns:
An empty string.
"""
return ""

def solve(self, problem: QuadraticProgram) -> OptimizationResult:
"""Tries to solves the given problem using the optimizer.
Runs the optimizer to try to solve the optimization problem. If problem is not convex,
this optimizer may raise an exception due to incompatibility, depending on the settings.
Args:
problem: The problem to be solved.
Returns:
The result of the optimizer applied to the problem.
Raises:
QiskitOptimizationError: If the problem is incompatible with the optimizer.
"""

# convert to Gurobi problem
model = problem.to_gurobipy()

# Enable non-convex
model.Params.NonConvex = 2

# set display setting

if not self.disp:
model.Params.OutputFlag = 0

# solve problem
try:
model.optimize()
except gp.GurobiError as ex:
raise QiskitOptimizationError(str(ex)) from ex

# create results
result = OptimizationResult(
x=model.X,
fval=model.ObjVal,
variables=problem.variables,
status=self._get_feasibility_status(problem, model.X),
raw_results=model,
)

# return solution
return result

0 comments on commit 26a2581

Please sign in to comment.