Skip to content

Commit

Permalink
Merge a7b7673 into 7a7784f
Browse files Browse the repository at this point in the history
  • Loading branch information
RichardOberdieck committed Apr 24, 2021
2 parents 7a7784f + a7b7673 commit dbbd29a
Show file tree
Hide file tree
Showing 9 changed files with 538 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .github/actions/install-optimization/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ runs:
using: "composite"
steps:
- run : |
# install gurobipy
pip install -i https://pypi.gurobi.com gurobipy
pip install -e .[cplex,cvx,matplotlib]
pip install -U -c constraints.txt -r requirements-dev.txt
shell: bash
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ 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 }}
run: |
pip uninstall -y cplex cvxpy matplotlib
pip uninstall -y cplex cvxpy matplotlib gurobipy
if [ "${{ github.event_name }}" == "schedule" ]; then
export QISKIT_TESTS="run_slow"
fi
Expand Down
5 changes: 5 additions & 0 deletions .pylintdict
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ getter
goemans
grover
gset
gurobi
gurobipy
hamiltonian
hamiltonians
hardcoded
Expand Down Expand Up @@ -79,6 +81,7 @@ minimumeigenoptimizationresult
networkx
ndarray
ndarrays
noop
nosignatures
np
num
Expand Down Expand Up @@ -129,6 +132,7 @@ stdout
str
subgraph
submodules
sys
th
toctree
todo
Expand All @@ -139,6 +143,7 @@ upperbound
variational
vartype
vqe
writelines
xixj
xs
xuxv
Expand Down
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,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
4 changes: 3 additions & 1 deletion 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 All @@ -68,6 +69,7 @@
from .goemans_williamson_optimizer import (GoemansWilliamsonOptimizer,
GoemansWilliamsonOptimizationResult)
from .grover_optimizer import GroverOptimizer, GroverOptimizationResult
from .gurobi_optimizer import GurobiOptimizer
from .minimum_eigen_optimizer import (MinimumEigenOptimizer, MinimumEigenOptimizationResult)
from .multistart_optimizer import MultiStartOptimizer
from .optimization_algorithm import (OptimizationAlgorithm, OptimizationResult,
Expand All @@ -83,7 +85,7 @@
"OptimizationResultStatus", "BaseAggregator",
"CplexOptimizer", "CobylaOptimizer", "GoemansWilliamsonOptimizer",
"GoemansWilliamsonOptimizationResult", "GroverOptimizer", "GroverOptimizationResult",
"MeanAggregator",
"GurobiOptimizer", "MeanAggregator",
"MinimumEigenOptimizer", "MinimumEigenOptimizationResult",
"RecursiveMinimumEigenOptimizer", "RecursiveMinimumEigenOptimizationResult",
"IntermediateResult", "SlsqpOptimizer", "SlsqpOptimizationResult", "SolutionSample",
Expand Down
146 changes: 146 additions & 0 deletions qiskit_optimization/algorithms/gurobi_optimizer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# 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 dbbd29a

Please sign in to comment.