Skip to content

Commit

Permalink
Fix cobyla optimizer (qiskit-community#999)
Browse files Browse the repository at this point in the history
* fix problem with variable bounds in cobyla optimizer and add unit test

* derive initial state from variable bounds

Co-authored-by: Julien Gacon <jules.gacon@googlemail.com>
  • Loading branch information
2 people authored and molar-volume committed May 20, 2020
1 parent c59e93e commit d94d475
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 7 deletions.
23 changes: 18 additions & 5 deletions qiskit/optimization/algorithms/cobyla_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,17 @@ def objective(x):
constraints = []

# add lower/upper bound constraints
for variable in problem.variables:
for i, variable in enumerate(problem.variables):
lowerbound = variable.lowerbound
upperbound = variable.upperbound
if lowerbound > -INFINITY:
constraints += [lambda x, lb=lowerbound: x - lb]
def lb_constraint(x, l_b=lowerbound, j=i):
return x[j] - l_b
constraints += [lb_constraint]
if upperbound < INFINITY:
constraints += [lambda x, ub=upperbound: ub - x]
def ub_constraint(x, u_b=upperbound, j=i):
return u_b - x[j]
constraints += [ub_constraint]

# pylint: disable=no-member
# add linear and quadratic constraints
Expand All @@ -140,8 +144,17 @@ def objective(x):
else:
raise QiskitOptimizationError('Unsupported constraint type!')

# TODO: derive x_0 from lower/upper bounds
x_0 = np.zeros(len(problem.variables))
# define initial state and adjust according to variable bounds
x_0 = np.zeros(problem.get_num_vars())
for i, variable in enumerate(problem.variables):
l_b = variable.lowerbound
u_b = variable.upperbound
if l_b > -INFINITY and u_b < INFINITY:
x_0[i] = (l_b + u_b) / 2.0
elif l_b > -INFINITY:
x_0[i] = l_b
elif u_b < INFINITY:
x_0[i] = u_b

# run optimization
x = fmin_cobyla(objective, x_0, constraints, rhobeg=self._rhobeg, rhoend=self._rhoend,
Expand Down
37 changes: 35 additions & 2 deletions test/optimization/test_cobyla_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@


class TestCobylaOptimizer(QiskitOptimizationTestCase):
"""Cobyla Optimizer Tests."""
"""Cobyla Optimizer Tests. """

def test_cobyla_optimizer(self):
""" Cobyla Optimizer Test. """
Expand All @@ -45,7 +45,7 @@ def test_cobyla_optimizer(self):
self.assertAlmostEqual(result.fval, 5.8750)

def test_cobyla_optimizer_with_quadratic_constraint(self):
""" Cobyla Optimizer Test """
""" Cobyla Optimizer Test With Quadratic Constraints. """
# load optimization problem
problem = QuadraticProgram()
problem.continuous_var(upperbound=1)
Expand All @@ -64,6 +64,39 @@ def test_cobyla_optimizer_with_quadratic_constraint(self):
# analyze results
self.assertAlmostEqual(result.fval, 1.0, places=2)

def test_cobyla_optimizer_with_variable_bounds(self):
""" Cobyla Optimizer Test With Variable Bounds. """

# initialize optimizer
cobyla = CobylaOptimizer()

# initialize problem
problem = QuadraticProgram()

# set variables and bounds
problem.continuous_var(lowerbound=-1, upperbound=1)
problem.continuous_var(lowerbound=-2, upperbound=2)

# set objective and minimize
problem.minimize(linear=[1, 1])

# solve problem with cobyla
result = cobyla.solve(problem)

# analyze results
self.assertAlmostEqual(result.x[0], -1.0, places=6)
self.assertAlmostEqual(result.x[1], -2.0, places=6)

# set objective and minimize
problem.maximize(linear=[1, 1])

# solve problem with cobyla
result = cobyla.solve(problem)

# analyze results
self.assertAlmostEqual(result.x[0], 1.0, places=6)
self.assertAlmostEqual(result.x[1], 2.0, places=6)


if __name__ == '__main__':
unittest.main()

0 comments on commit d94d475

Please sign in to comment.