Skip to content

Commit 75a2c80

Browse files
stefan-woernermanoelmarquesCryoris
authored
Fix recursive optimization (qiskit-community/qiskit-aqua#976)
* fix recursive optimization * Update recursive_minimum_eigen_optimizer.py Co-authored-by: Manoel Marques <[email protected]> Co-authored-by: Julien Gacon <[email protected]>
1 parent 7b66fe9 commit 75a2c80

File tree

2 files changed

+41
-14
lines changed

2 files changed

+41
-14
lines changed

qiskit/optimization/algorithms/minimum_eigen_optimizer.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,29 @@ def solve(self, problem: QuadraticProgram) -> MinimumEigenOptimizerResult:
152152
operator_converter = QuadraticProgramToIsing()
153153
operator, offset = operator_converter.encode(problem_)
154154

155-
# approximate ground state of operator using min eigen solver
156-
eigen_results = self._min_eigen_solver.compute_minimum_eigenvalue(operator)
157-
158-
# analyze results
159-
samples = eigenvector_to_solutions(eigen_results.eigenstate, operator)
160-
samples = [(res[0], problem_.objective.sense.value * (res[1] + offset), res[2])
161-
for res in samples]
162-
samples.sort(key=lambda x: problem_.objective.sense.value * x[1])
155+
# only try to solve non-empty Ising Hamiltonians
156+
if operator.num_qubits > 0:
157+
158+
# approximate ground state of operator using min eigen solver
159+
eigen_results = self._min_eigen_solver.compute_minimum_eigenvalue(operator)
160+
161+
# analyze results
162+
samples = eigenvector_to_solutions(eigen_results.eigenstate, operator)
163+
samples = [(res[0], problem_.objective.sense.value * (res[1] + offset), res[2])
164+
for res in samples]
165+
samples.sort(key=lambda x: problem_.objective.sense.value * x[1])
166+
x = samples[0][0]
167+
fval = samples[0][1]
168+
169+
# if Hamiltonian is empty, then the objective function is constant to the offset
170+
else:
171+
x = [0]*problem_.get_num_binary_vars()
172+
fval = offset
173+
x_str = '0'*problem_.get_num_binary_vars()
174+
samples = [(x_str, offset, 1.0)]
163175

164176
# translate result back to integers
165-
opt_res = MinimumEigenOptimizerResult(samples[0][0], samples[0][1], samples, qubo_converter)
177+
opt_res = MinimumEigenOptimizerResult(x, fval, samples, qubo_converter)
166178
opt_res = qubo_converter.decode(opt_res)
167179

168180
# translate results back to original problem

qiskit/optimization/algorithms/recursive_minimum_eigen_optimizer.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
146146
x_j = problem_.variables[j].name
147147
if correlations[i, j] > 0:
148148
# set x_i = x_j
149-
problem_.substitute_variables()
150149
problem_ = problem_.substitute_variables(variables={i: (j, 1)})
151150
if problem_.status == QuadraticProgram.Status.INFEASIBLE:
152151
raise QiskitOptimizationError('Infeasible due to variable substitution')
@@ -158,16 +157,23 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
158157

159158
# 1a. get additional offset
160159
constant = problem_.objective.constant
161-
constant += problem_.objective.quadratic[i, i]
162160
constant += problem_.objective.linear[i]
161+
constant += problem_.objective.quadratic[i, i]
163162
problem_.objective.constant = constant
164163

165164
# 1b. get additional linear part
166165
for k in range(problem_.get_num_vars()):
167-
coeff = problem_.objective.quadratic[i, k]
166+
coeff = problem_.objective.linear[k]
167+
if k == i:
168+
coeff += 2*problem_.objective.quadratic[i, k]
169+
else:
170+
coeff += problem_.objective.quadratic[i, k]
171+
172+
# set new coefficient if not too small
168173
if np.abs(coeff) > 1e-10:
169-
coeff += problem_.objective.linear[k]
170174
problem_.objective.linear[k] = coeff
175+
else:
176+
problem_.objective.linear[k] = 0
171177

172178
# 2. replace x_i by -x_j
173179
problem_ = problem_.substitute_variables(variables={i: (j, -1)})
@@ -211,7 +217,16 @@ def find_value(x, replacements, var_values):
211217
return results
212218

213219
def _find_strongest_correlation(self, correlations):
214-
m_max = np.argmax(np.abs(correlations.flatten()))
220+
221+
# get absolute values and set diagonal to -1 to make sure maximum is always on off-diagonal
222+
abs_correlations = np.abs(correlations)
223+
for i in range(len(correlations)):
224+
abs_correlations[i, i] = -1
225+
226+
# get index of maximum (by construction on off-diagonal)
227+
m_max = np.argmax(abs_correlations.flatten())
228+
229+
# translate back to indices
215230
i = int(m_max // len(correlations))
216231
j = int(m_max - i*len(correlations))
217232
return (i, j)

0 commit comments

Comments
 (0)