Skip to content

Commit 160926a

Browse files
authored
Remove dependency on internal DOCplex methods. (qiskit-community/qiskit-aqua#1441)
* docplex corrections * more on docplex methods. * fixes in docplex.py
1 parent 12adf39 commit 160926a

File tree

2 files changed

+57
-17
lines changed

2 files changed

+57
-17
lines changed

qiskit/optimization/applications/ising/docplex.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@
5757
5858
"""
5959

60-
from typing import Tuple
60+
from typing import Tuple, Union, List
6161
import logging
6262
from math import fsum
6363

6464
import numpy as np
6565
from docplex.mp.constants import ComparisonType
66+
from docplex.mp.constr import LinearConstraint, QuadraticConstraint
67+
from docplex.mp.linear import Var
6668
from docplex.mp.model import Model
6769
from qiskit.quantum_info import Pauli
6870

@@ -113,7 +115,7 @@ def get_operator(mdl: Model, auto_penalty: bool = True,
113115
# initialize Hamiltonian.
114116
num_nodes = len(q_d)
115117
pauli_list = []
116-
shift = 0
118+
shift = 0.
117119
zero = np.zeros(num_nodes, dtype=np.bool)
118120

119121
# convert a constant part of the object function into Hamiltonian.
@@ -157,13 +159,15 @@ def get_operator(mdl: Model, auto_penalty: bool = True,
157159

158160
# convert constraints into penalty terms.
159161
for constraint in mdl.iter_constraints():
160-
constant = constraint.cplex_num_rhs()
162+
right_cst = constraint.get_right_expr().get_constant()
163+
left_cst = constraint.get_left_expr().get_constant()
164+
constant = float(right_cst - left_cst)
161165

162166
# constant parts of penalty*(Constant-func)**2: penalty*(Constant**2)
163167
shift += penalty * constant ** 2
164168

165169
# linear parts of penalty*(Constant-func)**2: penalty*(-2*Constant*func)
166-
for __l in constraint.iter_net_linear_coefs():
170+
for __l in _iter_net_linear_coeffs(constraint):
167171
z_p = np.zeros(num_nodes, dtype=np.bool)
168172
index = q_d[__l[0]]
169173
weight = __l[1]
@@ -173,8 +177,8 @@ def get_operator(mdl: Model, auto_penalty: bool = True,
173177
shift += -penalty * constant * weight
174178

175179
# quadratic parts of penalty*(Constant-func)**2: penalty*(func**2)
176-
for __l in constraint.iter_net_linear_coefs():
177-
for l_2 in constraint.iter_net_linear_coefs():
180+
for __l in _iter_net_linear_coeffs(constraint):
181+
for l_2 in _iter_net_linear_coeffs(constraint):
178182
index1 = q_d[__l[0]]
179183
index2 = q_d[l_2[0]]
180184
weight1 = __l[1]
@@ -205,6 +209,35 @@ def get_operator(mdl: Model, auto_penalty: bool = True,
205209
return qubit_op, shift
206210

207211

212+
def _iter_net_linear_coeffs(constraint: Union[LinearConstraint, QuadraticConstraint]) \
213+
-> List[Tuple[Var, float]]:
214+
"""
215+
Builds a list of tuples, where each tuple contains a decision variable and a
216+
corresponding coefficient of this variable in the constraint.
217+
218+
Args:
219+
constraint: A constraint to analyze.
220+
221+
Returns:
222+
A list of tuples of variables and coefficients.
223+
"""
224+
left_expr = constraint.get_left_expr()
225+
right_expr = constraint.get_right_expr()
226+
# for linear constraints we may get an instance of Var instead of expression,
227+
# e.g. x + y = z
228+
if isinstance(left_expr, Var):
229+
left_expr = left_expr + 0
230+
if isinstance(right_expr, Var):
231+
right_expr = right_expr + 0
232+
233+
variables = {}
234+
for var in left_expr.iter_variables():
235+
variables[var] = left_expr.get_coef(var)
236+
for var in right_expr.iter_variables():
237+
variables[var] = variables.get(var, 0.0) - right_expr.get_coef(var)
238+
return list(variables.items())
239+
240+
208241
def _validate_input_model(mdl: Model) -> None:
209242
"""Check whether an input model is valid. If not, raise an AquaError.
210243

qiskit/optimization/problems/quadratic_program.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -561,11 +561,11 @@ def from_docplex(self, model: Model) -> None:
561561
# keep track of names separately, since docplex allows to have None names.
562562
var_names = {}
563563
for x in model.iter_variables():
564-
if isinstance(x.get_vartype(), ContinuousVarType):
564+
if isinstance(x.vartype, ContinuousVarType):
565565
x_new = self.continuous_var(x.lb, x.ub, x.name)
566-
elif isinstance(x.get_vartype(), BinaryVarType):
566+
elif isinstance(x.vartype, BinaryVarType):
567567
x_new = self.binary_var(x.name)
568-
elif isinstance(x.get_vartype(), IntegerVarType):
568+
elif isinstance(x.vartype, IntegerVarType):
569569
x_new = self.integer_var(x.lb, x.ub, x.name)
570570
else:
571571
raise QiskitOptimizationError(
@@ -591,7 +591,7 @@ def from_docplex(self, model: Model) -> None:
591591
# get quadratic part of objective
592592
quadratic = {}
593593
if isinstance(model.objective_expr, QuadExpr):
594-
for quad_triplet in model.objective_expr.generate_quad_triplets():
594+
for quad_triplet in model.objective_expr.iter_quad_triplets():
595595
i = var_names[quad_triplet[0]]
596596
j = var_names[quad_triplet[1]]
597597
v = quad_triplet[2]
@@ -618,15 +618,22 @@ def from_docplex(self, model: Model) -> None:
618618
name = constraint.name
619619
sense = constraint.sense
620620

621-
rhs = 0
622-
if not isinstance(constraint.lhs, Var):
623-
rhs -= constraint.lhs.constant
624-
if not isinstance(constraint.rhs, Var):
625-
rhs += constraint.rhs.constant
621+
left_expr = constraint.get_left_expr()
622+
right_expr = constraint.get_right_expr()
623+
# for linear constraints we may get an instance of Var instead of expression,
624+
# e.g. x + y = z
625+
if isinstance(left_expr, Var):
626+
left_expr = left_expr + 0
627+
if isinstance(right_expr, Var):
628+
right_expr = right_expr + 0
629+
630+
rhs = right_expr.constant - left_expr.constant
626631

627632
lhs = {}
628-
for x in constraint.iter_net_linear_coefs():
629-
lhs[var_names[x[0]]] = x[1]
633+
for x in left_expr.iter_variables():
634+
lhs[var_names[x]] = left_expr.get_coef(x)
635+
for x in right_expr.iter_variables():
636+
lhs[var_names[x]] = lhs.get(var_names[x], 0.0) - right_expr.get_coef(x)
630637

631638
if sense == sense.EQ:
632639
self.linear_constraint(lhs, '==', rhs, name)

0 commit comments

Comments
 (0)